Commit 9f3c3b42 authored by Jakub Kicinski's avatar Jakub Kicinski

Merge tag 'linux-can-fixes-for-5.13-20210506' of...

Merge tag 'linux-can-fixes-for-5.13-20210506' of git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can

Marc Kleine-Budde says:

====================
pull-request: can 2021-05-06

The first two patches target the mcp251xfd driver. Dan Carpenter's
patch fixes a NULL pointer dereference in the probe function's error
path. A patch by me adds the missing can_rx_offload_del() in error
path of the probe function.

Frieder Schrempf contributes a patch for the mcp251x driver, the patch
fixes the resume from sleep before interface was brought up.

The last patch is by me and fixes a race condition in the TX path of
the m_can driver for peripheral (SPI) based m_can cores.

* tag 'linux-can-fixes-for-5.13-20210506' of git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can:
  can: m_can: m_can_tx_work_queue(): fix tx_skb race condition
  can: mcp251x: fix resume from sleep before interface was brought up
  can: mcp251xfd: mcp251xfd_probe(): add missing can_rx_offload_del() in error path
  can: mcp251xfd: mcp251xfd_probe(): fix an error pointer dereference in probe
====================

Link: https://lore.kernel.org/r/20210506074015.1300591-1-mkl@pengutronix.deSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents 86214366 e04b2cfe
......@@ -1562,6 +1562,8 @@ static netdev_tx_t m_can_tx_handler(struct m_can_classdev *cdev)
int i;
int putidx;
cdev->tx_skb = NULL;
/* Generate ID field for TX buffer Element */
/* Common to all supported M_CAN versions */
if (cf->can_id & CAN_EFF_FLAG) {
......@@ -1678,7 +1680,6 @@ static void m_can_tx_work_queue(struct work_struct *ws)
tx_work);
m_can_tx_handler(cdev);
cdev->tx_skb = NULL;
}
static netdev_tx_t m_can_start_xmit(struct sk_buff *skb,
......
......@@ -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);
......@@ -1224,24 +1222,15 @@ 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;
goto out_free_irq;
ret = mcp251x_setup(net, spi);
if (ret)
goto out_free_wq;
goto out_free_irq;
ret = mcp251x_set_normal_mode(spi);
if (ret)
goto out_free_wq;
goto out_free_irq;
can_led_event(net, CAN_LED_EVENT_OPEN);
......@@ -1250,9 +1239,7 @@ static int mcp251x_open(struct net_device *net)
return 0;
out_free_wq:
destroy_workqueue(priv->wq);
out_clean:
out_free_irq:
free_irq(spi->irq, priv);
mcp251x_hw_sleep(spi);
out_close:
......@@ -1373,6 +1360,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);
......@@ -1417,6 +1413,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:
......@@ -1438,6 +1436,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);
......
......@@ -2885,7 +2885,7 @@ static int mcp251xfd_probe(struct spi_device *spi)
clk = devm_clk_get(&spi->dev, NULL);
if (IS_ERR(clk))
dev_err_probe(&spi->dev, PTR_ERR(clk),
return dev_err_probe(&spi->dev, PTR_ERR(clk),
"Failed to get Oscillator (clock)!\n");
freq = clk_get_rate(clk);
......@@ -2986,10 +2986,12 @@ static int mcp251xfd_probe(struct spi_device *spi)
err = mcp251xfd_register(priv);
if (err)
goto out_free_candev;
goto out_can_rx_offload_del;
return 0;
out_can_rx_offload_del:
can_rx_offload_del(&priv->offload);
out_free_candev:
spi->max_speed_hz = priv->spi_max_speed_hz_orig;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment