197f17497SC.J. Collier/*-
297f17497SC.J. Collier *   BSD LICENSE
397f17497SC.J. Collier *
497f17497SC.J. Collier *   Copyright 2015 6WIND S.A.
597f17497SC.J. Collier *   Copyright 2015 Mellanox.
697f17497SC.J. Collier *
797f17497SC.J. Collier *   Redistribution and use in source and binary forms, with or without
897f17497SC.J. Collier *   modification, are permitted provided that the following conditions
997f17497SC.J. Collier *   are met:
1097f17497SC.J. Collier *
1197f17497SC.J. Collier *     * Redistributions of source code must retain the above copyright
1297f17497SC.J. Collier *       notice, this list of conditions and the following disclaimer.
1397f17497SC.J. Collier *     * Redistributions in binary form must reproduce the above copyright
1497f17497SC.J. Collier *       notice, this list of conditions and the following disclaimer in
1597f17497SC.J. Collier *       the documentation and/or other materials provided with the
1697f17497SC.J. Collier *       distribution.
1797f17497SC.J. Collier *     * Neither the name of 6WIND S.A. nor the names of its
1897f17497SC.J. Collier *       contributors may be used to endorse or promote products derived
1997f17497SC.J. Collier *       from this software without specific prior written permission.
2097f17497SC.J. Collier *
2197f17497SC.J. Collier *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2297f17497SC.J. Collier *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2397f17497SC.J. Collier *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2497f17497SC.J. Collier *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2597f17497SC.J. Collier *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2697f17497SC.J. Collier *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2797f17497SC.J. Collier *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2897f17497SC.J. Collier *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2997f17497SC.J. Collier *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3097f17497SC.J. Collier *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
3197f17497SC.J. Collier *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3297f17497SC.J. Collier */
3397f17497SC.J. Collier
3497f17497SC.J. Collier#include <stddef.h>
3597f17497SC.J. Collier#include <errno.h>
3697f17497SC.J. Collier#include <assert.h>
3797f17497SC.J. Collier#include <stdint.h>
3897f17497SC.J. Collier
3943192222SLuca Boccassi/*
4043192222SLuca Boccassi * Not needed by this file; included to work around the lack of off_t
4143192222SLuca Boccassi * definition for mlx5dv.h with unpatched rdma-core versions.
4243192222SLuca Boccassi */
4343192222SLuca Boccassi#include <sys/types.h>
4443192222SLuca Boccassi
4597f17497SC.J. Collier/* DPDK headers don't like -pedantic. */
4697f17497SC.J. Collier#ifdef PEDANTIC
4732e04ea0SChristian Ehrhardt#pragma GCC diagnostic ignored "-Wpedantic"
4897f17497SC.J. Collier#endif
4997f17497SC.J. Collier#include <rte_ethdev.h>
5097f17497SC.J. Collier#include <rte_common.h>
5197f17497SC.J. Collier#ifdef PEDANTIC
5232e04ea0SChristian Ehrhardt#pragma GCC diagnostic error "-Wpedantic"
5397f17497SC.J. Collier#endif
5497f17497SC.J. Collier
5597f17497SC.J. Collier#include "mlx5_utils.h"
5697f17497SC.J. Collier#include "mlx5.h"
5797f17497SC.J. Collier#include "mlx5_autoconf.h"
5897f17497SC.J. Collier
5997f17497SC.J. Collier/**
6097f17497SC.J. Collier * Configure a VLAN filter.
6197f17497SC.J. Collier *
6297f17497SC.J. Collier * @param dev
6397f17497SC.J. Collier *   Pointer to Ethernet device structure.
6497f17497SC.J. Collier * @param vlan_id
6597f17497SC.J. Collier *   VLAN ID to filter.
6697f17497SC.J. Collier * @param on
6797f17497SC.J. Collier *   Toggle filter.
6897f17497SC.J. Collier *
6997f17497SC.J. Collier * @return
7097f17497SC.J. Collier *   0 on success, errno value on failure.
7197f17497SC.J. Collier */
7297f17497SC.J. Collierstatic int
7397f17497SC.J. Colliervlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on)
7497f17497SC.J. Collier{
7597f17497SC.J. Collier	struct priv *priv = dev->data->dev_private;
7697f17497SC.J. Collier	unsigned int i;
7797f17497SC.J. Collier
7897f17497SC.J. Collier	DEBUG("%p: %s VLAN filter ID %" PRIu16,
7997f17497SC.J. Collier	      (void *)dev, (on ? "enable" : "disable"), vlan_id);
8097f17497SC.J. Collier	assert(priv->vlan_filter_n <= RTE_DIM(priv->vlan_filter));
8197f17497SC.J. Collier	for (i = 0; (i != priv->vlan_filter_n); ++i)
8297f17497SC.J. Collier		if (priv->vlan_filter[i] == vlan_id)
8397f17497SC.J. Collier			break;
8497f17497SC.J. Collier	/* Check if there's room for another VLAN filter. */
8597f17497SC.J. Collier	if (i == RTE_DIM(priv->vlan_filter))
8697f17497SC.J. Collier		return ENOMEM;
8797f17497SC.J. Collier	if (i < priv->vlan_filter_n) {
8897f17497SC.J. Collier		assert(priv->vlan_filter_n != 0);
8997f17497SC.J. Collier		/* Enabling an existing VLAN filter has no effect. */
9097f17497SC.J. Collier		if (on)
9197f17497SC.J. Collier			return 0;
9297f17497SC.J. Collier		/* Remove VLAN filter from list. */
9397f17497SC.J. Collier		--priv->vlan_filter_n;
9497f17497SC.J. Collier		memmove(&priv->vlan_filter[i],
9597f17497SC.J. Collier			&priv->vlan_filter[i + 1],
9632e04ea0SChristian Ehrhardt			sizeof(priv->vlan_filter[i]) *
9732e04ea0SChristian Ehrhardt			(priv->vlan_filter_n - i));
9897f17497SC.J. Collier		priv->vlan_filter[priv->vlan_filter_n] = 0;
9997f17497SC.J. Collier	} else {
10097f17497SC.J. Collier		assert(i == priv->vlan_filter_n);
10197f17497SC.J. Collier		/* Disabling an unknown VLAN filter has no effect. */
10297f17497SC.J. Collier		if (!on)
10397f17497SC.J. Collier			return 0;
10497f17497SC.J. Collier		/* Add new VLAN filter. */
10597f17497SC.J. Collier		priv->vlan_filter[priv->vlan_filter_n] = vlan_id;
10697f17497SC.J. Collier		++priv->vlan_filter_n;
10797f17497SC.J. Collier	}
10897f17497SC.J. Collier	/* Rehash flows in all hash RX queues. */
10997f17497SC.J. Collier	priv_mac_addrs_disable(priv);
11097f17497SC.J. Collier	priv_special_flow_disable_all(priv);
11197f17497SC.J. Collier	return priv_rehash_flows(priv);
11297f17497SC.J. Collier}
11397f17497SC.J. Collier
11497f17497SC.J. Collier/**
11597f17497SC.J. Collier * DPDK callback to configure a VLAN filter.
11697f17497SC.J. Collier *
11797f17497SC.J. Collier * @param dev
11897f17497SC.J. Collier *   Pointer to Ethernet device structure.
11997f17497SC.J. Collier * @param vlan_id
12097f17497SC.J. Collier *   VLAN ID to filter.
12197f17497SC.J. Collier * @param on
12297f17497SC.J. Collier *   Toggle filter.
12397f17497SC.J. Collier *
12497f17497SC.J. Collier * @return
12597f17497SC.J. Collier *   0 on success, negative errno value on failure.
12697f17497SC.J. Collier */
12797f17497SC.J. Collierint
12897f17497SC.J. Colliermlx5_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on)
12997f17497SC.J. Collier{
13097f17497SC.J. Collier	struct priv *priv = dev->data->dev_private;
13197f17497SC.J. Collier	int ret;
13297f17497SC.J. Collier
13397f17497SC.J. Collier	priv_lock(priv);
13497f17497SC.J. Collier	ret = vlan_filter_set(dev, vlan_id, on);
13597f17497SC.J. Collier	priv_unlock(priv);
13697f17497SC.J. Collier	assert(ret >= 0);
13797f17497SC.J. Collier	return -ret;
13897f17497SC.J. Collier}
13997f17497SC.J. Collier
14097f17497SC.J. Collier/**
14197f17497SC.J. Collier * Set/reset VLAN stripping for a specific queue.
14297f17497SC.J. Collier *
14397f17497SC.J. Collier * @param priv
14497f17497SC.J. Collier *   Pointer to private structure.
14597f17497SC.J. Collier * @param idx
14697f17497SC.J. Collier *   RX queue index.
14797f17497SC.J. Collier * @param on
14897f17497SC.J. Collier *   Enable/disable VLAN stripping.
14997f17497SC.J. Collier */
15097f17497SC.J. Collierstatic void
15197f17497SC.J. Collierpriv_vlan_strip_queue_set(struct priv *priv, uint16_t idx, int on)
15297f17497SC.J. Collier{
15397f17497SC.J. Collier	struct rxq *rxq = (*priv->rxqs)[idx];
1548b25d1adSChristian Ehrhardt	struct rxq_ctrl *rxq_ctrl = container_of(rxq, struct rxq_ctrl, rxq);
15597f17497SC.J. Collier	struct ibv_exp_wq_attr mod;
15697f17497SC.J. Collier	uint16_t vlan_offloads =
15797f17497SC.J. Collier		(on ? IBV_EXP_RECEIVE_WQ_CVLAN_STRIP : 0) |
15897f17497SC.J. Collier		0;
15997f17497SC.J. Collier	int err;
16097f17497SC.J. Collier
16197f17497SC.J. Collier	DEBUG("set VLAN offloads 0x%x for port %d queue %d",
16297f17497SC.J. Collier	      vlan_offloads, rxq->port_id, idx);
16397f17497SC.J. Collier	mod = (struct ibv_exp_wq_attr){
16497f17497SC.J. Collier		.attr_mask = IBV_EXP_WQ_ATTR_VLAN_OFFLOADS,
16597f17497SC.J. Collier		.vlan_offloads = vlan_offloads,
16697f17497SC.J. Collier	};
16797f17497SC.J. Collier
1688b25d1adSChristian Ehrhardt	err = ibv_exp_modify_wq(rxq_ctrl->wq, &mod);
16997f17497SC.J. Collier	if (err) {
17097f17497SC.J. Collier		ERROR("%p: failed to modified stripping mode: %s",
17197f17497SC.J. Collier		      (void *)priv, strerror(err));
17297f17497SC.J. Collier		return;
17397f17497SC.J. Collier	}
17497f17497SC.J. Collier
17597f17497SC.J. Collier	/* Update related bits in RX queue. */
17697f17497SC.J. Collier	rxq->vlan_strip = !!on;
17797f17497SC.J. Collier}
17897f17497SC.J. Collier
17997f17497SC.J. Collier/**
18097f17497SC.J. Collier * Callback to set/reset VLAN stripping for a specific queue.
18197f17497SC.J. Collier *
18297f17497SC.J. Collier * @param dev
18397f17497SC.J. Collier *   Pointer to Ethernet device structure.
18497f17497SC.J. Collier * @param queue
18597f17497SC.J. Collier *   RX queue index.
18697f17497SC.J. Collier * @param on
18797f17497SC.J. Collier *   Enable/disable VLAN stripping.
18897f17497SC.J. Collier */
18997f17497SC.J. Colliervoid
19097f17497SC.J. Colliermlx5_vlan_strip_queue_set(struct rte_eth_dev *dev, uint16_t queue, int on)
19197f17497SC.J. Collier{
19297f17497SC.J. Collier	struct priv *priv = dev->data->dev_private;
19397f17497SC.J. Collier
19497f17497SC.J. Collier	/* Validate hw support */
19597f17497SC.J. Collier	if (!priv->hw_vlan_strip) {
19697f17497SC.J. Collier		ERROR("VLAN stripping is not supported");
19797f17497SC.J. Collier		return;
19897f17497SC.J. Collier	}
19997f17497SC.J. Collier
20097f17497SC.J. Collier	/* Validate queue number */
20197f17497SC.J. Collier	if (queue >= priv->rxqs_n) {
20297f17497SC.J. Collier		ERROR("VLAN stripping, invalid queue number %d", queue);
20397f17497SC.J. Collier		return;
20497f17497SC.J. Collier	}
20597f17497SC.J. Collier
20697f17497SC.J. Collier	priv_lock(priv);
20797f17497SC.J. Collier	priv_vlan_strip_queue_set(priv, queue, on);
20897f17497SC.J. Collier	priv_unlock(priv);
20997f17497SC.J. Collier}
21097f17497SC.J. Collier
21197f17497SC.J. Collier/**
21297f17497SC.J. Collier * Callback to set/reset VLAN offloads for a port.
21397f17497SC.J. Collier *
21497f17497SC.J. Collier * @param dev
21597f17497SC.J. Collier *   Pointer to Ethernet device structure.
21697f17497SC.J. Collier * @param mask
21797f17497SC.J. Collier *   VLAN offload bit mask.
21897f17497SC.J. Collier */
21997f17497SC.J. Colliervoid
22097f17497SC.J. Colliermlx5_vlan_offload_set(struct rte_eth_dev *dev, int mask)
22197f17497SC.J. Collier{
22297f17497SC.J. Collier	struct priv *priv = dev->data->dev_private;
22397f17497SC.J. Collier	unsigned int i;
22497f17497SC.J. Collier
22597f17497SC.J. Collier	if (mask & ETH_VLAN_STRIP_MASK) {
2268b25d1adSChristian Ehrhardt		int hw_vlan_strip = !!dev->data->dev_conf.rxmode.hw_vlan_strip;
22797f17497SC.J. Collier
22897f17497SC.J. Collier		if (!priv->hw_vlan_strip) {
22997f17497SC.J. Collier			ERROR("VLAN stripping is not supported");
23097f17497SC.J. Collier			return;
23197f17497SC.J. Collier		}
23297f17497SC.J. Collier
23397f17497SC.J. Collier		/* Run on every RX queue and set/reset VLAN stripping. */
23497f17497SC.J. Collier		priv_lock(priv);
23597f17497SC.J. Collier		for (i = 0; (i != priv->rxqs_n); i++)
23697f17497SC.J. Collier			priv_vlan_strip_queue_set(priv, i, hw_vlan_strip);
23797f17497SC.J. Collier		priv_unlock(priv);
23897f17497SC.J. Collier	}
23997f17497SC.J. Collier}
240