]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.19-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 26 Apr 2015 10:05:56 +0000 (12:05 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 26 Apr 2015 10:05:56 +0000 (12:05 +0200)
added patches:
rtlwifi-rtl8192ee-fix-handling-of-new-style-descriptors.patch

queue-3.19/rtlwifi-rtl8192ee-fix-handling-of-new-style-descriptors.patch [new file with mode: 0644]
queue-3.19/series

diff --git a/queue-3.19/rtlwifi-rtl8192ee-fix-handling-of-new-style-descriptors.patch b/queue-3.19/rtlwifi-rtl8192ee-fix-handling-of-new-style-descriptors.patch
new file mode 100644 (file)
index 0000000..ebbd14c
--- /dev/null
@@ -0,0 +1,190 @@
+From d0311314d00298f83aa5450a1d4a92889e7cc2ea Mon Sep 17 00:00:00 2001
+From: Troy Tan <troy_tan@realsil.com.cn>
+Date: Tue, 3 Feb 2015 11:15:17 -0600
+Subject: rtlwifi: rtl8192ee: Fix handling of new style descriptors
+
+From: Troy Tan <troy_tan@realsil.com.cn>
+
+commit d0311314d00298f83aa5450a1d4a92889e7cc2ea upstream.
+
+The hardware and firmware for the RTL8192EE utilize a FIFO list of
+descriptors. There were some problems with the initial implementation.
+The worst of these failed to detect that the FIFO was becoming full,
+which led to the device needing to be power cycled. As this condition
+is not relevant to most of the devices supported by rtlwifi, a callback
+routine was added to detect this situation. This patch implements the
+necessary changes in the pci handler, and the linkage into the appropriate
+rtl8192ee routine.
+
+Signed-off-by: Troy Tan <troy_tan@realsil.com.cn>
+Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net>
+Cc: Stable <stable@vger.kernel.org> [V3.18]
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/net/wireless/rtlwifi/pci.c           |   31 ++++++++++++++++++++-------
+ drivers/net/wireless/rtlwifi/rtl8192ee/sw.c  |    3 --
+ drivers/net/wireless/rtlwifi/rtl8192ee/trx.c |    7 +++---
+ drivers/net/wireless/rtlwifi/rtl8192ee/trx.h |    2 -
+ drivers/net/wireless/rtlwifi/wifi.h          |    1 
+ 5 files changed, 30 insertions(+), 14 deletions(-)
+
+--- a/drivers/net/wireless/rtlwifi/pci.c
++++ b/drivers/net/wireless/rtlwifi/pci.c
+@@ -578,6 +578,13 @@ static void _rtl_pci_tx_isr(struct ieee8
+               else
+                       entry = (u8 *)(&ring->desc[ring->idx]);
++              if (rtlpriv->cfg->ops->get_available_desc &&
++                  rtlpriv->cfg->ops->get_available_desc(hw, prio) <= 1) {
++                      RT_TRACE(rtlpriv, (COMP_INTR | COMP_SEND), DBG_DMESG,
++                               "no available desc!\n");
++                      return;
++              }
++
+               if (!rtlpriv->cfg->ops->is_tx_desc_closed(hw, prio, ring->idx))
+                       return;
+               ring->idx = (ring->idx + 1) % ring->entries;
+@@ -641,10 +648,9 @@ static void _rtl_pci_tx_isr(struct ieee8
+               ieee80211_tx_status_irqsafe(hw, skb);
+-              if ((ring->entries - skb_queue_len(&ring->queue))
+-                              == 2) {
++              if ((ring->entries - skb_queue_len(&ring->queue)) <= 4) {
+-                      RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD,
++                      RT_TRACE(rtlpriv, COMP_ERR, DBG_DMESG,
+                                "more desc left, wake skb_queue@%d, ring->idx = %d, skb_queue_len = 0x%x\n",
+                                prio, ring->idx,
+                                skb_queue_len(&ring->queue));
+@@ -793,7 +799,7 @@ static void _rtl_pci_rx_interrupt(struct
+                       rx_remained_cnt =
+                               rtlpriv->cfg->ops->rx_desc_buff_remained_cnt(hw,
+                                                                     hw_queue);
+-                      if (rx_remained_cnt < 1)
++                      if (rx_remained_cnt == 0)
+                               return;
+               } else {        /* rx descriptor */
+@@ -845,18 +851,18 @@ static void _rtl_pci_rx_interrupt(struct
+                       else
+                               skb_reserve(skb, stats.rx_drvinfo_size +
+                                           stats.rx_bufshift);
+-
+               } else {
+                       RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
+                                "skb->end - skb->tail = %d, len is %d\n",
+                                skb->end - skb->tail, len);
+-                      break;
++                      dev_kfree_skb_any(skb);
++                      goto new_trx_end;
+               }
+               /* handle command packet here */
+               if (rtlpriv->cfg->ops->rx_command_packet &&
+                   rtlpriv->cfg->ops->rx_command_packet(hw, stats, skb)) {
+                               dev_kfree_skb_any(skb);
+-                              goto end;
++                              goto new_trx_end;
+               }
+               /*
+@@ -906,6 +912,7 @@ static void _rtl_pci_rx_interrupt(struct
+               } else {
+                       dev_kfree_skb_any(skb);
+               }
++new_trx_end:
+               if (rtlpriv->use_new_trx_flow) {
+                       rtlpci->rx_ring[hw_queue].next_rx_rp += 1;
+                       rtlpci->rx_ring[hw_queue].next_rx_rp %=
+@@ -921,7 +928,6 @@ static void _rtl_pci_rx_interrupt(struct
+                       rtlpriv->enter_ps = false;
+                       schedule_work(&rtlpriv->works.lps_change_work);
+               }
+-end:
+               skb = new_skb;
+ no_new:
+               if (rtlpriv->use_new_trx_flow) {
+@@ -1695,6 +1701,15 @@ static int rtl_pci_tx(struct ieee80211_h
+               }
+       }
++      if (rtlpriv->cfg->ops->get_available_desc &&
++          rtlpriv->cfg->ops->get_available_desc(hw, hw_queue) == 0) {
++                      RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
++                               "get_available_desc fail\n");
++                      spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock,
++                                             flags);
++                      return skb->len;
++      }
++
+       if (ieee80211_is_data_qos(fc)) {
+               tid = rtl_get_tid(skb);
+               if (sta) {
+--- a/drivers/net/wireless/rtlwifi/rtl8192ee/sw.c
++++ b/drivers/net/wireless/rtlwifi/rtl8192ee/sw.c
+@@ -113,8 +113,6 @@ int rtl92ee_init_sw_vars(struct ieee8021
+                                 RCR_HTC_LOC_CTRL              |
+                                 RCR_AMF                       |
+                                 RCR_ACF                       |
+-                                RCR_ADF                       |
+-                                RCR_AICV                      |
+                                 RCR_ACRC32                    |
+                                 RCR_AB                        |
+                                 RCR_AM                        |
+@@ -241,6 +239,7 @@ static struct rtl_hal_ops rtl8192ee_hal_
+       .set_desc = rtl92ee_set_desc,
+       .get_desc = rtl92ee_get_desc,
+       .is_tx_desc_closed = rtl92ee_is_tx_desc_closed,
++      .get_available_desc = rtl92ee_get_available_desc,
+       .tx_polling = rtl92ee_tx_polling,
+       .enable_hw_sec = rtl92ee_enable_hw_security_config,
+       .set_key = rtl92ee_set_key,
+--- a/drivers/net/wireless/rtlwifi/rtl8192ee/trx.c
++++ b/drivers/net/wireless/rtlwifi/rtl8192ee/trx.c
+@@ -707,7 +707,7 @@ static u16 get_desc_addr_fr_q_idx(u16 qu
+       return desc_address;
+ }
+-void rtl92ee_get_available_desc(struct ieee80211_hw *hw, u8 q_idx)
++u16 rtl92ee_get_available_desc(struct ieee80211_hw *hw, u8 q_idx)
+ {
+       struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+@@ -721,11 +721,12 @@ void rtl92ee_get_available_desc(struct i
+       current_tx_write_point = (u16)((tmp_4byte) & 0x0fff);
+       point_diff = ((current_tx_read_point > current_tx_write_point) ?
+-                    (current_tx_read_point - current_tx_write_point) :
+-                    (TX_DESC_NUM_92E - current_tx_write_point +
++                    (current_tx_read_point - current_tx_write_point - 1) :
++                    (TX_DESC_NUM_92E - 1 - current_tx_write_point +
+                      current_tx_read_point));
+       rtlpci->tx_ring[q_idx].avl_desc = point_diff;
++      return point_diff;
+ }
+ void rtl92ee_pre_fill_tx_bd_desc(struct ieee80211_hw *hw,
+--- a/drivers/net/wireless/rtlwifi/rtl8192ee/trx.h
++++ b/drivers/net/wireless/rtlwifi/rtl8192ee/trx.h
+@@ -831,7 +831,7 @@ void rtl92ee_rx_check_dma_ok(struct ieee
+                            u8 queue_index);
+ u16   rtl92ee_rx_desc_buff_remained_cnt(struct ieee80211_hw *hw,
+                                         u8 queue_index);
+-void rtl92ee_get_available_desc(struct ieee80211_hw *hw, u8 queue_index);
++u16 rtl92ee_get_available_desc(struct ieee80211_hw *hw, u8 queue_index);
+ void rtl92ee_pre_fill_tx_bd_desc(struct ieee80211_hw *hw,
+                                u8 *tx_bd_desc, u8 *desc, u8 queue_index,
+                                struct sk_buff *skb, dma_addr_t addr);
+--- a/drivers/net/wireless/rtlwifi/wifi.h
++++ b/drivers/net/wireless/rtlwifi/wifi.h
+@@ -2161,6 +2161,7 @@ struct rtl_hal_ops {
+       void (*add_wowlan_pattern)(struct ieee80211_hw *hw,
+                                  struct rtl_wow_pattern *rtl_pattern,
+                                  u8 index);
++      u16 (*get_available_desc)(struct ieee80211_hw *hw, u8 q_idx);
+ };
+ struct rtl_intf_ops {
index 8204dc048ee1597045e1c92d95a9ec5993a0e49d..93c3de1cdc80b0b2265c8eef09ba409c2618644b 100644 (file)
@@ -23,3 +23,4 @@ kvm-nvmx-mask-unrestricted_guest-if-disabled-on-l0.patch
 staging-comedi-adv_pci1710-fix-ai-insn_read-for-non-zero-channel.patch
 mm-hugetlb-reduce-arch-dependent-code-around-follow_huge_.patch
 mm-hugetlb-take-page-table-lock-in-follow_huge_pmd.patch
+rtlwifi-rtl8192ee-fix-handling-of-new-style-descriptors.patch