Merge branch 'net-systemport-Unmap-queues-upon-DSA-unregister-event'
Florian Fainelli says: ==================== net: systemport: Unmap queues upon DSA unregister event This patch series fixes the unbinding/binding of the bcm_sf2 switch driver along with bcmsysport which monitors the switch port queues. Because the driver was not processing the DSA_PORT_UNREGISTER event, we would not be unmapping switch port/queues, which could cause incorrect decisions to be made by the HW (e.g: queue always back-pressured). ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Коммит
7c588c7468
|
@ -1095,12 +1095,16 @@ static int bcm_sf2_sw_probe(struct platform_device *pdev)
|
|||
return ret;
|
||||
}
|
||||
|
||||
bcm_sf2_gphy_enable_set(priv->dev->ds, true);
|
||||
|
||||
ret = bcm_sf2_mdio_register(ds);
|
||||
if (ret) {
|
||||
pr_err("failed to register MDIO bus\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
bcm_sf2_gphy_enable_set(priv->dev->ds, false);
|
||||
|
||||
ret = bcm_sf2_cfp_rst(priv);
|
||||
if (ret) {
|
||||
pr_err("failed to reset CFP\n");
|
||||
|
|
|
@ -2324,7 +2324,7 @@ static int bcm_sysport_map_queues(struct notifier_block *nb,
|
|||
struct bcm_sysport_priv *priv;
|
||||
struct net_device *slave_dev;
|
||||
unsigned int num_tx_queues;
|
||||
unsigned int q, start, port;
|
||||
unsigned int q, qp, port;
|
||||
struct net_device *dev;
|
||||
|
||||
priv = container_of(nb, struct bcm_sysport_priv, dsa_notifier);
|
||||
|
@ -2363,20 +2363,61 @@ static int bcm_sysport_map_queues(struct notifier_block *nb,
|
|||
|
||||
priv->per_port_num_tx_queues = num_tx_queues;
|
||||
|
||||
start = find_first_zero_bit(&priv->queue_bitmap, dev->num_tx_queues);
|
||||
for (q = 0; q < num_tx_queues; q++) {
|
||||
ring = &priv->tx_rings[q + start];
|
||||
for (q = 0, qp = 0; q < dev->num_tx_queues && qp < num_tx_queues;
|
||||
q++) {
|
||||
ring = &priv->tx_rings[q];
|
||||
|
||||
if (ring->inspect)
|
||||
continue;
|
||||
|
||||
/* Just remember the mapping actual programming done
|
||||
* during bcm_sysport_init_tx_ring
|
||||
*/
|
||||
ring->switch_queue = q;
|
||||
ring->switch_queue = qp;
|
||||
ring->switch_port = port;
|
||||
ring->inspect = true;
|
||||
priv->ring_map[q + port * num_tx_queues] = ring;
|
||||
qp++;
|
||||
}
|
||||
|
||||
/* Set all queues as being used now */
|
||||
set_bit(q + start, &priv->queue_bitmap);
|
||||
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;
|
||||
|
@ -2385,14 +2426,18 @@ static int bcm_sysport_map_queues(struct notifier_block *nb,
|
|||
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;
|
||||
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;
|
||||
}
|
||||
|
||||
info = ptr;
|
||||
|
||||
return notifier_from_errno(bcm_sysport_map_queues(nb, info));
|
||||
return notifier_from_errno(ret);
|
||||
}
|
||||
|
||||
#define REV_FMT "v%2x.%02x"
|
||||
|
|
|
@ -796,7 +796,6 @@ struct bcm_sysport_priv {
|
|||
/* map information between switch port queues and local queues */
|
||||
struct notifier_block dsa_notifier;
|
||||
unsigned int per_port_num_tx_queues;
|
||||
unsigned long queue_bitmap;
|
||||
struct bcm_sysport_tx_ring *ring_map[DSA_MAX_PORTS * 8];
|
||||
|
||||
};
|
||||
|
|
Загрузка…
Ссылка в новой задаче