OSDN Git Service

Merge branch 'net-systemport-Unmap-queues-upon-DSA-unregister-event'
authorDavid S. Miller <davem@davemloft.net>
Tue, 6 Nov 2018 23:39:48 +0000 (15:39 -0800)
committerDavid S. Miller <davem@davemloft.net>
Tue, 6 Nov 2018 23:39:48 +0000 (15:39 -0800)
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>
drivers/net/dsa/bcm_sf2.c
drivers/net/ethernet/broadcom/bcmsysport.c
drivers/net/ethernet/broadcom/bcmsysport.h

index d8b9304..aa4a1f5 100644 (file)
@@ -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");
index 2e60dda..4574275 100644 (file)
@@ -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++;
+       }
+
+       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;
 
-               /* Set all queues as being used now */
-               set_bit(q + start, &priv->queue_bitmap);
+       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;
-
-       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"
index 7a0b7bf..0887e63 100644 (file)
@@ -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];
 
 };