rtlwifi: rtl8192ee: Fix handling of new style descriptors
authorTroy Tan <troy_tan@realsil.com.cn>
Tue, 3 Feb 2015 17:15:17 +0000 (11:15 -0600)
committerSasha Levin <sasha.levin@oracle.com>
Sun, 17 May 2015 23:12:31 +0000 (19:12 -0400)
[ Upstream commit d0311314d00298f83aa5450a1d4a92889e7cc2ea ]

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: Sasha Levin <sasha.levin@oracle.com>
drivers/net/wireless/rtlwifi/pci.c
drivers/net/wireless/rtlwifi/rtl8192ee/sw.c
drivers/net/wireless/rtlwifi/rtl8192ee/trx.c
drivers/net/wireless/rtlwifi/rtl8192ee/trx.h
drivers/net/wireless/rtlwifi/wifi.h

index a5186bb7c63ec424d6902497c7fdd34753c9b7e4..8c45cf44ce24bac6393902ae2daf708b0ce11e6a 100644 (file)
@@ -578,6 +578,13 @@ static void _rtl_pci_tx_isr(struct ieee80211_hw *hw, int prio)
                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 ieee80211_hw *hw, int prio)
 
                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 ieee80211_hw *hw)
                        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 ieee80211_hw *hw)
                        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 ieee80211_hw *hw)
                } 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 ieee80211_hw *hw)
                        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_hw *hw,
                }
        }
 
+       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) {
index 9b5a7d5be1215626929e5d8673d62dfd50743b26..c31c6bfb536d0c520076c0794934043fc27752fb 100644 (file)
@@ -113,8 +113,6 @@ int rtl92ee_init_sw_vars(struct ieee80211_hw *hw)
                                  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_ops = {
        .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,
index 00690040be3781a884edf8ada2d10ba6b6319e64..1f6d160877e199425672eb4e3d3254b97d8fca53 100644 (file)
@@ -707,7 +707,7 @@ static u16 get_desc_addr_fr_q_idx(u16 queue_index)
        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 ieee80211_hw *hw, u8 q_idx)
        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,
index 8effef9b13dd68a846f7b416207191f9c0dde43a..b489dd9c840189f41920b24c934b359c74139ed1 100644 (file)
@@ -831,7 +831,7 @@ void rtl92ee_rx_check_dma_ok(struct ieee80211_hw *hw, u8 *header_desc,
                             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);
index 6866dcf24340959c78483e6e098d9e3c0dcfd889..27822fe34d9a2925d09c1055946acff588b69534 100644 (file)
@@ -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 {