diff options
Diffstat (limited to 'drivers/net/wireless/rtlwifi/pci.c')
-rw-r--r-- | drivers/net/wireless/rtlwifi/pci.c | 41 |
1 files changed, 24 insertions, 17 deletions
diff --git a/drivers/net/wireless/rtlwifi/pci.c b/drivers/net/wireless/rtlwifi/pci.c index 89100e7c553b..fc44005b0d53 100644 --- a/drivers/net/wireless/rtlwifi/pci.c +++ b/drivers/net/wireless/rtlwifi/pci.c | |||
@@ -622,7 +622,7 @@ tx_status_ok: | |||
622 | if (((rtlpriv->link_info.num_rx_inperiod + | 622 | if (((rtlpriv->link_info.num_rx_inperiod + |
623 | rtlpriv->link_info.num_tx_inperiod) > 8) || | 623 | rtlpriv->link_info.num_tx_inperiod) > 8) || |
624 | (rtlpriv->link_info.num_rx_inperiod > 2)) { | 624 | (rtlpriv->link_info.num_rx_inperiod > 2)) { |
625 | rtl_lps_leave(hw); | 625 | tasklet_schedule(&rtlpriv->works.ips_leave_tasklet); |
626 | } | 626 | } |
627 | } | 627 | } |
628 | 628 | ||
@@ -644,22 +644,23 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw) | |||
644 | .noise = -98, | 644 | .noise = -98, |
645 | .rate = 0, | 645 | .rate = 0, |
646 | }; | 646 | }; |
647 | int index = rtlpci->rx_ring[rx_queue_idx].idx; | ||
647 | 648 | ||
648 | /*RX NORMAL PKT */ | 649 | /*RX NORMAL PKT */ |
649 | while (count--) { | 650 | while (count--) { |
650 | /*rx descriptor */ | 651 | /*rx descriptor */ |
651 | struct rtl_rx_desc *pdesc = &rtlpci->rx_ring[rx_queue_idx].desc[ | 652 | struct rtl_rx_desc *pdesc = &rtlpci->rx_ring[rx_queue_idx].desc[ |
652 | rtlpci->rx_ring[rx_queue_idx].idx]; | 653 | index]; |
653 | /*rx pkt */ | 654 | /*rx pkt */ |
654 | struct sk_buff *skb = rtlpci->rx_ring[rx_queue_idx].rx_buf[ | 655 | struct sk_buff *skb = rtlpci->rx_ring[rx_queue_idx].rx_buf[ |
655 | rtlpci->rx_ring[rx_queue_idx].idx]; | 656 | index]; |
656 | 657 | ||
657 | own = (u8) rtlpriv->cfg->ops->get_desc((u8 *) pdesc, | 658 | own = (u8) rtlpriv->cfg->ops->get_desc((u8 *) pdesc, |
658 | false, HW_DESC_OWN); | 659 | false, HW_DESC_OWN); |
659 | 660 | ||
660 | if (own) { | 661 | if (own) { |
661 | /*wait data to be filled by hardware */ | 662 | /*wait data to be filled by hardware */ |
662 | return; | 663 | break; |
663 | } else { | 664 | } else { |
664 | struct ieee80211_hdr *hdr; | 665 | struct ieee80211_hdr *hdr; |
665 | __le16 fc; | 666 | __le16 fc; |
@@ -700,7 +701,7 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw) | |||
700 | rtlpci->rxbuffersize, | 701 | rtlpci->rxbuffersize, |
701 | PCI_DMA_FROMDEVICE); | 702 | PCI_DMA_FROMDEVICE); |
702 | 703 | ||
703 | if (!stats.crc || !stats.hwerror) { | 704 | if (!stats.crc && !stats.hwerror) { |
704 | memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, | 705 | memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, |
705 | sizeof(rx_status)); | 706 | sizeof(rx_status)); |
706 | 707 | ||
@@ -765,15 +766,12 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw) | |||
765 | if (((rtlpriv->link_info.num_rx_inperiod + | 766 | if (((rtlpriv->link_info.num_rx_inperiod + |
766 | rtlpriv->link_info.num_tx_inperiod) > 8) || | 767 | rtlpriv->link_info.num_tx_inperiod) > 8) || |
767 | (rtlpriv->link_info.num_rx_inperiod > 2)) { | 768 | (rtlpriv->link_info.num_rx_inperiod > 2)) { |
768 | rtl_lps_leave(hw); | 769 | tasklet_schedule(&rtlpriv->works.ips_leave_tasklet); |
769 | } | 770 | } |
770 | 771 | ||
771 | skb = new_skb; | 772 | skb = new_skb; |
772 | 773 | ||
773 | rtlpci->rx_ring[rx_queue_idx].rx_buf[rtlpci-> | 774 | rtlpci->rx_ring[rx_queue_idx].rx_buf[index] = skb; |
774 | rx_ring | ||
775 | [rx_queue_idx]. | ||
776 | idx] = skb; | ||
777 | *((dma_addr_t *) skb->cb) = | 775 | *((dma_addr_t *) skb->cb) = |
778 | pci_map_single(rtlpci->pdev, skb_tail_pointer(skb), | 776 | pci_map_single(rtlpci->pdev, skb_tail_pointer(skb), |
779 | rtlpci->rxbuffersize, | 777 | rtlpci->rxbuffersize, |
@@ -786,23 +784,22 @@ done: | |||
786 | rtlpriv->cfg->ops->set_desc((u8 *) pdesc, false, | 784 | rtlpriv->cfg->ops->set_desc((u8 *) pdesc, false, |
787 | HW_DESC_RXBUFF_ADDR, | 785 | HW_DESC_RXBUFF_ADDR, |
788 | (u8 *)&bufferaddress); | 786 | (u8 *)&bufferaddress); |
789 | rtlpriv->cfg->ops->set_desc((u8 *)pdesc, false, HW_DESC_RXOWN, | ||
790 | (u8 *)&tmp_one); | ||
791 | rtlpriv->cfg->ops->set_desc((u8 *)pdesc, false, | 787 | rtlpriv->cfg->ops->set_desc((u8 *)pdesc, false, |
792 | HW_DESC_RXPKT_LEN, | 788 | HW_DESC_RXPKT_LEN, |
793 | (u8 *)&rtlpci->rxbuffersize); | 789 | (u8 *)&rtlpci->rxbuffersize); |
794 | 790 | ||
795 | if (rtlpci->rx_ring[rx_queue_idx].idx == | 791 | if (index == rtlpci->rxringcount - 1) |
796 | rtlpci->rxringcount - 1) | ||
797 | rtlpriv->cfg->ops->set_desc((u8 *)pdesc, false, | 792 | rtlpriv->cfg->ops->set_desc((u8 *)pdesc, false, |
798 | HW_DESC_RXERO, | 793 | HW_DESC_RXERO, |
799 | (u8 *)&tmp_one); | 794 | (u8 *)&tmp_one); |
800 | 795 | ||
801 | rtlpci->rx_ring[rx_queue_idx].idx = | 796 | rtlpriv->cfg->ops->set_desc((u8 *)pdesc, false, HW_DESC_RXOWN, |
802 | (rtlpci->rx_ring[rx_queue_idx].idx + 1) % | 797 | (u8 *)&tmp_one); |
803 | rtlpci->rxringcount; | 798 | |
799 | index = (index + 1) % rtlpci->rxringcount; | ||
804 | } | 800 | } |
805 | 801 | ||
802 | rtlpci->rx_ring[rx_queue_idx].idx = index; | ||
806 | } | 803 | } |
807 | 804 | ||
808 | static irqreturn_t _rtl_pci_interrupt(int irq, void *dev_id) | 805 | static irqreturn_t _rtl_pci_interrupt(int irq, void *dev_id) |
@@ -940,6 +937,11 @@ static void _rtl_pci_irq_tasklet(struct ieee80211_hw *hw) | |||
940 | _rtl_pci_tx_chk_waitq(hw); | 937 | _rtl_pci_tx_chk_waitq(hw); |
941 | } | 938 | } |
942 | 939 | ||
940 | static void _rtl_pci_ips_leave_tasklet(struct ieee80211_hw *hw) | ||
941 | { | ||
942 | rtl_lps_leave(hw); | ||
943 | } | ||
944 | |||
943 | static void _rtl_pci_prepare_bcn_tasklet(struct ieee80211_hw *hw) | 945 | static void _rtl_pci_prepare_bcn_tasklet(struct ieee80211_hw *hw) |
944 | { | 946 | { |
945 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 947 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
@@ -1038,6 +1040,9 @@ static void _rtl_pci_init_struct(struct ieee80211_hw *hw, | |||
1038 | tasklet_init(&rtlpriv->works.irq_prepare_bcn_tasklet, | 1040 | tasklet_init(&rtlpriv->works.irq_prepare_bcn_tasklet, |
1039 | (void (*)(unsigned long))_rtl_pci_prepare_bcn_tasklet, | 1041 | (void (*)(unsigned long))_rtl_pci_prepare_bcn_tasklet, |
1040 | (unsigned long)hw); | 1042 | (unsigned long)hw); |
1043 | tasklet_init(&rtlpriv->works.ips_leave_tasklet, | ||
1044 | (void (*)(unsigned long))_rtl_pci_ips_leave_tasklet, | ||
1045 | (unsigned long)hw); | ||
1041 | } | 1046 | } |
1042 | 1047 | ||
1043 | static int _rtl_pci_init_tx_ring(struct ieee80211_hw *hw, | 1048 | static int _rtl_pci_init_tx_ring(struct ieee80211_hw *hw, |
@@ -1507,6 +1512,7 @@ static void rtl_pci_deinit(struct ieee80211_hw *hw) | |||
1507 | 1512 | ||
1508 | synchronize_irq(rtlpci->pdev->irq); | 1513 | synchronize_irq(rtlpci->pdev->irq); |
1509 | tasklet_kill(&rtlpriv->works.irq_tasklet); | 1514 | tasklet_kill(&rtlpriv->works.irq_tasklet); |
1515 | tasklet_kill(&rtlpriv->works.ips_leave_tasklet); | ||
1510 | 1516 | ||
1511 | flush_workqueue(rtlpriv->works.rtl_wq); | 1517 | flush_workqueue(rtlpriv->works.rtl_wq); |
1512 | destroy_workqueue(rtlpriv->works.rtl_wq); | 1518 | destroy_workqueue(rtlpriv->works.rtl_wq); |
@@ -1581,6 +1587,7 @@ static void rtl_pci_stop(struct ieee80211_hw *hw) | |||
1581 | set_hal_stop(rtlhal); | 1587 | set_hal_stop(rtlhal); |
1582 | 1588 | ||
1583 | rtlpriv->cfg->ops->disable_interrupt(hw); | 1589 | rtlpriv->cfg->ops->disable_interrupt(hw); |
1590 | tasklet_kill(&rtlpriv->works.ips_leave_tasklet); | ||
1584 | 1591 | ||
1585 | spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flags); | 1592 | spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flags); |
1586 | while (ppsc->rfchange_inprogress) { | 1593 | while (ppsc->rfchange_inprogress) { |