@@ -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;
}
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(-)