xref: /dpdk/drivers/net/mlx5/mlx5_vlan.c (revision af4f09f28294fac762ff413fbf14b48c42c128fd)
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