Commit 1f3ccc3c authored by Florian Fainelli's avatar Florian Fainelli Committed by David S. Miller

net: systemport: Correclty disambiguate driver instances

While adding the DSA notifier, we will be sending DSA notifications with
info->master that is going to point to a particular net_device instance.

Our logic in bcm_sysport_map_queues() correctly disambiguates net_device
instances that are not covered by our own driver, but it will not make
sure that info->master points to a particular driver instance that we
are interested in. In a system where e.g: two or more SYSTEMPORT
instances are registered, this would lead in programming two or more
times the queue mapping, completely messing with the logic which does
the queue/port allocation and tracking.

Fix this by looking at the notifier_block pointer which is unique per
instance and allows us to go back to our driver private structure, and
in turn to the backing net_device instance.

Fixes: d1565763 ("net: systemport: Establish lower/upper queue mapping")
Signed-off-by: default avatarFlorian Fainelli <f.fainelli@gmail.com>
Reviewed-by: default avatarVivien Didelot <vivien.didelot@savoirfairelinux.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 9faedd64
...@@ -2144,14 +2144,21 @@ static const struct net_device_ops bcm_sysport_netdev_ops = { ...@@ -2144,14 +2144,21 @@ static const struct net_device_ops bcm_sysport_netdev_ops = {
.ndo_select_queue = bcm_sysport_select_queue, .ndo_select_queue = bcm_sysport_select_queue,
}; };
static int bcm_sysport_map_queues(struct net_device *dev, static int bcm_sysport_map_queues(struct notifier_block *nb,
struct dsa_notifier_register_info *info) struct dsa_notifier_register_info *info)
{ {
struct bcm_sysport_priv *priv = netdev_priv(dev);
struct bcm_sysport_tx_ring *ring; struct bcm_sysport_tx_ring *ring;
struct bcm_sysport_priv *priv;
struct net_device *slave_dev; struct net_device *slave_dev;
unsigned int num_tx_queues; unsigned int num_tx_queues;
unsigned int q, start, port; unsigned int q, start, port;
struct net_device *dev;
priv = container_of(nb, struct bcm_sysport_priv, dsa_notifier);
if (priv->netdev != info->master)
return 0;
dev = info->master;
/* We can't be setting up queue inspection for non directly attached /* We can't be setting up queue inspection for non directly attached
* switches * switches
...@@ -2174,6 +2181,7 @@ static int bcm_sysport_map_queues(struct net_device *dev, ...@@ -2174,6 +2181,7 @@ static int bcm_sysport_map_queues(struct net_device *dev,
if (priv->is_lite) if (priv->is_lite)
netif_set_real_num_tx_queues(slave_dev, netif_set_real_num_tx_queues(slave_dev,
slave_dev->num_tx_queues / 2); slave_dev->num_tx_queues / 2);
num_tx_queues = slave_dev->real_num_tx_queues; num_tx_queues = slave_dev->real_num_tx_queues;
if (priv->per_port_num_tx_queues && if (priv->per_port_num_tx_queues &&
...@@ -2201,7 +2209,7 @@ static int bcm_sysport_map_queues(struct net_device *dev, ...@@ -2201,7 +2209,7 @@ static int bcm_sysport_map_queues(struct net_device *dev,
return 0; return 0;
} }
static int bcm_sysport_dsa_notifier(struct notifier_block *unused, static int bcm_sysport_dsa_notifier(struct notifier_block *nb,
unsigned long event, void *ptr) unsigned long event, void *ptr)
{ {
struct dsa_notifier_register_info *info; struct dsa_notifier_register_info *info;
...@@ -2211,7 +2219,7 @@ static int bcm_sysport_dsa_notifier(struct notifier_block *unused, ...@@ -2211,7 +2219,7 @@ static int bcm_sysport_dsa_notifier(struct notifier_block *unused,
info = ptr; info = ptr;
return notifier_from_errno(bcm_sysport_map_queues(info->master, info)); return notifier_from_errno(bcm_sysport_map_queues(nb, info));
} }
#define REV_FMT "v%2x.%02x" #define REV_FMT "v%2x.%02x"
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment