From: Amitkumar Karwar <[email protected]>
This patch series brings in improvements in scan, Tx path, roaming and
regulatory handling.
Prameela Rani Garnepudi (9):
rsi: add support for hardware scan offload
rsi: move xtend_desc structure from rsi_main.h to rsi_mgmt.h
rsi: move descriptor preparation to core
rsi: enable 80MHz clock by default
rsi: roaming enhancements
rsi: add module parameter rsi_reg
rsi: regulatory modifications for 'dlcar' mode
rsi: device disconnect changes
rsi: tx improvements
Siva Rebbagondla (1):
rsi: drop RX broadcast/multicast packets with invalid PN
drivers/net/wireless/rsi/rsi_91x_core.c | 31 +-
drivers/net/wireless/rsi/rsi_91x_hal.c | 82 +++--
drivers/net/wireless/rsi/rsi_91x_mac80211.c | 353 +++++++++++++++++++---
drivers/net/wireless/rsi/rsi_91x_main.c | 20 ++
drivers/net/wireless/rsi/rsi_91x_mgmt.c | 447 +++++++++++++++++++++++++++-
drivers/net/wireless/rsi/rsi_91x_usb.c | 10 +
drivers/net/wireless/rsi/rsi_boot_params.h | 3 +-
drivers/net/wireless/rsi/rsi_common.h | 3 +
drivers/net/wireless/rsi/rsi_hal.h | 3 +
drivers/net/wireless/rsi/rsi_main.h | 50 +++-
drivers/net/wireless/rsi/rsi_mgmt.h | 67 ++++-
11 files changed, 977 insertions(+), 92 deletions(-)
--
2.7.4
From: Siva Rebbagondla <[email protected]>
This patch adds a check to drop received broadcast/multicast frames if
PN is invalid (i.e. not greater than last PN). bc_mc_pn
variable added for each interface
Signed-off-by: Siva Rebbagondla <[email protected]>
Signed-off-by: Amitkumar Karwar <[email protected]>
---
drivers/net/wireless/rsi/rsi_91x_mac80211.c | 166 ++++++++++++++++++++++++++--
drivers/net/wireless/rsi/rsi_main.h | 3 +
2 files changed, 160 insertions(+), 9 deletions(-)
diff --git a/drivers/net/wireless/rsi/rsi_91x_mac80211.c b/drivers/net/wireless/rsi/rsi_91x_mac80211.c
index 70b2d61..f73c0f0 100644
--- a/drivers/net/wireless/rsi/rsi_91x_mac80211.c
+++ b/drivers/net/wireless/rsi/rsi_91x_mac80211.c
@@ -522,6 +522,9 @@ static int rsi_mac80211_add_interface(struct ieee80211_hw *hw,
mutex_unlock(&common->mutex);
return -EINVAL;
}
+ memset(vif_info->rx_bcmc_pn, 0, IEEE80211_CCMP_PN_LEN);
+ vif_info->rx_pn_valid = false;
+ vif_info->key = NULL;
if ((vif->type == NL80211_IFTYPE_AP) ||
(vif->type == NL80211_IFTYPE_P2P_GO)) {
@@ -1035,6 +1038,8 @@ static int rsi_mac80211_set_key(struct ieee80211_hw *hw,
struct rsi_hw *adapter = hw->priv;
struct rsi_common *common = adapter->priv;
struct security_info *secinfo = &common->secinfo;
+ struct vif_priv *vif_info = (struct vif_priv *)vif->drv_priv;
+ struct ieee80211_key_seq seq;
int status;
mutex_lock(&common->mutex);
@@ -1047,10 +1052,41 @@ static int rsi_mac80211_set_key(struct ieee80211_hw *hw,
return status;
}
- if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE)
+ if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) {
secinfo->ptk_cipher = key->cipher;
- else
+ } else {
secinfo->gtk_cipher = key->cipher;
+ ieee80211_get_key_rx_seq(key, 0, &seq);
+ switch (key->cipher) {
+ case WLAN_CIPHER_SUITE_CCMP:
+ case WLAN_CIPHER_SUITE_CCMP_256:
+ memcpy(vif_info->rx_bcmc_pn, seq.ccmp.pn,
+ IEEE80211_CCMP_PN_LEN);
+ vif_info->rx_pn_valid = true;
+ vif_info->key = key;
+ break;
+ case WLAN_CIPHER_SUITE_TKIP:
+ vif_info->rx_bcmc_pn[0] = seq.tkip.iv16 & 0xff;
+ vif_info->rx_bcmc_pn[1] =
+ (seq.tkip.iv16 >> 8) & 0xff;
+ vif_info->rx_bcmc_pn[2] = seq.tkip.iv32 & 0xff;
+ vif_info->rx_bcmc_pn[3] =
+ (seq.tkip.iv32 >> 8) & 0xff;
+ vif_info->rx_bcmc_pn[4] =
+ (seq.tkip.iv32 >> 16) & 0xff;
+ vif_info->rx_bcmc_pn[5] =
+ (seq.tkip.iv32 >> 24) & 0xff;
+ vif_info->rx_pn_valid = true;
+ vif_info->key = key;
+ break;
+ case WLAN_CIPHER_SUITE_AES_CMAC:
+ memcpy(vif_info->rx_bcmc_pn,
+ seq.aes_cmac.pn, IEEE80211_CMAC_PN_LEN);
+ vif_info->rx_pn_valid = true;
+ vif_info->key = key;
+ break;
+ }
+ }
key->hw_key_idx = key->keyidx;
key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
@@ -1063,6 +1099,9 @@ static int rsi_mac80211_set_key(struct ieee80211_hw *hw,
secinfo->security_enable = false;
rsi_dbg(ERR_ZONE, "%s: RSI del key\n", __func__);
memset(key, 0, sizeof(struct ieee80211_key_conf));
+ memset(vif_info->rx_bcmc_pn, 0, IEEE80211_CCMP_PN_LEN);
+ vif_info->rx_pn_valid = false;
+ vif_info->key = NULL;
status = rsi_hal_key_config(hw, vif, key, sta);
break;
@@ -1277,6 +1316,103 @@ static void rsi_perform_cqm(struct rsi_common *common,
return;
}
+struct dot11_ccmp_hdr {
+ u8 pn0;
+ u8 pn1;
+ u8 reserved;
+ u8 keyid_info;
+ u8 pn2;
+ u8 pn3;
+ u8 pn4;
+ u8 pn5;
+};
+
+struct dot11_tkip_hdr {
+ u8 tsc1;
+ u8 wep_seed;
+ u8 tsc0;
+ u8 keyid_info;
+ u8 tsc2;
+ u8 tsc3;
+ u8 tsc4;
+ u8 tsc5;
+};
+
+static int rsi_validate_pn(struct rsi_hw *adapter, struct ieee80211_hdr *hdr)
+{
+ struct ieee80211_vif *vif;
+ struct ieee80211_bss_conf *bss;
+ struct vif_priv *vif_info = NULL;
+ u8 cur_pn[IEEE80211_CCMP_PN_LEN];
+ u8 *last_pn;
+ int i, hdrlen;
+
+ if (!is_broadcast_ether_addr(hdr->addr1) &&
+ !is_multicast_ether_addr(hdr->addr1))
+ return 1;
+
+ hdrlen = ieee80211_hdrlen(hdr->frame_control);
+ for (i = 0; i < adapter->sc_nvifs; i++) {
+ vif = adapter->vifs[i];
+
+ if (!vif)
+ continue;
+ if (vif->type != NL80211_IFTYPE_STATION &&
+ vif->type != NL80211_IFTYPE_P2P_CLIENT)
+ continue;
+ bss = &vif->bss_conf;
+ if (!bss->assoc)
+ continue;
+ if (!ether_addr_equal(bss->bssid, hdr->addr2))
+ continue;
+ vif_info = (struct vif_priv *)vif->drv_priv;
+ if (!vif_info->key) {
+ vif_info = NULL;
+ continue;
+ }
+ if (!vif_info->rx_pn_valid) {
+ vif_info = NULL;
+ continue;
+ }
+ }
+ if (!vif_info)
+ return 1;
+ last_pn = vif_info->rx_bcmc_pn;
+ if (vif_info->key->cipher == WLAN_CIPHER_SUITE_CCMP) {
+ struct dot11_ccmp_hdr *ccmp =
+ (struct dot11_ccmp_hdr *)&((u8 *)hdr)[hdrlen];
+
+ cur_pn[0] = ccmp->pn0;
+ cur_pn[1] = ccmp->pn1;
+ cur_pn[2] = ccmp->pn2;
+ cur_pn[3] = ccmp->pn3;
+ cur_pn[4] = ccmp->pn4;
+ cur_pn[5] = ccmp->pn5;
+ } else {
+ struct dot11_tkip_hdr *tkip =
+ (struct dot11_tkip_hdr *)&((u8 *)hdr)[hdrlen];
+
+ cur_pn[0] = tkip->tsc0;
+ cur_pn[1] = tkip->tsc1;
+ cur_pn[2] = tkip->tsc2;
+ cur_pn[3] = tkip->tsc3;
+ cur_pn[4] = tkip->tsc4;
+ cur_pn[5] = tkip->tsc5;
+ }
+ for (i = (IEEE80211_CCMP_PN_LEN - 1); i >= 0; i--)
+ if (last_pn[i] ^ cur_pn[i])
+ break;
+ if (i < 0)
+ return -1;
+
+ if (last_pn[i] >= cur_pn[i])
+ return -1;
+
+ memcpy(vif_info->rx_bcmc_pn, cur_pn, IEEE80211_CCMP_PN_LEN);
+
+ return 0;
+}
+
/**
* rsi_fill_rx_status() - This function fills rx status in
* ieee80211_rx_status structure.
@@ -1287,10 +1423,10 @@ static void rsi_perform_cqm(struct rsi_common *common,
*
* Return: None.
*/
-static void rsi_fill_rx_status(struct ieee80211_hw *hw,
- struct sk_buff *skb,
- struct rsi_common *common,
- struct ieee80211_rx_status *rxs)
+static int rsi_fill_rx_status(struct ieee80211_hw *hw,
+ struct sk_buff *skb,
+ struct rsi_common *common,
+ struct ieee80211_rx_status *rxs)
{
struct rsi_hw *adapter = common->priv;
struct ieee80211_vif *vif;
@@ -1323,6 +1459,17 @@ static void rsi_fill_rx_status(struct ieee80211_hw *hw,
memmove(skb->data + 4, skb->data, hdrlen);
skb_pull(skb, 4);
} else {
+ if (skb->len < (hdrlen + IEEE80211_CCMP_HDR_LEN)) {
+ rsi_dbg(ERR_ZONE, "Invalid encrypted packet\n");
+ dev_kfree_skb(skb);
+ return -EINVAL;
+ }
+ if (rsi_validate_pn(adapter, hdr) < 0) {
+ rsi_dbg(INFO_ZONE,
+ "Invalid RX PN; Dropping\n");
+ dev_kfree_skb(skb);
+ return -EINVAL;
+ }
memmove(skb->data + 8, skb->data, hdrlen);
skb_pull(skb, 8);
rxs->flag |= RX_FLAG_MMIC_STRIPPED;
@@ -1341,14 +1488,14 @@ static void rsi_fill_rx_status(struct ieee80211_hw *hw,
}
}
if (!bss)
- return;
+ return -1;
/* CQM only for connected AP beacons, the RSSI is a weighted avg */
if (bss->assoc && !(memcmp(bss->bssid, hdr->addr2, ETH_ALEN))) {
if (ieee80211_is_beacon(hdr->frame_control))
rsi_perform_cqm(common, hdr->addr2, rxs->signal, vif);
}
- return;
+ return 0;
}
/**
@@ -1371,7 +1518,8 @@ void rsi_indicate_pkt_to_os(struct rsi_common *common,
}
/* filling in the ieee80211_rx_status flags */
- rsi_fill_rx_status(hw, skb, common, rx_status);
+ if (rsi_fill_rx_status(hw, skb, common, rx_status))
+ return;
ieee80211_rx_irqsafe(hw, skb);
}
diff --git a/drivers/net/wireless/rsi/rsi_main.h b/drivers/net/wireless/rsi/rsi_main.h
index 9e09dd5..566379c 100644
--- a/drivers/net/wireless/rsi/rsi_main.h
+++ b/drivers/net/wireless/rsi/rsi_main.h
@@ -191,6 +191,9 @@ struct vif_priv {
bool sgi;
u16 seq_start;
int vap_id;
+ struct ieee80211_key_conf *key;
+ u8 rx_bcmc_pn[IEEE80211_CCMP_PN_LEN];
+ bool rx_pn_valid;
};
struct rsi_event {
--
2.7.4
On Tue, Mar 13, 2018 at 8:59 PM, Kalle Valo <[email protected]> wrote:
> Amitkumar Karwar <[email protected]> writes:
>
>> From: Prameela Rani Garnepudi <[email protected]>
>>
>> Changes done to improve TX path:
>> 1. Max number of frames to aggregate is increased to 8
>> 2. Bootup parameters updated.
>> 3. registering 5g band is done only when device supports
>> 4. Vif is properly taken to enable power save.
>> 5. When coex mode exist, power save on by default is set
>
> If you have a list of changes in the commit log to me that's a strong
> indication that you need to split the patches.
>
> Also I don't see any answers to question "Why?".
Sure. I will split into multiple incremental patches and submit with
proper commit log.
Regards,
Amitkumar
Amitkumar Karwar <[email protected]> writes:
> From: Prameela Rani Garnepudi <[email protected]>
>
> For few regulatory customizations, we are taking rsi_reg
> as module parameter.
Why?
> +static u16 rsi_reg = RSI_REG_DEF;
> +module_param(rsi_reg, ushort, 0444);
> +MODULE_PARM_DESC(rsi_reg, "0 - RSI_REG_DEF, 1 - RSI_REG_DLCAR");
The documentation tells nothing.
--
Kalle Valo
From: Prameela Rani Garnepudi <[email protected]>
To support roaming below changes are done:
* Station notify frame is send to firmware after sending assoc
request. This will avoid dropping of first EAPOL frame due to
delay in creation of station control block in firmware.
* Data queues are unblocked after sending station notify in open
mode, after configuring key in WEP mode, and after receiving
EAPOL4 confirm in WPA mode.
* Initial EAPOL frames priority is chaged to MGMT, rekey EAPOL
frames priority changed to VO.
* Data frames with wrong BSSID are dropped.
Signed-off-by: Prameela Rani Garnepudi <[email protected]>
---
drivers/net/wireless/rsi/rsi_91x_core.c | 16 +++++++++++++++
drivers/net/wireless/rsi/rsi_91x_hal.c | 24 +++++++++++++++++++---
drivers/net/wireless/rsi/rsi_91x_mac80211.c | 29 ++++++++++++++++----------
drivers/net/wireless/rsi/rsi_91x_mgmt.c | 32 +++++++++++++++++------------
drivers/net/wireless/rsi/rsi_main.h | 1 +
drivers/net/wireless/rsi/rsi_mgmt.h | 11 +++++++++-
6 files changed, 85 insertions(+), 28 deletions(-)
diff --git a/drivers/net/wireless/rsi/rsi_91x_core.c b/drivers/net/wireless/rsi/rsi_91x_core.c
index f5d1756..3ca468b9 100644
--- a/drivers/net/wireless/rsi/rsi_91x_core.c
+++ b/drivers/net/wireless/rsi/rsi_91x_core.c
@@ -411,6 +411,18 @@ void rsi_core_xmit(struct rsi_common *common, struct sk_buff *skb)
if ((ieee80211_is_mgmt(wh->frame_control)) ||
(ieee80211_is_ctl(wh->frame_control)) ||
(ieee80211_is_qos_nullfunc(wh->frame_control))) {
+ if (ieee80211_is_assoc_req(wh->frame_control) ||
+ ieee80211_is_reassoc_req(wh->frame_control)) {
+ struct ieee80211_bss_conf *bss = &vif->bss_conf;
+
+ common->eapol4_confirm = false;
+ rsi_hal_send_sta_notify_frame(common,
+ RSI_IFTYPE_STATION,
+ STA_CONNECTED, bss->bssid,
+ bss->qos, bss->aid, 0,
+ vif);
+ }
+
q_num = MGMT_SOFT_Q;
skb->priority = q_num;
@@ -450,6 +462,10 @@ void rsi_core_xmit(struct rsi_common *common, struct sk_buff *skb)
tid, 0);
}
}
+ if (skb->protocol == cpu_to_be16(ETH_P_PAE)) {
+ q_num = MGMT_SOFT_Q;
+ skb->priority = q_num;
+ }
if (rsi_prepare_data_desc(common, skb)) {
rsi_dbg(ERR_ZONE, "Failed to prepare data desc\n");
goto xmit_fail;
diff --git a/drivers/net/wireless/rsi/rsi_91x_hal.c b/drivers/net/wireless/rsi/rsi_91x_hal.c
index 7e04daf..ac40507 100644
--- a/drivers/net/wireless/rsi/rsi_91x_hal.c
+++ b/drivers/net/wireless/rsi/rsi_91x_hal.c
@@ -235,6 +235,18 @@ int rsi_prepare_data_desc(struct rsi_common *common, struct sk_buff *skb)
data_desc->misc_flags |= RSI_FETCH_RETRY_CNT_FRM_HST;
#define EAPOL_RETRY_CNT 15
xtend_desc->retry_cnt = EAPOL_RETRY_CNT;
+
+ if (common->eapol4_confirm)
+ skb->priority = VO_Q;
+ else
+ rsi_set_len_qno(&data_desc->len_qno,
+ (skb->len - FRAME_DESC_SZ),
+ RSI_WIFI_MGMT_Q);
+ if ((skb->len - header_size) == EAPOL4_PACKET_LEN) {
+ data_desc->misc_flags |=
+ RSI_DESC_REQUIRE_CFM_TO_HOST;
+ xtend_desc->confirm_frame_type = EAPOL4_CONFIRM;
+ }
}
data_desc->mac_flags = cpu_to_le16(seq_num & 0xfff);
@@ -274,8 +286,11 @@ int rsi_send_data_pkt(struct rsi_common *common, struct sk_buff *skb)
struct rsi_hw *adapter = common->priv;
struct ieee80211_vif *vif;
struct ieee80211_tx_info *info;
+ struct skb_info *tx_params;
struct ieee80211_bss_conf *bss;
+ struct ieee80211_hdr *wh;
int status = -EINVAL;
+ u8 header_size;
if (!skb)
return 0;
@@ -287,10 +302,13 @@ int rsi_send_data_pkt(struct rsi_common *common, struct sk_buff *skb)
goto err;
vif = info->control.vif;
bss = &vif->bss_conf;
+ tx_params = (struct skb_info *)info->driver_data;
+ header_size = tx_params->internal_hdr_size;
+ wh = (struct ieee80211_hdr *)&skb->data[header_size];
- if (((vif->type == NL80211_IFTYPE_STATION) ||
- (vif->type == NL80211_IFTYPE_P2P_CLIENT)) &&
- (!bss->assoc))
+ if ((vif->type == NL80211_IFTYPE_STATION ||
+ vif->type == NL80211_IFTYPE_P2P_CLIENT) &&
+ !(bss->assoc && ether_addr_equal(wh->addr1, bss->bssid)))
goto err;
status = rsi_send_pkt_to_bus(common, skb);
diff --git a/drivers/net/wireless/rsi/rsi_91x_mac80211.c b/drivers/net/wireless/rsi/rsi_91x_mac80211.c
index 4957690..ef7cabf 100644
--- a/drivers/net/wireless/rsi/rsi_91x_mac80211.c
+++ b/drivers/net/wireless/rsi/rsi_91x_mac80211.c
@@ -816,7 +816,8 @@ static void rsi_mac80211_bss_info_changed(struct ieee80211_hw *hw,
bss_conf->bssid,
bss_conf->qos,
bss_conf->aid,
- NULL, 0, vif);
+ NULL, 0,
+ bss_conf->assoc_capability, vif);
adapter->ps_info.dtim_interval_duration = bss->dtim_period;
adapter->ps_info.listen_interval = conf->listen_interval;
@@ -985,14 +986,20 @@ static int rsi_hal_key_config(struct ieee80211_hw *hw,
}
}
- return rsi_hal_load_key(adapter->priv,
- key->key,
- key->keylen,
- key_type,
- key->keyidx,
- key->cipher,
- sta_id,
- vif);
+ status = rsi_hal_load_key(adapter->priv, key->key, key->keylen,
+ key_type, key->keyidx, key->cipher,
+ sta_id, vif);
+ if (status)
+ return status;
+
+ if (vif->type == NL80211_IFTYPE_STATION && key->key &&
+ (key->cipher == WLAN_CIPHER_SUITE_WEP104 ||
+ key->cipher == WLAN_CIPHER_SUITE_WEP40)) {
+ if (!rsi_send_block_unblock_frame(adapter->priv, false))
+ adapter->priv->hw_data_qs_blocked = false;
+ }
+
+ return 0;
}
/**
@@ -1470,7 +1477,7 @@ static int rsi_mac80211_sta_add(struct ieee80211_hw *hw,
rsi_dbg(INFO_ZONE, "Indicate bss status to device\n");
rsi_inform_bss_status(common, RSI_OPMODE_AP, 1,
sta->addr, sta->wme, sta->aid,
- sta, sta_idx, vif);
+ sta, sta_idx, 0, vif);
if (common->key) {
struct ieee80211_key_conf *key = common->key;
@@ -1548,7 +1555,7 @@ static int rsi_mac80211_sta_remove(struct ieee80211_hw *hw,
rsi_inform_bss_status(common, RSI_OPMODE_AP, 0,
sta->addr, sta->wme,
sta->aid, sta, sta_idx,
- vif);
+ 0, vif);
rsta->sta = NULL;
rsta->sta_id = -1;
for (cnt = 0; cnt < IEEE80211_NUM_TIDS; cnt++)
diff --git a/drivers/net/wireless/rsi/rsi_91x_mgmt.c b/drivers/net/wireless/rsi/rsi_91x_mgmt.c
index 6f995d5a..0444025 100644
--- a/drivers/net/wireless/rsi/rsi_91x_mgmt.c
+++ b/drivers/net/wireless/rsi/rsi_91x_mgmt.c
@@ -467,14 +467,10 @@ static int rsi_mgmt_pkt_to_core(struct rsi_common *common,
*
* Return: status: 0 on success, corresponding negative error code on failure.
*/
-static int rsi_hal_send_sta_notify_frame(struct rsi_common *common,
- enum opmode opmode,
- u8 notify_event,
- const unsigned char *bssid,
- u8 qos_enable,
- u16 aid,
- u16 sta_id,
- struct ieee80211_vif *vif)
+int rsi_hal_send_sta_notify_frame(struct rsi_common *common, enum opmode opmode,
+ u8 notify_event, const unsigned char *bssid,
+ u8 qos_enable, u16 aid, u16 sta_id,
+ struct ieee80211_vif *vif)
{
struct sk_buff *skb = NULL;
struct rsi_peer_notify *peer_notify;
@@ -1342,6 +1338,7 @@ void rsi_inform_bss_status(struct rsi_common *common,
u16 aid,
struct ieee80211_sta *sta,
u16 sta_id,
+ u16 assoc_cap,
struct ieee80211_vif *vif)
{
if (status) {
@@ -1356,10 +1353,10 @@ void rsi_inform_bss_status(struct rsi_common *common,
vif);
if (common->min_rate == 0xffff)
rsi_send_auto_rate_request(common, sta, sta_id, vif);
- if (opmode == RSI_OPMODE_STA) {
- if (!rsi_send_block_unblock_frame(common, false))
- common->hw_data_qs_blocked = false;
- }
+ if (opmode == RSI_OPMODE_STA &&
+ !(assoc_cap & DOT11_ASSOC_CAP_SECURITY) &&
+ !rsi_send_block_unblock_frame(common, false))
+ common->hw_data_qs_blocked = false;
} else {
if (opmode == RSI_OPMODE_STA)
common->hw_data_qs_blocked = true;
@@ -2120,11 +2117,20 @@ int rsi_mgmt_pkt_recv(struct rsi_common *common, u8 *msg)
__func__);
return rsi_handle_card_ready(common, msg);
case TX_STATUS_IND:
- if (msg[15] == PROBEREQ_CONFIRM) {
+ switch (msg[RSI_TX_STATUS_TYPE]) {
+ case PROBEREQ_CONFIRM:
common->mgmt_q_block = false;
rsi_dbg(INFO_ZONE, "%s: Mgmt queue unblocked\n",
__func__);
rsi_set_event(&common->probe_cfm_event);
+ break;
+ case EAPOL4_CONFIRM:
+ if (msg[RSI_TX_STATUS]) {
+ common->eapol4_confirm = true;
+ if (!rsi_send_block_unblock_frame(common,
+ false))
+ common->hw_data_qs_blocked = false;
+ }
}
break;
case BEACON_EVENT_IND:
diff --git a/drivers/net/wireless/rsi/rsi_main.h b/drivers/net/wireless/rsi/rsi_main.h
index abc4f29..e2bbbbd 100644
--- a/drivers/net/wireless/rsi/rsi_main.h
+++ b/drivers/net/wireless/rsi/rsi_main.h
@@ -324,6 +324,7 @@ struct rsi_common {
bool fgscan_in_prog;
bool bgscan_en;
bool cancel_hwscan;
+ bool eapol4_confirm;
};
struct eepromrw_info {
diff --git a/drivers/net/wireless/rsi/rsi_mgmt.h b/drivers/net/wireless/rsi/rsi_mgmt.h
index 2513fb8..f21fdd4 100644
--- a/drivers/net/wireless/rsi/rsi_mgmt.h
+++ b/drivers/net/wireless/rsi/rsi_mgmt.h
@@ -33,6 +33,7 @@
#define WMM_SHORT_SLOT_TIME 9
#define SIFS_DURATION 16
+#define EAPOL4_PACKET_LEN 0x85
#define KEY_TYPE_CLEAR 0
#define RSI_PAIRWISE_KEY 1
#define RSI_GROUP_KEY 2
@@ -62,9 +63,12 @@
#define RX_DOT11_MGMT 0x02
#define TX_STATUS_IND 0x04
#define BEACON_EVENT_IND 0x08
+#define EAPOL4_CONFIRM 1
#define PROBEREQ_CONFIRM 2
#define CARD_READY_IND 0x00
#define SLEEP_NOTIFY_IND 0x06
+#define RSI_TX_STATUS_TYPE 15
+#define RSI_TX_STATUS 12
#define RSI_DELETE_PEER 0x0
#define RSI_ADD_PEER 0x1
@@ -226,6 +230,7 @@
#define RSI_CHAN_DWELL_TIME 300
#define RSI_CHAN_SET_TIME 50
#define RSI_PROBE_CFM_TIME 50
+#define DOT11_ASSOC_CAP_SECURITY BIT(4)
enum opmode {
RSI_OPMODE_UNSUPPORTED = -1,
@@ -694,10 +699,14 @@ int rsi_set_channel(struct rsi_common *common,
struct ieee80211_channel *channel);
int rsi_send_vap_dynamic_update(struct rsi_common *common);
int rsi_send_block_unblock_frame(struct rsi_common *common, bool event);
+int rsi_hal_send_sta_notify_frame(struct rsi_common *common, enum opmode opmode,
+ u8 notify_event, const unsigned char *bssid,
+ u8 qos_enable, u16 aid, u16 sta_id,
+ struct ieee80211_vif *vif);
void rsi_inform_bss_status(struct rsi_common *common, enum opmode opmode,
u8 status, const u8 *addr, u8 qos_enable, u16 aid,
struct ieee80211_sta *sta, u16 sta_id,
- struct ieee80211_vif *vif);
+ u16 assoc_cap, struct ieee80211_vif *vif);
void rsi_indicate_pkt_to_os(struct rsi_common *common, struct sk_buff *skb);
int rsi_mac80211_attach(struct rsi_common *common);
void rsi_indicate_tx_status(struct rsi_hw *common, struct sk_buff *skb,
--
2.7.4
Johannes Berg <[email protected]> writes:
> On Fri, 2018-03-23 at 20:20 +0530, Amitkumar Karwar wrote:
>
>> > But maybe that's not really true at all? At least in one case it seems
>> > you just kick off something called "bgscan".
>>
>> Yes. We have different scan implementations for device is connected
>> and non-connected cases. In connected case, firmware will take care of
>> timings when driver configures bgscan parameters due to power save and
>> coex restrictions. In non-connected state, driver is taking care of
>> it.
>> I found hardware scan in mac80211 more suitable for our device.
>
> Yeah it's a bit odd though that you're still implementing software scan
> :-)
>
> Perhaps we could make a special return code from the hwscan callback
> that would tell mac80211 to fall back to software scanning, so you'd
> only implement the connected case, and leave the rest up to mac80211?
Hehe, this is exactly what I proposed during my review :)
--
Kalle Valo
Kalle Valo <[email protected]> writes:
> Amitkumar Karwar <[email protected]> writes:
>
>> From: Prameela Rani Garnepudi <[email protected]>
>>
>> With the current approach of scanning, roaming delays
>> are observed. Firmware has support for back ground scanning.
>> To get this advantage, mac80211 hardware scan is implemented.
>> In this method, foreground scan is performed in driver and
>> back ground scan is configured to firmware.
>
> To me doesn't like a good idea to duplicate scan functionality in the
> driver.
Also a pro tip: Don't place controversial patches as the first patch in
a big patchset, instead put them last so that I can apply rest of
patches anyway. Even better to submit them separately as RFC.
--
Kalle Valo
From: Prameela Rani Garnepudi <[email protected]>
All descriptor structures are in rsi_mgmt.h except this
extended descriptor structure. Hence moving it to rsi_mgmt.h
and also renaming to rsi_xtend_desc.
Signed-off-by: Prameela Rani Garnepudi <[email protected]>
---
drivers/net/wireless/rsi/rsi_91x_hal.c | 12 ++++++------
drivers/net/wireless/rsi/rsi_main.h | 6 ------
drivers/net/wireless/rsi/rsi_mgmt.h | 6 ++++++
3 files changed, 12 insertions(+), 12 deletions(-)
diff --git a/drivers/net/wireless/rsi/rsi_91x_hal.c b/drivers/net/wireless/rsi/rsi_91x_hal.c
index 20c2f6b..718f793 100644
--- a/drivers/net/wireless/rsi/rsi_91x_hal.c
+++ b/drivers/net/wireless/rsi/rsi_91x_hal.c
@@ -55,7 +55,7 @@ static int rsi_prepare_mgmt_desc(struct rsi_common *common, struct sk_buff *skb)
struct rsi_mgmt_desc *mgmt_desc;
struct skb_info *tx_params;
struct ieee80211_bss_conf *bss = NULL;
- struct xtended_desc *xtend_desc = NULL;
+ struct rsi_xtended_desc *xtend_desc = NULL;
u8 header_size;
u32 dword_align_bytes = 0;
@@ -69,7 +69,7 @@ static int rsi_prepare_mgmt_desc(struct rsi_common *common, struct sk_buff *skb)
vif = tx_params->vif;
/* Update header size */
- header_size = FRAME_DESC_SZ + sizeof(struct xtended_desc);
+ header_size = FRAME_DESC_SZ + sizeof(struct rsi_xtended_desc);
if (header_size > skb_headroom(skb)) {
rsi_dbg(ERR_ZONE,
"%s: Failed to add extended descriptor\n",
@@ -92,7 +92,7 @@ static int rsi_prepare_mgmt_desc(struct rsi_common *common, struct sk_buff *skb)
wh = (struct ieee80211_hdr *)&skb->data[header_size];
mgmt_desc = (struct rsi_mgmt_desc *)skb->data;
- xtend_desc = (struct xtended_desc *)&skb->data[FRAME_DESC_SZ];
+ xtend_desc = (struct rsi_xtended_desc *)&skb->data[FRAME_DESC_SZ];
rsi_set_len_qno(&mgmt_desc->len_qno, (skb->len - FRAME_DESC_SZ),
RSI_WIFI_MGMT_Q);
@@ -161,7 +161,7 @@ static int rsi_prepare_data_desc(struct rsi_common *common, struct sk_buff *skb)
struct skb_info *tx_params;
struct ieee80211_bss_conf *bss;
struct rsi_data_desc *data_desc;
- struct xtended_desc *xtend_desc;
+ struct rsi_xtended_desc *xtend_desc;
u8 ieee80211_size = MIN_802_11_HDR_LEN;
u8 header_size;
u8 vap_id = 0;
@@ -173,7 +173,7 @@ static int rsi_prepare_data_desc(struct rsi_common *common, struct sk_buff *skb)
bss = &vif->bss_conf;
tx_params = (struct skb_info *)info->driver_data;
- header_size = FRAME_DESC_SZ + sizeof(struct xtended_desc);
+ header_size = FRAME_DESC_SZ + sizeof(struct rsi_xtended_desc);
if (header_size > skb_headroom(skb)) {
rsi_dbg(ERR_ZONE, "%s: Unable to send pkt\n", __func__);
return -ENOSPC;
@@ -191,7 +191,7 @@ static int rsi_prepare_data_desc(struct rsi_common *common, struct sk_buff *skb)
data_desc = (struct rsi_data_desc *)skb->data;
memset(data_desc, 0, header_size);
- xtend_desc = (struct xtended_desc *)&skb->data[FRAME_DESC_SZ];
+ xtend_desc = (struct rsi_xtended_desc *)&skb->data[FRAME_DESC_SZ];
wh = (struct ieee80211_hdr *)&skb->data[header_size];
seq_num = IEEE80211_SEQ_TO_SN(le16_to_cpu(wh->seq_ctrl));
diff --git a/drivers/net/wireless/rsi/rsi_main.h b/drivers/net/wireless/rsi/rsi_main.h
index 3dd08f5..abc4f29 100644
--- a/drivers/net/wireless/rsi/rsi_main.h
+++ b/drivers/net/wireless/rsi/rsi_main.h
@@ -212,12 +212,6 @@ struct cqm_info {
u32 rssi_hyst;
};
-struct xtended_desc {
- u8 confirm_frame_type;
- u8 retry_cnt;
- u16 reserved;
-};
-
enum rsi_dfs_regions {
RSI_REGION_FCC = 0,
RSI_REGION_ETSI,
diff --git a/drivers/net/wireless/rsi/rsi_mgmt.h b/drivers/net/wireless/rsi/rsi_mgmt.h
index b7f63c9..2513fb8 100644
--- a/drivers/net/wireless/rsi/rsi_mgmt.h
+++ b/drivers/net/wireless/rsi/rsi_mgmt.h
@@ -307,6 +307,12 @@ struct rsi_mac_frame {
#define ENCAP_MGMT_PKT BIT(7)
#define DESC_IMMEDIATE_WAKEUP BIT(15)
+struct rsi_xtended_desc {
+ u8 confirm_frame_type;
+ u8 retry_cnt;
+ u16 reserved;
+};
+
struct rsi_cmd_desc_dword0 {
__le16 len_qno;
u8 frame_type;
--
2.7.4
Amitkumar Karwar <[email protected]> writes:
> From: Prameela Rani Garnepudi <[email protected]>
>
> Changes done to improve TX path:
> 1. Max number of frames to aggregate is increased to 8
> 2. Bootup parameters updated.
> 3. registering 5g band is done only when device supports
> 4. Vif is properly taken to enable power save.
> 5. When coex mode exist, power save on by default is set
If you have a list of changes in the commit log to me that's a strong
indication that you need to split the patches.
Also I don't see any answers to question "Why?".
--
Kalle Valo
From: Prameela Rani Garnepudi <[email protected]>
Changes in this patch are for applying custom regulatory
rules for 'dlcar' regulatory mode. Max channel power values
are updated for 12, 13, and 14. Dlcar only has 2.4GHz band.
Signed-off-by: Prameela Rani Garnepudi <[email protected]>
---
drivers/net/wireless/rsi/rsi_91x_mac80211.c | 30 +++++-
drivers/net/wireless/rsi/rsi_91x_main.c | 2 +
drivers/net/wireless/rsi/rsi_91x_mgmt.c | 140 ++++++++++++++++++++++++++++
drivers/net/wireless/rsi/rsi_main.h | 3 +-
drivers/net/wireless/rsi/rsi_mgmt.h | 4 +
5 files changed, 173 insertions(+), 6 deletions(-)
diff --git a/drivers/net/wireless/rsi/rsi_91x_mac80211.c b/drivers/net/wireless/rsi/rsi_91x_mac80211.c
index ef7cabf..a7e1f7d 100644
--- a/drivers/net/wireless/rsi/rsi_91x_mac80211.c
+++ b/drivers/net/wireless/rsi/rsi_91x_mac80211.c
@@ -1666,7 +1666,8 @@ static int rsi_mac80211_get_antenna(struct ieee80211_hw *hw,
return 0;
}
-static int rsi_map_region_code(enum nl80211_dfs_regions region_code)
+static enum rsi_dfs_regions rsi_map_region_code
+ (enum nl80211_dfs_regions region_code)
{
switch (region_code) {
case NL80211_DFS_FCC:
@@ -1681,6 +1682,22 @@ static int rsi_map_region_code(enum nl80211_dfs_regions region_code)
return RSI_REGION_WORLD;
}
+static char *dfsreg_str(enum rsi_dfs_regions reg)
+{
+ switch (reg) {
+ case RSI_REGION_FCC:
+ return "FCC";
+ case RSI_REGION_ETSI:
+ return "ETSI";
+ case RSI_REGION_TELEC:
+ return "TELEC";
+ case RSI_REGION_WORLD:
+ return "WORLD";
+ default:
+ return "INVALID";
+ }
+}
+
static void rsi_reg_notify(struct wiphy *wiphy,
struct regulatory_request *request)
{
@@ -1693,7 +1710,8 @@ static void rsi_reg_notify(struct wiphy *wiphy,
mutex_lock(&common->mutex);
- rsi_dbg(INFO_ZONE, "country = %s dfs_region = %d\n",
+ rsi_dbg(INFO_ZONE,
+ "Regulatory notifcation: country: %s region:%d\n",
request->alpha2, request->dfs_region);
if (common->num_supp_bands > 1) {
@@ -1708,11 +1726,13 @@ static void rsi_reg_notify(struct wiphy *wiphy,
ch->flags |= IEEE80211_CHAN_NO_IR;
}
}
- adapter->dfs_region = rsi_map_region_code(request->dfs_region);
- rsi_dbg(INFO_ZONE, "RSI region code = %d\n", adapter->dfs_region);
-
adapter->country[0] = request->alpha2[0];
adapter->country[1] = request->alpha2[1];
+ adapter->dfs_region = rsi_map_region_code(request->dfs_region);
+ if (adapter->reg_mode == RSI_REG_DLCAR)
+ rsi_apply_dlcar_reg_rules(adapter);
+
+ rsi_dbg(INFO_ZONE, "DFS region: %s", dfsreg_str(adapter->dfs_region));
mutex_unlock(&common->mutex);
}
diff --git a/drivers/net/wireless/rsi/rsi_91x_main.c b/drivers/net/wireless/rsi/rsi_91x_main.c
index e290779..7790314 100644
--- a/drivers/net/wireless/rsi/rsi_91x_main.c
+++ b/drivers/net/wireless/rsi/rsi_91x_main.c
@@ -352,6 +352,8 @@ struct rsi_hw *rsi_91x_init(u16 oper_mode)
common->init_done = true;
adapter->device_model = RSI_DEV_9113;
common->oper_mode = oper_mode;
+ adapter->reg_mode = rsi_reg;
+ rsi_dbg(INFO_ZONE, "Reg mode = %d\n", adapter->reg_mode);
/* Determine coex mode */
switch (common->oper_mode) {
diff --git a/drivers/net/wireless/rsi/rsi_91x_mgmt.c b/drivers/net/wireless/rsi/rsi_91x_mgmt.c
index 0444025..4ba5966 100644
--- a/drivers/net/wireless/rsi/rsi_91x_mgmt.c
+++ b/drivers/net/wireless/rsi/rsi_91x_mgmt.c
@@ -211,6 +211,28 @@ static struct bootup_params boot_params_40 = {
static u16 mcs[] = {13, 26, 39, 52, 78, 104, 117, 130};
+struct reg_map {
+ char country_code[2];
+ u8 region_code;
+};
+
+#define MAX_REG_COUNTRIES 30
+static struct reg_map rsi_dlcar_reg_map[MAX_REG_COUNTRIES] = {
+ {"AU", RSI_REGION_ETSI}, {"AT", RSI_REGION_ETSI},
+ {"BE", RSI_REGION_ETSI}, {"BR", RSI_REGION_WORLD},
+ {"CA", RSI_REGION_FCC}, {"CL", RSI_REGION_WORLD},
+ {"CN", RSI_REGION_WORLD}, {"CO", RSI_REGION_FCC},
+ {"CZ", RSI_REGION_ETSI}, {"DK", RSI_REGION_ETSI},
+ {"FI", RSI_REGION_ETSI}, {"FR", RSI_REGION_ETSI},
+ {"DE", RSI_REGION_ETSI}, {"HK", RSI_REGION_WORLD},
+ {"IN", RSI_REGION_WORLD}, {"ID", RSI_REGION_WORLD},
+ {"IE", RSI_REGION_ETSI}, {"IL", RSI_REGION_ETSI},
+ {"IT", RSI_REGION_ETSI}, {"JP", RSI_REGION_TELEC},
+ {"KR", RSI_REGION_WORLD}, {"LU", RSI_REGION_ETSI},
+ {"MY", RSI_REGION_WORLD}, {"MX", RSI_REGION_FCC},
+ {"MA", RSI_REGION_WORLD}, {"NL", RSI_REGION_ETSI},
+};
+
/**
* rsi_set_default_parameters() - This function sets default parameters.
* @common: Pointer to the driver private structure.
@@ -986,6 +1008,120 @@ int rsi_band_check(struct rsi_common *common,
return status;
}
+enum rsi_chan_type {
+ RSI_CHAN_11B = 0,
+ RSI_CHAN_11G,
+ RSI_CHAN_HT_20,
+ RSI_CHAN_HT_40
+};
+
+static enum rsi_chan_type rsi_get_chan_type(struct rsi_hw *adapter)
+{
+ struct ieee80211_bss_conf *bss;
+ u16 ch_type = RSI_CHAN_11B;
+ u8 i;
+
+ for (i = 0; i < adapter->sc_nvifs; i++) {
+ bss = &adapter->vifs[i]->bss_conf;
+
+ if (ch_type < RSI_CHAN_11G && !conf_is_ht(&adapter->hw->conf)) {
+ if (bss->basic_rates & 0xfff0)
+ ch_type = RSI_CHAN_11G;
+ } else {
+ if (ch_type < RSI_CHAN_HT_20 &&
+ conf_is_ht20(&adapter->hw->conf))
+ ch_type = RSI_CHAN_HT_20;
+ else if (conf_is_ht40(&adapter->hw->conf))
+ ch_type = RSI_CHAN_HT_40;
+ }
+ }
+ return ch_type;
+}
+
+void rsi_apply_dlcar_power_values(struct rsi_hw *adapter,
+ struct ieee80211_channel *ch)
+{
+ enum rsi_chan_type ch_type;
+
+ ch_type = rsi_get_chan_type(adapter);
+ switch (ch_type) {
+ case RSI_CHAN_11B:
+ if (ch->hw_value == 12)
+ ch->max_power = 15;
+ else if (ch->hw_value == 13)
+ ch->max_power = 7;
+ else
+ return;
+ break;
+ case RSI_CHAN_11G:
+ if (ch->hw_value == 12)
+ ch->max_power = 8;
+ else if (ch->hw_value == 13)
+ ch->max_power = 7;
+ else
+ return;
+ case RSI_CHAN_HT_20:
+ if (ch->hw_value == 12)
+ ch->max_power = 7;
+ else if (ch->hw_value == 13)
+ ch->max_power = 5;
+ else
+ return;
+ case RSI_CHAN_HT_40:
+ if (ch->hw_value == 6)
+ ch->max_power = 9;
+ else if (ch->hw_value == 9)
+ ch->max_power = 5;
+ else if (ch->hw_value == 10)
+ ch->max_power = 4;
+ else
+ return;
+ }
+ ch->max_antenna_gain = 0;
+}
+
+void rsi_apply_dlcar_reg_rules(struct rsi_hw *adapter)
+{
+ struct ieee80211_supported_band *sband =
+ adapter->hw->wiphy->bands[NL80211_BAND_2GHZ];
+ struct ieee80211_channel *ch;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(rsi_dlcar_reg_map); i++) {
+ if (!memcmp(rsi_dlcar_reg_map[i].country_code,
+ adapter->country, 2)) {
+ adapter->dfs_region = rsi_dlcar_reg_map[i].region_code;
+ break;
+ }
+ }
+ for (i = 0; i < sband->n_channels; i++) {
+ ch = &sband->channels[i];
+
+ if (ch->hw_value < 12)
+ continue;
+
+ switch (adapter->dfs_region) {
+ case RSI_REGION_FCC:
+ if (ch->hw_value == 12 || ch->hw_value == 13) {
+ ch->flags &= ~IEEE80211_CHAN_DISABLED;
+ ch->flags &= ~IEEE80211_CHAN_NO_IR;
+ rsi_apply_dlcar_power_values(adapter, ch);
+ }
+ break;
+ case RSI_REGION_WORLD:
+ case RSI_REGION_ETSI:
+ if (ch->hw_value == 12 || ch->hw_value == 13)
+ rsi_apply_dlcar_power_values(adapter, ch);
+ break;
+ case RSI_REGION_TELEC:
+ if (ch->hw_value == 12 || ch->hw_value == 13 ||
+ ch->hw_value == 14)
+ rsi_apply_dlcar_power_values(adapter, ch);
+ break;
+ }
+ }
+}
+
/**
* rsi_set_channel() - This function programs the channel.
* @common: Pointer to the driver private structure.
@@ -1024,6 +1160,10 @@ int rsi_set_channel(struct rsi_common *common,
chan_cfg->antenna_gain_offset_5g = channel->max_antenna_gain;
chan_cfg->region_rftype = (RSI_RF_TYPE & 0xf) << 4;
+ if (common->priv->reg_mode == RSI_REG_DLCAR) {
+ rsi_apply_dlcar_power_values(common->priv, channel);
+ chan_cfg->flags = RSI_CHAN_FLAGS_DLCAR;
+ }
if ((channel->flags & IEEE80211_CHAN_NO_IR) ||
(channel->flags & IEEE80211_CHAN_RADAR)) {
chan_cfg->antenna_gain_offset_2g |= RSI_CHAN_RADAR;
diff --git a/drivers/net/wireless/rsi/rsi_main.h b/drivers/net/wireless/rsi/rsi_main.h
index e2bbbbd..4521c43 100644
--- a/drivers/net/wireless/rsi/rsi_main.h
+++ b/drivers/net/wireless/rsi/rsi_main.h
@@ -367,8 +367,9 @@ struct rsi_hw {
u32 flash_capacity;
struct eepromrw_info eeprom;
u32 interrupt_status;
- u8 dfs_region;
+ enum rsi_dfs_regions dfs_region;
char country[2];
+ u16 reg_mode;
void *rsi_dev;
struct rsi_host_intf_ops *host_intf_ops;
int (*check_hw_queue_status)(struct rsi_hw *adapter, u8 q_num);
diff --git a/drivers/net/wireless/rsi/rsi_mgmt.h b/drivers/net/wireless/rsi/rsi_mgmt.h
index f21fdd4..65ae037 100644
--- a/drivers/net/wireless/rsi/rsi_mgmt.h
+++ b/drivers/net/wireless/rsi/rsi_mgmt.h
@@ -387,6 +387,7 @@ struct rsi_bb_rf_prog {
__le16 flags;
} __packed;
+#define RSI_CHAN_FLAGS_DLCAR BIT(2)
struct rsi_chan_config {
struct rsi_cmd_desc_dword0 desc_dword0;
struct rsi_cmd_desc_dword1 desc_dword1;
@@ -736,4 +737,7 @@ void rsi_fgscan_start(struct work_struct *data);
void init_bgscan_params(struct rsi_common *common);
int rsi_send_bgscan_params(struct rsi_common *common, int enable);
int rsi_send_bgscan_probe_req(struct rsi_common *common);
+void rsi_apply_dlcar_power_values(struct rsi_hw *adapter,
+ struct ieee80211_channel *ch);
+void rsi_apply_dlcar_reg_rules(struct rsi_hw *adapter);
#endif
--
2.7.4
Amitkumar Karwar <[email protected]> writes:
> On Tue, Mar 13, 2018 at 8:46 PM, Kalle Valo <[email protected]> wrote:
>> Amitkumar Karwar <[email protected]> writes:
>>
>>> From: Prameela Rani Garnepudi <[email protected]>
>>>
>>> With the current approach of scanning, roaming delays
>>> are observed. Firmware has support for back ground scanning.
>>> To get this advantage, mac80211 hardware scan is implemented.
>>> In this method, foreground scan is performed in driver and
>>> back ground scan is configured to firmware.
>>
>> To me doesn't like a good idea to duplicate scan functionality in the
>> driver.
>
> There is a limitation with our device. We need to configure background
> scan parameters to firmware when device is connected.
Yeah, I guessed that.
> In non-connected state, we can directly dump probe requests received
> from mac80211 as a part of software scan. Some synchronization issues
> are with existing software scan when device is connected. This patch
> implements hw_scan where these issues are no seen, as driver has more
> control on scan state machine
What I don't like here is that you are duplicating functionality already
existing in mac80211 and I hope there is a better way to solve the
problem. Just as a a crazy idea what if the driver returns -EOPNOTSUPP
when hardware scan is not possible and mac80211 falls back to software
scan? But of course this depends on what Johannes thinks.
--
Kalle Valo
On Tue, Mar 13, 2018 at 8:46 PM, Kalle Valo <[email protected]> wrote:
> Amitkumar Karwar <[email protected]> writes:
>
>> From: Prameela Rani Garnepudi <[email protected]>
>>
>> With the current approach of scanning, roaming delays
>> are observed. Firmware has support for back ground scanning.
>> To get this advantage, mac80211 hardware scan is implemented.
>> In this method, foreground scan is performed in driver and
>> back ground scan is configured to firmware.
>
> To me doesn't like a good idea to duplicate scan functionality in the
> driver.
There is a limitation with our device. We need to configure background
scan parameters to firmware when device is connected. In non-connected
state, we can directly dump probe requests received from mac80211 as a
part of software scan.
Some synchronization issues are with existing software scan when
device is connected. This patch implements hw_scan where these issues
are no seen, as driver has more control on scan state machine
>
>> --- a/drivers/net/wireless/rsi/rsi_91x_main.c
>> +++ b/drivers/net/wireless/rsi/rsi_91x_main.c
>> @@ -324,6 +324,14 @@ struct rsi_hw *rsi_91x_init(u16 oper_mode)
>> mutex_init(&common->rx_lock);
>> mutex_init(&common->tx_bus_mutex);
>>
>> + rsi_init_event(&common->chan_set_event);
>> + rsi_init_event(&common->probe_cfm_event);
>> + rsi_init_event(&common->chan_change_event);
>> + rsi_init_event(&common->cancel_hw_scan_event);
>
> And I'm starting to dislike this rsi_init_event() even more (see my
> other mail). In upstream driver's custom abstractions are very much
> frowned upon, especially that it makes review harder.
Agreed. I will get rid of this in a separate cleanup patch series.
Regards,
Amitkumar Karwar
From: Prameela Rani Garnepudi <[email protected]>
With the current approach of scanning, roaming delays
are observed. Firmware has support for back ground scanning.
To get this advantage, mac80211 hardware scan is implemented.
In this method, foreground scan is performed in driver and
back ground scan is configured to firmware.
Signed-off-by: Prameela Rani Garnepudi <[email protected]>
---
drivers/net/wireless/rsi/rsi_91x_hal.c | 3 +
drivers/net/wireless/rsi/rsi_91x_mac80211.c | 84 +++++++++
drivers/net/wireless/rsi/rsi_91x_main.c | 12 ++
drivers/net/wireless/rsi/rsi_91x_mgmt.c | 273 +++++++++++++++++++++++++++-
drivers/net/wireless/rsi/rsi_main.h | 36 ++++
drivers/net/wireless/rsi/rsi_mgmt.h | 44 +++++
6 files changed, 451 insertions(+), 1 deletion(-)
diff --git a/drivers/net/wireless/rsi/rsi_91x_hal.c b/drivers/net/wireless/rsi/rsi_91x_hal.c
index de608ae..20c2f6b 100644
--- a/drivers/net/wireless/rsi/rsi_91x_hal.c
+++ b/drivers/net/wireless/rsi/rsi_91x_hal.c
@@ -99,6 +99,9 @@ static int rsi_prepare_mgmt_desc(struct rsi_common *common, struct sk_buff *skb)
mgmt_desc->frame_type = TX_DOT11_MGMT;
mgmt_desc->header_len = MIN_802_11_HDR_LEN;
mgmt_desc->xtend_desc_size = header_size - FRAME_DESC_SZ;
+
+ if (ieee80211_is_probe_req(wh->frame_control) && common->fgscan_in_prog)
+ mgmt_desc->frame_info = cpu_to_le16(RSI_INSERT_SEQ_IN_FW);
mgmt_desc->frame_info |= cpu_to_le16(RATE_INFO_ENABLE);
if (is_broadcast_ether_addr(wh->addr1))
mgmt_desc->frame_info |= cpu_to_le16(RSI_BROADCAST_PKT);
diff --git a/drivers/net/wireless/rsi/rsi_91x_mac80211.c b/drivers/net/wireless/rsi/rsi_91x_mac80211.c
index 32f5cb4..4957690 100644
--- a/drivers/net/wireless/rsi/rsi_91x_mac80211.c
+++ b/drivers/net/wireless/rsi/rsi_91x_mac80211.c
@@ -229,6 +229,79 @@ static void rsi_register_rates_channels(struct rsi_hw *adapter, int band)
/* sbands->ht_cap.mcs.rx_highest = 0x82; */
}
+static int rsi_mac80211_hw_scan_start(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_scan_request *hw_req)
+{
+ struct cfg80211_scan_request *scan_req = &hw_req->req;
+ struct rsi_hw *adapter = hw->priv;
+ struct rsi_common *common = adapter->priv;
+ struct ieee80211_bss_conf *bss = &vif->bss_conf;
+
+ rsi_dbg(INFO_ZONE, "***** Hardware scan start *****\n");
+
+ if (common->fsm_state != FSM_MAC_INIT_DONE)
+ return -ENODEV;
+
+ if ((common->wow_flags & RSI_WOW_ENABLED) ||
+ scan_req->n_channels == 0)
+ return -EINVAL;
+
+ /* Scan already in progress. So return */
+ if (common->bgscan_en || common->fgscan_in_prog)
+ return -EBUSY;
+
+ mutex_lock(&common->mutex);
+
+ common->hwscan = scan_req;
+ common->scan_vif = vif;
+ if (!bss->assoc) {
+ common->cancel_hwscan = false;
+ queue_work(common->scan_workqueue, &common->scan_work);
+ } else {
+ if (!rsi_send_bgscan_params(common, RSI_START_BGSCAN)) {
+ if (!rsi_send_bgscan_probe_req(common)) {
+ rsi_dbg(INFO_ZONE,
+ "Background scan started...\n");
+ common->bgscan_en = true;
+ }
+ }
+ }
+
+ mutex_unlock(&common->mutex);
+
+ return 0;
+}
+
+static void rsi_mac80211_cancel_hw_scan(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif)
+{
+ struct rsi_hw *adapter = hw->priv;
+ struct rsi_common *common = adapter->priv;
+ struct cfg80211_scan_info info;
+
+ rsi_dbg(INFO_ZONE, "***** Hardware scan stop *****\n");
+
+ mutex_lock(&common->mutex);
+
+ if (common->fgscan_in_prog) {
+ common->cancel_hwscan = true;
+ rsi_wait_event(&common->cancel_hw_scan_event,
+ EVENT_WAIT_FOREVER);
+ rsi_reset_event(&common->cancel_hw_scan_event);
+ }
+ if (common->bgscan_en) {
+ if (!rsi_send_bgscan_params(common, RSI_STOP_BGSCAN))
+ common->bgscan_en = 0;
+ info.aborted = false;
+ ieee80211_scan_completed(adapter->hw, &info);
+ rsi_dbg(INFO_ZONE, "Back ground scan cancelled\b");
+ }
+ common->hwscan = NULL;
+ common->scan_vif = NULL;
+ mutex_unlock(&common->mutex);
+}
+
/**
* rsi_mac80211_detach() - This function is used to de-initialize the
* Mac80211 stack.
@@ -239,12 +312,18 @@ static void rsi_register_rates_channels(struct rsi_hw *adapter, int band)
void rsi_mac80211_detach(struct rsi_hw *adapter)
{
struct ieee80211_hw *hw = adapter->hw;
+ struct rsi_common *common = adapter->priv;
enum nl80211_band band;
+ if (common->fgscan_in_prog)
+ common->cancel_hwscan = true;
+ flush_workqueue(common->scan_workqueue);
if (hw) {
ieee80211_stop_queues(hw);
ieee80211_unregister_hw(hw);
ieee80211_free_hw(hw);
+ adapter->hw = NULL;
+ adapter->sc_nvifs = 0;
}
for (band = 0; band < NUM_NL80211_BANDS; band++) {
@@ -1894,6 +1973,8 @@ static const struct ieee80211_ops mac80211_ops = {
.suspend = rsi_mac80211_suspend,
.resume = rsi_mac80211_resume,
#endif
+ .hw_scan = rsi_mac80211_hw_scan_start,
+ .cancel_hw_scan = rsi_mac80211_cancel_hw_scan,
};
/**
@@ -1972,6 +2053,9 @@ int rsi_mac80211_attach(struct rsi_common *common)
common->max_stations = wiphy->max_ap_assoc_sta;
rsi_dbg(ERR_ZONE, "Max Stations Allowed = %d\n", common->max_stations);
hw->sta_data_size = sizeof(struct rsi_sta);
+
+ wiphy->max_scan_ssids = RSI_MAX_SCAN_SSIDS;
+ wiphy->max_scan_ie_len = RSI_MAX_SCAN_IE_LEN;
wiphy->flags = WIPHY_FLAG_REPORTS_OBSS;
wiphy->flags |= WIPHY_FLAG_AP_UAPSD;
wiphy->features |= NL80211_FEATURE_INACTIVITY_TIMER;
diff --git a/drivers/net/wireless/rsi/rsi_91x_main.c b/drivers/net/wireless/rsi/rsi_91x_main.c
index 1485a0c..bf05242 100644
--- a/drivers/net/wireless/rsi/rsi_91x_main.c
+++ b/drivers/net/wireless/rsi/rsi_91x_main.c
@@ -324,6 +324,14 @@ struct rsi_hw *rsi_91x_init(u16 oper_mode)
mutex_init(&common->rx_lock);
mutex_init(&common->tx_bus_mutex);
+ rsi_init_event(&common->chan_set_event);
+ rsi_init_event(&common->probe_cfm_event);
+ rsi_init_event(&common->chan_change_event);
+ rsi_init_event(&common->cancel_hw_scan_event);
+ common->scan_workqueue =
+ create_singlethread_workqueue("rsi_scan_worker");
+ INIT_WORK(&common->scan_work, rsi_fgscan_start);
+
if (rsi_create_kthread(common,
&common->tx_thread,
rsi_tx_scheduler_thread,
@@ -333,6 +341,7 @@ struct rsi_hw *rsi_91x_init(u16 oper_mode)
}
rsi_default_ps_params(adapter);
+ init_bgscan_params(common);
spin_lock_init(&adapter->ps_lock);
timer_setup(&common->roc_timer, rsi_roc_timeout, 0);
init_completion(&common->wlan_init_completion);
@@ -396,6 +405,9 @@ void rsi_91x_deinit(struct rsi_hw *adapter)
rsi_dbg(INFO_ZONE, "%s: Performing deinit os ops\n", __func__);
+ flush_workqueue(common->scan_workqueue);
+ destroy_workqueue(common->scan_workqueue);
+
rsi_kill_thread(&common->tx_thread);
for (ii = 0; ii < NUM_SOFT_QUEUES; ii++)
diff --git a/drivers/net/wireless/rsi/rsi_91x_mgmt.c b/drivers/net/wireless/rsi/rsi_91x_mgmt.c
index c21fca7..0bcf841 100644
--- a/drivers/net/wireless/rsi/rsi_91x_mgmt.c
+++ b/drivers/net/wireless/rsi/rsi_91x_mgmt.c
@@ -15,6 +15,7 @@
*/
#include <linux/etherdevice.h>
+#include <linux/timer.h>
#include "rsi_mgmt.h"
#include "rsi_common.h"
#include "rsi_ps.h"
@@ -236,6 +237,18 @@ static void rsi_set_default_parameters(struct rsi_common *common)
common->dtim_cnt = RSI_DTIM_COUNT;
}
+void init_bgscan_params(struct rsi_common *common)
+{
+ memset((u8 *)&common->bgscan, 0, sizeof(struct rsi_bgscan_params));
+ common->bgscan.bgscan_threshold = RSI_DEF_BGSCAN_THRLD;
+ common->bgscan.roam_threshold = RSI_DEF_ROAM_THRLD;
+ common->bgscan.bgscan_periodicity = RSI_BGSCAN_PERIODICITY;
+ common->bgscan.num_bgscan_channels = 0;
+ common->bgscan.two_probe = 1;
+ common->bgscan.active_scan_duration = RSI_ACTIVE_SCAN_TIME;
+ common->bgscan.passive_scan_duration = RSI_PASSIVE_SCAN_TIME;
+}
+
/**
* rsi_set_contention_vals() - This function sets the contention values for the
* backoff procedure.
@@ -1193,6 +1206,7 @@ static int rsi_send_auto_rate_request(struct rsi_common *common,
__func__);
return -ENOMEM;
}
+ memset(skb->data, 0, frame_len);
selected_rates = kzalloc(2 * RSI_TBL_SZ, GFP_KERNEL);
if (!selected_rates) {
@@ -1633,6 +1647,240 @@ int rsi_send_wowlan_request(struct rsi_common *common, u16 flags,
}
#endif
+static void channel_change_event(struct timer_list *t)
+{
+ struct rsi_common *common = from_timer(common, t, scan_timer);
+
+ rsi_set_event(&common->chan_change_event);
+ del_timer(&common->scan_timer);
+}
+
+static int init_channel_timer(struct rsi_common *common, u32 timeout)
+{
+ timer_setup(&common->scan_timer, channel_change_event, 0);
+ rsi_reset_event(&common->chan_change_event);
+ common->scan_timer.expires = msecs_to_jiffies(timeout) + jiffies;
+ add_timer(&common->scan_timer);
+
+ return 0;
+}
+
+int rsi_prepare_probe_request(struct rsi_common *common,
+ struct cfg80211_scan_request *scan_req,
+ u8 n_ssid, u8 channel, u8 *pbreq, u16 *pbreq_len)
+{
+ struct ieee80211_vif *vif = common->scan_vif;
+ struct cfg80211_ssid *ssid_info;
+ struct ieee80211_hdr *hdr = NULL;
+ u8 *pos;
+
+ if (common->priv->sc_nvifs <= 0)
+ return -ENODEV;
+ if (!scan_req)
+ return -EINVAL;
+ ssid_info = &scan_req->ssids[n_ssid];
+ if (!ssid_info)
+ return -EINVAL;
+
+ hdr = (struct ieee80211_hdr *)pbreq;
+ hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
+ IEEE80211_STYPE_PROBE_REQ);
+ hdr->duration_id = 0x0;
+ memset(hdr->addr1, 0xff, ETH_ALEN);
+ memset(hdr->addr3, 0xff, ETH_ALEN);
+ ether_addr_copy(hdr->addr2, vif->addr);
+ hdr->seq_ctrl = 0x00;
+ pos = (u8 *)hdr + MIN_802_11_HDR_LEN;
+
+ *pos++ = WLAN_EID_SSID;
+ *pos++ = ssid_info->ssid_len;
+ if (ssid_info->ssid_len)
+ memcpy(pos, ssid_info->ssid, ssid_info->ssid_len);
+ pos += ssid_info->ssid_len;
+
+ if (scan_req->ie_len)
+ memcpy(pos, scan_req->ie, scan_req->ie_len);
+ pos += scan_req->ie_len;
+ *pbreq_len = pos - pbreq;
+
+ return 0;
+}
+
+int rsi_send_probe_request(struct rsi_common *common,
+ struct cfg80211_scan_request *scan_req,
+ u8 n_ssid, u8 channel)
+{
+ struct cfg80211_ssid *ssid_info = &scan_req->ssids[n_ssid];
+ struct sk_buff *skb = NULL;
+ u16 len;
+ u8 ssid_ie_len;
+
+ ssid_ie_len = ssid_info->ssid_len + 2;
+ len = MIN_802_11_HDR_LEN + scan_req->ie_len + ssid_ie_len;
+
+ skb = dev_alloc_skb(len + MAX_DWORD_ALIGN_BYTES);
+ if (!skb)
+ return -ENOMEM;
+ skb_reserve(skb, MAX_DWORD_ALIGN_BYTES);
+ memset(skb->data, 0, len);
+ if (rsi_prepare_probe_request(common, scan_req, n_ssid, channel,
+ skb->data, &len)) {
+ rsi_dbg(ERR_ZONE, "Failed to prepare probe request\n");
+ dev_kfree_skb(skb);
+ return -EINVAL;
+ }
+ skb_put(skb, len);
+ rsi_core_xmit(common, skb);
+
+ return 0;
+}
+
+void rsi_fgscan_start(struct work_struct *work)
+{
+ struct rsi_common *common =
+ container_of(work, struct rsi_common, scan_work);
+ struct cfg80211_scan_request *scan_req = common->hwscan;
+ struct ieee80211_channel *cur_chan = NULL;
+ struct cfg80211_scan_info info;
+ u8 i, j;
+
+ if (!scan_req || common->fgscan_in_prog)
+ return;
+
+ common->fgscan_in_prog = true;
+ rsi_dbg(INFO_ZONE, "Foreground scan started...\n");
+
+ info.aborted = false;
+ for (i = 0; i < scan_req->n_channels ; i++) {
+ if (common->iface_down || common->cancel_hwscan) {
+ info.aborted = true;
+ break;
+ }
+
+ cur_chan = scan_req->channels[i];
+ if (cur_chan->flags & IEEE80211_CHAN_DISABLED)
+ continue;
+
+ rsi_dbg(INFO_ZONE, "Scanning chan: %d\n", cur_chan->hw_value);
+
+ rsi_reset_event(&common->chan_set_event);
+ rsi_band_check(common, cur_chan);
+ if (rsi_set_channel(common, cur_chan)) {
+ rsi_dbg(ERR_ZONE, "Failed to set the channel\n");
+ info.aborted = true;
+ break;
+ }
+ rsi_wait_event(&common->chan_set_event,
+ msecs_to_jiffies(RSI_CHAN_SET_TIME));
+ rsi_reset_event(&common->chan_set_event);
+
+ init_channel_timer(common, RSI_CHAN_DWELL_TIME);
+ for (j = 0; j < scan_req->n_ssids; j++) {
+ rsi_send_probe_request(common, scan_req, j,
+ cur_chan->hw_value);
+ rsi_reset_event(&common->probe_cfm_event);
+ rsi_wait_event(&common->probe_cfm_event,
+ msecs_to_jiffies(RSI_PROBE_CFM_TIME));
+ rsi_reset_event(&common->probe_cfm_event);
+ }
+ rsi_wait_event(&common->chan_change_event, EVENT_WAIT_FOREVER);
+ rsi_reset_event(&common->chan_change_event);
+ }
+
+ del_timer(&common->scan_timer);
+ common->fgscan_in_prog = false;
+ ieee80211_scan_completed(common->priv->hw, &info);
+ rsi_dbg(INFO_ZONE, "Foreground scan completed\n");
+ rsi_set_event(&common->cancel_hw_scan_event);
+}
+
+int rsi_send_bgscan_params(struct rsi_common *common, int enable)
+{
+ struct rsi_bgscan_params *params = &common->bgscan;
+ struct cfg80211_scan_request *scan_req = common->hwscan;
+ struct rsi_bgscan_config *bgscan;
+ struct sk_buff *skb;
+ u16 frame_len = sizeof(*bgscan);
+ u8 i;
+
+ rsi_dbg(MGMT_TX_ZONE, "%s: Sending bgscan params frame\n", __func__);
+
+ skb = dev_alloc_skb(frame_len);
+ if (!skb)
+ return -ENOMEM;
+ memset(skb->data, 0, frame_len);
+
+ bgscan = (struct rsi_bgscan_config *)skb->data;
+ rsi_set_len_qno(&bgscan->desc_dword0.len_qno,
+ (frame_len - FRAME_DESC_SZ), RSI_WIFI_MGMT_Q);
+ bgscan->desc_dword0.frame_type = BG_SCAN_PARAMS;
+ bgscan->bgscan_threshold = cpu_to_le16(params->bgscan_threshold);
+ bgscan->roam_threshold = cpu_to_le16(params->roam_threshold);
+ if (enable)
+ bgscan->bgscan_periodicity =
+ cpu_to_le16(params->bgscan_periodicity);
+ bgscan->active_scan_duration =
+ cpu_to_le16(params->active_scan_duration);
+ bgscan->passive_scan_duration =
+ cpu_to_le16(params->passive_scan_duration);
+ bgscan->two_probe = params->two_probe;
+
+ bgscan->num_bgscan_channels = scan_req->n_channels;
+ for (i = 0; i < bgscan->num_bgscan_channels; i++)
+ bgscan->channels2scan[i] =
+ cpu_to_le16(scan_req->channels[i]->hw_value);
+
+ skb_put(skb, frame_len);
+
+ return rsi_send_internal_mgmt_frame(common, skb);
+}
+
+/* This function sends the probe request to be used by firmware in
+ * background scan
+ */
+int rsi_send_bgscan_probe_req(struct rsi_common *common)
+{
+ struct cfg80211_scan_request *scan_req = common->hwscan;
+ struct rsi_bgscan_probe *bgscan;
+ struct sk_buff *skb;
+ u16 frame_len = sizeof(*bgscan);
+ u16 len = MAX_BGSCAN_PROBE_REQ_LEN;
+ u16 pbreq_len = 0;
+
+ rsi_dbg(MGMT_TX_ZONE,
+ "%s: Sending bgscan probe req frame\n", __func__);
+
+ skb = dev_alloc_skb(frame_len + len);
+ if (!skb)
+ return -ENOMEM;
+ memset(skb->data, 0, frame_len + len);
+
+ bgscan = (struct rsi_bgscan_probe *)skb->data;
+ bgscan->desc_dword0.frame_type = BG_SCAN_PROBE_REQ;
+ bgscan->flags = cpu_to_le16(HOST_BG_SCAN_TRIG);
+ if (common->band == NL80211_BAND_5GHZ) {
+ bgscan->mgmt_rate = cpu_to_le16(RSI_RATE_6);
+ bgscan->def_chan = cpu_to_le16(40);
+ } else {
+ bgscan->mgmt_rate = cpu_to_le16(RSI_RATE_1);
+ bgscan->def_chan = cpu_to_le16(11);
+ }
+ bgscan->channel_scan_time = cpu_to_le16(RSI_CHANNEL_SCAN_TIME);
+
+ /* Append dot11 probe request */
+ rsi_prepare_probe_request(common, scan_req, 0, 0,
+ &skb->data[frame_len],
+ &pbreq_len);
+ bgscan->probe_req_length = cpu_to_le16(pbreq_len);
+
+ rsi_set_len_qno(&bgscan->desc_dword0.len_qno,
+ (frame_len - FRAME_DESC_SZ + pbreq_len),
+ RSI_WIFI_MGMT_Q);
+ skb_put(skb, frame_len + pbreq_len);
+
+ return rsi_send_internal_mgmt_frame(common, skb);
+}
+
/**
* rsi_handle_ta_confirm_type() - This function handles the confirm frames.
* @common: Pointer to the driver private structure.
@@ -1776,15 +2024,37 @@ static int rsi_handle_ta_confirm_type(struct rsi_common *common,
return 0;
}
break;
+
+ case SCAN_REQUEST:
+ rsi_dbg(INFO_ZONE, "Set channel confirm\n");
+ rsi_set_event(&common->chan_set_event);
+ break;
+
case WAKEUP_SLEEP_REQUEST:
rsi_dbg(INFO_ZONE, "Wakeup/Sleep confirmation.\n");
return rsi_handle_ps_confirm(adapter, msg);
+
+ case BG_SCAN_PROBE_REQ:
+ rsi_dbg(INFO_ZONE, "BG scan complete event\n");
+ if (common->bgscan_en) {
+ struct cfg80211_scan_info info;
+
+ if (!rsi_send_bgscan_params(common, RSI_STOP_BGSCAN))
+ common->bgscan_en = 0;
+ info.aborted = false;
+ ieee80211_scan_completed(adapter->hw, &info);
+ rsi_set_event(&common->cancel_hw_scan_event);
+ }
+ rsi_dbg(INFO_ZONE, "Background scan completed\n");
+ break;
+
default:
rsi_dbg(INFO_ZONE, "%s: Invalid TA confirm pkt received\n",
__func__);
break;
}
return 0;
+
out:
rsi_dbg(ERR_ZONE, "%s: Unable to send pkt/Invalid frame received\n",
__func__);
@@ -1852,8 +2122,9 @@ int rsi_mgmt_pkt_recv(struct rsi_common *common, u8 *msg)
case TX_STATUS_IND:
if (msg[15] == PROBEREQ_CONFIRM) {
common->mgmt_q_block = false;
- rsi_dbg(FSM_ZONE, "%s: Probe confirm received\n",
+ rsi_dbg(INFO_ZONE, "%s: Mgmt queue unblocked\n",
__func__);
+ rsi_set_event(&common->probe_cfm_event);
}
break;
case BEACON_EVENT_IND:
diff --git a/drivers/net/wireless/rsi/rsi_main.h b/drivers/net/wireless/rsi/rsi_main.h
index ef4fa32..3dd08f5 100644
--- a/drivers/net/wireless/rsi/rsi_main.h
+++ b/drivers/net/wireless/rsi/rsi_main.h
@@ -164,6 +164,28 @@ struct transmit_q_stats {
u32 total_tx_pkt_freed[NUM_EDCA_QUEUES + 2];
};
+#define MAX_BGSCAN_CHANNELS_DUAL_BAND 38
+#define MAX_BGSCAN_PROBE_REQ_LEN 0x05DC
+#define BG_PROBE_REQ_LEN_CHECK 0x78
+#define RSI_BGSCAN_START 0x1
+#define RSI_BGSCAN_STOP 0x0
+#define RSI_DEF_BGSCAN_THRLD 0x0
+#define RSI_DEF_ROAM_THRLD 0xa
+#define RSI_BGSCAN_PERIODICITY 0x1e
+#define RSI_ACTIVE_SCAN_TIME 0x14
+#define RSI_PASSIVE_SCAN_TIME 0x46
+#define MAX_BGSCAN_CHANNELS_2GHZ 0xe
+#define RSI_CHANNEL_SCAN_TIME 20
+struct rsi_bgscan_params {
+ u16 bgscan_threshold;
+ u16 roam_threshold;
+ u16 bgscan_periodicity;
+ u8 num_bgscan_channels;
+ u8 two_probe;
+ u16 active_scan_duration;
+ u16 passive_scan_duration;
+};
+
struct vif_priv {
bool is_ht;
bool sgi;
@@ -294,6 +316,20 @@ struct rsi_common {
struct ieee80211_vif *roc_vif;
void *bt_adapter;
+
+ struct ieee80211_vif *scan_vif;
+ struct cfg80211_scan_request *hwscan;
+ struct rsi_bgscan_params bgscan;
+ struct workqueue_struct *scan_workqueue;
+ struct work_struct scan_work;
+ struct rsi_event chan_set_event;
+ struct rsi_event probe_cfm_event;
+ struct rsi_event chan_change_event;
+ struct rsi_event cancel_hw_scan_event;
+ struct timer_list scan_timer;
+ bool fgscan_in_prog;
+ bool bgscan_en;
+ bool cancel_hwscan;
};
struct eepromrw_info {
diff --git a/drivers/net/wireless/rsi/rsi_mgmt.h b/drivers/net/wireless/rsi/rsi_mgmt.h
index cf6567a..b7f63c9 100644
--- a/drivers/net/wireless/rsi/rsi_mgmt.h
+++ b/drivers/net/wireless/rsi/rsi_mgmt.h
@@ -221,6 +221,12 @@
#define RSI_WOW_DISCONNECT BIT(5)
#endif
+#define RSI_MAX_SCAN_SSIDS 16
+#define RSI_MAX_SCAN_IE_LEN 256
+#define RSI_CHAN_DWELL_TIME 300
+#define RSI_CHAN_SET_TIME 50
+#define RSI_PROBE_CFM_TIME 50
+
enum opmode {
RSI_OPMODE_UNSUPPORTED = -1,
RSI_OPMODE_AP = 0,
@@ -610,6 +616,34 @@ struct rsi_wowlan_req {
u16 host_sleep_status;
} __packed;
+#define RSI_START_BGSCAN 1
+#define RSI_STOP_BGSCAN 0
+#define HOST_BG_SCAN_TRIG BIT(4)
+struct rsi_bgscan_config {
+ struct rsi_cmd_desc_dword0 desc_dword0;
+ __le64 reserved;
+ __le32 reserved1;
+ __le16 bgscan_threshold;
+ __le16 roam_threshold;
+ __le16 bgscan_periodicity;
+ u8 num_bgscan_channels;
+ u8 two_probe;
+ __le16 active_scan_duration;
+ __le16 passive_scan_duration;
+ __le16 channels2scan[MAX_BGSCAN_CHANNELS_DUAL_BAND];
+} __packed;
+
+struct rsi_bgscan_probe {
+ struct rsi_cmd_desc_dword0 desc_dword0;
+ __le64 reserved;
+ __le32 reserved1;
+ __le16 mgmt_rate;
+ __le16 flags;
+ __le16 def_chan;
+ __le16 channel_scan_time;
+ __le16 probe_req_length;
+} __packed;
+
static inline u32 rsi_get_queueno(u8 *addr, u16 offset)
{
return (le16_to_cpu(*(__le16 *)&addr[offset]) & 0x7000) >> 12;
@@ -677,4 +711,14 @@ int rsi_send_wowlan_request(struct rsi_common *common, u16 flags,
#endif
int rsi_send_ps_request(struct rsi_hw *adapter, bool enable,
struct ieee80211_vif *vif);
+int rsi_prepare_probe_request(struct rsi_common *common,
+ struct cfg80211_scan_request *scan_req,
+ u8 n_ssid, u8 channel, u8 *pbreq, u16 *pbreq_len);
+int rsi_send_probe_request(struct rsi_common *common,
+ struct cfg80211_scan_request *scan_req, u8 n_ssid,
+ u8 channel);
+void rsi_fgscan_start(struct work_struct *data);
+void init_bgscan_params(struct rsi_common *common);
+int rsi_send_bgscan_params(struct rsi_common *common, int enable);
+int rsi_send_bgscan_probe_req(struct rsi_common *common);
#endif
--
2.7.4
Hi Kalle/Johannes,
On Tue, Mar 27, 2018 at 7:48 PM, Kalle Valo <[email protected]> wrote:
> Johannes Berg <[email protected]> writes:
>
>> On Fri, 2018-03-23 at 20:20 +0530, Amitkumar Karwar wrote:
>>
>>> > But maybe that's not really true at all? At least in one case it seems
>>> > you just kick off something called "bgscan".
>>>
>>> Yes. We have different scan implementations for device is connected
>>> and non-connected cases. In connected case, firmware will take care of
>>> timings when driver configures bgscan parameters due to power save and
>>> coex restrictions. In non-connected state, driver is taking care of
>>> it.
>>> I found hardware scan in mac80211 more suitable for our device.
>>
>> Yeah it's a bit odd though that you're still implementing software scan
>> :-)
>>
>> Perhaps we could make a special return code from the hwscan callback
>> that would tell mac80211 to fall back to software scanning, so you'd
>> only implement the connected case, and leave the rest up to mac80211?
>
> Hehe, this is exactly what I proposed during my review :)
>
Sounds good. I will prepare a patch with this approach.
Regards,
Amitkumar
Amitkumar Karwar <[email protected]> writes:
> From: Siva Rebbagondla <[email protected]>
>
> This patch adds a check to drop received broadcast/multicast frames if
> PN is invalid (i.e. not greater than last PN). bc_mc_pn
> variable added for each interface
>
> Signed-off-by: Siva Rebbagondla <[email protected]>
> Signed-off-by: Amitkumar Karwar <[email protected]>
[...]
> +static int rsi_validate_pn(struct rsi_hw *adapter, struct ieee80211_hdr *hdr)
> +{
> + struct ieee80211_vif *vif;
> + struct ieee80211_bss_conf *bss;
> + struct vif_priv *vif_info = NULL;
> + u8 cur_pn[IEEE80211_CCMP_PN_LEN];
> + u8 *last_pn;
> + int i, hdrlen;
> +
> + if (!is_broadcast_ether_addr(hdr->addr1) &&
> + !is_multicast_ether_addr(hdr->addr1))
> + return 1;
> +
> + hdrlen = ieee80211_hdrlen(hdr->frame_control);
> + for (i = 0; i < adapter->sc_nvifs; i++) {
> + vif = adapter->vifs[i];
> +
> + if (!vif)
> + continue;
> + if (vif->type != NL80211_IFTYPE_STATION &&
> + vif->type != NL80211_IFTYPE_P2P_CLIENT)
> + continue;
> + bss = &vif->bss_conf;
> + if (!bss->assoc)
> + continue;
> + if (!ether_addr_equal(bss->bssid, hdr->addr2))
> + continue;
> + vif_info = (struct vif_priv *)vif->drv_priv;
> + if (!vif_info->key) {
> + vif_info = NULL;
> + continue;
> + }
> + if (!vif_info->rx_pn_valid) {
> + vif_info = NULL;
> + continue;
> + }
> + }
> + if (!vif_info)
> + return 1;
Why +1 here?
> + last_pn = vif_info->rx_bcmc_pn;
> + if (vif_info->key->cipher == WLAN_CIPHER_SUITE_CCMP) {
> + struct dot11_ccmp_hdr *ccmp =
> + (struct dot11_ccmp_hdr *)&((u8 *)hdr)[hdrlen];
> +
> + cur_pn[0] = ccmp->pn0;
> + cur_pn[1] = ccmp->pn1;
> + cur_pn[2] = ccmp->pn2;
> + cur_pn[3] = ccmp->pn3;
> + cur_pn[4] = ccmp->pn4;
> + cur_pn[5] = ccmp->pn5;
> + } else {
> + struct dot11_tkip_hdr *tkip =
> + (struct dot11_tkip_hdr *)&((u8 *)hdr)[hdrlen];
> +
> + cur_pn[0] = tkip->tsc0;
> + cur_pn[1] = tkip->tsc1;
> + cur_pn[2] = tkip->tsc2;
> + cur_pn[3] = tkip->tsc3;
> + cur_pn[4] = tkip->tsc4;
> + cur_pn[5] = tkip->tsc5;
> + }
> + for (i = (IEEE80211_CCMP_PN_LEN - 1); i >= 0; i--)
> + if (last_pn[i] ^ cur_pn[i])
> + break;
> + if (i < 0)
> + return -1;
And why -1 here? Please use real error codes (-EINVAL etc).
> @@ -1341,14 +1488,14 @@ static void rsi_fill_rx_status(struct ieee80211_hw *hw,
> }
> }
> if (!bss)
> - return;
> + return -1;
Here as well.
--
Kalle Valo
From: Prameela Rani Garnepudi <[email protected]>
80MHz clock for device should be enabled by default in
TX command frame radio capabilities.
Signed-off-by: Prameela Rani Garnepudi <[email protected]>
---
drivers/net/wireless/rsi/rsi_91x_mgmt.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/wireless/rsi/rsi_91x_mgmt.c b/drivers/net/wireless/rsi/rsi_91x_mgmt.c
index 0bcf841..6f995d5a 100644
--- a/drivers/net/wireless/rsi/rsi_91x_mgmt.c
+++ b/drivers/net/wireless/rsi/rsi_91x_mgmt.c
@@ -338,8 +338,8 @@ static int rsi_load_radio_caps(struct rsi_common *common)
radio_caps->channel_num = common->channel;
radio_caps->rf_model = RSI_RF_TYPE;
+ radio_caps->radio_cfg_info = RSI_LMAC_CLOCK_80MHZ;
if (common->channel_width == BW_40MHZ) {
- radio_caps->radio_cfg_info = RSI_LMAC_CLOCK_80MHZ;
radio_caps->radio_cfg_info |= RSI_ENABLE_40MHZ;
if (common->fsm_state == FSM_MAC_INIT_DONE) {
--
2.7.4
On Thu, Mar 15, 2018 at 2:30 PM, Kalle Valo <[email protected]> wrote:
> Amitkumar Karwar <[email protected]> writes:
>
>> On Tue, Mar 13, 2018 at 8:46 PM, Kalle Valo <[email protected]> wrote:
>>> Amitkumar Karwar <[email protected]> writes:
>>>
>>>> From: Prameela Rani Garnepudi <[email protected]>
>>>>
>>>> With the current approach of scanning, roaming delays
>>>> are observed. Firmware has support for back ground scanning.
>>>> To get this advantage, mac80211 hardware scan is implemented.
>>>> In this method, foreground scan is performed in driver and
>>>> back ground scan is configured to firmware.
>>>
>>> To me doesn't like a good idea to duplicate scan functionality in the
>>> driver.
>>
>> There is a limitation with our device. We need to configure background
>> scan parameters to firmware when device is connected.
>
> Yeah, I guessed that.
>
>> In non-connected state, we can directly dump probe requests received
>> from mac80211 as a part of software scan. Some synchronization issues
>> are with existing software scan when device is connected. This patch
>> implements hw_scan where these issues are no seen, as driver has more
>> control on scan state machine
>
> What I don't like here is that you are duplicating functionality already
> existing in mac80211 and I hope there is a better way to solve the
> problem. Just as a a crazy idea what if the driver returns -EOPNOTSUPP
> when hardware scan is not possible and mac80211 falls back to software
> scan? But of course this depends on what Johannes thinks.
Currently mac80211 offloads scan to driver if "ops->hw_scan" is
implemented. Otherwise falls back to software scan.
I can see below vendors have already implemented hw_scan with their
own scan state machine. This patch does the same thing.
Let me know if I missed anything here.
/ath/ath10k/mac.c:7684: .hw_scan = ath10k_hw_scan,
./ath/wcn36xx/main.c:1115: .hw_scan = wcn36xx_hw_scan,
./ath/ath9k/main.c:2626: ath9k_ops.hw_scan = ath9k_hw_scan;
./st/cw1200/main.c:215: .hw_scan = cw1200_hw_scan,
./atmel/at76c50x-usb.c:2195: .hw_scan = at76_hw_scan,
./ti/wl1251/main.c:1376: .hw_scan = wl1251_op_hw_scan,
./ti/wlcore/main.c:5923: .hw_scan = wl1271_op_hw_scan,
./intel/iwlegacy/3945-mac.c:3485: .hw_scan = il_mac_hw_scan,
./intel/iwlegacy/3945-mac.c:3915: il3945_mac_ops.hw_scan = NULL;
./intel/iwlegacy/4965-mac.c:6352: .hw_scan = il_mac_hw_scan,
./intel/iwlwifi/mvm/mac80211.c:4343: .hw_scan = iwl_mvm_mac_hw_scan,
./intel/iwlwifi/dvm/mac80211.c:1627: .hw_scan = iwlagn_mac_hw_scan,
./mac80211_hwsim.c:2390: .hw_scan = mac80211_hwsim_hw_scan,
Regards,
Amitkumar
From: Prameela Rani Garnepudi <[email protected]>
Below changes are done:
1. When HCI detach is called, making bt_adapter null and checking
for this variable where ever required.
2. In USB case, one extra register write is added to disable
firmware watchdog.
3. When interface down is called as part of disconnect, don't
send RX filter frame.
Signed-off-by: Prameela Rani Garnepudi <[email protected]>
---
drivers/net/wireless/rsi/rsi_91x_mac80211.c | 8 ++++++--
drivers/net/wireless/rsi/rsi_91x_main.c | 2 ++
drivers/net/wireless/rsi/rsi_91x_usb.c | 10 ++++++++++
drivers/net/wireless/rsi/rsi_hal.h | 1 +
drivers/net/wireless/rsi/rsi_main.h | 1 +
5 files changed, 20 insertions(+), 2 deletions(-)
diff --git a/drivers/net/wireless/rsi/rsi_91x_mac80211.c b/drivers/net/wireless/rsi/rsi_91x_mac80211.c
index a7e1f7d..63d43fc 100644
--- a/drivers/net/wireless/rsi/rsi_91x_mac80211.c
+++ b/drivers/net/wireless/rsi/rsi_91x_mac80211.c
@@ -428,14 +428,18 @@ static void rsi_mac80211_stop(struct ieee80211_hw *hw)
{
struct rsi_hw *adapter = hw->priv;
struct rsi_common *common = adapter->priv;
+ u16 rx_filter_word = 0xffff;
rsi_dbg(ERR_ZONE, "===> Interface DOWN <===\n");
mutex_lock(&common->mutex);
common->iface_down = true;
wiphy_rfkill_stop_polling(hw->wiphy);
- /* Block all rx frames */
- rsi_send_rx_filter_frame(common, 0xffff);
+ if (!common->disc_in_prog) {
+ /* Block all rx frames */
+ rx_filter_word |= ~DISALLOW_BEACONS;
+ rsi_send_rx_filter_frame(common, rx_filter_word);
+ }
mutex_unlock(&common->mutex);
}
diff --git a/drivers/net/wireless/rsi/rsi_91x_main.c b/drivers/net/wireless/rsi/rsi_91x_main.c
index 7790314..96b36aa 100644
--- a/drivers/net/wireless/rsi/rsi_91x_main.c
+++ b/drivers/net/wireless/rsi/rsi_91x_main.c
@@ -350,6 +350,8 @@ struct rsi_hw *rsi_91x_init(u16 oper_mode)
timer_setup(&common->roc_timer, rsi_roc_timeout, 0);
init_completion(&common->wlan_init_completion);
common->init_done = true;
+ common->disc_in_prog = false;
+ common->bt_adapter = NULL;
adapter->device_model = RSI_DEV_9113;
common->oper_mode = oper_mode;
adapter->reg_mode = rsi_reg;
diff --git a/drivers/net/wireless/rsi/rsi_91x_usb.c b/drivers/net/wireless/rsi/rsi_91x_usb.c
index be8236f..f92909c 100644
--- a/drivers/net/wireless/rsi/rsi_91x_usb.c
+++ b/drivers/net/wireless/rsi/rsi_91x_usb.c
@@ -676,11 +676,13 @@ static int usb_ulp_read_write(struct rsi_hw *adapter, u16 addr, u32 data,
return 0;
}
+#define FW_WDT_DISABLE_REQ 0x69
static int rsi_reset_card(struct rsi_hw *adapter)
{
int ret;
rsi_dbg(INFO_ZONE, "Resetting Card...\n");
+
rsi_usb_master_reg_write(adapter, RSI_TA_HOLD_REG, 0xE, 4);
/* This msleep will ensure Thread-Arch processor to go to hold
@@ -688,6 +690,13 @@ static int rsi_reset_card(struct rsi_hw *adapter)
*/
msleep(100);
+ if (rsi_usb_master_reg_write(adapter, SWBL_REGOUT,
+ FW_WDT_DISABLE_REQ,
+ RSI_COMMON_REG_SIZE) < 0) {
+ rsi_dbg(ERR_ZONE, "%s: FW WDT Disable failed...\n", __func__);
+ goto fail;
+ }
+
ret = usb_ulp_read_write(adapter, RSI_WATCH_DOG_TIMER_1,
RSI_ULP_WRITE_2, 32);
if (ret < 0)
@@ -804,6 +813,7 @@ static void rsi_disconnect(struct usb_interface *pfunction)
if (!adapter)
return;
+ adapter->priv->disc_in_prog = true;
rsi_mac80211_detach(adapter);
rsi_reset_card(adapter);
diff --git a/drivers/net/wireless/rsi/rsi_hal.h b/drivers/net/wireless/rsi/rsi_hal.h
index d6c2baa..327638c 100644
--- a/drivers/net/wireless/rsi/rsi_hal.h
+++ b/drivers/net/wireless/rsi/rsi_hal.h
@@ -115,6 +115,7 @@
#define FW_FLASH_OFFSET 0x820
#define LMAC_VER_OFFSET (FW_FLASH_OFFSET + 0x200)
#define MAX_DWORD_ALIGN_BYTES 64
+#define RSI_COMMON_REG_SIZE 2
struct bl_header {
__le32 flags;
diff --git a/drivers/net/wireless/rsi/rsi_main.h b/drivers/net/wireless/rsi/rsi_main.h
index 4521c43..9e09dd5 100644
--- a/drivers/net/wireless/rsi/rsi_main.h
+++ b/drivers/net/wireless/rsi/rsi_main.h
@@ -325,6 +325,7 @@ struct rsi_common {
bool bgscan_en;
bool cancel_hwscan;
bool eapol4_confirm;
+ bool disc_in_prog;
};
struct eepromrw_info {
--
2.7.4
On Wed, Mar 21, 2018 at 4:25 AM, Johannes Berg
<[email protected]> wrote:
> On Mon, 2018-03-05 at 20:07 +0530, Amitkumar Karwar wrote:
>> From: Siva Rebbagondla <[email protected]>
>>
>> This patch adds a check to drop received broadcast/multicast frames
>> if
>> PN is invalid (i.e. not greater than last PN). bc_mc_pn
>> variable added for each interface
>>
> Can you say why you do this rather than letting mac80211 do it?
Thanks for your comment.
I wasn't aware that mac80211 can do this even for decrypted Rx
packets. Only thing is we need to avoid IV stripping. I will create a
patch for it.
Regards,
Amitkumar
On Wed, Mar 21, 2018 at 4:02 AM, Johannes Berg
<[email protected]> wrote:
> On Thu, 2018-03-15 at 14:57 +0530, Amitkumar Karwar wrote:
>>
>> > What I don't like here is that you are duplicating functionality
>> > already
>> > existing in mac80211 and I hope there is a better way to solve the
>> > problem. Just as a a crazy idea what if the driver returns
>> > -EOPNOTSUPP
>> > when hardware scan is not possible and mac80211 falls back to
>> > software
>> > scan? But of course this depends on what Johannes thinks.
>>
>> Currently mac80211 offloads scan to driver if "ops->hw_scan" is
>> implemented. Otherwise falls back to software scan.
>> I can see below vendors have already implemented hw_scan with their
>> own scan state machine. This patch does the same thing.
>> Let me know if I missed anything here.
>
> I think the argument is that at least it looks like you're implementing
> the timing etc. in software in the driver again, which others don't do,
> they do it in firmware. Which is just software again, but we don't see
> it ;-)
Understood. Timing logic is either is hardware or mac80211 for others.
> But maybe that's not really true at all? At least in one case it seems
> you just kick off something called "bgscan".
Yes. We have different scan implementations for device is connected
and non-connected cases. In connected case, firmware will take care of
timings when driver configures bgscan parameters due to power save and
coex restrictions. In non-connected state, driver is taking care of
it.
I found hardware scan in mac80211 more suitable for our device.
Regards,
Amitkumar Karwar
Amitkumar Karwar <[email protected]> writes:
> From: Prameela Rani Garnepudi <[email protected]>
>
> With the current approach of scanning, roaming delays
> are observed. Firmware has support for back ground scanning.
> To get this advantage, mac80211 hardware scan is implemented.
> In this method, foreground scan is performed in driver and
> back ground scan is configured to firmware.
To me doesn't like a good idea to duplicate scan functionality in the
driver.
> --- a/drivers/net/wireless/rsi/rsi_91x_main.c
> +++ b/drivers/net/wireless/rsi/rsi_91x_main.c
> @@ -324,6 +324,14 @@ struct rsi_hw *rsi_91x_init(u16 oper_mode)
> mutex_init(&common->rx_lock);
> mutex_init(&common->tx_bus_mutex);
>
> + rsi_init_event(&common->chan_set_event);
> + rsi_init_event(&common->probe_cfm_event);
> + rsi_init_event(&common->chan_change_event);
> + rsi_init_event(&common->cancel_hw_scan_event);
And I'm starting to dislike this rsi_init_event() even more (see my
other mail). In upstream driver's custom abstractions are very much
frowned upon, especially that it makes review harder.
--
Kalle Valo
From: Prameela Rani Garnepudi <[email protected]>
For few regulatory customizations, we are taking rsi_reg
as module parameter.
Signed-off-by: Prameela Rani Garnepudi <[email protected]>
---
drivers/net/wireless/rsi/rsi_91x_main.c | 4 ++++
drivers/net/wireless/rsi/rsi_common.h | 3 +++
2 files changed, 7 insertions(+)
diff --git a/drivers/net/wireless/rsi/rsi_91x_main.c b/drivers/net/wireless/rsi/rsi_91x_main.c
index bf05242..e290779 100644
--- a/drivers/net/wireless/rsi/rsi_91x_main.c
+++ b/drivers/net/wireless/rsi/rsi_91x_main.c
@@ -24,6 +24,10 @@
#include "rsi_coex.h"
#include "rsi_hal.h"
+static u16 rsi_reg = RSI_REG_DEF;
+module_param(rsi_reg, ushort, 0444);
+MODULE_PARM_DESC(rsi_reg, "0 - RSI_REG_DEF, 1 - RSI_REG_DLCAR");
+
u32 rsi_zone_enabled = /* INFO_ZONE |
INIT_ZONE |
MGMT_TX_ZONE |
diff --git a/drivers/net/wireless/rsi/rsi_common.h b/drivers/net/wireless/rsi/rsi_common.h
index d9ff3b8..df40556 100644
--- a/drivers/net/wireless/rsi/rsi_common.h
+++ b/drivers/net/wireless/rsi/rsi_common.h
@@ -24,6 +24,9 @@
#define QUEUE_NOT_FULL 1
#define QUEUE_FULL 0
+#define RSI_REG_DEF 0
+#define RSI_REG_DLCAR 1
+
static inline int rsi_init_event(struct rsi_event *pevent)
{
atomic_set(&pevent->event_condition, 1);
--
2.7.4
On Fri, 2018-03-23 at 20:20 +0530, Amitkumar Karwar wrote:
> > But maybe that's not really true at all? At least in one case it seems
> > you just kick off something called "bgscan".
>
> Yes. We have different scan implementations for device is connected
> and non-connected cases. In connected case, firmware will take care of
> timings when driver configures bgscan parameters due to power save and
> coex restrictions. In non-connected state, driver is taking care of
> it.
> I found hardware scan in mac80211 more suitable for our device.
Yeah it's a bit odd though that you're still implementing software scan
:-)
Perhaps we could make a special return code from the hwscan callback
that would tell mac80211 to fall back to software scanning, so you'd
only implement the connected case, and leave the rest up to mac80211?
johannes
On Thu, 2018-03-15 at 14:57 +0530, Amitkumar Karwar wrote:
>
> > What I don't like here is that you are duplicating functionality
> > already
> > existing in mac80211 and I hope there is a better way to solve the
> > problem. Just as a a crazy idea what if the driver returns
> > -EOPNOTSUPP
> > when hardware scan is not possible and mac80211 falls back to
> > software
> > scan? But of course this depends on what Johannes thinks.
>
> Currently mac80211 offloads scan to driver if "ops->hw_scan" is
> implemented. Otherwise falls back to software scan.
> I can see below vendors have already implemented hw_scan with their
> own scan state machine. This patch does the same thing.
> Let me know if I missed anything here.
I think the argument is that at least it looks like you're implementing
the timing etc. in software in the driver again, which others don't do,
they do it in firmware. Which is just software again, but we don't see
it ;-)
But maybe that's not really true at all? At least in one case it seems
you just kick off something called "bgscan".
johannes
From: Prameela Rani Garnepudi <[email protected]>
Changes done to improve TX path:
1. Max number of frames to aggregate is increased to 8
2. Bootup parameters updated.
3. registering 5g band is done only when device supports
4. Vif is properly taken to enable power save.
5. When coex mode exist, power save on by default is set
Signed-off-by: Prameela Rani Garnepudi <[email protected]>
---
drivers/net/wireless/rsi/rsi_91x_core.c | 4 +++-
drivers/net/wireless/rsi/rsi_91x_mac80211.c | 36 +++++++++++++++++++++--------
drivers/net/wireless/rsi/rsi_boot_params.h | 3 ++-
drivers/net/wireless/rsi/rsi_mgmt.h | 2 ++
4 files changed, 33 insertions(+), 12 deletions(-)
diff --git a/drivers/net/wireless/rsi/rsi_91x_core.c b/drivers/net/wireless/rsi/rsi_91x_core.c
index 3ca468b9..1f1b972 100644
--- a/drivers/net/wireless/rsi/rsi_91x_core.c
+++ b/drivers/net/wireless/rsi/rsi_91x_core.c
@@ -432,7 +432,9 @@ void rsi_core_xmit(struct rsi_common *common, struct sk_buff *skb)
}
} else {
if (ieee80211_is_data_qos(wh->frame_control)) {
- tid = (skb->data[24] & IEEE80211_QOS_TID);
+ u8 *qos = ieee80211_get_qos_ctl(wh);
+
+ tid = *qos & IEEE80211_QOS_CTL_TID_MASK;
skb->priority = TID_TO_WME_AC(tid);
} else {
tid = IEEE80211_NONQOS_TID;
diff --git a/drivers/net/wireless/rsi/rsi_91x_mac80211.c b/drivers/net/wireless/rsi/rsi_91x_mac80211.c
index 63d43fc..70b2d61 100644
--- a/drivers/net/wireless/rsi/rsi_91x_mac80211.c
+++ b/drivers/net/wireless/rsi/rsi_91x_mac80211.c
@@ -240,6 +240,9 @@ static int rsi_mac80211_hw_scan_start(struct ieee80211_hw *hw,
rsi_dbg(INFO_ZONE, "***** Hardware scan start *****\n");
+ if (common->iface_down)
+ return -ENETDOWN;
+
if (common->fsm_state != FSM_MAC_INIT_DONE)
return -ENODEV;
@@ -697,7 +700,7 @@ static int rsi_mac80211_config(struct ieee80211_hw *hw,
/* Power save parameters */
if (changed & IEEE80211_CONF_CHANGE_PS) {
- struct ieee80211_vif *vif;
+ struct ieee80211_vif *vif, *sta_vif = NULL;
unsigned long flags;
int i, set_ps = 1;
@@ -711,13 +714,20 @@ static int rsi_mac80211_config(struct ieee80211_hw *hw,
set_ps = 0;
break;
}
+ if (vif->type == NL80211_IFTYPE_STATION ||
+ vif->type == NL80211_IFTYPE_P2P_CLIENT) {
+ if (!sta_vif)
+ sta_vif = vif;
+ else if (vif->bss_conf.assoc)
+ sta_vif = vif;
+ }
}
- if (set_ps) {
+ if (set_ps && sta_vif) {
spin_lock_irqsave(&adapter->ps_lock, flags);
if (conf->flags & IEEE80211_CONF_PS)
- rsi_enable_ps(adapter, vif);
+ rsi_enable_ps(adapter, sta_vif);
else
- rsi_disable_ps(adapter, vif);
+ rsi_disable_ps(adapter, sta_vif);
spin_unlock_irqrestore(&adapter->ps_lock, flags);
}
}
@@ -2051,9 +2061,16 @@ int rsi_mac80211_attach(struct rsi_common *common)
hw->uapsd_queues = RSI_IEEE80211_UAPSD_QUEUES;
hw->uapsd_max_sp_len = IEEE80211_WMM_IE_STA_QOSINFO_SP_ALL;
- hw->max_tx_aggregation_subframes = 6;
+ hw->max_tx_aggregation_subframes = RSI_MAX_TX_AGGR_FRMS;
+ hw->max_rx_aggregation_subframes = RSI_MAX_RX_AGGR_FRMS;
rsi_register_rates_channels(adapter, NL80211_BAND_2GHZ);
- rsi_register_rates_channels(adapter, NL80211_BAND_5GHZ);
+ wiphy->bands[NL80211_BAND_2GHZ] =
+ &adapter->sbands[NL80211_BAND_2GHZ];
+ if (common->num_supp_bands > 1) {
+ rsi_register_rates_channels(adapter, NL80211_BAND_5GHZ);
+ wiphy->bands[NL80211_BAND_5GHZ] =
+ &adapter->sbands[NL80211_BAND_5GHZ];
+ }
hw->rate_control_algorithm = "AARF";
SET_IEEE80211_PERM_ADDR(hw, common->mac_addr);
@@ -2074,10 +2091,6 @@ int rsi_mac80211_attach(struct rsi_common *common)
wiphy->available_antennas_rx = 1;
wiphy->available_antennas_tx = 1;
- wiphy->bands[NL80211_BAND_2GHZ] =
- &adapter->sbands[NL80211_BAND_2GHZ];
- wiphy->bands[NL80211_BAND_5GHZ] =
- &adapter->sbands[NL80211_BAND_5GHZ];
/* AP Parameters */
wiphy->max_ap_assoc_sta = rsi_max_ap_stas[common->oper_mode - 1];
@@ -2106,6 +2119,9 @@ int rsi_mac80211_attach(struct rsi_common *common)
wiphy->iface_combinations = rsi_iface_combinations;
wiphy->n_iface_combinations = ARRAY_SIZE(rsi_iface_combinations);
+ if (common->coex_mode > 1)
+ wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT;
+
status = ieee80211_register_hw(hw);
if (status)
return status;
diff --git a/drivers/net/wireless/rsi/rsi_boot_params.h b/drivers/net/wireless/rsi/rsi_boot_params.h
index 238ee96..ad903b22 100644
--- a/drivers/net/wireless/rsi/rsi_boot_params.h
+++ b/drivers/net/wireless/rsi/rsi_boot_params.h
@@ -46,7 +46,8 @@
(((TA_PLL_M_VAL_20 + 1) * 40) / \
((TA_PLL_N_VAL_20 + 1) * (TA_PLL_P_VAL_20 + 1)))
#define VALID_20 \
- (WIFI_PLL960_CONFIGS | WIFI_AFEPLL_CONFIGS | WIFI_SWITCH_CLK_CONFIGS)
+ (WIFI_TAPLL_CONFIGS | WIFI_PLL960_CONFIGS | WIFI_AFEPLL_CONFIGS | \
+ WIFI_SWITCH_CLK_CONFIGS | BOOTUP_MODE_INFO | CRYSTAL_GOOD_TIME)
#define UMAC_CLK_40BW \
(((TA_PLL_M_VAL_40 + 1) * 40) / \
((TA_PLL_N_VAL_40 + 1) * (TA_PLL_P_VAL_40 + 1)))
diff --git a/drivers/net/wireless/rsi/rsi_mgmt.h b/drivers/net/wireless/rsi/rsi_mgmt.h
index 65ae037..ae7dff3 100644
--- a/drivers/net/wireless/rsi/rsi_mgmt.h
+++ b/drivers/net/wireless/rsi/rsi_mgmt.h
@@ -231,6 +231,8 @@
#define RSI_CHAN_SET_TIME 50
#define RSI_PROBE_CFM_TIME 50
#define DOT11_ASSOC_CAP_SECURITY BIT(4)
+#define RSI_MAX_TX_AGGR_FRMS 8
+#define RSI_MAX_RX_AGGR_FRMS 8
enum opmode {
RSI_OPMODE_UNSUPPORTED = -1,
--
2.7.4
On Tue, Mar 13, 2018 at 8:57 PM, Kalle Valo <[email protected]> wrote:
> Amitkumar Karwar <[email protected]> writes:
>
>> From: Prameela Rani Garnepudi <[email protected]>
>>
>> Below changes are done:
>> 1. When HCI detach is called, making bt_adapter null and checking
>> for this variable where ever required.
>> 2. In USB case, one extra register write is added to disable
>> firmware watchdog.
>> 3. When interface down is called as part of disconnect, don't
>> send RX filter frame.
>
> Why? What does this patch fix? Please explain that (symptoms) in the
> commit log.
Kindly ignore this patch. I will include proper commit log which
explains the issue and resolution in updated version.
Regards,
Amitkumar
From: Prameela Rani Garnepudi <[email protected]>
To avoid synchronization issues in sending TX frames,
descriptors preparation is moved to core, instead of HAL.
This will avoid races during foreground scan because of mgmt
configurations.
Also xtended descriptor is moved from rsi_main.h to rsi_mgmt.h
as all descriptor information is in rsi_mgmt.h
Signed-off-by: Prameela Rani Garnepudi <[email protected]>
---
drivers/net/wireless/rsi/rsi_91x_core.c | 11 +++++++++
drivers/net/wireless/rsi/rsi_91x_hal.c | 43 +++++++++++++++++----------------
drivers/net/wireless/rsi/rsi_hal.h | 2 ++
3 files changed, 35 insertions(+), 21 deletions(-)
diff --git a/drivers/net/wireless/rsi/rsi_91x_core.c b/drivers/net/wireless/rsi/rsi_91x_core.c
index 5dafd2e..f5d1756 100644
--- a/drivers/net/wireless/rsi/rsi_91x_core.c
+++ b/drivers/net/wireless/rsi/rsi_91x_core.c
@@ -413,6 +413,11 @@ void rsi_core_xmit(struct rsi_common *common, struct sk_buff *skb)
(ieee80211_is_qos_nullfunc(wh->frame_control))) {
q_num = MGMT_SOFT_Q;
skb->priority = q_num;
+
+ if (rsi_prepare_mgmt_desc(common, skb)) {
+ rsi_dbg(ERR_ZONE, "Failed to prepare desc\n");
+ goto xmit_fail;
+ }
} else {
if (ieee80211_is_data_qos(wh->frame_control)) {
tid = (skb->data[24] & IEEE80211_QOS_TID);
@@ -433,6 +438,8 @@ void rsi_core_xmit(struct rsi_common *common, struct sk_buff *skb)
if (!rsta)
goto xmit_fail;
tx_params->sta_id = rsta->sta_id;
+ } else {
+ tx_params->sta_id = 0;
}
if (rsta) {
@@ -443,6 +450,10 @@ void rsi_core_xmit(struct rsi_common *common, struct sk_buff *skb)
tid, 0);
}
}
+ if (rsi_prepare_data_desc(common, skb)) {
+ rsi_dbg(ERR_ZONE, "Failed to prepare data desc\n");
+ goto xmit_fail;
+ }
}
if ((q_num < MGMT_SOFT_Q) &&
diff --git a/drivers/net/wireless/rsi/rsi_91x_hal.c b/drivers/net/wireless/rsi/rsi_91x_hal.c
index 718f793..7e04daf 100644
--- a/drivers/net/wireless/rsi/rsi_91x_hal.c
+++ b/drivers/net/wireless/rsi/rsi_91x_hal.c
@@ -45,7 +45,7 @@ int rsi_send_pkt_to_bus(struct rsi_common *common, struct sk_buff *skb)
return status;
}
-static int rsi_prepare_mgmt_desc(struct rsi_common *common, struct sk_buff *skb)
+int rsi_prepare_mgmt_desc(struct rsi_common *common, struct sk_buff *skb)
{
struct rsi_hw *adapter = common->priv;
struct ieee80211_hdr *wh = NULL;
@@ -116,17 +116,6 @@ static int rsi_prepare_mgmt_desc(struct rsi_common *common, struct sk_buff *skb)
if (conf_is_ht40(conf))
mgmt_desc->bbp_info = cpu_to_le16(FULL40M_ENABLE);
- if (ieee80211_is_probe_req(wh->frame_control)) {
- if (!bss->assoc) {
- rsi_dbg(INFO_ZONE,
- "%s: blocking mgmt queue\n", __func__);
- mgmt_desc->misc_flags = RSI_DESC_REQUIRE_CFM_TO_HOST;
- xtend_desc->confirm_frame_type = PROBEREQ_CONFIRM;
- common->mgmt_q_block = true;
- rsi_dbg(INFO_ZONE, "Mgmt queue blocked\n");
- }
- }
-
if (ieee80211_is_probe_resp(wh->frame_control)) {
mgmt_desc->misc_flags |= (RSI_ADD_DELTA_TSF_VAP_ID |
RSI_FETCH_RETRY_CNT_FRM_HST);
@@ -152,7 +141,7 @@ static int rsi_prepare_mgmt_desc(struct rsi_common *common, struct sk_buff *skb)
}
/* This function prepares descriptor for given data packet */
-static int rsi_prepare_data_desc(struct rsi_common *common, struct sk_buff *skb)
+int rsi_prepare_data_desc(struct rsi_common *common, struct sk_buff *skb)
{
struct rsi_hw *adapter = common->priv;
struct ieee80211_vif *vif;
@@ -304,10 +293,6 @@ int rsi_send_data_pkt(struct rsi_common *common, struct sk_buff *skb)
(!bss->assoc))
goto err;
- status = rsi_prepare_data_desc(common, skb);
- if (status)
- goto err;
-
status = rsi_send_pkt_to_bus(common, skb);
if (status)
rsi_dbg(ERR_ZONE, "%s: Failed to write pkt\n", __func__);
@@ -330,12 +315,18 @@ int rsi_send_mgmt_pkt(struct rsi_common *common,
struct sk_buff *skb)
{
struct rsi_hw *adapter = common->priv;
+ struct ieee80211_bss_conf *bss;
+ struct ieee80211_hdr *wh;
struct ieee80211_tx_info *info;
struct skb_info *tx_params;
+ struct rsi_mgmt_desc *mgmt_desc;
+ struct rsi_xtended_desc *xtend_desc;
int status = -E2BIG;
+ u8 header_size;
info = IEEE80211_SKB_CB(skb);
tx_params = (struct skb_info *)info->driver_data;
+ header_size = tx_params->internal_hdr_size;
if (tx_params->flags & INTERNAL_MGMT_PKT) {
status = adapter->host_intf_ops->write_pkt(common->priv,
@@ -349,15 +340,25 @@ int rsi_send_mgmt_pkt(struct rsi_common *common,
return status;
}
- if (FRAME_DESC_SZ > skb_headroom(skb))
- goto err;
+ bss = &info->control.vif->bss_conf;
+ wh = (struct ieee80211_hdr *)&skb->data[header_size];
+ mgmt_desc = (struct rsi_mgmt_desc *)skb->data;
+ xtend_desc = (struct rsi_xtended_desc *)&skb->data[FRAME_DESC_SZ];
+
+ /* Indicate to firmware to give cfm for probe */
+ if (ieee80211_is_probe_req(wh->frame_control) && !bss->assoc) {
+ rsi_dbg(INFO_ZONE,
+ "%s: blocking mgmt queue\n", __func__);
+ mgmt_desc->misc_flags = RSI_DESC_REQUIRE_CFM_TO_HOST;
+ xtend_desc->confirm_frame_type = PROBEREQ_CONFIRM;
+ common->mgmt_q_block = true;
+ rsi_dbg(INFO_ZONE, "Mgmt queue blocked\n");
+ }
- rsi_prepare_mgmt_desc(common, skb);
status = rsi_send_pkt_to_bus(common, skb);
if (status)
rsi_dbg(ERR_ZONE, "%s: Failed to write the packet\n", __func__);
-err:
rsi_indicate_tx_status(common->priv, skb, status);
return status;
}
diff --git a/drivers/net/wireless/rsi/rsi_hal.h b/drivers/net/wireless/rsi/rsi_hal.h
index 786dccd..d6c2baa 100644
--- a/drivers/net/wireless/rsi/rsi_hal.h
+++ b/drivers/net/wireless/rsi/rsi_hal.h
@@ -167,6 +167,8 @@ struct rsi_bt_desc {
} __packed;
int rsi_hal_device_init(struct rsi_hw *adapter);
+int rsi_prepare_mgmt_desc(struct rsi_common *common, struct sk_buff *skb);
+int rsi_prepare_data_desc(struct rsi_common *common, struct sk_buff *skb);
int rsi_prepare_beacon(struct rsi_common *common, struct sk_buff *skb);
int rsi_send_pkt_to_bus(struct rsi_common *common, struct sk_buff *skb);
int rsi_send_bt_pkt(struct rsi_common *common, struct sk_buff *skb);
--
2.7.4
On Tue, Mar 13, 2018 at 8:48 PM, Kalle Valo <[email protected]> wrote:
> Kalle Valo <[email protected]> writes:
>
>> Amitkumar Karwar <[email protected]> writes:
>>
>>> From: Prameela Rani Garnepudi <[email protected]>
>>>
>>> With the current approach of scanning, roaming delays
>>> are observed. Firmware has support for back ground scanning.
>>> To get this advantage, mac80211 hardware scan is implemented.
>>> In this method, foreground scan is performed in driver and
>>> back ground scan is configured to firmware.
>>
>> To me doesn't like a good idea to duplicate scan functionality in the
>> driver.
>
> Also a pro tip: Don't place controversial patches as the first patch in
> a big patchset, instead put them last so that I can apply rest of
> patches anyway. Even better to submit them separately as RFC.
Got it. I will follow this.
Regards,
Amitkumar Karwar
On Tue, Mar 13, 2018 at 8:55 PM, Kalle Valo <[email protected]> wrote:
> Amitkumar Karwar <[email protected]> writes:
>
>> From: Prameela Rani Garnepudi <[email protected]>
>>
>> For few regulatory customizations, we are taking rsi_reg
>> as module parameter.
>
> Why?
We have a custom power table and country to region mapping, This
setting will be used only for a special mode called 'dlcar'
We want to have an option to enable this mode through a module parameter.
This patch introduces a module parameter. Next patch makes use of it.
Let me know if you have any suggestions here.
>> +static u16 rsi_reg = RSI_REG_DEF;
>> +module_param(rsi_reg, ushort, 0444)
>> +MODULE_PARM_DESC(rsi_reg, "0 - RSI_REG_DEF, 1 - RSI_REG_DLCAR");
>
> The documentation tells nothing.
>
Below are the details. I will add include this info if the approach
and patches(6/10 and 7/10) look ok to you.
0 - RSI_REG_DEF
Keep default regulatory configuration
1 - RSI_REG_DLCAR
Enable custom settings for 'dlcar' mode
Regards,
Amitkumar
On Tue, Mar 13, 2018 at 8:54 PM, Kalle Valo <[email protected]> wrote:
> Amitkumar Karwar <[email protected]> writes:
>
>> From: Prameela Rani Garnepudi <[email protected]>
>>
>> To support roaming below changes are done:
>> * Station notify frame is send to firmware after sending assoc
>> request. This will avoid dropping of first EAPOL frame due to
>> delay in creation of station control block in firmware.
>> * Data queues are unblocked after sending station notify in open
>> mode, after configuring key in WEP mode, and after receiving
>> EAPOL4 confirm in WPA mode.
>> * Initial EAPOL frames priority is chaged to MGMT, rekey EAPOL
>> frames priority changed to VO.
>> * Data frames with wrong BSSID are dropped.
>
> I don't know what Johannes thinks but IMHO the driver should not drop
> any data frames, it should just submit what mac80211 gives to it. All
> filtering should happen in mac80211 (or controlled by it).
This was just an extra check to ensure that when we roam from one AP
to another, we should drop frames for previous AP. We don't have any
evidence that such are received.
I will remove this change in next version.
Regards,
Amitkumar Karwar
On Mon, 2018-03-05 at 20:07 +0530, Amitkumar Karwar wrote:
> From: Siva Rebbagondla <[email protected]>
>
> This patch adds a check to drop received broadcast/multicast frames
> if
> PN is invalid (i.e. not greater than last PN). bc_mc_pn
> variable added for each interface
>
Can you say why you do this rather than letting mac80211 do it?
johannes
Amitkumar Karwar <[email protected]> writes:
> From: Prameela Rani Garnepudi <[email protected]>
>
> Below changes are done:
> 1. When HCI detach is called, making bt_adapter null and checking
> for this variable where ever required.
> 2. In USB case, one extra register write is added to disable
> firmware watchdog.
> 3. When interface down is called as part of disconnect, don't
> send RX filter frame.
Why? What does this patch fix? Please explain that (symptoms) in the
commit log.
--
Kalle Valo
Amitkumar Karwar <[email protected]> writes:
> From: Prameela Rani Garnepudi <[email protected]>
>
> To support roaming below changes are done:
> * Station notify frame is send to firmware after sending assoc
> request. This will avoid dropping of first EAPOL frame due to
> delay in creation of station control block in firmware.
> * Data queues are unblocked after sending station notify in open
> mode, after configuring key in WEP mode, and after receiving
> EAPOL4 confirm in WPA mode.
> * Initial EAPOL frames priority is chaged to MGMT, rekey EAPOL
> frames priority changed to VO.
> * Data frames with wrong BSSID are dropped.
I don't know what Johannes thinks but IMHO the driver should not drop
any data frames, it should just submit what mac80211 gives to it. All
filtering should happen in mac80211 (or controlled by it).
--
Kalle Valo