diff mbox series

[net-next,3/3] cxgb4: add main VI to mirror VI config replication

Message ID 49115de640336dc419200a740b58793ac26a674e.1593085107.git.rahul.lakkireddy@chelsio.com
State Changes Requested
Delegated to: David Miller
Headers show
Series cxgb4: add mirror action support for TC-MATCHALL | expand

Commit Message

Rahul Lakkireddy June 25, 2020, 11:58 a.m. UTC
When mirror VI is enabled, replicate various VI config params
enabled on main VI to mirror VI. These include replicating MTU,
promiscuous mode, all-multicast mode, and enabled netdev Rx
feature offloads.

Signed-off-by: Rahul Lakkireddy <rahul.lakkireddy@chelsio.com>
---
 .../net/ethernet/chelsio/cxgb4/cxgb4_main.c   | 155 ++++++++++++++++--
 1 file changed, 143 insertions(+), 12 deletions(-)
diff mbox series

Patch

diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
index 0517eac4c8a5..7e7fd34c04a8 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
@@ -431,14 +431,32 @@  static int set_rxmode(struct net_device *dev, int mtu, bool sleep_ok)
 {
 	struct port_info *pi = netdev_priv(dev);
 	struct adapter *adapter = pi->adapter;
+	int ret;
 
 	__dev_uc_sync(dev, cxgb4_mac_sync, cxgb4_mac_unsync);
 	__dev_mc_sync(dev, cxgb4_mac_sync, cxgb4_mac_unsync);
 
-	return t4_set_rxmode(adapter, adapter->mbox, pi->viid, mtu,
-			     (dev->flags & IFF_PROMISC) ? 1 : 0,
-			     (dev->flags & IFF_ALLMULTI) ? 1 : 0, 1, -1,
-			     sleep_ok);
+	ret = t4_set_rxmode(adapter, adapter->mbox, pi->viid, mtu,
+			    (dev->flags & IFF_PROMISC) ? 1 : 0,
+			    (dev->flags & IFF_ALLMULTI) ? 1 : 0, 1, -1,
+			    sleep_ok);
+	if (ret)
+		return ret;
+
+	if (refcount_read(&pi->vi_mirror_refcnt)) {
+		ret = t4_set_rxmode(adapter, adapter->mbox, pi->viid_mirror,
+				    mtu, (dev->flags & IFF_PROMISC) ? 1 : 0,
+				    (dev->flags & IFF_ALLMULTI) ? 1 : 0, 1, -1,
+				    sleep_ok);
+		if (ret) {
+			dev_err(adapter->pdev_dev,
+				"Failed setting Rx Mode for Mirror VI 0x%x, ret: %d\n",
+				pi->viid_mirror, ret);
+			return ret;
+		}
+	}
+
+	return ret;
 }
 
 /**
@@ -1270,18 +1288,36 @@  int cxgb4_set_rspq_intr_params(struct sge_rspq *q,
 
 static int cxgb_set_features(struct net_device *dev, netdev_features_t features)
 {
-	const struct port_info *pi = netdev_priv(dev);
 	netdev_features_t changed = dev->features ^ features;
+	const struct port_info *pi = netdev2pinfo(dev);
+	struct adapter *adap = netdev2adap(dev);
 	int err;
 
 	if (!(changed & NETIF_F_HW_VLAN_CTAG_RX))
 		return 0;
 
-	err = t4_set_rxmode(pi->adapter, pi->adapter->pf, pi->viid, -1,
-			    -1, -1, -1,
+	err = t4_set_rxmode(adap, adap->mbox, pi->viid, -1, -1, -1, -1,
 			    !!(features & NETIF_F_HW_VLAN_CTAG_RX), true);
-	if (unlikely(err))
+	if (err)
+		goto out;
+
+	if (refcount_read(&pi->vi_mirror_refcnt)) {
+		err = t4_set_rxmode(adap, adap->mbox, pi->viid_mirror,
+				    -1, -1, -1, -1,
+				    !!(features & NETIF_F_HW_VLAN_CTAG_RX),
+				    true);
+		if (err) {
+			dev_err(adap->pdev_dev,
+				"Failed setting VLAN Rx mode for Mirror VI 0x%x, ret: %d\n",
+				pi->viid_mirror, err);
+			goto out;
+		}
+	}
+
+out:
+	if (err)
 		dev->features = features ^ NETIF_F_HW_VLAN_CTAG_RX;
+
 	return err;
 }
 
@@ -1452,6 +1488,74 @@  static void cxgb4_port_mirror_free_queues(struct net_device *dev)
 	mutex_unlock(&s->queue_mutex);
 }
 
+static int cxgb4_port_mirror_start(struct net_device *dev)
+{
+	struct port_info *pi = netdev2pinfo(dev);
+	struct adapter *adap = netdev2adap(dev);
+	int ret, idx = -1;
+
+	if (!refcount_read(&pi->vi_mirror_refcnt))
+		return 0;
+
+	/* Mirror VIs can be created dynamically after stack had
+	 * already setup Rx modes like MTU, promisc, allmulti, etc.
+	 * on main VI. So, parse what the stack had setup on the
+	 * main VI and update the same on the mirror VI.
+	 */
+	ret = t4_set_rxmode(adap, adap->mbox, pi->viid_mirror, dev->mtu,
+			    (dev->flags & IFF_PROMISC) ? 1 : 0,
+			    (dev->flags & IFF_ALLMULTI) ? 1 : 0, 1,
+			    !!(dev->features & NETIF_F_HW_VLAN_CTAG_RX), true);
+	if (ret) {
+		dev_err(adap->pdev_dev,
+			"Failed start up Rx mode for Mirror VI 0x%x, ret: %d\n",
+			pi->viid_mirror, ret);
+		return ret;
+	}
+
+	/* Enable replication bit for the device's MAC address
+	 * in MPS TCAM, so that the packets for the main VI are
+	 * replicated to mirror VI.
+	 */
+	ret = cxgb4_update_mac_filt(pi, pi->viid_mirror, &idx,
+				    dev->dev_addr, true, NULL);
+	if (ret) {
+		dev_err(adap->pdev_dev,
+			"Failed updating MAC filter for Mirror VI 0x%x, ret: %d\n",
+			pi->viid_mirror, ret);
+		return ret;
+	}
+
+	/* Enabling a Virtual Interface can result in an interrupt
+	 * during the processing of the VI Enable command and, in some
+	 * paths, result in an attempt to issue another command in the
+	 * interrupt context. Thus, we disable interrupts during the
+	 * course of the VI Enable command ...
+	 */
+	local_bh_disable();
+	ret = t4_enable_vi_params(adap, adap->mbox, pi->viid_mirror, true, true,
+				  false);
+	local_bh_enable();
+	if (ret)
+		dev_err(adap->pdev_dev,
+			"Failed starting Mirror VI 0x%x, ret: %d\n",
+			pi->viid_mirror, ret);
+
+	return ret;
+}
+
+static void cxgb4_port_mirror_stop(struct net_device *dev)
+{
+	struct port_info *pi = netdev2pinfo(dev);
+	struct adapter *adap = netdev2adap(dev);
+
+	if (!refcount_read(&pi->vi_mirror_refcnt))
+		return;
+
+	t4_enable_vi_params(adap, adap->mbox, pi->viid_mirror, false, false,
+			    false);
+}
+
 int cxgb4_port_mirror_alloc(struct net_device *dev)
 {
 	struct port_info *pi = netdev2pinfo(dev);
@@ -1477,10 +1581,17 @@  int cxgb4_port_mirror_alloc(struct net_device *dev)
 		ret = cxgb4_port_mirror_alloc_queues(dev);
 		if (ret < 0)
 			goto out_free_vi;
+
+		ret = cxgb4_port_mirror_start(dev);
+		if (ret < 0)
+			goto out_free_queues;
 	}
 
 	return 0;
 
+out_free_queues:
+	cxgb4_port_mirror_free_queues(dev);
+
 out_free_vi:
 	refcount_set(&pi->vi_mirror_refcnt, 0);
 	t4_free_vi(adap, adap->mbox, adap->pf, 0, pi->viid_mirror);
@@ -1501,6 +1612,7 @@  void cxgb4_port_mirror_free(struct net_device *dev)
 		return;
 	}
 
+	cxgb4_port_mirror_stop(dev);
 	cxgb4_port_mirror_free_queues(dev);
 
 	refcount_set(&pi->vi_mirror_refcnt, 0);
@@ -2786,6 +2898,10 @@  int cxgb_open(struct net_device *dev)
 	if (err)
 		goto out_free;
 
+	err = cxgb4_port_mirror_start(dev);
+	if (err)
+		goto out_free;
+
 	netif_tx_start_all_queues(dev);
 	return err;
 
@@ -2811,6 +2927,7 @@  int cxgb_close(struct net_device *dev)
 	if (ret)
 		return ret;
 
+	cxgb4_port_mirror_stop(dev);
 	cxgb4_port_mirror_free_queues(dev);
 	return ret;
 }
@@ -3078,13 +3195,27 @@  static void cxgb_set_rxmode(struct net_device *dev)
 
 static int cxgb_change_mtu(struct net_device *dev, int new_mtu)
 {
+	struct port_info *pi = netdev2pinfo(dev);
+	struct adapter *adap = netdev2adap(dev);
 	int ret;
-	struct port_info *pi = netdev_priv(dev);
 
-	ret = t4_set_rxmode(pi->adapter, pi->adapter->pf, pi->viid, new_mtu, -1,
+	ret = t4_set_rxmode(adap, adap->mbox, pi->viid, new_mtu, -1,
 			    -1, -1, -1, true);
-	if (!ret)
-		dev->mtu = new_mtu;
+	if (ret)
+		return ret;
+
+	if (refcount_read(&pi->vi_mirror_refcnt)) {
+		ret = t4_set_rxmode(adap, adap->mbox, pi->viid_mirror,
+				    new_mtu, -1, -1, -1, -1, true);
+		if (ret) {
+			dev_err(adap->pdev_dev,
+				"MTU change for Mirror VI 0x%x error: %d\n",
+				pi->viid_mirror, ret);
+			return ret;
+		}
+	}
+
+	dev->mtu = new_mtu;
 	return ret;
 }