Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/gve/gve_qpl.c
| Show All 26 Lines | |||||
| * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||||
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||||
| * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
| */ | */ | ||||
| #include <sys/malloc.h> | #include <sys/malloc.h> | ||||
| #include "gve.h" | #include "gve.h" | ||||
| #include "gve_adminq.h" | #include "gve_adminq.h" | ||||
| #include "gve_dqo.h" | |||||
| static MALLOC_DEFINE(M_GVE_QPL, "gve qpl", "gve qpl allocations"); | static MALLOC_DEFINE(M_GVE_QPL, "gve qpl", "gve qpl allocations"); | ||||
| static uint32_t | static uint32_t | ||||
| gve_num_tx_qpls(struct gve_priv *priv) | gve_num_tx_qpls(struct gve_priv *priv) | ||||
| { | { | ||||
| if (priv->queue_format != GVE_GQI_QPL_FORMAT) | if (!gve_is_qpl(priv)) | ||||
| return (0); | return (0); | ||||
| return (priv->tx_cfg.max_queues); | return (priv->tx_cfg.max_queues); | ||||
| } | } | ||||
| static uint32_t | static uint32_t | ||||
| gve_num_rx_qpls(struct gve_priv *priv) | gve_num_rx_qpls(struct gve_priv *priv) | ||||
| { | { | ||||
| if (priv->queue_format != GVE_GQI_QPL_FORMAT) | if (!gve_is_qpl(priv)) | ||||
| return (0); | return (0); | ||||
| return (priv->rx_cfg.max_queues); | return (priv->rx_cfg.max_queues); | ||||
| } | } | ||||
| static void | static void | ||||
| gve_free_qpl(struct gve_priv *priv, uint32_t id) | gve_free_qpl(struct gve_priv *priv, uint32_t id) | ||||
| { | { | ||||
| ▲ Show 20 Lines • Show All 125 Lines • ▼ Show 20 Lines | if (priv->qpls != NULL) { | ||||
| free(priv->qpls, M_GVE_QPL); | free(priv->qpls, M_GVE_QPL); | ||||
| priv->qpls = NULL; | priv->qpls = NULL; | ||||
| } | } | ||||
| } | } | ||||
| int gve_alloc_qpls(struct gve_priv *priv) | int gve_alloc_qpls(struct gve_priv *priv) | ||||
| { | { | ||||
| int num_qpls = gve_num_tx_qpls(priv) + gve_num_rx_qpls(priv); | int num_qpls = gve_num_tx_qpls(priv) + gve_num_rx_qpls(priv); | ||||
| int num_pages; | |||||
| int err; | int err; | ||||
| int i; | int i; | ||||
| if (num_qpls == 0) | if (num_qpls == 0) | ||||
| return (0); | return (0); | ||||
| priv->qpls = malloc(num_qpls * sizeof(*priv->qpls), M_GVE_QPL, | priv->qpls = malloc(num_qpls * sizeof(*priv->qpls), M_GVE_QPL, | ||||
| M_WAITOK | M_ZERO); | 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++) { | for (i = 0; i < gve_num_tx_qpls(priv); i++) { | ||||
| err = gve_alloc_qpl(priv, i, priv->tx_desc_cnt / GVE_QPL_DIVISOR, | err = gve_alloc_qpl(priv, i, num_pages, | ||||
| /*single_kva=*/true); | /*single_kva=*/true); | ||||
| if (err != 0) | if (err != 0) | ||||
| goto abort; | goto abort; | ||||
| } | } | ||||
| num_pages = gve_is_gqi(priv) ? priv->rx_desc_cnt : GVE_RX_NUM_QPL_PAGES_DQO; | |||||
| for (; i < num_qpls; i++) { | for (; i < num_qpls; i++) { | ||||
| err = gve_alloc_qpl(priv, i, priv->rx_desc_cnt, /*single_kva=*/false); | err = gve_alloc_qpl(priv, i, num_pages, /*single_kva=*/false); | ||||
| if (err != 0) | if (err != 0) | ||||
| goto abort; | goto abort; | ||||
| } | } | ||||
| return (0); | return (0); | ||||
| abort: | abort: | ||||
| gve_free_qpls(priv); | gve_free_qpls(priv); | ||||
| ▲ Show 20 Lines • Show All 59 Lines • ▼ Show 20 Lines | if (!gve_get_state_flag(priv, GVE_STATE_FLAG_QPLREG_OK)) | ||||
| return (0); | return (0); | ||||
| err = gve_unregister_n_qpls(priv, num_qpls); | err = gve_unregister_n_qpls(priv, num_qpls); | ||||
| if (err != 0) | if (err != 0) | ||||
| return (err); | return (err); | ||||
| gve_clear_state_flag(priv, GVE_STATE_FLAG_QPLREG_OK); | gve_clear_state_flag(priv, GVE_STATE_FLAG_QPLREG_OK); | ||||
| return (0); | return (0); | ||||
| } | |||||
| void | |||||
| gve_mextadd_free(struct mbuf *mbuf) | |||||
| { | |||||
| vm_page_t page = (vm_page_t)mbuf->m_ext.ext_arg1; | |||||
| vm_offset_t va = (vm_offset_t)mbuf->m_ext.ext_arg2; | |||||
| /* | |||||
| * Free the page only if this is the last ref. | |||||
| * The interface might no longer exist by the time | |||||
| * this callback is called, see gve_free_qpl. | |||||
| */ | |||||
| if (__predict_false(vm_page_unwire_noq(page))) { | |||||
| pmap_qremove(va, 1); | |||||
| kva_free(va, PAGE_SIZE); | |||||
| vm_page_free(page); | |||||
| } | |||||
| } | } | ||||