mirror of https://gitee.com/openkylin/linux.git
linux-can-fixes-for-5.13-20210506
-----BEGIN PGP SIGNATURE----- iQFHBAABCgAxFiEEK3kIWJt9yTYMP3ehqclaivrt76kFAmCTmoITHG1rbEBwZW5n dXRyb25peC5kZQAKCRCpyVqK+u3vqU5PB/9qI41z2PuH+Y3xmR9h5+vV/Nq6TJMg OGyOfqVn10Z7athCsLZEYBtTLot3BxpHLFoAxWDVqXZTSGF6nKEHokJtknUijqBF prnQIgYC7q4fSC01Q4vTjnC04WwNyN28+J6AnWpNLx78rrhjoli7MRtLC0utuSfi i8Kzs1uk/iTP9aN24OtcMT5YhJDqASv6pnHp4hvdT2nQmRZ2EScl4in94dI2kVay 5Sgmh2gXYz+RzayaQOL8b6JIDHSaFjKOWY7ZWLm8ZlWv01EH4pphEqPapKzBCP1M 9e65znoGyLA3bIr7noBo9LuGMhLai5tnJJ2FrGcvG3MZFF7OdmJmz10p =0olA -----END PGP SIGNATURE----- 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.de Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
commit
9f3c3b4235
|
@ -1562,6 +1562,8 @@ static netdev_tx_t m_can_tx_handler(struct m_can_classdev *cdev)
|
||||||
int i;
|
int i;
|
||||||
int putidx;
|
int putidx;
|
||||||
|
|
||||||
|
cdev->tx_skb = NULL;
|
||||||
|
|
||||||
/* Generate ID field for TX buffer Element */
|
/* Generate ID field for TX buffer Element */
|
||||||
/* Common to all supported M_CAN versions */
|
/* Common to all supported M_CAN versions */
|
||||||
if (cf->can_id & CAN_EFF_FLAG) {
|
if (cf->can_id & CAN_EFF_FLAG) {
|
||||||
|
@ -1678,7 +1680,6 @@ static void m_can_tx_work_queue(struct work_struct *ws)
|
||||||
tx_work);
|
tx_work);
|
||||||
|
|
||||||
m_can_tx_handler(cdev);
|
m_can_tx_handler(cdev);
|
||||||
cdev->tx_skb = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static netdev_tx_t m_can_start_xmit(struct sk_buff *skb,
|
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;
|
priv->force_quit = 1;
|
||||||
free_irq(spi->irq, priv);
|
free_irq(spi->irq, priv);
|
||||||
destroy_workqueue(priv->wq);
|
|
||||||
priv->wq = NULL;
|
|
||||||
|
|
||||||
mutex_lock(&priv->mcp_lock);
|
mutex_lock(&priv->mcp_lock);
|
||||||
|
|
||||||
|
@ -1224,24 +1222,15 @@ static int mcp251x_open(struct net_device *net)
|
||||||
goto out_close;
|
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);
|
ret = mcp251x_hw_wake(spi);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out_free_wq;
|
goto out_free_irq;
|
||||||
ret = mcp251x_setup(net, spi);
|
ret = mcp251x_setup(net, spi);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out_free_wq;
|
goto out_free_irq;
|
||||||
ret = mcp251x_set_normal_mode(spi);
|
ret = mcp251x_set_normal_mode(spi);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out_free_wq;
|
goto out_free_irq;
|
||||||
|
|
||||||
can_led_event(net, CAN_LED_EVENT_OPEN);
|
can_led_event(net, CAN_LED_EVENT_OPEN);
|
||||||
|
|
||||||
|
@ -1250,9 +1239,7 @@ static int mcp251x_open(struct net_device *net)
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
out_free_wq:
|
out_free_irq:
|
||||||
destroy_workqueue(priv->wq);
|
|
||||||
out_clean:
|
|
||||||
free_irq(spi->irq, priv);
|
free_irq(spi->irq, priv);
|
||||||
mcp251x_hw_sleep(spi);
|
mcp251x_hw_sleep(spi);
|
||||||
out_close:
|
out_close:
|
||||||
|
@ -1373,6 +1360,15 @@ static int mcp251x_can_probe(struct spi_device *spi)
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out_clk;
|
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;
|
priv->spi = spi;
|
||||||
mutex_init(&priv->mcp_lock);
|
mutex_init(&priv->mcp_lock);
|
||||||
|
|
||||||
|
@ -1417,6 +1413,8 @@ static int mcp251x_can_probe(struct spi_device *spi)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
error_probe:
|
error_probe:
|
||||||
|
destroy_workqueue(priv->wq);
|
||||||
|
priv->wq = NULL;
|
||||||
mcp251x_power_enable(priv->power, 0);
|
mcp251x_power_enable(priv->power, 0);
|
||||||
|
|
||||||
out_clk:
|
out_clk:
|
||||||
|
@ -1438,6 +1436,9 @@ static int mcp251x_can_remove(struct spi_device *spi)
|
||||||
|
|
||||||
mcp251x_power_enable(priv->power, 0);
|
mcp251x_power_enable(priv->power, 0);
|
||||||
|
|
||||||
|
destroy_workqueue(priv->wq);
|
||||||
|
priv->wq = NULL;
|
||||||
|
|
||||||
clk_disable_unprepare(priv->clk);
|
clk_disable_unprepare(priv->clk);
|
||||||
|
|
||||||
free_candev(net);
|
free_candev(net);
|
||||||
|
|
|
@ -2885,8 +2885,8 @@ static int mcp251xfd_probe(struct spi_device *spi)
|
||||||
|
|
||||||
clk = devm_clk_get(&spi->dev, NULL);
|
clk = devm_clk_get(&spi->dev, NULL);
|
||||||
if (IS_ERR(clk))
|
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");
|
"Failed to get Oscillator (clock)!\n");
|
||||||
freq = clk_get_rate(clk);
|
freq = clk_get_rate(clk);
|
||||||
|
|
||||||
/* Sanity check */
|
/* Sanity check */
|
||||||
|
@ -2986,10 +2986,12 @@ static int mcp251xfd_probe(struct spi_device *spi)
|
||||||
|
|
||||||
err = mcp251xfd_register(priv);
|
err = mcp251xfd_register(priv);
|
||||||
if (err)
|
if (err)
|
||||||
goto out_free_candev;
|
goto out_can_rx_offload_del;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
out_can_rx_offload_del:
|
||||||
|
can_rx_offload_del(&priv->offload);
|
||||||
out_free_candev:
|
out_free_candev:
|
||||||
spi->max_speed_hz = priv->spi_max_speed_hz_orig;
|
spi->max_speed_hz = priv->spi_max_speed_hz_orig;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue