diff options
Diffstat (limited to 'drivers/net/wireless/brcm80211/brcmfmac/usb.c')
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/usb.c | 27 |
1 files changed, 19 insertions, 8 deletions
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/usb.c b/drivers/net/wireless/brcm80211/brcmfmac/usb.c index 914c56fe6c5f..e15630cc3889 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/usb.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/usb.c | |||
@@ -443,14 +443,15 @@ static void brcmf_usb_rx_complete(struct urb *urb) | |||
443 | struct brcmf_usbreq *req = (struct brcmf_usbreq *)urb->context; | 443 | struct brcmf_usbreq *req = (struct brcmf_usbreq *)urb->context; |
444 | struct brcmf_usbdev_info *devinfo = req->devinfo; | 444 | struct brcmf_usbdev_info *devinfo = req->devinfo; |
445 | struct sk_buff *skb; | 445 | struct sk_buff *skb; |
446 | int ifidx = 0; | 446 | struct sk_buff_head skbq; |
447 | 447 | ||
448 | brcmf_dbg(USB, "Enter, urb->status=%d\n", urb->status); | 448 | brcmf_dbg(USB, "Enter, urb->status=%d\n", urb->status); |
449 | brcmf_usb_del_fromq(devinfo, req); | 449 | brcmf_usb_del_fromq(devinfo, req); |
450 | skb = req->skb; | 450 | skb = req->skb; |
451 | req->skb = NULL; | 451 | req->skb = NULL; |
452 | 452 | ||
453 | if (urb->status == 0) { | 453 | /* zero lenght packets indicate usb "failure". Do not refill */ |
454 | if (urb->status == 0 && urb->actual_length) { | ||
454 | devinfo->bus_pub.bus->dstats.rx_packets++; | 455 | devinfo->bus_pub.bus->dstats.rx_packets++; |
455 | } else { | 456 | } else { |
456 | devinfo->bus_pub.bus->dstats.rx_errors++; | 457 | devinfo->bus_pub.bus->dstats.rx_errors++; |
@@ -460,13 +461,10 @@ static void brcmf_usb_rx_complete(struct urb *urb) | |||
460 | } | 461 | } |
461 | 462 | ||
462 | if (devinfo->bus_pub.state == BRCMFMAC_USB_STATE_UP) { | 463 | if (devinfo->bus_pub.state == BRCMFMAC_USB_STATE_UP) { |
464 | skb_queue_head_init(&skbq); | ||
465 | skb_queue_tail(&skbq, skb); | ||
463 | skb_put(skb, urb->actual_length); | 466 | skb_put(skb, urb->actual_length); |
464 | if (brcmf_proto_hdrpull(devinfo->dev, &ifidx, skb) != 0) { | 467 | brcmf_rx_frames(devinfo->dev, &skbq); |
465 | brcmf_err("rx protocol error\n"); | ||
466 | brcmu_pkt_buf_free_skb(skb); | ||
467 | devinfo->bus_pub.bus->dstats.rx_errors++; | ||
468 | } else | ||
469 | brcmf_rx_packet(devinfo->dev, ifidx, skb); | ||
470 | brcmf_usb_rx_refill(devinfo, req); | 468 | brcmf_usb_rx_refill(devinfo, req); |
471 | } else { | 469 | } else { |
472 | brcmu_pkt_buf_free_skb(skb); | 470 | brcmu_pkt_buf_free_skb(skb); |
@@ -1520,10 +1518,23 @@ static void brcmf_release_fw(struct list_head *q) | |||
1520 | } | 1518 | } |
1521 | } | 1519 | } |
1522 | 1520 | ||
1521 | static int brcmf_usb_reset_device(struct device *dev, void *notused) | ||
1522 | { | ||
1523 | /* device past is the usb interface so we | ||
1524 | * need to use parent here. | ||
1525 | */ | ||
1526 | brcmf_dev_reset(dev->parent); | ||
1527 | return 0; | ||
1528 | } | ||
1523 | 1529 | ||
1524 | void brcmf_usb_exit(void) | 1530 | void brcmf_usb_exit(void) |
1525 | { | 1531 | { |
1532 | struct device_driver *drv = &brcmf_usbdrvr.drvwrap.driver; | ||
1533 | int ret; | ||
1534 | |||
1526 | brcmf_dbg(USB, "Enter\n"); | 1535 | brcmf_dbg(USB, "Enter\n"); |
1536 | ret = driver_for_each_device(drv, NULL, NULL, | ||
1537 | brcmf_usb_reset_device); | ||
1527 | usb_deregister(&brcmf_usbdrvr); | 1538 | usb_deregister(&brcmf_usbdrvr); |
1528 | brcmf_release_fw(&fw_image_list); | 1539 | brcmf_release_fw(&fw_image_list); |
1529 | } | 1540 | } |