diff options
| author | Paolo Abeni <pabeni@redhat.com> | 2026-06-09 16:23:15 +0300 |
|---|---|---|
| committer | Paolo Abeni <pabeni@redhat.com> | 2026-06-09 16:23:15 +0300 |
| commit | 0aa05daef7848a5ac11158949dc73cd741995dc1 (patch) | |
| tree | f43b5a45703e3216ad34832b6bba3654ab32bb31 | |
| parent | 004e9ecfe6c5384f9e0b2f6f6389d42ec22789af (diff) | |
| parent | 881a3113b74964918cdd72747e3bc119c02b0c0c (diff) | |
| download | linux-0aa05daef7848a5ac11158949dc73cd741995dc1.tar.xz | |
Merge branch 'net-mctp-usb-minor-fixes-for-mctp-over-usb-transport-driver'
Jeremy Kerr says:
====================
net: mctp: usb: minor fixes for MCTP over USB transport driver
This series adds a couple of fixes in the ndo_open / ndo_stop path for
the MCTP over USB transport, where we are incorrectly sequencing two
error cases.
Signed-off-by: Jeremy Kerr <jk@codeconstruct.com.au>
====================
Link: https://patch.msgid.link/20260608-dev-mctp-usb-rx-requeue-v2-0-29a3aa507609@codeconstruct.com.au
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
| -rw-r--r-- | drivers/net/mctp/mctp-usb.c | 28 |
1 files changed, 18 insertions, 10 deletions
diff --git a/drivers/net/mctp/mctp-usb.c b/drivers/net/mctp/mctp-usb.c index 3b5dff144177..fade65f2f269 100644 --- a/drivers/net/mctp/mctp-usb.c +++ b/drivers/net/mctp/mctp-usb.c @@ -22,7 +22,6 @@ struct mctp_usb { struct usb_device *usbdev; struct usb_interface *intf; - bool stopped; struct net_device *netdev; @@ -32,6 +31,9 @@ struct mctp_usb { struct urb *tx_urb; struct urb *rx_urb; + /* enforces atomic access to rx_stopped and requeuing the retry work */ + spinlock_t rx_lock; + bool rx_stopped; struct delayed_work rx_retry_work; }; @@ -122,6 +124,7 @@ static const unsigned long RX_RETRY_DELAY = HZ / 4; static int mctp_usb_rx_queue(struct mctp_usb *mctp_usb, gfp_t gfp) { + unsigned long flags; struct sk_buff *skb; int rc; @@ -147,8 +150,11 @@ static int mctp_usb_rx_queue(struct mctp_usb *mctp_usb, gfp_t gfp) return rc; err_retry: - schedule_delayed_work(&mctp_usb->rx_retry_work, RX_RETRY_DELAY); - return rc; + spin_lock_irqsave(&mctp_usb->rx_lock, flags); + if (!mctp_usb->rx_stopped) + schedule_delayed_work(&mctp_usb->rx_retry_work, RX_RETRY_DELAY); + spin_unlock_irqrestore(&mctp_usb->rx_lock, flags); + return 0; } static void mctp_usb_in_complete(struct urb *urb) @@ -248,9 +254,6 @@ static void mctp_usb_rx_retry_work(struct work_struct *work) struct mctp_usb *mctp_usb = container_of(work, struct mctp_usb, rx_retry_work.work); - if (READ_ONCE(mctp_usb->stopped)) - return; - mctp_usb_rx_queue(mctp_usb, GFP_KERNEL); } @@ -258,7 +261,7 @@ static int mctp_usb_open(struct net_device *dev) { struct mctp_usb *mctp_usb = netdev_priv(dev); - WRITE_ONCE(mctp_usb->stopped, false); + WRITE_ONCE(mctp_usb->rx_stopped, false); netif_start_queue(dev); @@ -268,17 +271,21 @@ static int mctp_usb_open(struct net_device *dev) static int mctp_usb_stop(struct net_device *dev) { struct mctp_usb *mctp_usb = netdev_priv(dev); + unsigned long flags; netif_stop_queue(dev); /* prevent RX submission retry */ - WRITE_ONCE(mctp_usb->stopped, true); + spin_lock_irqsave(&mctp_usb->rx_lock, flags); + mctp_usb->rx_stopped = true; + cancel_delayed_work(&mctp_usb->rx_retry_work); + spin_unlock_irqrestore(&mctp_usb->rx_lock, flags); + + flush_delayed_work(&mctp_usb->rx_retry_work); usb_kill_urb(mctp_usb->rx_urb); usb_kill_urb(mctp_usb->tx_urb); - cancel_delayed_work_sync(&mctp_usb->rx_retry_work); - return 0; } @@ -331,6 +338,7 @@ static int mctp_usb_probe(struct usb_interface *intf, dev->netdev = netdev; dev->usbdev = interface_to_usbdev(intf); dev->intf = intf; + spin_lock_init(&dev->rx_lock); usb_set_intfdata(intf, dev); dev->ep_in = ep_in->bEndpointAddress; |
