mirror of
https://github.com/torvalds/linux.git
synced 2024-11-08 05:01:48 +00:00
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: Christian Lamparter <chunkeey@web.de> Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
parent
1be491fca1
commit
6d541a684d
@ -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)
|
|||||||
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)
|
|||||||
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),
|
||||||
@ -334,7 +332,7 @@ static void p54u_tx_net2280(struct ieee80211_hw *dev, struct sk_buff *skb)
|
|||||||
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user