Skip to content

Commit

Permalink
can: mcp251x: Fix resume from sleep before interface was brought up
Browse files Browse the repository at this point in the history
Since 8ce8c0a the driver queues work via priv->restart_work when
resuming after suspend, even when the interface was not previously
enabled. This causes a null dereference error as the workqueue is
only allocated and initialized in mcp251x_open().

To fix this we move the workqueue init to mcp251x_can_probe() as
there is no reason to do it later and repeat it whenever
mcp251x_open() is called.

Fixes: 8ce8c0a ("can: mcp251x: only reset hardware as required")
Cc: stable@vger.kernel.org
Signed-off-by: Frieder Schrempf <frieder.schrempf@kontron.de>
  • Loading branch information
fschrempf authored and intel-lab-lkp committed May 4, 2021
1 parent bd573ea commit a6e3fbb
Showing 1 changed file with 14 additions and 11 deletions.
25 changes: 14 additions & 11 deletions drivers/net/can/spi/mcp251x.c
Expand Up @@ -956,8 +956,6 @@ static int mcp251x_stop(struct net_device *net)

priv->force_quit = 1;
free_irq(spi->irq, priv);
destroy_workqueue(priv->wq);
priv->wq = NULL;

mutex_lock(&priv->mcp_lock);

Expand Down Expand Up @@ -1224,15 +1222,6 @@ static int mcp251x_open(struct net_device *net)
goto out_close;
}

priv->wq = alloc_workqueue("mcp251x_wq", WQ_FREEZABLE | WQ_MEM_RECLAIM,
0);
if (!priv->wq) {
ret = -ENOMEM;
goto out_clean;
}
INIT_WORK(&priv->tx_work, mcp251x_tx_work_handler);
INIT_WORK(&priv->restart_work, mcp251x_restart_work_handler);

ret = mcp251x_hw_wake(spi);
if (ret)
goto out_free_wq;
Expand Down Expand Up @@ -1373,6 +1362,15 @@ static int mcp251x_can_probe(struct spi_device *spi)
if (ret)
goto out_clk;

priv->wq = alloc_workqueue("mcp251x_wq", WQ_FREEZABLE | WQ_MEM_RECLAIM,
0);
if (!priv->wq) {
ret = -ENOMEM;
goto out_clk;
}
INIT_WORK(&priv->tx_work, mcp251x_tx_work_handler);
INIT_WORK(&priv->restart_work, mcp251x_restart_work_handler);

priv->spi = spi;
mutex_init(&priv->mcp_lock);

Expand Down Expand Up @@ -1417,6 +1415,8 @@ static int mcp251x_can_probe(struct spi_device *spi)
return 0;

error_probe:
destroy_workqueue(priv->wq);
priv->wq = NULL;
mcp251x_power_enable(priv->power, 0);

out_clk:
Expand All @@ -1438,6 +1438,9 @@ static int mcp251x_can_remove(struct spi_device *spi)

mcp251x_power_enable(priv->power, 0);

destroy_workqueue(priv->wq);
priv->wq = NULL;

clk_disable_unprepare(priv->clk);

free_candev(net);
Expand Down

0 comments on commit a6e3fbb

Please sign in to comment.