Commit 6d541a68 authored by Christian Lamparter's avatar Christian Lamparter Committed by John W. Linville

p54usb: fix stalls caused by urb allocation failures

This patch squashes a few old bugs, which have been around since
the initial version of p54usb in one form or another.

we never freed a orphaned frame, when were denied the resources,
which are necessary to pass the data into the usb subsystem.
As a result we could end up with a full queue that wasn't emptied,
until the device was brought down.
Signed-off-by: default avatarChristian Lamparter <chunkeey@web.de>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 1be491fc
...@@ -246,8 +246,10 @@ static void p54u_tx_lm87(struct ieee80211_hw *dev, struct sk_buff *skb) ...@@ -246,8 +246,10 @@ static void p54u_tx_lm87(struct ieee80211_hw *dev, struct sk_buff *skb)
struct lm87_tx_hdr *hdr = (void *)skb->data - sizeof(*hdr); struct lm87_tx_hdr *hdr = (void *)skb->data - sizeof(*hdr);
data_urb = usb_alloc_urb(0, GFP_ATOMIC); data_urb = usb_alloc_urb(0, GFP_ATOMIC);
if (!data_urb) if (!data_urb) {
p54_free_skb(dev, skb);
return; return;
}
hdr->chksum = p54u_lm87_chksum((__le32 *)skb->data, skb->len); hdr->chksum = p54u_lm87_chksum((__le32 *)skb->data, skb->len);
hdr->device_addr = ((struct p54_hdr *)skb->data)->req_id; hdr->device_addr = ((struct p54_hdr *)skb->data)->req_id;
...@@ -269,27 +271,22 @@ static void p54u_tx_lm87(struct ieee80211_hw *dev, struct sk_buff *skb) ...@@ -269,27 +271,22 @@ static void p54u_tx_lm87(struct ieee80211_hw *dev, struct sk_buff *skb)
static void p54u_tx_net2280(struct ieee80211_hw *dev, struct sk_buff *skb) static void p54u_tx_net2280(struct ieee80211_hw *dev, struct sk_buff *skb)
{ {
struct p54u_priv *priv = dev->priv; struct p54u_priv *priv = dev->priv;
struct urb *int_urb, *data_urb; struct urb *int_urb = NULL, *data_urb = NULL;
struct net2280_tx_hdr *hdr = (void *)skb->data - sizeof(*hdr); struct net2280_tx_hdr *hdr = (void *)skb->data - sizeof(*hdr);
struct net2280_reg_write *reg; struct net2280_reg_write *reg = NULL;
int err = 0; int err = -ENOMEM;
reg = kmalloc(sizeof(*reg), GFP_ATOMIC); reg = kmalloc(sizeof(*reg), GFP_ATOMIC);
if (!reg) if (!reg)
return; goto out;
int_urb = usb_alloc_urb(0, GFP_ATOMIC); int_urb = usb_alloc_urb(0, GFP_ATOMIC);
if (!int_urb) { if (!int_urb)
kfree(reg); goto out;
return;
}
data_urb = usb_alloc_urb(0, GFP_ATOMIC); data_urb = usb_alloc_urb(0, GFP_ATOMIC);
if (!data_urb) { if (!data_urb)
kfree(reg); goto out;
usb_free_urb(int_urb);
return;
}
reg->port = cpu_to_le16(NET2280_DEV_U32); reg->port = cpu_to_le16(NET2280_DEV_U32);
reg->addr = cpu_to_le32(P54U_DEV_BASE); reg->addr = cpu_to_le32(P54U_DEV_BASE);
...@@ -304,11 +301,12 @@ static void p54u_tx_net2280(struct ieee80211_hw *dev, struct sk_buff *skb) ...@@ -304,11 +301,12 @@ static void p54u_tx_net2280(struct ieee80211_hw *dev, struct sk_buff *skb)
p54u_tx_dummy_cb, dev); p54u_tx_dummy_cb, dev);
/* /*
* This flag triggers a code path in the USB subsystem that will * URB_FREE_BUFFER triggers a code path in the USB subsystem that will
* free what's inside the transfer_buffer after the callback routine * free what is inside the transfer_buffer after the last reference to
* has completed. * the int_urb is dropped.
*/ */
int_urb->transfer_flags |= URB_FREE_BUFFER | URB_ZERO_PACKET; int_urb->transfer_flags |= URB_FREE_BUFFER | URB_ZERO_PACKET;
reg = NULL;
usb_fill_bulk_urb(data_urb, priv->udev, usb_fill_bulk_urb(data_urb, priv->udev,
usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA), usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA),
...@@ -329,12 +327,12 @@ static void p54u_tx_net2280(struct ieee80211_hw *dev, struct sk_buff *skb) ...@@ -329,12 +327,12 @@ static void p54u_tx_net2280(struct ieee80211_hw *dev, struct sk_buff *skb)
usb_unanchor_urb(data_urb); usb_unanchor_urb(data_urb);
goto out; goto out;
} }
out: out:
usb_free_urb(int_urb); usb_free_urb(int_urb);
usb_free_urb(data_urb); usb_free_urb(data_urb);
if (err) { if (err) {
skb_pull(skb, sizeof(*hdr)); kfree(reg);
p54_free_skb(dev, skb); p54_free_skb(dev, skb);
} }
} }
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment