Search Linux Wireless

[PATCH] wifi: rtlwifi: Fix setting the basic rates

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



RTL8192CU transmits RTS frames at 48M instead of the expected 24M.
This is because rtlwifi never writes REG_INIRTS_RATE_SEL, because when
rtl_op_bss_info_changed() is called with BSS_CHANGED_BASIC_RATES (and
BSS_CHANGED_BSSID) it calls ieee80211_find_sta(), which returns NULL,
and the code skips over the part that handles BSS_CHANGED_BASIC_RATES.

A bit later rtl_op_bss_info_changed() is called with BSS_CHANGED_ASSOC.
At this point ieee80211_find_sta() works, so set the basic rates from
here.

Some of the code from BSS_CHANGED_BSSID which needs ieee80211_find_sta()
was already duplicated under BSS_CHANGED_ASSOC, so delete it from
BSS_CHANGED_BSSID.

Signed-off-by: Bitterblue Smith <rtl8821cerfe2@xxxxxxxxx>
---

I'm not sure if this is enough. Should we also handle
BSS_CHANGED_BASIC_RATES? But bss_conf->basic_rates is only 0xf (CCK
rates only) and the out-of-tree Realtek drivers want to use the 6, 12,
and 24M rates as well. If ieee80211_find_sta() returns NULL, how can we
know if OFDM rates are supported?

I'm also not sure if it's okay to set the basic rates later than
originally intended, but it's still better than never.
---
 drivers/net/wireless/realtek/rtlwifi/core.c | 103 ++++++--------------
 1 file changed, 32 insertions(+), 71 deletions(-)

diff --git a/drivers/net/wireless/realtek/rtlwifi/core.c b/drivers/net/wireless/realtek/rtlwifi/core.c
index 2e60a6991ca1..7a68c528bcd2 100644
--- a/drivers/net/wireless/realtek/rtlwifi/core.c
+++ b/drivers/net/wireless/realtek/rtlwifi/core.c
@@ -1139,6 +1139,15 @@ static void rtl_op_bss_info_changed(struct ieee80211_hw *hw,
 					mac->mode = WIRELESS_MODE_N_24G;
 				else
 					mac->mode = WIRELESS_MODE_N_5G;
+
+				mac->ht_enable = true;
+
+				/*
+				* for cisco 1252 bw20 it's wrong
+				* if (ht_cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) {
+				*	mac->bw_40 = true;
+				* }
+				* */
 			}
 
 			if (sta->deflink.vht_cap.vht_supported) {
@@ -1146,13 +1155,35 @@ static void rtl_op_bss_info_changed(struct ieee80211_hw *hw,
 					mac->mode = WIRELESS_MODE_AC_5G;
 				else
 					mac->mode = WIRELESS_MODE_AC_24G;
+
+				mac->vht_enable = true;
 			}
 
-			if (vif->type == NL80211_IFTYPE_STATION)
+			if (vif->type == NL80211_IFTYPE_STATION) {
+				struct rtl_sta_info *sta_entry;
+
+				sta_entry = (struct rtl_sta_info *)sta->drv_priv;
+				/* Just station needs it, because ibss & ap mode
+				 * will set in sta_add, and will be NULL here.
+				 */
+				sta_entry->wireless_mode = mac->mode;
+
 				rtlpriv->cfg->ops->update_rate_tbl(hw, sta, 0,
 								   true);
+			}
+
+			/* for 5G must << RATE_6M_INDEX = 4,
+			 * because 5G have no cck rate*/
+			if (rtlhal->current_bandtype == BAND_ON_5G)
+				mac->basic_rates = sta->deflink.supp_rates[1] << 4;
+			else
+				mac->basic_rates = sta->deflink.supp_rates[0];
+
 			rcu_read_unlock();
 
+			rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_BASIC_RATE,
+						      (u8 *)(&mac->basic_rates));
+
 			/* to avoid AP Disassociation caused by inactivity */
 			rtlpriv->cfg->ops->set_hw_reg(hw,
 						      HW_VAR_KEEP_ALIVE,
@@ -1266,9 +1297,6 @@ static void rtl_op_bss_info_changed(struct ieee80211_hw *hw,
 	}
 
 	if (changed & BSS_CHANGED_BSSID) {
-		u32 basic_rates;
-		struct ieee80211_sta *sta = NULL;
-
 		rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_BSSID,
 					      (u8 *)bss_conf->bssid);
 
@@ -1277,73 +1305,6 @@ static void rtl_op_bss_info_changed(struct ieee80211_hw *hw,
 
 		mac->vendor = PEER_UNKNOWN;
 		memcpy(mac->bssid, bss_conf->bssid, ETH_ALEN);
-
-		rcu_read_lock();
-		sta = ieee80211_find_sta(vif, (u8 *)bss_conf->bssid);
-		if (!sta) {
-			rcu_read_unlock();
-			goto out;
-		}
-
-		if (rtlhal->current_bandtype == BAND_ON_5G) {
-			mac->mode = WIRELESS_MODE_A;
-		} else {
-			if (sta->deflink.supp_rates[0] <= 0xf)
-				mac->mode = WIRELESS_MODE_B;
-			else
-				mac->mode = WIRELESS_MODE_G;
-		}
-
-		if (sta->deflink.ht_cap.ht_supported) {
-			if (rtlhal->current_bandtype == BAND_ON_2_4G)
-				mac->mode = WIRELESS_MODE_N_24G;
-			else
-				mac->mode = WIRELESS_MODE_N_5G;
-		}
-
-		if (sta->deflink.vht_cap.vht_supported) {
-			if (rtlhal->current_bandtype == BAND_ON_5G)
-				mac->mode = WIRELESS_MODE_AC_5G;
-			else
-				mac->mode = WIRELESS_MODE_AC_24G;
-		}
-
-		/* just station need it, because ibss & ap mode will
-		 * set in sta_add, and will be NULL here */
-		if (vif->type == NL80211_IFTYPE_STATION) {
-			struct rtl_sta_info *sta_entry;
-
-			sta_entry = (struct rtl_sta_info *)sta->drv_priv;
-			sta_entry->wireless_mode = mac->mode;
-		}
-
-		if (sta->deflink.ht_cap.ht_supported) {
-			mac->ht_enable = true;
-
-			/*
-			 * for cisco 1252 bw20 it's wrong
-			 * if (ht_cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) {
-			 *	mac->bw_40 = true;
-			 * }
-			 * */
-		}
-
-		if (sta->deflink.vht_cap.vht_supported)
-			mac->vht_enable = true;
-
-		if (changed & BSS_CHANGED_BASIC_RATES) {
-			/* for 5G must << RATE_6M_INDEX = 4,
-			 * because 5G have no cck rate*/
-			if (rtlhal->current_bandtype == BAND_ON_5G)
-				basic_rates = sta->deflink.supp_rates[1] << 4;
-			else
-				basic_rates = sta->deflink.supp_rates[0];
-
-			mac->basic_rates = basic_rates;
-			rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_BASIC_RATE,
-					(u8 *)(&basic_rates));
-		}
-		rcu_read_unlock();
 	}
 out:
 	mutex_unlock(&rtlpriv->locks.conf_mutex);
-- 
2.43.0




[Index of Archives]     [Linux Host AP]     [ATH6KL]     [Linux Wireless Personal Area Network]     [Linux Bluetooth]     [Wireless Regulations]     [Linux Netdev]     [Kernel Newbies]     [Linux Kernel]     [IDE]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite Hiking]     [MIPS Linux]     [ARM Linux]     [Linux RAID]

  Powered by Linux