| .. | .. |
|---|
| 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_destoy_wmi(hif_dev->htc_handle->drv_priv); |
|---|
| 1405 | 1446 | ath9k_htc_hw_free(hif_dev->htc_handle); |
|---|
| 1406 | 1447 | } |
|---|
| 1407 | 1448 | |
|---|