aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/can/usb/gs_usb.c
diff options
context:
space:
mode:
authorMarc Kleine-Budde <mkl@pengutronix.de>2022-09-20 11:46:12 +0200
committerMarc Kleine-Budde <mkl@pengutronix.de>2022-09-23 13:55:00 +0200
commit103108cb9673814a1f73522dacc79ad28cfc0271 (patch)
treee9446035f1290b9e5d61d69ba88ae82a6eed60ad /drivers/net/can/usb/gs_usb.c
parentcan: gs_usb: add missing lock to protect struct timecounter::cycle_last (diff)
downloadlinux-dev-103108cb9673814a1f73522dacc79ad28cfc0271.tar.xz
linux-dev-103108cb9673814a1f73522dacc79ad28cfc0271.zip
can: gs_usb: gs_can_open(): initialize time counter before starting device
On busy networks the CAN controller might receive CAN frames directly after starting it but before the timecounter is setup. This will lead to NULL pointer deref while converting the converting the CAN frame's timestamp with the timecounter. Close the race window by setting up the timecounter before starting the CAN controller. Fixes: 45dfa45f52e6 ("can: gs_usb: add RX and TX hardware timestamp support") Link: https://lore.kernel.org/all/20220921081329.385509-1-mkl@pengutronix.de Cc: John Whittington <git@jbrengineering.co.uk Tested-by: John Whittington <git@jbrengineering.co.uk> Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
Diffstat (limited to '')
-rw-r--r--drivers/net/can/usb/gs_usb.c10
1 files changed, 6 insertions, 4 deletions
diff --git a/drivers/net/can/usb/gs_usb.c b/drivers/net/can/usb/gs_usb.c
index 9a8a7f1b2002..aa619dfc3ff2 100644
--- a/drivers/net/can/usb/gs_usb.c
+++ b/drivers/net/can/usb/gs_usb.c
@@ -972,6 +972,10 @@ static int gs_can_open(struct net_device *netdev)
if (dev->feature & GS_CAN_FEATURE_HW_TIMESTAMP)
flags |= GS_CAN_MODE_HW_TIMESTAMP;
+ /* start polling timestamp */
+ if (dev->feature & GS_CAN_FEATURE_HW_TIMESTAMP)
+ gs_usb_timestamp_init(dev);
+
/* finally start device */
dev->can.state = CAN_STATE_ERROR_ACTIVE;
dm->mode = cpu_to_le32(GS_CAN_MODE_START);
@@ -985,16 +989,14 @@ 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);
+ if (dev->feature & GS_CAN_FEATURE_HW_TIMESTAMP)
+ gs_usb_timestamp_stop(dev);
dev->can.state = CAN_STATE_STOPPED;
return rc;
}
kfree(dm);
- /* start polling timestamp */
- if (dev->feature & GS_CAN_FEATURE_HW_TIMESTAMP)
- gs_usb_timestamp_init(dev);
-
parent->active_channels++;
if (!(dev->can.ctrlmode & CAN_CTRLMODE_LISTENONLY))
netif_start_queue(netdev);