| From 10d4018f3e04e68c381ee8055337dfd50697411c Mon Sep 17 00:00:00 2001 |
| From: Weitao Hou <houweitaoo@gmail.com> |
| Date: Tue, 25 Jun 2019 20:50:48 +0800 |
| Subject: can: mcp251x: add error check when wq alloc failed |
| |
| [ Upstream commit 375f755899b8fc21196197e02aab26257df26e85 ] |
| |
| add error check when workqueue alloc failed, and remove redundant code |
| to make it clear. |
| |
| Fixes: e0000163e30e ("can: Driver for the Microchip MCP251x SPI CAN controllers") |
| Signed-off-by: Weitao Hou <houweitaoo@gmail.com> |
| Acked-by: Willem de Bruijn <willemb@google.com> |
| Tested-by: Sean Nyekjaer <sean@geanix.com> |
| Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| drivers/net/can/spi/mcp251x.c | 49 ++++++++++++++++------------------- |
| 1 file changed, 22 insertions(+), 27 deletions(-) |
| |
| diff --git a/drivers/net/can/spi/mcp251x.c b/drivers/net/can/spi/mcp251x.c |
| index da64e71a62ee2..fccb6bf21fada 100644 |
| --- a/drivers/net/can/spi/mcp251x.c |
| +++ b/drivers/net/can/spi/mcp251x.c |
| @@ -678,17 +678,6 @@ static int mcp251x_power_enable(struct regulator *reg, int enable) |
| return regulator_disable(reg); |
| } |
| |
| -static void mcp251x_open_clean(struct net_device *net) |
| -{ |
| - struct mcp251x_priv *priv = netdev_priv(net); |
| - struct spi_device *spi = priv->spi; |
| - |
| - free_irq(spi->irq, priv); |
| - mcp251x_hw_sleep(spi); |
| - mcp251x_power_enable(priv->transceiver, 0); |
| - close_candev(net); |
| -} |
| - |
| static int mcp251x_stop(struct net_device *net) |
| { |
| struct mcp251x_priv *priv = netdev_priv(net); |
| @@ -954,37 +943,43 @@ static int mcp251x_open(struct net_device *net) |
| flags | IRQF_ONESHOT, DEVICE_NAME, priv); |
| if (ret) { |
| dev_err(&spi->dev, "failed to acquire irq %d\n", spi->irq); |
| - mcp251x_power_enable(priv->transceiver, 0); |
| - close_candev(net); |
| - goto open_unlock; |
| + 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_reset(spi); |
| - if (ret) { |
| - mcp251x_open_clean(net); |
| - goto open_unlock; |
| - } |
| + if (ret) |
| + goto out_free_wq; |
| ret = mcp251x_setup(net, spi); |
| - if (ret) { |
| - mcp251x_open_clean(net); |
| - goto open_unlock; |
| - } |
| + if (ret) |
| + goto out_free_wq; |
| ret = mcp251x_set_normal_mode(spi); |
| - if (ret) { |
| - mcp251x_open_clean(net); |
| - goto open_unlock; |
| - } |
| + if (ret) |
| + goto out_free_wq; |
| |
| can_led_event(net, CAN_LED_EVENT_OPEN); |
| |
| netif_wake_queue(net); |
| + mutex_unlock(&priv->mcp_lock); |
| |
| -open_unlock: |
| + return 0; |
| + |
| +out_free_wq: |
| + destroy_workqueue(priv->wq); |
| +out_clean: |
| + free_irq(spi->irq, priv); |
| + mcp251x_hw_sleep(spi); |
| +out_close: |
| + mcp251x_power_enable(priv->transceiver, 0); |
| + close_candev(net); |
| mutex_unlock(&priv->mcp_lock); |
| return ret; |
| } |
| -- |
| 2.20.1 |
| |