All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/6] Updates to rtlwifi family to match latest vendor version
@ 2012-08-21 15:00 Larry Finger
  2012-08-21 15:00 ` [PATCH 1/6] rtlwifi: rtl8192c: rtl8192de: Fix typo in cursta_connectctate Larry Finger
                   ` (5 more replies)
  0 siblings, 6 replies; 10+ messages in thread
From: Larry Finger @ 2012-08-21 15:00 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, Larry Finger, Li Chaoming

Realtek's latest driver for the PCI-based devices include many changes
that are ported to the in-kernel driver with this set of patches intended
for wireless-next.

Larry Finger (3):
  rtlwifi: rtl8192c: rtl8192de: Fix typo in cursta_connectctate
  rtlwifi: rtl8192c: rtl8192ce: rtl8192cu: rtl8192se: Remove sparse
    warnings
  rtlwifi: Update header file
Li Chaoming (3):
  rtlwifi: Add changes for new vendor driver version
  rtlwifi: rtl8192ce: Update for new vendor driver version
  rtlwifi: rtl8192se: Update driver for changes in 12/30/2011 vendor
    version

 drivers/net/wireless/rtlwifi/base.c               |  323 ++++++++++-
 drivers/net/wireless/rtlwifi/base.h               |   10 +-
 drivers/net/wireless/rtlwifi/cam.c                |    7 +-
 drivers/net/wireless/rtlwifi/core.c               |   76 ++-
 drivers/net/wireless/rtlwifi/debug.h              |    8 +
 drivers/net/wireless/rtlwifi/efuse.c              |   40 +-
 drivers/net/wireless/rtlwifi/efuse.h              |    1 -
 drivers/net/wireless/rtlwifi/pci.c                |  624 +++++++++++----------
 drivers/net/wireless/rtlwifi/pci.h                |    3 +
 drivers/net/wireless/rtlwifi/ps.c                 |   93 ++-
 drivers/net/wireless/rtlwifi/ps.h                 |    3 +-
 drivers/net/wireless/rtlwifi/rc.c                 |    3 +-
 drivers/net/wireless/rtlwifi/regd.c               |   18 +
 drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c |   41 +-
 drivers/net/wireless/rtlwifi/rtl8192ce/def.h      |   12 +-
 drivers/net/wireless/rtlwifi/rtl8192ce/hw.c       |  110 +++-
 drivers/net/wireless/rtlwifi/rtl8192ce/reg.h      |    1 +
 drivers/net/wireless/rtlwifi/rtl8192ce/sw.c       |    3 +-
 drivers/net/wireless/rtlwifi/rtl8192ce/trx.c      |   70 ++-
 drivers/net/wireless/rtlwifi/rtl8192cu/trx.c      |    2 +-
 drivers/net/wireless/rtlwifi/rtl8192de/dm.c       |   10 +-
 drivers/net/wireless/rtlwifi/rtl8192se/dm.c       |   91 +--
 drivers/net/wireless/rtlwifi/rtl8192se/fw.c       |    1 -
 drivers/net/wireless/rtlwifi/rtl8192se/hw.c       |   25 +-
 drivers/net/wireless/rtlwifi/rtl8192se/phy.c      |  353 ++++++------
 drivers/net/wireless/rtlwifi/rtl8192se/trx.c      |   17 +-
 drivers/net/wireless/rtlwifi/usb.c                |    2 +-
 drivers/net/wireless/rtlwifi/wifi.h               |  108 +++-
 28 files changed, 1412 insertions(+), 643 deletions(-)

-- 
1.7.10.4


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 1/6] rtlwifi: rtl8192c: rtl8192de: Fix typo in cursta_connectctate
  2012-08-21 15:00 [PATCH 0/6] Updates to rtlwifi family to match latest vendor version Larry Finger
@ 2012-08-21 15:00 ` Larry Finger
  2012-08-21 15:00 ` [PATCH 2/6] rtlwifi: rtl8192c: rtl8192ce: rtl8192cu: rtl8192se: Remove sparse warnings Larry Finger
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 10+ messages in thread
From: Larry Finger @ 2012-08-21 15:00 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, Larry Finger

Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net>
---
 drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c |   30 ++++++++++-----------
 drivers/net/wireless/rtlwifi/rtl8192de/dm.c       |   10 +++----
 drivers/net/wireless/rtlwifi/wifi.h               |    2 +-
 3 files changed, 21 insertions(+), 21 deletions(-)

diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c b/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c
index a45afda..2fd3b49 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c
@@ -167,7 +167,7 @@ static void rtl92c_dm_diginit(struct ieee80211_hw *hw)
 	dm_digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_MAX;
 	dm_digtable->cur_igvalue = 0x20;
 	dm_digtable->pre_igvalue = 0x0;
-	dm_digtable->cursta_connectctate = DIG_STA_DISCONNECT;
+	dm_digtable->cursta_connectstate = DIG_STA_DISCONNECT;
 	dm_digtable->presta_connectstate = DIG_STA_DISCONNECT;
 	dm_digtable->curmultista_connectstate = DIG_MULTISTA_DISCONNECT;
 	dm_digtable->rssi_lowthresh = DM_DIG_THRESH_LOW;
@@ -190,7 +190,7 @@ static u8 rtl92c_dm_initial_gain_min_pwdb(struct ieee80211_hw *hw)
 	long rssi_val_min = 0;
 
 	if ((dm_digtable->curmultista_connectstate == DIG_MULTISTA_CONNECT) &&
-	    (dm_digtable->cursta_connectctate == DIG_STA_CONNECT)) {
+	    (dm_digtable->cursta_connectstate == DIG_STA_CONNECT)) {
 		if (rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb != 0)
 			rssi_val_min =
 			    (rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb >
@@ -199,8 +199,8 @@ static u8 rtl92c_dm_initial_gain_min_pwdb(struct ieee80211_hw *hw)
 			    rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb;
 		else
 			rssi_val_min = rtlpriv->dm.undecorated_smoothed_pwdb;
-	} else if (dm_digtable->cursta_connectctate == DIG_STA_CONNECT ||
-		   dm_digtable->cursta_connectctate == DIG_STA_BEFORE_CONNECT) {
+	} else if (dm_digtable->cursta_connectstate == DIG_STA_CONNECT ||
+		   dm_digtable->cursta_connectstate == DIG_STA_BEFORE_CONNECT) {
 		rssi_val_min = rtlpriv->dm.undecorated_smoothed_pwdb;
 	} else if (dm_digtable->curmultista_connectstate ==
 		   DIG_MULTISTA_CONNECT) {
@@ -334,7 +334,7 @@ static void rtl92c_dm_initial_gain_multi_sta(struct ieee80211_hw *hw)
 		multi_sta = true;
 
 	if (!multi_sta ||
-	    dm_digtable->cursta_connectctate != DIG_STA_DISCONNECT) {
+	    dm_digtable->cursta_connectstate != DIG_STA_DISCONNECT) {
 		initialized = false;
 		dm_digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_MAX;
 		return;
@@ -378,15 +378,15 @@ static void rtl92c_dm_initial_gain_sta(struct ieee80211_hw *hw)
 	struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
 
 	RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE,
-		 "presta_connectstate = %x, cursta_connectctate = %x\n",
+		 "presta_connectstate = %x, cursta_connectstate = %x\n",
 		 dm_digtable->presta_connectstate,
-		 dm_digtable->cursta_connectctate);
+		 dm_digtable->cursta_connectstate);
 
-	if (dm_digtable->presta_connectstate == dm_digtable->cursta_connectctate
-	    || dm_digtable->cursta_connectctate == DIG_STA_BEFORE_CONNECT
-	    || dm_digtable->cursta_connectctate == DIG_STA_CONNECT) {
+	if (dm_digtable->presta_connectstate == dm_digtable->cursta_connectstate
+	    || dm_digtable->cursta_connectstate == DIG_STA_BEFORE_CONNECT
+	    || dm_digtable->cursta_connectstate == DIG_STA_CONNECT) {
 
-		if (dm_digtable->cursta_connectctate != DIG_STA_DISCONNECT) {
+		if (dm_digtable->cursta_connectstate != DIG_STA_DISCONNECT) {
 			dm_digtable->rssi_val_min =
 			    rtl92c_dm_initial_gain_min_pwdb(hw);
 			rtl92c_dm_ctrl_initgain_by_rssi(hw);
@@ -407,7 +407,7 @@ static void rtl92c_dm_cck_packet_detection_thresh(struct ieee80211_hw *hw)
 	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
 	struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
 
-	if (dm_digtable->cursta_connectctate == DIG_STA_CONNECT) {
+	if (dm_digtable->cursta_connectstate == DIG_STA_CONNECT) {
 		dm_digtable->rssi_val_min = rtl92c_dm_initial_gain_min_pwdb(hw);
 
 		if (dm_digtable->pre_cck_pd_state == CCK_PD_STAGE_LowRssi) {
@@ -484,15 +484,15 @@ static void rtl92c_dm_ctrl_initgain_by_twoport(struct ieee80211_hw *hw)
 		return;
 
 	if (mac->link_state >= MAC80211_LINKED)
-		dm_digtable->cursta_connectctate = DIG_STA_CONNECT;
+		dm_digtable->cursta_connectstate = DIG_STA_CONNECT;
 	else
-		dm_digtable->cursta_connectctate = DIG_STA_DISCONNECT;
+		dm_digtable->cursta_connectstate = DIG_STA_DISCONNECT;
 
 	rtl92c_dm_initial_gain_sta(hw);
 	rtl92c_dm_initial_gain_multi_sta(hw);
 	rtl92c_dm_cck_packet_detection_thresh(hw);
 
-	dm_digtable->presta_connectstate = dm_digtable->cursta_connectctate;
+	dm_digtable->presta_connectstate = dm_digtable->cursta_connectstate;
 
 }
 
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/dm.c b/drivers/net/wireless/rtlwifi/rtl8192de/dm.c
index c0201ed..ed868c3 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192de/dm.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192de/dm.c
@@ -164,7 +164,7 @@ static void rtl92d_dm_diginit(struct ieee80211_hw *hw)
 	de_digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_MAX;
 	de_digtable->cur_igvalue = 0x20;
 	de_digtable->pre_igvalue = 0x0;
-	de_digtable->cursta_connectctate = DIG_STA_DISCONNECT;
+	de_digtable->cursta_connectstate = DIG_STA_DISCONNECT;
 	de_digtable->presta_connectstate = DIG_STA_DISCONNECT;
 	de_digtable->curmultista_connectstate = DIG_MULTISTA_DISCONNECT;
 	de_digtable->rssi_lowthresh = DM_DIG_THRESH_LOW;
@@ -310,7 +310,7 @@ static void rtl92d_dm_cck_packet_detection_thresh(struct ieee80211_hw *hw)
 	struct dig_t *de_digtable = &rtlpriv->dm_digtable;
 	unsigned long flag = 0;
 
-	if (de_digtable->cursta_connectctate == DIG_STA_CONNECT) {
+	if (de_digtable->cursta_connectstate == DIG_STA_CONNECT) {
 		if (de_digtable->pre_cck_pd_state == CCK_PD_STAGE_LOWRSSI) {
 			if (de_digtable->min_undecorated_pwdb_for_dm <= 25)
 				de_digtable->cur_cck_pd_state =
@@ -342,7 +342,7 @@ static void rtl92d_dm_cck_packet_detection_thresh(struct ieee80211_hw *hw)
 		de_digtable->pre_cck_pd_state = de_digtable->cur_cck_pd_state;
 	}
 	RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, "CurSTAConnectState=%s\n",
-		 de_digtable->cursta_connectctate == DIG_STA_CONNECT ?
+		 de_digtable->cursta_connectstate == DIG_STA_CONNECT ?
 		 "DIG_STA_CONNECT " : "DIG_STA_DISCONNECT");
 	RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, "CCKPDStage=%s\n",
 		 de_digtable->cur_cck_pd_state == CCK_PD_STAGE_LOWRSSI ?
@@ -428,9 +428,9 @@ static void rtl92d_dm_dig(struct ieee80211_hw *hw)
 	RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, "progress\n");
 	/* Decide the current status and if modify initial gain or not */
 	if (rtlpriv->mac80211.link_state >= MAC80211_LINKED)
-		de_digtable->cursta_connectctate = DIG_STA_CONNECT;
+		de_digtable->cursta_connectstate = DIG_STA_CONNECT;
 	else
-		de_digtable->cursta_connectctate = DIG_STA_DISCONNECT;
+		de_digtable->cursta_connectstate = DIG_STA_DISCONNECT;
 
 	/* adjust initial gain according to false alarm counter */
 	if (falsealm_cnt->cnt_all < DM_DIG_FA_TH0)
diff --git a/drivers/net/wireless/rtlwifi/wifi.h b/drivers/net/wireless/rtlwifi/wifi.h
index cdaa21f..3ae43f9 100644
--- a/drivers/net/wireless/rtlwifi/wifi.h
+++ b/drivers/net/wireless/rtlwifi/wifi.h
@@ -1619,7 +1619,7 @@ struct dig_t {
 	u8 dig_twoport_algorithm;
 	u8 dig_dbgmode;
 	u8 dig_slgorithm_switch;
-	u8 cursta_connectctate;
+	u8 cursta_connectstate;
 	u8 presta_connectstate;
 	u8 curmultista_connectstate;
 	char backoff_val;
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 2/6] rtlwifi: rtl8192c: rtl8192ce: rtl8192cu: rtl8192se: Remove sparse warnings
  2012-08-21 15:00 [PATCH 0/6] Updates to rtlwifi family to match latest vendor version Larry Finger
  2012-08-21 15:00 ` [PATCH 1/6] rtlwifi: rtl8192c: rtl8192de: Fix typo in cursta_connectctate Larry Finger
@ 2012-08-21 15:00 ` Larry Finger
  2012-08-21 15:00 ` [PATCH 3/6] rtlwifi: Update header file Larry Finger
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 10+ messages in thread
From: Larry Finger @ 2012-08-21 15:00 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, Larry Finger

The rtlwifi family of drivers has the following sparse errors:

  CHECK   drivers/net/wireless/rtlwifi/usb.c
drivers/net/wireless/rtlwifi/usb.c:122:17: warning: cast to restricted __le32
  CHECK   drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c
drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c:1157:13: warning: context imbalance in 'rtl92c_dm_refresh_rate_adaptive_mask' - different lock contexts for basic block
  CHECK   drivers/net/wireless/rtlwifi/rtl8192ce/hw.c
drivers/net/wireless/rtlwifi/rtl8192ce/hw.c:1909:30: warning: cast to restricted __le32
  CHECK   drivers/net/wireless/rtlwifi/rtl8192ce/sw.c
drivers/net/wireless/rtlwifi/rtl8192ce/sw.c:345:1: warning: symbol 'rtl92ce_pci_ids' was not declared. Should it be static?
  CHECK   drivers/net/wireless/rtlwifi/rtl8192cu/trx.c
drivers/net/wireless/rtlwifi/rtl8192cu/trx.c:494:9: warning: cast from restricted __le16
  CHECK   drivers/net/wireless/rtlwifi/rtl8192se/fw.c
drivers/net/wireless/rtlwifi/rtl8192se/fw.c:490:17: warning: cast to restricted __le32
drivers/net/wireless/rtlwifi/rtl8192se/fw.c:490:17: warning: cast to restricted __le32
drivers/net/wireless/rtlwifi/rtl8192se/fw.c:494:17: warning: cast to restricted __le32
drivers/net/wireless/rtlwifi/rtl8192se/fw.c:494:17: warning: cast to restricted __le32
drivers/net/wireless/rtlwifi/rtl8192se/fw.c:499:17: warning: cast to restricted __le32
drivers/net/wireless/rtlwifi/rtl8192se/fw.c:499:17: warning: cast to restricted __le32
drivers/net/wireless/rtlwifi/rtl8192se/fw.c:510:25: warning: cast to restricted __le32
drivers/net/wireless/rtlwifi/rtl8192se/fw.c:510:25: warning: cast to restricted __le32
drivers/net/wireless/rtlwifi/rtl8192se/fw.c:607:9: warning: cast to restricted __le16
drivers/net/wireless/rtlwifi/rtl8192se/fw.c:607:9: warning: cast to restricted __le16
drivers/net/wireless/rtlwifi/rtl8192se/fw.c:650:9: warning: cast to restricted __le16
drivers/net/wireless/rtlwifi/rtl8192se/fw.c:650:9: warning: cast to restricted __le16
drivers/net/wireless/rtlwifi/rtl8192se/fw.c:652:9: warning: cast to restricted __le16
drivers/net/wireless/rtlwifi/rtl8192se/fw.c:652:9: warning: cast to restricted __le16
  CHECK   drivers/net/wireless/rtlwifi/rtl8192se/trx.c
drivers/net/wireless/rtlwifi/rtl8192se/trx.c:758:9: warning: cast from restricted __le32
drivers/net/wireless/rtlwifi/rtl8192se/trx.c:788:17: warning: cast from restricted __le32
drivers/net/wireless/rtlwifi/rtl8192se/trx.c:804:17: warning: cast to restricted __le32
drivers/net/wireless/rtlwifi/rtl8192se/trx.c:804:17: warning: cast to restricted __le32
drivers/net/wireless/rtlwifi/rtl8192se/trx.c:807:17: warning: cast from restricted __le32

Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net>
---
 drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c |   11 +++--------
 drivers/net/wireless/rtlwifi/rtl8192ce/hw.c       |    4 ++--
 drivers/net/wireless/rtlwifi/rtl8192ce/sw.c       |    2 +-
 drivers/net/wireless/rtlwifi/rtl8192cu/trx.c      |    2 +-
 drivers/net/wireless/rtlwifi/rtl8192se/trx.c      |    6 +++---
 drivers/net/wireless/rtlwifi/usb.c                |    2 +-
 drivers/net/wireless/rtlwifi/wifi.h               |   14 +++++++-------
 7 files changed, 18 insertions(+), 23 deletions(-)

diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c b/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c
index 2fd3b49..1ca4e25 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c
@@ -1214,18 +1214,13 @@ static void rtl92c_dm_refresh_rate_adaptive_mask(struct ieee80211_hw *hw)
 				 "PreState = %d, CurState = %d\n",
 				 p_ra->pre_ratr_state, p_ra->ratr_state);
 
-			/* Only the PCI card uses sta in the update rate table
-			 * callback routine */
-			if (rtlhal->interface == INTF_PCI) {
-				rcu_read_lock();
-				sta = ieee80211_find_sta(mac->vif, mac->bssid);
-			}
+			rcu_read_lock();
+			sta = ieee80211_find_sta(mac->vif, mac->bssid);
 			rtlpriv->cfg->ops->update_rate_tbl(hw, sta,
 					p_ra->ratr_state);
 
 			p_ra->pre_ratr_state = p_ra->ratr_state;
-			if (rtlhal->interface == INTF_PCI)
-				rcu_read_unlock();
+			rcu_read_unlock();
 		}
 	}
 }
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c b/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c
index bd0da7e..cc89582 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c
@@ -1906,8 +1906,8 @@ static void rtl92ce_update_hal_rate_mask(struct ieee80211_hw *hw,
 	}
 	RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG,
 		 "ratr_bitmap :%x\n", ratr_bitmap);
-	*(u32 *)&rate_mask = EF4BYTE((ratr_bitmap & 0x0fffffff) |
-				     (ratr_index << 28));
+	*(u32 *)&rate_mask = (ratr_bitmap & 0x0fffffff) |
+				     (ratr_index << 28);
 	rate_mask[4] = macid | (shortgi ? 0x20 : 0x00) | 0x80;
 	RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG,
 		 "Rate_index:%x, ratr_val:%x, %x:%x:%x:%x:%x\n",
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c b/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c
index 3aa927f..60451ee 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c
@@ -342,7 +342,7 @@ static struct rtl_hal_cfg rtl92ce_hal_cfg = {
 	.maps[RTL_RC_HT_RATEMCS15] = DESC92_RATEMCS15,
 };
 
-DEFINE_PCI_DEVICE_TABLE(rtl92ce_pci_ids) = {
+static DEFINE_PCI_DEVICE_TABLE(rtl92ce_pci_ids) = {
 	{RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8191, rtl92ce_hal_cfg)},
 	{RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8178, rtl92ce_hal_cfg)},
 	{RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8177, rtl92ce_hal_cfg)},
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c b/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c
index 2e6eb35..bb51f8c 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c
@@ -491,7 +491,7 @@ static void _rtl_tx_desc_checksum(u8 *txdesc)
 	SET_TX_DESC_TX_DESC_CHECKSUM(txdesc, 0);
 	for (index = 0; index < 16; index++)
 		checksum = checksum ^ (*(ptr + index));
-	SET_TX_DESC_TX_DESC_CHECKSUM(txdesc, cpu_to_le16(checksum));
+	SET_TX_DESC_TX_DESC_CHECKSUM(txdesc, checksum);
 }
 
 void rtl92cu_tx_fill_desc(struct ieee80211_hw *hw,
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/trx.c b/drivers/net/wireless/rtlwifi/rtl8192se/trx.c
index 36d1cb3..e67b338 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/trx.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192se/trx.c
@@ -755,7 +755,7 @@ void rtl92se_tx_fill_desc(struct ieee80211_hw *hw,
 	SET_TX_DESC_TX_BUFFER_SIZE(pdesc, (u16) skb->len);
 
 	/* DOWRD 8 */
-	SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, cpu_to_le32(mapping));
+	SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, mapping);
 
 	RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, "\n");
 }
@@ -785,7 +785,7 @@ void rtl92se_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc,
 		/* 92SE need not to set TX packet size when firmware download */
 		SET_TX_DESC_PKT_SIZE(pdesc, (u16)(skb->len));
 		SET_TX_DESC_TX_BUFFER_SIZE(pdesc, (u16)(skb->len));
-		SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, cpu_to_le32(mapping));
+		SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, mapping);
 
 		wmb();
 		SET_TX_DESC_OWN(pdesc, 1);
@@ -804,7 +804,7 @@ void rtl92se_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc,
 		SET_BITS_TO_LE_4BYTE(skb->data, 24, 7, rtlhal->h2c_txcmd_seq);
 
 		SET_TX_DESC_TX_BUFFER_SIZE(pdesc, (u16)(skb->len));
-		SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, cpu_to_le32(mapping));
+		SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, mapping);
 
 		wmb();
 		SET_TX_DESC_OWN(pdesc, 1);
diff --git a/drivers/net/wireless/rtlwifi/usb.c b/drivers/net/wireless/rtlwifi/usb.c
index aa970fc..1dc758e 100644
--- a/drivers/net/wireless/rtlwifi/usb.c
+++ b/drivers/net/wireless/rtlwifi/usb.c
@@ -120,7 +120,7 @@ static int _usbctrl_vendorreq_sync_read(struct usb_device *udev, u8 request,
 
 	if (status < 0 && count++ < 4)
 		pr_err("reg 0x%x, usbctrl_vendorreq TimeOut! status:0x%x value=0x%x\n",
-		       value, status, le32_to_cpu(*(u32 *)pdata));
+		       value, status, *(u32 *)pdata);
 	return status;
 }
 
diff --git a/drivers/net/wireless/rtlwifi/wifi.h b/drivers/net/wireless/rtlwifi/wifi.h
index 3ae43f9..51da6de 100644
--- a/drivers/net/wireless/rtlwifi/wifi.h
+++ b/drivers/net/wireless/rtlwifi/wifi.h
@@ -1815,9 +1815,9 @@ struct bt_coexist_info {
 	EF1BYTE(*((u8 *)(_ptr)))
 /* Read le16 data from memory and convert to host ordering */
 #define READEF2BYTE(_ptr)	\
-	EF2BYTE(*((u16 *)(_ptr)))
+	EF2BYTE(*(_ptr))
 #define READEF4BYTE(_ptr)	\
-	EF4BYTE(*((u32 *)(_ptr)))
+	EF4BYTE(*(_ptr))
 
 /* Write data to memory */
 #define WRITEEF1BYTE(_ptr, _val)	\
@@ -1826,7 +1826,7 @@ struct bt_coexist_info {
 #define WRITEEF2BYTE(_ptr, _val)	\
 	(*((u16 *)(_ptr))) = EF2BYTE(_val)
 #define WRITEEF4BYTE(_ptr, _val)	\
-	(*((u16 *)(_ptr))) = EF2BYTE(_val)
+	(*((u32 *)(_ptr))) = EF2BYTE(_val)
 
 /* Create a bit mask
  * Examples:
@@ -1859,9 +1859,9 @@ struct bt_coexist_info {
  * 4-byte pointer in little-endian system.
  */
 #define LE_P4BYTE_TO_HOST_4BYTE(__pstart) \
-	(EF4BYTE(*((u32 *)(__pstart))))
+	(EF4BYTE(*((__le32 *)(__pstart))))
 #define LE_P2BYTE_TO_HOST_2BYTE(__pstart) \
-	(EF2BYTE(*((u16 *)(__pstart))))
+	(EF2BYTE(*((__le16 *)(__pstart))))
 #define LE_P1BYTE_TO_HOST_1BYTE(__pstart) \
 	(EF1BYTE(*((u8 *)(__pstart))))
 
@@ -1908,13 +1908,13 @@ value to host byte ordering.*/
  * Set subfield of little-endian 4-byte value to specified value.
  */
 #define SET_BITS_TO_LE_4BYTE(__pstart, __bitoffset, __bitlen, __val) \
-	*((u32 *)(__pstart)) = EF4BYTE \
+	*((u32 *)(__pstart)) = \
 	( \
 		LE_BITS_CLEARED_TO_4BYTE(__pstart, __bitoffset, __bitlen) | \
 		((((u32)__val) & BIT_LEN_MASK_32(__bitlen)) << (__bitoffset)) \
 	);
 #define SET_BITS_TO_LE_2BYTE(__pstart, __bitoffset, __bitlen, __val) \
-	*((u16 *)(__pstart)) = EF2BYTE \
+	*((u16 *)(__pstart)) = \
 	( \
 		LE_BITS_CLEARED_TO_2BYTE(__pstart, __bitoffset, __bitlen) | \
 		((((u16)__val) & BIT_LEN_MASK_16(__bitlen)) << (__bitoffset)) \
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 3/6] rtlwifi: Update header file
  2012-08-21 15:00 [PATCH 0/6] Updates to rtlwifi family to match latest vendor version Larry Finger
  2012-08-21 15:00 ` [PATCH 1/6] rtlwifi: rtl8192c: rtl8192de: Fix typo in cursta_connectctate Larry Finger
  2012-08-21 15:00 ` [PATCH 2/6] rtlwifi: rtl8192c: rtl8192ce: rtl8192cu: rtl8192se: Remove sparse warnings Larry Finger
@ 2012-08-21 15:00 ` Larry Finger
  2012-08-21 15:00 ` [PATCH 4/6] rtlwifi: Add changes for new vendor driver version Larry Finger
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 10+ messages in thread
From: Larry Finger @ 2012-08-21 15:00 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, Larry Finger

The latest version of the vendor driver for the rtlwifi family
includes many changes. This patch incorporates the difference
in the main header file. Many of the changes are in preparation
for adding a new driver for the RTL8723AE device.

Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net>
---
 drivers/net/wireless/rtlwifi/wifi.h |   92 ++++++++++++++++++++++++++++++++++-
 1 file changed, 91 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/rtlwifi/wifi.h b/drivers/net/wireless/rtlwifi/wifi.h
index 51da6de..ec33cde 100644
--- a/drivers/net/wireless/rtlwifi/wifi.h
+++ b/drivers/net/wireless/rtlwifi/wifi.h
@@ -135,7 +135,7 @@ enum hardware_type {
 	HARDWARE_TYPE_RTL8192CU,
 	HARDWARE_TYPE_RTL8192DE,
 	HARDWARE_TYPE_RTL8192DU,
-	HARDWARE_TYPE_RTL8723E,
+	HARDWARE_TYPE_RTL8723AE,
 	HARDWARE_TYPE_RTL8723U,
 
 	/* keep it last */
@@ -389,6 +389,7 @@ enum rt_enc_alg {
 	RSERVED_ENCRYPTION = 3,
 	AESCCMP_ENCRYPTION = 4,
 	WEP104_ENCRYPTION = 5,
+	AESCMAC_ENCRYPTION = 6,	/*IEEE802.11w */
 };
 
 enum rtl_hal_state {
@@ -873,6 +874,7 @@ struct rtl_phy {
 	u32 adda_backup[16];
 	u32 iqk_mac_backup[IQK_MAC_REG_NUM];
 	u32 iqk_bb_backup[10];
+	bool iqk_initialized;
 
 	/* Dual mac */
 	bool need_iqk;
@@ -910,6 +912,8 @@ struct rtl_phy {
 #define RTL_AGG_OPERATIONAL			3
 #define RTL_AGG_OFF				0
 #define RTL_AGG_ON				1
+#define RTL_RX_AGG_START			1
+#define RTL_RX_AGG_STOP				0
 #define RTL_AGG_EMPTYING_HW_QUEUE_ADDBA		2
 #define RTL_AGG_EMPTYING_HW_QUEUE_DELBA		3
 
@@ -920,6 +924,7 @@ struct rtl_ht_agg {
 	u64 bitmap;
 	u32 rate_n_flags;
 	u8 agg_state;
+	u8 rx_agg_state;
 };
 
 struct rtl_tid_data {
@@ -927,11 +932,19 @@ struct rtl_tid_data {
 	struct rtl_ht_agg agg;
 };
 
+struct rssi_sta {
+	long undecorated_smoothed_pwdb;
+};
+
 struct rtl_sta_info {
+	struct list_head list;
 	u8 ratr_index;
 	u8 wireless_mode;
 	u8 mimo_ps;
 	struct rtl_tid_data tids[MAX_TID_COUNT];
+
+	/* just used for ap adhoc or mesh*/
+	struct rssi_sta rssi_stat;
 } __packed;
 
 struct rtl_priv;
@@ -1034,6 +1047,11 @@ struct rtl_mac {
 struct rtl_hal {
 	struct ieee80211_hw *hw;
 
+	bool up_first_time;
+	bool first_init;
+	bool being_init_adapter;
+	bool bbrf_ready;
+
 	enum intf_type interface;
 	u16 hw_type;		/*92c or 92d or 92s and so on */
 	u8 ic_class;
@@ -1048,6 +1066,7 @@ struct rtl_hal {
 	u16 fw_subversion;
 	bool h2c_setinprogress;
 	u8 last_hmeboxnum;
+	bool fw_ready;
 	/*Reserve page start offset except beacon in TxQ. */
 	u8 fw_rsvdpage_startoffset;
 	u8 h2c_txcmd_seq;
@@ -1083,6 +1102,8 @@ struct rtl_hal {
 	bool load_imrandiqk_setting_for2g;
 
 	bool disable_amsdu_8k;
+	bool master_of_dmsp;
+	bool slave_of_dmsp;
 };
 
 struct rtl_security {
@@ -1144,6 +1165,9 @@ struct rtl_dm {
 	bool disable_tx_int;
 	char ofdm_index[2];
 	char cck_index;
+
+	/* DMSP */
+	bool supp_phymode_switch;
 };
 
 #define	EFUSE_MAX_LOGICAL_SIZE			256
@@ -1337,6 +1361,10 @@ struct rtl_stats {
 };
 
 struct rt_link_detect {
+	/* count for roaming */
+	u32 bcn_rx_inperiod;
+	u32 roam_times;
+
 	u32 num_tx_in4period[4];
 	u32 num_rx_in4period[4];
 
@@ -1344,6 +1372,8 @@ struct rt_link_detect {
 	u32 num_rx_inperiod;
 
 	bool busytraffic;
+	bool tx_busy_traffic;
+	bool rx_busy_traffic;
 	bool higher_busytraffic;
 	bool higher_busyrxtraffic;
 
@@ -1454,7 +1484,12 @@ struct rtl_hal_ops {
 			  u32 regaddr, u32 bitmask);
 	void (*set_rfreg) (struct ieee80211_hw *hw, enum radio_path rfpath,
 			   u32 regaddr, u32 bitmask, u32 data);
+	void (*allow_all_destaddr)(struct ieee80211_hw *hw,
+		bool allow_all_da, bool write_into_reg);
 	void (*linked_set_reg) (struct ieee80211_hw *hw);
+	void (*check_switch_to_dmdp) (struct ieee80211_hw *hw);
+	void (*dualmac_easy_concurrent) (struct ieee80211_hw *hw);
+	void (*dualmac_switch_to_dmdp) (struct ieee80211_hw *hw);
 	bool (*phy_rf6052_config) (struct ieee80211_hw *hw);
 	void (*phy_rf6052_set_cck_txpower) (struct ieee80211_hw *hw,
 					    u8 *powerlevel);
@@ -1474,6 +1509,8 @@ struct rtl_intf_ops {
 	void (*read_efuse_byte)(struct ieee80211_hw *hw, u16 _offset, u8 *pbuf);
 	int (*adapter_start) (struct ieee80211_hw *hw);
 	void (*adapter_stop) (struct ieee80211_hw *hw);
+	bool (*check_buddy_priv)(struct ieee80211_hw *hw,
+				 struct rtl_priv **buddy_priv);
 
 	int (*adapter_tx) (struct ieee80211_hw *hw, struct sk_buff *skb,
 			struct rtl_tcb_desc *ptcb_desc);
@@ -1554,11 +1591,16 @@ struct rtl_locks {
 	spinlock_t h2c_lock;
 	spinlock_t rf_ps_lock;
 	spinlock_t rf_lock;
+	spinlock_t lps_lock;
 	spinlock_t waitq_lock;
+	spinlock_t entry_list_lock;
 	spinlock_t usb_lock;
 
 	/*Dual mac*/
 	spinlock_t cck_and_rw_pagea_lock;
+
+	/*Easy concurrent*/
+	spinlock_t check_sendpkt_lock;
 };
 
 struct rtl_works {
@@ -1566,6 +1608,7 @@ struct rtl_works {
 
 	/*timer */
 	struct timer_list watchdog_timer;
+	struct timer_list dualmac_easyconcurrent_retrytimer;
 
 	/*task */
 	struct tasklet_struct irq_tasklet;
@@ -1593,6 +1636,31 @@ struct rtl_debug {
 	char proc_name[20];
 };
 
+#define MIMO_PS_STATIC			0
+#define MIMO_PS_DYNAMIC			1
+#define MIMO_PS_NOLIMIT			3
+
+struct rtl_dualmac_easy_concurrent_ctl {
+	enum band_type currentbandtype_backfordmdp;
+	bool close_bbandrf_for_dmsp;
+	bool change_to_dmdp;
+	bool change_to_dmsp;
+	bool switch_in_process;
+};
+
+struct rtl_dmsp_ctl {
+	bool activescan_for_slaveofdmsp;
+	bool scan_for_anothermac_fordmsp;
+	bool scan_for_itself_fordmsp;
+	bool writedig_for_anothermacofdmsp;
+	u32 curdigvalue_for_anothermacofdmsp;
+	bool changecckpdstate_for_anothermacofdmsp;
+	u8 curcckpdstate_for_anothermacofdmsp;
+	bool changetxhighpowerlvl_for_anothermacofdmsp;
+	u8 curtxhighlvl_for_anothermacofdmsp;
+	long rssivalmin_for_anothermacofdmsp;
+};
+
 struct ps_t {
 	u8 pre_ccastate;
 	u8 cur_ccasate;
@@ -1652,8 +1720,20 @@ struct dig_t {
 	char backoffval_range_min;
 };
 
+struct rtl_global_var {
+	/* from this list we can get
+	 * other adapter's rtl_priv */
+	struct list_head glb_priv_list;
+	spinlock_t glb_list_lock;
+};
+
 struct rtl_priv {
 	struct completion firmware_loading_complete;
+	struct list_head list;
+	struct rtl_priv *buddy_priv;
+	struct rtl_global_var *glb_var;
+	struct rtl_dualmac_easy_concurrent_ctl easy_concurrent_ctl;
+	struct rtl_dmsp_ctl dmsp_ctl;
 	struct rtl_locks locks;
 	struct rtl_works works;
 	struct rtl_mac mac80211;
@@ -1674,6 +1754,9 @@ struct rtl_priv {
 
 	struct rtl_rate_priv *rate_priv;
 
+	/* sta entry list for ap adhoc or mesh */
+	struct list_head entry_list;
+
 	struct rtl_debug dbg;
 	int max_fw_size;
 
@@ -2100,4 +2183,11 @@ static inline struct ieee80211_sta *get_sta(struct ieee80211_hw *hw,
 	return ieee80211_find_sta(vif, bssid);
 }
 
+static inline struct ieee80211_sta *rtl_find_sta(struct ieee80211_hw *hw,
+		u8 *mac_addr)
+{
+	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+	return ieee80211_find_sta(mac->vif, mac_addr);
+}
+
 #endif
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 4/6] rtlwifi: Add changes for new vendor driver version
  2012-08-21 15:00 [PATCH 0/6] Updates to rtlwifi family to match latest vendor version Larry Finger
                   ` (2 preceding siblings ...)
  2012-08-21 15:00 ` [PATCH 3/6] rtlwifi: Update header file Larry Finger
@ 2012-08-21 15:00 ` Larry Finger
  2012-08-22 10:50   ` Stanislaw Gruszka
  2012-08-21 15:00 ` [PATCH 5/6] rtlwifi: rtl8192ce: Update " Larry Finger
  2012-08-21 15:00 ` [PATCH 6/6] rtlwifi: rtl8192se: Update driver for changes in 12/30/2011 vendor version Larry Finger
  5 siblings, 1 reply; 10+ messages in thread
From: Larry Finger @ 2012-08-21 15:00 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, Li Chaoming, Larry Finger

From: Li Chaoming <chaoming_li@realsil.com.cn>

Realtek driver rtl_92ce_92se_92de_linux_mac80211_0005.1230.2011 includes
many changes not previously included. The main changes are as follows:

1. Support for the PHY mode switch implemented for some models.
2. Implementation of new routines for the dual-MAC devices.
3. Implement a mechanism for reaching the private data storage
   of the other unit in a dual-MAC device.
4. Impplementation of RX aggregation.
5. Storage of beacon statistics for roaming.
6. The RX routine has been rewritten to reduce the number of O(1) buffers.

Signed-off-by: Li Chaoming <chaoming_li@realsil.com.cn>
Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net>
---
 drivers/net/wireless/rtlwifi/base.c  |  323 ++++++++++++++++--
 drivers/net/wireless/rtlwifi/base.h  |   10 +-
 drivers/net/wireless/rtlwifi/cam.c   |    7 +-
 drivers/net/wireless/rtlwifi/core.c  |   76 +++--
 drivers/net/wireless/rtlwifi/debug.h |    8 +
 drivers/net/wireless/rtlwifi/efuse.c |   40 ++-
 drivers/net/wireless/rtlwifi/efuse.h |    1 -
 drivers/net/wireless/rtlwifi/pci.c   |  624 +++++++++++++++++++---------------
 drivers/net/wireless/rtlwifi/pci.h   |    3 +
 drivers/net/wireless/rtlwifi/ps.c    |   93 ++++-
 drivers/net/wireless/rtlwifi/ps.h    |    3 +-
 drivers/net/wireless/rtlwifi/rc.c    |    3 +-
 drivers/net/wireless/rtlwifi/regd.c  |   18 +
 13 files changed, 851 insertions(+), 358 deletions(-)

diff --git a/drivers/net/wireless/rtlwifi/base.c b/drivers/net/wireless/rtlwifi/base.c
index 942e56b..b9afd49 100644
--- a/drivers/net/wireless/rtlwifi/base.c
+++ b/drivers/net/wireless/rtlwifi/base.c
@@ -208,24 +208,40 @@ static void _rtl_init_hw_ht_capab(struct ieee80211_hw *hw,
 	 *if BW_40 rx_mask[4]=0x01;
 	 *highest supported RX rate
 	 */
-	if (get_rf_type(rtlphy) == RF_1T2R || get_rf_type(rtlphy) == RF_2T2R) {
-
-		RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "1T2R or 2T2R\n");
+	if (rtlpriv->dm.supp_phymode_switch) {
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_EMERG,
+			 "Support phy mode switch\n");
 
 		ht_cap->mcs.rx_mask[0] = 0xFF;
 		ht_cap->mcs.rx_mask[1] = 0xFF;
 		ht_cap->mcs.rx_mask[4] = 0x01;
 
-		ht_cap->mcs.rx_highest = cpu_to_le16(MAX_BIT_RATE_40MHZ_MCS15);
-	} else if (get_rf_type(rtlphy) == RF_1T1R) {
+		ht_cap->mcs.rx_highest =
+			 cpu_to_le16(MAX_BIT_RATE_40MHZ_MCS15);
+	} else {
+		if (get_rf_type(rtlphy) == RF_1T2R ||
+		    get_rf_type(rtlphy) == RF_2T2R) {
 
-		RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "1T1R\n");
+			RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
+				 "1T2R or 2T2R\n");
 
-		ht_cap->mcs.rx_mask[0] = 0xFF;
-		ht_cap->mcs.rx_mask[1] = 0x00;
-		ht_cap->mcs.rx_mask[4] = 0x01;
+			ht_cap->mcs.rx_mask[0] = 0xFF;
+			ht_cap->mcs.rx_mask[1] = 0xFF;
+			ht_cap->mcs.rx_mask[4] = 0x01;
+
+			ht_cap->mcs.rx_highest =
+				cpu_to_le16(MAX_BIT_RATE_40MHZ_MCS15);
+		} else if (get_rf_type(rtlphy) == RF_1T1R) {
 
-		ht_cap->mcs.rx_highest = cpu_to_le16(MAX_BIT_RATE_40MHZ_MCS7);
+			RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "1T1R\n");
+
+			ht_cap->mcs.rx_mask[0] = 0xFF;
+			ht_cap->mcs.rx_mask[1] = 0x00;
+			ht_cap->mcs.rx_mask[4] = 0x01;
+
+			ht_cap->mcs.rx_highest =
+				cpu_to_le16(MAX_BIT_RATE_40MHZ_MCS7);
+		}
 	}
 }
 
@@ -311,7 +327,9 @@ static void _rtl_init_mac80211(struct ieee80211_hw *hw)
 	    IEEE80211_HW_AMPDU_AGGREGATION |
 	    IEEE80211_HW_CONNECTION_MONITOR |
 	    /* IEEE80211_HW_SUPPORTS_CQM_RSSI | */
-	    IEEE80211_HW_REPORTS_TX_ACK_STATUS | 0;
+	    IEEE80211_HW_REPORTS_TX_ACK_STATUS |
+	    WIPHY_FLAG_IBSS_RSN |
+	    IEEE80211_HW_MFP_CAPABLE | 0;
 
 	/* swlps or hwlps has been set in diff chip in init_sw_vars */
 	if (rtlpriv->psc.swctrl_lps)
@@ -357,6 +375,9 @@ static void _rtl_init_deferred_work(struct ieee80211_hw *hw)
 	init_timer(&rtlpriv->works.watchdog_timer);
 	setup_timer(&rtlpriv->works.watchdog_timer,
 		    rtl_watch_dog_timer_callback, (unsigned long)hw);
+	init_timer(&rtlpriv->works.dualmac_easyconcurrent_retrytimer);
+	setup_timer(&rtlpriv->works.dualmac_easyconcurrent_retrytimer,
+		    rtl_easy_concurrent_retrytimer_callback, (unsigned long)hw);
 
 	/* <2> work queue */
 	rtlpriv->works.hw = hw;
@@ -446,18 +467,23 @@ int rtl_init_core(struct ieee80211_hw *hw)
 
 	/* <4> locks */
 	mutex_init(&rtlpriv->locks.conf_mutex);
-	mutex_init(&rtlpriv->locks.ps_mutex);
 	spin_lock_init(&rtlpriv->locks.ips_lock);
 	spin_lock_init(&rtlpriv->locks.irq_th_lock);
 	spin_lock_init(&rtlpriv->locks.h2c_lock);
 	spin_lock_init(&rtlpriv->locks.rf_ps_lock);
 	spin_lock_init(&rtlpriv->locks.rf_lock);
+	spin_lock_init(&rtlpriv->locks.lps_lock);
 	spin_lock_init(&rtlpriv->locks.waitq_lock);
+	spin_lock_init(&rtlpriv->locks.entry_list_lock);
 	spin_lock_init(&rtlpriv->locks.cck_and_rw_pagea_lock);
+	spin_lock_init(&rtlpriv->locks.check_sendpkt_lock);
 
 	rtlmac->link_state = MAC80211_NOLINK;
 
-	/* <5> init deferred work */
+	/* <5> init list */
+	INIT_LIST_HEAD(&rtlpriv->entry_list);
+
+	/* <6> init deferred work */
 	_rtl_init_deferred_work(hw);
 
 	return 0;
@@ -583,17 +609,18 @@ static void _rtl_txrate_selectmode(struct ieee80211_hw *hw,
 				tcb_desc->hw_rate =
 				    rtlpriv->cfg->maps[RTL_RC_CCK_RATE2M];
 				tcb_desc->use_driver_rate = 1;
+				tcb_desc->ratr_index = RATR_INX_WIRELESS_MC;
 			} else {
-				/* TODO */
+				tcb_desc->ratr_index = ratr_index;
 			}
-			tcb_desc->ratr_index = ratr_index;
 		} else if (mac->opmode == NL80211_IFTYPE_AP) {
 			tcb_desc->ratr_index = ratr_index;
 		}
 	}
 
 	if (rtlpriv->dm.useramask) {
-		/* TODO we will differentiate adhoc and station futrue  */
+		/* TODO In future, differentiate adhoc and station */
+		tcb_desc->ratr_index = ratr_index;
 		if (mac->opmode == NL80211_IFTYPE_STATION) {
 			tcb_desc->mac_id = 0;
 
@@ -840,8 +867,6 @@ void rtl_get_tcb_desc(struct ieee80211_hw *hw,
 	txrate = ieee80211_get_tx_rate(hw, info);
 	if (txrate)
 		tcb_desc->hw_rate = txrate->hw_value;
-	else
-		tcb_desc->hw_rate = 0;
 
 	if (ieee80211_is_data(fc)) {
 		/*
@@ -901,6 +926,33 @@ void rtl_get_tcb_desc(struct ieee80211_hw *hw,
 }
 EXPORT_SYMBOL(rtl_get_tcb_desc);
 
+bool rtl_tx_mgmt_proc(struct ieee80211_hw *hw, struct sk_buff *skb)
+{
+	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	__le16 fc = rtl_get_fc(skb);
+
+	if (rtlpriv->dm.supp_phymode_switch &&
+	    mac->link_state < MAC80211_LINKED &&
+	    (ieee80211_is_auth(fc) || ieee80211_is_probe_req(fc))) {
+		if (rtlpriv->cfg->ops->check_switch_to_dmdp)
+			rtlpriv->cfg->ops->check_switch_to_dmdp(hw);
+	}
+	if (ieee80211_is_auth(fc)) {
+		RT_TRACE(rtlpriv, COMP_SEND, DBG_DMESG, "MAC80211_LINKING\n");
+		rtl_ips_nic_on(hw);
+
+		mac->link_state = MAC80211_LINKING;
+		/* Dual mac */
+		rtlpriv->phy.need_iqk = true;
+
+	}
+
+	return true;
+}
+
+struct sk_buff *rtl_make_del_ba(struct ieee80211_hw *hw, u8 *sa, u8 *bssid, u16 tid);
+
 bool rtl_action_proc(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx)
 {
 	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
@@ -925,6 +977,56 @@ bool rtl_action_proc(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx)
 			RT_TRACE(rtlpriv, (COMP_SEND | COMP_RECV), DBG_DMESG,
 				 "%s ACT_ADDBAREQ From :%pM\n",
 				 is_tx ? "Tx" : "Rx", hdr->addr2);
+			RT_PRINT_DATA(rtlpriv, COMP_INIT, DBG_DMESG, "req\n",
+				      skb->data, skb->len);
+			if (!is_tx) {
+				struct ieee80211_sta *sta = NULL;
+				struct rtl_sta_info *sta_entry = NULL;
+				struct ieee80211_mgmt *mgmt = (void *)skb->data;
+				u16 capab = 0, tid = 0;
+				struct rtl_tid_data *tid_data;
+				struct sk_buff *skb_delba = NULL;
+				struct ieee80211_rx_status rx_status = { 0 };
+				rcu_read_lock();
+				sta = rtl_find_sta(hw, hdr->addr3);
+				if (sta == NULL) {
+					RT_TRACE(rtlpriv,
+						 (COMP_SEND | COMP_RECV),
+						 DBG_EMERG,
+						 "sta is NULL\n");
+					rcu_read_unlock();
+					return true;
+				}
+
+				sta_entry = (struct rtl_sta_info *)sta->drv_priv;
+				if (!sta_entry) {
+					rcu_read_unlock();
+					return true;
+				}
+				capab = le16_to_cpu(mgmt->u.action.u.addba_req.capab);
+				tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2;
+				tid_data = &sta_entry->tids[tid];
+				if (tid_data->agg.rx_agg_state == RTL_RX_AGG_START) {
+					skb_delba = rtl_make_del_ba(hw,
+							 hdr->addr2,
+							 hdr->addr3, tid);
+					if (skb_delba) {
+						rx_status.freq = hw->conf.channel->center_freq;
+						rx_status.band = hw->conf.channel->band;
+						rx_status.flag |= RX_FLAG_DECRYPTED;
+						rx_status.flag |= RX_FLAG_MACTIME_MPDU;
+						rx_status.rate_idx = 0;
+						rx_status.signal = 50 + 10;
+						memcpy(IEEE80211_SKB_RXCB(skb_delba), &rx_status,
+								sizeof(rx_status));
+						RT_PRINT_DATA(rtlpriv, COMP_INIT, DBG_DMESG,
+								("fake del\n"), skb_delba->data,
+								skb_delba->len);
+						ieee80211_rx_irqsafe(hw, skb_delba);
+					}
+				}
+			rcu_read_unlock();
+			}
 			break;
 		case ACT_ADDBARSP:
 			RT_TRACE(rtlpriv, (COMP_SEND | COMP_RECV), DBG_DMESG,
@@ -1077,6 +1179,60 @@ int rtl_tx_agg_stop(struct ieee80211_hw *hw,
 	return 0;
 }
 
+int rtl_rx_agg_start(struct ieee80211_hw *hw,
+		struct ieee80211_sta *sta, u16 tid)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_tid_data *tid_data;
+	struct rtl_sta_info *sta_entry = NULL;
+
+	if (sta == NULL)
+		return -EINVAL;
+
+	if (unlikely(tid >= MAX_TID_COUNT))
+		return -EINVAL;
+
+	sta_entry = (struct rtl_sta_info *)sta->drv_priv;
+	if (!sta_entry)
+		return -ENXIO;
+	tid_data = &sta_entry->tids[tid];
+
+	RT_TRACE(rtlpriv, COMP_RECV, DBG_DMESG,
+		 "on ra = %pM tid = %d seq:%d\n", sta->addr, tid,
+		 tid_data->seq_number);
+
+	tid_data->agg.rx_agg_state = RTL_RX_AGG_START;
+	return 0;
+}
+
+int rtl_rx_agg_stop(struct ieee80211_hw *hw,
+		struct ieee80211_sta *sta, u16 tid)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_tid_data *tid_data;
+	struct rtl_sta_info *sta_entry = NULL;
+
+	if (sta == NULL)
+		return -EINVAL;
+
+	if (!sta->addr) {
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "ra = NULL\n");
+		return -EINVAL;
+	}
+
+	RT_TRACE(rtlpriv, COMP_SEND, DBG_DMESG,
+		 "on ra = %pM tid = %d\n", sta->addr, tid);
+
+	if (unlikely(tid >= MAX_TID_COUNT))
+		return -EINVAL;
+
+	sta_entry = (struct rtl_sta_info *)sta->drv_priv;
+	tid_data = &sta_entry->tids[tid];
+	sta_entry->tids[tid].agg.rx_agg_state = RTL_RX_AGG_STOP;
+
+	return 0;
+}
+
 int rtl_tx_agg_oper(struct ieee80211_hw *hw,
 		struct ieee80211_sta *sta, u16 tid)
 {
@@ -1108,6 +1264,34 @@ int rtl_tx_agg_oper(struct ieee80211_hw *hw,
  * wq & timer callback functions
  *
  *********************************************************/
+/* this function is used for roaming */
+void rtl_beacon_statistic(struct ieee80211_hw *hw, struct sk_buff *skb)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+
+	if (rtlpriv->mac80211.opmode != NL80211_IFTYPE_STATION)
+		return;
+
+	if (rtlpriv->mac80211.link_state < MAC80211_LINKED)
+		return;
+
+	/* check if this really is a beacon */
+	if (!ieee80211_is_beacon(hdr->frame_control) &&
+	    !ieee80211_is_probe_resp(hdr->frame_control))
+		return;
+
+	/* min. beacon length + FCS_LEN */
+	if (skb->len <= 40 + FCS_LEN)
+		return;
+
+	/* and only beacons from the associated BSSID, please */
+	if (!ether_addr_equal(hdr->addr3, rtlpriv->mac80211.bssid))
+		return;
+
+	rtlpriv->link_info.bcn_rx_inperiod++;
+}
+
 void rtl_watchdog_wq_callback(void *data)
 {
 	struct rtl_works *rtlworks = container_of_dwork_rtl(data,
@@ -1118,6 +1302,8 @@ void rtl_watchdog_wq_callback(void *data)
 	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
 	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
 	bool busytraffic = false;
+	bool tx_busy_traffic = false;
+	bool rx_busy_traffic = false;
 	bool higher_busytraffic = false;
 	bool higher_busyrxtraffic = false;
 	u8 idx, tid;
@@ -1167,8 +1353,13 @@ void rtl_watchdog_wq_callback(void *data)
 		aver_tx_cnt_inperiod = tx_cnt_inp4eriod / 4;
 
 		/* (2) check traffic busy */
-		if (aver_rx_cnt_inperiod > 100 || aver_tx_cnt_inperiod > 100)
+		if (aver_rx_cnt_inperiod > 100 || aver_tx_cnt_inperiod > 100) {
 			busytraffic = true;
+			if (aver_rx_cnt_inperiod > aver_tx_cnt_inperiod)
+				rx_busy_traffic = true;
+			else
+				tx_busy_traffic = false;
+		}
 
 		/* Higher Tx/Rx data. */
 		if (aver_rx_cnt_inperiod > 4000 ||
@@ -1221,11 +1412,34 @@ void rtl_watchdog_wq_callback(void *data)
 		rtlpriv->link_info.tidtx_inperiod[tid] = 0;
 
 	rtlpriv->link_info.busytraffic = busytraffic;
+	rtlpriv->link_info.rx_busy_traffic = rx_busy_traffic;
+	rtlpriv->link_info.tx_busy_traffic = tx_busy_traffic;
 	rtlpriv->link_info.higher_busytraffic = higher_busytraffic;
 	rtlpriv->link_info.higher_busyrxtraffic = higher_busyrxtraffic;
 
 	/* <3> DM */
 	rtlpriv->cfg->ops->dm_watchdog(hw);
+
+	/* <4> roaming */
+	if (mac->link_state == MAC80211_LINKED &&
+	    mac->opmode == NL80211_IFTYPE_STATION) {
+		if ((rtlpriv->link_info.bcn_rx_inperiod +
+		    rtlpriv->link_info.num_rx_inperiod) == 0) {
+			rtlpriv->link_info.roam_times++;
+			RT_TRACE(rtlpriv, COMP_ERR, DBG_DMESG, "AP off for %d s\n",
+				(rtlpriv->link_info.roam_times * 2));
+
+			/* if we can't recv beacon for 6s, we should reconnect this AP */
+			if (rtlpriv->link_info.roam_times >= 3) {
+				RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "AP off, try to reconnect now\n");
+				rtlpriv->link_info.roam_times = 0;
+				ieee80211_connection_loss(rtlpriv->mac80211.vif);
+			}
+		} else {
+			rtlpriv->link_info.roam_times = 0;
+		}
+	}
+	rtlpriv->link_info.bcn_rx_inperiod = 0;
 }
 
 void rtl_watch_dog_timer_callback(unsigned long data)
@@ -1240,6 +1454,18 @@ void rtl_watch_dog_timer_callback(unsigned long data)
 		  jiffies + MSECS(RTL_WATCH_DOG_TIME));
 }
 
+void rtl_easy_concurrent_retrytimer_callback(unsigned long data)
+{
+	struct ieee80211_hw *hw = (struct ieee80211_hw *)data;
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_priv *buddy_priv = rtlpriv->buddy_priv;
+
+	if (buddy_priv == NULL)
+		return;
+
+	rtlpriv->cfg->ops->dualmac_easy_concurrent(hw);
+}
+
 /*********************************************************
  *
  * frame process functions
@@ -1310,14 +1536,16 @@ static struct sk_buff *rtl_make_smps_action(struct ieee80211_hw *hw,
 }
 
 int rtl_send_smps_action(struct ieee80211_hw *hw,
-		struct ieee80211_sta *sta, u8 *da, u8 *bssid,
+		struct ieee80211_sta *sta,
 		enum ieee80211_smps_mode smps)
 {
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
 	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
-	struct sk_buff *skb = rtl_make_smps_action(hw, smps, da, bssid);
+	struct sk_buff *skb;
 	struct rtl_tcb_desc tcb_desc;
+	u8 bssid[ETH_ALEN];
+
 	memset(&tcb_desc, 0, sizeof(struct rtl_tcb_desc));
 
 	if (rtlpriv->mac80211.act_scanning)
@@ -1332,22 +1560,67 @@ int rtl_send_smps_action(struct ieee80211_hw *hw,
 	if (!test_bit(RTL_STATUS_INTERFACE_START, &rtlpriv->status))
 		goto err_free;
 
+	if (rtlpriv->mac80211.opmode == NL80211_IFTYPE_AP)
+		memcpy(bssid, rtlpriv->efuse.dev_addr, ETH_ALEN);
+	else
+		memcpy(bssid, rtlpriv->mac80211.bssid, ETH_ALEN);
+
+	skb = rtl_make_smps_action(hw, smps, sta->addr, bssid);
 	/* this is a type = mgmt * stype = action frame */
 	if (skb) {
 		struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
 		struct rtl_sta_info *sta_entry =
 			(struct rtl_sta_info *) sta->drv_priv;
 		sta_entry->mimo_ps = smps;
-		rtlpriv->cfg->ops->update_rate_tbl(hw, sta, 0);
 
 		info->control.rates[0].idx = 0;
 		info->control.sta = sta;
 		info->band = hw->conf.channel->band;
 		rtlpriv->intf_ops->adapter_tx(hw, skb, &tcb_desc);
 	}
+	return 1;
 err_free:
 	return 0;
 }
+EXPORT_SYMBOL(rtl_send_smps_action);
+
+/* mac80211 have issues when receive del ba
+ * so here we just make a fake del_ba when we receive a ba_req
+ * but rx_agg was opened to let mac80211 release some ba
+ * related resources, so please this del_ba for tx
+ */
+struct sk_buff *rtl_make_del_ba(struct ieee80211_hw *hw,
+		u8 *sa, u8 *bssid, u16 tid)
+{
+	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+	struct sk_buff *skb;
+	struct ieee80211_mgmt *action_frame;
+	u16 params;
+
+	/* 27 = header + category + action + smps mode */
+	skb = dev_alloc_skb(34 + hw->extra_tx_headroom);
+	if (!skb)
+		return NULL;
+
+	skb_reserve(skb, hw->extra_tx_headroom);
+	action_frame = (void *)skb_put(skb, 34);
+	memset(action_frame, 0, 34);
+	memcpy(action_frame->sa, sa, ETH_ALEN);
+	memcpy(action_frame->da, rtlefuse->dev_addr, ETH_ALEN);
+	memcpy(action_frame->bssid, bssid, ETH_ALEN);
+	action_frame->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
+						  IEEE80211_STYPE_ACTION);
+	action_frame->u.action.category = WLAN_CATEGORY_BACK;
+	action_frame->u.action.u.delba.action_code = WLAN_ACTION_DELBA;
+	params = (u16)(1 << 11);		/* bit 11 initiator */
+	params |= (u16)(tid << 12);		/* bit 15:12 TID number */
+
+	action_frame->u.action.u.delba.params = cpu_to_le16(params);
+	action_frame->u.action.u.delba.reason_code =
+		cpu_to_le16(WLAN_REASON_QSTA_TIMEOUT);
+
+	return skb;
+}
 
 /*********************************************************
  *
@@ -1564,11 +1837,17 @@ MODULE_AUTHOR("Larry Finger	<Larry.FInger@lwfinger.net>");
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Realtek 802.11n PCI wireless core");
 
+struct rtl_global_var global_var = {};
+
 static int __init rtl_core_module_init(void)
 {
 	if (rtl_rate_control_register())
 		pr_err("Unable to register rtl_rc, use default RC !!\n");
 
+	/* init some global vars */
+	INIT_LIST_HEAD(&global_var.glb_priv_list);
+	spin_lock_init(&global_var.glb_list_lock);
+
 	return 0;
 }
 
diff --git a/drivers/net/wireless/rtlwifi/base.h b/drivers/net/wireless/rtlwifi/base.h
index f35af0f..04bd282 100644
--- a/drivers/net/wireless/rtlwifi/base.h
+++ b/drivers/net/wireless/rtlwifi/base.h
@@ -117,8 +117,10 @@ void rtl_watch_dog_timer_callback(unsigned long data);
 void rtl_deinit_deferred_work(struct ieee80211_hw *hw);
 
 bool rtl_action_proc(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx);
+bool rtl_tx_mgmt_proc(struct ieee80211_hw *hw, struct sk_buff *skb);
 u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx);
 
+void rtl_beacon_statistic(struct ieee80211_hw *hw, struct sk_buff *skb);
 void rtl_watch_dog_timer_callback(unsigned long data);
 int rtl_tx_agg_start(struct ieee80211_hw *hw, struct ieee80211_sta *sta,
 		     u16 tid, u16 *ssn);
@@ -126,6 +128,10 @@ int rtl_tx_agg_stop(struct ieee80211_hw *hw, struct ieee80211_sta *sta,
 		    u16 tid);
 int rtl_tx_agg_oper(struct ieee80211_hw *hw, struct ieee80211_sta *sta,
 		    u16 tid);
+int rtl_rx_agg_start(struct ieee80211_hw *hw, struct ieee80211_sta *sta,
+		     u16 tid);
+int rtl_rx_agg_stop(struct ieee80211_hw *hw, struct ieee80211_sta *sta,
+		    u16 tid);
 void rtl_watchdog_wq_callback(void *data);
 
 void rtl_get_tcb_desc(struct ieee80211_hw *hw,
@@ -134,12 +140,14 @@ void rtl_get_tcb_desc(struct ieee80211_hw *hw,
 		      struct sk_buff *skb, struct rtl_tcb_desc *tcb_desc);
 
 int rtl_send_smps_action(struct ieee80211_hw *hw,
-		struct ieee80211_sta *sta, u8 *da, u8 *bssid,
+		struct ieee80211_sta *sta,
 		enum ieee80211_smps_mode smps);
 u8 *rtl_find_ie(u8 *data, unsigned int len, u8 ie);
 void rtl_recognize_peer(struct ieee80211_hw *hw, u8 *data, unsigned int len);
 u8 rtl_tid_to_ac(u8 tid);
 extern struct attribute_group rtl_attribute_group;
+void rtl_easy_concurrent_retrytimer_callback(unsigned long data);
+extern struct rtl_global_var global_var;
 int rtlwifi_rate_mapping(struct ieee80211_hw *hw,
 			 bool isht, u8 desc_rate, bool first_ampdu);
 #endif
diff --git a/drivers/net/wireless/rtlwifi/cam.c b/drivers/net/wireless/rtlwifi/cam.c
index 5b4b4d4..48dcef4 100644
--- a/drivers/net/wireless/rtlwifi/cam.c
+++ b/drivers/net/wireless/rtlwifi/cam.c
@@ -52,11 +52,8 @@ static void rtl_cam_program_entry(struct ieee80211_hw *hw, u32 entry_no,
 	u32 target_content = 0;
 	u8 entry_i;
 
-	RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD,
-		 "key_cont_128:\n %x:%x:%x:%x:%x:%x\n",
-		 key_cont_128[0], key_cont_128[1],
-		 key_cont_128[2], key_cont_128[3],
-		 key_cont_128[4], key_cont_128[5]);
+	RT_PRINT_DATA(rtlpriv, COMP_SEC, DBG_LOUD, "Key content :",
+			key_cont_128, 16);
 
 	for (entry_i = 0; entry_i < CAM_CONTENT_COUNT; entry_i++) {
 		target_command = entry_i + CAM_CONTENT_COUNT * entry_no;
diff --git a/drivers/net/wireless/rtlwifi/core.c b/drivers/net/wireless/rtlwifi/core.c
index a18ad2a..8e2ad66 100644
--- a/drivers/net/wireless/rtlwifi/core.c
+++ b/drivers/net/wireless/rtlwifi/core.c
@@ -154,8 +154,6 @@ static int rtl_op_add_interface(struct ieee80211_hw *hw,
 	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
 	int err = 0;
 
-	vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER;
-
 	if (mac->vif) {
 		RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
 			 "vif has been set!! mac->vif = 0x%p\n", mac->vif);
@@ -321,6 +319,13 @@ static int rtl_op_config(struct ieee80211_hw *hw, u32 changed)
 		struct ieee80211_channel *channel = hw->conf.channel;
 		u8 wide_chan = (u8) channel->hw_value;
 
+		if (rtlpriv->dm.supp_phymode_switch &&
+		    mac->link_state < MAC80211_LINKED &&
+		    !mac->act_scanning) {
+			if (rtlpriv->cfg->ops->check_switch_to_dmdp)
+				rtlpriv->cfg->ops->check_switch_to_dmdp(hw);
+		}
+
 		/*
 		 *because we should back channel to
 		 *current_network.chan in in scanning,
@@ -483,21 +488,26 @@ static int rtl_op_sta_add(struct ieee80211_hw *hw,
 
 	if (sta) {
 		sta_entry = (struct rtl_sta_info *) sta->drv_priv;
+		spin_lock_bh(&rtlpriv->locks.entry_list_lock);
+		list_add_tail(&sta_entry->list, &rtlpriv->entry_list);
+		spin_unlock_bh(&rtlpriv->locks.entry_list_lock);
 		if (rtlhal->current_bandtype == BAND_ON_2_4G) {
 			sta_entry->wireless_mode = WIRELESS_MODE_G;
 			if (sta->supp_rates[0] <= 0xf)
 				sta_entry->wireless_mode = WIRELESS_MODE_B;
 			if (sta->ht_cap.ht_supported)
 				sta_entry->wireless_mode = WIRELESS_MODE_N_24G;
+
+			if (rtlpriv->mac80211.opmode == NL80211_IFTYPE_ADHOC)
+				sta_entry->wireless_mode = WIRELESS_MODE_G;
 		} else if (rtlhal->current_bandtype == BAND_ON_5G) {
 			sta_entry->wireless_mode = WIRELESS_MODE_A;
 			if (sta->ht_cap.ht_supported)
 				sta_entry->wireless_mode = WIRELESS_MODE_N_24G;
-		}
 
-		/* I found some times mac80211 give wrong supp_rates for adhoc*/
-		if (rtlpriv->mac80211.opmode == NL80211_IFTYPE_ADHOC)
-			sta_entry->wireless_mode = WIRELESS_MODE_G;
+			if (rtlpriv->mac80211.opmode == NL80211_IFTYPE_ADHOC)
+				sta_entry->wireless_mode = WIRELESS_MODE_A;
+		}
 
 		RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG,
 			 "Add sta addr is %pM\n", sta->addr);
@@ -517,6 +527,9 @@ static int rtl_op_sta_remove(struct ieee80211_hw *hw,
 		sta_entry = (struct rtl_sta_info *) sta->drv_priv;
 		sta_entry->wireless_mode = 0;
 		sta_entry->ratr_index = 0;
+		spin_lock_bh(&rtlpriv->locks.entry_list_lock);
+		list_del(&sta_entry->list);
+		spin_unlock_bh(&rtlpriv->locks.entry_list_lock);
 	}
 	return 0;
 }
@@ -645,9 +658,20 @@ static void rtl_op_bss_info_changed(struct ieee80211_hw *hw,
 
 			if (rtlpriv->cfg->ops->linked_set_reg)
 				rtlpriv->cfg->ops->linked_set_reg(hw);
+
+			rcu_read_lock();
+			sta = ieee80211_find_sta(vif, (u8 *)bss_conf->bssid);
 			if (mac->opmode == NL80211_IFTYPE_STATION && sta)
 				rtlpriv->cfg->ops->update_rate_tbl(hw, sta, 0);
-			RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG,
+			RT_TRACE(rtlpriv, COMP_EASY_CONCURRENT, DBG_LOUD,
+				 "send PS STATIC frame\n");
+			if (rtlpriv->dm.supp_phymode_switch) {
+				if (sta->ht_cap.ht_supported)
+					rtl_send_smps_action(hw, sta,
+						IEEE80211_SMPS_STATIC);
+			}
+			rcu_read_unlock();
+				RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG,
 				 "BSS_CHANGED_ASSOC\n");
 		} else {
 			if (mac->link_state == MAC80211_LINKED)
@@ -655,13 +679,12 @@ static void rtl_op_bss_info_changed(struct ieee80211_hw *hw,
 
 			mac->link_state = MAC80211_NOLINK;
 			memset(mac->bssid, 0, 6);
-
-			/* reset sec info */
-			rtl_cam_reset_sec_info(hw);
-
-			rtl_cam_reset_all_entry(hw);
 			mac->vendor = PEER_UNKNOWN;
 
+			if (rtlpriv->dm.supp_phymode_switch) {
+				if (rtlpriv->cfg->ops->check_switch_to_dmdp)
+					rtlpriv->cfg->ops->check_switch_to_dmdp(hw);
+			}
 			RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG,
 				 "BSS_CHANGED_UN_ASSOC\n");
 		}
@@ -876,12 +899,10 @@ static int rtl_op_ampdu_action(struct ieee80211_hw *hw,
 		RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE,
 			 "IEEE80211_AMPDU_TX_START: TID:%d\n", tid);
 		return rtl_tx_agg_start(hw, sta, tid, ssn);
-		break;
 	case IEEE80211_AMPDU_TX_STOP:
 		RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE,
 			 "IEEE80211_AMPDU_TX_STOP: TID:%d\n", tid);
 		return rtl_tx_agg_stop(hw, sta, tid);
-		break;
 	case IEEE80211_AMPDU_TX_OPERATIONAL:
 		RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE,
 			 "IEEE80211_AMPDU_TX_OPERATIONAL:TID:%d\n", tid);
@@ -890,11 +911,11 @@ static int rtl_op_ampdu_action(struct ieee80211_hw *hw,
 	case IEEE80211_AMPDU_RX_START:
 		RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE,
 			 "IEEE80211_AMPDU_RX_START:TID:%d\n", tid);
-		break;
+		return rtl_rx_agg_start(hw, sta, tid);
 	case IEEE80211_AMPDU_RX_STOP:
 		RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE,
 			 "IEEE80211_AMPDU_RX_STOP:TID:%d\n", tid);
-		break;
+		return rtl_rx_agg_stop(hw, sta, tid);
 	default:
 		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
 			 "IEEE80211_AMPDU_ERR!!!!:\n");
@@ -908,6 +929,10 @@ static void rtl_op_sw_scan_start(struct ieee80211_hw *hw)
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
 
+	if (rtlpriv->dm.supp_phymode_switch) {
+		if (rtlpriv->cfg->ops->check_switch_to_dmdp)
+			rtlpriv->cfg->ops->check_switch_to_dmdp(hw);
+	}
 	mac->act_scanning = true;
 
 	RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, "\n");
@@ -967,6 +992,10 @@ static int rtl_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
 			 "not open hw encryption\n");
 		return -ENOSPC;	/*User disabled HW-crypto */
 	}
+	/* To support IBSS, use sw-crypto for GTK */
+	if (vif->type == NL80211_IFTYPE_ADHOC &&
+	   !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE))
+		return -ENOSPC;
 	RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
 		 "%s hardware based encryption for keyidx: %d, mac: %pM\n",
 		 cmd == SET_KEY ? "Using" : "Disabling", key->keyidx,
@@ -993,6 +1022,15 @@ static int rtl_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
 		key_type = AESCCMP_ENCRYPTION;
 		RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "alg:CCMP\n");
 		break;
+	case WLAN_CIPHER_SUITE_AES_CMAC:
+		/*HW don't support CMAC encryption, use software CMAC encryption */
+		key_type = AESCMAC_ENCRYPTION;
+		RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "alg:CMAC\n");
+		RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
+			 "HW don't support CMAC encrypiton, "
+			 "use software CMAC encrypiton\n");
+		err = -EOPNOTSUPP;
+		goto out_unlock;
 	default:
 		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "alg_err:%x!!!!\n",
 			 key->cipher);
@@ -1095,6 +1133,9 @@ static int rtl_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
 		key->hw_key_idx = key_idx;
 		if (key_type == TKIP_ENCRYPTION)
 			key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
+		/*use software CCMP encryption for management frames (MFP) */
+		if (key_type == AESCCMP_ENCRYPTION)
+			key->flags |= IEEE80211_KEY_FLAG_SW_MGMT;
 		break;
 	case DISABLE_KEY:
 		RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
@@ -1113,9 +1154,6 @@ static int rtl_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
 		 *or clear all entry here.
 		 */
 		rtl_cam_delete_one_entry(hw, mac_addr, key_idx);
-
-		rtl_cam_reset_sec_info(hw);
-
 		break;
 	default:
 		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
diff --git a/drivers/net/wireless/rtlwifi/debug.h b/drivers/net/wireless/rtlwifi/debug.h
index 07493d2..2ce21e8 100644
--- a/drivers/net/wireless/rtlwifi/debug.h
+++ b/drivers/net/wireless/rtlwifi/debug.h
@@ -106,6 +106,7 @@
 #define COMP_REGD			BIT(27)
 #define COMP_CHAN			BIT(28)
 #define COMP_USB			BIT(29)
+#define COMP_EASY_CONCURRENT		BIT(30)
 
 /*--------------------------------------------------------------
 		Define the rt_print components
@@ -133,6 +134,13 @@
 #define	PHY_TXPWR			BIT(8)
 #define	PHY_PWRDIFF			BIT(9)
 
+/* Define Dynamic Mechanism check module bit --> FDM */
+#define WA_IOT				BIT(0)
+#define DM_PWDB				BIT(1)
+#define DM_MONITOR			BIT(2)
+#define DM_DIG				BIT(3)
+#define DM_EDCA_TURBO			BIT(4)
+
 enum dbgp_flag_e {
 	FQOS = 0,
 	FTX = 1,
diff --git a/drivers/net/wireless/rtlwifi/efuse.c b/drivers/net/wireless/rtlwifi/efuse.c
index 8e2f9af..1e3ff71 100644
--- a/drivers/net/wireless/rtlwifi/efuse.c
+++ b/drivers/net/wireless/rtlwifi/efuse.c
@@ -35,8 +35,6 @@ static const u8 MAX_PGPKT_SIZE = 9;
 static const u8 PGPKT_DATA_SIZE = 8;
 static const int EFUSE_MAX_SIZE = 512;
 
-static const u8 EFUSE_OOB_PROTECT_BYTES = 15;
-
 static const struct efuse_map RTL8712_SDIO_EFUSE_TABLE[] = {
 	{0, 0, 0, 2},
 	{0, 1, 0, 2},
@@ -240,6 +238,7 @@ void read_efuse(struct ieee80211_hw *hw, u16 _offset, u16 _size_byte, u8 *pbuf)
 	u8 rtemp8[1];
 	u16 efuse_addr = 0;
 	u8 offset, wren;
+	u8 u1temp;
 	u16 i;
 	u16 j;
 	const u16 efuse_max_section =
@@ -287,6 +286,28 @@ void read_efuse(struct ieee80211_hw *hw, u16 _offset, u16 _size_byte, u8 *pbuf)
 	while ((*rtemp8 != 0xFF) && (efuse_addr < efuse_len)) {
 		offset = ((*rtemp8 >> 4) & 0x0f);
 
+		/*  Check PG header for section num.  */
+		if ((*rtemp8 & 0x1F) == 0x0F) { /* extended header */
+			u1temp = (*rtemp8 & 0xE0) >> 5;
+			read_efuse_byte(hw, efuse_addr, rtemp8);
+
+			if ((*rtemp8 & 0x0F) == 0x0F) {
+				efuse_addr++;
+				read_efuse_byte(hw, efuse_addr, rtemp8);
+
+				if (*rtemp8 != 0xFF && (efuse_addr < efuse_len))
+					efuse_addr++;
+				continue;
+			} else {
+				offset = ((*rtemp8 & 0xF0) >> 1) | u1temp;
+				wren = (*rtemp8 & 0x0F);
+				efuse_addr++;
+			}
+		} else {
+			offset = ((*rtemp8 >> 4) & 0x0f);
+			wren = (*rtemp8 & 0x0f);
+		}
+
 		if (offset < efuse_max_section) {
 			wren = (*rtemp8 & 0x0f);
 			RTPRINT(rtlpriv, FEEPROM, EFUSE_READ_ALL,
@@ -390,8 +411,8 @@ bool efuse_shadow_update_chk(struct ieee80211_hw *hw)
 	totalbytes = hdr_num + words_need * 2;
 	efuse_used = rtlefuse->efuse_usedbytes;
 
-	if ((totalbytes + efuse_used) >=
-	    (EFUSE_MAX_SIZE - EFUSE_OOB_PROTECT_BYTES))
+	if ((totalbytes + efuse_used) >= (EFUSE_MAX_SIZE -
+	    rtlpriv->cfg->maps[EFUSE_OOB_PROTECT_BYTES_LEN]))
 		result = false;
 
 	RT_TRACE(rtlpriv, COMP_EFUSE, DBG_LOUD,
@@ -932,8 +953,8 @@ static int efuse_pg_packet_write(struct ieee80211_hw *hw,
 	u8 badworden = 0x0F;
 	static int repeat_times;
 
-	if (efuse_get_current_size(hw) >=
-	    (EFUSE_MAX_SIZE - EFUSE_OOB_PROTECT_BYTES)) {
+	if (efuse_get_current_size(hw) >= (EFUSE_MAX_SIZE -
+	    rtlpriv->cfg->maps[EFUSE_OOB_PROTECT_BYTES_LEN])) {
 		RTPRINT(rtlpriv, FEEPROM, EFUSE_PG,
 			"efuse_pg_packet_write error\n");
 		return false;
@@ -949,8 +970,8 @@ static int efuse_pg_packet_write(struct ieee80211_hw *hw,
 
 	RTPRINT(rtlpriv, FEEPROM, EFUSE_PG,  "efuse Power ON\n");
 
-	while (continual && (efuse_addr <
-	       (EFUSE_MAX_SIZE - EFUSE_OOB_PROTECT_BYTES))) {
+	while (continual && (efuse_addr < (EFUSE_MAX_SIZE -
+	       rtlpriv->cfg->maps[EFUSE_OOB_PROTECT_BYTES_LEN]))) {
 
 		if (write_state == PG_STATE_HEADER) {
 			badworden = 0x0F;
@@ -1003,7 +1024,8 @@ static int efuse_pg_packet_write(struct ieee80211_hw *hw,
 		}
 	}
 
-	if (efuse_addr >= (EFUSE_MAX_SIZE - EFUSE_OOB_PROTECT_BYTES)) {
+	if (efuse_addr >= (EFUSE_MAX_SIZE -
+	    rtlpriv->cfg->maps[EFUSE_OOB_PROTECT_BYTES_LEN])) {
 		RT_TRACE(rtlpriv, COMP_EFUSE, DBG_LOUD,
 			 "efuse_addr(%#x) Out of size!!\n", efuse_addr);
 	}
diff --git a/drivers/net/wireless/rtlwifi/efuse.h b/drivers/net/wireless/rtlwifi/efuse.h
index 2bdea9a..395a326 100644
--- a/drivers/net/wireless/rtlwifi/efuse.h
+++ b/drivers/net/wireless/rtlwifi/efuse.h
@@ -32,7 +32,6 @@
 
 #define EFUSE_IC_ID_OFFSET		506
 
-#define EFUSE_REAL_CONTENT_LEN		512
 #define EFUSE_MAP_LEN			128
 #define EFUSE_MAX_WORD_UNIT		4
 
diff --git a/drivers/net/wireless/rtlwifi/pci.c b/drivers/net/wireless/rtlwifi/pci.c
index 80f75d3..50c51f0 100644
--- a/drivers/net/wireless/rtlwifi/pci.c
+++ b/drivers/net/wireless/rtlwifi/pci.c
@@ -59,7 +59,7 @@ static u8 _rtl_mac_to_hwqueue(struct ieee80211_hw *hw,
 
 	if (unlikely(ieee80211_is_beacon(fc)))
 		return BEACON_QUEUE;
-	if (ieee80211_is_mgmt(fc))
+	if (ieee80211_is_mgmt(fc) || ieee80211_is_ctl(fc))
 		return MGNT_QUEUE;
 	if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192SE)
 		if (ieee80211_is_nullfunc(fc))
@@ -349,6 +349,49 @@ static bool rtl_pci_get_amd_l1_patch(struct ieee80211_hw *hw)
 	return status;
 }
 
+static bool rtl_pci_check_buddy_priv(struct ieee80211_hw *hw,
+				     struct rtl_priv **buddy_priv)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
+	bool find_buddy_priv = false;
+	struct rtl_priv *temp_priv = NULL;
+	struct rtl_pci_priv *temp_pcipriv = NULL;
+
+	if (!list_empty(&rtlpriv->glb_var->glb_priv_list)) {
+		list_for_each_entry(temp_priv, &rtlpriv->glb_var->glb_priv_list,
+			list) {
+			if (temp_priv) {
+				temp_pcipriv = (struct rtl_pci_priv *)temp_priv->priv;
+				RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+					"pcipriv->ndis_adapter.funcnumber %x\n",
+					pcipriv->ndis_adapter.funcnumber);
+				RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+					"temp_pcipriv->ndis_adapter.funcnumber %x\n",
+					temp_pcipriv->ndis_adapter.funcnumber);
+
+				if ((pcipriv->ndis_adapter.busnumber ==
+				    temp_pcipriv->ndis_adapter.busnumber) &&
+				    (pcipriv->ndis_adapter.devnumber ==
+				    temp_pcipriv->ndis_adapter.devnumber) &&
+				    (pcipriv->ndis_adapter.funcnumber !=
+				    temp_pcipriv->ndis_adapter.funcnumber)) {
+					find_buddy_priv = true;
+					break;
+				}
+			}
+		}
+	}
+
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+		"find_buddy_priv %d\n", find_buddy_priv);
+
+	if (find_buddy_priv)
+		*buddy_priv = temp_priv;
+
+	return find_buddy_priv;
+}
+
 static void rtl_pci_get_linkcontrol_field(struct ieee80211_hw *hw)
 {
 	struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
@@ -478,6 +521,12 @@ static void _rtl_pci_tx_chk_waitq(struct ieee80211_hw *hw)
 	if (!rtlpriv->rtlhal.earlymode_enable)
 		return;
 
+	if (rtlpriv->dm.supp_phymode_switch &&
+	    (rtlpriv->easy_concurrent_ctl.switch_in_process ||
+	    (rtlpriv->buddy_priv &&
+	    rtlpriv->buddy_priv->easy_concurrent_ctl.switch_in_process)))
+		return;
+
 	/* we juse use em for BE/BK/VI/VO */
 	for (tid = 7; tid >= 0; tid--) {
 		u8 hw_queue = ac_to_hwq[rtl_tid_to_ac(tid)];
@@ -571,6 +620,15 @@ static void _rtl_pci_tx_isr(struct ieee80211_hw *hw, int prio)
 				rtlpriv->psc.state_inap = false;
 			}
 		}
+		if (ieee80211_is_action(fc)) {
+			struct ieee80211_mgmt *action_frame =
+				(struct ieee80211_mgmt *)skb->data;
+			if (action_frame->u.action.u.ht_smps.action ==
+			    WLAN_HT_ACTION_SMPS) {
+				dev_kfree_skb(skb);
+				goto tx_status_ok;
+			}
+		}
 
 		/* update tid tx pkt num */
 		tid = rtl_get_tid(skb);
@@ -602,169 +660,201 @@ tx_status_ok:
 	}
 
 	if (((rtlpriv->link_info.num_rx_inperiod +
-		rtlpriv->link_info.num_tx_inperiod) > 8) ||
-		(rtlpriv->link_info.num_rx_inperiod > 2)) {
-		schedule_work(&rtlpriv->works.lps_leave_work);
-	}
+	    rtlpriv->link_info.num_tx_inperiod) > 8) ||
+	    (rtlpriv->link_info.num_rx_inperiod > 2))
+		rtl_lps_leave(hw);
 }
 
-static void _rtl_receive_one(struct ieee80211_hw *hw, struct sk_buff *skb,
-			     struct ieee80211_rx_status rx_status)
+static int _rtl_pci_init_one_rxdesc(struct ieee80211_hw *hw,
+				    struct rtl_rx_desc *entry,
+				    int rxring_idx, int desc_idx)
 {
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	struct ieee80211_hdr *hdr = rtl_get_hdr(skb);
-	__le16 fc = rtl_get_fc(skb);
-	bool unicast = false;
-	struct sk_buff *uskb = NULL;
-	u8 *pdata;
-
+	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+	u32 bufferaddress;
+	u8 tmp_one = 1;
+	struct sk_buff *skb;
+
+	skb = dev_alloc_skb(rtlpci->rxbuffersize);
+	if (!skb)
+		return 0;
+	rtlpci->rx_ring[rxring_idx].rx_buf[desc_idx] = skb;
+
+	/* just set skb->cb to mapping addr
+	 * for pci_unmap_single use */
+	*((dma_addr_t *) skb->cb) = pci_map_single(rtlpci->pdev,
+				skb_tail_pointer(skb), rtlpci->rxbuffersize,
+				PCI_DMA_FROMDEVICE);
+	bufferaddress = *((dma_addr_t *) skb->cb);
+
+	rtlpriv->cfg->ops->set_desc((u8 *)entry, false, HW_DESC_RXBUFF_ADDR,
+				    (u8 *)&bufferaddress);
+	rtlpriv->cfg->ops->set_desc((u8 *)entry, false, HW_DESC_RXPKT_LEN,
+				    (u8 *)&rtlpci->
+				    rxbuffersize);
+	rtlpriv->cfg->ops->set_desc((u8 *)entry, false, HW_DESC_RXOWN,
+				    (u8 *)&tmp_one);
 
-	memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status));
+	return 1;
+}
 
-	if (is_broadcast_ether_addr(hdr->addr1)) {
-		;/*TODO*/
-	} else if (is_multicast_ether_addr(hdr->addr1)) {
-		;/*TODO*/
+/* inorder to receive 8K AMSDU we have set skb to
+ * 9100bytes in init rx ring, but if this packet is
+ * not a AMSDU, this so big packet will be sent to
+ * TCP/IP directly, this cause big packet ping fail
+ * like: "ping -s 65507", so here we will realloc skb
+ * based on the true size of packet, I think mac80211
+ * do it will be better, but now mac80211 haven't */
+
+/* but some platform will fail when alloc skb sometimes.
+ * in this condition, we will send the old skb to
+ * mac80211 directly, this will not cause any other
+ * issues, but only be losted by TCP/IP */
+static void _rtl_pci_rx_to_mac80211(struct ieee80211_hw *hw,
+	struct sk_buff *skb, struct ieee80211_rx_status rx_status)
+{
+	if (unlikely(!rtl_action_proc(hw, skb, false))) {
+		dev_kfree_skb_any(skb);
 	} else {
-		unicast = true;
-		rtlpriv->stats.rxbytesunicast += skb->len;
-	}
-
-	rtl_is_special_data(hw, skb, false);
-
-	if (ieee80211_is_data(fc)) {
-		rtlpriv->cfg->ops->led_control(hw, LED_CTL_RX);
-
-		if (unicast)
-			rtlpriv->link_info.num_rx_inperiod++;
+		struct sk_buff *uskb = NULL;
+		u8 *pdata;
+
+		uskb = dev_alloc_skb(skb->len + 128);
+		if (likely(uskb)) {
+			memcpy(IEEE80211_SKB_RXCB(uskb), &rx_status,
+			       sizeof(rx_status));
+			pdata = (u8 *)skb_put(uskb, skb->len);
+			memcpy(pdata, skb->data, skb->len);
+			dev_kfree_skb_any(skb);
+
+			ieee80211_rx_irqsafe(hw, uskb);
+		} else {
+			ieee80211_rx_irqsafe(hw, skb);
+		}
 	}
-
-	/* for sw lps */
-	rtl_swlps_beacon(hw, (void *)skb->data, skb->len);
-	rtl_recognize_peer(hw, (void *)skb->data, skb->len);
-	if ((rtlpriv->mac80211.opmode == NL80211_IFTYPE_AP) &&
-	    (rtlpriv->rtlhal.current_bandtype == BAND_ON_2_4G) &&
-	     (ieee80211_is_beacon(fc) || ieee80211_is_probe_resp(fc)))
-		return;
-
-	if (unlikely(!rtl_action_proc(hw, skb, false)))
-		return;
-
-	uskb = dev_alloc_skb(skb->len + 128);
-	if (!uskb)
-		return;		/* exit if allocation failed */
-	memcpy(IEEE80211_SKB_RXCB(uskb), &rx_status, sizeof(rx_status));
-	pdata = (u8 *)skb_put(uskb, skb->len);
-	memcpy(pdata, skb->data, skb->len);
-
-	ieee80211_rx_irqsafe(hw, uskb);
 }
 
 static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw)
 {
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
-	int rx_queue_idx = RTL_PCI_RX_MPDU_QUEUE;
+	int rxring_idx = RTL_PCI_RX_MPDU_QUEUE;
 
 	struct ieee80211_rx_status rx_status = { 0 };
 	unsigned int count = rtlpci->rxringcount;
 	u8 own;
 	u8 tmp_one;
-	u32 bufferaddress;
+	bool unicast = false;
 
 	struct rtl_stats stats = {
 		.signal = 0,
 		.noise = -98,
 		.rate = 0,
 	};
-	int index = rtlpci->rx_ring[rx_queue_idx].idx;
 
 	/*RX NORMAL PKT */
 	while (count--) {
+		int index = rtlpci->rx_ring[rxring_idx].idx;
 		/*rx descriptor */
-		struct rtl_rx_desc *pdesc = &rtlpci->rx_ring[rx_queue_idx].desc[
+		struct rtl_rx_desc *pdesc = &rtlpci->rx_ring[rxring_idx].desc[
 				index];
 		/*rx pkt */
-		struct sk_buff *skb = rtlpci->rx_ring[rx_queue_idx].rx_buf[
+		struct sk_buff *skb = rtlpci->rx_ring[rxring_idx].rx_buf[
 				index];
-		struct sk_buff *new_skb = NULL;
 
 		own = (u8) rtlpriv->cfg->ops->get_desc((u8 *) pdesc,
 						       false, HW_DESC_OWN);
 
-		/*wait data to be filled by hardware */
-		if (own)
-			break;
-
-		rtlpriv->cfg->ops->query_rx_desc(hw, &stats,
-						 &rx_status,
-						 (u8 *) pdesc, skb);
-
-		if (stats.crc || stats.hwerror)
-			goto done;
+		if (own) {
+			/*wait data to be filled by hardware */
+			return;
+		} else {
+			struct ieee80211_hdr *hdr;
+			__le16 fc;
 
-		new_skb = dev_alloc_skb(rtlpci->rxbuffersize);
-		if (unlikely(!new_skb)) {
-			RT_TRACE(rtlpriv, (COMP_INTR | COMP_RECV), DBG_DMESG,
-				 "can't alloc skb for rx\n");
-			goto done;
-		}
+			rtlpriv->cfg->ops->query_rx_desc(hw, &stats,
+							 &rx_status,
+							 (u8 *)pdesc, skb);
+			pci_unmap_single(rtlpci->pdev, *((dma_addr_t *)skb->cb),
+					 rtlpci->rxbuffersize,
+					 PCI_DMA_FROMDEVICE);
 
-		pci_unmap_single(rtlpci->pdev,
-				 *((dma_addr_t *) skb->cb),
-				 rtlpci->rxbuffersize,
-				 PCI_DMA_FROMDEVICE);
+			skb_put(skb, rtlpriv->cfg->ops->get_desc((u8 *) pdesc,
+				false,	 HW_DESC_RXPKT_LEN));
+			skb_reserve(skb, stats.rx_drvinfo_size +
+				    stats.rx_bufshift);
 
-		skb_put(skb, rtlpriv->cfg->ops->get_desc((u8 *) pdesc, false,
-			HW_DESC_RXPKT_LEN));
-		skb_reserve(skb, stats.rx_drvinfo_size + stats.rx_bufshift);
+			/*
+			 *NOTICE This can not be use for mac80211,
+			 *this is done in mac80211 code,
+			 *if you done here sec DHCP will fail
+			 *skb_trim(skb, skb->len - 4);
+			 */
 
-		/*
-		 * NOTICE This can not be use for mac80211,
-		 * this is done in mac80211 code,
-		 * if you done here sec DHCP will fail
-		 * skb_trim(skb, skb->len - 4);
-		 */
+			hdr = rtl_get_hdr(skb);
+			fc = rtl_get_fc(skb);
+
+			if (!stats.crc && !stats.hwerror) {
+				memcpy(IEEE80211_SKB_RXCB(skb), &rx_status,
+				       sizeof(rx_status));
+
+				if (is_broadcast_ether_addr(hdr->addr1)) {
+					;/*TODO*/
+				} else if (is_multicast_ether_addr(hdr->addr1)) {
+					;/*TODO*/
+				} else {
+					unicast = true;
+					rtlpriv->stats.rxbytesunicast += skb->len;
+				}
+
+				rtl_is_special_data(hw, skb, false);
+
+				if (ieee80211_is_data(fc)) {
+					rtlpriv->cfg->ops->led_control(hw,
+							 LED_CTL_RX);
+
+					if (unicast)
+						rtlpriv->link_info.num_rx_inperiod++;
+				}
+
+				/* static bcn for roaming */
+				rtl_beacon_statistic(hw, skb);
+
+				/* for sw lps */
+				rtl_swlps_beacon(hw, (void *)skb->data,
+						 skb->len);
+				rtl_recognize_peer(hw, (void *)skb->data,
+						   skb->len);
+				if ((rtlpriv->mac80211.opmode ==
+				     NL80211_IFTYPE_AP) &&
+				    (rtlpriv->rtlhal.current_bandtype ==
+				    BAND_ON_2_4G) &&
+				    (ieee80211_is_beacon(fc) ||
+				    ieee80211_is_probe_resp(fc)))
+					dev_kfree_skb_any(skb);
+				else
+					_rtl_pci_rx_to_mac80211(hw, skb,
+								rx_status);
+			} else {
+				dev_kfree_skb_any(skb);
+			}
 
-		_rtl_receive_one(hw, skb, rx_status);
+			if (((rtlpriv->link_info.num_rx_inperiod +
+				rtlpriv->link_info.num_tx_inperiod) > 8) ||
+				(rtlpriv->link_info.num_rx_inperiod > 2))
+				rtl_lps_leave(hw);
 
-		if (((rtlpriv->link_info.num_rx_inperiod +
-			rtlpriv->link_info.num_tx_inperiod) > 8) ||
-			(rtlpriv->link_info.num_rx_inperiod > 2)) {
-			schedule_work(&rtlpriv->works.lps_leave_work);
+			_rtl_pci_init_one_rxdesc(hw, pdesc, rxring_idx,
+					rtlpci->rx_ring[rxring_idx].idx);
 		}
 
-		dev_kfree_skb_any(skb);
-		skb = new_skb;
-
-		rtlpci->rx_ring[rx_queue_idx].rx_buf[index] = skb;
-		*((dma_addr_t *) skb->cb) =
-			    pci_map_single(rtlpci->pdev, skb_tail_pointer(skb),
-					   rtlpci->rxbuffersize,
-					   PCI_DMA_FROMDEVICE);
-
-done:
-		bufferaddress = (*((dma_addr_t *)skb->cb));
-		tmp_one = 1;
-		rtlpriv->cfg->ops->set_desc((u8 *) pdesc, false,
-					    HW_DESC_RXBUFF_ADDR,
-					    (u8 *)&bufferaddress);
-		rtlpriv->cfg->ops->set_desc((u8 *)pdesc, false,
-					    HW_DESC_RXPKT_LEN,
-					    (u8 *)&rtlpci->rxbuffersize);
-
-		if (index == rtlpci->rxringcount - 1)
+		if (rtlpci->rx_ring[rxring_idx].idx == rtlpci->rxringcount - 1)
 			rtlpriv->cfg->ops->set_desc((u8 *)pdesc, false,
-						    HW_DESC_RXERO,
-						    &tmp_one);
-
-		rtlpriv->cfg->ops->set_desc((u8 *)pdesc, false, HW_DESC_RXOWN,
-					    &tmp_one);
-
-		index = (index + 1) % rtlpci->rxringcount;
+						     HW_DESC_RXERO,
+						     &tmp_one);
+		rtlpci->rx_ring[rxring_idx].idx = (rtlpci->rx_ring[rxring_idx].idx
+						   + 1)%rtlpci->rxringcount;
 	}
-
-	rtlpci->rx_ring[rx_queue_idx].idx = index;
 }
 
 static irqreturn_t _rtl_pci_interrupt(int irq, void *dev_id)
@@ -775,7 +865,6 @@ static irqreturn_t _rtl_pci_interrupt(int irq, void *dev_id)
 	unsigned long flags;
 	u32 inta = 0;
 	u32 intb = 0;
-	irqreturn_t ret = IRQ_HANDLED;
 
 	spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags);
 
@@ -783,10 +872,8 @@ static irqreturn_t _rtl_pci_interrupt(int irq, void *dev_id)
 	rtlpriv->cfg->ops->interrupt_recognized(hw, &inta, &intb);
 
 	/*Shared IRQ or HW disappared */
-	if (!inta || inta == 0xffff) {
-		ret = IRQ_NONE;
+	if (!inta || inta == 0xffff)
 		goto done;
-	}
 
 	/*<1> beacon related */
 	if (inta & rtlpriv->cfg->maps[RTL_IMR_TBDOK]) {
@@ -889,7 +976,7 @@ static irqreturn_t _rtl_pci_interrupt(int irq, void *dev_id)
 
 done:
 	spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags);
-	return ret;
+	return IRQ_HANDLED;
 }
 
 static void _rtl_pci_irq_tasklet(struct ieee80211_hw *hw)
@@ -939,15 +1026,6 @@ static void _rtl_pci_prepare_bcn_tasklet(struct ieee80211_hw *hw)
 	return;
 }
 
-static void rtl_lps_leave_work_callback(struct work_struct *work)
-{
-	struct rtl_works *rtlworks =
-	    container_of(work, struct rtl_works, lps_leave_work);
-	struct ieee80211_hw *hw = rtlworks->hw;
-
-	rtl_lps_leave(hw);
-}
-
 static void _rtl_pci_init_trx_var(struct ieee80211_hw *hw)
 {
 	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
@@ -1009,7 +1087,6 @@ static void _rtl_pci_init_struct(struct ieee80211_hw *hw,
 	tasklet_init(&rtlpriv->works.irq_prepare_bcn_tasklet,
 		     (void (*)(unsigned long))_rtl_pci_prepare_bcn_tasklet,
 		     (unsigned long)hw);
-	INIT_WORK(&rtlpriv->works.lps_leave_work, rtl_lps_leave_work_callback);
 }
 
 static int _rtl_pci_init_tx_ring(struct ieee80211_hw *hw,
@@ -1022,6 +1099,7 @@ static int _rtl_pci_init_tx_ring(struct ieee80211_hw *hw,
 	u32 nextdescaddress;
 	int i;
 
+	/* alloc dma for this ring */
 	ring = pci_alloc_consistent(rtlpci->pdev,
 				    sizeof(*ring) * entries, &dma);
 
@@ -1041,6 +1119,7 @@ static int _rtl_pci_init_tx_ring(struct ieee80211_hw *hw,
 	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "queue:%d, ring_addr:%p\n",
 		 prio, ring);
 
+	/* init every desc in this ring */
 	for (i = 0; i < entries; i++) {
 		nextdescaddress = (u32) dma +
 					      ((i + 1) % entries) *
@@ -1054,84 +1133,38 @@ static int _rtl_pci_init_tx_ring(struct ieee80211_hw *hw,
 	return 0;
 }
 
-static int _rtl_pci_init_rx_ring(struct ieee80211_hw *hw)
+static int _rtl_pci_init_rx_ring(struct ieee80211_hw *hw, int rxring_idx)
 {
 	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	struct rtl_rx_desc *entry = NULL;
-	int i, rx_queue_idx;
+	int i;
 	u8 tmp_one = 1;
 
-	/*
-	 *rx_queue_idx 0:RX_MPDU_QUEUE
-	 *rx_queue_idx 1:RX_CMD_QUEUE
-	 */
-	for (rx_queue_idx = 0; rx_queue_idx < RTL_PCI_MAX_RX_QUEUE;
-	     rx_queue_idx++) {
-		rtlpci->rx_ring[rx_queue_idx].desc =
-		    pci_alloc_consistent(rtlpci->pdev,
-					 sizeof(*rtlpci->rx_ring[rx_queue_idx].
-						desc) * rtlpci->rxringcount,
-					 &rtlpci->rx_ring[rx_queue_idx].dma);
-
-		if (!rtlpci->rx_ring[rx_queue_idx].desc ||
-		    (unsigned long)rtlpci->rx_ring[rx_queue_idx].desc & 0xFF) {
-			RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
-				 "Cannot allocate RX ring\n");
-			return -ENOMEM;
-		}
-
-		memset(rtlpci->rx_ring[rx_queue_idx].desc, 0,
-		       sizeof(*rtlpci->rx_ring[rx_queue_idx].desc) *
-		       rtlpci->rxringcount);
-
-		rtlpci->rx_ring[rx_queue_idx].idx = 0;
-
-		/* If amsdu_8k is disabled, set buffersize to 4096. This
-		 * change will reduce memory fragmentation.
-		 */
-		if (rtlpci->rxbuffersize > 4096 &&
-		    rtlpriv->rtlhal.disable_amsdu_8k)
-			rtlpci->rxbuffersize = 4096;
-
-		for (i = 0; i < rtlpci->rxringcount; i++) {
-			struct sk_buff *skb =
-			    dev_alloc_skb(rtlpci->rxbuffersize);
-			u32 bufferaddress;
-			if (!skb)
-				return 0;
-			kmemleak_not_leak(skb);
-			entry = &rtlpci->rx_ring[rx_queue_idx].desc[i];
-
-			/*skb->dev = dev; */
-
-			rtlpci->rx_ring[rx_queue_idx].rx_buf[i] = skb;
+	/* alloc dma for this ring */
+	rtlpci->rx_ring[rxring_idx].desc = pci_alloc_consistent(rtlpci->pdev,
+			 sizeof(*rtlpci->rx_ring[rxring_idx].desc) *
+			 rtlpci->rxringcount, &rtlpci->rx_ring[rxring_idx].dma);
+	if (!rtlpci->rx_ring[rxring_idx].desc ||
+	    (unsigned long)rtlpci->rx_ring[rxring_idx].desc & 0xFF) {
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+			 "Cannot allocate RX ring\n");
+		return -ENOMEM;
+	}
 
-			/*
-			 *just set skb->cb to mapping addr
-			 *for pci_unmap_single use
-			 */
-			*((dma_addr_t *) skb->cb) =
-			    pci_map_single(rtlpci->pdev, skb_tail_pointer(skb),
-					   rtlpci->rxbuffersize,
-					   PCI_DMA_FROMDEVICE);
-
-			bufferaddress = (*((dma_addr_t *)skb->cb));
-			rtlpriv->cfg->ops->set_desc((u8 *)entry, false,
-						    HW_DESC_RXBUFF_ADDR,
-						    (u8 *)&bufferaddress);
-			rtlpriv->cfg->ops->set_desc((u8 *)entry, false,
-						    HW_DESC_RXPKT_LEN,
-						    (u8 *)&rtlpci->
-						    rxbuffersize);
-			rtlpriv->cfg->ops->set_desc((u8 *) entry, false,
-						    HW_DESC_RXOWN,
-						    &tmp_one);
-		}
+	memset(rtlpci->rx_ring[rxring_idx].desc, 0,
+			sizeof(*rtlpci->rx_ring[rxring_idx].desc) *
+			rtlpci->rxringcount);
 
-		rtlpriv->cfg->ops->set_desc((u8 *) entry, false,
-					    HW_DESC_RXERO, &tmp_one);
+	/* init every desc in this ring */
+	rtlpci->rx_ring[rxring_idx].idx = 0;
+	for (i = 0; i < rtlpci->rxringcount; i++) {
+		entry = &rtlpci->rx_ring[rxring_idx].desc[i];
+		if (!_rtl_pci_init_one_rxdesc(hw, entry, rxring_idx, i))
+			return -ENOMEM;
 	}
+	rtlpriv->cfg->ops->set_desc((u8 *) entry, false,
+				    HW_DESC_RXERO, &tmp_one);
 	return 0;
 }
 
@@ -1142,6 +1175,7 @@ static void _rtl_pci_free_tx_ring(struct ieee80211_hw *hw,
 	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
 	struct rtl8192_tx_ring *ring = &rtlpci->tx_ring[prio];
 
+	/* free every desc in this ring */
 	while (skb_queue_len(&ring->queue)) {
 		struct rtl_tx_desc *entry = &ring->desc[ring->idx];
 		struct sk_buff *skb = __skb_dequeue(&ring->queue);
@@ -1155,6 +1189,7 @@ static void _rtl_pci_free_tx_ring(struct ieee80211_hw *hw,
 		ring->idx = (ring->idx + 1) % ring->entries;
 	}
 
+	/* free dma of this ring */
 	if (ring->desc) {
 		pci_free_consistent(rtlpci->pdev,
 				    sizeof(*ring->desc) * ring->entries,
@@ -1163,35 +1198,30 @@ static void _rtl_pci_free_tx_ring(struct ieee80211_hw *hw,
 	}
 }
 
-static void _rtl_pci_free_rx_ring(struct rtl_pci *rtlpci)
+static void _rtl_pci_free_rx_ring(struct rtl_pci *rtlpci,
+			int rxring_idx)
 {
-	int i, rx_queue_idx;
-
-	/*rx_queue_idx 0:RX_MPDU_QUEUE */
-	/*rx_queue_idx 1:RX_CMD_QUEUE */
-	for (rx_queue_idx = 0; rx_queue_idx < RTL_PCI_MAX_RX_QUEUE;
-	     rx_queue_idx++) {
-		for (i = 0; i < rtlpci->rxringcount; i++) {
-			struct sk_buff *skb =
-			    rtlpci->rx_ring[rx_queue_idx].rx_buf[i];
-			if (!skb)
-				continue;
-
-			pci_unmap_single(rtlpci->pdev,
-					 *((dma_addr_t *) skb->cb),
-					 rtlpci->rxbuffersize,
-					 PCI_DMA_FROMDEVICE);
-			kfree_skb(skb);
-		}
+	int i;
 
-		if (rtlpci->rx_ring[rx_queue_idx].desc) {
-			pci_free_consistent(rtlpci->pdev,
-				    sizeof(*rtlpci->rx_ring[rx_queue_idx].
-					   desc) * rtlpci->rxringcount,
-				    rtlpci->rx_ring[rx_queue_idx].desc,
-				    rtlpci->rx_ring[rx_queue_idx].dma);
-			rtlpci->rx_ring[rx_queue_idx].desc = NULL;
-		}
+	/* free every desc in this ring */
+	for (i = 0; i < rtlpci->rxringcount; i++) {
+		struct sk_buff *skb = rtlpci->rx_ring[rxring_idx].rx_buf[i];
+		if (!skb)
+			continue;
+
+		pci_unmap_single(rtlpci->pdev, *((dma_addr_t *) skb->cb),
+				 rtlpci->rxbuffersize, PCI_DMA_FROMDEVICE);
+		kfree_skb(skb);
+	}
+
+	/* free dma of this ring */
+	if (rtlpci->rx_ring[rxring_idx].desc) {
+		pci_free_consistent(rtlpci->pdev,
+			    sizeof(*rtlpci->rx_ring[rxring_idx].desc) *
+			    rtlpci->rxringcount,
+			    rtlpci->rx_ring[rxring_idx].desc,
+			    rtlpci->rx_ring[rxring_idx].dma);
+		rtlpci->rx_ring[rxring_idx].desc = NULL;
 	}
 }
 
@@ -1199,15 +1229,19 @@ static int _rtl_pci_init_trx_ring(struct ieee80211_hw *hw)
 {
 	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
 	int ret;
-	int i;
+	int i, rxring_idx;
 
-	ret = _rtl_pci_init_rx_ring(hw);
-	if (ret)
-		return ret;
+	/* rxring_idx 0:RX_MPDU_QUEUE
+	 * rxring_idx 1:RX_CMD_QUEUE */
+	for (rxring_idx = 0; rxring_idx < RTL_PCI_MAX_RX_QUEUE;
+	     rxring_idx++) {
+		ret = _rtl_pci_init_rx_ring(hw, rxring_idx);
+		if (ret)
+			return ret;
+	}
 
 	for (i = 0; i < RTL_PCI_MAX_TX_QUEUE_COUNT; i++) {
-		ret = _rtl_pci_init_tx_ring(hw, i,
-				 rtlpci->txringcount[i]);
+		ret = _rtl_pci_init_tx_ring(hw, i, rtlpci->txringcount[i]);
 		if (ret)
 			goto err_free_rings;
 	}
@@ -1215,7 +1249,9 @@ static int _rtl_pci_init_trx_ring(struct ieee80211_hw *hw)
 	return 0;
 
 err_free_rings:
-	_rtl_pci_free_rx_ring(rtlpci);
+	for (rxring_idx = 0; rxring_idx < RTL_PCI_MAX_RX_QUEUE;
+	     rxring_idx++)
+		_rtl_pci_free_rx_ring(rtlpci, rxring_idx);
 
 	for (i = 0; i < RTL_PCI_MAX_TX_QUEUE_COUNT; i++)
 		if (rtlpci->tx_ring[i].desc)
@@ -1227,10 +1263,12 @@ err_free_rings:
 static int _rtl_pci_deinit_trx_ring(struct ieee80211_hw *hw)
 {
 	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
-	u32 i;
+	u32 i, rxring_idx;
 
 	/*free rx rings */
-	_rtl_pci_free_rx_ring(rtlpci);
+	for (rxring_idx = 0; rxring_idx < RTL_PCI_MAX_RX_QUEUE;
+	     rxring_idx++)
+		_rtl_pci_free_rx_ring(rtlpci, rxring_idx);
 
 	/*free tx rings */
 	for (i = 0; i < RTL_PCI_MAX_TX_QUEUE_COUNT; i++)
@@ -1243,64 +1281,52 @@ int rtl_pci_reset_trx_ring(struct ieee80211_hw *hw)
 {
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
-	int i, rx_queue_idx;
+	int i, rxring_idx;
 	unsigned long flags;
 	u8 tmp_one = 1;
 
-	/*rx_queue_idx 0:RX_MPDU_QUEUE */
-	/*rx_queue_idx 1:RX_CMD_QUEUE */
-	for (rx_queue_idx = 0; rx_queue_idx < RTL_PCI_MAX_RX_QUEUE;
-	     rx_queue_idx++) {
-		/*
-		 *force the rx_ring[RX_MPDU_QUEUE/
-		 *RX_CMD_QUEUE].idx to the first one
-		 */
-		if (rtlpci->rx_ring[rx_queue_idx].desc) {
+	/* rxring_idx 0:RX_MPDU_QUEUE */
+	/* rxring_idx 1:RX_CMD_QUEUE */
+	for (rxring_idx = 0; rxring_idx < RTL_PCI_MAX_RX_QUEUE;
+	     rxring_idx++) {
+		/* force the rx_ring[RX_MPDU_QUEUE/
+		 * RX_CMD_QUEUE].idx to the first one */
+		if (rtlpci->rx_ring[rxring_idx].desc) {
 			struct rtl_rx_desc *entry = NULL;
 
 			for (i = 0; i < rtlpci->rxringcount; i++) {
-				entry = &rtlpci->rx_ring[rx_queue_idx].desc[i];
-				rtlpriv->cfg->ops->set_desc((u8 *) entry,
-							    false,
-							    HW_DESC_RXOWN,
-							    &tmp_one);
+				entry = &rtlpci->rx_ring[rxring_idx].desc[i];
+				rtlpriv->cfg->ops->set_desc((u8 *) entry, false,
+					    HW_DESC_RXOWN, &tmp_one);
 			}
-			rtlpci->rx_ring[rx_queue_idx].idx = 0;
+			rtlpci->rx_ring[rxring_idx].idx = 0;
 		}
 	}
 
-	/*
-	 *after reset, release previous pending packet,
-	 *and force the  tx idx to the first one
-	 */
+	/* after reset, release previous pending packet,
+	 * and force the  tx idx to the first one */
+	spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags);
 	for (i = 0; i < RTL_PCI_MAX_TX_QUEUE_COUNT; i++) {
 		if (rtlpci->tx_ring[i].desc) {
 			struct rtl8192_tx_ring *ring = &rtlpci->tx_ring[i];
 
 			while (skb_queue_len(&ring->queue)) {
-				struct rtl_tx_desc *entry;
-				struct sk_buff *skb;
+				struct rtl_tx_desc *entry = &ring->desc[ring->idx];
+				struct sk_buff *skb = __skb_dequeue(&ring->queue);
 
-				spin_lock_irqsave(&rtlpriv->locks.irq_th_lock,
-						  flags);
-				entry = &ring->desc[ring->idx];
-				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);
-				ring->idx = (ring->idx + 1) % ring->entries;
-				spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock,
-						  flags);
+					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;
 			}
 			ring->idx = 0;
 		}
 	}
 
+	spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags);
+
 	return 0;
 }
 
@@ -1312,6 +1338,7 @@ static bool rtl_pci_tx_chk_waitq_insert(struct ieee80211_hw *hw,
 	struct ieee80211_sta *sta = info->control.sta;
 	struct rtl_sta_info *sta_entry = NULL;
 	u8 tid = rtl_get_tid(skb);
+	__le16 fc = rtl_get_fc(skb);
 
 	if (!sta)
 		return false;
@@ -1319,6 +1346,12 @@ static bool rtl_pci_tx_chk_waitq_insert(struct ieee80211_hw *hw,
 
 	if (!rtlpriv->rtlhal.earlymode_enable)
 		return false;
+	if (ieee80211_is_nullfunc(fc))
+		return false;
+	if (ieee80211_is_qos_nullfunc(fc))
+		return false;
+	if (ieee80211_is_pspoll(fc))
+		return false;
 	if (sta_entry->tids[tid].agg.agg_state != RTL_AGG_OPERATIONAL)
 		return false;
 	if (_rtl_mac_to_hwqueue(hw, skb) > VO_QUEUE)
@@ -1359,10 +1392,8 @@ static int rtl_pci_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
 	u8 own;
 	u8 temp_one = 1;
 
-	if (ieee80211_is_auth(fc)) {
-		RT_TRACE(rtlpriv, COMP_SEND, DBG_DMESG, "MAC80211_LINKING\n");
-		rtl_ips_nic_on(hw);
-	}
+	if (ieee80211_is_mgmt(fc))
+		rtl_tx_mgmt_proc(hw, skb);
 
 	if (rtlpriv->psc.sw_ps_enabled) {
 		if (ieee80211_is_data(fc) && !ieee80211_is_nullfunc(fc) &&
@@ -1462,7 +1493,7 @@ static void rtl_pci_flush(struct ieee80211_hw *hw, bool drop)
 			queue_id--;
 			continue;
 		} else {
-			msleep(20);
+			usleep_range(5000, 6000);
 			i++;
 		}
 
@@ -1482,7 +1513,6 @@ static void rtl_pci_deinit(struct ieee80211_hw *hw)
 
 	synchronize_irq(rtlpci->pdev->irq);
 	tasklet_kill(&rtlpriv->works.irq_tasklet);
-	cancel_work_sync(&rtlpriv->works.lps_leave_work);
 
 	flush_workqueue(rtlpriv->works.rtl_wq);
 	destroy_workqueue(rtlpriv->works.rtl_wq);
@@ -1557,7 +1587,6 @@ static void rtl_pci_stop(struct ieee80211_hw *hw)
 	set_hal_stop(rtlhal);
 
 	rtlpriv->cfg->ops->disable_interrupt(hw);
-	cancel_work_sync(&rtlpriv->works.lps_leave_work);
 
 	spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flags);
 	while (ppsc->rfchange_inprogress) {
@@ -1630,7 +1659,7 @@ static bool _rtl_pci_find_adapter(struct pci_dev *pdev,
 				 "8192 PCI-E is found - vid/did=%x/%x\n",
 				 venderid, deviceid);
 			rtlhal->hw_type = HARDWARE_TYPE_RTL8192E;
-			break;
+			return false;
 		case RTL_PCI_REVISION_ID_8192SE:
 			RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
 				 "8192SE is found - vid/did=%x/%x\n",
@@ -1645,6 +1674,11 @@ static bool _rtl_pci_find_adapter(struct pci_dev *pdev,
 			break;
 
 		}
+	} else if (deviceid == RTL_PCI_8723AE_DID) {
+		rtlhal->hw_type = HARDWARE_TYPE_RTL8723AE;
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
+			 "8723AE PCI-E is found - "
+			 "vid/did=%x/%x\n", venderid, deviceid);
 	} else if (deviceid == RTL_PCI_8192CET_DID ||
 		   deviceid == RTL_PCI_8192CE_DID ||
 		   deviceid == RTL_PCI_8191CE_DID ||
@@ -1690,6 +1724,10 @@ static bool _rtl_pci_find_adapter(struct pci_dev *pdev,
 	pcipriv->ndis_adapter.devnumber = PCI_SLOT(pdev->devfn);
 	pcipriv->ndis_adapter.funcnumber = PCI_FUNC(pdev->devfn);
 
+	/*find bridge info */
+	pcipriv->ndis_adapter.pcibridge_vendor = PCI_BRIDGE_VENDOR_UNKNOWN;
+	/* some ARM have no bridge_pdev and will crash here
+	 * so we should check if bridge_pdev is NULL */
 	if (bridge_pdev) {
 		/*find bridge info if available */
 		pcipriv->ndis_adapter.pcibridge_vendorid = bridge_pdev->vendor;
@@ -1712,6 +1750,10 @@ static bool _rtl_pci_find_adapter(struct pci_dev *pdev,
 		    PCI_SLOT(bridge_pdev->devfn);
 		pcipriv->ndis_adapter.pcibridge_funcnum =
 		    PCI_FUNC(bridge_pdev->devfn);
+		pcipriv->ndis_adapter.pcicfg_addrport =
+		    (pcipriv->ndis_adapter.pcibridge_busnum << 16) |
+		    (pcipriv->ndis_adapter.pcibridge_devnum << 11) |
+		    (pcipriv->ndis_adapter.pcibridge_funcnum << 8) | (1 << 31);
 		pcipriv->ndis_adapter.pcibridge_pciehdr_offset =
 		    pci_pcie_cap(bridge_pdev);
 		pcipriv->ndis_adapter.num4bytes =
@@ -1744,10 +1786,15 @@ static bool _rtl_pci_find_adapter(struct pci_dev *pdev,
 		 pcipriv->ndis_adapter.amd_l1_patch);
 
 	rtl_pci_parse_configuration(pdev, hw);
-
+	list_add_tail(&rtlpriv->list, &rtlpriv->glb_var->glb_priv_list);
 	return true;
 }
 
+/* this is used for other modules get
+ * hw pointer in rtl_pci_get_hw_pointer
+ */
+static struct ieee80211_hw *hw_export;
+
 int __devinit rtl_pci_probe(struct pci_dev *pdev,
 			    const struct pci_device_id *id)
 {
@@ -1785,6 +1832,7 @@ int __devinit rtl_pci_probe(struct pci_dev *pdev,
 		err = -ENOMEM;
 		goto fail1;
 	}
+	hw_export = hw;
 
 	SET_IEEE80211_DEV(hw, &pdev->dev);
 	pci_set_drvdata(pdev, hw);
@@ -1798,6 +1846,7 @@ int __devinit rtl_pci_probe(struct pci_dev *pdev,
 	rtlpriv->rtlhal.interface = INTF_PCI;
 	rtlpriv->cfg = (struct rtl_hal_cfg *)(id->driver_data);
 	rtlpriv->intf_ops = &rtl_pci_ops;
+	rtlpriv->glb_var = &global_var;
 
 	/*
 	 *init dbgp flags before all
@@ -1843,6 +1892,7 @@ int __devinit rtl_pci_probe(struct pci_dev *pdev,
 	pci_write_config_byte(pdev, 0x04, 0x07);
 
 	/* find adapter */
+	/* if chip not supported, will return false */
 	if (!_rtl_pci_find_adapter(pdev, hw)) {
 		err = -ENODEV;
 		goto fail3;
@@ -1898,6 +1948,7 @@ int __devinit rtl_pci_probe(struct pci_dev *pdev,
 	}
 	rtlpci->irq_alloc = 1;
 
+	set_bit(RTL_STATUS_INTERFACE_START, &rtlpriv->status);
 	return 0;
 
 fail3:
@@ -1922,6 +1973,12 @@ fail1:
 }
 EXPORT_SYMBOL(rtl_pci_probe);
 
+struct ieee80211_hw *rtl_pci_get_hw_pointer(void)
+{
+	return hw_export;
+}
+EXPORT_SYMBOL(rtl_pci_get_hw_pointer);
+
 void rtl_pci_disconnect(struct pci_dev *pdev)
 {
 	struct ieee80211_hw *hw = pci_get_drvdata(pdev);
@@ -1955,10 +2012,12 @@ void rtl_pci_disconnect(struct pci_dev *pdev)
 	rtlpriv->cfg->ops->deinit_sw_vars(hw);
 
 	if (rtlpci->irq_alloc) {
+		synchronize_irq(rtlpci->pdev->irq);
 		free_irq(rtlpci->pdev->irq, hw);
 		rtlpci->irq_alloc = 0;
 	}
 
+	list_del(&rtlpriv->list);
 	if (rtlpriv->io.pci_mem_start != 0) {
 		pci_iounmap(pdev, (void __iomem *)rtlpriv->io.pci_mem_start);
 		pci_release_regions(pdev);
@@ -2018,6 +2077,7 @@ struct rtl_intf_ops rtl_pci_ops = {
 	.read_efuse_byte = read_efuse_byte,
 	.adapter_start = rtl_pci_start,
 	.adapter_stop = rtl_pci_stop,
+	.check_buddy_priv = rtl_pci_check_buddy_priv,
 	.adapter_tx = rtl_pci_tx,
 	.flush = rtl_pci_flush,
 	.reset_trx_ring = rtl_pci_reset_trx_ring,
diff --git a/drivers/net/wireless/rtlwifi/pci.h b/drivers/net/wireless/rtlwifi/pci.h
index 241448f..12975a3 100644
--- a/drivers/net/wireless/rtlwifi/pci.h
+++ b/drivers/net/wireless/rtlwifi/pci.h
@@ -86,6 +86,7 @@
 #define RTL_PCI_700F_DID	0x700F
 #define RTL_PCI_701F_DID	0x701F
 #define RTL_PCI_DLINK_DID	0x3304
+#define RTL_PCI_8723AE_DID	0x8723	/*8723e */
 #define RTL_PCI_8192CET_DID	0x8191	/*8192ce */
 #define RTL_PCI_8192CE_DID	0x8178	/*8192ce */
 #define RTL_PCI_8191CE_DID	0x8177	/*8192ce */
@@ -212,6 +213,7 @@ struct mp_adapter {
 	u16 pcibridge_vendorid;
 	u16 pcibridge_deviceid;
 
+	u32 pcicfg_addrport;
 	u8 num4bytes;
 
 	u8 pcibridge_pciehdr_offset;
@@ -239,6 +241,7 @@ int __devinit rtl_pci_probe(struct pci_dev *pdev,
 void rtl_pci_disconnect(struct pci_dev *pdev);
 int rtl_pci_suspend(struct device *dev);
 int rtl_pci_resume(struct device *dev);
+struct ieee80211_hw *rtl_pci_get_hw_pointer(void);
 static inline u8 pci_read8_sync(struct rtl_priv *rtlpriv, u32 addr)
 {
 	return readb((u8 __iomem *) rtlpriv->io.pci_mem_start + addr);
diff --git a/drivers/net/wireless/rtlwifi/ps.c b/drivers/net/wireless/rtlwifi/ps.c
index 13ad33e..ce9ca3f 100644
--- a/drivers/net/wireless/rtlwifi/ps.c
+++ b/drivers/net/wireless/rtlwifi/ps.c
@@ -48,7 +48,7 @@ bool rtl_ps_enable_nic(struct ieee80211_hw *hw)
 
 	/*<2> Enable Adapter */
 	if (rtlpriv->cfg->ops->hw_init(hw))
-		return 1;
+		return false;
 	RT_CLEAR_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC);
 
 	/*<3> Enable Interrupt */
@@ -81,11 +81,53 @@ EXPORT_SYMBOL(rtl_ps_disable_nic);
 
 bool rtl_ps_set_rf_state(struct ieee80211_hw *hw,
 			 enum rf_pwrstate state_toset,
-			 u32 changesource)
+			 u32 changesource, bool protect_or_not)
 {
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
+	enum rf_pwrstate rtstate;
 	bool actionallowed = false;
+	u16 rfwait_cnt = 0;
+
+	if (protect_or_not)
+		goto no_protect;
+
+	/*
+	 *Only one thread can change
+	 *the RF state at one time, and others
+	 *should wait to be executed.
+	 */
+	while (true) {
+		spin_lock(&rtlpriv->locks.rf_ps_lock);
+		if (ppsc->rfchange_inprogress) {
+			spin_unlock(&rtlpriv->locks.rf_ps_lock);
+
+			RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
+				 "RF Change in progress!"
+				  "Wait to set..state_toset(%d).\n",
+				  state_toset);
+
+			/* Set RF after the previous action is done.  */
+			while (ppsc->rfchange_inprogress) {
+				rfwait_cnt++;
+				mdelay(1);
+
+				/*
+				 *Waited too long, return false to avoid
+				 *to be stuck here.
+				 */
+				if (rfwait_cnt > 100)
+					return false;
+			}
+		} else {
+			ppsc->rfchange_inprogress = true;
+			spin_unlock(&rtlpriv->locks.rf_ps_lock);
+			break;
+		}
+	}
+
+no_protect:
+	rtstate = ppsc->rfpwr_state;
 
 	switch (state_toset) {
 	case ERFON:
@@ -127,6 +169,12 @@ bool rtl_ps_set_rf_state(struct ieee80211_hw *hw,
 	if (actionallowed)
 		rtlpriv->cfg->ops->set_rf_power_state(hw, state_toset);
 
+	if (!protect_or_not) {
+		spin_lock(&rtlpriv->locks.rf_ps_lock);
+		ppsc->rfchange_inprogress = false;
+		spin_unlock(&rtlpriv->locks.rf_ps_lock);
+	}
+
 	return actionallowed;
 }
 EXPORT_SYMBOL(rtl_ps_set_rf_state);
@@ -149,7 +197,8 @@ static void _rtl_ps_inactive_ps(struct ieee80211_hw *hw)
 		}
 	}
 
-	rtl_ps_set_rf_state(hw, ppsc->inactive_pwrstate, RF_CHANGE_BY_IPS);
+	rtl_ps_set_rf_state(hw, ppsc->inactive_pwrstate,
+			    RF_CHANGE_BY_IPS, false);
 
 	if (ppsc->inactive_pwrstate == ERFOFF &&
 	    rtlhal->interface == INTF_PCI) {
@@ -231,17 +280,16 @@ void rtl_ips_nic_off(struct ieee80211_hw *hw)
 			   &rtlpriv->works.ips_nic_off_wq, MSECS(100));
 }
 
+/* NOTICE: any opmode should exc nic_on, or disable without
+ * nic_on may ndicate that something is wrong, like adhoc TP
+ */
 void rtl_ips_nic_on(struct ieee80211_hw *hw)
 {
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
 	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
 	enum rf_pwrstate rtstate;
 	unsigned long flags;
 
-	if (mac->opmode != NL80211_IFTYPE_STATION)
-		return;
-
 	spin_lock_irqsave(&rtlpriv->locks.ips_lock, flags);
 
 	if (ppsc->inactiveps) {
@@ -375,6 +423,7 @@ void rtl_lps_enter(struct ieee80211_hw *hw)
 	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
 	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	unsigned long flag;
 
 	if (!ppsc->fwctrl_lps)
 		return;
@@ -395,7 +444,7 @@ void rtl_lps_enter(struct ieee80211_hw *hw)
 	if (mac->link_state != MAC80211_LINKED)
 		return;
 
-	mutex_lock(&rtlpriv->locks.ps_mutex);
+	spin_lock_irqsave(&rtlpriv->locks.lps_lock, flag);
 
 	/* Idle for a while if we connect to AP a while ago. */
 	if (mac->cnt_after_linked >= 2) {
@@ -407,7 +456,7 @@ void rtl_lps_enter(struct ieee80211_hw *hw)
 		}
 	}
 
-	mutex_unlock(&rtlpriv->locks.ps_mutex);
+	spin_unlock_irqrestore(&rtlpriv->locks.lps_lock, flag);
 }
 
 /*Leave the leisure power save mode.*/
@@ -416,8 +465,9 @@ void rtl_lps_leave(struct ieee80211_hw *hw)
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
 	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	unsigned long flag;
 
-	mutex_lock(&rtlpriv->locks.ps_mutex);
+	spin_lock_irqsave(&rtlpriv->locks.lps_lock, flag);
 
 	if (ppsc->fwctrl_lps) {
 		if (ppsc->dot11_psmode != EACTIVE) {
@@ -438,7 +488,7 @@ void rtl_lps_leave(struct ieee80211_hw *hw)
 			rtl_lps_set_psmode(hw, EACTIVE);
 		}
 	}
-	mutex_unlock(&rtlpriv->locks.ps_mutex);
+	spin_unlock_irqrestore(&rtlpriv->locks.lps_lock, flag);
 }
 
 /* For sw LPS*/
@@ -527,6 +577,7 @@ void rtl_swlps_rf_awake(struct ieee80211_hw *hw)
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
 	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+	unsigned long flag;
 
 	if (!rtlpriv->psc.swctrl_lps)
 		return;
@@ -539,9 +590,9 @@ void rtl_swlps_rf_awake(struct ieee80211_hw *hw)
 		RT_CLEAR_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM);
 	}
 
-	mutex_lock(&rtlpriv->locks.ps_mutex);
-	rtl_ps_set_rf_state(hw, ERFON, RF_CHANGE_BY_PS);
-	mutex_unlock(&rtlpriv->locks.ps_mutex);
+	spin_lock_irqsave(&rtlpriv->locks.lps_lock, flag);
+	rtl_ps_set_rf_state(hw, ERFON, RF_CHANGE_BY_PS, false);
+	spin_unlock_irqrestore(&rtlpriv->locks.lps_lock, flag);
 }
 
 void rtl_swlps_rfon_wq_callback(void *data)
@@ -559,6 +610,7 @@ void rtl_swlps_rf_sleep(struct ieee80211_hw *hw)
 	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
 	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
 	u8 sleep_intv;
+	unsigned long flags;
 
 	if (!rtlpriv->psc.sw_ps_enabled)
 		return;
@@ -574,9 +626,16 @@ void rtl_swlps_rf_sleep(struct ieee80211_hw *hw)
 	if (rtlpriv->link_info.busytraffic)
 		return;
 
-	mutex_lock(&rtlpriv->locks.ps_mutex);
-	rtl_ps_set_rf_state(hw, ERFSLEEP, RF_CHANGE_BY_PS);
-	mutex_unlock(&rtlpriv->locks.ps_mutex);
+	spin_lock(&rtlpriv->locks.rf_ps_lock);
+	if (rtlpriv->psc.rfchange_inprogress) {
+		spin_unlock(&rtlpriv->locks.rf_ps_lock);
+		return;
+	}
+	spin_unlock(&rtlpriv->locks.rf_ps_lock);
+
+	spin_lock_irqsave(&rtlpriv->locks.lps_lock, flags);
+	rtl_ps_set_rf_state(hw, ERFSLEEP, RF_CHANGE_BY_PS, false);
+	spin_unlock_irqrestore(&rtlpriv->locks.lps_lock, flags);
 
 	if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_ASPM &&
 		!RT_IN_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM)) {
diff --git a/drivers/net/wireless/rtlwifi/ps.h b/drivers/net/wireless/rtlwifi/ps.h
index 1357856..573dc9a 100644
--- a/drivers/net/wireless/rtlwifi/ps.h
+++ b/drivers/net/wireless/rtlwifi/ps.h
@@ -33,7 +33,8 @@
 #define MAX_SW_LPS_SLEEP_INTV	5
 
 bool rtl_ps_set_rf_state(struct ieee80211_hw *hw,
-			 enum rf_pwrstate state_toset, u32 changesource);
+			 enum rf_pwrstate state_toset, u32 changesource,
+			 bool protect_or_not);
 bool rtl_ps_enable_nic(struct ieee80211_hw *hw);
 bool rtl_ps_disable_nic(struct ieee80211_hw *hw);
 void rtl_ips_nic_off(struct ieee80211_hw *hw);
diff --git a/drivers/net/wireless/rtlwifi/rc.c b/drivers/net/wireless/rtlwifi/rc.c
index d5cbf01..21560ff 100644
--- a/drivers/net/wireless/rtlwifi/rc.c
+++ b/drivers/net/wireless/rtlwifi/rc.c
@@ -35,7 +35,8 @@
  *Finds the highest rate index we can use
  *if skb is special data like DHCP/EAPOL, we set should
  *it to lowest rate CCK_1M, otherwise we set rate to
- *CCK11M or OFDM_54M based on wireless mode.
+ *highest rate based on wireless mode used for
+ *iwconfig show Tx rate.
  */
 static u8 _rtl_rc_get_highest_rix(struct rtl_priv *rtlpriv,
 				  struct ieee80211_sta *sta,
diff --git a/drivers/net/wireless/rtlwifi/regd.c b/drivers/net/wireless/rtlwifi/regd.c
index c1608cd..3da6219 100644
--- a/drivers/net/wireless/rtlwifi/regd.c
+++ b/drivers/net/wireless/rtlwifi/regd.c
@@ -303,6 +303,22 @@ static void _rtl_reg_apply_world_flags(struct wiphy *wiphy,
 	return;
 }
 
+static void _rtl_dump_channel_map(struct wiphy *wiphy)
+{
+	enum ieee80211_band band;
+	struct ieee80211_supported_band *sband;
+	struct ieee80211_channel *ch;
+	unsigned int i;
+
+	for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
+		if (!wiphy->bands[band])
+			continue;
+		sband = wiphy->bands[band];
+		for (i = 0; i < sband->n_channels; i++)
+			ch = &sband->channels[i];
+	}
+}
+
 static int _rtl_reg_notifier_apply(struct wiphy *wiphy,
 				   struct regulatory_request *request,
 				   struct rtl_regulatory *reg)
@@ -320,6 +336,8 @@ static int _rtl_reg_notifier_apply(struct wiphy *wiphy,
 		break;
 	}
 
+	_rtl_dump_channel_map(wiphy);
+
 	return 0;
 }
 
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 5/6] rtlwifi: rtl8192ce: Update for new vendor driver version
  2012-08-21 15:00 [PATCH 0/6] Updates to rtlwifi family to match latest vendor version Larry Finger
                   ` (3 preceding siblings ...)
  2012-08-21 15:00 ` [PATCH 4/6] rtlwifi: Add changes for new vendor driver version Larry Finger
@ 2012-08-21 15:00 ` Larry Finger
  2012-08-21 15:00 ` [PATCH 6/6] rtlwifi: rtl8192se: Update driver for changes in 12/30/2011 vendor version Larry Finger
  5 siblings, 0 replies; 10+ messages in thread
From: Larry Finger @ 2012-08-21 15:00 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, Li Chaoming, Larry Finger

From: Li Chaoming <chaoming_li@realsil.com.cn>

Realtek driver version rtl_92ce_92se_92de_linux_mac80211_0005.1230.2011
includes a number of changes in rtl8192ce. The main differences are as
follows:

1. Include code for a number of new versions.
2. Update the signal strength reporting.
3. Update to handle 802.11w encryption correctly.

Signed-off-by: Li Chaoming <chaoming_li@realsil.com.cn>
Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net>
---
 drivers/net/wireless/rtlwifi/rtl8192ce/def.h |   12 ++-
 drivers/net/wireless/rtlwifi/rtl8192ce/hw.c  |  106 +++++++++++++++++++++-----
 drivers/net/wireless/rtlwifi/rtl8192ce/reg.h |    1 +
 drivers/net/wireless/rtlwifi/rtl8192ce/sw.c  |    1 +
 drivers/net/wireless/rtlwifi/rtl8192ce/trx.c |   70 +++++++++++++++--
 5 files changed, 164 insertions(+), 26 deletions(-)

diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/def.h b/drivers/net/wireless/rtlwifi/rtl8192ce/def.h
index 04c3aef..3e0432b 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/def.h
+++ b/drivers/net/wireless/rtlwifi/rtl8192ce/def.h
@@ -115,8 +115,18 @@
 #define	GET_C2H_CMD_FEEDBACK_CCX_SEQ(__pcmdfbhdr)	\
 	LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 20, 12)
 
-#define CHIP_VER_B			BIT(4)
+#define CHIP_BONDING_IDENTIFIER(_value)	(((_value) >> 22) & 0x3)
+#define	CHIP_BONDING_92C_1T2R		0x1
+
 #define CHIP_92C_BITMASK		BIT(0)
+#define RF_TYPE_1T2R			BIT(1)
+#define NORMAL_CHIP			BIT(4)
+#define CHIP_VENDOR_UMC			BIT(5)
+#define CHIP_VENDOR_UMC_B_CUT	BIT(6) /* Chip version for ECO */
+#define CHIP_UNKNOW			BIT(7)
+#define CUT_VERSION_MASK		(BIT(6)|BIT(7))
+#define RF_TYPE_MASK			(BIT(0)|BIT(1))
+#define CHIP_VER_B			BIT(4)
 #define CHIP_92C_1T2R			0x03
 #define CHIP_92C			0x01
 #define CHIP_88C			0x00
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c b/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c
index cc89582..a088ecd 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c
@@ -896,7 +896,6 @@ int rtl92ce_hw_init(struct ieee80211_hw *hw)
 	struct rtl_phy *rtlphy = &(rtlpriv->phy);
 	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
 	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
-	static bool iqk_initialized; /* initialized to false */
 	bool rtstatus = true;
 	bool is92c;
 	int err;
@@ -921,9 +920,29 @@ int rtl92ce_hw_init(struct ieee80211_hw *hw)
 
 	rtlhal->last_hmeboxnum = 0;
 	rtl92c_phy_mac_config(hw);
+	/* because last function modify RCR, we update
+	 * rcr var here, or TP will unstable for receive_config
+	 * is wrong, RX RCR_ACRC32 will cause TP unstabel & Rx
+	 * RCR_APP_ICV will cause mac80211 unassoc for Cisco 1252 */
+	rtlpci->receive_config = rtl_read_dword(rtlpriv, REG_RCR);
+	rtlpci->receive_config &= ~(RCR_ACRC32 | RCR_AICV);
+	rtl_write_dword(rtlpriv, REG_RCR, rtlpci->receive_config);
+
 	rtl92c_phy_bb_config(hw);
 	rtlphy->rf_mode = RF_OP_BY_SW_3WIRE;
 	rtl92c_phy_rf_config(hw);
+	if (IS_VENDOR_UMC_A_CUT(rtlhal->version) &&
+	    !IS_92C_SERIAL(rtlhal->version)) {
+		rtl_set_rfreg(hw, RF90_PATH_A, RF_RX_G1, MASKDWORD, 0x30255);
+		rtl_set_rfreg(hw, RF90_PATH_A, RF_RX_G2, MASKDWORD, 0x50a00);
+	} else if (IS_81xxC_VENDOR_UMC_B_CUT(rtlhal->version)) {
+		rtl_set_rfreg(hw, RF90_PATH_A, 0x0C, MASKDWORD, 0x894AE);
+		rtl_set_rfreg(hw, RF90_PATH_A, 0x0A, MASKDWORD, 0x1AF31);
+		rtl_set_rfreg(hw, RF90_PATH_A, RF_IPA, MASKDWORD, 0x8F425);
+		rtl_set_rfreg(hw, RF90_PATH_A, RF_SYN_G2, MASKDWORD, 0x4F200);
+		rtl_set_rfreg(hw, RF90_PATH_A, RF_RCK1, MASKDWORD, 0x44053);
+		rtl_set_rfreg(hw, RF90_PATH_A, RF_RCK2, MASKDWORD, 0x80201);
+	}
 	rtlphy->rfreg_chnlval[0] = rtl_get_rfreg(hw, (enum radio_path)0,
 						 RF_CHNLBW, RFREG_OFFSET_MASK);
 	rtlphy->rfreg_chnlval[1] = rtl_get_rfreg(hw, (enum radio_path)1,
@@ -945,11 +964,11 @@ int rtl92ce_hw_init(struct ieee80211_hw *hw)
 
 	if (ppsc->rfpwr_state == ERFON) {
 		rtl92c_phy_set_rfpath_switch(hw, 1);
-		if (iqk_initialized) {
+		if (rtlphy->iqk_initialized) {
 			rtl92c_phy_iq_calibrate(hw, true);
 		} else {
 			rtl92c_phy_iq_calibrate(hw, false);
-			iqk_initialized = true;
+			rtlphy->iqk_initialized = true;
 		}
 
 		rtl92c_dm_check_txpower_tracking(hw);
@@ -987,38 +1006,79 @@ static enum version_8192c _rtl92ce_read_chip_version(struct ieee80211_hw *hw)
 	struct rtl_phy *rtlphy = &(rtlpriv->phy);
 	enum version_8192c version = VERSION_UNKNOWN;
 	u32 value32;
-	const char *versionid;
 
 	value32 = rtl_read_dword(rtlpriv, REG_SYS_CFG);
 	if (value32 & TRP_VAUX_EN) {
 		version = (value32 & TYPE_ID) ? VERSION_A_CHIP_92C :
 			   VERSION_A_CHIP_88C;
 	} else {
-		version = (value32 & TYPE_ID) ? VERSION_B_CHIP_92C :
-			   VERSION_B_CHIP_88C;
+		version = (enum version_8192c) NORMAL_CHIP;
+		version = (enum version_8192c) (version |
+			  ((value32 & TYPE_ID) ? CHIP_92C_BITMASK : 0));
+		version = (enum version_8192c) (version |
+			  ((value32 & VENDOR_ID) ? CHIP_VENDOR_UMC : 0));
+		if ((!IS_CHIP_VENDOR_UMC(version)) &&
+		    (value32 & CHIP_VER_RTL_MASK)) {
+			version = (enum version_8192c)(version |
+				  ((((value32 & CHIP_VER_RTL_MASK) == BIT(12))
+				  ? CHIP_VENDOR_UMC_B_CUT : CHIP_UNKNOW) |
+				  CHIP_VENDOR_UMC));
+		}
+		if (IS_92C_SERIAL(version)) {
+			value32 = rtl_read_dword(rtlpriv, REG_HPON_FSM);
+			version = (enum version_8192c)(version |
+				  ((CHIP_BONDING_IDENTIFIER(value32)
+				  == CHIP_BONDING_92C_1T2R) ?
+				  RF_TYPE_1T2R : 0));
+		}
 	}
 
 	switch (version) {
 	case VERSION_B_CHIP_92C:
-		versionid = "B_CHIP_92C";
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 "Chip Version ID: VERSION_B_CHIP_92C.\n");
 		break;
 	case VERSION_B_CHIP_88C:
-		versionid = "B_CHIP_88C";
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 "Chip Version ID: VERSION_B_CHIP_88C.\n");
 		break;
 	case VERSION_A_CHIP_92C:
-		versionid = "A_CHIP_92C";
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 "Chip Version ID: VERSION_A_CHIP_92C.\n");
 		break;
 	case VERSION_A_CHIP_88C:
-		versionid = "A_CHIP_88C";
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 "Chip Version ID: VERSION_A_CHIP_88C.\n");
+		break;
+	case VERSION_NORMAL_UMC_CHIP_92C_1T2R_A_CUT:
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 "Chip Version ID: VERSION_NORMAL_UMC_CHIP_92C_1T2R_A_CUT.\n");
+		break;
+	case VERSION_NORMAL_UMC_CHIP_92C_A_CUT:
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 "Chip Version ID: VERSION_NORMAL_UMC_CHIP_92C_A_CUT.\n");
+		break;
+	case VERSION_NORMAL_UMC_CHIP_88C_A_CUT:
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 "Chip Version ID: VERSION_NORMAL_UMC_CHIP_88C_A_CUT.\n");
+		break;
+	case VERSION_NORMAL_UMC_CHIP_92C_1T2R_B_CUT:
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 "Chip Version ID: VERSION_NORMAL_UMC_CHIP_92C_1T2R_B_CUT.\n");
+		break;
+	case VERSION_NORMAL_UMC_CHIP_92C_B_CUT:
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 "Chip Version ID: VERSION_NORMAL_UMC_CHIP_92C_B_CUT.\n");
+		break;
+	case VERSION_NORMAL_UMC_CHIP_88C_B_CUT:
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 "Chip Version ID: VERSION_NORMAL_UMC_CHIP_88C_B_CUT.\n");
 		break;
 	default:
-		versionid = "Unknown. Bug?";
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+			 "Chip Version ID: Unknown. Bug?\n");
 		break;
 	}
-
-	RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
-		 "Chip Version ID: %s\n", versionid);
-
 	switch (version & 0x3) {
 	case CHIP_88C:
 		rtlphy->rf_type = RF_1T1R;
@@ -1189,6 +1249,7 @@ static void _rtl92ce_poweroff_adapter(struct ieee80211_hw *hw)
 {
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
 	u8 u1b_tmp;
 	u32 u4b_tmp;
 
@@ -1217,7 +1278,8 @@ static void _rtl92ce_poweroff_adapter(struct ieee80211_hw *hw)
 	rtl_write_word(rtlpriv, REG_GPIO_IO_SEL, 0x0790);
 	rtl_write_word(rtlpriv, REG_LEDCFG0, 0x8080);
 	rtl_write_byte(rtlpriv, REG_AFE_PLL_CTRL, 0x80);
-	rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x23);
+	if (!IS_81xxC_VENDOR_UMC_B_CUT(rtlhal->version))
+		rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x23);
 	if (rtlpcipriv->bt_coexist.bt_coexistence) {
 		u4b_tmp = rtl_read_dword(rtlpriv, REG_AFE_XTAL_CTRL);
 		u4b_tmp |= 0x03824800;
@@ -1246,6 +1308,9 @@ void rtl92ce_card_disable(struct ieee80211_hw *hw)
 		rtlpriv->cfg->ops->led_control(hw, LED_CTL_POWER_OFF);
 	RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC);
 	_rtl92ce_poweroff_adapter(hw);
+
+	/* after power off we should do iqk again */
+	rtlpriv->phy.iqk_initialized = false;
 }
 
 void rtl92ce_interrupt_recognized(struct ieee80211_hw *hw,
@@ -1710,6 +1775,8 @@ static void rtl92ce_update_hal_rate_table(struct ieee80211_hw *hw,
 		ratr_value = sta->supp_rates[1] << 4;
 	else
 		ratr_value = sta->supp_rates[0];
+	if (mac->opmode == NL80211_IFTYPE_ADHOC)
+		ratr_value = 0xfff;
 	ratr_value |= (sta->ht_cap.mcs.rx_mask[1] << 20 |
 			sta->ht_cap.mcs.rx_mask[0] << 12);
 	switch (wirelessmode) {
@@ -1814,6 +1881,8 @@ static void rtl92ce_update_hal_rate_mask(struct ieee80211_hw *hw,
 		ratr_bitmap = sta->supp_rates[1] << 4;
 	else
 		ratr_bitmap = sta->supp_rates[0];
+	if (mac->opmode == NL80211_IFTYPE_ADHOC)
+		ratr_bitmap = 0xfff;
 	ratr_bitmap |= (sta->ht_cap.mcs.rx_mask[1] << 20 |
 			sta->ht_cap.mcs.rx_mask[0] << 12);
 	switch (wirelessmode) {
@@ -1904,6 +1973,8 @@ static void rtl92ce_update_hal_rate_mask(struct ieee80211_hw *hw,
 			ratr_bitmap &= 0x0f0ff0ff;
 		break;
 	}
+	sta_entry->ratr_index = ratr_index;
+
 	RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG,
 		 "ratr_bitmap :%x\n", ratr_bitmap);
 	*(u32 *)&rate_mask = (ratr_bitmap & 0x0fffffff) |
@@ -1915,9 +1986,6 @@ static void rtl92ce_update_hal_rate_mask(struct ieee80211_hw *hw,
 		 rate_mask[0], rate_mask[1], rate_mask[2], rate_mask[3],
 		 rate_mask[4]);
 	rtl92c_fill_h2c_cmd(hw, H2C_RA_MASK, 5, rate_mask);
-
-	if (macid != 0)
-		sta_entry->ratr_index = ratr_index;
 }
 
 void rtl92ce_update_hal_rate_tbl(struct ieee80211_hw *hw,
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/reg.h b/drivers/net/wireless/rtlwifi/rtl8192ce/reg.h
index e4d738f..bd4aef7 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/reg.h
+++ b/drivers/net/wireless/rtlwifi/rtl8192ce/reg.h
@@ -544,6 +544,7 @@
 #define	IMR_WLANOFF				BIT(0)
 
 #define EFUSE_REAL_CONTENT_LEN			512
+#define EFUSE_OOB_PROTECT_BYTES			15
 
 #define	EEPROM_DEFAULT_TSSI			0x0
 #define EEPROM_DEFAULT_TXPOWERDIFF		0x0
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c b/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c
index 60451ee..8f853f0 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c
@@ -278,6 +278,7 @@ static struct rtl_hal_cfg rtl92ce_hal_cfg = {
 	.maps[EFUSE_HWSET_MAX_SIZE] = HWSET_MAX_SIZE,
 	.maps[EFUSE_MAX_SECTION_MAP] = EFUSE_MAX_SECTION,
 	.maps[EFUSE_REAL_CONTENT_SIZE] = EFUSE_REAL_CONTENT_LEN,
+	.maps[EFUSE_OOB_PROTECT_BYTES_LEN] = EFUSE_OOB_PROTECT_BYTES,
 
 	.maps[RWCAM] = REG_CAMCMD,
 	.maps[WCAMI] = REG_CAMWRITE,
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c b/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c
index 5216664..64cde4a 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c
@@ -42,7 +42,7 @@ static u8 _rtl92ce_map_hwqueue_to_fwqueue(struct sk_buff *skb, u8 hw_queue)
 
 	if (unlikely(ieee80211_is_beacon(fc)))
 		return QSLT_BEACON;
-	if (ieee80211_is_mgmt(fc))
+	if (ieee80211_is_mgmt(fc) || ieee80211_is_ctl(fc))
 		return QSLT_MGNT;
 
 	return skb->priority;
@@ -127,13 +127,14 @@ static void _rtl92ce_query_rxphystatus(struct ieee80211_hw *hw,
 {
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	struct phy_sts_cck_8192s_t *cck_buf;
+	struct rtl_ps_ctl *ppsc = rtl_psc(rtlpriv);
 	s8 rx_pwr_all = 0, rx_pwr[4];
 	u8 evm, pwdb_all, rf_rx_num = 0;
 	u8 i, max_spatial_stream;
 	u32 rssi, total_rssi = 0;
-	bool in_powersavemode = false;
 	bool is_cck_rate;
 
+	/* Save data for next packet processing */
 	is_cck_rate = RX_HAL_IS_CCK_RATE(pdesc);
 	pstats->packet_matchbssid = packet_match_bssid;
 	pstats->packet_toself = packet_toself;
@@ -145,9 +146,14 @@ static void _rtl92ce_query_rxphystatus(struct ieee80211_hw *hw,
 
 	if (is_cck_rate) {
 		u8 report, cck_highpwr;
+
+		/* CCK info is not the same as OFDM */
 		cck_buf = (struct phy_sts_cck_8192s_t *)p_drvinfo;
 
-		if (!in_powersavemode)
+		/* (1)Hardware does not provide RSSI for CCK */
+		/* (2)PWDB, Average PWDB cacluated by
+		 * hardware (for rate adaptive) */
+		if (ppsc->rfpwr_state == ERFON)
 			cck_highpwr = (u8) rtl_get_bbreg(hw,
 						 RFPGA0_XA_HSSIPARAMETER2,
 						 BIT(9));
@@ -193,9 +199,26 @@ static void _rtl92ce_query_rxphystatus(struct ieee80211_hw *hw,
 		}
 
 		pwdb_all = _rtl92c_query_rxpwrpercentage(rx_pwr_all);
+		/* CCK gain is smaller than OFDM/MCS gain,
+		 * so we add gain diff by experiences,
+		 * the val is 6 */
+		pwdb_all += 6;
+		if (pwdb_all > 100)
+			pwdb_all = 100;
+		/* modify the offset to make the same
+		 * gain index with OFDM. */
+		if (pwdb_all > 34 && pwdb_all <= 42)
+			pwdb_all -= 2;
+		else if (pwdb_all > 26 && pwdb_all <= 34)
+			pwdb_all -= 6;
+		else if (pwdb_all > 14 && pwdb_all <= 26)
+			pwdb_all -= 8;
+		else if (pwdb_all > 4 && pwdb_all <= 14)
+			pwdb_all -= 4;
 		pstats->rx_pwdb_all = pwdb_all;
 		pstats->recvsignalpower = rx_pwr_all;
 
+		/* (3) Get Signal Quality (EVM) */
 		if (packet_match_bssid) {
 			u8 sq;
 			if (pstats->rx_pwdb_all > 40)
@@ -217,27 +240,39 @@ static void _rtl92ce_query_rxphystatus(struct ieee80211_hw *hw,
 	} else {
 		rtlpriv->dm.rfpath_rxenable[0] =
 		    rtlpriv->dm.rfpath_rxenable[1] = true;
+
+		/* (1)Get RSSI for HT rate */
 		for (i = RF90_PATH_A; i < RF90_PATH_MAX; i++) {
+
+			/* we will judge RF RX path now. */
 			if (rtlpriv->dm.rfpath_rxenable[i])
 				rf_rx_num++;
 
 			rx_pwr[i] =
 			    ((p_drvinfo->gain_trsw[i] & 0x3f) * 2) - 110;
+
+			/* Translate DBM to percentage. */
 			rssi = _rtl92c_query_rxpwrpercentage(rx_pwr[i]);
 			total_rssi += rssi;
+
+			/* Get Rx snr value in DB */
 			rtlpriv->stats.rx_snr_db[i] =
 			    (long)(p_drvinfo->rxsnr[i] / 2);
 
+			/* Record Signal Strength for next packet */
 			if (packet_match_bssid)
 				pstats->rx_mimo_signalstrength[i] = (u8) rssi;
 		}
 
+		/* (2)PWDB, Average PWDB cacluated by
+		 * hardware (for rate adaptive) */
 		rx_pwr_all = ((p_drvinfo->pwdb_all >> 1) & 0x7f) - 110;
 		pwdb_all = _rtl92c_query_rxpwrpercentage(rx_pwr_all);
 		pstats->rx_pwdb_all = pwdb_all;
 		pstats->rxpower = rx_pwr_all;
 		pstats->recvsignalpower = rx_pwr_all;
 
+		/* (3)EVM of HT rate */
 		if (pdesc->rxht && pdesc->rxmcs >= DESC92_RATEMCS8 &&
 		    pdesc->rxmcs <= DESC92_RATEMCS15)
 			max_spatial_stream = 2;
@@ -248,6 +283,8 @@ static void _rtl92ce_query_rxphystatus(struct ieee80211_hw *hw,
 			evm = _rtl92c_evm_db_to_percentage(p_drvinfo->rxevm[i]);
 
 			if (packet_match_bssid) {
+				/* Fill value in RFD, Get the first
+				 * spatial stream only */
 				if (i == 0)
 					pstats->signalquality =
 					    (u8) (evm & 0xff);
@@ -257,6 +294,8 @@ static void _rtl92ce_query_rxphystatus(struct ieee80211_hw *hw,
 		}
 	}
 
+	/* UI BSS List signal strength(in percentage),
+	 * make it good looking, from 0~100. */
 	if (is_cck_rate)
 		pstats->signalstrength =
 		    (u8) (_rtl92ce_signal_scale_mapping(hw, pwdb_all));
@@ -534,6 +573,7 @@ bool rtl92ce_rx_query_desc(struct ieee80211_hw *hw,
 {
 	struct rx_fwinfo_92c *p_drvinfo;
 	struct rx_desc_92c *pdesc = (struct rx_desc_92c *)p_desc;
+	struct ieee80211_hdr *hdr;
 
 	u32 phystatus = GET_RX_DESC_PHYST(pdesc);
 	stats->length = (u16) GET_RX_DESC_PKT_LEN(pdesc);
@@ -558,7 +598,10 @@ bool rtl92ce_rx_query_desc(struct ieee80211_hw *hw,
 	if (GET_RX_DESC_CRC32(pdesc))
 		rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
 
-	if (!GET_RX_DESC_SWDEC(pdesc))
+	hdr = (struct ieee80211_hdr *)(skb->data + stats->rx_drvinfo_size
+			+ stats->rx_bufshift);
+
+	if (stats->crc)
 		rx_status->flag |= RX_FLAG_DECRYPTED;
 
 	if (GET_RX_DESC_BW(pdesc))
@@ -569,9 +612,24 @@ bool rtl92ce_rx_query_desc(struct ieee80211_hw *hw,
 
 	rx_status->flag |= RX_FLAG_MACTIME_MPDU;
 
-	if (stats->decrypted)
-		rx_status->flag |= RX_FLAG_DECRYPTED;
+	/* hw will set status->decrypted true, if it finds the
+	 * frame is open data frame or mgmt frame.
+	 * Thus hw will not decrypt robust managment frame
+	 * for IEEE80211w but still set status->decrypted
+	 * true, so here we should set it back to undecrypted
+	 * for IEEE80211w frame, and mac80211 sw will help
+	 * to decrypt it */
+	if (stats->decrypted) {
+		if ((ieee80211_is_robust_mgmt_frame(hdr)) &&
+		    (ieee80211_has_protected(hdr->frame_control)))
+			rx_status->flag &= ~RX_FLAG_DECRYPTED;
+		else
+			rx_status->flag |= RX_FLAG_DECRYPTED;
+	}
 
+	/* rate_idx: index of data rate into band's
+	 * supported rates or MCS index if HT rates
+	 * are in use (RX_FLAG_HT)*/
 	rx_status->rate_idx = rtlwifi_rate_mapping(hw,
 				(bool)GET_RX_DESC_RXHT(pdesc),
 				(u8)GET_RX_DESC_RXMCS(pdesc),
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 6/6] rtlwifi: rtl8192se: Update driver for changes in 12/30/2011 vendor version
  2012-08-21 15:00 [PATCH 0/6] Updates to rtlwifi family to match latest vendor version Larry Finger
                   ` (4 preceding siblings ...)
  2012-08-21 15:00 ` [PATCH 5/6] rtlwifi: rtl8192ce: Update " Larry Finger
@ 2012-08-21 15:00 ` Larry Finger
  5 siblings, 0 replies; 10+ messages in thread
From: Larry Finger @ 2012-08-21 15:00 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, Li Chaoming, Larry Finger

From: Li Chaoming <chaoming_li@realsil.com.cn>

Yhis patch implements the changes found in the vendor driver with version
rtl_92ce_92se_92de_linux_mac80211_0005.1230.2011. The reasons for these
changes are not specified in Realtek's code.

Signed-off-by: Li Chaoming <chaoming_li@realsil.com.cn>
Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net>
---
 drivers/net/wireless/rtlwifi/rtl8192se/dm.c  |   91 ++++---
 drivers/net/wireless/rtlwifi/rtl8192se/fw.c  |    1 -
 drivers/net/wireless/rtlwifi/rtl8192se/hw.c  |   25 +-
 drivers/net/wireless/rtlwifi/rtl8192se/phy.c |  353 ++++++++++++++------------
 drivers/net/wireless/rtlwifi/rtl8192se/trx.c |   11 +-
 5 files changed, 267 insertions(+), 214 deletions(-)

diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/dm.c b/drivers/net/wireless/rtlwifi/rtl8192se/dm.c
index 465f581..e1079eb 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/dm.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192se/dm.c
@@ -175,7 +175,20 @@ static void _rtl92s_dm_txpowertracking_callback_thermalmeter(
 
 	if (thermalvalue) {
 		rtlpriv->dm.thermalvalue = thermalvalue;
-		rtl92s_phy_set_fw_cmd(hw, FW_CMD_TXPWR_TRACK_THERMAL);
+
+		if (hal_get_firmwareversion(rtlpriv) >= 0x35) {
+			rtl92s_phy_set_fw_cmd(hw, FW_CMD_TXPWR_TRACK_THERMAL);
+		} else {
+			u32 fw_cmd = (FW_TXPWR_TRACK_THERMAL |
+				(rtlpriv->efuse.thermalmeter[0] << 8) |
+				(thermalvalue << 16));
+
+			RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
+				 "Write to FW Thermal Val = 0x%x\n", fw_cmd);
+
+			rtl_write_dword(rtlpriv, WFM5, fw_cmd);
+			rtl92s_phy_chk_fwcmd_iodone(hw);
+		}
 	}
 
 	rtlpriv->dm.txpowercount = 0;
@@ -217,11 +230,11 @@ static void _rtl92s_dm_refresh_rateadaptive_mask(struct ieee80211_hw *hw)
 	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
 	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
 	struct rate_adaptive *ra = &(rtlpriv->ra);
-
+	struct ieee80211_sta *sta = NULL;
+	u8 rssi_level;
 	u32 low_rssi_thresh = 0;
 	u32 middle_rssi_thresh = 0;
 	u32 high_rssi_thresh = 0;
-	struct ieee80211_sta *sta = NULL;
 
 	if (is_hal_stop(rtlhal))
 		return;
@@ -229,16 +242,14 @@ static void _rtl92s_dm_refresh_rateadaptive_mask(struct ieee80211_hw *hw)
 	if (!rtlpriv->dm.useramask)
 		return;
 
-	if (!rtlpriv->dm.inform_fw_driverctrldm) {
+	if (hal_get_firmwareversion(rtlpriv) >= 61 &&
+		!rtlpriv->dm.inform_fw_driverctrldm) {
 		rtl92s_phy_set_fw_cmd(hw, FW_CMD_CTRL_DM_BY_DRIVER);
 		rtlpriv->dm.inform_fw_driverctrldm = true;
 	}
 
-	rcu_read_lock();
-	if (mac->opmode == NL80211_IFTYPE_STATION)
-		sta = get_sta(hw, mac->vif, mac->bssid);
 	if ((mac->link_state == MAC80211_LINKED) &&
-	    (mac->opmode == NL80211_IFTYPE_STATION)) {
+		(mac->opmode == NL80211_IFTYPE_STATION)) {
 		switch (ra->pre_ratr_state) {
 		case DM_RATR_STA_HIGH:
 			high_rssi_thresh = 40;
@@ -270,29 +281,36 @@ static void _rtl92s_dm_refresh_rateadaptive_mask(struct ieee80211_hw *hw)
 		if (rtlpriv->dm.undecorated_smoothed_pwdb >
 		    (long)high_rssi_thresh) {
 			ra->ratr_state = DM_RATR_STA_HIGH;
+			rssi_level = 1;
 		} else if (rtlpriv->dm.undecorated_smoothed_pwdb >
-			   (long)middle_rssi_thresh) {
+			(long)middle_rssi_thresh) {
 			ra->ratr_state = DM_RATR_STA_LOW;
+			rssi_level = 3;
 		} else if (rtlpriv->dm.undecorated_smoothed_pwdb >
-			   (long)low_rssi_thresh) {
+			(long)low_rssi_thresh) {
 			ra->ratr_state = DM_RATR_STA_LOW;
+			rssi_level = 5;
 		} else {
 			ra->ratr_state = DM_RATR_STA_ULTRALOW;
+			rssi_level = 6;
 		}
 
 		if (ra->pre_ratr_state != ra->ratr_state) {
 			RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD,
 				 "RSSI = %ld RSSI_LEVEL = %d PreState = %d, CurState = %d\n",
 				 rtlpriv->dm.undecorated_smoothed_pwdb,
-				 ra->ratr_state,
-				 ra->pre_ratr_state, ra->ratr_state);
+				 ra->ratr_state, ra->pre_ratr_state,
+				 ra->ratr_state);
 
+			rcu_read_lock();
+			sta = rtl_find_sta(hw, mac->bssid);
 			rtlpriv->cfg->ops->update_rate_tbl(hw, sta,
 							   ra->ratr_state);
+			rcu_read_unlock();
+
 			ra->pre_ratr_state = ra->ratr_state;
 		}
 	}
-	rcu_read_unlock();
 }
 
 static void _rtl92s_dm_switch_baseband_mrc(struct ieee80211_hw *hw)
@@ -417,28 +435,6 @@ static void _rtl92s_dm_false_alarm_counter_statistics(struct ieee80211_hw *hw)
 		falsealm_cnt->cnt_cck_fail;
 }
 
-static void rtl92s_backoff_enable_flag(struct ieee80211_hw *hw)
-{
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	struct dig_t *digtable = &rtlpriv->dm_digtable;
-	struct false_alarm_statistics *falsealm_cnt = &(rtlpriv->falsealm_cnt);
-
-	if (falsealm_cnt->cnt_all > digtable->fa_highthresh) {
-		if ((digtable->backoff_val - 6) <
-			digtable->backoffval_range_min)
-			digtable->backoff_val = digtable->backoffval_range_min;
-		else
-			digtable->backoff_val -= 6;
-	} else if (falsealm_cnt->cnt_all < digtable->fa_lowthresh) {
-		if ((digtable->backoff_val + 6) >
-			digtable->backoffval_range_max)
-			digtable->backoff_val =
-				 digtable->backoffval_range_max;
-		else
-			digtable->backoff_val += 6;
-	}
-}
-
 static void _rtl92s_dm_initial_gain_sta_beforeconnect(struct ieee80211_hw *hw)
 {
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
@@ -453,13 +449,30 @@ static void _rtl92s_dm_initial_gain_sta_beforeconnect(struct ieee80211_hw *hw)
 			if (rtlpriv->psc.rfpwr_state != ERFON)
 				return;
 
-			if (digtable->backoff_enable_flag)
-				rtl92s_backoff_enable_flag(hw);
-			else
+			if (digtable->backoff_enable_flag) {
+				if (falsealm_cnt->cnt_all >
+				    digtable->fa_highthresh) {
+					if ((digtable->backoff_val - 6) <
+					    digtable->backoffval_range_min)
+						digtable->backoff_val =
+						 digtable->backoffval_range_min;
+					else
+						digtable->backoff_val -= 6;
+				} else if (falsealm_cnt->cnt_all <
+					   digtable->fa_lowthresh) {
+					if ((digtable->backoff_val + 6) >
+					    digtable->backoffval_range_max)
+						digtable->backoff_val =
+						 digtable->backoffval_range_max;
+					else
+						digtable->backoff_val += 6;
+				}
+			} else {
 				digtable->backoff_val = DM_DIG_BACKOFF;
+			}
 
 			if ((digtable->rssi_val + 10 - digtable->backoff_val) >
-				digtable->rx_gain_range_max)
+			    digtable->rx_gain_range_max)
 				digtable->cur_igvalue =
 						digtable->rx_gain_range_max;
 			else if ((digtable->rssi_val + 10 - digtable->backoff_val)
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/fw.c b/drivers/net/wireless/rtlwifi/rtl8192se/fw.c
index 380e7d4..d52fb37 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/fw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192se/fw.c
@@ -485,7 +485,6 @@ static u32 _rtl92s_fill_h2c_cmd(struct sk_buff *skb, u32 h2cbufferlen,
 		/* Clear content */
 		ph2c_buffer = (u8 *)skb_put(skb, (u32)len);
 		memset((ph2c_buffer + totallen + tx_desclen), 0, len);
-
 		/* CMD len */
 		SET_BITS_TO_LE_4BYTE((ph2c_buffer + totallen + tx_desclen),
 				      0, 16, pcmd_len[i]);
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/hw.c b/drivers/net/wireless/rtlwifi/rtl8192se/hw.c
index 4542e69..d2b02bd 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/hw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192se/hw.c
@@ -1058,7 +1058,22 @@ int rtl92se_hw_init(struct ieee80211_hw *hw)
 
 	/* We enable high power and RA related mechanism after NIC
 	 * initialized. */
-	rtl92s_phy_set_fw_cmd(hw, FW_CMD_RA_INIT);
+	if (hal_get_firmwareversion(rtlpriv) >= 0x35) {
+		/* Fw v.53 and later. */
+		rtl92s_phy_set_fw_cmd(hw, FW_CMD_RA_INIT);
+	} else if (hal_get_firmwareversion(rtlpriv) == 0x34) {
+		/* Fw v.52 and later. */
+		rtl_write_dword(rtlpriv, WFM5, FW_RA_INIT);
+		rtl92s_phy_chk_fwcmd_iodone(hw);
+	} else {
+		/* Compatible earlier FW version. */
+		rtl_write_dword(rtlpriv, WFM5, FW_RA_RESET);
+		rtl92s_phy_chk_fwcmd_iodone(hw);
+		rtl_write_dword(rtlpriv, WFM5, FW_RA_ACTIVE);
+		rtl92s_phy_chk_fwcmd_iodone(hw);
+		rtl_write_dword(rtlpriv, WFM5, FW_RA_REFRESH);
+		rtl92s_phy_chk_fwcmd_iodone(hw);
+	}
 
 	/* Add to prevent ASPM bug. */
 	/* Always enable hst and NIC clock request. */
@@ -1998,6 +2013,8 @@ static void rtl92se_update_hal_rate_table(struct ieee80211_hw *hw,
 		ratr_value = sta->supp_rates[1] << 4;
 	else
 		ratr_value = sta->supp_rates[0];
+	if (mac->opmode == NL80211_IFTYPE_ADHOC)
+		ratr_value = 0xfff;
 	ratr_value |= (sta->ht_cap.mcs.rx_mask[1] << 20 |
 			sta->ht_cap.mcs.rx_mask[0] << 12);
 	switch (wirelessmode) {
@@ -2112,6 +2129,8 @@ static void rtl92se_update_hal_rate_mask(struct ieee80211_hw *hw,
 		ratr_bitmap = sta->supp_rates[1] << 4;
 	else
 		ratr_bitmap = sta->supp_rates[0];
+	if (mac->opmode == NL80211_IFTYPE_ADHOC)
+		ratr_bitmap = 0xfff;
 	ratr_bitmap |= (sta->ht_cap.mcs.rx_mask[1] << 20 |
 			sta->ht_cap.mcs.rx_mask[0] << 12);
 	switch (wirelessmode) {
@@ -2200,6 +2219,7 @@ static void rtl92se_update_hal_rate_mask(struct ieee80211_hw *hw,
 			ratr_bitmap &= 0x0f8ff0ff;
 		break;
 	}
+	sta_entry->ratr_index = ratr_index;
 
 	if (rtlpriv->rtlhal.version >= VERSION_8192S_BCUT)
 		ratr_bitmap &= 0x0FFFFFFF;
@@ -2226,9 +2246,6 @@ static void rtl92se_update_hal_rate_mask(struct ieee80211_hw *hw,
 		 mask, ratr_bitmap);
 	rtl_write_dword(rtlpriv, 0x2c4, ratr_bitmap);
 	rtl_write_dword(rtlpriv, WFM5, (FW_RA_UPDATE_MASK | (mask << 8)));
-
-	if (macid != 0)
-		sta_entry->ratr_index = ratr_index;
 }
 
 void rtl92se_update_hal_rate_tbl(struct ieee80211_hw *hw,
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/phy.c b/drivers/net/wireless/rtlwifi/rtl8192se/phy.c
index b917a2a..daa81ea 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/phy.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192se/phy.c
@@ -181,19 +181,20 @@ u32 rtl92s_phy_query_rf_reg(struct ieee80211_hw *hw, enum radio_path rfpath,
 {
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	u32 original_value, readback_value, bitshift;
+	unsigned long flags;
 
 	RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE,
 		 "regaddr(%#x), rfpath(%#x), bitmask(%#x)\n",
 		 regaddr, rfpath, bitmask);
 
-	spin_lock(&rtlpriv->locks.rf_lock);
+	spin_lock_irqsave(&rtlpriv->locks.rf_lock, flags);
 
 	original_value = _rtl92s_phy_rf_serial_read(hw, rfpath, regaddr);
 
 	bitshift = _rtl92s_phy_calculate_bit_shift(bitmask);
 	readback_value = (original_value & bitmask) >> bitshift;
 
-	spin_unlock(&rtlpriv->locks.rf_lock);
+	spin_unlock_irqrestore(&rtlpriv->locks.rf_lock, flags);
 
 	RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE,
 		 "regaddr(%#x), rfpath(%#x), bitmask(%#x), original_value(%#x)\n",
@@ -208,6 +209,7 @@ void rtl92s_phy_set_rf_reg(struct ieee80211_hw *hw, enum radio_path rfpath,
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	struct rtl_phy *rtlphy = &(rtlpriv->phy);
 	u32 original_value, bitshift;
+	unsigned long flags;
 
 	if (!((rtlphy->rf_pathmap >> rfpath) & 0x1))
 		return;
@@ -216,7 +218,7 @@ void rtl92s_phy_set_rf_reg(struct ieee80211_hw *hw, enum radio_path rfpath,
 		 "regaddr(%#x), bitmask(%#x), data(%#x), rfpath(%#x)\n",
 		 regaddr, bitmask, data, rfpath);
 
-	spin_lock(&rtlpriv->locks.rf_lock);
+	spin_lock_irqsave(&rtlpriv->locks.rf_lock, flags);
 
 	if (bitmask != RFREG_OFFSET_MASK) {
 		original_value = _rtl92s_phy_rf_serial_read(hw, rfpath,
@@ -227,7 +229,7 @@ void rtl92s_phy_set_rf_reg(struct ieee80211_hw *hw, enum radio_path rfpath,
 
 	_rtl92s_phy_rf_serial_write(hw, rfpath, regaddr, data);
 
-	spin_unlock(&rtlpriv->locks.rf_lock);
+	spin_unlock_irqrestore(&rtlpriv->locks.rf_lock, flags);
 
 	RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE,
 		 "regaddr(%#x), bitmask(%#x), data(%#x), rfpath(%#x)\n",
@@ -1327,15 +1329,17 @@ static void _rtl92s_phy_set_fwcmd_io(struct ieee80211_hw *hw)
 
 	/* We re-map RA related CMD IO to combinational ones */
 	/* if FW version is v.52 or later. */
-	switch (rtlhal->current_fwcmd_io) {
-	case FW_CMD_RA_REFRESH_N:
-		rtlhal->current_fwcmd_io = FW_CMD_RA_REFRESH_N_COMB;
-		break;
-	case FW_CMD_RA_REFRESH_BG:
-		rtlhal->current_fwcmd_io = FW_CMD_RA_REFRESH_BG_COMB;
-		break;
-	default:
-		break;
+	if (hal_get_firmwareversion(rtlpriv) >= 0x34) {
+		switch (rtlhal->current_fwcmd_io) {
+		case FW_CMD_RA_REFRESH_N:
+			rtlhal->current_fwcmd_io = FW_CMD_RA_REFRESH_N_COMB;
+			break;
+		case FW_CMD_RA_REFRESH_BG:
+			rtlhal->current_fwcmd_io = FW_CMD_RA_REFRESH_BG_COMB;
+			break;
+		default:
+			break;
+		}
 	}
 
 	switch (rtlhal->current_fwcmd_io) {
@@ -1464,9 +1468,9 @@ bool rtl92s_phy_set_fw_cmd(struct ieee80211_hw *hw, enum fwcmd_iotype fw_cmdio)
 		 "Set FW Cmd(%#x), set_fwcmd_inprogress(%d)\n",
 		 fw_cmdio, rtlhal->set_fwcmd_inprogress);
 
-	do {
-		/* We re-map to combined FW CMD ones if firmware version */
-		/* is v.53 or later. */
+	/* We re-map to combined FW CMD ones if firmware version */
+	/* is v.53 or later. */
+	if (hal_get_firmwareversion(rtlpriv) >= 0x35) {
 		switch (fw_cmdio) {
 		case FW_CMD_RA_REFRESH_N:
 			fw_cmdio = FW_CMD_RA_REFRESH_N_COMB;
@@ -1478,180 +1482,186 @@ bool rtl92s_phy_set_fw_cmd(struct ieee80211_hw *hw, enum fwcmd_iotype fw_cmdio)
 			break;
 		}
 
-		/* If firmware version is v.62 or later,
-		 * use FW_CMD_IO_SET for FW_CMD_CTRL_DM_BY_DRIVER */
-		if (hal_get_firmwareversion(rtlpriv) >= 0x3E) {
-			if (fw_cmdio == FW_CMD_CTRL_DM_BY_DRIVER)
-				fw_cmdio = FW_CMD_CTRL_DM_BY_DRIVER_NEW;
+	} else {
+		if ((fw_cmdio == FW_CMD_IQK_ENABLE) ||
+		    (fw_cmdio == FW_CMD_RA_REFRESH_N) ||
+		    (fw_cmdio == FW_CMD_RA_REFRESH_BG)) {
+			bPostProcessing = true;
+			goto post_proc;
 		}
+	}
+	/* If firmware version is v.62 or later,
+	 * use FW_CMD_IO_SET for FW_CMD_CTRL_DM_BY_DRIVER */
+	if (hal_get_firmwareversion(rtlpriv) >= 0x3E) {
+		if (fw_cmdio == FW_CMD_CTRL_DM_BY_DRIVER)
+			fw_cmdio = FW_CMD_CTRL_DM_BY_DRIVER_NEW;
+	}
 
-
-		/* We shall revise all FW Cmd IO into Reg0x364
-		 * DM map table in the future. */
-		switch (fw_cmdio) {
-		case FW_CMD_RA_INIT:
-			RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "RA init!!\n");
-			fw_cmdmap |= FW_RA_INIT_CTL;
-			FW_CMD_IO_SET(rtlpriv, fw_cmdmap);
-			/* Clear control flag to sync with FW. */
-			FW_CMD_IO_CLR(rtlpriv, FW_RA_INIT_CTL);
-			break;
-		case FW_CMD_DIG_DISABLE:
-			RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
-				 "Set DIG disable!!\n");
-			fw_cmdmap &= ~FW_DIG_ENABLE_CTL;
-			FW_CMD_IO_SET(rtlpriv, fw_cmdmap);
-			break;
-		case FW_CMD_DIG_ENABLE:
-		case FW_CMD_DIG_RESUME:
-			if (!(rtlpriv->dm.dm_flag & HAL_DM_DIG_DISABLE)) {
-				RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
-					 "Set DIG enable or resume!!\n");
-				fw_cmdmap |= (FW_DIG_ENABLE_CTL | FW_SS_CTL);
-				FW_CMD_IO_SET(rtlpriv, fw_cmdmap);
-			}
-			break;
-		case FW_CMD_DIG_HALT:
+	/* We shall revise all FW Cmd IO into Reg0x364
+	 * DM map table in the future. */
+	switch (fw_cmdio) {
+	case FW_CMD_RA_INIT:
+		RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "RA init!!\n");
+		fw_cmdmap |= FW_RA_INIT_CTL;
+		FW_CMD_IO_SET(rtlpriv, fw_cmdmap);
+		/* Clear control flag to sync with FW. */
+		FW_CMD_IO_CLR(rtlpriv, FW_RA_INIT_CTL);
+		break;
+	case FW_CMD_DIG_DISABLE:
+		RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
+			 "Set DIG disable!!\n");
+		fw_cmdmap &= ~FW_DIG_ENABLE_CTL;
+		FW_CMD_IO_SET(rtlpriv, fw_cmdmap);
+		break;
+	case FW_CMD_DIG_ENABLE:
+	case FW_CMD_DIG_RESUME:
+		if (!(rtlpriv->dm.dm_flag & HAL_DM_DIG_DISABLE)) {
 			RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
-				 "Set DIG halt!!\n");
-			fw_cmdmap &= ~(FW_DIG_ENABLE_CTL | FW_SS_CTL);
+				 "Set DIG enable or resume!!\n");
+			fw_cmdmap |= (FW_DIG_ENABLE_CTL | FW_SS_CTL);
 			FW_CMD_IO_SET(rtlpriv, fw_cmdmap);
-			break;
-		case FW_CMD_TXPWR_TRACK_THERMAL: {
-			u8	thermalval = 0;
-			fw_cmdmap |= FW_PWR_TRK_CTL;
-
-			/* Clear FW parameter in terms of thermal parts. */
-			fw_param &= FW_PWR_TRK_PARAM_CLR;
-
-			thermalval = rtlpriv->dm.thermalvalue;
-			fw_param |= ((thermalval << 24) |
-				     (rtlefuse->thermalmeter[0] << 16));
+		}
+		break;
+	case FW_CMD_DIG_HALT:
+		RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
+			 "Set DIG halt!!\n");
+		fw_cmdmap &= ~(FW_DIG_ENABLE_CTL | FW_SS_CTL);
+		FW_CMD_IO_SET(rtlpriv, fw_cmdmap);
+		break;
+	case FW_CMD_TXPWR_TRACK_THERMAL: {
+		u8	thermalval = 0;
+		fw_cmdmap |= FW_PWR_TRK_CTL;
 
-			RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
-				 "Set TxPwr tracking!! FwCmdMap(%#x), FwParam(%#x)\n",
-				 fw_cmdmap, fw_param);
+		/* Clear FW parameter in terms of thermal parts. */
+		fw_param &= FW_PWR_TRK_PARAM_CLR;
 
-			FW_CMD_PARA_SET(rtlpriv, fw_param);
-			FW_CMD_IO_SET(rtlpriv, fw_cmdmap);
+		thermalval = rtlpriv->dm.thermalvalue;
+		fw_param |= ((thermalval << 24) |
+			     (rtlefuse->thermalmeter[0] << 16));
 
-			/* Clear control flag to sync with FW. */
-			FW_CMD_IO_CLR(rtlpriv, FW_PWR_TRK_CTL);
-			}
-			break;
-		/* The following FW CMDs are only compatible to
-		 * v.53 or later. */
-		case FW_CMD_RA_REFRESH_N_COMB:
-			fw_cmdmap |= FW_RA_N_CTL;
+		RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
+			 "Set TxPwr tracking!! FwCmdMap(%#x), FwParam(%#x)\n",
+			 fw_cmdmap, fw_param);
 
-			/* Clear RA BG mode control. */
-			fw_cmdmap &= ~(FW_RA_BG_CTL | FW_RA_INIT_CTL);
+		FW_CMD_PARA_SET(rtlpriv, fw_param);
+		FW_CMD_IO_SET(rtlpriv, fw_cmdmap);
 
-			/* Clear FW parameter in terms of RA parts. */
-			fw_param &= FW_RA_PARAM_CLR;
+		/* Clear control flag to sync with FW. */
+		FW_CMD_IO_CLR(rtlpriv, FW_PWR_TRK_CTL); }
+		break;
+	/* The following FW CMDs are only compatible to
+	 * v.53 or later. */
+	case FW_CMD_RA_REFRESH_N_COMB:
+		fw_cmdmap |= FW_RA_N_CTL;
 
-			RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
-				 "[FW CMD] [New Version] Set RA/IOT Comb in n mode!! FwCmdMap(%#x), FwParam(%#x)\n",
-				 fw_cmdmap, fw_param);
+		/* Clear RA BG mode control. */
+		fw_cmdmap &= ~(FW_RA_BG_CTL | FW_RA_INIT_CTL);
 
-			FW_CMD_PARA_SET(rtlpriv, fw_param);
-			FW_CMD_IO_SET(rtlpriv, fw_cmdmap);
+		/* Clear FW parameter in terms of RA parts. */
+		fw_param &= FW_RA_PARAM_CLR;
 
-			/* Clear control flag to sync with FW. */
-			FW_CMD_IO_CLR(rtlpriv, FW_RA_N_CTL);
-			break;
-		case FW_CMD_RA_REFRESH_BG_COMB:
-			fw_cmdmap |= FW_RA_BG_CTL;
+		RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
+			 "[FW CMD] [New Version] Set RA/IOT Comb in n mode!! FwCmdMap(%#x), FwParam(%#x)\n",
+			 fw_cmdmap, fw_param);
 
-			/* Clear RA n-mode control. */
-			fw_cmdmap &= ~(FW_RA_N_CTL | FW_RA_INIT_CTL);
-			/* Clear FW parameter in terms of RA parts. */
-			fw_param &= FW_RA_PARAM_CLR;
+		FW_CMD_PARA_SET(rtlpriv, fw_param);
+		FW_CMD_IO_SET(rtlpriv, fw_cmdmap);
 
-			FW_CMD_PARA_SET(rtlpriv, fw_param);
-			FW_CMD_IO_SET(rtlpriv, fw_cmdmap);
+		/* Clear control flag to sync with FW. */
+		FW_CMD_IO_CLR(rtlpriv, FW_RA_N_CTL);
+		break;
+	case FW_CMD_RA_REFRESH_BG_COMB:
+		fw_cmdmap |= FW_RA_BG_CTL;
 
-			/* Clear control flag to sync with FW. */
-			FW_CMD_IO_CLR(rtlpriv, FW_RA_BG_CTL);
-			break;
-		case FW_CMD_IQK_ENABLE:
-			fw_cmdmap |= FW_IQK_CTL;
-			FW_CMD_IO_SET(rtlpriv, fw_cmdmap);
-			/* Clear control flag to sync with FW. */
-			FW_CMD_IO_CLR(rtlpriv, FW_IQK_CTL);
-			break;
-		/* The following FW CMD is compatible to v.62 or later.  */
-		case FW_CMD_CTRL_DM_BY_DRIVER_NEW:
-			fw_cmdmap |= FW_DRIVER_CTRL_DM_CTL;
-			FW_CMD_IO_SET(rtlpriv, fw_cmdmap);
-			break;
-		/*  The followed FW Cmds needs post-processing later. */
-		case FW_CMD_RESUME_DM_BY_SCAN:
-			fw_cmdmap |= (FW_DIG_ENABLE_CTL |
-				      FW_HIGH_PWR_ENABLE_CTL |
-				      FW_SS_CTL);
+		/* Clear RA n-mode control. */
+		fw_cmdmap &= ~(FW_RA_N_CTL | FW_RA_INIT_CTL);
+		/* Clear FW parameter in terms of RA parts. */
+		fw_param &= FW_RA_PARAM_CLR;
 
-			if (rtlpriv->dm.dm_flag & HAL_DM_DIG_DISABLE ||
-				!digtable->dig_enable_flag)
-				fw_cmdmap &= ~FW_DIG_ENABLE_CTL;
+		FW_CMD_PARA_SET(rtlpriv, fw_param);
+		FW_CMD_IO_SET(rtlpriv, fw_cmdmap);
 
-			if ((rtlpriv->dm.dm_flag & HAL_DM_HIPWR_DISABLE) ||
-			    rtlpriv->dm.dynamic_txpower_enable)
-				fw_cmdmap &= ~FW_HIGH_PWR_ENABLE_CTL;
+		/* Clear control flag to sync with FW. */
+		FW_CMD_IO_CLR(rtlpriv, FW_RA_BG_CTL);
+		break;
+	case FW_CMD_IQK_ENABLE:
+		fw_cmdmap |= FW_IQK_CTL;
+		FW_CMD_IO_SET(rtlpriv, fw_cmdmap);
+		/* Clear control flag to sync with FW. */
+		FW_CMD_IO_CLR(rtlpriv, FW_IQK_CTL);
+		break;
+	/* The following FW CMD is compatible to v.62 or later.  */
+	case FW_CMD_CTRL_DM_BY_DRIVER_NEW:
+		fw_cmdmap |= FW_DRIVER_CTRL_DM_CTL;
+		FW_CMD_IO_SET(rtlpriv, fw_cmdmap);
+		break;
+	/*  The followed FW Cmds needs post-processing later. */
+	case FW_CMD_RESUME_DM_BY_SCAN:
+		fw_cmdmap |= (FW_DIG_ENABLE_CTL |
+			      FW_HIGH_PWR_ENABLE_CTL |
+			      FW_SS_CTL);
 
-			if ((digtable->dig_ext_port_stage ==
-			    DIG_EXT_PORT_STAGE_0) ||
-			    (digtable->dig_ext_port_stage ==
-			    DIG_EXT_PORT_STAGE_1))
-				fw_cmdmap &= ~FW_DIG_ENABLE_CTL;
+		if (rtlpriv->dm.dm_flag & HAL_DM_DIG_DISABLE ||
+		    !digtable->dig_enable_flag)
+			fw_cmdmap &= ~FW_DIG_ENABLE_CTL;
 
-			FW_CMD_IO_SET(rtlpriv, fw_cmdmap);
-			bPostProcessing = true;
-			break;
-		case FW_CMD_PAUSE_DM_BY_SCAN:
-			fw_cmdmap &= ~(FW_DIG_ENABLE_CTL |
-				       FW_HIGH_PWR_ENABLE_CTL |
-				       FW_SS_CTL);
-			FW_CMD_IO_SET(rtlpriv, fw_cmdmap);
-			bPostProcessing = true;
-			break;
-		case FW_CMD_HIGH_PWR_DISABLE:
+		if ((rtlpriv->dm.dm_flag & HAL_DM_HIPWR_DISABLE) ||
+		    rtlpriv->dm.dynamic_txpower_enable)
 			fw_cmdmap &= ~FW_HIGH_PWR_ENABLE_CTL;
-			FW_CMD_IO_SET(rtlpriv, fw_cmdmap);
-			bPostProcessing = true;
-			break;
-		case FW_CMD_HIGH_PWR_ENABLE:
-			if (!(rtlpriv->dm.dm_flag & HAL_DM_HIPWR_DISABLE) &&
-			    !rtlpriv->dm.dynamic_txpower_enable) {
-				fw_cmdmap |= (FW_HIGH_PWR_ENABLE_CTL |
-					      FW_SS_CTL);
-				FW_CMD_IO_SET(rtlpriv, fw_cmdmap);
-				bPostProcessing = true;
-			}
-			break;
-		case FW_CMD_DIG_MODE_FA:
-			fw_cmdmap |= FW_FA_CTL;
-			FW_CMD_IO_SET(rtlpriv, fw_cmdmap);
-			break;
-		case FW_CMD_DIG_MODE_SS:
-			fw_cmdmap &= ~FW_FA_CTL;
-			FW_CMD_IO_SET(rtlpriv, fw_cmdmap);
-			break;
-		case FW_CMD_PAPE_CONTROL:
-			RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
-				 "[FW CMD] Set PAPE Control\n");
-			fw_cmdmap &= ~FW_PAPE_CTL_BY_SW_HW;
 
+		if ((digtable->dig_ext_port_stage ==
+		    DIG_EXT_PORT_STAGE_0) ||
+		    (digtable->dig_ext_port_stage ==
+		    DIG_EXT_PORT_STAGE_1))
+			fw_cmdmap &= ~FW_DIG_ENABLE_CTL;
+
+		FW_CMD_IO_SET(rtlpriv, fw_cmdmap);
+		bPostProcessing = true;
+		break;
+	case FW_CMD_PAUSE_DM_BY_SCAN:
+		fw_cmdmap &= ~(FW_DIG_ENABLE_CTL |
+			       FW_HIGH_PWR_ENABLE_CTL |
+			       FW_SS_CTL);
+		FW_CMD_IO_SET(rtlpriv, fw_cmdmap);
+		bPostProcessing = true;
+		break;
+	case FW_CMD_HIGH_PWR_DISABLE:
+		fw_cmdmap &= ~FW_HIGH_PWR_ENABLE_CTL;
+		FW_CMD_IO_SET(rtlpriv, fw_cmdmap);
+		bPostProcessing = true;
+		break;
+	case FW_CMD_HIGH_PWR_ENABLE:
+		if (!(rtlpriv->dm.dm_flag & HAL_DM_HIPWR_DISABLE) &&
+		    !rtlpriv->dm.dynamic_txpower_enable) {
+			fw_cmdmap |= (FW_HIGH_PWR_ENABLE_CTL |
+				      FW_SS_CTL);
 			FW_CMD_IO_SET(rtlpriv, fw_cmdmap);
-			break;
-		default:
-			/* Pass to original FW CMD processing callback
-			 * routine. */
 			bPostProcessing = true;
-			break;
 		}
-	} while (false);
+		break;
+	case FW_CMD_DIG_MODE_FA:
+		fw_cmdmap |= FW_FA_CTL;
+		FW_CMD_IO_SET(rtlpriv, fw_cmdmap);
+		break;
+	case FW_CMD_DIG_MODE_SS:
+		fw_cmdmap &= ~FW_FA_CTL;
+		FW_CMD_IO_SET(rtlpriv, fw_cmdmap);
+		break;
+	case FW_CMD_PAPE_CONTROL:
+		RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
+			 "[FW CMD] Set PAPE Control\n");
+		fw_cmdmap &= ~FW_PAPE_CTL_BY_SW_HW;
 
+		FW_CMD_IO_SET(rtlpriv, fw_cmdmap);
+		break;
+	default:
+		/* Pass to original FW CMD processing callback
+		 * routine. */
+		bPostProcessing = true;
+		break;
+	}
+
+post_proc:
 	/* We shall post processing these FW CMD if
 	 * variable bPostProcessing is set. */
 	if (bPostProcessing && !rtlhal->set_fwcmd_inprogress) {
@@ -1715,8 +1725,17 @@ void rtl92s_phy_switch_ephy_parameter(struct ieee80211_hw *hw)
 
 }
 
-void rtl92s_phy_set_beacon_hwreg(struct ieee80211_hw *hw, u16 BeaconInterval)
+void rtl92s_phy_set_beacon_hwreg(struct ieee80211_hw *hw, u16 BeaconInt)
 {
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	rtl_write_dword(rtlpriv, WFM5, 0xF1000000 | (BeaconInterval << 8));
+	u32 new_bcn_num = 0;
+
+	if (hal_get_firmwareversion(rtlpriv) >= 0x33) {
+		/* Fw v.51 and later. */
+		rtl_write_dword(rtlpriv, WFM5, 0xF1000000 | (BeaconInt << 8));
+	} else {
+		new_bcn_num = BeaconInt * 32 - 64;
+		rtl_write_dword(rtlpriv, WFM3 + 4, new_bcn_num);
+		rtl_write_dword(rtlpriv, WFM3, 0xB026007C);
+	}
 }
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/trx.c b/drivers/net/wireless/rtlwifi/rtl8192se/trx.c
index e67b338..20081b9 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/trx.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192se/trx.c
@@ -43,7 +43,7 @@ static u8 _rtl92se_map_hwqueue_to_fwqueue(struct sk_buff *skb,	u8 skb_queue)
 
 	if (unlikely(ieee80211_is_beacon(fc)))
 		return QSLT_BEACON;
-	if (ieee80211_is_mgmt(fc))
+	if (ieee80211_is_mgmt(fc) || ieee80211_is_ctl(fc))
 		return QSLT_MGNT;
 	if (ieee80211_is_nullfunc(fc))
 		return QSLT_HIGH;
@@ -118,12 +118,12 @@ static void _rtl92se_query_rxphystatus(struct ieee80211_hw *hw,
 				       bool packet_beacon)
 {
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_ps_ctl *ppsc = rtl_psc(rtlpriv);
 	struct phy_sts_cck_8192s_t *cck_buf;
 	s8 rx_pwr_all = 0, rx_pwr[4];
 	u8 rf_rx_num = 0, evm, pwdb_all;
 	u8 i, max_spatial_stream;
 	u32 rssi, total_rssi = 0;
-	bool in_powersavemode = false;
 	bool is_cck = pstats->is_cck;
 
 	pstats->packet_matchbssid = packet_match_bssid;
@@ -136,7 +136,7 @@ static void _rtl92se_query_rxphystatus(struct ieee80211_hw *hw,
 		u8 report, cck_highpwr;
 		cck_buf = (struct phy_sts_cck_8192s_t *)p_drvinfo;
 
-		if (!in_powersavemode)
+		if (ppsc->rfpwr_state == ERFON)
 			cck_highpwr = (u8) rtl_get_bbreg(hw,
 						RFPGA0_XA_HSSIPARAMETER2,
 						0x200);
@@ -626,6 +626,11 @@ void rtl92se_tx_fill_desc(struct ieee80211_hw *hw,
 
 	CLEAR_PCI_TX_DESC_CONTENT(pdesc, TX_DESC_SIZE_RTL8192S);
 
+	if (ieee80211_is_nullfunc(fc) || ieee80211_is_ctl(fc)) {
+		firstseg = true;
+		lastseg = true;
+	}
+
 	if (firstseg) {
 		if (rtlpriv->dm.useramask) {
 			/* set txdesc macId */
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [PATCH 4/6] rtlwifi: Add changes for new vendor driver version
  2012-08-21 15:00 ` [PATCH 4/6] rtlwifi: Add changes for new vendor driver version Larry Finger
@ 2012-08-22 10:50   ` Stanislaw Gruszka
  2012-08-23 16:56     ` Larry Finger
  0 siblings, 1 reply; 10+ messages in thread
From: Stanislaw Gruszka @ 2012-08-22 10:50 UTC (permalink / raw)
  To: Larry Finger; +Cc: linville, linux-wireless, Li Chaoming

On Tue, Aug 21, 2012 at 10:00:53AM -0500, Larry Finger wrote:
> From: Li Chaoming <chaoming_li@realsil.com.cn>
> 
> Realtek driver rtl_92ce_92se_92de_linux_mac80211_0005.1230.2011 includes
> many changes not previously included. The main changes are as follows:
> 
> 1. Support for the PHY mode switch implemented for some models.
> 2. Implementation of new routines for the dual-MAC devices.
> 3. Implement a mechanism for reaching the private data storage
>    of the other unit in a dual-MAC device.
> 4. Impplementation of RX aggregation.
> 5. Storage of beacon statistics for roaming.
> 6. The RX routine has been rewritten to reduce the number of O(1) buffers.
> 
> Signed-off-by: Li Chaoming <chaoming_li@realsil.com.cn>
> Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net>
> ---
>  drivers/net/wireless/rtlwifi/base.c  |  323 ++++++++++++++++--
>  drivers/net/wireless/rtlwifi/base.h  |   10 +-
>  drivers/net/wireless/rtlwifi/cam.c   |    7 +-
>  drivers/net/wireless/rtlwifi/core.c  |   76 +++--
>  drivers/net/wireless/rtlwifi/debug.h |    8 +
>  drivers/net/wireless/rtlwifi/efuse.c |   40 ++-
>  drivers/net/wireless/rtlwifi/efuse.h |    1 -
>  drivers/net/wireless/rtlwifi/pci.c   |  624 +++++++++++++++++++---------------
>  drivers/net/wireless/rtlwifi/pci.h   |    3 +
>  drivers/net/wireless/rtlwifi/ps.c    |   93 ++++-
>  drivers/net/wireless/rtlwifi/ps.h    |    3 +-
>  drivers/net/wireless/rtlwifi/rc.c    |    3 +-
>  drivers/net/wireless/rtlwifi/regd.c  |   18 +
>  13 files changed, 851 insertions(+), 358 deletions(-)

Could Realsil/Realtek post small patches please?

See "Separate your changes." from Documentation/SubmittingPatches.

You must have separate patches in repositories already. Life is strange,
but I don't believe Realsil/Realtek develops driver without source
control :-)

>  	    /* IEEE80211_HW_SUPPORTS_CQM_RSSI | */
> -	    IEEE80211_HW_REPORTS_TX_ACK_STATUS | 0;
> +	    IEEE80211_HW_REPORTS_TX_ACK_STATUS |
> +	    WIPHY_FLAG_IBSS_RSN |
This flags belongs to hw->wiphy->flags.

Apparently RSN IBSS functionality wasn't tested, so for now, this probably
should be removed.

> +	init_timer(&rtlpriv->works.dualmac_easyconcurrent_retrytimer);
> +	setup_timer(&rtlpriv->works.dualmac_easyconcurrent_retrytimer,
> +		    rtl_easy_concurrent_retrytimer_callback, (unsigned long)hw);
Nit: init_timer is not needed if setup_timer is used.

>  	mutex_init(&rtlpriv->locks.conf_mutex);
> -	mutex_init(&rtlpriv->locks.ps_mutex);
>  	spin_lock_init(&rtlpriv->locks.ips_lock);
>  	spin_lock_init(&rtlpriv->locks.irq_th_lock);
>  	spin_lock_init(&rtlpriv->locks.h2c_lock);
>  	spin_lock_init(&rtlpriv->locks.rf_ps_lock);
>  	spin_lock_init(&rtlpriv->locks.rf_lock);
> +	spin_lock_init(&rtlpriv->locks.lps_lock);
This reverts various changes we did in kernel driver regarding PS
locking, which was started by commit:

commit 312d5479dcfaca2b8aa451201b5388fdb8c8684a
Author: Mike McCormack <mikem@ring3k.org>
Date:   Tue May 31 08:49:36 2011 +0900

    rtlwifi: Don't block interrupts in spinlocks

I wonder if this change does not reintroduce "disabling interrupts for
long time" problem.

Also below there is overwrite of IRQ_HANDLED fix. I did not check more,
but possibly patch also overwrite some other, more important fixes
we have in kernel version of rtlwifi driver. Larry put dozen of fixes to
driver, would be pity to lost them.

> +/* mac80211 have issues when receive del ba
> + * so here we just make a fake del_ba when we receive a ba_req
> + * but rx_agg was opened to let mac80211 release some ba
> + * related resources, so please this del_ba for tx
> + */

So this issue should be fixed in mac80211 instead of work around 
in driver.

BTW, such approach is typical "platform problem" (see
http://lwn.net/Articles/443531/), which frustrate kernel developers.
Please participate in mac80211 and other kernel core components too.

>  static irqreturn_t _rtl_pci_interrupt(int irq, void *dev_id)
> @@ -775,7 +865,6 @@ static irqreturn_t _rtl_pci_interrupt(int irq, void *dev_id)
>  	unsigned long flags;
>  	u32 inta = 0;
>  	u32 intb = 0;
> -	irqreturn_t ret = IRQ_HANDLED;
>  
>  	spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags);
>  
> @@ -783,10 +872,8 @@ static irqreturn_t _rtl_pci_interrupt(int irq, void *dev_id)
>  	rtlpriv->cfg->ops->interrupt_recognized(hw, &inta, &intb);
>  
>  	/*Shared IRQ or HW disappared */
> -	if (!inta || inta == 0xffff) {
> -		ret = IRQ_NONE;
> +	if (!inta || inta == 0xffff)
>  		goto done;
> -	}
>  
>  	/*<1> beacon related */
>  	if (inta & rtlpriv->cfg->maps[RTL_IMR_TBDOK]) {
> @@ -889,7 +976,7 @@ static irqreturn_t _rtl_pci_interrupt(int irq, void *dev_id)
>  
>  done:
>  	spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags);
> -	return ret;
> +	return IRQ_HANDLED;
Overwrite of:

commit de2e56cea25c80f91a6c6699de40fb3fe8b2479d
Author: Larry Finger <Larry.Finger@lwfinger.net>
Date:   Wed Nov 23 21:30:19 2011 -0600

    rtlwifi: Fix incorrect return of IRQ_HANDLED

> +/* this is used for other modules get
> + * hw pointer in rtl_pci_get_hw_pointer
> + */
> +static struct ieee80211_hw *hw_export;
> +
>  int __devinit rtl_pci_probe(struct pci_dev *pdev,
>  			    const struct pci_device_id *id)
>  {
> @@ -1785,6 +1832,7 @@ int __devinit rtl_pci_probe(struct pci_dev *pdev,
>  		err = -ENOMEM;
>  		goto fail1;
>  	}
> +	hw_export = hw;
How this is suppose to work, this variable will be overwritten by
any ->pci_probe ? In general this buddy/glabal_var stuff is very 
fishy, but I did not looked in detail at that. Does all of
that actually work ? 

>  	if (rtlpci->irq_alloc) {
> +		synchronize_irq(rtlpci->pdev->irq);
>  		free_irq(rtlpci->pdev->irq, hw);
Nit: not needed - free_irq do sync internally.

> +static void _rtl_dump_channel_map(struct wiphy *wiphy)
> +{
> +	enum ieee80211_band band;
> +	struct ieee80211_supported_band *sband;
> +	struct ieee80211_channel *ch;
> +	unsigned int i;
> +
> +	for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
> +		if (!wiphy->bands[band])
> +			continue;
> +		sband = wiphy->bands[band];
> +		for (i = 0; i < sband->n_channels; i++)
> +			ch = &sband->channels[i];
> +	}
> +}
This functions doesn't do anything useful.

Thanks
Stanislaw

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 4/6] rtlwifi: Add changes for new vendor driver version
  2012-08-22 10:50   ` Stanislaw Gruszka
@ 2012-08-23 16:56     ` Larry Finger
  2012-08-24  8:59       ` Stanislaw Gruszka
  0 siblings, 1 reply; 10+ messages in thread
From: Larry Finger @ 2012-08-23 16:56 UTC (permalink / raw)
  To: Stanislaw Gruszka; +Cc: linville, linux-wireless, Li Chaoming

On 08/22/2012 05:50 AM, Stanislaw Gruszka wrote:

Stanislaw,

Thanks for the review. I have in-line responses.

> On Tue, Aug 21, 2012 at 10:00:53AM -0500, Larry Finger wrote:
>> From: Li Chaoming <chaoming_li@realsil.com.cn>
>>
>> Realtek driver rtl_92ce_92se_92de_linux_mac80211_0005.1230.2011 includes
>> many changes not previously included. The main changes are as follows:
>>
>> 1. Support for the PHY mode switch implemented for some models.
>> 2. Implementation of new routines for the dual-MAC devices.
>> 3. Implement a mechanism for reaching the private data storage
>>     of the other unit in a dual-MAC device.
>> 4. Impplementation of RX aggregation.
>> 5. Storage of beacon statistics for roaming.
>> 6. The RX routine has been rewritten to reduce the number of O(1) buffers.
>>
>> Signed-off-by: Li Chaoming <chaoming_li@realsil.com.cn>
>> Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net>
>> ---
>>   drivers/net/wireless/rtlwifi/base.c  |  323 ++++++++++++++++--
>>   drivers/net/wireless/rtlwifi/base.h  |   10 +-
>>   drivers/net/wireless/rtlwifi/cam.c   |    7 +-
>>   drivers/net/wireless/rtlwifi/core.c  |   76 +++--
>>   drivers/net/wireless/rtlwifi/debug.h |    8 +
>>   drivers/net/wireless/rtlwifi/efuse.c |   40 ++-
>>   drivers/net/wireless/rtlwifi/efuse.h |    1 -
>>   drivers/net/wireless/rtlwifi/pci.c   |  624 +++++++++++++++++++---------------
>>   drivers/net/wireless/rtlwifi/pci.h   |    3 +
>>   drivers/net/wireless/rtlwifi/ps.c    |   93 ++++-
>>   drivers/net/wireless/rtlwifi/ps.h    |    3 +-
>>   drivers/net/wireless/rtlwifi/rc.c    |    3 +-
>>   drivers/net/wireless/rtlwifi/regd.c  |   18 +
>>   13 files changed, 851 insertions(+), 358 deletions(-)
>
> Could Realsil/Realtek post small patches please?
>
> See "Separate your changes." from Documentation/SubmittingPatches.
>
> You must have separate patches in repositories already. Life is strange,
> but I don't believe Realsil/Realtek develops driver without source
> control :-)

Sorry for making the patch so large.

I have no idea what Realtek uses for version control, but I have no access to 
it. What I get from them is a complete new version of a driver. To discover what 
changes have been made, I diff the new version against the old and prepare the 
necessary patches for the in-kernel versions, which have diverged from the 
vendor version. Most of the changes are cosmetic, but not all of them fit that 
category. When patches are submitted, I mark them as from Realtek authors when 
that is appropriate. If the change is something that I instituted, then I claim 
authorship. In either case, I am the one that prepared the patch.

>>   	    /* IEEE80211_HW_SUPPORTS_CQM_RSSI | */
>> -	    IEEE80211_HW_REPORTS_TX_ACK_STATUS | 0;
>> +	    IEEE80211_HW_REPORTS_TX_ACK_STATUS |
>> +	    WIPHY_FLAG_IBSS_RSN |
> This flags belongs to hw->wiphy->flags.
>
> Apparently RSN IBSS functionality wasn't tested, so for now, this probably
> should be removed.

OK.

>> +	init_timer(&rtlpriv->works.dualmac_easyconcurrent_retrytimer);
>> +	setup_timer(&rtlpriv->works.dualmac_easyconcurrent_retrytimer,
>> +		    rtl_easy_concurrent_retrytimer_callback, (unsigned long)hw);
> Nit: init_timer is not needed if setup_timer is used.

Good to know.

>>   	mutex_init(&rtlpriv->locks.conf_mutex);
>> -	mutex_init(&rtlpriv->locks.ps_mutex);
>>   	spin_lock_init(&rtlpriv->locks.ips_lock);
>>   	spin_lock_init(&rtlpriv->locks.irq_th_lock);
>>   	spin_lock_init(&rtlpriv->locks.h2c_lock);
>>   	spin_lock_init(&rtlpriv->locks.rf_ps_lock);
>>   	spin_lock_init(&rtlpriv->locks.rf_lock);
>> +	spin_lock_init(&rtlpriv->locks.lps_lock);
> This reverts various changes we did in kernel driver regarding PS
> locking, which was started by commit:
>
> commit 312d5479dcfaca2b8aa451201b5388fdb8c8684a
> Author: Mike McCormack <mikem@ring3k.org>
> Date:   Tue May 31 08:49:36 2011 +0900
>
>      rtlwifi: Don't block interrupts in spinlocks
>
> I wonder if this change does not reintroduce "disabling interrupts for
> long time" problem.
>
> Also below there is overwrite of IRQ_HANDLED fix. I did not check more,
> but possibly patch also overwrite some other, more important fixes
> we have in kernel version of rtlwifi driver. Larry put dozen of fixes to
> driver, would be pity to lost them.

I got confused here. I certainly have no intent to undo my work.

>> +/* mac80211 have issues when receive del ba
>> + * so here we just make a fake del_ba when we receive a ba_req
>> + * but rx_agg was opened to let mac80211 release some ba
>> + * related resources, so please this del_ba for tx
>> + */
>
> So this issue should be fixed in mac80211 instead of work around
> in driver.
>
> BTW, such approach is typical "platform problem" (see
> http://lwn.net/Articles/443531/), which frustrate kernel developers.
> Please participate in mac80211 and other kernel core components too.

I will pass that on to Chaoming, and I will remove that routine and its call. As 
soon as possible, I hope to have a patch for mac80211.

>>   static irqreturn_t _rtl_pci_interrupt(int irq, void *dev_id)
>> @@ -775,7 +865,6 @@ static irqreturn_t _rtl_pci_interrupt(int irq, void *dev_id)
>>   	unsigned long flags;
>>   	u32 inta = 0;
>>   	u32 intb = 0;
>> -	irqreturn_t ret = IRQ_HANDLED;
>>
>>   	spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags);
>>
>> @@ -783,10 +872,8 @@ static irqreturn_t _rtl_pci_interrupt(int irq, void *dev_id)
>>   	rtlpriv->cfg->ops->interrupt_recognized(hw, &inta, &intb);
>>
>>   	/*Shared IRQ or HW disappared */
>> -	if (!inta || inta == 0xffff) {
>> -		ret = IRQ_NONE;
>> +	if (!inta || inta == 0xffff)
>>   		goto done;
>> -	}
>>
>>   	/*<1> beacon related */
>>   	if (inta & rtlpriv->cfg->maps[RTL_IMR_TBDOK]) {
>> @@ -889,7 +976,7 @@ static irqreturn_t _rtl_pci_interrupt(int irq, void *dev_id)
>>
>>   done:
>>   	spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags);
>> -	return ret;
>> +	return IRQ_HANDLED;
> Overwrite of:
>
> commit de2e56cea25c80f91a6c6699de40fb3fe8b2479d
> Author: Larry Finger <Larry.Finger@lwfinger.net>
> Date:   Wed Nov 23 21:30:19 2011 -0600
>
>      rtlwifi: Fix incorrect return of IRQ_HANDLED
>

This will be fixed.

>> +/* this is used for other modules get
>> + * hw pointer in rtl_pci_get_hw_pointer
>> + */
>> +static struct ieee80211_hw *hw_export;
>> +
>>   int __devinit rtl_pci_probe(struct pci_dev *pdev,
>>   			    const struct pci_device_id *id)
>>   {
>> @@ -1785,6 +1832,7 @@ int __devinit rtl_pci_probe(struct pci_dev *pdev,
>>   		err = -ENOMEM;
>>   		goto fail1;
>>   	}
>> +	hw_export = hw;
> How this is suppose to work, this variable will be overwritten by
> any ->pci_probe ? In general this buddy/glabal_var stuff is very
> fishy, but I did not looked in detail at that. Does all of
> that actually work ?

The question of whether it works will need to be deferred to Chaoming. The 
situation is that the device has both a 2.4 GHz part and a 5 GHz part that 
register as two separate devices; however, each driver instance needs to have 
access to some of the private variables of the other. Can you point me to an 
example of a safe way to do this without using a global variable?

>>   	if (rtlpci->irq_alloc) {
>> +		synchronize_irq(rtlpci->pdev->irq);
>>   		free_irq(rtlpci->pdev->irq, hw);
> Nit: not needed - free_irq do sync internally.

Thanks.

>> +static void _rtl_dump_channel_map(struct wiphy *wiphy)
>> +{
>> +	enum ieee80211_band band;
>> +	struct ieee80211_supported_band *sband;
>> +	struct ieee80211_channel *ch;
>> +	unsigned int i;
>> +
>> +	for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
>> +		if (!wiphy->bands[band])
>> +			continue;
>> +		sband = wiphy->bands[band];
>> +		for (i = 0; i < sband->n_channels; i++)
>> +			ch = &sband->channels[i];
>> +	}
>> +}
> This functions doesn't do anything useful.

Agreed. I must have missed something. If not, it will go away.

Thanks again,

Larry


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 4/6] rtlwifi: Add changes for new vendor driver version
  2012-08-23 16:56     ` Larry Finger
@ 2012-08-24  8:59       ` Stanislaw Gruszka
  0 siblings, 0 replies; 10+ messages in thread
From: Stanislaw Gruszka @ 2012-08-24  8:59 UTC (permalink / raw)
  To: Larry Finger; +Cc: linville, linux-wireless, Li Chaoming

Hi Larry

On Thu, Aug 23, 2012 at 11:56:51AM -0500, Larry Finger wrote:
> >Could Realsil/Realtek post small patches please?
> >
> >See "Separate your changes." from Documentation/SubmittingPatches.
> >
> >You must have separate patches in repositories already. Life is strange,
> >but I don't believe Realsil/Realtek develops driver without source
> >control :-)
> 
> Sorry for making the patch so large.
> 
> I have no idea what Realtek uses for version control, but I have no
> access to it. What I get from them is a complete new version of a
> driver. To discover what changes have been made, I diff the new
> version against the old and prepare the necessary patches for the
> in-kernel versions, which have diverged from the vendor version.
> Most of the changes are cosmetic, but not all of them fit that
> category. When patches are submitted, I mark them as from Realtek
> authors when that is appropriate. If the change is something that I
> instituted, then I claim authorship. In either case, I am the one
> that prepared the patch.

Ok, I thought/hoped that Realtek is involved into that patch submission.
But if that is only your work, based on vendor driver release, I don't
want you to separate patches into smaller paces, since that is very
tedious work.

> >How this is suppose to work, this variable will be overwritten by
> >any ->pci_probe ? In general this buddy/glabal_var stuff is very
> >fishy, but I did not looked in detail at that. Does all of
> >that actually work ?
> 
> The question of whether it works will need to be deferred to
> Chaoming. The situation is that the device has both a 2.4 GHz part
> and a 5 GHz part that register as two separate devices; however,
> each driver instance needs to have access to some of the private
> variables of the other. Can you point me to an example of a safe way
> to do this without using a global variable?

Global variable is fine for that, but this need to be done carefully.

Thanks
Stanislaw

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2012-08-24  9:01 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-08-21 15:00 [PATCH 0/6] Updates to rtlwifi family to match latest vendor version Larry Finger
2012-08-21 15:00 ` [PATCH 1/6] rtlwifi: rtl8192c: rtl8192de: Fix typo in cursta_connectctate Larry Finger
2012-08-21 15:00 ` [PATCH 2/6] rtlwifi: rtl8192c: rtl8192ce: rtl8192cu: rtl8192se: Remove sparse warnings Larry Finger
2012-08-21 15:00 ` [PATCH 3/6] rtlwifi: Update header file Larry Finger
2012-08-21 15:00 ` [PATCH 4/6] rtlwifi: Add changes for new vendor driver version Larry Finger
2012-08-22 10:50   ` Stanislaw Gruszka
2012-08-23 16:56     ` Larry Finger
2012-08-24  8:59       ` Stanislaw Gruszka
2012-08-21 15:00 ` [PATCH 5/6] rtlwifi: rtl8192ce: Update " Larry Finger
2012-08-21 15:00 ` [PATCH 6/6] rtlwifi: rtl8192se: Update driver for changes in 12/30/2011 vendor version Larry Finger

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.