2017-12-09 17:37:16

by Larry Finger

[permalink] [raw]
Subject: [PATCH 0/3] rtlwifi: rtl_pci: More updates to mini driver for RTL8822BE

These changes are for the 4.16 stream.

The modifications implement nearly all the changes needed to allow the
RTL8822BE in staging to use rtl_pci in the wireless tree. The only
exceptions are related to BT coexistence, which will be added once btcoex
is updated.

Once these patches reach mainline, I will submit a patch to staging that
changes r8822be to use the standard rtl_pci, and deletes the duplicated
code.

Signed-off-by: Larry Finger <[email protected]>
Cc: Ping-Ke Shih <[email protected]>
Cc: Yan-Hsuan Chuang <[email protected]>
Cc: Birming Chiu <[email protected]>
Cc: Shaofu <[email protected]>
Cc: Steven Ting <[email protected]>

Ping-Ke Shih (1):
rtlwifi: rtl_pci: 8822BE puts broadcast and multicast packet to HIQ

Tsang-Shian Lin (2):
rtlwifi: Add beacon check mechanism to check if AP settings changed.
rtlwifi: rtl_pci: Fix the bug when inactiveps is enabled.

drivers/net/wireless/realtek/rtlwifi/base.c | 179 ++++++++++++++++++++++++++++
drivers/net/wireless/realtek/rtlwifi/base.h | 3 +-
drivers/net/wireless/realtek/rtlwifi/core.c | 48 ++++++++
drivers/net/wireless/realtek/rtlwifi/pci.c | 17 +++
drivers/net/wireless/realtek/rtlwifi/wifi.h | 13 ++
5 files changed, 259 insertions(+), 1 deletion(-)

--
2.15.1


2017-12-14 16:06:23

by Larry Finger

[permalink] [raw]
Subject: Re: [PATCH 2/3] rtlwifi: Add beacon check mechanism to check if AP settings changed.

On 12/14/2017 06:35 AM, Kalle Valo wrote:
> Larry Finger <[email protected]> writes:
>
>> From: Tsang-Shian Lin <[email protected]>
>>
>> +bool rtl_check_beacon_key(struct ieee80211_hw *hw, void *data, unsigned int len)
>> +{
>> + struct rtl_priv *rtlpriv = rtl_priv(hw);
>> + struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
>> + struct rtl_phy *rtlphy = &rtlpriv->phy;
>> + struct ieee80211_hdr *hdr = data;
>> + struct ieee80211_ht_cap *ht_cap_ie;
>> + struct ieee80211_ht_operation *ht_oper_ie = NULL;
>> + struct rtl_beacon_keys bcn_key = {0};
>> + struct rtl_beacon_keys *cur_bcn_key;
>> + u8 *ht_cap;
>> + u8 ht_cap_len;
>> + u8 *ht_oper;
>> + u8 ht_oper_len;
>> + u8 *ds_param;
>> + u8 ds_param_len;
>> +
>> + if (mac->opmode != NL80211_IFTYPE_STATION)
>> + return false;
>> +
>> + /* check if this really is a beacon*/
>> + if (!ieee80211_is_beacon(hdr->frame_control))
>> + return false;
>> +
>> + /* min. beacon length + FCS_LEN */
>> + if (len <= 40 + FCS_LEN)
>> + return false;
>> +
>> + cur_bcn_key = &mac->cur_beacon_keys;
>> +
>> + if (rtlpriv->mac80211.link_state == MAC80211_NOLINK) {
>> + if (cur_bcn_key->valid) {
>> + cur_bcn_key->valid = false;
>> + RT_TRACE(rtlpriv, COMP_BEACON, DBG_LOUD,
>> + "Reset cur_beacon_keys.valid to false!\n");
>> + }
>> + return false;
>> + }
>> +
>> + /* and only beacons from the associated BSSID, please */
>> + if (!ether_addr_equal(hdr->addr3, rtlpriv->mac80211.bssid))
>> + return false;
>> +
>> + /***** Parsing DS Param IE ******/
>> + ds_param = rtl_find_ie(data, len - FCS_LEN, WLAN_EID_DS_PARAMS);
>> +
>> + if (ds_param && !(ds_param[1] < sizeof(*ds_param)))
>> + ds_param_len = ds_param[1];
>> + else
>> + ds_param = NULL;
>> +
>> + /***** Parsing HT Cap. IE ******/
>> + ht_cap = rtl_find_ie(data, len - FCS_LEN, WLAN_EID_HT_CAPABILITY);
>> +
>> + if (ht_cap && !(ht_cap[1] < sizeof(*ht_cap))) {
>> + ht_cap_len = ht_cap[1];
>> + ht_cap_ie = (struct ieee80211_ht_cap *)&ht_cap[2];
>> + } else {
>> + ht_cap = NULL;
>> + ht_cap_ie = NULL;
>> + }
>> +
>> + /***** Parsing HT Info. IE ******/
>> + ht_oper = rtl_find_ie(data, len - FCS_LEN, WLAN_EID_HT_OPERATION);
>> +
>> + if (ht_oper && !(ht_oper[1] < sizeof(*ht_oper))) {
>> + ht_oper_len = ht_oper[1];
>> + ht_oper_ie = (struct ieee80211_ht_operation *)&ht_oper[2];
>> + } else {
>> + ht_oper = NULL;
>> + }
>> +
>> + /* update bcn_key */
>> + memset(&bcn_key, 0, sizeof(bcn_key));
>> +
>> + if (ds_param)
>> + bcn_key.bcn_channel = ds_param[2];
>> + else if (ht_oper && ht_oper_ie)
>> + bcn_key.bcn_channel = ht_oper_ie->primary_chan;
>> +
>> + if (ht_cap_ie)
>> + bcn_key.ht_cap_info = ht_cap_ie->cap_info;
>> +
>> + if (ht_oper && ht_oper_ie)
>> + bcn_key.ht_info_infos_0_sco = ht_oper_ie->ht_param & 0x03;
>> +
>> + bcn_key.valid = true;
>> +
>> + /* update cur_beacon_keys or compare beacon key */
>> + if (rtlpriv->mac80211.link_state != MAC80211_LINKED &&
>> + rtlpriv->mac80211.link_state != MAC80211_LINKED_SCANNING)
>> + return true;
>> +
>> + if (!cur_bcn_key->valid) {
>> + /* update cur_beacon_keys */
>> + memset(cur_bcn_key, 0, sizeof(bcn_key));
>> + memcpy(cur_bcn_key, &bcn_key, sizeof(bcn_key));
>> + cur_bcn_key->valid = true;
>> +
>> + RT_TRACE(rtlpriv, COMP_BEACON, DBG_LOUD,
>> + "Beacon key update!ch=%d, ht_cap_info=0x%x, sco=0x%x\n",
>> + cur_bcn_key->bcn_channel,
>> + cur_bcn_key->ht_cap_info,
>> + cur_bcn_key->ht_info_infos_0_sco);
>> +
>> + return true;
>> + }
>> +
>> + /* compare beacon key */
>> + if (!memcmp(cur_bcn_key, &bcn_key, sizeof(bcn_key))) {
>> + /* same beacon key */
>> + mac->new_beacon_cnt = 0;
>> + goto chk_exit;
>> + }
>> +
>> + if (cur_bcn_key->bcn_channel == bcn_key.bcn_channel &&
>> + cur_bcn_key->ht_cap_info == bcn_key.ht_cap_info) {
>> + /* Beacon HT info IE, secondary channel offset check */
>> + /* 40M -> 20M */
>> + if (cur_bcn_key->ht_info_infos_0_sco >
>> + bcn_key.ht_info_infos_0_sco) {
>> + /* Not a new beacon */
>> + RT_TRACE(rtlpriv, COMP_BEACON, DBG_DMESG,
>> + "Beacon BW change! sco:0x%x -> 0x%x\n",
>> + cur_bcn_key->ht_info_infos_0_sco,
>> + bcn_key.ht_info_infos_0_sco);
>> +
>> + cur_bcn_key->ht_info_infos_0_sco =
>> + bcn_key.ht_info_infos_0_sco;
>> + } else {
>> + /* 20M -> 40M */
>> + if (rtlphy->max_ht_chan_bw >= HT_CHANNEL_WIDTH_20_40) {
>> + /* Not a new beacon */
>> + RT_TRACE(rtlpriv, COMP_BEACON, DBG_DMESG,
>> + "Beacon BW change! sco:0x%x -> 0x%x\n",
>> + cur_bcn_key->ht_info_infos_0_sco,
>> + bcn_key.ht_info_infos_0_sco);
>> +
>> + cur_bcn_key->ht_info_infos_0_sco =
>> + bcn_key.ht_info_infos_0_sco;
>> + } else {
>> + mac->new_beacon_cnt++;
>> + }
>> + }
>> + } else {
>> + mac->new_beacon_cnt++;
>> + }
>> +
>> + if (mac->new_beacon_cnt == 1) {
>> + RT_TRACE(rtlpriv, COMP_BEACON, DBG_DMESG,
>> + "Get new beacon.\n");
>> + RT_TRACE(rtlpriv, COMP_BEACON, DBG_DMESG,
>> + "Cur : ch=%d, ht_cap=0x%x, sco=0x%x\n",
>> + cur_bcn_key->bcn_channel,
>> + cur_bcn_key->ht_cap_info,
>> + cur_bcn_key->ht_info_infos_0_sco);
>> + RT_TRACE(rtlpriv, COMP_BEACON, DBG_DMESG,
>> + "New RX : ch=%d, ht_cap=0x%x, sco=0x%x\n",
>> + bcn_key.bcn_channel,
>> + bcn_key.ht_cap_info,
>> + bcn_key.ht_info_infos_0_sco);
>> +
>> + } else if (mac->new_beacon_cnt > 1) {
>> + RT_TRACE(rtlpriv, COMP_BEACON, DBG_DMESG,
>> + "new beacon cnt: %d\n",
>> + mac->new_beacon_cnt);
>> + }
>> +
>> + if (mac->new_beacon_cnt > 3) {
>> + ieee80211_connection_loss(rtlpriv->mac80211.vif);
>> + RT_TRACE(rtlpriv, COMP_BEACON, DBG_DMESG,
>> + "new beacon cnt >3, disconnect !\n");
>> + }
>> +
>> +chk_exit:
>> +
>> + return true;
>> +}
>> +EXPORT_SYMBOL_GPL(rtl_check_beacon_key);
>
> Why do all this in the driver? I would expect something like this to be
> done in mac80211, not in the driver.

Johannes,

Does mac80211 have this facility? If so, how would we tap into it? If this
capability does not exist in mac80211, how would one add it? I have never
devoted much effort to looking at the internals of mac80211.
>
>> +struct rtl_beacon_keys {
>> + /*u8 ssid[32];*/
>> + /*u32 ssid_len;*/
>
> Commented out fields, please drop.

Yes, those will be dropped.

Larry

2017-12-09 17:37:19

by Larry Finger

[permalink] [raw]
Subject: [PATCH 3/3] rtlwifi: rtl_pci: Fix the bug when inactiveps is enabled.

From: Tsang-Shian Lin <[email protected]>

Reset the driver current tx read/write index to zero when inactiveps
nic out of sync with HW state. Wrong driver tx read/write index will
cause Tx fail.

Signed-off-by: Tsang-Shian Lin <[email protected]>
Signed-off-by: Ping-Ke Shih <[email protected]>
Signed-off-by: Larry Finger <[email protected]>
Cc: Yan-Hsuan Chuang <[email protected]>
Cc: Birming Chiu <[email protected]>
Cc: Shaofu <[email protected]>
Cc: Steven Ting <[email protected]>
---
drivers/net/wireless/realtek/rtlwifi/pci.c | 7 +++++++
1 file changed, 7 insertions(+)

diff --git a/drivers/net/wireless/realtek/rtlwifi/pci.c b/drivers/net/wireless/realtek/rtlwifi/pci.c
index 0bafcefacad0..1f2b04bb7ae4 100644
--- a/drivers/net/wireless/realtek/rtlwifi/pci.c
+++ b/drivers/net/wireless/realtek/rtlwifi/pci.c
@@ -1557,7 +1557,14 @@ int rtl_pci_reset_trx_ring(struct ieee80211_hw *hw)
dev_kfree_skb_irq(skb);
ring->idx = (ring->idx + 1) % ring->entries;
}
+
+ if (rtlpriv->use_new_trx_flow) {
+ rtlpci->tx_ring[i].cur_tx_rp = 0;
+ rtlpci->tx_ring[i].cur_tx_wp = 0;
+ }
+
ring->idx = 0;
+ ring->entries = rtlpci->txringcount[i];
}
}
spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags);
--
2.15.1

2017-12-14 12:35:19

by Kalle Valo

[permalink] [raw]
Subject: Re: [PATCH 2/3] rtlwifi: Add beacon check mechanism to check if AP settings changed.

Larry Finger <[email protected]> writes:

> From: Tsang-Shian Lin <[email protected]>
>
> AP WiFi settings are changed(channel, bandwidth), but deauth may not
> received by STA. For these cases, we need to detect and handle beacon
> changes.
>
> Signed-off-by: Tsang-Shian Lin <[email protected]>
> Signed-off-by: Ping-Ke Shih <[email protected]>
> Signed-off-by: Larry Finger <[email protected]>
> Cc: Yan-Hsuan Chuang <[email protected]>
> Cc: Birming Chiu <[email protected]>
> Cc: Shaofu <[email protected]>
> Cc: Steven Ting <[email protected]>

[...]

> --- a/drivers/net/wireless/realtek/rtlwifi/base.c
> +++ b/drivers/net/wireless/realtek/rtlwifi/base.c
> @@ -2360,6 +2360,185 @@ struct sk_buff *rtl_make_del_ba(struct ieee80211_hw *hw,
> return skb;
> }
>
> +bool rtl_check_beacon_key(struct ieee80211_hw *hw, void *data, unsigned int len)
> +{
> + struct rtl_priv *rtlpriv = rtl_priv(hw);
> + struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
> + struct rtl_phy *rtlphy = &rtlpriv->phy;
> + struct ieee80211_hdr *hdr = data;
> + struct ieee80211_ht_cap *ht_cap_ie;
> + struct ieee80211_ht_operation *ht_oper_ie = NULL;
> + struct rtl_beacon_keys bcn_key = {0};
> + struct rtl_beacon_keys *cur_bcn_key;
> + u8 *ht_cap;
> + u8 ht_cap_len;
> + u8 *ht_oper;
> + u8 ht_oper_len;
> + u8 *ds_param;
> + u8 ds_param_len;
> +
> + if (mac->opmode != NL80211_IFTYPE_STATION)
> + return false;
> +
> + /* check if this really is a beacon*/
> + if (!ieee80211_is_beacon(hdr->frame_control))
> + return false;
> +
> + /* min. beacon length + FCS_LEN */
> + if (len <= 40 + FCS_LEN)
> + return false;
> +
> + cur_bcn_key = &mac->cur_beacon_keys;
> +
> + if (rtlpriv->mac80211.link_state == MAC80211_NOLINK) {
> + if (cur_bcn_key->valid) {
> + cur_bcn_key->valid = false;
> + RT_TRACE(rtlpriv, COMP_BEACON, DBG_LOUD,
> + "Reset cur_beacon_keys.valid to false!\n");
> + }
> + return false;
> + }
> +
> + /* and only beacons from the associated BSSID, please */
> + if (!ether_addr_equal(hdr->addr3, rtlpriv->mac80211.bssid))
> + return false;
> +
> + /***** Parsing DS Param IE ******/
> + ds_param = rtl_find_ie(data, len - FCS_LEN, WLAN_EID_DS_PARAMS);
> +
> + if (ds_param && !(ds_param[1] < sizeof(*ds_param)))
> + ds_param_len = ds_param[1];
> + else
> + ds_param = NULL;
> +
> + /***** Parsing HT Cap. IE ******/
> + ht_cap = rtl_find_ie(data, len - FCS_LEN, WLAN_EID_HT_CAPABILITY);
> +
> + if (ht_cap && !(ht_cap[1] < sizeof(*ht_cap))) {
> + ht_cap_len = ht_cap[1];
> + ht_cap_ie = (struct ieee80211_ht_cap *)&ht_cap[2];
> + } else {
> + ht_cap = NULL;
> + ht_cap_ie = NULL;
> + }
> +
> + /***** Parsing HT Info. IE ******/
> + ht_oper = rtl_find_ie(data, len - FCS_LEN, WLAN_EID_HT_OPERATION);
> +
> + if (ht_oper && !(ht_oper[1] < sizeof(*ht_oper))) {
> + ht_oper_len = ht_oper[1];
> + ht_oper_ie = (struct ieee80211_ht_operation *)&ht_oper[2];
> + } else {
> + ht_oper = NULL;
> + }
> +
> + /* update bcn_key */
> + memset(&bcn_key, 0, sizeof(bcn_key));
> +
> + if (ds_param)
> + bcn_key.bcn_channel = ds_param[2];
> + else if (ht_oper && ht_oper_ie)
> + bcn_key.bcn_channel = ht_oper_ie->primary_chan;
> +
> + if (ht_cap_ie)
> + bcn_key.ht_cap_info = ht_cap_ie->cap_info;
> +
> + if (ht_oper && ht_oper_ie)
> + bcn_key.ht_info_infos_0_sco = ht_oper_ie->ht_param & 0x03;
> +
> + bcn_key.valid = true;
> +
> + /* update cur_beacon_keys or compare beacon key */
> + if (rtlpriv->mac80211.link_state != MAC80211_LINKED &&
> + rtlpriv->mac80211.link_state != MAC80211_LINKED_SCANNING)
> + return true;
> +
> + if (!cur_bcn_key->valid) {
> + /* update cur_beacon_keys */
> + memset(cur_bcn_key, 0, sizeof(bcn_key));
> + memcpy(cur_bcn_key, &bcn_key, sizeof(bcn_key));
> + cur_bcn_key->valid = true;
> +
> + RT_TRACE(rtlpriv, COMP_BEACON, DBG_LOUD,
> + "Beacon key update!ch=%d, ht_cap_info=0x%x, sco=0x%x\n",
> + cur_bcn_key->bcn_channel,
> + cur_bcn_key->ht_cap_info,
> + cur_bcn_key->ht_info_infos_0_sco);
> +
> + return true;
> + }
> +
> + /* compare beacon key */
> + if (!memcmp(cur_bcn_key, &bcn_key, sizeof(bcn_key))) {
> + /* same beacon key */
> + mac->new_beacon_cnt = 0;
> + goto chk_exit;
> + }
> +
> + if (cur_bcn_key->bcn_channel == bcn_key.bcn_channel &&
> + cur_bcn_key->ht_cap_info == bcn_key.ht_cap_info) {
> + /* Beacon HT info IE, secondary channel offset check */
> + /* 40M -> 20M */
> + if (cur_bcn_key->ht_info_infos_0_sco >
> + bcn_key.ht_info_infos_0_sco) {
> + /* Not a new beacon */
> + RT_TRACE(rtlpriv, COMP_BEACON, DBG_DMESG,
> + "Beacon BW change! sco:0x%x -> 0x%x\n",
> + cur_bcn_key->ht_info_infos_0_sco,
> + bcn_key.ht_info_infos_0_sco);
> +
> + cur_bcn_key->ht_info_infos_0_sco =
> + bcn_key.ht_info_infos_0_sco;
> + } else {
> + /* 20M -> 40M */
> + if (rtlphy->max_ht_chan_bw >= HT_CHANNEL_WIDTH_20_40) {
> + /* Not a new beacon */
> + RT_TRACE(rtlpriv, COMP_BEACON, DBG_DMESG,
> + "Beacon BW change! sco:0x%x -> 0x%x\n",
> + cur_bcn_key->ht_info_infos_0_sco,
> + bcn_key.ht_info_infos_0_sco);
> +
> + cur_bcn_key->ht_info_infos_0_sco =
> + bcn_key.ht_info_infos_0_sco;
> + } else {
> + mac->new_beacon_cnt++;
> + }
> + }
> + } else {
> + mac->new_beacon_cnt++;
> + }
> +
> + if (mac->new_beacon_cnt == 1) {
> + RT_TRACE(rtlpriv, COMP_BEACON, DBG_DMESG,
> + "Get new beacon.\n");
> + RT_TRACE(rtlpriv, COMP_BEACON, DBG_DMESG,
> + "Cur : ch=%d, ht_cap=0x%x, sco=0x%x\n",
> + cur_bcn_key->bcn_channel,
> + cur_bcn_key->ht_cap_info,
> + cur_bcn_key->ht_info_infos_0_sco);
> + RT_TRACE(rtlpriv, COMP_BEACON, DBG_DMESG,
> + "New RX : ch=%d, ht_cap=0x%x, sco=0x%x\n",
> + bcn_key.bcn_channel,
> + bcn_key.ht_cap_info,
> + bcn_key.ht_info_infos_0_sco);
> +
> + } else if (mac->new_beacon_cnt > 1) {
> + RT_TRACE(rtlpriv, COMP_BEACON, DBG_DMESG,
> + "new beacon cnt: %d\n",
> + mac->new_beacon_cnt);
> + }
> +
> + if (mac->new_beacon_cnt > 3) {
> + ieee80211_connection_loss(rtlpriv->mac80211.vif);
> + RT_TRACE(rtlpriv, COMP_BEACON, DBG_DMESG,
> + "new beacon cnt >3, disconnect !\n");
> + }
> +
> +chk_exit:
> +
> + return true;
> +}
> +EXPORT_SYMBOL_GPL(rtl_check_beacon_key);

Why do all this in the driver? I would expect something like this to be
done in mac80211, not in the driver.

> +struct rtl_beacon_keys {
> + /*u8 ssid[32];*/
> + /*u32 ssid_len;*/

Commented out fields, please drop.

--
Kalle Valo

2017-12-19 09:41:21

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH 2/3] rtlwifi: Add beacon check mechanism to check if AP settings changed.

On Thu, 2017-12-14 at 10:06 -0600, Larry Finger wrote:

> Does mac80211 have this facility? If so, how would we tap into it? If this
> capability does not exist in mac80211, how would one add it? I have never
> devoted much effort to looking at the internals of mac80211.

It really should, and this code looks awful - but can you tell me what
exactly this is doing?

If the AP changed settings, then we should handle this in
ieee80211_rx_mgmt_beacon() and simply reconfigure the driver
accordingly.

johannes

2017-12-14 12:43:23

by Kalle Valo

[permalink] [raw]
Subject: Re: [1/3] rtlwifi: rtl_pci: 8822BE puts broadcast and multicast packet to HIQ

Larry Finger <[email protected]> wrote:

> From: Ping-Ke Shih <[email protected]>
>
> Making this change to HIQ, which has high priority, improves the response
> time for transmission after TBTT or beacon.
>
> Signed-off-by: Ping-Ke Shih <[email protected]>
> Signed-off-by: Larry Finger <[email protected]>
> Cc: Yan-Hsuan Chuang <[email protected]>
> Cc: Birming Chiu <[email protected]>
> Cc: Shaofu <[email protected]>
> Cc: Steven Ting <[email protected]>

2 patches applied to wireless-drivers-next.git, thanks.

e298be2a97fd rtlwifi: rtl_pci: 8822BE puts broadcast and multicast packet to HIQ
b7573a0a27bf rtlwifi: rtl_pci: Fix the bug when inactiveps is enabled.

--
https://patchwork.kernel.org/patch/10103759/

https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches

2017-12-09 17:37:18

by Larry Finger

[permalink] [raw]
Subject: [PATCH 2/3] rtlwifi: Add beacon check mechanism to check if AP settings changed.

From: Tsang-Shian Lin <[email protected]>

AP WiFi settings are changed(channel, bandwidth), but deauth may not
received by STA. For these cases, we need to detect and handle beacon
changes.

Signed-off-by: Tsang-Shian Lin <[email protected]>
Signed-off-by: Ping-Ke Shih <[email protected]>
Signed-off-by: Larry Finger <[email protected]>
Cc: Yan-Hsuan Chuang <[email protected]>
Cc: Birming Chiu <[email protected]>
Cc: Shaofu <[email protected]>
Cc: Steven Ting <[email protected]>
---
drivers/net/wireless/realtek/rtlwifi/base.c | 179 ++++++++++++++++++++++++++++
drivers/net/wireless/realtek/rtlwifi/base.h | 3 +-
drivers/net/wireless/realtek/rtlwifi/core.c | 48 ++++++++
drivers/net/wireless/realtek/rtlwifi/pci.c | 2 +
drivers/net/wireless/realtek/rtlwifi/wifi.h | 13 ++
5 files changed, 244 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/realtek/rtlwifi/base.c b/drivers/net/wireless/realtek/rtlwifi/base.c
index cad2272ae21b..a04afdd55569 100644
--- a/drivers/net/wireless/realtek/rtlwifi/base.c
+++ b/drivers/net/wireless/realtek/rtlwifi/base.c
@@ -2360,6 +2360,185 @@ struct sk_buff *rtl_make_del_ba(struct ieee80211_hw *hw,
return skb;
}

+bool rtl_check_beacon_key(struct ieee80211_hw *hw, void *data, unsigned int len)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+ struct rtl_phy *rtlphy = &rtlpriv->phy;
+ struct ieee80211_hdr *hdr = data;
+ struct ieee80211_ht_cap *ht_cap_ie;
+ struct ieee80211_ht_operation *ht_oper_ie = NULL;
+ struct rtl_beacon_keys bcn_key = {0};
+ struct rtl_beacon_keys *cur_bcn_key;
+ u8 *ht_cap;
+ u8 ht_cap_len;
+ u8 *ht_oper;
+ u8 ht_oper_len;
+ u8 *ds_param;
+ u8 ds_param_len;
+
+ if (mac->opmode != NL80211_IFTYPE_STATION)
+ return false;
+
+ /* check if this really is a beacon*/
+ if (!ieee80211_is_beacon(hdr->frame_control))
+ return false;
+
+ /* min. beacon length + FCS_LEN */
+ if (len <= 40 + FCS_LEN)
+ return false;
+
+ cur_bcn_key = &mac->cur_beacon_keys;
+
+ if (rtlpriv->mac80211.link_state == MAC80211_NOLINK) {
+ if (cur_bcn_key->valid) {
+ cur_bcn_key->valid = false;
+ RT_TRACE(rtlpriv, COMP_BEACON, DBG_LOUD,
+ "Reset cur_beacon_keys.valid to false!\n");
+ }
+ return false;
+ }
+
+ /* and only beacons from the associated BSSID, please */
+ if (!ether_addr_equal(hdr->addr3, rtlpriv->mac80211.bssid))
+ return false;
+
+ /***** Parsing DS Param IE ******/
+ ds_param = rtl_find_ie(data, len - FCS_LEN, WLAN_EID_DS_PARAMS);
+
+ if (ds_param && !(ds_param[1] < sizeof(*ds_param)))
+ ds_param_len = ds_param[1];
+ else
+ ds_param = NULL;
+
+ /***** Parsing HT Cap. IE ******/
+ ht_cap = rtl_find_ie(data, len - FCS_LEN, WLAN_EID_HT_CAPABILITY);
+
+ if (ht_cap && !(ht_cap[1] < sizeof(*ht_cap))) {
+ ht_cap_len = ht_cap[1];
+ ht_cap_ie = (struct ieee80211_ht_cap *)&ht_cap[2];
+ } else {
+ ht_cap = NULL;
+ ht_cap_ie = NULL;
+ }
+
+ /***** Parsing HT Info. IE ******/
+ ht_oper = rtl_find_ie(data, len - FCS_LEN, WLAN_EID_HT_OPERATION);
+
+ if (ht_oper && !(ht_oper[1] < sizeof(*ht_oper))) {
+ ht_oper_len = ht_oper[1];
+ ht_oper_ie = (struct ieee80211_ht_operation *)&ht_oper[2];
+ } else {
+ ht_oper = NULL;
+ }
+
+ /* update bcn_key */
+ memset(&bcn_key, 0, sizeof(bcn_key));
+
+ if (ds_param)
+ bcn_key.bcn_channel = ds_param[2];
+ else if (ht_oper && ht_oper_ie)
+ bcn_key.bcn_channel = ht_oper_ie->primary_chan;
+
+ if (ht_cap_ie)
+ bcn_key.ht_cap_info = ht_cap_ie->cap_info;
+
+ if (ht_oper && ht_oper_ie)
+ bcn_key.ht_info_infos_0_sco = ht_oper_ie->ht_param & 0x03;
+
+ bcn_key.valid = true;
+
+ /* update cur_beacon_keys or compare beacon key */
+ if (rtlpriv->mac80211.link_state != MAC80211_LINKED &&
+ rtlpriv->mac80211.link_state != MAC80211_LINKED_SCANNING)
+ return true;
+
+ if (!cur_bcn_key->valid) {
+ /* update cur_beacon_keys */
+ memset(cur_bcn_key, 0, sizeof(bcn_key));
+ memcpy(cur_bcn_key, &bcn_key, sizeof(bcn_key));
+ cur_bcn_key->valid = true;
+
+ RT_TRACE(rtlpriv, COMP_BEACON, DBG_LOUD,
+ "Beacon key update!ch=%d, ht_cap_info=0x%x, sco=0x%x\n",
+ cur_bcn_key->bcn_channel,
+ cur_bcn_key->ht_cap_info,
+ cur_bcn_key->ht_info_infos_0_sco);
+
+ return true;
+ }
+
+ /* compare beacon key */
+ if (!memcmp(cur_bcn_key, &bcn_key, sizeof(bcn_key))) {
+ /* same beacon key */
+ mac->new_beacon_cnt = 0;
+ goto chk_exit;
+ }
+
+ if (cur_bcn_key->bcn_channel == bcn_key.bcn_channel &&
+ cur_bcn_key->ht_cap_info == bcn_key.ht_cap_info) {
+ /* Beacon HT info IE, secondary channel offset check */
+ /* 40M -> 20M */
+ if (cur_bcn_key->ht_info_infos_0_sco >
+ bcn_key.ht_info_infos_0_sco) {
+ /* Not a new beacon */
+ RT_TRACE(rtlpriv, COMP_BEACON, DBG_DMESG,
+ "Beacon BW change! sco:0x%x -> 0x%x\n",
+ cur_bcn_key->ht_info_infos_0_sco,
+ bcn_key.ht_info_infos_0_sco);
+
+ cur_bcn_key->ht_info_infos_0_sco =
+ bcn_key.ht_info_infos_0_sco;
+ } else {
+ /* 20M -> 40M */
+ if (rtlphy->max_ht_chan_bw >= HT_CHANNEL_WIDTH_20_40) {
+ /* Not a new beacon */
+ RT_TRACE(rtlpriv, COMP_BEACON, DBG_DMESG,
+ "Beacon BW change! sco:0x%x -> 0x%x\n",
+ cur_bcn_key->ht_info_infos_0_sco,
+ bcn_key.ht_info_infos_0_sco);
+
+ cur_bcn_key->ht_info_infos_0_sco =
+ bcn_key.ht_info_infos_0_sco;
+ } else {
+ mac->new_beacon_cnt++;
+ }
+ }
+ } else {
+ mac->new_beacon_cnt++;
+ }
+
+ if (mac->new_beacon_cnt == 1) {
+ RT_TRACE(rtlpriv, COMP_BEACON, DBG_DMESG,
+ "Get new beacon.\n");
+ RT_TRACE(rtlpriv, COMP_BEACON, DBG_DMESG,
+ "Cur : ch=%d, ht_cap=0x%x, sco=0x%x\n",
+ cur_bcn_key->bcn_channel,
+ cur_bcn_key->ht_cap_info,
+ cur_bcn_key->ht_info_infos_0_sco);
+ RT_TRACE(rtlpriv, COMP_BEACON, DBG_DMESG,
+ "New RX : ch=%d, ht_cap=0x%x, sco=0x%x\n",
+ bcn_key.bcn_channel,
+ bcn_key.ht_cap_info,
+ bcn_key.ht_info_infos_0_sco);
+
+ } else if (mac->new_beacon_cnt > 1) {
+ RT_TRACE(rtlpriv, COMP_BEACON, DBG_DMESG,
+ "new beacon cnt: %d\n",
+ mac->new_beacon_cnt);
+ }
+
+ if (mac->new_beacon_cnt > 3) {
+ ieee80211_connection_loss(rtlpriv->mac80211.vif);
+ RT_TRACE(rtlpriv, COMP_BEACON, DBG_DMESG,
+ "new beacon cnt >3, disconnect !\n");
+ }
+
+chk_exit:
+
+ return true;
+}
+EXPORT_SYMBOL_GPL(rtl_check_beacon_key);
/*********************************************************
*
* IOT functions
diff --git a/drivers/net/wireless/realtek/rtlwifi/base.h b/drivers/net/wireless/realtek/rtlwifi/base.h
index 26735319b38f..3ad8e8107209 100644
--- a/drivers/net/wireless/realtek/rtlwifi/base.h
+++ b/drivers/net/wireless/realtek/rtlwifi/base.h
@@ -176,5 +176,6 @@ u8 rtl_tid_to_ac(u8 tid);
void rtl_easy_concurrent_retrytimer_callback(struct timer_list *t);
extern struct rtl_global_var rtl_global_var;
void rtl_phy_scan_operation_backup(struct ieee80211_hw *hw, u8 operation);
-
+bool rtl_check_beacon_key(struct ieee80211_hw *hw, void *data,
+ unsigned int len);
#endif
diff --git a/drivers/net/wireless/realtek/rtlwifi/core.c b/drivers/net/wireless/realtek/rtlwifi/core.c
index 3cb88825473e..195f7c41b4aa 100644
--- a/drivers/net/wireless/realtek/rtlwifi/core.c
+++ b/drivers/net/wireless/realtek/rtlwifi/core.c
@@ -909,6 +909,7 @@ static int rtl_op_sta_add(struct ieee80211_hw *hw,
struct ieee80211_sta *sta)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_phy *rtlphy = &rtlpriv->phy;
struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
struct rtl_sta_info *sta_entry;
@@ -941,6 +942,16 @@ static int rtl_op_sta_add(struct ieee80211_hw *hw,
if (mac->p2p)
sta->supp_rates[0] &= 0xfffffff0;

+ if (sta->ht_cap.ht_supported) {
+ if (sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40)
+ rtlphy->max_ht_chan_bw = HT_CHANNEL_WIDTH_20_40;
+ else
+ rtlphy->max_ht_chan_bw = HT_CHANNEL_WIDTH_20;
+ }
+
+ if (sta->vht_cap.vht_supported)
+ rtlphy->max_vht_chan_bw = HT_CHANNEL_WIDTH_80;
+
memcpy(sta_entry->mac_addr, sta->addr, ETH_ALEN);
RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG,
"Add sta addr is %pM\n", sta->addr);
@@ -1039,6 +1050,7 @@ static void rtl_op_bss_info_changed(struct ieee80211_hw *hw,
u32 changed)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_phy *rtlphy = &rtlpriv->phy;
struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
@@ -1241,6 +1253,16 @@ static void rtl_op_bss_info_changed(struct ieee80211_hw *hw,
mac->current_ampdu_factor)
mac->current_ampdu_factor =
sta->ht_cap.ampdu_factor;
+
+ if (sta->ht_cap.ht_supported) {
+ if (sta->ht_cap.cap &
+ IEEE80211_HT_CAP_SUP_WIDTH_20_40)
+ rtlphy->max_ht_chan_bw =
+ HT_CHANNEL_WIDTH_20_40;
+ else
+ rtlphy->max_ht_chan_bw =
+ HT_CHANNEL_WIDTH_20;
+ }
}
rcu_read_unlock();

@@ -1252,6 +1274,32 @@ static void rtl_op_bss_info_changed(struct ieee80211_hw *hw,
&mac->current_ampdu_density);
}

+ if (changed & BSS_CHANGED_BANDWIDTH) {
+ struct ieee80211_sta *sta = NULL;
+
+ RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE,
+ "BSS_CHANGED_BANDWIDTH\n");
+
+ rcu_read_lock();
+ sta = ieee80211_find_sta(vif, (u8 *)bss_conf->bssid);
+
+ if (sta) {
+ if (sta->ht_cap.ht_supported) {
+ if (sta->ht_cap.cap &
+ IEEE80211_HT_CAP_SUP_WIDTH_20_40)
+ rtlphy->max_ht_chan_bw =
+ HT_CHANNEL_WIDTH_20_40;
+ else
+ rtlphy->max_ht_chan_bw =
+ HT_CHANNEL_WIDTH_20;
+ }
+
+ if (sta->vht_cap.vht_supported)
+ rtlphy->max_vht_chan_bw = HT_CHANNEL_WIDTH_80;
+ }
+ rcu_read_unlock();
+ }
+
if (changed & BSS_CHANGED_BSSID) {
u32 basic_rates;
struct ieee80211_sta *sta = NULL;
diff --git a/drivers/net/wireless/realtek/rtlwifi/pci.c b/drivers/net/wireless/realtek/rtlwifi/pci.c
index 8ae36a263426..0bafcefacad0 100644
--- a/drivers/net/wireless/realtek/rtlwifi/pci.c
+++ b/drivers/net/wireless/realtek/rtlwifi/pci.c
@@ -877,6 +877,8 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw)
ieee80211_is_probe_resp(fc))) {
dev_kfree_skb_any(skb);
} else {
+ rtl_check_beacon_key(hw, (void *)skb->data,
+ skb->len);
_rtl_pci_rx_to_mac80211(hw, skb, rx_status);
}
} else {
diff --git a/drivers/net/wireless/realtek/rtlwifi/wifi.h b/drivers/net/wireless/realtek/rtlwifi/wifi.h
index e2b14793b705..d3ea6260f01c 100644
--- a/drivers/net/wireless/realtek/rtlwifi/wifi.h
+++ b/drivers/net/wireless/realtek/rtlwifi/wifi.h
@@ -962,6 +962,15 @@ struct rtl_probe_rsp {
struct rtl_info_element info_element[0];
} __packed;

+struct rtl_beacon_keys {
+ /*u8 ssid[32];*/
+ /*u32 ssid_len;*/
+ u8 bcn_channel;
+ __le16 ht_cap_info;
+ u8 ht_info_infos_0_sco; /* bit0 & bit1 in infos[0] is 2nd ch offset */
+ bool valid;
+};
+
/*LED related.*/
/*ledpin Identify how to implement this SW led.*/
struct rtl_led {
@@ -1209,6 +1218,8 @@ struct rtl_phy {
u8 rf_mode;
u8 rf_type;
u8 current_chan_bw;
+ u8 max_ht_chan_bw;
+ u8 max_vht_chan_bw;
u8 set_bwmode_inprogress;
u8 sw_chnl_inprogress;
u8 sw_chnl_stage;
@@ -1380,6 +1391,8 @@ struct rtl_mac {
/*Probe Beacon management */
struct rtl_tid_data tids[MAX_TID_COUNT];
enum rtl_link_state link_state;
+ struct rtl_beacon_keys cur_beacon_keys;
+ u8 new_beacon_cnt;

int n_channels;
int n_bitrates;
--
2.15.1

2017-12-09 17:37:17

by Larry Finger

[permalink] [raw]
Subject: [PATCH 1/3] rtlwifi: rtl_pci: 8822BE puts broadcast and multicast packet to HIQ

From: Ping-Ke Shih <[email protected]>

Making this change to HIQ, which has high priority, improves the response
time for transmission after TBTT or beacon.

Signed-off-by: Ping-Ke Shih <[email protected]>
Signed-off-by: Larry Finger <[email protected]>
Cc: Yan-Hsuan Chuang <[email protected]>
Cc: Birming Chiu <[email protected]>
Cc: Shaofu <[email protected]>
Cc: Steven Ting <[email protected]>
---
drivers/net/wireless/realtek/rtlwifi/pci.c | 8 ++++++++
1 file changed, 8 insertions(+)

diff --git a/drivers/net/wireless/realtek/rtlwifi/pci.c b/drivers/net/wireless/realtek/rtlwifi/pci.c
index 3e9eb11a38f9..8ae36a263426 100644
--- a/drivers/net/wireless/realtek/rtlwifi/pci.c
+++ b/drivers/net/wireless/realtek/rtlwifi/pci.c
@@ -59,6 +59,7 @@ static u8 _rtl_mac_to_hwqueue(struct ieee80211_hw *hw, struct sk_buff *skb)
struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
__le16 fc = rtl_get_fc(skb);
u8 queue_index = skb_get_queue_mapping(skb);
+ struct ieee80211_hdr *hdr;

if (unlikely(ieee80211_is_beacon(fc)))
return BEACON_QUEUE;
@@ -67,6 +68,13 @@ static u8 _rtl_mac_to_hwqueue(struct ieee80211_hw *hw, struct sk_buff *skb)
if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192SE)
if (ieee80211_is_nullfunc(fc))
return HIGH_QUEUE;
+ if (rtlhal->hw_type == HARDWARE_TYPE_RTL8822BE) {
+ hdr = rtl_get_hdr(skb);
+
+ if (is_multicast_ether_addr(hdr->addr1) ||
+ is_broadcast_ether_addr(hdr->addr1))
+ return HIGH_QUEUE;
+ }

return ac_to_hwq[queue_index];
}
--
2.15.1