diff options
author | Marc Kleine-Budde <mkl@pengutronix.de> | 2022-09-20 12:40:56 +0300 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2022-09-28 12:02:56 +0300 |
commit | 71d9e0874c6bd577ac29fbd515515f54048932f7 (patch) | |
tree | fe133d80db7bc55eefb6e20962b83157cb3a0d0b | |
parent | 1e98318af2f163eadaff815abcef38d27ca92c1e (diff) | |
download | linux-71d9e0874c6bd577ac29fbd515515f54048932f7.tar.xz |
can: gs_usb: gs_can_open(): fix race dev->can.state condition
[ Upstream commit 5440428b3da65408dba0241985acb7a05258b85e ]
The dev->can.state is set to CAN_STATE_ERROR_ACTIVE, after the device
has been started. On busy networks the CAN controller might receive
CAN frame between and go into an error state before the dev->can.state
is assigned.
Assign dev->can.state before starting the controller to close the race
window.
Fixes: d08e973a77d1 ("can: gs_usb: Added support for the GS_USB CAN devices")
Link: https://lore.kernel.org/all/20220920195216.232481-1-mkl@pengutronix.de
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
Signed-off-by: Sasha Levin <sashal@kernel.org>
-rw-r--r-- | drivers/net/can/usb/gs_usb.c | 4 |
1 files changed, 2 insertions, 2 deletions
diff --git a/drivers/net/can/usb/gs_usb.c b/drivers/net/can/usb/gs_usb.c index 2101b2fab7df..62ca4964a863 100644 --- a/drivers/net/can/usb/gs_usb.c +++ b/drivers/net/can/usb/gs_usb.c @@ -686,6 +686,7 @@ static int gs_can_open(struct net_device *netdev) flags |= GS_CAN_MODE_TRIPLE_SAMPLE; /* finally start device */ + dev->can.state = CAN_STATE_ERROR_ACTIVE; dm->mode = cpu_to_le32(GS_CAN_MODE_START); dm->flags = cpu_to_le32(flags); rc = usb_control_msg(interface_to_usbdev(dev->iface), @@ -702,13 +703,12 @@ static int gs_can_open(struct net_device *netdev) if (rc < 0) { netdev_err(netdev, "Couldn't start device (err=%d)\n", rc); kfree(dm); + dev->can.state = CAN_STATE_STOPPED; return rc; } kfree(dm); - dev->can.state = CAN_STATE_ERROR_ACTIVE; - parent->active_channels++; if (!(dev->can.ctrlmode & CAN_CTRLMODE_LISTENONLY)) netif_start_queue(netdev); |