]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
wifi: libertas: use USB anchors for tracking in-flight URBs
authorHeitor Alves de Siqueira <halves@igalia.com>
Fri, 13 Mar 2026 21:27:57 +0000 (18:27 -0300)
committerJohannes Berg <johannes.berg@intel.com>
Thu, 19 Mar 2026 08:07:55 +0000 (09:07 +0100)
The libertas driver currently handles URB lifecycles manually, which
makes it non-trivial to check if specific URBs are pending or not. Add
anchors for TX/RX URBs, and use those to track in-flight requests.

Signed-off-by: Heitor Alves de Siqueira <halves@igalia.com>
Link: https://patch.msgid.link/20260313-libertas-usb-anchors-v1-1-915afbe988d7@igalia.com
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
drivers/net/wireless/marvell/libertas/if_usb.c
drivers/net/wireless/marvell/libertas/if_usb.h

index 05fcf9cc28fa92076057c9b92c7e1b728716fa36..71fa38ef2c966dc30759a27d7631d0e06fd16511 100644 (file)
@@ -114,8 +114,8 @@ static void if_usb_write_bulk_callback(struct urb *urb)
 static void if_usb_free(struct if_usb_card *cardp)
 {
        /* Unlink tx & rx urb */
-       usb_kill_urb(cardp->tx_urb);
-       usb_kill_urb(cardp->rx_urb);
+       usb_kill_anchored_urbs(&cardp->tx_submitted);
+       usb_kill_anchored_urbs(&cardp->rx_submitted);
 
        usb_free_urb(cardp->tx_urb);
        cardp->tx_urb = NULL;
@@ -221,6 +221,9 @@ static int if_usb_probe(struct usb_interface *intf,
                     udev->descriptor.bDeviceSubClass,
                     udev->descriptor.bDeviceProtocol);
 
+       init_usb_anchor(&cardp->rx_submitted);
+       init_usb_anchor(&cardp->tx_submitted);
+
        for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
                endpoint = &iface_desc->endpoint[i].desc;
                if (usb_endpoint_is_bulk_in(endpoint)) {
@@ -423,7 +426,7 @@ static int usb_tx_block(struct if_usb_card *cardp, uint8_t *payload, uint16_t nb
                goto tx_ret;
        }
 
-       usb_kill_urb(cardp->tx_urb);
+       usb_kill_anchored_urbs(&cardp->tx_submitted);
 
        usb_fill_bulk_urb(cardp->tx_urb, cardp->udev,
                          usb_sndbulkpipe(cardp->udev,
@@ -432,8 +435,10 @@ static int usb_tx_block(struct if_usb_card *cardp, uint8_t *payload, uint16_t nb
 
        cardp->tx_urb->transfer_flags |= URB_ZERO_PACKET;
 
+       usb_anchor_urb(cardp->tx_urb, &cardp->tx_submitted);
        if ((ret = usb_submit_urb(cardp->tx_urb, GFP_ATOMIC))) {
                lbs_deb_usbd(&cardp->udev->dev, "usb_submit_urb failed: %d\n", ret);
+               usb_unanchor_urb(cardp->tx_urb);
        } else {
                lbs_deb_usb2(&cardp->udev->dev, "usb_submit_urb success\n");
                ret = 0;
@@ -464,8 +469,10 @@ static int __if_usb_submit_rx_urb(struct if_usb_card *cardp,
                          cardp);
 
        lbs_deb_usb2(&cardp->udev->dev, "Pointer for rx_urb %p\n", cardp->rx_urb);
+       usb_anchor_urb(cardp->rx_urb, &cardp->rx_submitted);
        if ((ret = usb_submit_urb(cardp->rx_urb, GFP_ATOMIC))) {
                lbs_deb_usbd(&cardp->udev->dev, "Submit Rx URB failed: %d\n", ret);
+               usb_unanchor_urb(cardp->rx_urb);
                kfree_skb(skb);
                cardp->rx_skb = NULL;
                ret = -1;
@@ -835,8 +842,8 @@ static void if_usb_prog_firmware(struct lbs_private *priv, int ret,
        }
 
        /* Cancel any pending usb business */
-       usb_kill_urb(cardp->rx_urb);
-       usb_kill_urb(cardp->tx_urb);
+       usb_kill_anchored_urbs(&cardp->rx_submitted);
+       usb_kill_anchored_urbs(&cardp->tx_submitted);
 
        cardp->fwlastblksent = 0;
        cardp->fwdnldover = 0;
@@ -866,8 +873,8 @@ restart:
        if (cardp->bootcmdresp == BOOT_CMD_RESP_NOT_SUPPORTED) {
                /* Return to normal operation */
                ret = -EOPNOTSUPP;
-               usb_kill_urb(cardp->rx_urb);
-               usb_kill_urb(cardp->tx_urb);
+               usb_kill_anchored_urbs(&cardp->rx_submitted);
+               usb_kill_anchored_urbs(&cardp->tx_submitted);
                if (if_usb_submit_rx_urb(cardp) < 0)
                        ret = -EIO;
                goto done;
@@ -897,7 +904,7 @@ restart:
        wait_event_interruptible(cardp->fw_wq, cardp->surprise_removed || cardp->fwdnldover);
 
        timer_delete_sync(&cardp->fw_timeout);
-       usb_kill_urb(cardp->rx_urb);
+       usb_kill_anchored_urbs(&cardp->rx_submitted);
 
        if (!cardp->fwdnldover) {
                pr_info("failed to load fw, resetting device!\n");
@@ -957,8 +964,8 @@ static int if_usb_suspend(struct usb_interface *intf, pm_message_t message)
                goto out;
 
        /* Unlink tx & rx urb */
-       usb_kill_urb(cardp->tx_urb);
-       usb_kill_urb(cardp->rx_urb);
+       usb_kill_anchored_urbs(&cardp->tx_submitted);
+       usb_kill_anchored_urbs(&cardp->rx_submitted);
 
  out:
        return ret;
index 7d0daeb33c3f7735aa6a5f8ff3a95f49c4c331f6..a0cd36197c2b0bc9debd8fb43fe93ef8975e536c 100644 (file)
@@ -48,6 +48,9 @@ struct if_usb_card {
        struct urb *rx_urb, *tx_urb;
        struct lbs_private *priv;
 
+       struct usb_anchor rx_submitted;
+       struct usb_anchor tx_submitted;
+
        struct sk_buff *rx_skb;
 
        uint8_t ep_in;