2017-08-16 13:17:39

by Amitkumar Karwar

[permalink] [raw]
Subject: [v2 00/11] rsi: support for AP mode

From: Amitkumar Karwar <[email protected]>

This patchset contains enhancements for AP mode operation.
Major changes are maintaining the station structures in
driver and adding station id parameter to the Tx packets
whenever required.
Tests are performed to confirm aggregation, connections in
WEP and WPA/WPA2 security.

Changes in v2:
patch 5/10: Avoided print_hex_dump to print station MAC in sta_add
patch 6/10: Avoided print hex_dump to print station MAC in sta_remove

Prameela Rani Garnepudi (11):
rsi: advertise ap mode support
rsi: add interface changes for ap mode
rsi: remove interface changes for AP mode
rsi: add beacon changes for AP mode
rsi: handle station connection in AP mode
rsi: handle station disconnection in AP mode
rsi: data and managemet path changes for AP mode
rsi: use common descriptor for auto rate frame
rsi: update tx auto rate command frame for AP mode
rsi: aggregation parameters frame for AP mode
rsi: security enhancements for AP mode

drivers/net/wireless/rsi/rsi_91x_core.c | 70 ++++--
drivers/net/wireless/rsi/rsi_91x_hal.c | 129 +++++++++--
drivers/net/wireless/rsi/rsi_91x_mac80211.c | 342 +++++++++++++++++++++++-----
drivers/net/wireless/rsi/rsi_91x_mgmt.c | 180 +++++++++++----
drivers/net/wireless/rsi/rsi_common.h | 1 +
drivers/net/wireless/rsi/rsi_hal.h | 4 +-
drivers/net/wireless/rsi/rsi_main.h | 27 ++-
drivers/net/wireless/rsi/rsi_mgmt.h | 35 ++-
8 files changed, 641 insertions(+), 147 deletions(-)

--
2.7.4


2017-08-16 13:18:23

by Amitkumar Karwar

[permalink] [raw]
Subject: [v2 08/11] rsi: use common descriptor for auto rate frame

From: Prameela Rani Garnepudi <[email protected]>

TX command frame auto rate request is modified to use common
descriptor struture.

Signed-off-by: Prameela Rani Garnepudi <[email protected]>
Signed-off-by: Amitkumar Karwar <[email protected]>
---
drivers/net/wireless/rsi/rsi_91x_mgmt.c | 18 +++++++-----------
drivers/net/wireless/rsi/rsi_mgmt.h | 2 +-
2 files changed, 8 insertions(+), 12 deletions(-)

diff --git a/drivers/net/wireless/rsi/rsi_91x_mgmt.c b/drivers/net/wireless/rsi/rsi_91x_mgmt.c
index 7c0f27a..c5d48cd 100644
--- a/drivers/net/wireless/rsi/rsi_91x_mgmt.c
+++ b/drivers/net/wireless/rsi/rsi_91x_mgmt.c
@@ -1164,8 +1164,9 @@ static int rsi_send_auto_rate_request(struct rsi_common *common)
u32 rate_bitmap = common->bitrate_mask[band];

u16 *selected_rates, min_rate;
+ u16 frame_len = sizeof(struct rsi_auto_rate);

- skb = dev_alloc_skb(sizeof(struct rsi_auto_rate));
+ skb = dev_alloc_skb(frame_len);
if (!skb) {
rsi_dbg(ERR_ZONE, "%s: Failed in allocation of skb\n",
__func__);
@@ -1180,8 +1181,6 @@ static int rsi_send_auto_rate_request(struct rsi_common *common)
return -ENOMEM;
}

- memset(skb->data, 0, sizeof(struct rsi_auto_rate));
-
auto_rate = (struct rsi_auto_rate *)skb->data;

auto_rate->aarf_rssi = cpu_to_le16(((u16)3 << 6) | (u16)(18 & 0x3f));
@@ -1190,10 +1189,10 @@ static int rsi_send_auto_rate_request(struct rsi_common *common)
auto_rate->initial_boundary = cpu_to_le16(3);
auto_rate->max_threshold_limt = cpu_to_le16(27);

- auto_rate->desc_word[1] = cpu_to_le16(AUTO_RATE_IND);
+ auto_rate->desc.desc_dword0.frame_type = AUTO_RATE_IND;

if (common->channel_width == BW_40MHZ)
- auto_rate->desc_word[7] |= cpu_to_le16(1);
+ auto_rate->desc.desc_dword3.qid_tid = BW_40MHZ;

if (band == NL80211_BAND_2GHZ) {
min_rate = RSI_RATE_1;
@@ -1259,15 +1258,12 @@ static int rsi_send_auto_rate_request(struct rsi_common *common)

auto_rate->num_supported_rates = cpu_to_le16(num_supported_rates * 2);
auto_rate->moderate_rate_inx = cpu_to_le16(num_supported_rates / 2);
- auto_rate->desc_word[7] |= cpu_to_le16(0 << 8);
num_supported_rates *= 2;

- auto_rate->desc_word[0] = cpu_to_le16((sizeof(*auto_rate) -
- FRAME_DESC_SZ) |
- (RSI_WIFI_MGMT_Q << 12));
+ rsi_set_len_qno(&auto_rate->desc.desc_dword0.len_qno,
+ (frame_len - FRAME_DESC_SZ), RSI_WIFI_MGMT_Q);

- skb_put(skb,
- sizeof(struct rsi_auto_rate));
+ skb_put(skb, frame_len);
kfree(selected_rates);

return rsi_send_internal_mgmt_frame(common, skb);
diff --git a/drivers/net/wireless/rsi/rsi_mgmt.h b/drivers/net/wireless/rsi/rsi_mgmt.h
index 9c59250..c50153d 100644
--- a/drivers/net/wireless/rsi/rsi_mgmt.h
+++ b/drivers/net/wireless/rsi/rsi_mgmt.h
@@ -425,7 +425,7 @@ struct rsi_set_key {
} __packed;

struct rsi_auto_rate {
- __le16 desc_word[8];
+ struct rsi_cmd_desc desc;
__le16 failure_limit;
__le16 initial_boundary;
__le16 max_threshold_limt;
--
2.7.4

2017-08-16 13:18:33

by Amitkumar Karwar

[permalink] [raw]
Subject: [v2 10/11] rsi: aggregation parameters frame for AP mode

From: Prameela Rani Garnepudi <[email protected]>

TX command frame ampdu aggregation parameters is updated to
include sta_id for AP mode.

Signed-off-by: Prameela Rani Garnepudi <[email protected]>
Signed-off-by: Amitkumar Karwar <[email protected]>
---
drivers/net/wireless/rsi/rsi_91x_mac80211.c | 43 +++++++++++++++++++++++------
drivers/net/wireless/rsi/rsi_91x_mgmt.c | 6 ++--
drivers/net/wireless/rsi/rsi_mgmt.h | 3 +-
3 files changed, 39 insertions(+), 13 deletions(-)

diff --git a/drivers/net/wireless/rsi/rsi_91x_mac80211.c b/drivers/net/wireless/rsi/rsi_91x_mac80211.c
index be10d50..f2cb61f 100644
--- a/drivers/net/wireless/rsi/rsi_91x_mac80211.c
+++ b/drivers/net/wireless/rsi/rsi_91x_mac80211.c
@@ -866,9 +866,11 @@ static int rsi_mac80211_ampdu_action(struct ieee80211_hw *hw,
int status = -EOPNOTSUPP;
struct rsi_hw *adapter = hw->priv;
struct rsi_common *common = adapter->priv;
- u16 seq_no = 0;
+ struct rsi_sta *rsta = NULL;
+ u16 seq_no = 0, seq_start = 0;
u8 ii = 0;
struct ieee80211_sta *sta = params->sta;
+ u8 sta_id = 0;
enum ieee80211_ampdu_mlme_action action = params->action;
u16 tid = params->tid;
u16 *ssn = &params->ssn;
@@ -880,17 +882,31 @@ static int rsi_mac80211_ampdu_action(struct ieee80211_hw *hw,
}

mutex_lock(&common->mutex);
- rsi_dbg(INFO_ZONE, "%s: AMPDU action %d called\n", __func__, action);
+
if (ssn != NULL)
seq_no = *ssn;

+ if (vif->type == NL80211_IFTYPE_AP) {
+ rsta = rsi_find_sta(common, sta->addr);
+ if (!rsta) {
+ rsi_dbg(ERR_ZONE, "No station mapped\n");
+ return 0;
+ }
+ sta_id = rsta->sta_id;
+ }
+
+ rsi_dbg(INFO_ZONE,
+ "%s: AMPDU action tid=%d ssn=0x%x, buf_size=%d sta_id=%d\n",
+ __func__, tid, seq_no, buf_size, sta_id);
+
switch (action) {
case IEEE80211_AMPDU_RX_START:
status = rsi_send_aggregation_params_frame(common,
tid,
seq_no,
buf_size,
- STA_RX_ADDBA_DONE);
+ STA_RX_ADDBA_DONE,
+ sta_id);
break;

case IEEE80211_AMPDU_RX_STOP:
@@ -898,11 +914,15 @@ static int rsi_mac80211_ampdu_action(struct ieee80211_hw *hw,
tid,
0,
buf_size,
- STA_RX_DELBA);
+ STA_RX_DELBA,
+ sta_id);
break;

case IEEE80211_AMPDU_TX_START:
- common->vif_info[ii].seq_start = seq_no;
+ if (vif->type == NL80211_IFTYPE_STATION)
+ common->vif_info[ii].seq_start = seq_no;
+ else if (vif->type == NL80211_IFTYPE_AP)
+ rsta->seq_start[tid] = seq_no;
ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
status = 0;
break;
@@ -914,18 +934,23 @@ static int rsi_mac80211_ampdu_action(struct ieee80211_hw *hw,
tid,
seq_no,
buf_size,
- STA_TX_DELBA);
+ STA_TX_DELBA,
+ sta_id);
if (!status)
ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
break;

case IEEE80211_AMPDU_TX_OPERATIONAL:
+ if (vif->type == NL80211_IFTYPE_STATION)
+ seq_start = common->vif_info[ii].seq_start;
+ else if (vif->type == NL80211_IFTYPE_AP)
+ seq_start = rsta->seq_start[tid];
status = rsi_send_aggregation_params_frame(common,
tid,
- common->vif_info[ii]
- .seq_start,
+ seq_start,
buf_size,
- STA_TX_ADDBA_DONE);
+ STA_TX_ADDBA_DONE,
+ sta_id);
break;

default:
diff --git a/drivers/net/wireless/rsi/rsi_91x_mgmt.c b/drivers/net/wireless/rsi/rsi_91x_mgmt.c
index 8762d13..2d3cae5 100644
--- a/drivers/net/wireless/rsi/rsi_91x_mgmt.c
+++ b/drivers/net/wireless/rsi/rsi_91x_mgmt.c
@@ -537,11 +537,11 @@ int rsi_send_aggregation_params_frame(struct rsi_common *common,
u16 tid,
u16 ssn,
u8 buf_size,
- u8 event)
+ u8 event,
+ u8 sta_id)
{
struct sk_buff *skb = NULL;
struct rsi_aggr_params *aggr_params;
- u8 peer_id = 0;
u16 frame_len = sizeof(struct rsi_aggr_params);

skb = dev_alloc_skb(frame_len);
@@ -561,7 +561,7 @@ int rsi_send_aggregation_params_frame(struct rsi_common *common,
aggr_params->desc_dword0.frame_type = AMPDU_IND;

aggr_params->aggr_params = tid & RSI_AGGR_PARAMS_TID_MASK;
- aggr_params->peer_id = peer_id;
+ aggr_params->peer_id = sta_id;
if (event == STA_TX_ADDBA_DONE) {
aggr_params->seq_start = cpu_to_le16(ssn);
aggr_params->baw_size = cpu_to_le16(buf_size);
diff --git a/drivers/net/wireless/rsi/rsi_mgmt.h b/drivers/net/wireless/rsi/rsi_mgmt.h
index c50153d..2d82733 100644
--- a/drivers/net/wireless/rsi/rsi_mgmt.h
+++ b/drivers/net/wireless/rsi/rsi_mgmt.h
@@ -609,7 +609,8 @@ int rsi_mgmt_pkt_recv(struct rsi_common *common, u8 *msg);
int rsi_set_vap_capabilities(struct rsi_common *common, enum opmode mode,
u8 *mac_addr, u8 vap_id, u8 vap_status);
int rsi_send_aggregation_params_frame(struct rsi_common *common, u16 tid,
- u16 ssn, u8 buf_size, u8 event);
+ u16 ssn, u8 buf_size, u8 event,
+ u8 sta_id);
int rsi_hal_load_key(struct rsi_common *common, u8 *data, u16 key_len,
u8 key_type, u8 key_id, u32 cipher);
int rsi_set_channel(struct rsi_common *common,
--
2.7.4

2017-08-16 13:17:43

by Amitkumar Karwar

[permalink] [raw]
Subject: [v2 01/11] rsi: advertise ap mode support

From: Prameela Rani Garnepudi <[email protected]>

AP mode support is advertised to cfg80211. Necessary wiphy
parameters are initialized.

Signed-off-by: Prameela Rani Garnepudi <[email protected]>
Signed-off-by: Amitkumar Karwar <[email protected]>
---
drivers/net/wireless/rsi/rsi_91x_mac80211.c | 28 +++++++++++++++++++++++++++-
drivers/net/wireless/rsi/rsi_main.h | 10 ++++++++++
2 files changed, 37 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/rsi/rsi_91x_mac80211.c b/drivers/net/wireless/rsi/rsi_91x_mac80211.c
index 210ad79..2da5493 100644
--- a/drivers/net/wireless/rsi/rsi_91x_mac80211.c
+++ b/drivers/net/wireless/rsi/rsi_91x_mac80211.c
@@ -122,6 +122,23 @@ const u16 rsi_mcsrates[8] = {
RSI_RATE_MCS4, RSI_RATE_MCS5, RSI_RATE_MCS6, RSI_RATE_MCS7
};

+static const u32 rsi_max_ap_stas[16] = {
+ 32, /* 1 - Wi-Fi alone */
+ 0, /* 2 */
+ 0, /* 3 */
+ 0, /* 4 - BT EDR alone */
+ 4, /* 5 - STA + BT EDR */
+ 32, /* 6 - AP + BT EDR */
+ 0, /* 7 */
+ 0, /* 8 - BT LE alone */
+ 4, /* 9 - STA + BE LE */
+ 0, /* 10 */
+ 0, /* 11 */
+ 0, /* 12 */
+ 1, /* 13 - STA + BT Dual */
+ 4, /* 14 - AP + BT Dual */
+};
+
/**
* rsi_is_cipher_wep() - This function determines if the cipher is WEP or not.
* @common: Pointer to the driver private structure.
@@ -1348,7 +1365,8 @@ int rsi_mac80211_attach(struct rsi_common *common)
SET_IEEE80211_PERM_ADDR(hw, common->mac_addr);
ether_addr_copy(hw->wiphy->addr_mask, addr_mask);

- wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
+ wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
+ BIT(NL80211_IFTYPE_AP);
wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
wiphy->retry_short = RETRY_SHORT;
wiphy->retry_long = RETRY_LONG;
@@ -1363,6 +1381,14 @@ int rsi_mac80211_attach(struct rsi_common *common)
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];
+ 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->flags = WIPHY_FLAG_REPORTS_OBSS;
+ wiphy->flags |= WIPHY_FLAG_AP_UAPSD;
+ wiphy->features |= NL80211_FEATURE_INACTIVITY_TIMER;
wiphy->reg_notifier = rsi_reg_notify;

wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST);
diff --git a/drivers/net/wireless/rsi/rsi_main.h b/drivers/net/wireless/rsi/rsi_main.h
index d05b5e0..0077888 100644
--- a/drivers/net/wireless/rsi/rsi_main.h
+++ b/drivers/net/wireless/rsi/rsi_main.h
@@ -21,6 +21,13 @@
#include <linux/skbuff.h>
#include <net/mac80211.h>

+struct rsi_sta {
+ struct ieee80211_sta *sta;
+ s16 sta_id;
+ u16 seq_start[IEEE80211_NUM_TIDS];
+ bool start_tx_aggr[IEEE80211_NUM_TIDS];
+};
+
struct rsi_hw;

#include "rsi_ps.h"
@@ -253,6 +260,9 @@ struct rsi_common {

u16 beacon_interval;
u8 dtim_cnt;
+
+ /* AP mode parameters */
+ int max_stations;
};

enum host_intf {
--
2.7.4

2017-08-16 13:18:18

by Amitkumar Karwar

[permalink] [raw]
Subject: [v2 07/11] rsi: data and managemet path changes for AP mode

From: Prameela Rani Garnepudi <[email protected]>

Station id needs to be get for data and management frames
to fill in the descruptor for AP mode. Few other changes
related to AP mode are covered here.

Signed-off-by: Prameela Rani Garnepudi <[email protected]>
Signed-off-by: Amitkumar Karwar <[email protected]>
---
drivers/net/wireless/rsi/rsi_91x_core.c | 55 ++++++++++++++++++++++------
drivers/net/wireless/rsi/rsi_91x_hal.c | 64 ++++++++++++++++++++++++---------
drivers/net/wireless/rsi/rsi_common.h | 1 +
drivers/net/wireless/rsi/rsi_hal.h | 2 +-
drivers/net/wireless/rsi/rsi_mgmt.h | 1 +
5 files changed, 96 insertions(+), 27 deletions(-)

diff --git a/drivers/net/wireless/rsi/rsi_91x_core.c b/drivers/net/wireless/rsi/rsi_91x_core.c
index 6cfda86..2b0516d 100644
--- a/drivers/net/wireless/rsi/rsi_91x_core.c
+++ b/drivers/net/wireless/rsi/rsi_91x_core.c
@@ -320,6 +320,20 @@ void rsi_core_qos_processor(struct rsi_common *common)
}
}

+struct rsi_sta *rsi_find_sta(struct rsi_common *common, u8 *mac_addr)
+{
+ int i;
+
+ for (i = 0; i < common->max_stations; i++) {
+ if (!common->stations[i].sta)
+ continue;
+ if (!(memcmp(common->stations[i].sta->addr,
+ mac_addr, ETH_ALEN)))
+ return &common->stations[i];
+ }
+ return NULL;
+}
+
/**
* rsi_core_xmit() - This function transmits the packets received from mac80211
* @common: Pointer to the driver private structure.
@@ -332,39 +346,60 @@ void rsi_core_xmit(struct rsi_common *common, struct sk_buff *skb)
struct rsi_hw *adapter = common->priv;
struct ieee80211_tx_info *info;
struct skb_info *tx_params;
- struct ieee80211_hdr *tmp_hdr = NULL;
+ struct ieee80211_hdr *wh;
+ struct ieee80211_vif *vif = adapter->vifs[0];
u8 q_num, tid = 0;
+ struct rsi_sta *rsta = NULL;

if ((!skb) || (!skb->len)) {
rsi_dbg(ERR_ZONE, "%s: Null skb/zero Length packet\n",
__func__);
goto xmit_fail;
}
- info = IEEE80211_SKB_CB(skb);
- tx_params = (struct skb_info *)info->driver_data;
- tmp_hdr = (struct ieee80211_hdr *)&skb->data[0];
-
if (common->fsm_state != FSM_MAC_INIT_DONE) {
rsi_dbg(ERR_ZONE, "%s: FSM state not open\n", __func__);
goto xmit_fail;
}

- if ((ieee80211_is_mgmt(tmp_hdr->frame_control)) ||
- (ieee80211_is_ctl(tmp_hdr->frame_control)) ||
- (ieee80211_is_qos_nullfunc(tmp_hdr->frame_control))) {
+ info = IEEE80211_SKB_CB(skb);
+ tx_params = (struct skb_info *)info->driver_data;
+ wh = (struct ieee80211_hdr *)&skb->data[0];
+ tx_params->sta_id = 0;
+
+ if ((ieee80211_is_mgmt(wh->frame_control)) ||
+ (ieee80211_is_ctl(wh->frame_control)) ||
+ (ieee80211_is_qos_nullfunc(wh->frame_control))) {
q_num = MGMT_SOFT_Q;
skb->priority = q_num;
} else {
- if (ieee80211_is_data_qos(tmp_hdr->frame_control)) {
+ if (ieee80211_is_data_qos(wh->frame_control)) {
tid = (skb->data[24] & IEEE80211_QOS_TID);
skb->priority = TID_TO_WME_AC(tid);
} else {
tid = IEEE80211_NONQOS_TID;
skb->priority = BE_Q;
}
+
q_num = skb->priority;
tx_params->tid = tid;
- tx_params->sta_id = 0;
+
+ if ((vif->type == NL80211_IFTYPE_AP) &&
+ (!is_broadcast_ether_addr(wh->addr1)) &&
+ (!is_multicast_ether_addr(wh->addr1))) {
+ rsta = rsi_find_sta(common, wh->addr1);
+ if (!rsta)
+ goto xmit_fail;
+ tx_params->sta_id = rsta->sta_id;
+ }
+
+ if (rsta) {
+ /* Start aggregation if not done for this tid */
+ if (!rsta->start_tx_aggr[tid]) {
+ rsta->start_tx_aggr[tid] = true;
+ ieee80211_start_tx_ba_session(rsta->sta,
+ tid, 0);
+ }
+ }
}

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 1ed7332..070dfd6 100644
--- a/drivers/net/wireless/rsi/rsi_91x_hal.c
+++ b/drivers/net/wireless/rsi/rsi_91x_hal.c
@@ -18,6 +18,7 @@
#include "rsi_mgmt.h"
#include "rsi_hal.h"
#include "rsi_sdio.h"
+#include "rsi_common.h"

/* FLASH Firmware */
static struct ta_metadata metadata_flash_content[] = {
@@ -41,7 +42,7 @@ static int rsi_prepare_mgmt_desc(struct rsi_common *common, struct sk_buff *skb)
struct ieee80211_hdr *wh = NULL;
struct ieee80211_tx_info *info;
struct ieee80211_conf *conf = &adapter->hw->conf;
- struct ieee80211_vif *vif = NULL;
+ struct ieee80211_vif *vif = adapter->vifs[0];
struct rsi_mgmt_desc *mgmt_desc;
struct skb_info *tx_params;
struct ieee80211_bss_conf *bss = NULL;
@@ -49,6 +50,11 @@ static int rsi_prepare_mgmt_desc(struct rsi_common *common, struct sk_buff *skb)
u8 header_size;
u32 dword_align_bytes = 0;

+ if (skb->len > MAX_MGMT_PKT_SIZE) {
+ rsi_dbg(INFO_ZONE, "%s: Dropping mgmt pkt > 512\n", __func__);
+ return -EINVAL;
+ }
+
info = IEEE80211_SKB_CB(skb);
tx_params = (struct skb_info *)info->driver_data;

@@ -74,15 +80,10 @@ static int rsi_prepare_mgmt_desc(struct rsi_common *common, struct sk_buff *skb)
memset(&skb->data[0], 0, header_size);
bss = &info->control.vif->bss_conf;
wh = (struct ieee80211_hdr *)&skb->data[header_size];
- vif = adapter->vifs[0];

mgmt_desc = (struct rsi_mgmt_desc *)skb->data;
xtend_desc = (struct xtended_desc *)&skb->data[FRAME_DESC_SZ];

- if (skb->len > MAX_MGMT_PKT_SIZE) {
- rsi_dbg(INFO_ZONE, "%s: Dropping mgmt pkt > 512\n", __func__);
- return -EINVAL;
- }
rsi_set_len_qno(&mgmt_desc->len_qno, (skb->len - FRAME_DESC_SZ),
RSI_WIFI_MGMT_Q);
mgmt_desc->frame_type = TX_DOT11_MGMT;
@@ -113,6 +114,22 @@ static int rsi_prepare_mgmt_desc(struct rsi_common *common, struct sk_buff *skb)
}
}

+ if (ieee80211_is_probe_resp(wh->frame_control)) {
+ mgmt_desc->misc_flags |= (RSI_ADD_DELTA_TSF_VAP_ID |
+ RSI_FETCH_RETRY_CNT_FRM_HST);
+#define PROBE_RESP_RETRY_CNT 3
+ xtend_desc->retry_cnt = PROBE_RESP_RETRY_CNT;
+ }
+
+ if ((vif->type == NL80211_IFTYPE_AP) &&
+ (ieee80211_is_action(wh->frame_control))) {
+ struct rsi_sta *rsta = rsi_find_sta(common, wh->addr1);
+
+ if (rsta)
+ mgmt_desc->sta_id = tx_params->sta_id;
+ else
+ return -EINVAL;
+ }
return 0;
}

@@ -157,7 +174,7 @@ static int rsi_prepare_data_desc(struct rsi_common *common, struct sk_buff *skb)

xtend_desc = (struct xtended_desc *)&skb->data[FRAME_DESC_SZ];
wh = (struct ieee80211_hdr *)&skb->data[header_size];
- seq_num = (le16_to_cpu(wh->seq_ctrl) >> 4);
+ seq_num = IEEE80211_SEQ_TO_SN(le16_to_cpu(wh->seq_ctrl));
vif = adapter->vifs[0];

data_desc->xtend_desc_size = header_size - FRAME_DESC_SZ;
@@ -191,12 +208,11 @@ static int rsi_prepare_data_desc(struct rsi_common *common, struct sk_buff *skb)
if (conf_is_ht40(&common->priv->hw->conf))
data_desc->bbp_info = cpu_to_le16(FULL40M_ENABLE);

- if (common->vif_info[0].sgi) {
- if (common->min_rate & 0x100) /* Only MCS rates */
- data_desc->rate_info |=
- cpu_to_le16(ENABLE_SHORTGI_RATE);
+ if ((common->vif_info[0].sgi) && (common->min_rate & 0x100)) {
+ /* Only MCS rates */
+ data_desc->rate_info |=
+ cpu_to_le16(ENABLE_SHORTGI_RATE);
}
-
}

if (skb->protocol == cpu_to_be16(ETH_P_PAE)) {
@@ -223,7 +239,17 @@ static int rsi_prepare_data_desc(struct rsi_common *common, struct sk_buff *skb)
data_desc->frame_info = cpu_to_le16(RATE_INFO_ENABLE);
data_desc->frame_info |= cpu_to_le16(RSI_BROADCAST_PKT);
data_desc->sta_id = vap_id;
+
+ if (vif->type == NL80211_IFTYPE_AP) {
+ if (common->band == NL80211_BAND_5GHZ)
+ data_desc->rate_info = cpu_to_le16(RSI_RATE_6);
+ else
+ data_desc->rate_info = cpu_to_le16(RSI_RATE_1);
+ }
}
+ if ((vif->type == NL80211_IFTYPE_AP) &&
+ (ieee80211_has_moredata(wh->frame_control)))
+ data_desc->frame_info |= cpu_to_le16(MORE_DATA_PRESENT);

return 0;
}
@@ -232,17 +258,23 @@ static int rsi_prepare_data_desc(struct rsi_common *common, struct sk_buff *skb)
int rsi_send_data_pkt(struct rsi_common *common, struct sk_buff *skb)
{
struct rsi_hw *adapter = common->priv;
+ struct ieee80211_vif *vif = adapter->vifs[0];
struct ieee80211_tx_info *info;
struct ieee80211_bss_conf *bss;
- int status = -EIO;
+ int status = -EINVAL;
+
+ if (!skb)
+ return 0;
+ if (common->iface_down)
+ goto err;

info = IEEE80211_SKB_CB(skb);
+ if (!info->control.vif)
+ goto err;
bss = &info->control.vif->bss_conf;

- if (!bss->assoc) {
- status = -EINVAL;
+ if ((vif->type == NL80211_IFTYPE_STATION) && (!bss->assoc))
goto err;
- }

status = rsi_prepare_data_desc(common, skb);
if (status)
diff --git a/drivers/net/wireless/rsi/rsi_common.h b/drivers/net/wireless/rsi/rsi_common.h
index 4434969..e579d69 100644
--- a/drivers/net/wireless/rsi/rsi_common.h
+++ b/drivers/net/wireless/rsi/rsi_common.h
@@ -83,4 +83,5 @@ u16 rsi_get_connected_channel(struct rsi_hw *adapter);
struct rsi_hw *rsi_91x_init(void);
void rsi_91x_deinit(struct rsi_hw *adapter);
int rsi_read_pkt(struct rsi_common *common, s32 rcv_pkt_len);
+struct rsi_sta *rsi_find_sta(struct rsi_common *common, u8 *mac_addr);
#endif
diff --git a/drivers/net/wireless/rsi/rsi_hal.h b/drivers/net/wireless/rsi/rsi_hal.h
index 297f4ce..7c14505 100644
--- a/drivers/net/wireless/rsi/rsi_hal.h
+++ b/drivers/net/wireless/rsi/rsi_hal.h
@@ -126,7 +126,7 @@ struct rsi_mgmt_desc {
__le16 bbp_info;
__le16 seq_ctrl;
u8 reserved2;
- u8 vap_info;
+ u8 sta_id;
} __packed;

struct rsi_data_desc {
diff --git a/drivers/net/wireless/rsi/rsi_mgmt.h b/drivers/net/wireless/rsi/rsi_mgmt.h
index a2e377f..9c59250 100644
--- a/drivers/net/wireless/rsi/rsi_mgmt.h
+++ b/drivers/net/wireless/rsi/rsi_mgmt.h
@@ -63,6 +63,7 @@
#define BBP_REG_WRITE 0
#define RF_RESET_ENABLE BIT(3)
#define RATE_INFO_ENABLE BIT(0)
+#define MORE_DATA_PRESENT BIT(1)
#define RSI_BROADCAST_PKT BIT(9)
#define RSI_DESC_REQUIRE_CFM_TO_HOST BIT(2)
#define RSI_ADD_DELTA_TSF_VAP_ID BIT(3)
--
2.7.4

2017-08-16 13:18:13

by Amitkumar Karwar

[permalink] [raw]
Subject: [v2 06/11] rsi: handle station disconnection in AP mode

From: Prameela Rani Garnepudi <[email protected]>

When sta_remove of mac80211 is called, driver iterates through
list of existing stations to get the station id. Then peer notify
is prepared and send to firmare.

Signed-off-by: Prameela Rani Garnepudi <[email protected]>
Signed-off-by: Amitkumar Karwar <[email protected]>
---
drivers/net/wireless/rsi/rsi_91x_mac80211.c | 56 +++++++++++++++++++++++------
1 file changed, 45 insertions(+), 11 deletions(-)

diff --git a/drivers/net/wireless/rsi/rsi_91x_mac80211.c b/drivers/net/wireless/rsi/rsi_91x_mac80211.c
index b1c0849..be10d50 100644
--- a/drivers/net/wireless/rsi/rsi_91x_mac80211.c
+++ b/drivers/net/wireless/rsi/rsi_91x_mac80211.c
@@ -1254,21 +1254,55 @@ static int rsi_mac80211_sta_remove(struct ieee80211_hw *hw,
{
struct rsi_hw *adapter = hw->priv;
struct rsi_common *common = adapter->priv;
+ struct ieee80211_bss_conf *bss = &vif->bss_conf;
+ struct rsi_sta *rsta;
+
+ rsi_dbg(INFO_ZONE, "Station Remove: %pM\n", sta->addr);

mutex_lock(&common->mutex);

- /* Resetting all the fields to default values */
- common->bitrate_mask[NL80211_BAND_2GHZ] = 0;
- common->bitrate_mask[NL80211_BAND_5GHZ] = 0;
- common->min_rate = 0xffff;
- common->vif_info[0].is_ht = false;
- common->vif_info[0].sgi = false;
- common->vif_info[0].seq_start = 0;
- common->secinfo.ptk_cipher = 0;
- common->secinfo.gtk_cipher = 0;
+ if (vif->type == NL80211_IFTYPE_AP) {
+ u8 sta_idx, cnt;

- rsi_send_rx_filter_frame(common, 0);
-
+ /* Send peer notify to device */
+ rsi_dbg(INFO_ZONE, "Indicate bss status to device\n");
+ for (sta_idx = 0; sta_idx < common->max_stations; sta_idx++) {
+ rsta = &common->stations[sta_idx];
+
+ if (!rsta->sta)
+ continue;
+ if (!memcmp(rsta->sta->addr, sta->addr, ETH_ALEN)) {
+ rsi_inform_bss_status(common, AP_OPMODE, 0,
+ sta->addr, sta->wme,
+ sta->aid, sta, sta_idx);
+ rsta->sta = NULL;
+ rsta->sta_id = -1;
+ for (cnt = 0; cnt < IEEE80211_NUM_TIDS; cnt++)
+ rsta->start_tx_aggr[cnt] = false;
+ if (common->num_stations > 0)
+ common->num_stations--;
+ break;
+ }
+ }
+ if (sta_idx >= common->max_stations)
+ rsi_dbg(ERR_ZONE, "%s: No station found\n", __func__);
+ }
+
+ if (vif->type == NL80211_IFTYPE_STATION) {
+ /* Resetting all the fields to default values */
+ memcpy((u8 *)bss->bssid, (u8 *)sta->addr, ETH_ALEN);
+ bss->qos = sta->wme;
+ common->bitrate_mask[NL80211_BAND_2GHZ] = 0;
+ common->bitrate_mask[NL80211_BAND_5GHZ] = 0;
+ common->min_rate = 0xffff;
+ common->vif_info[0].is_ht = false;
+ common->vif_info[0].sgi = false;
+ common->vif_info[0].seq_start = 0;
+ common->secinfo.ptk_cipher = 0;
+ common->secinfo.gtk_cipher = 0;
+ if (!common->iface_down)
+ rsi_send_rx_filter_frame(common, 0);
+ }
mutex_unlock(&common->mutex);

return 0;
--
2.7.4

2017-08-16 13:17:49

by Amitkumar Karwar

[permalink] [raw]
Subject: [v2 02/11] rsi: add interface changes for ap mode

From: Prameela Rani Garnepudi <[email protected]>

AP mode is handled in add_interface callback of mac80211.
Also for AP mode, sending rx filter frame to disallow beacons
to host is added. Station structures are initialized to NULL.

Signed-off-by: Prameela Rani Garnepudi <[email protected]>
Signed-off-by: Amitkumar Karwar <[email protected]>
---
drivers/net/wireless/rsi/rsi_91x_mac80211.c | 43 +++++++++++++++++++++++------
drivers/net/wireless/rsi/rsi_91x_mgmt.c | 5 ++--
drivers/net/wireless/rsi/rsi_main.h | 3 ++
drivers/net/wireless/rsi/rsi_mgmt.h | 6 ++--
4 files changed, 44 insertions(+), 13 deletions(-)

diff --git a/drivers/net/wireless/rsi/rsi_91x_mac80211.c b/drivers/net/wireless/rsi/rsi_91x_mac80211.c
index 2da5493..edcba56 100644
--- a/drivers/net/wireless/rsi/rsi_91x_mac80211.c
+++ b/drivers/net/wireless/rsi/rsi_91x_mac80211.c
@@ -342,25 +342,51 @@ static int rsi_mac80211_add_interface(struct ieee80211_hw *hw,
{
struct rsi_hw *adapter = hw->priv;
struct rsi_common *common = adapter->priv;
+ enum opmode intf_mode;
int ret = -EOPNOTSUPP;

vif->driver_flags |= IEEE80211_VIF_SUPPORTS_UAPSD;
mutex_lock(&common->mutex);
+
+ if (adapter->sc_nvifs > 1) {
+ mutex_unlock(&common->mutex);
+ return -EOPNOTSUPP;
+ }
+
switch (vif->type) {
case NL80211_IFTYPE_STATION:
- if (!adapter->sc_nvifs) {
- ++adapter->sc_nvifs;
- adapter->vifs[0] = vif;
- ret = rsi_set_vap_capabilities(common,
- STA_OPMODE,
- VAP_ADD);
- }
+ rsi_dbg(INFO_ZONE, "Station Mode");
+ intf_mode = STA_OPMODE;
+ break;
+ case NL80211_IFTYPE_AP:
+ rsi_dbg(INFO_ZONE, "AP Mode");
+ intf_mode = AP_OPMODE;
break;
default:
rsi_dbg(ERR_ZONE,
"%s: Interface type %d not supported\n", __func__,
vif->type);
+ goto out;
}
+
+ adapter->vifs[adapter->sc_nvifs++] = vif;
+ ret = rsi_set_vap_capabilities(common, intf_mode, common->mac_addr,
+ 0, VAP_ADD);
+ if (ret) {
+ rsi_dbg(ERR_ZONE, "Failed to set VAP capabilities\n");
+ goto out;
+ }
+
+ if (vif->type == NL80211_IFTYPE_AP) {
+ int i;
+
+ rsi_send_rx_filter_frame(common, DISALLOW_BEACONS);
+ common->min_rate = RSI_RATE_AUTO;
+ for (i = 0; i < common->max_stations; i++)
+ common->stations[i].sta = NULL;
+ }
+
+out:
mutex_unlock(&common->mutex);

return ret;
@@ -383,7 +409,8 @@ static void rsi_mac80211_remove_interface(struct ieee80211_hw *hw,
mutex_lock(&common->mutex);
if (vif->type == NL80211_IFTYPE_STATION) {
adapter->sc_nvifs--;
- rsi_set_vap_capabilities(common, STA_OPMODE, VAP_DELETE);
+ rsi_set_vap_capabilities(common, STA_OPMODE, vif->addr,
+ 0, VAP_DELETE);
}

if (!memcmp(adapter->vifs[0], vif, sizeof(struct ieee80211_vif)))
diff --git a/drivers/net/wireless/rsi/rsi_91x_mgmt.c b/drivers/net/wireless/rsi/rsi_91x_mgmt.c
index f93499d0..233a418 100644
--- a/drivers/net/wireless/rsi/rsi_91x_mgmt.c
+++ b/drivers/net/wireless/rsi/rsi_91x_mgmt.c
@@ -624,6 +624,8 @@ static int rsi_program_bb_rf(struct rsi_common *common)
*/
int rsi_set_vap_capabilities(struct rsi_common *common,
enum opmode mode,
+ u8 *mac_addr,
+ u8 vap_id,
u8 vap_status)
{
struct sk_buff *skb = NULL;
@@ -632,7 +634,6 @@ int rsi_set_vap_capabilities(struct rsi_common *common,
struct ieee80211_hw *hw = adapter->hw;
struct ieee80211_conf *conf = &hw->conf;
u16 frame_len = sizeof(struct rsi_vap_caps);
- u16 vap_id = 0;

rsi_dbg(MGMT_TX_ZONE, "%s: Sending VAP capabilities frame\n", __func__);

@@ -656,7 +657,7 @@ int rsi_set_vap_capabilities(struct rsi_common *common,
vap_caps->radioid_macid = ((common->mac_id & 0xf) << 4) |
(common->radio_id & 0xf);

- memcpy(vap_caps->mac_addr, common->mac_addr, IEEE80211_ADDR_LEN);
+ memcpy(vap_caps->mac_addr, mac_addr, IEEE80211_ADDR_LEN);
vap_caps->keep_alive_period = cpu_to_le16(90);
vap_caps->frag_threshold = cpu_to_le16(IEEE80211_MAX_FRAG_THRESHOLD);

diff --git a/drivers/net/wireless/rsi/rsi_main.h b/drivers/net/wireless/rsi/rsi_main.h
index 0077888..9f5f33f 100644
--- a/drivers/net/wireless/rsi/rsi_main.h
+++ b/drivers/net/wireless/rsi/rsi_main.h
@@ -90,6 +90,7 @@ extern __printf(2, 3) void rsi_dbg(u32 zone, const char *fmt, ...);
#define IEEE80211_MGMT_FRAME 0x00
#define IEEE80211_CTL_FRAME 0x04

+#define RSI_MAX_ASSOC_STAS 32
#define IEEE80211_QOS_TID 0x0f
#define IEEE80211_NONQOS_TID 16

@@ -262,6 +263,8 @@ struct rsi_common {
u8 dtim_cnt;

/* AP mode parameters */
+ struct rsi_sta stations[RSI_MAX_ASSOC_STAS + 1];
+ int num_stations;
int max_stations;
};

diff --git a/drivers/net/wireless/rsi/rsi_mgmt.h b/drivers/net/wireless/rsi/rsi_mgmt.h
index 201a465..9093ba6 100644
--- a/drivers/net/wireless/rsi/rsi_mgmt.h
+++ b/drivers/net/wireless/rsi/rsi_mgmt.h
@@ -188,8 +188,8 @@
IEEE80211_WMM_IE_STA_QOSINFO_AC_BK)

enum opmode {
- STA_OPMODE = 1,
- AP_OPMODE = 2
+ AP_OPMODE = 0,
+ STA_OPMODE,
};

enum vap_status {
@@ -591,7 +591,7 @@ static inline void rsi_set_len_qno(__le16 *addr, u16 len, u8 qno)

int rsi_mgmt_pkt_recv(struct rsi_common *common, u8 *msg);
int rsi_set_vap_capabilities(struct rsi_common *common, enum opmode mode,
- u8 vap_status);
+ u8 *mac_addr, u8 vap_id, u8 vap_status);
int rsi_send_aggregation_params_frame(struct rsi_common *common, u16 tid,
u16 ssn, u8 buf_size, u8 event);
int rsi_hal_load_key(struct rsi_common *common, u8 *data, u16 key_len,
--
2.7.4

2017-08-16 13:18:28

by Amitkumar Karwar

[permalink] [raw]
Subject: [v2 09/11] rsi: update tx auto rate command frame for AP mode

From: Prameela Rani Garnepudi <[email protected]>

Auto rate frame is sent to firmware when a new station is
connected. Station id and station's ht capabilities are updated
in auto rate command frame.

Signed-off-by: Prameela Rani Garnepudi <[email protected]>
Signed-off-by: Amitkumar Karwar <[email protected]>
---
drivers/net/wireless/rsi/rsi_91x_mgmt.c | 44 +++++++++++++++++++++++++--------
1 file changed, 34 insertions(+), 10 deletions(-)

diff --git a/drivers/net/wireless/rsi/rsi_91x_mgmt.c b/drivers/net/wireless/rsi/rsi_91x_mgmt.c
index c5d48cd..8762d13 100644
--- a/drivers/net/wireless/rsi/rsi_91x_mgmt.c
+++ b/drivers/net/wireless/rsi/rsi_91x_mgmt.c
@@ -1152,8 +1152,11 @@ static bool rsi_map_rates(u16 rate, int *offset)
*
* Return: 0 on success, corresponding error code on failure.
*/
-static int rsi_send_auto_rate_request(struct rsi_common *common)
+static int rsi_send_auto_rate_request(struct rsi_common *common,
+ struct ieee80211_sta *sta,
+ u16 sta_id)
{
+ struct ieee80211_vif *vif = common->priv->vifs[0];
struct sk_buff *skb;
struct rsi_auto_rate *auto_rate;
int ii = 0, jj = 0, kk = 0;
@@ -1161,11 +1164,14 @@ static int rsi_send_auto_rate_request(struct rsi_common *common)
u8 band = hw->conf.chandef.chan->band;
u8 num_supported_rates = 0;
u8 rate_table_offset, rate_offset = 0;
- u32 rate_bitmap = common->bitrate_mask[band];
-
+ u32 rate_bitmap;
u16 *selected_rates, min_rate;
+ bool is_ht = false, is_sgi = false;
u16 frame_len = sizeof(struct rsi_auto_rate);

+ rsi_dbg(MGMT_TX_ZONE,
+ "%s: Sending auto rate request frame\n", __func__);
+
skb = dev_alloc_skb(frame_len);
if (!skb) {
rsi_dbg(ERR_ZONE, "%s: Failed in allocation of skb\n",
@@ -1193,12 +1199,31 @@ static int rsi_send_auto_rate_request(struct rsi_common *common)

if (common->channel_width == BW_40MHZ)
auto_rate->desc.desc_dword3.qid_tid = BW_40MHZ;
+ auto_rate->desc.desc_dword3.sta_id = sta_id;
+
+ if (vif->type == NL80211_IFTYPE_STATION) {
+ rate_bitmap = common->bitrate_mask[band];
+ is_ht = common->vif_info[0].is_ht;
+ is_sgi = common->vif_info[0].sgi;
+ } else {
+ rate_bitmap = sta->supp_rates[band];
+ is_ht = sta->ht_cap.ht_supported;
+ if ((sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) ||
+ (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40))
+ is_sgi = true;
+ }

if (band == NL80211_BAND_2GHZ) {
- min_rate = RSI_RATE_1;
+ if ((rate_bitmap == 0) && (is_ht))
+ min_rate = RSI_RATE_MCS0;
+ else
+ min_rate = RSI_RATE_1;
rate_table_offset = 0;
} else {
- min_rate = RSI_RATE_6;
+ if ((rate_bitmap == 0) && (is_ht))
+ min_rate = RSI_RATE_MCS0;
+ else
+ min_rate = RSI_RATE_6;
rate_table_offset = 4;
}

@@ -1212,7 +1237,7 @@ static int rsi_send_auto_rate_request(struct rsi_common *common)
}
num_supported_rates = jj;

- if (common->vif_info[0].is_ht) {
+ if (is_ht) {
for (ii = 0; ii < ARRAY_SIZE(mcs); ii++)
selected_rates[jj++] = mcs[ii];
num_supported_rates += ARRAY_SIZE(mcs);
@@ -1233,11 +1258,10 @@ static int rsi_send_auto_rate_request(struct rsi_common *common)
}

/* loading HT rates in the bottom half of the auto rate table */
- if (common->vif_info[0].is_ht) {
+ if (is_ht) {
for (ii = rate_offset, kk = ARRAY_SIZE(rsi_mcsrates) - 1;
ii < rate_offset + 2 * ARRAY_SIZE(rsi_mcsrates); ii++) {
- if (common->vif_info[0].sgi ||
- conf_is_ht40(&common->priv->hw->conf))
+ if (is_sgi || conf_is_ht40(&common->priv->hw->conf))
auto_rate->supported_rates[ii++] =
cpu_to_le16(rsi_mcsrates[kk] | BIT(9));
else
@@ -1300,7 +1324,7 @@ void rsi_inform_bss_status(struct rsi_common *common,
qos_enable,
aid, sta_id);
if (common->min_rate == 0xffff)
- rsi_send_auto_rate_request(common);
+ rsi_send_auto_rate_request(common, sta, sta_id);
if (opmode == STA_OPMODE) {
if (!rsi_send_block_unblock_frame(common, false))
common->hw_data_qs_blocked = false;
--
2.7.4

2017-08-16 13:18:38

by Amitkumar Karwar

[permalink] [raw]
Subject: [v2 11/11] rsi: security enhancements for AP mode

From: Prameela Rani Garnepudi <[email protected]>

Station id should be set in load key frame configured to device.
For WEP mode, key is configured once from mac80211. This key is
saved and configured to device every time a station is connected.

Signed-off-by: Prameela Rani Garnepudi <[email protected]>
---
drivers/net/wireless/rsi/rsi_91x_mac80211.c | 60 +++++++++++++++++++++--------
drivers/net/wireless/rsi/rsi_91x_mgmt.c | 10 ++++-
drivers/net/wireless/rsi/rsi_main.h | 1 +
drivers/net/wireless/rsi/rsi_mgmt.h | 3 +-
4 files changed, 56 insertions(+), 18 deletions(-)

diff --git a/drivers/net/wireless/rsi/rsi_91x_mac80211.c b/drivers/net/wireless/rsi/rsi_91x_mac80211.c
index f2cb61f..8b983d0 100644
--- a/drivers/net/wireless/rsi/rsi_91x_mac80211.c
+++ b/drivers/net/wireless/rsi/rsi_91x_mac80211.c
@@ -758,11 +758,14 @@ static int rsi_mac80211_conf_tx(struct ieee80211_hw *hw,
*/
static int rsi_hal_key_config(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
- struct ieee80211_key_conf *key)
+ struct ieee80211_key_conf *key,
+ struct ieee80211_sta *sta)
{
struct rsi_hw *adapter = hw->priv;
+ struct rsi_sta *rsta = NULL;
int status;
u8 key_type;
+ s16 sta_id = 0;

if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE)
key_type = RSI_PAIRWISE_KEY;
@@ -772,23 +775,35 @@ static int rsi_hal_key_config(struct ieee80211_hw *hw,
rsi_dbg(ERR_ZONE, "%s: Cipher 0x%x key_type: %d key_len: %d\n",
__func__, key->cipher, key_type, key->keylen);

- if ((key->cipher == WLAN_CIPHER_SUITE_WEP104) ||
- (key->cipher == WLAN_CIPHER_SUITE_WEP40)) {
- status = rsi_hal_load_key(adapter->priv,
- key->key,
- key->keylen,
- RSI_PAIRWISE_KEY,
- key->keyidx,
- key->cipher);
- if (status)
- return status;
+ if (vif->type == NL80211_IFTYPE_AP) {
+ if (sta) {
+ rsta = rsi_find_sta(adapter->priv, sta->addr);
+ if (rsta)
+ sta_id = rsta->sta_id;
+ }
+ adapter->priv->key = key;
+ } else {
+ if ((key->cipher == WLAN_CIPHER_SUITE_WEP104) ||
+ (key->cipher == WLAN_CIPHER_SUITE_WEP40)) {
+ status = rsi_hal_load_key(adapter->priv,
+ key->key,
+ key->keylen,
+ RSI_PAIRWISE_KEY,
+ key->keyidx,
+ key->cipher,
+ sta_id);
+ if (status)
+ return status;
+ }
}
+
return rsi_hal_load_key(adapter->priv,
key->key,
key->keylen,
key_type,
key->keyidx,
- key->cipher);
+ key->cipher,
+ sta_id);
}

/**
@@ -816,7 +831,7 @@ static int rsi_mac80211_set_key(struct ieee80211_hw *hw,
switch (cmd) {
case SET_KEY:
secinfo->security_enable = true;
- status = rsi_hal_key_config(hw, vif, key);
+ status = rsi_hal_key_config(hw, vif, key, sta);
if (status) {
mutex_unlock(&common->mutex);
return status;
@@ -834,10 +849,11 @@ static int rsi_mac80211_set_key(struct ieee80211_hw *hw,
break;

case DISABLE_KEY:
- secinfo->security_enable = false;
+ if (vif->type == NL80211_IFTYPE_STATION)
+ secinfo->security_enable = false;
rsi_dbg(ERR_ZONE, "%s: RSI del key\n", __func__);
memset(key, 0, sizeof(struct ieee80211_key_conf));
- status = rsi_hal_key_config(hw, vif, key);
+ status = rsi_hal_key_config(hw, vif, key, sta);
break;

default:
@@ -1242,6 +1258,20 @@ static int rsi_mac80211_sta_add(struct ieee80211_hw *hw,
rsi_inform_bss_status(common, AP_OPMODE, 1, sta->addr,
sta->wme, sta->aid, sta, sta_idx);

+ if (common->key) {
+ struct ieee80211_key_conf *key = common->key;
+
+ if ((key->cipher == WLAN_CIPHER_SUITE_WEP104) ||
+ (key->cipher == WLAN_CIPHER_SUITE_WEP40))
+ rsi_hal_load_key(adapter->priv,
+ key->key,
+ key->keylen,
+ RSI_PAIRWISE_KEY,
+ key->keyidx,
+ key->cipher,
+ sta_idx);
+ }
+
common->num_stations++;
}
}
diff --git a/drivers/net/wireless/rsi/rsi_91x_mgmt.c b/drivers/net/wireless/rsi/rsi_91x_mgmt.c
index 2d3cae5..f7b550f 100644
--- a/drivers/net/wireless/rsi/rsi_91x_mgmt.c
+++ b/drivers/net/wireless/rsi/rsi_91x_mgmt.c
@@ -715,8 +715,10 @@ int rsi_hal_load_key(struct rsi_common *common,
u16 key_len,
u8 key_type,
u8 key_id,
- u32 cipher)
+ u32 cipher,
+ s16 sta_id)
{
+ struct ieee80211_vif *vif = common->priv->vifs[0];
struct sk_buff *skb = NULL;
struct rsi_set_key *set_key;
u16 key_descriptor = 0;
@@ -734,8 +736,11 @@ int rsi_hal_load_key(struct rsi_common *common,
memset(skb->data, 0, frame_len);
set_key = (struct rsi_set_key *)skb->data;

- if (key_type == RSI_GROUP_KEY)
+ if (key_type == RSI_GROUP_KEY) {
key_descriptor = RSI_KEY_TYPE_BROADCAST;
+ if (vif->type == NL80211_IFTYPE_AP)
+ key_descriptor |= RSI_KEY_MODE_AP;
+ }
if ((cipher == WLAN_CIPHER_SUITE_WEP40) ||
(cipher == WLAN_CIPHER_SUITE_WEP104)) {
key_id = 0;
@@ -754,6 +759,7 @@ int rsi_hal_load_key(struct rsi_common *common,
(frame_len - FRAME_DESC_SZ), RSI_WIFI_MGMT_Q);
set_key->desc_dword0.frame_type = SET_KEY_REQ;
set_key->key_desc = cpu_to_le16(key_descriptor);
+ set_key->sta_id = sta_id;

if (data) {
if ((cipher == WLAN_CIPHER_SUITE_WEP40) ||
diff --git a/drivers/net/wireless/rsi/rsi_main.h b/drivers/net/wireless/rsi/rsi_main.h
index 169e2f9..2c18dde 100644
--- a/drivers/net/wireless/rsi/rsi_main.h
+++ b/drivers/net/wireless/rsi/rsi_main.h
@@ -269,6 +269,7 @@ struct rsi_common {
struct rsi_sta stations[RSI_MAX_ASSOC_STAS + 1];
int num_stations;
int max_stations;
+ struct ieee80211_key_conf *key;
};

enum host_intf {
diff --git a/drivers/net/wireless/rsi/rsi_mgmt.h b/drivers/net/wireless/rsi/rsi_mgmt.h
index 2d82733..c6e1fa6 100644
--- a/drivers/net/wireless/rsi/rsi_mgmt.h
+++ b/drivers/net/wireless/rsi/rsi_mgmt.h
@@ -409,6 +409,7 @@ struct rsi_dynamic_s {
#define RSI_WEP_KEY_104 BIT(3)
#define RSI_CIPHER_WPA BIT(4)
#define RSI_CIPHER_TKIP BIT(5)
+#define RSI_KEY_MODE_AP BIT(7)
#define RSI_PROTECT_DATA_FRAMES BIT(13)
#define RSI_KEY_ID_MASK 0xC0
#define RSI_KEY_ID_OFFSET 14
@@ -612,7 +613,7 @@ int rsi_send_aggregation_params_frame(struct rsi_common *common, u16 tid,
u16 ssn, u8 buf_size, u8 event,
u8 sta_id);
int rsi_hal_load_key(struct rsi_common *common, u8 *data, u16 key_len,
- u8 key_type, u8 key_id, u32 cipher);
+ u8 key_type, u8 key_id, u32 cipher, s16 sta_id);
int rsi_set_channel(struct rsi_common *common,
struct ieee80211_channel *channel);
int rsi_send_vap_dynamic_update(struct rsi_common *common);
--
2.7.4

2017-08-17 07:07:25

by Kalle Valo

[permalink] [raw]
Subject: Re: [v2,01/11] rsi: advertise ap mode support

Amitkumar Karwar <[email protected]> wrote:

> From: Prameela Rani Garnepudi <[email protected]>
>
> AP mode support is advertised to cfg80211. Necessary wiphy
> parameters are initialized.
>
> Signed-off-by: Prameela Rani Garnepudi <[email protected]>
> Signed-off-by: Amitkumar Karwar <[email protected]>

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

6da1e00a539d rsi: advertise ap mode support
03c34c0d73ae rsi: add interface changes for ap mode
75ca0049aad6 rsi: remove interface changes for AP mode
d26a9559403c rsi: add beacon changes for AP mode
3528608f3a79 rsi: handle station connection in AP mode
571b050b42ae rsi: handle station disconnection in AP mode
19844c0a9a19 rsi: data and managemet path changes for AP mode
6572f054e964 rsi: use common descriptor for auto rate frame
8a1ff83f2bf8 rsi: update tx auto rate command frame for AP mode
32be57a666a5 rsi: aggregation parameters frame for AP mode
38ef62353acb rsi: security enhancements for AP mode

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

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

2017-08-16 13:18:08

by Amitkumar Karwar

[permalink] [raw]
Subject: [v2 05/11] rsi: handle station connection in AP mode

From: Prameela Rani Garnepudi <[email protected]>

Station structures are maintained in driver with required
fields. When mac80211 callback sta_add is called, driver
iterates through list of connected stations to check available
index and assigns station id which is important for further
communication to that station. Then peer notify frame is send
to firmware to inform the firmware about new station connection.

Signed-off-by: Prameela Rani Garnepudi <[email protected]>
Signed-off-by: Amitkumar Karwar <[email protected]>
---
drivers/net/wireless/rsi/rsi_91x_mac80211.c | 78 ++++++++++++++++++++++++++---
drivers/net/wireless/rsi/rsi_91x_mgmt.c | 49 +++++++++++-------
drivers/net/wireless/rsi/rsi_mgmt.h | 9 +++-
3 files changed, 110 insertions(+), 26 deletions(-)

diff --git a/drivers/net/wireless/rsi/rsi_91x_mac80211.c b/drivers/net/wireless/rsi/rsi_91x_mac80211.c
index 6038a2f..b1c0849 100644
--- a/drivers/net/wireless/rsi/rsi_91x_mac80211.c
+++ b/drivers/net/wireless/rsi/rsi_91x_mac80211.c
@@ -626,10 +626,12 @@ static void rsi_mac80211_bss_info_changed(struct ieee80211_hw *hw,
rsi_send_rx_filter_frame(common, rx_filter_word);
}
rsi_inform_bss_status(common,
+ STA_OPMODE,
bss_conf->assoc,
bss_conf->bssid,
bss_conf->qos,
- bss_conf->aid);
+ bss_conf->aid,
+ NULL, 0);
adapter->ps_info.dtim_interval_duration = bss->dtim_period;
adapter->ps_info.listen_interval = conf->listen_interval;

@@ -1157,18 +1159,80 @@ static int rsi_mac80211_sta_add(struct ieee80211_hw *hw,
{
struct rsi_hw *adapter = hw->priv;
struct rsi_common *common = adapter->priv;
+ bool sta_exist = false;
+ struct rsi_sta *rsta;
+
+ rsi_dbg(INFO_ZONE, "Station Add: %pM\n", sta->addr);

mutex_lock(&common->mutex);

- rsi_set_min_rate(hw, sta, common);
+ if (vif->type == NL80211_IFTYPE_AP) {
+ u8 cnt;
+ int sta_idx = -1;
+ int free_index = -1;
+
+ /* Check if max stations reached */
+ if (common->num_stations >= common->max_stations) {
+ rsi_dbg(ERR_ZONE, "Reject: Max Stations exists\n");
+ mutex_unlock(&common->mutex);
+ return -EOPNOTSUPP;
+ }
+ for (cnt = 0; cnt < common->max_stations; cnt++) {
+ rsta = &common->stations[cnt];

- if ((sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) ||
- (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40)) {
- common->vif_info[0].sgi = true;
+ if (!rsta->sta) {
+ if (free_index < 0)
+ free_index = cnt;
+ continue;
+ }
+ if (!memcmp(rsta->sta->addr, sta->addr, ETH_ALEN)) {
+ rsi_dbg(INFO_ZONE, "Station exists\n");
+ sta_idx = cnt;
+ sta_exist = true;
+ break;
+ }
+ }
+ if (!sta_exist) {
+ if (free_index >= 0)
+ sta_idx = free_index;
+ }
+ if (sta_idx < 0) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Some problem reaching here...\n",
+ __func__);
+ return -EINVAL;
+ }
+ rsta = &common->stations[sta_idx];
+ rsta->sta = sta;
+ rsta->sta_id = sta_idx;
+ for (cnt = 0; cnt < IEEE80211_NUM_TIDS; cnt++)
+ rsta->start_tx_aggr[cnt] = false;
+ for (cnt = 0; cnt < IEEE80211_NUM_TIDS; cnt++)
+ rsta->seq_start[cnt] = 0;
+ if (!sta_exist) {
+ rsi_dbg(INFO_ZONE, "New Station\n");
+
+ /* Send peer notify to device */
+ rsi_dbg(INFO_ZONE, "Indicate bss status to device\n");
+ rsi_inform_bss_status(common, AP_OPMODE, 1, sta->addr,
+ sta->wme, sta->aid, sta, sta_idx);
+
+ common->num_stations++;
+ }
}

- if (sta->ht_cap.ht_supported)
- ieee80211_start_tx_ba_session(sta, 0, 0);
+ if (vif->type == NL80211_IFTYPE_STATION) {
+ rsi_set_min_rate(hw, sta, common);
+ if (sta->ht_cap.ht_supported) {
+ common->vif_info[0].is_ht = true;
+ common->bitrate_mask[NL80211_BAND_2GHZ] =
+ sta->supp_rates[NL80211_BAND_2GHZ];
+ if ((sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) ||
+ (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40))
+ common->vif_info[0].sgi = true;
+ ieee80211_start_tx_ba_session(sta, 0, 0);
+ }
+ }

mutex_unlock(&common->mutex);

diff --git a/drivers/net/wireless/rsi/rsi_91x_mgmt.c b/drivers/net/wireless/rsi/rsi_91x_mgmt.c
index e47fc0d..7c0f27a 100644
--- a/drivers/net/wireless/rsi/rsi_91x_mgmt.c
+++ b/drivers/net/wireless/rsi/rsi_91x_mgmt.c
@@ -455,12 +455,14 @@ 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,
- u8 opmode,
+ enum opmode opmode,
u8 notify_event,
const unsigned char *bssid,
u8 qos_enable,
- u16 aid)
+ u16 aid,
+ u16 sta_id)
{
+ struct ieee80211_vif *vif = common->priv->vifs[0];
struct sk_buff *skb = NULL;
struct rsi_peer_notify *peer_notify;
u16 vap_id = 0;
@@ -480,7 +482,10 @@ static int rsi_hal_send_sta_notify_frame(struct rsi_common *common,
memset(skb->data, 0, frame_len);
peer_notify = (struct rsi_peer_notify *)skb->data;

- peer_notify->command = cpu_to_le16(opmode << 1);
+ if (opmode == STA_OPMODE)
+ peer_notify->command = cpu_to_le16(PEER_TYPE_AP << 1);
+ else if (opmode == AP_OPMODE)
+ peer_notify->command = cpu_to_le16(PEER_TYPE_STA << 1);

switch (notify_event) {
case STA_CONNECTED:
@@ -502,13 +507,15 @@ static int rsi_hal_send_sta_notify_frame(struct rsi_common *common,
(frame_len - FRAME_DESC_SZ),
RSI_WIFI_MGMT_Q);
peer_notify->desc.desc_dword0.frame_type = PEER_NOTIFY;
+ peer_notify->desc.desc_dword3.qid_tid = sta_id;
peer_notify->desc.desc_dword3.sta_id = vap_id;

skb_put(skb, frame_len);

status = rsi_send_internal_mgmt_frame(common, skb);

- if (!status && qos_enable) {
+ if ((vif->type == NL80211_IFTYPE_STATION) &&
+ (!status && qos_enable)) {
rsi_set_contention_vals(common);
status = rsi_load_radio_caps(common);
}
@@ -1279,32 +1286,40 @@ static int rsi_send_auto_rate_request(struct rsi_common *common)
* Return: None.
*/
void rsi_inform_bss_status(struct rsi_common *common,
+ enum opmode opmode,
u8 status,
- const unsigned char *bssid,
+ const u8 *addr,
u8 qos_enable,
- u16 aid)
+ u16 aid,
+ struct ieee80211_sta *sta,
+ u16 sta_id)
{
if (status) {
- common->hw_data_qs_blocked = true;
+ if (opmode == STA_OPMODE)
+ common->hw_data_qs_blocked = true;
rsi_hal_send_sta_notify_frame(common,
- RSI_IFTYPE_STATION,
+ opmode,
STA_CONNECTED,
- bssid,
+ addr,
qos_enable,
- aid);
+ aid, sta_id);
if (common->min_rate == 0xffff)
rsi_send_auto_rate_request(common);
- if (!rsi_send_block_unblock_frame(common, false))
- common->hw_data_qs_blocked = false;
+ if (opmode == STA_OPMODE) {
+ if (!rsi_send_block_unblock_frame(common, false))
+ common->hw_data_qs_blocked = false;
+ }
} else {
- common->hw_data_qs_blocked = true;
+ if (opmode == STA_OPMODE)
+ common->hw_data_qs_blocked = true;
rsi_hal_send_sta_notify_frame(common,
- RSI_IFTYPE_STATION,
+ opmode,
STA_DISCONNECTED,
- bssid,
+ addr,
qos_enable,
- aid);
- rsi_send_block_unblock_frame(common, true);
+ aid, sta_id);
+ if (opmode == STA_OPMODE)
+ rsi_send_block_unblock_frame(common, true);
}
}

diff --git a/drivers/net/wireless/rsi/rsi_mgmt.h b/drivers/net/wireless/rsi/rsi_mgmt.h
index a00aa10..a2e377f 100644
--- a/drivers/net/wireless/rsi/rsi_mgmt.h
+++ b/drivers/net/wireless/rsi/rsi_mgmt.h
@@ -209,6 +209,10 @@ enum vap_status {
VAP_UPDATE = 3
};

+enum peer_type {
+ PEER_TYPE_AP,
+ PEER_TYPE_STA,
+};
extern struct ieee80211_rate rsi_rates[12];
extern const u16 rsi_mcsrates[8];

@@ -611,8 +615,9 @@ 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);
-void rsi_inform_bss_status(struct rsi_common *common, u8 status,
- const u8 *bssid, u8 qos_enable, u16 aid);
+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);
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

2017-08-16 13:18:03

by Amitkumar Karwar

[permalink] [raw]
Subject: [v2 04/11] rsi: add beacon changes for AP mode

From: Prameela Rani Garnepudi <[email protected]>

Mac80211 config parameter BEACON_ENABLE is handled. When VAP
capabilities frame with AP mode is configured to firmware, beacon
events start coming to host at each PreTBTT. At this time, beacon
is taken from mac80211, descriptor is prepared and send to firmware.

Signed-off-by: Prameela Rani Garnepudi <[email protected]>
Signed-off-by: Amitkumar Karwar <[email protected]>
---
drivers/net/wireless/rsi/rsi_91x_core.c | 15 +++++--
drivers/net/wireless/rsi/rsi_91x_hal.c | 65 ++++++++++++++++++++++++++++-
drivers/net/wireless/rsi/rsi_91x_mac80211.c | 12 ++++++
drivers/net/wireless/rsi/rsi_91x_mgmt.c | 48 ++++++++++++++++++---
drivers/net/wireless/rsi/rsi_hal.h | 2 +
drivers/net/wireless/rsi/rsi_main.h | 13 +++---
drivers/net/wireless/rsi/rsi_mgmt.h | 11 +++++
7 files changed, 152 insertions(+), 14 deletions(-)

diff --git a/drivers/net/wireless/rsi/rsi_91x_core.c b/drivers/net/wireless/rsi/rsi_91x_core.c
index 88a1a56..6cfda86 100644
--- a/drivers/net/wireless/rsi/rsi_91x_core.c
+++ b/drivers/net/wireless/rsi/rsi_91x_core.c
@@ -16,6 +16,7 @@

#include "rsi_mgmt.h"
#include "rsi_common.h"
+#include "rsi_hal.h"

/**
* rsi_determine_min_weight_queue() - This function determines the queue with
@@ -136,6 +137,10 @@ static u8 rsi_core_determine_hal_queue(struct rsi_common *common)
u8 q_num = INVALID_QUEUE;
u8 ii = 0;

+ if (skb_queue_len(&common->tx_queue[MGMT_BEACON_Q])) {
+ q_num = MGMT_BEACON_Q;
+ return q_num;
+ }
if (skb_queue_len(&common->tx_queue[MGMT_SOFT_Q])) {
if (!common->mgmt_q_block)
q_num = MGMT_SOFT_Q;
@@ -291,10 +296,14 @@ void rsi_core_qos_processor(struct rsi_common *common)
break;
}

- if (q_num == MGMT_SOFT_Q)
+ if (q_num == MGMT_SOFT_Q) {
status = rsi_send_mgmt_pkt(common, skb);
- else
+ } else if (q_num == MGMT_BEACON_Q) {
+ status = rsi_send_pkt_to_bus(common, skb);
+ dev_kfree_skb(skb);
+ } else {
status = rsi_send_data_pkt(common, skb);
+ }

if (status) {
mutex_unlock(&common->tx_lock);
@@ -358,7 +367,7 @@ void rsi_core_xmit(struct rsi_common *common, struct sk_buff *skb)
tx_params->sta_id = 0;
}

- if ((q_num != MGMT_SOFT_Q) &&
+ if ((q_num < MGMT_SOFT_Q) &&
((skb_queue_len(&common->tx_queue[q_num]) + 1) >=
DATA_QUEUE_WATER_MARK)) {
rsi_dbg(ERR_ZONE, "%s: sw queue full\n", __func__);
diff --git a/drivers/net/wireless/rsi/rsi_91x_hal.c b/drivers/net/wireless/rsi/rsi_91x_hal.c
index 4addcc0..1ed7332 100644
--- a/drivers/net/wireless/rsi/rsi_91x_hal.c
+++ b/drivers/net/wireless/rsi/rsi_91x_hal.c
@@ -25,7 +25,15 @@ static struct ta_metadata metadata_flash_content[] = {
{"rsi/rs9113_wlan_qspi.rps", 0x00010000},
};

-/*This function prepares descriptor for given management packet*/
+int rsi_send_pkt_to_bus(struct rsi_common *common, struct sk_buff *skb)
+{
+ struct rsi_hw *adapter = common->priv;
+ int status;
+
+ status = adapter->host_intf_ops->write_pkt(common->priv,
+ skb->data, skb->len);
+ return status;
+}

static int rsi_prepare_mgmt_desc(struct rsi_common *common, struct sk_buff *skb)
{
@@ -306,6 +314,61 @@ int rsi_send_mgmt_pkt(struct rsi_common *common,
return status;
}

+int rsi_prepare_beacon(struct rsi_common *common, struct sk_buff *skb)
+{
+ struct rsi_hw *adapter = (struct rsi_hw *)common->priv;
+ struct rsi_data_desc *bcn_frm;
+ struct ieee80211_hw *hw = common->priv->hw;
+ struct ieee80211_conf *conf = &hw->conf;
+ struct sk_buff *mac_bcn;
+ u8 vap_id = 0;
+ u16 tim_offset;
+
+ mac_bcn = ieee80211_beacon_get_tim(adapter->hw,
+ adapter->vifs[adapter->sc_nvifs - 1],
+ &tim_offset, NULL);
+ if (!mac_bcn) {
+ rsi_dbg(ERR_ZONE, "Failed to get beacon from mac80211\n");
+ return -EINVAL;
+ }
+
+ common->beacon_cnt++;
+ bcn_frm = (struct rsi_data_desc *)skb->data;
+ rsi_set_len_qno(&bcn_frm->len_qno, mac_bcn->len, RSI_WIFI_DATA_Q);
+ bcn_frm->header_len = MIN_802_11_HDR_LEN;
+ bcn_frm->frame_info = cpu_to_le16(RSI_DATA_DESC_MAC_BBP_INFO |
+ RSI_DATA_DESC_NO_ACK_IND |
+ RSI_DATA_DESC_BEACON_FRAME |
+ RSI_DATA_DESC_INSERT_TSF |
+ RSI_DATA_DESC_INSERT_SEQ_NO |
+ RATE_INFO_ENABLE);
+ bcn_frm->rate_info = cpu_to_le16(vap_id << 14);
+ bcn_frm->qid_tid = BEACON_HW_Q;
+
+ if (conf_is_ht40_plus(conf)) {
+ bcn_frm->bbp_info = cpu_to_le16(LOWER_20_ENABLE);
+ bcn_frm->bbp_info |= cpu_to_le16(LOWER_20_ENABLE >> 12);
+ } else if (conf_is_ht40_minus(conf)) {
+ bcn_frm->bbp_info = cpu_to_le16(UPPER_20_ENABLE);
+ bcn_frm->bbp_info |= cpu_to_le16(UPPER_20_ENABLE >> 12);
+ }
+
+ if (common->band == NL80211_BAND_2GHZ)
+ bcn_frm->bbp_info |= cpu_to_le16(RSI_RATE_1);
+ else
+ bcn_frm->bbp_info |= cpu_to_le16(RSI_RATE_6);
+
+ if (mac_bcn->data[tim_offset + 2] == 0)
+ bcn_frm->frame_info |= cpu_to_le16(RSI_DATA_DESC_DTIM_BEACON);
+
+ memcpy(&skb->data[FRAME_DESC_SZ], mac_bcn->data, mac_bcn->len);
+ skb_put(skb, mac_bcn->len + FRAME_DESC_SZ);
+
+ dev_kfree_skb(mac_bcn);
+
+ return 0;
+}
+
static void bl_cmd_timeout(unsigned long priv)
{
struct rsi_hw *adapter = (struct rsi_hw *)priv;
diff --git a/drivers/net/wireless/rsi/rsi_91x_mac80211.c b/drivers/net/wireless/rsi/rsi_91x_mac80211.c
index 99446bb..6038a2f 100644
--- a/drivers/net/wireless/rsi/rsi_91x_mac80211.c
+++ b/drivers/net/wireless/rsi/rsi_91x_mac80211.c
@@ -652,6 +652,18 @@ static void rsi_mac80211_bss_info_changed(struct ieee80211_hw *hw,
common->cqm_info.rssi_thold,
common->cqm_info.rssi_hyst);
}
+
+ if ((changed & BSS_CHANGED_BEACON_ENABLED) &&
+ (vif->type == NL80211_IFTYPE_AP)) {
+ if (bss->enable_beacon) {
+ rsi_dbg(INFO_ZONE, "===> BEACON ENABLED <===\n");
+ common->beacon_enabled = 1;
+ } else {
+ rsi_dbg(INFO_ZONE, "===> BEACON DISABLED <===\n");
+ common->beacon_enabled = 0;
+ }
+ }
+
mutex_unlock(&common->mutex);
}

diff --git a/drivers/net/wireless/rsi/rsi_91x_mgmt.c b/drivers/net/wireless/rsi/rsi_91x_mgmt.c
index 233a418..e47fc0d 100644
--- a/drivers/net/wireless/rsi/rsi_91x_mgmt.c
+++ b/drivers/net/wireless/rsi/rsi_91x_mgmt.c
@@ -18,6 +18,7 @@
#include "rsi_mgmt.h"
#include "rsi_common.h"
#include "rsi_ps.h"
+#include "rsi_hal.h"

static struct bootup_params boot_params_20 = {
.magic_number = cpu_to_le16(0x5aa5),
@@ -1518,6 +1519,31 @@ int rsi_set_antenna(struct rsi_common *common, u8 antenna)
return rsi_send_internal_mgmt_frame(common, skb);
}

+static int rsi_send_beacon(struct rsi_common *common)
+{
+ struct sk_buff *skb = NULL;
+ u8 dword_align_bytes = 0;
+
+ skb = dev_alloc_skb(MAX_MGMT_PKT_SIZE);
+ if (!skb)
+ return -ENOMEM;
+
+ memset(skb->data, 0, MAX_MGMT_PKT_SIZE);
+
+ dword_align_bytes = ((unsigned long)skb->data & 0x3f);
+ if (dword_align_bytes)
+ skb_pull(skb, (64 - dword_align_bytes));
+ if (rsi_prepare_beacon(common, skb)) {
+ rsi_dbg(ERR_ZONE, "Failed to prepare beacon\n");
+ return -EINVAL;
+ }
+ skb_queue_tail(&common->tx_queue[MGMT_BEACON_Q], skb);
+ rsi_set_event(&common->tx_thread.event);
+ rsi_dbg(DATA_TX_ZONE, "%s: Added to beacon queue\n", __func__);
+
+ return 0;
+}
+
/**
* rsi_handle_ta_confirm_type() - This function handles the confirm frames.
* @common: Pointer to the driver private structure.
@@ -1722,21 +1748,33 @@ int rsi_mgmt_pkt_recv(struct rsi_common *common, u8 *msg)
rsi_dbg(FSM_ZONE, "%s: Msg Len: %d, Msg Type: %4x\n",
__func__, msg_len, msg_type);

- if (msg_type == TA_CONFIRM_TYPE) {
+ switch (msg_type) {
+ case TA_CONFIRM_TYPE:
return rsi_handle_ta_confirm_type(common, msg);
- } else if (msg_type == CARD_READY_IND) {
+ case CARD_READY_IND:
rsi_dbg(FSM_ZONE, "%s: Card ready indication received\n",
__func__);
return rsi_handle_card_ready(common, msg);
- } else if (msg_type == TX_STATUS_IND) {
+ case TX_STATUS_IND:
if (msg[15] == PROBEREQ_CONFIRM) {
common->mgmt_q_block = false;
rsi_dbg(FSM_ZONE, "%s: Probe confirm received\n",
__func__);
}
- } else if (msg_type == RX_DOT11_MGMT) {
+ break;
+ case BEACON_EVENT_IND:
+ rsi_dbg(INFO_ZONE, "Beacon event\n");
+ if (common->fsm_state != FSM_MAC_INIT_DONE)
+ return -1;
+ if (common->iface_down)
+ return -1;
+ if (!common->beacon_enabled)
+ return -1;
+ rsi_send_beacon(common);
+ break;
+ case RX_DOT11_MGMT:
return rsi_mgmt_pkt_to_core(common, msg, msg_len);
- } else {
+ default:
rsi_dbg(INFO_ZONE, "Received packet type: 0x%x\n", msg_type);
}
return 0;
diff --git a/drivers/net/wireless/rsi/rsi_hal.h b/drivers/net/wireless/rsi/rsi_hal.h
index 00c6a0c..297f4ce 100644
--- a/drivers/net/wireless/rsi/rsi_hal.h
+++ b/drivers/net/wireless/rsi/rsi_hal.h
@@ -144,5 +144,7 @@ struct rsi_data_desc {
} __packed;

int rsi_hal_device_init(struct rsi_hw *adapter);
+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);

#endif
diff --git a/drivers/net/wireless/rsi/rsi_main.h b/drivers/net/wireless/rsi/rsi_main.h
index 9f5f33f..169e2f9 100644
--- a/drivers/net/wireless/rsi/rsi_main.h
+++ b/drivers/net/wireless/rsi/rsi_main.h
@@ -72,7 +72,7 @@ extern __printf(2, 3) void rsi_dbg(u32 zone, const char *fmt, ...);
#define MULTICAST_WATER_MARK 200
#define MAC_80211_HDR_FRAME_CONTROL 0
#define WME_NUM_AC 4
-#define NUM_SOFT_QUEUES 5
+#define NUM_SOFT_QUEUES 6
#define MAX_HW_QUEUES 12
#define INVALID_QUEUE 0xff
#define MAX_CONTINUOUS_VO_PKTS 8
@@ -131,7 +131,8 @@ enum edca_queue {
BE_Q,
VI_Q,
VO_Q,
- MGMT_SOFT_Q
+ MGMT_SOFT_Q,
+ MGMT_BEACON_Q
};

struct security_info {
@@ -148,8 +149,8 @@ struct wmm_qinfo {
};

struct transmit_q_stats {
- u32 total_tx_pkt_send[NUM_EDCA_QUEUES + 1];
- u32 total_tx_pkt_freed[NUM_EDCA_QUEUES + 1];
+ u32 total_tx_pkt_send[NUM_EDCA_QUEUES + 2];
+ u32 total_tx_pkt_freed[NUM_EDCA_QUEUES + 2];
};

struct vif_priv {
@@ -199,7 +200,7 @@ struct rsi_common {
struct version_info fw_ver;

struct rsi_thread tx_thread;
- struct sk_buff_head tx_queue[NUM_EDCA_QUEUES + 1];
+ struct sk_buff_head tx_queue[NUM_EDCA_QUEUES + 2];
/* Mutex declaration */
struct mutex mutex;
/* Mutex used for tx thread */
@@ -263,6 +264,8 @@ struct rsi_common {
u8 dtim_cnt;

/* AP mode parameters */
+ u8 beacon_enabled;
+ u16 beacon_cnt;
struct rsi_sta stations[RSI_MAX_ASSOC_STAS + 1];
int num_stations;
int max_stations;
diff --git a/drivers/net/wireless/rsi/rsi_mgmt.h b/drivers/net/wireless/rsi/rsi_mgmt.h
index 9093ba6..a00aa10 100644
--- a/drivers/net/wireless/rsi/rsi_mgmt.h
+++ b/drivers/net/wireless/rsi/rsi_mgmt.h
@@ -49,6 +49,7 @@
#define TA_CONFIRM_TYPE 0x01
#define RX_DOT11_MGMT 0x02
#define TX_STATUS_IND 0x04
+#define BEACON_EVENT_IND 0x08
#define PROBEREQ_CONFIRM 2
#define CARD_READY_IND 0x00

@@ -187,6 +188,16 @@
IEEE80211_WMM_IE_STA_QOSINFO_AC_BE | \
IEEE80211_WMM_IE_STA_QOSINFO_AC_BK)

+#define RSI_DATA_DESC_MAC_BBP_INFO BIT(0)
+#define RSI_DATA_DESC_NO_ACK_IND BIT(9)
+#define RSI_DATA_DESC_QOS_EN BIT(12)
+#define RSI_DATA_DESC_NORMAL_FRAME 0x00
+#define RSI_DATA_DESC_DTIM_BEACON_GATED_FRAME BIT(10)
+#define RSI_DATA_DESC_BEACON_FRAME BIT(11)
+#define RSI_DATA_DESC_DTIM_BEACON (BIT(10) | BIT(11))
+#define RSI_DATA_DESC_INSERT_TSF BIT(15)
+#define RSI_DATA_DESC_INSERT_SEQ_NO BIT(2)
+
enum opmode {
AP_OPMODE = 0,
STA_OPMODE,
--
2.7.4

2017-08-16 13:17:57

by Amitkumar Karwar

[permalink] [raw]
Subject: [v2 03/11] rsi: remove interface changes for AP mode

From: Prameela Rani Garnepudi <[email protected]>

remove_interface callback of mac80211 is handled for AP mode.
Same is notified to firmware through vap_capabilities frame
with VAP status VAP_DELETE.

Signed-off-by: Prameela Rani Garnepudi <[email protected]>
Signed-off-by: Amitkumar Karwar <[email protected]>
---
drivers/net/wireless/rsi/rsi_91x_mac80211.c | 26 ++++++++++++++++++++++----
1 file changed, 22 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wireless/rsi/rsi_91x_mac80211.c b/drivers/net/wireless/rsi/rsi_91x_mac80211.c
index edcba56..99446bb 100644
--- a/drivers/net/wireless/rsi/rsi_91x_mac80211.c
+++ b/drivers/net/wireless/rsi/rsi_91x_mac80211.c
@@ -405,13 +405,31 @@ static void rsi_mac80211_remove_interface(struct ieee80211_hw *hw,
{
struct rsi_hw *adapter = hw->priv;
struct rsi_common *common = adapter->priv;
+ enum opmode opmode;
+
+ rsi_dbg(INFO_ZONE, "Remove Interface Called\n");

mutex_lock(&common->mutex);
- if (vif->type == NL80211_IFTYPE_STATION) {
- adapter->sc_nvifs--;
- rsi_set_vap_capabilities(common, STA_OPMODE, vif->addr,
- 0, VAP_DELETE);
+
+ if (adapter->sc_nvifs <= 0) {
+ mutex_unlock(&common->mutex);
+ return;
+ }
+
+ switch (vif->type) {
+ case NL80211_IFTYPE_STATION:
+ opmode = STA_OPMODE;
+ break;
+ case NL80211_IFTYPE_AP:
+ opmode = AP_OPMODE;
+ break;
+ default:
+ mutex_unlock(&common->mutex);
+ return;
}
+ rsi_set_vap_capabilities(common, opmode, vif->addr,
+ 0, VAP_DELETE);
+ adapter->sc_nvifs--;

if (!memcmp(adapter->vifs[0], vif, sizeof(struct ieee80211_vif)))
adapter->vifs[0] = NULL;
--
2.7.4