2015-01-14 17:37:28

by Larry Finger

[permalink] [raw]
Subject: [PATCH for 3.19 0/3] rtlwifi: Various updates/fixes

The first of these patches removes a logging statement that is no longer
needed. The other two fix a number of bugs in rtl8192ee that have been
found since the original inclusion of this driver.

Signed-off-by: Larry Finger <[email protected]>


Larry Finger (1):
rtlwifi: Remove logging statement that is no longer needed

Troy Tan (2):
rtlwifi: Fix handling of new style descriptors
rtlwifi: rtl8192ee: Implement new handling of FIFO descriptor buffer

drivers/net/wireless/rtlwifi/pci.c | 36 ++++--
drivers/net/wireless/rtlwifi/rtl8192ee/hw.c | 167 +++++++++++++++++++++----
drivers/net/wireless/rtlwifi/rtl8192ee/reg.h | 2 +
drivers/net/wireless/rtlwifi/rtl8192ee/sw.c | 3 +-
drivers/net/wireless/rtlwifi/rtl8192ee/trx.c | 175 +++++++++++----------------
drivers/net/wireless/rtlwifi/rtl8192ee/trx.h | 4 +-
drivers/net/wireless/rtlwifi/wifi.h | 1 +
7 files changed, 242 insertions(+), 146 deletions(-)

--
2.1.2



2015-01-15 17:14:53

by Larry Finger

[permalink] [raw]
Subject: Re: [PATCH for 3.19 2/3] rtlwifi: Fix handling of new style descriptors

On 01/15/2015 06:00 AM, Kalle Valo wrote:
> Hi Troy,
>
> please avoid top-posting.
>
> 谭杭波 <[email protected]> writes:
>
>> You can find get_available_desc here:
>>
>> diff --git a/drivers/net/wireless/rtlwifi/pci.c b/drivers/net/wireless/rtlwifi/
>> pci.c
>> index e25faac..a62170e 100644
>> --- 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 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;
>> + }
>
> I don't see rtlpriv->cfg->ops->get_available_desc set here, only being
> called?

Only one of the drivers (rtl8192ee) needs to implement that routine, which is
the reason it is checked for non-NULL before it is called. The implementation is
in patch 3 in file rtl8192ee/sw.c where it says:

@@ -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,
.init_sw_leds = rtl92ee_init_sw_leds,

Larry




2015-01-14 17:37:41

by Larry Finger

[permalink] [raw]
Subject: [PATCH for 3.19 3/3] rtlwifi: rtl8192ee: Fix several bugs

From: Troy Tan <[email protected]>

The following bugs are fixed in this driver:
1. Problems parsing C2H CMD
2. An ad-hoc connection can cause a TX freeze.
3. There are additional conditions that cause a TX freeze.
4. The previous code failed to handle situations where an RX
descriptor was unavailable.

Signed-off-by: Troy Tan <[email protected]>
Signed-off-by: Larry Finger <[email protected]>
---
drivers/net/wireless/rtlwifi/rtl8192ee/hw.c | 167 +++++++++++++++++++++----
drivers/net/wireless/rtlwifi/rtl8192ee/reg.h | 2 +
drivers/net/wireless/rtlwifi/rtl8192ee/sw.c | 3 +-
drivers/net/wireless/rtlwifi/rtl8192ee/trx.c | 175 +++++++++++----------------
drivers/net/wireless/rtlwifi/rtl8192ee/trx.h | 4 +-
5 files changed, 217 insertions(+), 134 deletions(-)

diff --git a/drivers/net/wireless/rtlwifi/rtl8192ee/hw.c b/drivers/net/wireless/rtlwifi/rtl8192ee/hw.c
index 47beb49..215b970 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ee/hw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192ee/hw.c
@@ -85,29 +85,6 @@ static void _rtl92ee_enable_bcn_sub_func(struct ieee80211_hw *hw)
_rtl92ee_set_bcn_ctrl_reg(hw, 0, BIT(1));
}

-static void _rtl92ee_return_beacon_queue_skb(struct ieee80211_hw *hw)
-{
- struct rtl_priv *rtlpriv = rtl_priv(hw);
- struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
- struct rtl8192_tx_ring *ring = &rtlpci->tx_ring[BEACON_QUEUE];
- unsigned long flags;
-
- spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags);
- while (skb_queue_len(&ring->queue)) {
- struct rtl_tx_buffer_desc *entry =
- &ring->buffer_desc[ring->idx];
- struct sk_buff *skb = __skb_dequeue(&ring->queue);
-
- pci_unmap_single(rtlpci->pdev,
- rtlpriv->cfg->ops->get_desc(
- (u8 *)entry, true, HW_DESC_TXBUFF_ADDR),
- skb->len, PCI_DMA_TODEVICE);
- kfree_skb(skb);
- ring->idx = (ring->idx + 1) % ring->entries;
- }
- spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags);
-}
-
static void _rtl92ee_disable_bcn_sub_func(struct ieee80211_hw *hw)
{
_rtl92ee_set_bcn_ctrl_reg(hw, BIT(1), 0);
@@ -403,9 +380,6 @@ static void _rtl92ee_download_rsvd_page(struct ieee80211_hw *hw)
rtl_write_byte(rtlpriv, REG_DWBCN0_CTRL + 2,
bcnvalid_reg | BIT(0));

- /* Return Beacon TCB */
- _rtl92ee_return_beacon_queue_skb(hw);
-
/* download rsvd page */
rtl92ee_set_fw_rsvdpagepkt(hw, false);

@@ -1163,6 +1137,140 @@ void rtl92ee_enable_hw_security_config(struct ieee80211_hw *hw)
rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_WPA_CONFIG, &sec_reg_value);
}

+static bool _rtl8192ee_check_pcie_dma_hang(struct rtl_priv *rtlpriv)
+{
+ u8 tmp;
+
+ /* write reg 0x350 Bit[26]=1. Enable debug port. */
+ tmp = rtl_read_byte(rtlpriv, REG_BACKDOOR_DBI_DATA + 3);
+ if (!(tmp & BIT(2))) {
+ rtl_write_byte(rtlpriv, REG_BACKDOOR_DBI_DATA + 3,
+ (tmp | BIT(2)));
+ mdelay(100); /* Suggested by DD Justin_tsai. */
+ }
+
+ /* read reg 0x350 Bit[25] if 1 : RX hang
+ * read reg 0x350 Bit[24] if 1 : TX hang
+ */
+ tmp = rtl_read_byte(rtlpriv, REG_BACKDOOR_DBI_DATA + 3);
+ if ((tmp & BIT(0)) || (tmp & BIT(1))) {
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+ "CheckPcieDMAHang8192EE(): true!!\n");
+ return true;
+ }
+ return false;
+}
+
+static void _rtl8192ee_reset_pcie_interface_dma(struct rtl_priv *rtlpriv,
+ bool mac_power_on)
+{
+ u8 tmp;
+ bool release_mac_rx_pause;
+ u8 backup_pcie_dma_pause;
+
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+ "ResetPcieInterfaceDMA8192EE()\n");
+
+ /* Revise Note: Follow the document "PCIe RX DMA Hang Reset Flow_v03"
+ * released by SD1 Alan.
+ * 2013.05.07, by tynli.
+ */
+
+ /* 1. disable register write lock
+ * write 0x1C bit[1:0] = 2'h0
+ * write 0xCC bit[2] = 1'b1
+ */
+ tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL);
+ tmp &= ~(BIT(1) | BIT(0));
+ rtl_write_byte(rtlpriv, REG_RSV_CTRL, tmp);
+ tmp = rtl_read_byte(rtlpriv, REG_PMC_DBG_CTRL2);
+ tmp |= BIT(2);
+ rtl_write_byte(rtlpriv, REG_PMC_DBG_CTRL2, tmp);
+
+ /* 2. Check and pause TRX DMA
+ * write 0x284 bit[18] = 1'b1
+ * write 0x301 = 0xFF
+ */
+ tmp = rtl_read_byte(rtlpriv, REG_RXDMA_CONTROL);
+ if (tmp & BIT(2)) {
+ /* Already pause before the function for another purpose. */
+ release_mac_rx_pause = false;
+ } else {
+ rtl_write_byte(rtlpriv, REG_RXDMA_CONTROL, (tmp | BIT(2)));
+ release_mac_rx_pause = true;
+ }
+
+ backup_pcie_dma_pause = rtl_read_byte(rtlpriv, REG_PCIE_CTRL_REG + 1);
+ if (backup_pcie_dma_pause != 0xFF)
+ rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG + 1, 0xFF);
+
+ if (mac_power_on) {
+ /* 3. reset TRX function
+ * write 0x100 = 0x00
+ */
+ rtl_write_byte(rtlpriv, REG_CR, 0);
+ }
+
+ /* 4. Reset PCIe DMA
+ * write 0x003 bit[0] = 0
+ */
+ tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
+ tmp &= ~(BIT(0));
+ rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, tmp);
+
+ /* 5. Enable PCIe DMA
+ * write 0x003 bit[0] = 1
+ */
+ tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
+ tmp |= BIT(0);
+ rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, tmp);
+
+ if (mac_power_on) {
+ /* 6. enable TRX function
+ * write 0x100 = 0xFF
+ */
+ rtl_write_byte(rtlpriv, REG_CR, 0xFF);
+
+ /* We should init LLT & RQPN and
+ * prepare Tx/Rx descrptor address later
+ * because MAC function is reset.
+ */
+ }
+
+ /* 7. Restore PCIe autoload down bit
+ * write 0xF8 bit[17] = 1'b1
+ */
+ tmp = rtl_read_byte(rtlpriv, REG_MAC_PHY_CTRL_NORMAL + 2);
+ tmp |= BIT(1);
+ rtl_write_byte(rtlpriv, REG_MAC_PHY_CTRL_NORMAL + 2, tmp);
+
+ /* In MAC power on state, BB and RF maybe in ON state,
+ * if we release TRx DMA here
+ * it will cause packets to be started to Tx/Rx,
+ * so we release Tx/Rx DMA later.
+ */
+ if (!mac_power_on) {
+ /* 8. release TRX DMA
+ * write 0x284 bit[18] = 1'b0
+ * write 0x301 = 0x00
+ */
+ if (release_mac_rx_pause) {
+ tmp = rtl_read_byte(rtlpriv, REG_RXDMA_CONTROL);
+ rtl_write_byte(rtlpriv, REG_RXDMA_CONTROL,
+ (tmp & (~BIT(2))));
+ }
+ rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG + 1,
+ backup_pcie_dma_pause);
+ }
+
+ /* 9. lock system register
+ * write 0xCC bit[2] = 1'b0
+ */
+ tmp = rtl_read_byte(rtlpriv, REG_PMC_DBG_CTRL2);
+ tmp &= ~(BIT(2));
+ rtl_write_byte(rtlpriv, REG_PMC_DBG_CTRL2, tmp);
+}
+
int rtl92ee_hw_init(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
@@ -1188,6 +1296,13 @@ int rtl92ee_hw_init(struct ieee80211_hw *hw)
rtlhal->fw_ps_state = FW_PS_STATE_ALL_ON_92E;
}

+ if (_rtl8192ee_check_pcie_dma_hang(rtlpriv)) {
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "92ee dma hang!\n");
+ _rtl8192ee_reset_pcie_interface_dma(rtlpriv,
+ rtlhal->mac_func_enable);
+ rtlhal->mac_func_enable = false;
+ }
+
rtstatus = _rtl92ee_init_mac(hw);

rtl_write_byte(rtlpriv, 0x577, 0x03);
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ee/reg.h b/drivers/net/wireless/rtlwifi/rtl8192ee/reg.h
index 3f2a959..696ae188 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ee/reg.h
+++ b/drivers/net/wireless/rtlwifi/rtl8192ee/reg.h
@@ -77,9 +77,11 @@
#define REG_HIMRE 0x00B8
#define REG_HISRE 0x00BC

+#define REG_PMC_DBG_CTRL2 0x00CC
#define REG_EFUSE_ACCESS 0x00CF
#define REG_HPON_FSM 0x00EC
#define REG_SYS_CFG1 0x00F0
+#define REG_MAC_PHY_CTRL_NORMAL 0x00F8
#define REG_SYS_CFG2 0x00FC

#define REG_CR 0x0100
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ee/sw.c b/drivers/net/wireless/rtlwifi/rtl8192ee/sw.c
index f30c916..100d6fc 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ee/sw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192ee/sw.c
@@ -114,8 +114,6 @@ int rtl92ee_init_sw_vars(struct ieee80211_hw *hw)
RCR_AMF |
RCR_ACF |
RCR_ADF |
- RCR_AICV |
- RCR_ACRC32 |
RCR_AB |
RCR_AM |
RCR_APM |
@@ -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,
.init_sw_leds = rtl92ee_init_sw_leds,
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ee/trx.c b/drivers/net/wireless/rtlwifi/rtl8192ee/trx.c
index 51806ac..ee1df82 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ee/trx.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192ee/trx.c
@@ -354,6 +354,11 @@ bool rtl92ee_rx_query_desc(struct ieee80211_hw *hw,
struct ieee80211_hdr *hdr;
u32 phystatus = GET_RX_DESC_PHYST(pdesc);

+ if (GET_RX_STATUS_DESC_RPT_SEL(pdesc) == 0)
+ status->packet_report_type = NORMAL_RX;
+ else
+ status->packet_report_type = C2H_PACKET;
+
status->length = (u16)GET_RX_DESC_PKT_LEN(pdesc);
status->rx_drvinfo_size = (u8)GET_RX_DESC_DRV_INFO_SIZE(pdesc) *
RX_DRV_INFO_SIZE_UNIT;
@@ -472,44 +477,22 @@ u16 rtl92ee_rx_desc_buff_remained_cnt(struct ieee80211_hw *hw, u8 queue_index)
{
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
struct rtl_priv *rtlpriv = rtl_priv(hw);
- u16 read_point = 0, write_point = 0, remind_cnt = 0;
- u32 tmp_4byte = 0;
- static u16 last_read_point;
- static bool start_rx;
-
- tmp_4byte = rtl_read_dword(rtlpriv, REG_RXQ_TXBD_IDX);
- read_point = (u16)((tmp_4byte>>16) & 0x7ff);
- write_point = (u16)(tmp_4byte & 0x7ff);
-
- if (write_point != rtlpci->rx_ring[queue_index].next_rx_rp) {
- RT_TRACE(rtlpriv, COMP_RXDESC, DBG_DMESG,
- "!!!write point is 0x%x, reg 0x3B4 value is 0x%x\n",
- write_point, tmp_4byte);
- tmp_4byte = rtl_read_dword(rtlpriv, REG_RXQ_TXBD_IDX);
- read_point = (u16)((tmp_4byte>>16) & 0x7ff);
- write_point = (u16)(tmp_4byte & 0x7ff);
- }
-
- if (read_point > 0)
- start_rx = true;
- if (!start_rx)
- return 0;
+ u16 desc_idx_hw = 0, desc_idx_host = 0, remind_cnt = 0;
+ u32 tmp_4byte = rtl_read_dword(rtlpriv, REG_RXQ_TXBD_IDX);
+ u32 rw_mask = 0x1ff;

- if ((last_read_point > (RX_DESC_NUM_92E / 2)) &&
- (read_point <= (RX_DESC_NUM_92E / 2))) {
- remind_cnt = RX_DESC_NUM_92E - write_point;
- } else {
- remind_cnt = (read_point >= write_point) ?
- (read_point - write_point) :
- (RX_DESC_NUM_92E - write_point + read_point);
- }
+ desc_idx_hw = (u16)((tmp_4byte>>16) & rw_mask);
+ desc_idx_host = (u16)(tmp_4byte & rw_mask);

- if (remind_cnt == 0)
+ /* may be no data, donot rx */
+ if (desc_idx_hw == desc_idx_host)
return 0;

- rtlpci->rx_ring[queue_index].next_rx_rp = write_point;
+ remind_cnt = (desc_idx_hw > desc_idx_host) ?
+ (desc_idx_hw - desc_idx_host) :
+ (RX_DESC_NUM_92E - (desc_idx_host - desc_idx_hw));

- last_read_point = read_point;
+ rtlpci->rx_ring[queue_index].next_rx_rp = desc_idx_host;
return remind_cnt;
}

@@ -551,7 +534,8 @@ 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)
+/*free desc that can be used */
+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);
@@ -561,15 +545,25 @@ void rtl92ee_get_available_desc(struct ieee80211_hw *hw, u8 q_idx)

tmp_4byte = rtl_read_dword(rtlpriv,
get_desc_addr_fr_q_idx(q_idx));
- current_tx_read_point = (u16)((tmp_4byte >> 16) & 0x0fff);
- current_tx_write_point = (u16)((tmp_4byte) & 0x0fff);
+ current_tx_read_point = (u16)((tmp_4byte >> 16) & 0x01ff);
+ current_tx_write_point = (u16)((tmp_4byte) & 0x01ff);
+
+ if (current_tx_read_point == current_tx_write_point)
+ point_diff = TX_DESC_NUM_92E - 1;
+ else if (current_tx_read_point < current_tx_write_point)
+ point_diff = TX_DESC_NUM_92E - (current_tx_write_point -
+ current_tx_read_point) - 1;
+ else
+ point_diff = current_tx_read_point - current_tx_write_point - 1;

- 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));
+ if (0 == point_diff) {
+ RT_TRACE(rtlpriv, COMP_SEND, DBG_DMESG,
+ "CR:%d,CW:%d\n",
+ current_tx_read_point, current_tx_write_point);
+ }

rtlpci->tx_ring[q_idx].avl_desc = point_diff;
+ return point_diff;
}

void rtl92ee_pre_fill_tx_bd_desc(struct ieee80211_hw *hw,
@@ -706,7 +700,7 @@ void rtl92ee_tx_fill_desc(struct ieee80211_hw *hw,
mapping = pci_map_single(rtlpci->pdev, skb->data, skb->len,
PCI_DMA_TODEVICE);
if (pci_dma_mapping_error(rtlpci->pdev, mapping)) {
- RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE,
+ RT_TRACE(rtlpriv, COMP_SEND, DBG_DMESG,
"DMA mapping error");
return;
}
@@ -870,7 +864,7 @@ void rtl92ee_tx_fill_cmddesc(struct ieee80211_hw *hw,
u8 txdesc_len = 40;

if (pci_dma_mapping_error(rtlpci->pdev, mapping)) {
- RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE,
+ RT_TRACE(rtlpriv, COMP_SEND, DBG_DMESG,
"DMA mapping error");
return;
}
@@ -918,8 +912,6 @@ void rtl92ee_set_desc(struct ieee80211_hw *hw, u8 *pdesc, bool istx,
struct rtl_priv *rtlpriv = rtl_priv(hw);
u16 cur_tx_rp = 0;
u16 cur_tx_wp = 0;
- static u16 last_txw_point;
- static bool over_run;
u32 tmp = 0;
u8 q_idx = *val;

@@ -932,6 +924,7 @@ void rtl92ee_set_desc(struct ieee80211_hw *hw, u8 *pdesc, bool istx,
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
struct rtl8192_tx_ring *ring = &rtlpci->tx_ring[q_idx];
u16 max_tx_desc = ring->entries;
+ u16 point_diff = 0;

if (q_idx == BEACON_QUEUE) {
ring->cur_tx_wp = 0;
@@ -940,44 +933,32 @@ void rtl92ee_set_desc(struct ieee80211_hw *hw, u8 *pdesc, bool istx,
return;
}

+ tmp = rtl_read_dword(rtlpriv,
+ get_desc_addr_fr_q_idx(q_idx));
+ cur_tx_rp = (u16)((tmp >> 16) & 0x0fff);
+ cur_tx_wp = (u16)(tmp & 0x0fff);
+
+ ring->cur_tx_wp = cur_tx_wp;
+ ring->cur_tx_rp = cur_tx_rp;
+ point_diff = ((cur_tx_rp > cur_tx_wp) ?
+ (cur_tx_rp - cur_tx_wp) :
+ (TX_DESC_NUM_92E - 1 -
+ cur_tx_wp + cur_tx_rp));
+
+ ring->avl_desc = point_diff;
+
ring->cur_tx_wp = ((ring->cur_tx_wp + 1) % max_tx_desc);

- if (over_run) {
- ring->cur_tx_wp = 0;
- over_run = false;
- }
- if (ring->avl_desc > 1) {
+ if (ring->avl_desc >= 1) {
ring->avl_desc--;
-
rtl_write_word(rtlpriv,
get_desc_addr_fr_q_idx(q_idx),
ring->cur_tx_wp);
-
- if (q_idx == 1)
- last_txw_point = cur_tx_wp;
- }
-
- if (ring->avl_desc < (max_tx_desc - 15)) {
- u16 point_diff = 0;
-
- tmp =
- rtl_read_dword(rtlpriv,
- get_desc_addr_fr_q_idx(q_idx));
- cur_tx_rp = (u16)((tmp >> 16) & 0x0fff);
- cur_tx_wp = (u16)(tmp & 0x0fff);
-
- ring->cur_tx_wp = cur_tx_wp;
- ring->cur_tx_rp = cur_tx_rp;
- point_diff = ((cur_tx_rp > cur_tx_wp) ?
- (cur_tx_rp - cur_tx_wp) :
- (TX_DESC_NUM_92E - 1 -
- cur_tx_wp + cur_tx_rp));
-
- ring->avl_desc = point_diff;
+ } else {
+ pr_err("critical error! ring->avl_desc == 0\n");
}
}
- break;
- }
+ break; }
} else {
switch (desc_name) {
case HW_DESC_RX_PREPARE:
@@ -1043,38 +1024,29 @@ bool rtl92ee_is_tx_desc_closed(struct ieee80211_hw *hw, u8 hw_queue, u16 index)
{
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
struct rtl_priv *rtlpriv = rtl_priv(hw);
- u16 read_point, write_point, available_desc_num;
+ u16 read_point, write_point;
bool ret = false;
- static u8 stop_report_cnt;
struct rtl8192_tx_ring *ring = &rtlpci->tx_ring[hw_queue];
+ u16 cur_tx_rp, cur_tx_wp;
+ u32 tmpu32 = 0;
+
+ tmpu32 = rtl_read_dword(rtlpriv,
+ get_desc_addr_fr_q_idx(hw_queue));
+ cur_tx_rp = (u16)((tmpu32 >> 16) & 0x01ff);
+ cur_tx_wp = (u16)(tmpu32 & 0x01ff);
+
+ ring->cur_tx_wp = cur_tx_wp;
+ ring->cur_tx_rp = cur_tx_rp;
+ ring->avl_desc = ((cur_tx_rp > cur_tx_wp) ? (cur_tx_rp - cur_tx_wp) :
+ (TX_DESC_NUM_92E - cur_tx_wp + cur_tx_rp));

- /*checking Read/Write Point each interrupt wastes CPU */
- if (stop_report_cnt > 15 || !rtlpriv->link_info.busytraffic) {
- u16 point_diff = 0;
- u16 cur_tx_rp, cur_tx_wp;
- u32 tmpu32 = 0;
-
- tmpu32 =
- rtl_read_dword(rtlpriv,
- get_desc_addr_fr_q_idx(hw_queue));
- cur_tx_rp = (u16)((tmpu32 >> 16) & 0x0fff);
- cur_tx_wp = (u16)(tmpu32 & 0x0fff);
-
- ring->cur_tx_wp = cur_tx_wp;
- ring->cur_tx_rp = cur_tx_rp;
- point_diff = ((cur_tx_rp > cur_tx_wp) ?
- (cur_tx_rp - cur_tx_wp) :
- (TX_DESC_NUM_92E - cur_tx_wp + cur_tx_rp));
-
- ring->avl_desc = point_diff;
- }

read_point = ring->cur_tx_rp;
write_point = ring->cur_tx_wp;
- available_desc_num = ring->avl_desc;
+

if (write_point > read_point) {
- if (index < write_point && index >= read_point)
+ if (index <= write_point && index >= read_point)
ret = false;
else
ret = true;
@@ -1095,13 +1067,6 @@ bool rtl92ee_is_tx_desc_closed(struct ieee80211_hw *hw, u8 hw_queue, u16 index)
rtlpriv->psc.rfoff_reason > RF_CHANGE_BY_PS)
ret = true;

- if (hw_queue < BEACON_QUEUE) {
- if (!ret)
- stop_report_cnt++;
- else
- stop_report_cnt = 0;
- }
-
return ret;
}

diff --git a/drivers/net/wireless/rtlwifi/rtl8192ee/trx.h b/drivers/net/wireless/rtlwifi/rtl8192ee/trx.h
index 45fd9db..8f78ac9 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ee/trx.h
+++ b/drivers/net/wireless/rtlwifi/rtl8192ee/trx.h
@@ -542,6 +542,8 @@
LE_BITS_TO_4BYTE(__pdesc+8, 12, 4)
#define GET_RX_DESC_RX_IS_QOS(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc+8, 16, 1)
+#define GET_RX_STATUS_DESC_RPT_SEL(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc+8, 28, 1)

#define GET_RX_DESC_RXMCS(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc+12, 0, 7)
@@ -829,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);
--
2.1.2


2015-01-15 12:03:24

by Kalle Valo

[permalink] [raw]
Subject: Re: [PATCH for 3.19 3/3] rtlwifi: rtl8192ee: Fix several bugs

谭杭波 <[email protected]> writes:

> I think a have located the bug reported, but the code
> seems so unclean, so after the bug fix I modified the code
> and tried to make it more easy to understand.

That's good, but I cannot send cleanup patches to 3.19. Even if the
cleanup fixes something. It's better to do bug fixes and cleanup in
separate patches.

--
Kalle Valo

2015-01-15 17:05:23

by Larry Finger

[permalink] [raw]
Subject: Re: [PATCH for 3.19 3/3] rtlwifi: rtl8192ee: Fix several bugs

On 01/15/2015 05:42 AM, Kalle Valo wrote:
> Larry Finger <[email protected]> writes:
>
>> From: Troy Tan <[email protected]>
>>
>> The following bugs are fixed in this driver:
>> 1. Problems parsing C2H CMD
>> 2. An ad-hoc connection can cause a TX freeze.
>> 3. There are additional conditions that cause a TX freeze.
>> 4. The previous code failed to handle situations where an RX
>> descriptor was unavailable.
>>
>> Signed-off-by: Troy Tan <[email protected]>
>> Signed-off-by: Larry Finger <[email protected]>
>
> Is this really so important that it should go to 3.19? A patch titled
> "Fix several bugs" immediately makes me cautious and then I look at the
> patch itself I see rewriting functions instead of simple bug fixes. From
> a quick look this looks more -next material than 3.19.

It is not a simple rewrite of functions. Tho mishandling of the descriptor ring
buffer locks up the device and requires a cold boot. These patches prevent that
from happening.

Yes, the patches are rather larger than I would like at the -rc4 stage, and I
defer to your judgement. At least we have an external source of corrected code
for users of 3.18 and 3.19.

Larry



2015-01-15 11:43:00

by Kalle Valo

[permalink] [raw]
Subject: Re: [PATCH for 3.19 3/3] rtlwifi: rtl8192ee: Fix several bugs

Larry Finger <[email protected]> writes:

> From: Troy Tan <[email protected]>
>
> The following bugs are fixed in this driver:
> 1. Problems parsing C2H CMD
> 2. An ad-hoc connection can cause a TX freeze.
> 3. There are additional conditions that cause a TX freeze.
> 4. The previous code failed to handle situations where an RX
> descriptor was unavailable.
>
> Signed-off-by: Troy Tan <[email protected]>
> Signed-off-by: Larry Finger <[email protected]>

Is this really so important that it should go to 3.19? A patch titled
"Fix several bugs" immediately makes me cautious and then I look at the
patch itself I see rewriting functions instead of simple bug fixes. From
a quick look this looks more -next material than 3.19.

--
Kalle Valo

2015-01-14 17:37:34

by Larry Finger

[permalink] [raw]
Subject: [PATCH for 3.19 1/3] rtlwifi: Remove logging statement that is no longer needed

In commit e9538cf4f907 ("rtlwifi: Fix error when accessing unmapped memory
in skb"), a printk was included to indicate that the condition had been
reached. There is now enough evidence from other users that the fix is
working. That logging statement can now be removed.

Signed-off-by: Larry Finger <[email protected]>
---
drivers/net/wireless/rtlwifi/pci.c | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/drivers/net/wireless/rtlwifi/pci.c b/drivers/net/wireless/rtlwifi/pci.c
index c70efb9..e25faac 100644
--- a/drivers/net/wireless/rtlwifi/pci.c
+++ b/drivers/net/wireless/rtlwifi/pci.c
@@ -816,11 +816,8 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw)

/* get a new skb - if fail, old one will be reused */
new_skb = dev_alloc_skb(rtlpci->rxbuffersize);
- if (unlikely(!new_skb)) {
- pr_err("Allocation of new skb failed in %s\n",
- __func__);
+ if (unlikely(!new_skb))
goto no_new;
- }
if (rtlpriv->use_new_trx_flow) {
buffer_desc =
&rtlpci->rx_ring[rxring_idx].buffer_desc
--
2.1.2


2015-01-14 17:37:40

by Larry Finger

[permalink] [raw]
Subject: [PATCH for 3.19 2/3] rtlwifi: Fix handling of new style descriptors

From: Troy Tan <[email protected]>

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.

Signed-off-by: Troy Tan <[email protected]>
Signed-off-by: Larry Finger <[email protected]>
---
drivers/net/wireless/rtlwifi/pci.c | 31 +++++++++++++++++++++++--------
drivers/net/wireless/rtlwifi/wifi.h | 1 +
2 files changed, 24 insertions(+), 8 deletions(-)

diff --git a/drivers/net/wireless/rtlwifi/pci.c b/drivers/net/wireless/rtlwifi/pci.c
index e25faac..a62170e 100644
--- 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 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) {
@@ -1685,6 +1691,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) {
diff --git a/drivers/net/wireless/rtlwifi/wifi.h b/drivers/net/wireless/rtlwifi/wifi.h
index 3b3453a..413c2ab 100644
--- a/drivers/net/wireless/rtlwifi/wifi.h
+++ b/drivers/net/wireless/rtlwifi/wifi.h
@@ -2172,6 +2172,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 {
--
2.1.2


2015-01-16 06:40:10

by Kalle Valo

[permalink] [raw]
Subject: Re: [PATCH for 3.19 2/3] rtlwifi: Fix handling of new style descriptors

Larry Finger <[email protected]> writes:

> Troy and I will try to prepare a patch that only fixes the bugs, and
> we will submit the cleanup for -next.

That's great, thank you.

--
Kalle Valo

2015-01-15 20:10:20

by Larry Finger

[permalink] [raw]
Subject: Re: [PATCH for 3.19 2/3] rtlwifi: Fix handling of new style descriptors

On 01/15/2015 06:00 AM, Kalle Valo wrote:
> Hi Troy,
>
> please avoid top-posting.
>
> 谭杭波 <[email protected]> writes:
>
>> You can find get_available_desc here:
>>
>> diff --git a/drivers/net/wireless/rtlwifi/pci.c b/drivers/net/wireless/rtlwifi/
>> pci.c
>> index e25faac..a62170e 100644
>> --- 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 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;
>> + }
>
> I don't see rtlpriv->cfg->ops->get_available_desc set here, only being
> called?

Kalle,

Troy and I will try to prepare a patch that only fixes the bugs, and we will
submit the cleanup for -next.

Sorry for the noise,

Larry



2015-01-15 12:00:59

by Kalle Valo

[permalink] [raw]
Subject: Re: [PATCH for 3.19 2/3] rtlwifi: Fix handling of new style descriptors

Hi Troy,

please avoid top-posting.

谭杭波 <[email protected]> writes:

> You can find get_available_desc here:
>
> diff --git a/drivers/net/wireless/rtlwifi/pci.c b/drivers/net/wireless/rtlwifi/
> pci.c
> index e25faac..a62170e 100644
> --- 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 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;
> + }

I don't see rtlpriv->cfg->ops->get_available_desc set here, only being
called?

--
Kalle Valo

2015-01-15 11:44:57

by Kalle Valo

[permalink] [raw]
Subject: Re: [PATCH for 3.19 2/3] rtlwifi: Fix handling of new style descriptors

Larry Finger <[email protected]> writes:

> From: Troy Tan <[email protected]>
>
> 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.
>
> Signed-off-by: Troy Tan <[email protected]>
> Signed-off-by: Larry Finger <[email protected]>

[...]

> --- a/drivers/net/wireless/rtlwifi/wifi.h
> +++ b/drivers/net/wireless/rtlwifi/wifi.h
> @@ -2172,6 +2172,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);

I don't see this op set anywhere within the patch. Is that correct or
did I miss something?

--
Kalle Valo