aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/broadcom/bcmsysport.c
diff options
context:
space:
mode:
authorFlorian Fainelli <f.fainelli@gmail.com>2018-11-06 15:15:18 -0800
committerDavid S. Miller <davem@davemloft.net>2018-11-06 15:39:48 -0800
commitda106a140f9c6955bb98dfc5a08c0dac72656d5c (patch)
treeb6f66cf629f3879448e9b28676bd43bc37002dc6 /drivers/net/ethernet/broadcom/bcmsysport.c
parentnet: systemport: Simplify queue mapping logic (diff)
downloadlinux-dev-da106a140f9c6955bb98dfc5a08c0dac72656d5c.tar.xz
linux-dev-da106a140f9c6955bb98dfc5a08c0dac72656d5c.zip
net: systemport: Unmap queues upon DSA unregister event
Binding and unbinding the switch driver which creates the DSA slave network devices for which we set-up inspection would lead to undesireable effects since we were not clearing the port/queue mapping to the SYSTEMPORT TX queue. Signed-off-by: Florian Fainelli <f.fainelli@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/broadcom/bcmsysport.c')
-rw-r--r--drivers/net/ethernet/broadcom/bcmsysport.c56
1 files changed, 50 insertions, 6 deletions
diff --git a/drivers/net/ethernet/broadcom/bcmsysport.c b/drivers/net/ethernet/broadcom/bcmsysport.c
index a161d3282321..4574275ef445 100644
--- a/drivers/net/ethernet/broadcom/bcmsysport.c
+++ b/drivers/net/ethernet/broadcom/bcmsysport.c
@@ -2383,17 +2383,61 @@ static int bcm_sysport_map_queues(struct notifier_block *nb,
return 0;
}
+static int bcm_sysport_unmap_queues(struct notifier_block *nb,
+ struct dsa_notifier_register_info *info)
+{
+ struct bcm_sysport_tx_ring *ring;
+ struct bcm_sysport_priv *priv;
+ struct net_device *slave_dev;
+ unsigned int num_tx_queues;
+ struct net_device *dev;
+ unsigned int q, port;
+
+ priv = container_of(nb, struct bcm_sysport_priv, dsa_notifier);
+ if (priv->netdev != info->master)
+ return 0;
+
+ dev = info->master;
+
+ if (dev->netdev_ops != &bcm_sysport_netdev_ops)
+ return 0;
+
+ port = info->port_number;
+ slave_dev = info->info.dev;
+
+ num_tx_queues = slave_dev->real_num_tx_queues;
+
+ for (q = 0; q < dev->num_tx_queues; q++) {
+ ring = &priv->tx_rings[q];
+
+ if (ring->switch_port != port)
+ continue;
+
+ if (!ring->inspect)
+ continue;
+
+ ring->inspect = false;
+ priv->ring_map[q + port * num_tx_queues] = NULL;
+ }
+
+ return 0;
+}
+
static int bcm_sysport_dsa_notifier(struct notifier_block *nb,
unsigned long event, void *ptr)
{
- struct dsa_notifier_register_info *info;
+ int ret = NOTIFY_DONE;
- if (event != DSA_PORT_REGISTER)
- return NOTIFY_DONE;
-
- info = ptr;
+ switch (event) {
+ case DSA_PORT_REGISTER:
+ ret = bcm_sysport_map_queues(nb, ptr);
+ break;
+ case DSA_PORT_UNREGISTER:
+ ret = bcm_sysport_unmap_queues(nb, ptr);
+ break;
+ }
- return notifier_from_errno(bcm_sysport_map_queues(nb, info));
+ return notifier_from_errno(ret);
}
#define REV_FMT "v%2x.%02x"