• Marc Kleine-Budde's avatar
    can: gs_usb: fix time stamp counter initialization · 5886e4d5
    Marc Kleine-Budde authored
    If the gs_usb device driver is unloaded (or unbound) before the
    interface is shut down, the USB stack first calls the struct
    usb_driver::disconnect and then the struct net_device_ops::ndo_stop
    callback.
    
    In gs_usb_disconnect() all pending bulk URBs are killed, i.e. no more
    RX'ed CAN frames are send from the USB device to the host. Later in
    gs_can_close() a reset control message is send to each CAN channel to
    remove the controller from the CAN bus. In this race window the USB
    device can still receive CAN frames from the bus and internally queue
    them to be send to the host.
    
    At least in the current version of the candlelight firmware, the queue
    of received CAN frames is not emptied during the reset command. After
    loading (or binding) the gs_usb driver, new URBs are submitted during
    the struct net_device_ops::ndo_open callback and the candlelight
    firmware starts sending its already queued CAN frames to the host.
    
    However, this scenario was not considered when implementing the
    hardware timestamp function. The cycle counter/time counter
    infrastructure is set up (gs_usb_timestamp_init()) after the USBs are
    submitted, resulting in a NULL pointer dereference if
    timecounter_cyc2time() (via the call chain:
    gs_usb_receive_bulk_callback() -> gs_usb_set_timestamp() ->
    gs_usb_skb_set_timestamp()) is called too early.
    
    Move the gs_usb_timestamp_init() function before the URBs are
    submitted to fix this problem.
    
    For a comprehensive solution, we need to consider gs_usb devices with
    more than 1 channel. The cycle counter/time counter infrastructure is
    setup per channel, but the RX URBs are per device. Once gs_can_open()
    of _a_ channel has been called, and URBs have been submitted, the
    gs_usb_receive_bulk_callback() can be called for _all_ available
    channels, even for channels that are not running, yet. As cycle
    counter/time counter has not set up, this will again lead to a NULL
    pointer dereference.
    
    Convert the cycle counter/time counter from a "per channel" to a "per
    device" functionality. Also set it up, before submitting any URBs to
    the device.
    
    Further in gs_usb_receive_bulk_callback(), don't process any URBs for
    not started CAN channels, only resubmit the URB.
    
    Fixes: 45dfa45f ("can: gs_usb: add RX and TX hardware timestamp support")
    Closes: https://github.com/candle-usb/candleLight_fw/issues/137#issuecomment-1623532076
    Cc: stable@vger.kernel.org
    Cc: John Whittington <git@jbrengineering.co.uk>
    Link: https://lore.kernel.org/all/20230716-gs_usb-fix-time-stamp-counter-v1-2-9017cefcd9d5@pengutronix.deSigned-off-by: default avatarMarc Kleine-Budde <mkl@pengutronix.de>
    5886e4d5
gs_usb.c 38.8 KB