wifi: libertas: use USB anchors for tracking in-flight URBs

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>
This commit is contained in:
Heitor Alves de Siqueira
2026-03-13 18:27:57 -03:00
committed by Johannes Berg
parent f10ebd136d
commit a57f35fc19
2 changed files with 20 additions and 10 deletions

View 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 @@ 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;
@@ -897,7 +904,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");
@@ -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;

View 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;