aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/gve/gve_qpl.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/gve/gve_qpl.c')
-rw-r--r--sys/dev/gve/gve_qpl.c174
1 files changed, 62 insertions, 112 deletions
diff --git a/sys/dev/gve/gve_qpl.c b/sys/dev/gve/gve_qpl.c
index 1fcc2b5365c9..0e7098dcd4a1 100644
--- a/sys/dev/gve/gve_qpl.c
+++ b/sys/dev/gve/gve_qpl.c
@@ -36,28 +36,9 @@
static MALLOC_DEFINE(M_GVE_QPL, "gve qpl", "gve qpl allocations");
-static uint32_t
-gve_num_tx_qpls(struct gve_priv *priv)
-{
- if (!gve_is_qpl(priv))
- return (0);
-
- return (priv->tx_cfg.max_queues);
-}
-
-static uint32_t
-gve_num_rx_qpls(struct gve_priv *priv)
-{
- if (!gve_is_qpl(priv))
- return (0);
-
- return (priv->rx_cfg.max_queues);
-}
-
-static void
-gve_free_qpl(struct gve_priv *priv, uint32_t id)
+void
+gve_free_qpl(struct gve_priv *priv, struct gve_queue_page_list *qpl)
{
- struct gve_queue_page_list *qpl = &priv->qpls[id];
int i;
for (i = 0; i < qpl->num_dmas; i++) {
@@ -92,12 +73,14 @@ gve_free_qpl(struct gve_priv *priv, uint32_t id)
if (qpl->dmas != NULL)
free(qpl->dmas, M_GVE_QPL);
+
+ free(qpl, M_GVE_QPL);
}
-static int
+struct gve_queue_page_list *
gve_alloc_qpl(struct gve_priv *priv, uint32_t id, int npages, bool single_kva)
{
- struct gve_queue_page_list *qpl = &priv->qpls[id];
+ struct gve_queue_page_list *qpl;
int err;
int i;
@@ -105,9 +88,12 @@ gve_alloc_qpl(struct gve_priv *priv, uint32_t id, int npages, bool single_kva)
device_printf(priv->dev, "Reached max number of registered pages %ju > %ju\n",
(uintmax_t)npages + priv->num_registered_pages,
(uintmax_t)priv->max_registered_pages);
- return (EINVAL);
+ return (NULL);
}
+ qpl = malloc(sizeof(struct gve_queue_page_list), M_GVE_QPL,
+ M_WAITOK | M_ZERO);
+
qpl->id = id;
qpl->num_pages = 0;
qpl->num_dmas = 0;
@@ -163,126 +149,90 @@ gve_alloc_qpl(struct gve_priv *priv, uint32_t id, int npages, bool single_kva)
priv->num_registered_pages++;
}
- return (0);
+ return (qpl);
abort:
- gve_free_qpl(priv, id);
- return (err);
+ gve_free_qpl(priv, qpl);
+ return (NULL);
}
-void
-gve_free_qpls(struct gve_priv *priv)
-{
- int num_qpls = gve_num_tx_qpls(priv) + gve_num_rx_qpls(priv);
- int i;
-
- if (num_qpls == 0)
- return;
-
- if (priv->qpls != NULL) {
- for (i = 0; i < num_qpls; i++)
- gve_free_qpl(priv, i);
- free(priv->qpls, M_GVE_QPL);
- priv->qpls = NULL;
- }
-}
-
-int gve_alloc_qpls(struct gve_priv *priv)
+int
+gve_register_qpls(struct gve_priv *priv)
{
- int num_qpls = gve_num_tx_qpls(priv) + gve_num_rx_qpls(priv);
- int num_pages;
+ struct gve_ring_com *com;
+ struct gve_tx_ring *tx;
+ struct gve_rx_ring *rx;
int err;
int i;
- if (num_qpls == 0)
+ if (gve_get_state_flag(priv, GVE_STATE_FLAG_QPLREG_OK))
return (0);
- priv->qpls = malloc(num_qpls * sizeof(*priv->qpls), M_GVE_QPL,
- M_WAITOK | M_ZERO);
-
- num_pages = gve_is_gqi(priv) ?
- priv->tx_desc_cnt / GVE_QPL_DIVISOR :
- GVE_TX_NUM_QPL_PAGES_DQO;
- for (i = 0; i < gve_num_tx_qpls(priv); i++) {
- err = gve_alloc_qpl(priv, i, num_pages,
- /*single_kva=*/true);
- if (err != 0)
- goto abort;
- }
-
- num_pages = gve_is_gqi(priv) ? priv->rx_desc_cnt : GVE_RX_NUM_QPL_PAGES_DQO;
- for (; i < num_qpls; i++) {
- err = gve_alloc_qpl(priv, i, num_pages, /*single_kva=*/false);
- if (err != 0)
- goto abort;
- }
-
- return (0);
-
-abort:
- gve_free_qpls(priv);
- return (err);
-}
-
-static int
-gve_unregister_n_qpls(struct gve_priv *priv, int n)
-{
- int err;
- int i;
-
- for (i = 0; i < n; i++) {
- err = gve_adminq_unregister_page_list(priv, priv->qpls[i].id);
+ /* Register TX qpls */
+ for (i = 0; i < priv->tx_cfg.num_queues; i++) {
+ tx = &priv->tx[i];
+ com = &tx->com;
+ err = gve_adminq_register_page_list(priv, com->qpl);
if (err != 0) {
device_printf(priv->dev,
- "Failed to unregister qpl %d, err: %d\n",
- priv->qpls[i].id, err);
+ "Failed to register qpl %d, err: %d\n",
+ com->qpl->id, err);
+ /* Caller schedules a reset when this fails */
+ return (err);
}
}
- if (err != 0)
- return (err);
-
- return (0);
-}
-
-int
-gve_register_qpls(struct gve_priv *priv)
-{
- int num_qpls = gve_num_tx_qpls(priv) + gve_num_rx_qpls(priv);
- int err;
- int i;
-
- if (gve_get_state_flag(priv, GVE_STATE_FLAG_QPLREG_OK))
- return (0);
-
- for (i = 0; i < num_qpls; i++) {
- err = gve_adminq_register_page_list(priv, &priv->qpls[i]);
+ /* Register RX qpls */
+ for (i = 0; i < priv->rx_cfg.num_queues; i++) {
+ rx = &priv->rx[i];
+ com = &rx->com;
+ err = gve_adminq_register_page_list(priv, com->qpl);
if (err != 0) {
device_printf(priv->dev,
"Failed to register qpl %d, err: %d\n",
- priv->qpls[i].id, err);
- goto abort;
+ com->qpl->id, err);
+ /* Caller schedules a reset when this fails */
+ return (err);
}
}
-
gve_set_state_flag(priv, GVE_STATE_FLAG_QPLREG_OK);
return (0);
-
-abort:
- gve_unregister_n_qpls(priv, i);
- return (err);
}
int
gve_unregister_qpls(struct gve_priv *priv)
{
- int num_qpls = gve_num_tx_qpls(priv) + gve_num_rx_qpls(priv);
int err;
+ int i;
+ struct gve_ring_com *com;
+ struct gve_tx_ring *tx;
+ struct gve_rx_ring *rx;
if (!gve_get_state_flag(priv, GVE_STATE_FLAG_QPLREG_OK))
return (0);
- err = gve_unregister_n_qpls(priv, num_qpls);
+ for (i = 0; i < priv->tx_cfg.num_queues; i++) {
+ tx = &priv->tx[i];
+ com = &tx->com;
+ err = gve_adminq_unregister_page_list(priv, com->qpl->id);
+ if (err != 0) {
+ device_printf(priv->dev,
+ "Failed to unregister qpl %d, err: %d\n",
+ com->qpl->id, err);
+ }
+ }
+
+ for (i = 0; i < priv->rx_cfg.num_queues; i++) {
+ rx = &priv->rx[i];
+ com = &rx->com;
+ err = gve_adminq_unregister_page_list(priv, com->qpl->id);
+ if (err != 0) {
+ device_printf(priv->dev,
+ "Failed to unregister qpl %d, err: %d\n",
+ com->qpl->id, err);
+ }
+ }
+
if (err != 0)
return (err);