summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaolo Abeni <pabeni@redhat.com>2026-06-09 16:23:15 +0300
committerPaolo Abeni <pabeni@redhat.com>2026-06-09 16:23:15 +0300
commit0aa05daef7848a5ac11158949dc73cd741995dc1 (patch)
treef43b5a45703e3216ad34832b6bba3654ab32bb31
parent004e9ecfe6c5384f9e0b2f6f6389d42ec22789af (diff)
parent881a3113b74964918cdd72747e3bc119c02b0c0c (diff)
downloadlinux-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.c28
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;