aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorChristian Lamparter <chunkeey@web.de>2009-07-06 09:17:56 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-07-10 15:02:30 -0400
commit6d541a684d7eb72c71eaba82b09a360c96609134 (patch)
tree7f96d9eae6ad0aa232678e576248744f98804220 /drivers
parent1be491fca12ff599c37ceaf7e9042ebee9f0068e (diff)
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>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/wireless/p54/p54usb.c36
1 files changed, 17 insertions, 19 deletions
diff --git a/drivers/net/wireless/p54/p54usb.c b/drivers/net/wireless/p54/p54usb.c
index 461d88f5ceb7..e44460ff149c 100644
--- a/drivers/net/wireless/p54/p54usb.c
+++ b/drivers/net/wireless/p54/p54usb.c
@@ -246,8 +246,10 @@ static void p54u_tx_lm87(struct ieee80211_hw *dev, struct sk_buff *skb)
246 struct lm87_tx_hdr *hdr = (void *)skb->data - sizeof(*hdr); 246 struct lm87_tx_hdr *hdr = (void *)skb->data - sizeof(*hdr);
247 247
248 data_urb = usb_alloc_urb(0, GFP_ATOMIC); 248 data_urb = usb_alloc_urb(0, GFP_ATOMIC);
249 if (!data_urb) 249 if (!data_urb) {
250 p54_free_skb(dev, skb);
250 return; 251 return;
252 }
251 253
252 hdr->chksum = p54u_lm87_chksum((__le32 *)skb->data, skb->len); 254 hdr->chksum = p54u_lm87_chksum((__le32 *)skb->data, skb->len);
253 hdr->device_addr = ((struct p54_hdr *)skb->data)->req_id; 255 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)
269static void p54u_tx_net2280(struct ieee80211_hw *dev, struct sk_buff *skb) 271static void p54u_tx_net2280(struct ieee80211_hw *dev, struct sk_buff *skb)
270{ 272{
271 struct p54u_priv *priv = dev->priv; 273 struct p54u_priv *priv = dev->priv;
272 struct urb *int_urb, *data_urb; 274 struct urb *int_urb = NULL, *data_urb = NULL;
273 struct net2280_tx_hdr *hdr = (void *)skb->data - sizeof(*hdr); 275 struct net2280_tx_hdr *hdr = (void *)skb->data - sizeof(*hdr);
274 struct net2280_reg_write *reg; 276 struct net2280_reg_write *reg = NULL;
275 int err = 0; 277 int err = -ENOMEM;
276 278
277 reg = kmalloc(sizeof(*reg), GFP_ATOMIC); 279 reg = kmalloc(sizeof(*reg), GFP_ATOMIC);
278 if (!reg) 280 if (!reg)
279 return; 281 goto out;
280 282
281 int_urb = usb_alloc_urb(0, GFP_ATOMIC); 283 int_urb = usb_alloc_urb(0, GFP_ATOMIC);
282 if (!int_urb) { 284 if (!int_urb)
283 kfree(reg); 285 goto out;
284 return;
285 }
286 286
287 data_urb = usb_alloc_urb(0, GFP_ATOMIC); 287 data_urb = usb_alloc_urb(0, GFP_ATOMIC);
288 if (!data_urb) { 288 if (!data_urb)
289 kfree(reg); 289 goto out;
290 usb_free_urb(int_urb);
291 return;
292 }
293 290
294 reg->port = cpu_to_le16(NET2280_DEV_U32); 291 reg->port = cpu_to_le16(NET2280_DEV_U32);
295 reg->addr = cpu_to_le32(P54U_DEV_BASE); 292 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 p54u_tx_dummy_cb, dev); 301 p54u_tx_dummy_cb, dev);
305 302
306 /* 303 /*
307 * This flag triggers a code path in the USB subsystem that will 304 * URB_FREE_BUFFER triggers a code path in the USB subsystem that will
308 * free what's inside the transfer_buffer after the callback routine 305 * free what is inside the transfer_buffer after the last reference to
309 * has completed. 306 * the int_urb is dropped.
310 */ 307 */
311 int_urb->transfer_flags |= URB_FREE_BUFFER | URB_ZERO_PACKET; 308 int_urb->transfer_flags |= URB_FREE_BUFFER | URB_ZERO_PACKET;
309 reg = NULL;
312 310
313 usb_fill_bulk_urb(data_urb, priv->udev, 311 usb_fill_bulk_urb(data_urb, priv->udev,
314 usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA), 312 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 usb_unanchor_urb(data_urb); 327 usb_unanchor_urb(data_urb);
330 goto out; 328 goto out;
331 } 329 }
332 out: 330out:
333 usb_free_urb(int_urb); 331 usb_free_urb(int_urb);
334 usb_free_urb(data_urb); 332 usb_free_urb(data_urb);
335 333
336 if (err) { 334 if (err) {
337 skb_pull(skb, sizeof(*hdr)); 335 kfree(reg);
338 p54_free_skb(dev, skb); 336 p54_free_skb(dev, skb);
339 } 337 }
340} 338}