net: mscc: ocelot: deinitialize only initialized ports
authorVladimir Oltean <vladimir.oltean@nxp.com>
Fri, 18 Sep 2020 01:07:30 +0000 (04:07 +0300)
committerDavid S. Miller <davem@davemloft.net>
Fri, 18 Sep 2020 20:52:34 +0000 (13:52 -0700)
Currently mscc_ocelot_init_ports() will skip initializing a port when it
doesn't have a phy-handle, so the ocelot->ports[port] pointer will be
NULL. Take this into consideration when tearing down the driver, and add
a new function ocelot_deinit_port() to the switch library, mirror of
ocelot_init_port(), which needs to be called by the driver for all ports
it has initialized.

Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
Tested-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
Reviewed-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/dsa/ocelot/felix.c
drivers/net/ethernet/mscc/ocelot.c
drivers/net/ethernet/mscc/ocelot_vsc7514.c
include/soc/mscc/ocelot.h

index 66da447..01427cd 100644 (file)
@@ -643,10 +643,13 @@ static void felix_teardown(struct dsa_switch *ds)
 {
        struct ocelot *ocelot = ds->priv;
        struct felix *felix = ocelot_to_felix(ocelot);
+       int port;
 
        if (felix->info->mdio_bus_free)
                felix->info->mdio_bus_free(ocelot);
 
+       for (port = 0; port < ocelot->num_phys_ports; port++)
+               ocelot_deinit_port(ocelot, port);
        ocelot_deinit_timestamp(ocelot);
        /* stop workqueue thread */
        ocelot_deinit(ocelot);
index 83eb7c3..8518e1d 100644 (file)
@@ -1550,18 +1550,18 @@ EXPORT_SYMBOL(ocelot_init);
 
 void ocelot_deinit(struct ocelot *ocelot)
 {
-       struct ocelot_port *port;
-       int i;
-
        cancel_delayed_work(&ocelot->stats_work);
        destroy_workqueue(ocelot->stats_queue);
        mutex_destroy(&ocelot->stats_lock);
-
-       for (i = 0; i < ocelot->num_phys_ports; i++) {
-               port = ocelot->ports[i];
-               skb_queue_purge(&port->tx_skbs);
-       }
 }
 EXPORT_SYMBOL(ocelot_deinit);
 
+void ocelot_deinit_port(struct ocelot *ocelot, int port)
+{
+       struct ocelot_port *ocelot_port = ocelot->ports[port];
+
+       skb_queue_purge(&ocelot_port->tx_skbs);
+}
+EXPORT_SYMBOL(ocelot_deinit_port);
+
 MODULE_LICENSE("Dual MIT/GPL");
index 252c49b..e02fb8b 100644 (file)
@@ -908,6 +908,8 @@ static void mscc_ocelot_release_ports(struct ocelot *ocelot)
                if (!ocelot_port)
                        continue;
 
+               ocelot_deinit_port(ocelot, port);
+
                priv = container_of(ocelot_port, struct ocelot_port_private,
                                    port);
 
index 4521dd6..0ac4e7f 100644 (file)
@@ -678,6 +678,7 @@ void ocelot_configure_cpu(struct ocelot *ocelot, int npi,
 int ocelot_init(struct ocelot *ocelot);
 void ocelot_deinit(struct ocelot *ocelot);
 void ocelot_init_port(struct ocelot *ocelot, int port);
+void ocelot_deinit_port(struct ocelot *ocelot, int port);
 
 /* DSA callbacks */
 void ocelot_port_enable(struct ocelot *ocelot, int port,