.. | .. |
---|
244 | 244 | ath9k_htc_txcompletion_cb(hif_dev->htc_handle, |
---|
245 | 245 | skb, txok); |
---|
246 | 246 | if (txok) { |
---|
247 | | - TX_STAT_INC(skb_success); |
---|
248 | | - TX_STAT_ADD(skb_success_bytes, ln); |
---|
| 247 | + TX_STAT_INC(hif_dev, skb_success); |
---|
| 248 | + TX_STAT_ADD(hif_dev, skb_success_bytes, ln); |
---|
249 | 249 | } |
---|
250 | 250 | else |
---|
251 | | - TX_STAT_INC(skb_failed); |
---|
| 251 | + TX_STAT_INC(hif_dev, skb_failed); |
---|
252 | 252 | } |
---|
253 | 253 | } |
---|
254 | 254 | |
---|
.. | .. |
---|
302 | 302 | hif_dev->tx.tx_buf_cnt++; |
---|
303 | 303 | if (!(hif_dev->tx.flags & HIF_USB_TX_STOP)) |
---|
304 | 304 | __hif_usb_tx(hif_dev); /* Check for pending SKBs */ |
---|
305 | | - TX_STAT_INC(buf_completed); |
---|
| 305 | + TX_STAT_INC(hif_dev, buf_completed); |
---|
306 | 306 | spin_unlock(&hif_dev->tx.tx_lock); |
---|
307 | 307 | } |
---|
308 | 308 | |
---|
.. | .. |
---|
353 | 353 | tx_buf->len += tx_buf->offset; |
---|
354 | 354 | |
---|
355 | 355 | __skb_queue_tail(&tx_buf->skb_queue, nskb); |
---|
356 | | - TX_STAT_INC(skb_queued); |
---|
| 356 | + TX_STAT_INC(hif_dev, skb_queued); |
---|
357 | 357 | } |
---|
358 | 358 | |
---|
359 | 359 | usb_fill_bulk_urb(tx_buf->urb, hif_dev->udev, |
---|
.. | .. |
---|
368 | 368 | __skb_queue_head_init(&tx_buf->skb_queue); |
---|
369 | 369 | list_move_tail(&tx_buf->list, &hif_dev->tx.tx_buf); |
---|
370 | 370 | hif_dev->tx.tx_buf_cnt++; |
---|
| 371 | + } else { |
---|
| 372 | + TX_STAT_INC(hif_dev, buf_queued); |
---|
371 | 373 | } |
---|
372 | | - |
---|
373 | | - if (!ret) |
---|
374 | | - TX_STAT_INC(buf_queued); |
---|
375 | 374 | |
---|
376 | 375 | return ret; |
---|
377 | 376 | } |
---|
.. | .. |
---|
515 | 514 | ath9k_htc_txcompletion_cb(hif_dev->htc_handle, |
---|
516 | 515 | skb, false); |
---|
517 | 516 | hif_dev->tx.tx_skb_cnt--; |
---|
518 | | - TX_STAT_INC(skb_failed); |
---|
| 517 | + TX_STAT_INC(hif_dev, skb_failed); |
---|
519 | 518 | } |
---|
520 | 519 | } |
---|
521 | 520 | |
---|
.. | .. |
---|
534 | 533 | .sta_drain = hif_usb_sta_drain, |
---|
535 | 534 | .send = hif_usb_send, |
---|
536 | 535 | }; |
---|
| 536 | + |
---|
| 537 | +/* Need to free remain_skb allocated in ath9k_hif_usb_rx_stream |
---|
| 538 | + * in case ath9k_hif_usb_rx_stream wasn't called next time to |
---|
| 539 | + * process the buffer and subsequently free it. |
---|
| 540 | + */ |
---|
| 541 | +static void ath9k_hif_usb_free_rx_remain_skb(struct hif_device_usb *hif_dev) |
---|
| 542 | +{ |
---|
| 543 | + unsigned long flags; |
---|
| 544 | + |
---|
| 545 | + spin_lock_irqsave(&hif_dev->rx_lock, flags); |
---|
| 546 | + if (hif_dev->remain_skb) { |
---|
| 547 | + dev_kfree_skb_any(hif_dev->remain_skb); |
---|
| 548 | + hif_dev->remain_skb = NULL; |
---|
| 549 | + hif_dev->rx_remain_len = 0; |
---|
| 550 | + RX_STAT_INC(hif_dev, skb_dropped); |
---|
| 551 | + } |
---|
| 552 | + spin_unlock_irqrestore(&hif_dev->rx_lock, flags); |
---|
| 553 | +} |
---|
537 | 554 | |
---|
538 | 555 | static void ath9k_hif_usb_rx_stream(struct hif_device_usb *hif_dev, |
---|
539 | 556 | struct sk_buff *skb) |
---|
.. | .. |
---|
562 | 579 | memcpy(ptr, skb->data, rx_remain_len); |
---|
563 | 580 | |
---|
564 | 581 | rx_pkt_len += rx_remain_len; |
---|
565 | | - hif_dev->rx_remain_len = 0; |
---|
566 | 582 | skb_put(remain_skb, rx_pkt_len); |
---|
567 | 583 | |
---|
568 | 584 | skb_pool[pool_index++] = remain_skb; |
---|
569 | | - |
---|
| 585 | + hif_dev->remain_skb = NULL; |
---|
| 586 | + hif_dev->rx_remain_len = 0; |
---|
570 | 587 | } else { |
---|
571 | 588 | index = rx_remain_len; |
---|
572 | 589 | } |
---|
.. | .. |
---|
585 | 602 | pkt_len = get_unaligned_le16(ptr + index); |
---|
586 | 603 | pkt_tag = get_unaligned_le16(ptr + index + 2); |
---|
587 | 604 | |
---|
| 605 | + /* It is supposed that if we have an invalid pkt_tag or |
---|
| 606 | + * pkt_len then the whole input SKB is considered invalid |
---|
| 607 | + * and dropped; the associated packets already in skb_pool |
---|
| 608 | + * are dropped, too. |
---|
| 609 | + */ |
---|
588 | 610 | if (pkt_tag != ATH_USB_RX_STREAM_MODE_TAG) { |
---|
589 | | - RX_STAT_INC(skb_dropped); |
---|
590 | | - return; |
---|
| 611 | + RX_STAT_INC(hif_dev, skb_dropped); |
---|
| 612 | + goto invalid_pkt; |
---|
591 | 613 | } |
---|
592 | 614 | |
---|
593 | 615 | if (pkt_len > 2 * MAX_RX_BUF_SIZE) { |
---|
594 | 616 | dev_err(&hif_dev->udev->dev, |
---|
595 | 617 | "ath9k_htc: invalid pkt_len (%x)\n", pkt_len); |
---|
596 | | - RX_STAT_INC(skb_dropped); |
---|
597 | | - return; |
---|
| 618 | + RX_STAT_INC(hif_dev, skb_dropped); |
---|
| 619 | + goto invalid_pkt; |
---|
598 | 620 | } |
---|
599 | 621 | |
---|
600 | 622 | pad_len = 4 - (pkt_len & 0x3); |
---|
.. | .. |
---|
606 | 628 | |
---|
607 | 629 | if (index > MAX_RX_BUF_SIZE) { |
---|
608 | 630 | spin_lock(&hif_dev->rx_lock); |
---|
609 | | - hif_dev->rx_remain_len = index - MAX_RX_BUF_SIZE; |
---|
610 | | - hif_dev->rx_transfer_len = |
---|
611 | | - MAX_RX_BUF_SIZE - chk_idx - 4; |
---|
612 | | - hif_dev->rx_pad_len = pad_len; |
---|
613 | | - |
---|
614 | 631 | nskb = __dev_alloc_skb(pkt_len + 32, GFP_ATOMIC); |
---|
615 | 632 | if (!nskb) { |
---|
616 | 633 | dev_err(&hif_dev->udev->dev, |
---|
.. | .. |
---|
618 | 635 | spin_unlock(&hif_dev->rx_lock); |
---|
619 | 636 | goto err; |
---|
620 | 637 | } |
---|
| 638 | + |
---|
| 639 | + hif_dev->rx_remain_len = index - MAX_RX_BUF_SIZE; |
---|
| 640 | + hif_dev->rx_transfer_len = |
---|
| 641 | + MAX_RX_BUF_SIZE - chk_idx - 4; |
---|
| 642 | + hif_dev->rx_pad_len = pad_len; |
---|
| 643 | + |
---|
621 | 644 | skb_reserve(nskb, 32); |
---|
622 | | - RX_STAT_INC(skb_allocated); |
---|
| 645 | + RX_STAT_INC(hif_dev, skb_allocated); |
---|
623 | 646 | |
---|
624 | 647 | memcpy(nskb->data, &(skb->data[chk_idx+4]), |
---|
625 | 648 | hif_dev->rx_transfer_len); |
---|
.. | .. |
---|
640 | 663 | goto err; |
---|
641 | 664 | } |
---|
642 | 665 | skb_reserve(nskb, 32); |
---|
643 | | - RX_STAT_INC(skb_allocated); |
---|
| 666 | + RX_STAT_INC(hif_dev, skb_allocated); |
---|
644 | 667 | |
---|
645 | 668 | memcpy(nskb->data, &(skb->data[chk_idx+4]), pkt_len); |
---|
646 | 669 | skb_put(nskb, pkt_len); |
---|
.. | .. |
---|
650 | 673 | |
---|
651 | 674 | err: |
---|
652 | 675 | for (i = 0; i < pool_index; i++) { |
---|
653 | | - RX_STAT_ADD(skb_completed_bytes, skb_pool[i]->len); |
---|
| 676 | + RX_STAT_ADD(hif_dev, skb_completed_bytes, skb_pool[i]->len); |
---|
654 | 677 | ath9k_htc_rx_msg(hif_dev->htc_handle, skb_pool[i], |
---|
655 | 678 | skb_pool[i]->len, USB_WLAN_RX_PIPE); |
---|
656 | | - RX_STAT_INC(skb_completed); |
---|
| 679 | + RX_STAT_INC(hif_dev, skb_completed); |
---|
657 | 680 | } |
---|
| 681 | + return; |
---|
| 682 | +invalid_pkt: |
---|
| 683 | + for (i = 0; i < pool_index; i++) { |
---|
| 684 | + dev_kfree_skb_any(skb_pool[i]); |
---|
| 685 | + RX_STAT_INC(hif_dev, skb_dropped); |
---|
| 686 | + } |
---|
| 687 | + return; |
---|
658 | 688 | } |
---|
659 | 689 | |
---|
660 | 690 | static void ath9k_hif_usb_rx_cb(struct urb *urb) |
---|
.. | .. |
---|
709 | 739 | struct rx_buf *rx_buf = (struct rx_buf *)urb->context; |
---|
710 | 740 | struct hif_device_usb *hif_dev = rx_buf->hif_dev; |
---|
711 | 741 | struct sk_buff *skb = rx_buf->skb; |
---|
712 | | - struct sk_buff *nskb; |
---|
713 | 742 | int ret; |
---|
714 | 743 | |
---|
715 | 744 | if (!skb) |
---|
716 | 745 | return; |
---|
717 | 746 | |
---|
718 | 747 | if (!hif_dev) |
---|
719 | | - goto free; |
---|
| 748 | + goto free_skb; |
---|
720 | 749 | |
---|
721 | 750 | switch (urb->status) { |
---|
722 | 751 | case 0: |
---|
.. | .. |
---|
725 | 754 | case -ECONNRESET: |
---|
726 | 755 | case -ENODEV: |
---|
727 | 756 | case -ESHUTDOWN: |
---|
728 | | - goto free; |
---|
| 757 | + goto free_skb; |
---|
729 | 758 | default: |
---|
730 | 759 | skb_reset_tail_pointer(skb); |
---|
731 | 760 | skb_trim(skb, 0); |
---|
.. | .. |
---|
736 | 765 | if (likely(urb->actual_length != 0)) { |
---|
737 | 766 | skb_put(skb, urb->actual_length); |
---|
738 | 767 | |
---|
739 | | - /* Process the command first */ |
---|
| 768 | + /* |
---|
| 769 | + * Process the command first. |
---|
| 770 | + * skb is either freed here or passed to be |
---|
| 771 | + * managed to another callback function. |
---|
| 772 | + */ |
---|
740 | 773 | ath9k_htc_rx_msg(hif_dev->htc_handle, skb, |
---|
741 | 774 | skb->len, USB_REG_IN_PIPE); |
---|
742 | 775 | |
---|
743 | | - |
---|
744 | | - nskb = alloc_skb(MAX_REG_IN_BUF_SIZE, GFP_ATOMIC); |
---|
745 | | - if (!nskb) { |
---|
| 776 | + skb = alloc_skb(MAX_REG_IN_BUF_SIZE, GFP_ATOMIC); |
---|
| 777 | + if (!skb) { |
---|
746 | 778 | dev_err(&hif_dev->udev->dev, |
---|
747 | 779 | "ath9k_htc: REG_IN memory allocation failure\n"); |
---|
748 | | - urb->context = NULL; |
---|
749 | | - return; |
---|
| 780 | + goto free_rx_buf; |
---|
750 | 781 | } |
---|
751 | 782 | |
---|
752 | | - rx_buf->skb = nskb; |
---|
| 783 | + rx_buf->skb = skb; |
---|
753 | 784 | |
---|
754 | 785 | usb_fill_int_urb(urb, hif_dev->udev, |
---|
755 | 786 | usb_rcvintpipe(hif_dev->udev, |
---|
756 | 787 | USB_REG_IN_PIPE), |
---|
757 | | - nskb->data, MAX_REG_IN_BUF_SIZE, |
---|
| 788 | + skb->data, MAX_REG_IN_BUF_SIZE, |
---|
758 | 789 | ath9k_hif_usb_reg_in_cb, rx_buf, 1); |
---|
759 | 790 | } |
---|
760 | 791 | |
---|
.. | .. |
---|
763 | 794 | ret = usb_submit_urb(urb, GFP_ATOMIC); |
---|
764 | 795 | if (ret) { |
---|
765 | 796 | usb_unanchor_urb(urb); |
---|
766 | | - goto free; |
---|
| 797 | + goto free_skb; |
---|
767 | 798 | } |
---|
768 | 799 | |
---|
769 | 800 | return; |
---|
770 | | -free: |
---|
| 801 | +free_skb: |
---|
771 | 802 | kfree_skb(skb); |
---|
| 803 | +free_rx_buf: |
---|
772 | 804 | kfree(rx_buf); |
---|
773 | 805 | urb->context = NULL; |
---|
774 | 806 | } |
---|
.. | .. |
---|
781 | 813 | spin_lock_irqsave(&hif_dev->tx.tx_lock, flags); |
---|
782 | 814 | list_for_each_entry_safe(tx_buf, tx_buf_tmp, |
---|
783 | 815 | &hif_dev->tx.tx_buf, list) { |
---|
784 | | - usb_get_urb(tx_buf->urb); |
---|
785 | | - spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags); |
---|
786 | | - usb_kill_urb(tx_buf->urb); |
---|
787 | 816 | list_del(&tx_buf->list); |
---|
788 | 817 | usb_free_urb(tx_buf->urb); |
---|
789 | 818 | kfree(tx_buf->buf); |
---|
790 | 819 | kfree(tx_buf); |
---|
791 | | - spin_lock_irqsave(&hif_dev->tx.tx_lock, flags); |
---|
792 | 820 | } |
---|
793 | 821 | spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags); |
---|
794 | 822 | |
---|
.. | .. |
---|
858 | 886 | static void ath9k_hif_usb_dealloc_rx_urbs(struct hif_device_usb *hif_dev) |
---|
859 | 887 | { |
---|
860 | 888 | usb_kill_anchored_urbs(&hif_dev->rx_submitted); |
---|
| 889 | + ath9k_hif_usb_free_rx_remain_skb(hif_dev); |
---|
861 | 890 | } |
---|
862 | 891 | |
---|
863 | 892 | static int ath9k_hif_usb_alloc_rx_urbs(struct hif_device_usb *hif_dev) |
---|
.. | .. |
---|
1330 | 1359 | static int ath9k_hif_usb_probe(struct usb_interface *interface, |
---|
1331 | 1360 | const struct usb_device_id *id) |
---|
1332 | 1361 | { |
---|
| 1362 | + struct usb_endpoint_descriptor *bulk_in, *bulk_out, *int_in, *int_out; |
---|
1333 | 1363 | struct usb_device *udev = interface_to_usbdev(interface); |
---|
| 1364 | + struct usb_host_interface *alt; |
---|
1334 | 1365 | struct hif_device_usb *hif_dev; |
---|
1335 | 1366 | int ret = 0; |
---|
| 1367 | + |
---|
| 1368 | + /* Verify the expected endpoints are present */ |
---|
| 1369 | + alt = interface->cur_altsetting; |
---|
| 1370 | + if (usb_find_common_endpoints(alt, &bulk_in, &bulk_out, &int_in, &int_out) < 0 || |
---|
| 1371 | + usb_endpoint_num(bulk_in) != USB_WLAN_RX_PIPE || |
---|
| 1372 | + usb_endpoint_num(bulk_out) != USB_WLAN_TX_PIPE || |
---|
| 1373 | + usb_endpoint_num(int_in) != USB_REG_IN_PIPE || |
---|
| 1374 | + usb_endpoint_num(int_out) != USB_REG_OUT_PIPE) { |
---|
| 1375 | + dev_err(&udev->dev, |
---|
| 1376 | + "ath9k_htc: Device endpoint numbers are not the expected ones\n"); |
---|
| 1377 | + return -ENODEV; |
---|
| 1378 | + } |
---|
1336 | 1379 | |
---|
1337 | 1380 | if (id->driver_info == STORAGE_DEVICE) |
---|
1338 | 1381 | return send_eject_command(interface); |
---|
.. | .. |
---|
1400 | 1443 | |
---|
1401 | 1444 | if (hif_dev->flags & HIF_USB_READY) { |
---|
1402 | 1445 | ath9k_htc_hw_deinit(hif_dev->htc_handle, unplugged); |
---|
1403 | | - ath9k_hif_usb_dev_deinit(hif_dev); |
---|
1404 | | - ath9k_destroy_wmi(hif_dev->htc_handle->drv_priv); |
---|
1405 | 1446 | ath9k_htc_hw_free(hif_dev->htc_handle); |
---|
1406 | 1447 | } |
---|
1407 | 1448 | |
---|