diff options
Diffstat (limited to 'sys/dev/gve/gve_qpl.c')
-rw-r--r-- | sys/dev/gve/gve_qpl.c | 174 |
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); |