net: mscc: ocelot: deinitialize only initialized ports
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>
This commit is contained in:
Родитель
22cdb493de
Коммит
e5fb512d81
|
@ -643,10 +643,13 @@ static void felix_teardown(struct dsa_switch *ds)
|
||||||
{
|
{
|
||||||
struct ocelot *ocelot = ds->priv;
|
struct ocelot *ocelot = ds->priv;
|
||||||
struct felix *felix = ocelot_to_felix(ocelot);
|
struct felix *felix = ocelot_to_felix(ocelot);
|
||||||
|
int port;
|
||||||
|
|
||||||
if (felix->info->mdio_bus_free)
|
if (felix->info->mdio_bus_free)
|
||||||
felix->info->mdio_bus_free(ocelot);
|
felix->info->mdio_bus_free(ocelot);
|
||||||
|
|
||||||
|
for (port = 0; port < ocelot->num_phys_ports; port++)
|
||||||
|
ocelot_deinit_port(ocelot, port);
|
||||||
ocelot_deinit_timestamp(ocelot);
|
ocelot_deinit_timestamp(ocelot);
|
||||||
/* stop workqueue thread */
|
/* stop workqueue thread */
|
||||||
ocelot_deinit(ocelot);
|
ocelot_deinit(ocelot);
|
||||||
|
|
|
@ -1550,18 +1550,18 @@ EXPORT_SYMBOL(ocelot_init);
|
||||||
|
|
||||||
void ocelot_deinit(struct ocelot *ocelot)
|
void ocelot_deinit(struct ocelot *ocelot)
|
||||||
{
|
{
|
||||||
struct ocelot_port *port;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
cancel_delayed_work(&ocelot->stats_work);
|
cancel_delayed_work(&ocelot->stats_work);
|
||||||
destroy_workqueue(ocelot->stats_queue);
|
destroy_workqueue(ocelot->stats_queue);
|
||||||
mutex_destroy(&ocelot->stats_lock);
|
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);
|
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");
|
MODULE_LICENSE("Dual MIT/GPL");
|
||||||
|
|
|
@ -908,6 +908,8 @@ static void mscc_ocelot_release_ports(struct ocelot *ocelot)
|
||||||
if (!ocelot_port)
|
if (!ocelot_port)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
ocelot_deinit_port(ocelot, port);
|
||||||
|
|
||||||
priv = container_of(ocelot_port, struct ocelot_port_private,
|
priv = container_of(ocelot_port, struct ocelot_port_private,
|
||||||
port);
|
port);
|
||||||
|
|
||||||
|
|
|
@ -678,6 +678,7 @@ void ocelot_configure_cpu(struct ocelot *ocelot, int npi,
|
||||||
int ocelot_init(struct ocelot *ocelot);
|
int ocelot_init(struct ocelot *ocelot);
|
||||||
void ocelot_deinit(struct ocelot *ocelot);
|
void ocelot_deinit(struct ocelot *ocelot);
|
||||||
void ocelot_init_port(struct ocelot *ocelot, int port);
|
void ocelot_init_port(struct ocelot *ocelot, int port);
|
||||||
|
void ocelot_deinit_port(struct ocelot *ocelot, int port);
|
||||||
|
|
||||||
/* DSA callbacks */
|
/* DSA callbacks */
|
||||||
void ocelot_port_enable(struct ocelot *ocelot, int port,
|
void ocelot_port_enable(struct ocelot *ocelot, int port,
|
||||||
|
|
Загрузка…
Ссылка в новой задаче