rtlwifi: rtl8192ee: Fix handling of new style descriptors
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>
This commit is contained in:
@@ -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));
|
||||
@@ -786,7 +792,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 */
|
||||
@@ -834,18 +840,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;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -895,6 +901,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 %=
|
||||
@@ -910,7 +917,6 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw)
|
||||
rtlpriv->enter_ps = false;
|
||||
schedule_work(&rtlpriv->works.lps_change_work);
|
||||
}
|
||||
end:
|
||||
if (rtlpriv->use_new_trx_flow) {
|
||||
_rtl_pci_init_one_rxdesc(hw, (u8 *)buffer_desc,
|
||||
rxring_idx,
|
||||
@@ -1672,6 +1678,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) {
|
||||
|
Reference in New Issue
Block a user