[PATCH 1/2] wifi: libertas: use USB anchors for tracking in-flight URBs
From: Heitor Alves de Siqueira
Date: Fri Mar 13 2026 - 17:30:14 EST
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@xxxxxxxxxx>
---
drivers/net/wireless/marvell/libertas/if_usb.c | 27 ++++++++++++++++----------
drivers/net/wireless/marvell/libertas/if_usb.h | 3 +++
2 files changed, 20 insertions(+), 10 deletions(-)
diff --git a/drivers/net/wireless/marvell/libertas/if_usb.c b/drivers/net/wireless/marvell/libertas/if_usb.c
index 8a6bf1365cfa..11cd1422f46a 100644
--- a/drivers/net/wireless/marvell/libertas/if_usb.c
+++ b/drivers/net/wireless/marvell/libertas/if_usb.c
@@ -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)) {
@@ -426,7 +429,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,
@@ -435,8 +438,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;
@@ -467,8 +472,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;
@@ -838,8 +845,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;
@@ -869,8 +876,8 @@ static void if_usb_prog_firmware(struct lbs_private *priv, int ret,
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;
@@ -900,7 +907,7 @@ static void if_usb_prog_firmware(struct lbs_private *priv, int ret,
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");
@@ -960,8 +967,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;
diff --git a/drivers/net/wireless/marvell/libertas/if_usb.h b/drivers/net/wireless/marvell/libertas/if_usb.h
index 7d0daeb33c3f..a0cd36197c2b 100644
--- a/drivers/net/wireless/marvell/libertas/if_usb.h
+++ b/drivers/net/wireless/marvell/libertas/if_usb.h
@@ -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;
--
2.53.0