18fd92a66SOlivier Matz /* SPDX-License-Identifier: BSD-3-Clause 2e9086978SAdrien Mazarguil * Copyright 2015 6WIND S.A. 3e9086978SAdrien Mazarguil * Copyright 2015 Mellanox. 4e9086978SAdrien Mazarguil */ 5e9086978SAdrien Mazarguil 6e9086978SAdrien Mazarguil #include <stddef.h> 7e9086978SAdrien Mazarguil #include <errno.h> 8e9086978SAdrien Mazarguil #include <assert.h> 9e9086978SAdrien Mazarguil #include <stdint.h> 10e9086978SAdrien Mazarguil 110e83b8e5SNelio Laranjeiro /* Verbs headers do not support -pedantic. */ 120e83b8e5SNelio Laranjeiro #ifdef PEDANTIC 130e83b8e5SNelio Laranjeiro #pragma GCC diagnostic ignored "-Wpedantic" 140e83b8e5SNelio Laranjeiro #endif 150e83b8e5SNelio Laranjeiro #include <infiniband/mlx5dv.h> 160e83b8e5SNelio Laranjeiro #include <infiniband/verbs.h> 170e83b8e5SNelio Laranjeiro #ifdef PEDANTIC 180e83b8e5SNelio Laranjeiro #pragma GCC diagnostic error "-Wpedantic" 190e83b8e5SNelio Laranjeiro #endif 200e83b8e5SNelio Laranjeiro 21ffc905f3SFerruh Yigit #include <rte_ethdev_driver.h> 22e9086978SAdrien Mazarguil #include <rte_common.h> 23e9086978SAdrien Mazarguil 24e9086978SAdrien Mazarguil #include "mlx5_utils.h" 25e9086978SAdrien Mazarguil #include "mlx5.h" 26f3db9489SYaacov Hazan #include "mlx5_autoconf.h" 270e83b8e5SNelio Laranjeiro #include "mlx5_glue.h" 28e9086978SAdrien Mazarguil 29e9086978SAdrien Mazarguil /** 30e9086978SAdrien Mazarguil * DPDK callback to configure a VLAN filter. 31e9086978SAdrien Mazarguil * 32e9086978SAdrien Mazarguil * @param dev 33e9086978SAdrien Mazarguil * Pointer to Ethernet device structure. 34e9086978SAdrien Mazarguil * @param vlan_id 35e9086978SAdrien Mazarguil * VLAN ID to filter. 36e9086978SAdrien Mazarguil * @param on 37e9086978SAdrien Mazarguil * Toggle filter. 38e9086978SAdrien Mazarguil * 39e9086978SAdrien Mazarguil * @return 40e9086978SAdrien Mazarguil * 0 on success, negative errno value on failure. 41e9086978SAdrien Mazarguil */ 42e9086978SAdrien Mazarguil int 43e9086978SAdrien Mazarguil mlx5_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on) 44e9086978SAdrien Mazarguil { 45e9086978SAdrien Mazarguil struct priv *priv = dev->data->dev_private; 46272733b5SNélio Laranjeiro unsigned int i; 47e4aefd6dSNélio Laranjeiro int ret = 0; 48e9086978SAdrien Mazarguil 49272733b5SNélio Laranjeiro DEBUG("%p: %s VLAN filter ID %" PRIu16, 50272733b5SNélio Laranjeiro (void *)dev, (on ? "enable" : "disable"), vlan_id); 51272733b5SNélio Laranjeiro assert(priv->vlan_filter_n <= RTE_DIM(priv->vlan_filter)); 52272733b5SNélio Laranjeiro for (i = 0; (i != priv->vlan_filter_n); ++i) 53272733b5SNélio Laranjeiro if (priv->vlan_filter[i] == vlan_id) 54272733b5SNélio Laranjeiro break; 55e4aefd6dSNélio Laranjeiro /* Check if there's room for another VLAN filter. */ 56e4aefd6dSNélio Laranjeiro if (i == RTE_DIM(priv->vlan_filter)) { 57e4aefd6dSNélio Laranjeiro ret = -ENOMEM; 58e4aefd6dSNélio Laranjeiro goto out; 59e4aefd6dSNélio Laranjeiro } 60272733b5SNélio Laranjeiro if (i < priv->vlan_filter_n) { 61272733b5SNélio Laranjeiro assert(priv->vlan_filter_n != 0); 62272733b5SNélio Laranjeiro /* Enabling an existing VLAN filter has no effect. */ 63272733b5SNélio Laranjeiro if (on) 64272733b5SNélio Laranjeiro goto out; 65272733b5SNélio Laranjeiro /* Remove VLAN filter from list. */ 66272733b5SNélio Laranjeiro --priv->vlan_filter_n; 67272733b5SNélio Laranjeiro memmove(&priv->vlan_filter[i], 68272733b5SNélio Laranjeiro &priv->vlan_filter[i + 1], 69272733b5SNélio Laranjeiro sizeof(priv->vlan_filter[i]) * 70272733b5SNélio Laranjeiro (priv->vlan_filter_n - i)); 71272733b5SNélio Laranjeiro priv->vlan_filter[priv->vlan_filter_n] = 0; 72272733b5SNélio Laranjeiro } else { 73272733b5SNélio Laranjeiro assert(i == priv->vlan_filter_n); 74272733b5SNélio Laranjeiro /* Disabling an unknown VLAN filter has no effect. */ 75272733b5SNélio Laranjeiro if (!on) 76272733b5SNélio Laranjeiro goto out; 77272733b5SNélio Laranjeiro /* Add new VLAN filter. */ 78272733b5SNélio Laranjeiro priv->vlan_filter[priv->vlan_filter_n] = vlan_id; 79272733b5SNélio Laranjeiro ++priv->vlan_filter_n; 80272733b5SNélio Laranjeiro } 81272733b5SNélio Laranjeiro if (dev->data->dev_started) 82*af4f09f2SNélio Laranjeiro mlx5_traffic_restart(dev); 83272733b5SNélio Laranjeiro out: 84e4aefd6dSNélio Laranjeiro return ret; 85e9086978SAdrien Mazarguil } 86f3db9489SYaacov Hazan 87f3db9489SYaacov Hazan /** 88f3db9489SYaacov Hazan * Callback to set/reset VLAN stripping for a specific queue. 89f3db9489SYaacov Hazan * 90f3db9489SYaacov Hazan * @param dev 91f3db9489SYaacov Hazan * Pointer to Ethernet device structure. 92f3db9489SYaacov Hazan * @param queue 93f3db9489SYaacov Hazan * RX queue index. 94f3db9489SYaacov Hazan * @param on 95f3db9489SYaacov Hazan * Enable/disable VLAN stripping. 96f3db9489SYaacov Hazan */ 97f3db9489SYaacov Hazan void 98f3db9489SYaacov Hazan mlx5_vlan_strip_queue_set(struct rte_eth_dev *dev, uint16_t queue, int on) 99f3db9489SYaacov Hazan { 100f3db9489SYaacov Hazan struct priv *priv = dev->data->dev_private; 101*af4f09f2SNélio Laranjeiro struct mlx5_rxq_data *rxq = (*priv->rxqs)[queue]; 102*af4f09f2SNélio Laranjeiro struct mlx5_rxq_ctrl *rxq_ctrl = 103*af4f09f2SNélio Laranjeiro container_of(rxq, struct mlx5_rxq_ctrl, rxq); 104*af4f09f2SNélio Laranjeiro struct ibv_wq_attr mod; 105*af4f09f2SNélio Laranjeiro uint16_t vlan_offloads = 106*af4f09f2SNélio Laranjeiro (on ? IBV_WQ_FLAGS_CVLAN_STRIPPING : 0) | 107*af4f09f2SNélio Laranjeiro 0; 108*af4f09f2SNélio Laranjeiro int err; 109f3db9489SYaacov Hazan 110f3db9489SYaacov Hazan /* Validate hw support */ 1117fe24446SShahaf Shuler if (!priv->config.hw_vlan_strip) { 112f3db9489SYaacov Hazan ERROR("VLAN stripping is not supported"); 113f3db9489SYaacov Hazan return; 114f3db9489SYaacov Hazan } 115f3db9489SYaacov Hazan /* Validate queue number */ 116f3db9489SYaacov Hazan if (queue >= priv->rxqs_n) { 117f3db9489SYaacov Hazan ERROR("VLAN stripping, invalid queue number %d", queue); 118f3db9489SYaacov Hazan return; 119f3db9489SYaacov Hazan } 120*af4f09f2SNélio Laranjeiro DEBUG("set VLAN offloads 0x%x for port %d queue %d", 121*af4f09f2SNélio Laranjeiro vlan_offloads, rxq->port_id, queue); 122*af4f09f2SNélio Laranjeiro if (!rxq_ctrl->ibv) { 123*af4f09f2SNélio Laranjeiro /* Update related bits in RX queue. */ 124*af4f09f2SNélio Laranjeiro rxq->vlan_strip = !!on; 125*af4f09f2SNélio Laranjeiro return; 126*af4f09f2SNélio Laranjeiro } 127*af4f09f2SNélio Laranjeiro mod = (struct ibv_wq_attr){ 128*af4f09f2SNélio Laranjeiro .attr_mask = IBV_WQ_ATTR_FLAGS, 129*af4f09f2SNélio Laranjeiro .flags_mask = IBV_WQ_FLAGS_CVLAN_STRIPPING, 130*af4f09f2SNélio Laranjeiro .flags = vlan_offloads, 131*af4f09f2SNélio Laranjeiro }; 132*af4f09f2SNélio Laranjeiro err = mlx5_glue->modify_wq(rxq_ctrl->ibv->wq, &mod); 133*af4f09f2SNélio Laranjeiro if (err) { 134*af4f09f2SNélio Laranjeiro ERROR("%p: failed to modified stripping mode: %s", 135*af4f09f2SNélio Laranjeiro (void *)dev, strerror(err)); 136*af4f09f2SNélio Laranjeiro return; 137*af4f09f2SNélio Laranjeiro } 138*af4f09f2SNélio Laranjeiro /* Update related bits in RX queue. */ 139*af4f09f2SNélio Laranjeiro rxq->vlan_strip = !!on; 140f3db9489SYaacov Hazan } 141f3db9489SYaacov Hazan 142f3db9489SYaacov Hazan /** 143f3db9489SYaacov Hazan * Callback to set/reset VLAN offloads for a port. 144f3db9489SYaacov Hazan * 145f3db9489SYaacov Hazan * @param dev 146f3db9489SYaacov Hazan * Pointer to Ethernet device structure. 147f3db9489SYaacov Hazan * @param mask 148f3db9489SYaacov Hazan * VLAN offload bit mask. 149f3db9489SYaacov Hazan */ 150289ba0c0SDavid Harton int 151f3db9489SYaacov Hazan mlx5_vlan_offload_set(struct rte_eth_dev *dev, int mask) 152f3db9489SYaacov Hazan { 153f3db9489SYaacov Hazan struct priv *priv = dev->data->dev_private; 154f3db9489SYaacov Hazan unsigned int i; 155f3db9489SYaacov Hazan 156f3db9489SYaacov Hazan if (mask & ETH_VLAN_STRIP_MASK) { 15717b843ebSShahaf Shuler int hw_vlan_strip = !!(dev->data->dev_conf.rxmode.offloads & 15817b843ebSShahaf Shuler DEV_RX_OFFLOAD_VLAN_STRIP); 159f3db9489SYaacov Hazan 1607fe24446SShahaf Shuler if (!priv->config.hw_vlan_strip) { 161f3db9489SYaacov Hazan ERROR("VLAN stripping is not supported"); 162289ba0c0SDavid Harton return 0; 163f3db9489SYaacov Hazan } 164f3db9489SYaacov Hazan /* Run on every RX queue and set/reset VLAN stripping. */ 165f3db9489SYaacov Hazan for (i = 0; (i != priv->rxqs_n); i++) 166*af4f09f2SNélio Laranjeiro mlx5_vlan_strip_queue_set(dev, i, hw_vlan_strip); 167f3db9489SYaacov Hazan } 168289ba0c0SDavid Harton return 0; 169f3db9489SYaacov Hazan } 170