[PATCH 28/29] staging: wilc1000: avoid extra buffer copy while connect cfg ops

2018-12-02 Thread Ajay.Kathat
From: Ajay Singh 

Refactor the code to avoid the use of an extra buffer to store the
connection related parameter. No need to call cfg80211_disconnected in
case of failure to send the wid command to firmware, an error status is
directly returned in cfg80211 connect callback.

Signed-off-by: Ajay Singh 
---
 drivers/staging/wilc1000/host_interface.c | 129 +++---
 drivers/staging/wilc1000/host_interface.h |   2 +
 drivers/staging/wilc1000/wilc_wfi_cfgoperations.c |   2 +
 3 files changed, 21 insertions(+), 112 deletions(-)

diff --git a/drivers/staging/wilc1000/host_interface.c 
b/drivers/staging/wilc1000/host_interface.c
index 783c99b..f50728c 100644
--- a/drivers/staging/wilc1000/host_interface.c
+++ b/drivers/staging/wilc1000/host_interface.c
@@ -25,20 +25,6 @@ struct scan_attr {
struct hidden_network hidden_network;
 };
 
-struct connect_attr {
-   u8 *bssid;
-   u8 *ssid;
-   size_t ssid_len;
-   u8 *ies;
-   size_t ies_len;
-   u8 security;
-   wilc_connect_result result;
-   void *arg;
-   enum authtype auth_type;
-   u8 ch;
-   void *params;
-};
-
 struct rcvd_async_info {
u8 *buffer;
u32 len;
@@ -99,7 +85,6 @@ struct wilc_gtk_key {
 
 union message_body {
struct scan_attr scan_info;
-   struct connect_attr con_info;
struct rcvd_net_info net_info;
struct rcvd_async_info async_info;
struct set_multicast multicast_info;
@@ -362,54 +347,15 @@ static void handle_scan(struct work_struct *work)
kfree(msg);
 }
 
-static int wilc_send_connect_wid(struct wilc_vif *vif,
-struct connect_attr *conn_attr)
+static int wilc_send_connect_wid(struct wilc_vif *vif)
 {
int result = 0;
struct wid wid_list[8];
u32 wid_cnt = 0, dummyval = 0;
u8 *cur_byte = NULL;
-   struct join_bss_param *bss_param = conn_attr->params;
struct host_if_drv *hif_drv = vif->hif_drv;
-
-   if (conn_attr->bssid) {
-   hif_drv->usr_conn_req.bssid = kmemdup(conn_attr->bssid, 6,
- GFP_KERNEL);
-   if (!hif_drv->usr_conn_req.bssid) {
-   result = -ENOMEM;
-   goto error;
-   }
-   }
-
-   hif_drv->usr_conn_req.ssid_len = conn_attr->ssid_len;
-   if (conn_attr->ssid) {
-   hif_drv->usr_conn_req.ssid = kmalloc(conn_attr->ssid_len + 1,
-GFP_KERNEL);
-   if (!hif_drv->usr_conn_req.ssid) {
-   result = -ENOMEM;
-   goto error;
-   }
-   memcpy(hif_drv->usr_conn_req.ssid,
-  conn_attr->ssid,
-  conn_attr->ssid_len);
-   hif_drv->usr_conn_req.ssid[conn_attr->ssid_len] = '\0';
-   }
-
-   hif_drv->usr_conn_req.ies_len = conn_attr->ies_len;
-   if (conn_attr->ies) {
-   hif_drv->usr_conn_req.ies = kmemdup(conn_attr->ies,
-   conn_attr->ies_len,
-   GFP_KERNEL);
-   if (!hif_drv->usr_conn_req.ies) {
-   result = -ENOMEM;
-   goto error;
-   }
-   }
-
-   hif_drv->usr_conn_req.security = conn_attr->security;
-   hif_drv->usr_conn_req.auth_type = conn_attr->auth_type;
-   hif_drv->usr_conn_req.conn_result = conn_attr->result;
-   hif_drv->usr_conn_req.arg = conn_attr->arg;
+   struct user_conn_req *conn_attr = _drv->usr_conn_req;
+   struct join_bss_param *bss_param = hif_drv->usr_conn_req.param;
 
wid_list[wid_cnt].id = WID_SUCCESS_FRAME_COUNT;
wid_list[wid_cnt].type = WID_INT;
@@ -431,20 +377,20 @@ static int wilc_send_connect_wid(struct wilc_vif *vif,
 
wid_list[wid_cnt].id = WID_INFO_ELEMENT_ASSOCIATE;
wid_list[wid_cnt].type = WID_BIN_DATA;
-   wid_list[wid_cnt].val = hif_drv->usr_conn_req.ies;
-   wid_list[wid_cnt].size = hif_drv->usr_conn_req.ies_len;
+   wid_list[wid_cnt].val = conn_attr->ies;
+   wid_list[wid_cnt].size = conn_attr->ies_len;
wid_cnt++;
 
wid_list[wid_cnt].id = WID_11I_MODE;
wid_list[wid_cnt].type = WID_CHAR;
wid_list[wid_cnt].size = sizeof(char);
-   wid_list[wid_cnt].val = (s8 *)_drv->usr_conn_req.security;
+   wid_list[wid_cnt].val = (s8 *)_attr->security;
wid_cnt++;
 
wid_list[wid_cnt].id = WID_AUTH_TYPE;
wid_list[wid_cnt].type = WID_CHAR;
wid_list[wid_cnt].size = sizeof(char);
-   wid_list[wid_cnt].val = (s8 *)_drv->usr_conn_req.auth_type;
+   wid_list[wid_cnt].val = (s8 *)_attr->auth_type;
wid_cnt++;
 
wid_list[wid_cnt].id = WID_JOIN_REQ_EXTENDED;
@@ -494,7 +440,7 @@ static int wilc_send_connect_wid(struct wilc_vif *vif,

[PATCH 27/29] staging: wilc1000: handle connect ops callback from cfg80211 context

2018-12-02 Thread Ajay.Kathat
From: Ajay Singh 

Refactor the connect related cfg callback to be called from cfg80211
context. No need to post connect command internally in case scan is in
progress instead simply return the error status in connect ops callback.

Signed-off-by: Ajay Singh 
---
 drivers/staging/wilc1000/host_interface.c | 104 +-
 1 file changed, 44 insertions(+), 60 deletions(-)

diff --git a/drivers/staging/wilc1000/host_interface.c 
b/drivers/staging/wilc1000/host_interface.c
index 6a908ea..783c99b 100644
--- a/drivers/staging/wilc1000/host_interface.c
+++ b/drivers/staging/wilc1000/host_interface.c
@@ -362,34 +362,16 @@ static void handle_scan(struct work_struct *work)
kfree(msg);
 }
 
-static void handle_connect(struct work_struct *work)
+static int wilc_send_connect_wid(struct wilc_vif *vif,
+struct connect_attr *conn_attr)
 {
-   struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
-   struct wilc_vif *vif = msg->vif;
-   struct connect_attr *conn_attr = >body.con_info;
int result = 0;
struct wid wid_list[8];
u32 wid_cnt = 0, dummyval = 0;
u8 *cur_byte = NULL;
-   struct join_bss_param *bss_param;
+   struct join_bss_param *bss_param = conn_attr->params;
struct host_if_drv *hif_drv = vif->hif_drv;
 
-   if (msg->vif->hif_drv->usr_scan_req.scan_result) {
-   result = wilc_enqueue_work(msg);
-   if (result)
-   goto error;
-
-   usleep_range(2 * 1000, 2 * 1000);
-   return;
-   }
-
-   bss_param = conn_attr->params;
-   if (!bss_param) {
-   netdev_err(vif->ndev, "Required BSSID not found\n");
-   result = -ENOENT;
-   goto error;
-   }
-
if (conn_attr->bssid) {
hif_drv->usr_conn_req.bssid = kmemdup(conn_attr->bssid, 6,
  GFP_KERNEL);
@@ -490,8 +472,8 @@ static void handle_connect(struct work_struct *work)
netdev_err(vif->ndev, "Channel out of range\n");
*(cur_byte++) = 0xFF;
}
-   *(cur_byte++)  = (bss_param->cap_info) & 0xFF;
-   *(cur_byte++)  = ((bss_param->cap_info) >> 8) & 0xFF;
+   put_unaligned_le16(bss_param->cap_info, cur_byte);
+   cur_byte += 2;
 
if (conn_attr->bssid)
memcpy(cur_byte, conn_attr->bssid, 6);
@@ -501,8 +483,8 @@ static void handle_connect(struct work_struct *work)
memcpy(cur_byte, conn_attr->bssid, 6);
cur_byte += 6;
 
-   *(cur_byte++)  = (bss_param->beacon_period) & 0xFF;
-   *(cur_byte++)  = ((bss_param->beacon_period) >> 8) & 0xFF;
+   put_unaligned_le16(bss_param->beacon_period, cur_byte);
+   cur_byte += 2;
*(cur_byte++)  =  bss_param->dtim_period;
 
memcpy(cur_byte, bss_param->supp_rates, MAX_RATES_SUPPORTED + 1);
@@ -533,10 +515,8 @@ static void handle_connect(struct work_struct *work)
*(cur_byte++) = bss_param->noa_enabled;
 
if (bss_param->noa_enabled) {
-   *(cur_byte++) = (bss_param->tsf) & 0xFF;
-   *(cur_byte++) = ((bss_param->tsf) >> 8) & 0xFF;
-   *(cur_byte++) = ((bss_param->tsf) >> 16) & 0xFF;
-   *(cur_byte++) = ((bss_param->tsf) >> 24) & 0xFF;
+   put_unaligned_le32(bss_param->tsf, cur_byte);
+   cur_byte += 4;
 
*(cur_byte++) = bss_param->opp_enabled;
*(cur_byte++) = bss_param->idx;
@@ -616,8 +596,10 @@ static void handle_connect(struct work_struct *work)
kfree(conn_attr->ies);
conn_attr->ies = NULL;
 
+   kfree(conn_attr);
kfree(cur_byte);
-   kfree(msg);
+
+   return result;
 }
 
 static void handle_connect_timeout(struct work_struct *work)
@@ -1926,8 +1908,8 @@ int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, 
const u8 *ssid,
  u8 channel, void *join_params)
 {
int result;
-   struct host_if_msg *msg;
struct host_if_drv *hif_drv = vif->hif_drv;
+   struct connect_attr *con_info;
 
if (!hif_drv || !connect_result) {
netdev_err(vif->ndev,
@@ -1941,50 +1923,51 @@ int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, 
const u8 *ssid,
return -EFAULT;
}
 
-   msg = wilc_alloc_work(vif, handle_connect, false);
-   if (IS_ERR(msg))
-   return PTR_ERR(msg);
+   if (hif_drv->usr_scan_req.scan_result) {
+   netdev_err(vif->ndev, "%s: Scan in progress\n", __func__);
+   return -EBUSY;
+   }
+
+   con_info = kzalloc(sizeof(*con_info), GFP_KERNEL);
+   if (!con_info)
+   return -ENOMEM;
 
-   msg->body.con_info.security = security;
-   msg->body.con_info.auth_type = auth_type;
-   msg->body.con_info.ch = channel;
-   msg->body.con_info.result = connect_result;
-   

[PATCH 29/29] staging: wilc1000: handle scan operation callback from cfg80211 context

2018-12-02 Thread Ajay.Kathat
From: Ajay Singh 

Refactor code to handle scan operation callback from cfg80211 context.
No need to maintain 'scan_attr' struct as the wid command is directly
sent to firmware from cfg80211 context.

Signed-off-by: Ajay Singh 
---
 drivers/staging/wilc1000/host_interface.c | 143 --
 drivers/staging/wilc1000/wilc_wfi_cfgoperations.c |  13 +-
 2 files changed, 33 insertions(+), 123 deletions(-)

diff --git a/drivers/staging/wilc1000/host_interface.c 
b/drivers/staging/wilc1000/host_interface.c
index f50728c..b8603f2 100644
--- a/drivers/staging/wilc1000/host_interface.c
+++ b/drivers/staging/wilc1000/host_interface.c
@@ -13,18 +13,6 @@
 
 #define REAL_JOIN_REQ  0
 
-struct scan_attr {
-   u8 src;
-   u8 type;
-   u8 *ch_freq_list;
-   u8 ch_list_len;
-   u8 *ies;
-   size_t ies_len;
-   wilc_scan_result result;
-   void *arg;
-   struct hidden_network hidden_network;
-};
-
 struct rcvd_async_info {
u8 *buffer;
u32 len;
@@ -84,7 +72,6 @@ struct wilc_gtk_key {
 } __packed;
 
 union message_body {
-   struct scan_attr scan_info;
struct rcvd_net_info net_info;
struct rcvd_async_info async_info;
struct set_multicast multicast_info;
@@ -230,11 +217,11 @@ static int handle_scan_done(struct wilc_vif *vif, enum 
scan_event evt)
return result;
 }
 
-static void handle_scan(struct work_struct *work)
+int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type,
+ u8 *ch_freq_list, u8 ch_list_len, const u8 *ies,
+ size_t ies_len, wilc_scan_result scan_result, void *user_arg,
+ struct hidden_network *hidden_net)
 {
-   struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
-   struct wilc_vif *vif = msg->vif;
-   struct scan_attr *scan_info = >body.scan_info;
int result = 0;
struct wid wid_list[5];
u32 index = 0;
@@ -243,10 +230,6 @@ static void handle_scan(struct work_struct *work)
u8 valuesize = 0;
u8 *hdn_ntwk_wid_val = NULL;
struct host_if_drv *hif_drv = vif->hif_drv;
-   struct hidden_network *hidden_net = _info->hidden_network;
-
-   hif_drv->usr_scan_req.scan_result = scan_info->result;
-   hif_drv->usr_scan_req.arg = scan_info->arg;
 
if (hif_drv->hif_state >= HOST_IF_SCANNING &&
hif_drv->hif_state < HOST_IF_CONNECTED) {
@@ -288,63 +271,55 @@ static void handle_scan(struct work_struct *work)
 
wid_list[index].id = WID_INFO_ELEMENT_PROBE;
wid_list[index].type = WID_BIN_DATA;
-   wid_list[index].val = scan_info->ies;
-   wid_list[index].size = scan_info->ies_len;
+   wid_list[index].val = (s8 *)ies;
+   wid_list[index].size = ies_len;
index++;
 
wid_list[index].id = WID_SCAN_TYPE;
wid_list[index].type = WID_CHAR;
wid_list[index].size = sizeof(char);
-   wid_list[index].val = (s8 *)_info->type;
+   wid_list[index].val = (s8 *)_type;
index++;
 
wid_list[index].id = WID_SCAN_CHANNEL_LIST;
wid_list[index].type = WID_BIN_DATA;
 
-   if (scan_info->ch_freq_list &&
-   scan_info->ch_list_len > 0) {
-   int i;
-
-   for (i = 0; i < scan_info->ch_list_len; i++) {
-   if (scan_info->ch_freq_list[i] > 0)
-   scan_info->ch_freq_list[i] -= 1;
+   if (ch_freq_list && ch_list_len > 0) {
+   for (i = 0; i < ch_list_len; i++) {
+   if (ch_freq_list[i] > 0)
+   ch_freq_list[i] -= 1;
}
}
 
-   wid_list[index].val = scan_info->ch_freq_list;
-   wid_list[index].size = scan_info->ch_list_len;
+   wid_list[index].val = ch_freq_list;
+   wid_list[index].size = ch_list_len;
index++;
 
wid_list[index].id = WID_START_SCAN_REQ;
wid_list[index].type = WID_CHAR;
wid_list[index].size = sizeof(char);
-   wid_list[index].val = (s8 *)_info->src;
+   wid_list[index].val = (s8 *)_source;
index++;
 
result = wilc_send_config_pkt(vif, WILC_SET_CFG, wid_list,
  index,
  wilc_get_vif_idx(vif));
-
-   if (result)
-   netdev_err(vif->ndev, "Failed to send scan parameters\n");
-
-error:
if (result) {
-   del_timer(_drv->scan_timer);
-   handle_scan_done(vif, SCAN_EVENT_ABORTED);
+   netdev_err(vif->ndev, "Failed to send scan parameters\n");
+   goto error;
}
 
-   kfree(scan_info->ch_freq_list);
-   scan_info->ch_freq_list = NULL;
-
-   kfree(scan_info->ies);
-   scan_info->ies = NULL;
-   kfree(scan_info->hidden_network.net_info);
-   scan_info->hidden_network.net_info = NULL;
+   hif_drv->usr_scan_req.scan_result = scan_result;
+   

[PATCH 26/29] staging: wilc1000: avoid deferred handling of cfg80211 disconnect callback

2018-12-02 Thread Ajay.Kathat
From: Ajay Singh 

Refactor disconnect operation callback to handle from the cfg80211
context. The reason code is not required to pass as parameter to the
function, so remove it.

Signed-off-by: Ajay Singh 
---
 drivers/staging/wilc1000/host_interface.c | 39 +++
 drivers/staging/wilc1000/host_interface.h |  2 +-
 drivers/staging/wilc1000/wilc_wfi_cfgoperations.c |  2 +-
 3 files changed, 6 insertions(+), 37 deletions(-)

diff --git a/drivers/staging/wilc1000/host_interface.c 
b/drivers/staging/wilc1000/host_interface.c
index 7ab46ef..6a908ea 100644
--- a/drivers/staging/wilc1000/host_interface.c
+++ b/drivers/staging/wilc1000/host_interface.c
@@ -1241,10 +1241,8 @@ static void handle_rcvd_gnrl_async_info(struct 
work_struct *work)
kfree(msg);
 }
 
-static void handle_disconnect(struct work_struct *work)
+int wilc_disconnect(struct wilc_vif *vif)
 {
-   struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
-   struct wilc_vif *vif = msg->vif;
struct wid wid;
struct host_if_drv *hif_drv = vif->hif_drv;
struct disconnect_info disconn_info;
@@ -1263,10 +1261,9 @@ static void handle_disconnect(struct work_struct *work)
 
result = wilc_send_config_pkt(vif, WILC_SET_CFG, , 1,
  wilc_get_vif_idx(vif));
-
if (result) {
netdev_err(vif->ndev, "Failed to send dissconect\n");
-   goto out;
+   return result;
}
 
memset(_info, 0, sizeof(struct disconnect_info));
@@ -1307,10 +1304,7 @@ static void handle_disconnect(struct work_struct *work)
kfree(conn_req->ies);
conn_req->ies = NULL;
 
-out:
-
-   complete(>work_comp);
-   /* free 'msg' in caller after receiving completion */
+   return 0;
 }
 
 void wilc_resolve_disconnect_aberration(struct wilc_vif *vif)
@@ -1319,7 +1313,7 @@ void wilc_resolve_disconnect_aberration(struct wilc_vif 
*vif)
return;
if (vif->hif_drv->hif_state == HOST_IF_WAITING_CONN_RESP ||
vif->hif_drv->hif_state == HOST_IF_CONNECTING)
-   wilc_disconnect(vif, 1);
+   wilc_disconnect(vif);
 }
 
 int wilc_get_statistics(struct wilc_vif *vif, struct rf_info *stats)
@@ -2012,31 +2006,6 @@ int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, 
const u8 *ssid,
return result;
 }
 
-int wilc_disconnect(struct wilc_vif *vif, u16 reason_code)
-{
-   int result;
-   struct host_if_msg *msg;
-   struct host_if_drv *hif_drv = vif->hif_drv;
-
-   if (!hif_drv) {
-   netdev_err(vif->ndev, "%s: hif driver is NULL", __func__);
-   return -EFAULT;
-   }
-
-   msg = wilc_alloc_work(vif, handle_disconnect, true);
-   if (IS_ERR(msg))
-   return PTR_ERR(msg);
-
-   result = wilc_enqueue_work(msg);
-   if (result)
-   netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__);
-   else
-   wait_for_completion(>work_comp);
-
-   kfree(msg);
-   return result;
-}
-
 int wilc_set_mac_chnl_num(struct wilc_vif *vif, u8 channel)
 {
struct wid wid;
diff --git a/drivers/staging/wilc1000/host_interface.h 
b/drivers/staging/wilc1000/host_interface.h
index 20af5c4..ac4bdfe 100644
--- a/drivers/staging/wilc1000/host_interface.h
+++ b/drivers/staging/wilc1000/host_interface.h
@@ -264,7 +264,7 @@ int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, 
const u8 *ssid,
  wilc_connect_result connect_result, void *user_arg,
  u8 security, enum authtype auth_type,
  u8 channel, void *join_params);
-int wilc_disconnect(struct wilc_vif *vif, u16 reason_code);
+int wilc_disconnect(struct wilc_vif *vif);
 int wilc_set_mac_chnl_num(struct wilc_vif *vif, u8 channel);
 int wilc_get_rssi(struct wilc_vif *vif, s8 *rssi_level);
 int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type,
diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c 
b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c
index 045e365..7cc985e 100644
--- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c
+++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c
@@ -760,7 +760,7 @@ static int disconnect(struct wiphy *wiphy, struct 
net_device *dev,
priv->p2p.is_wilc_ie = false;
wfi_drv->p2p_timeout = 0;
 
-   ret = wilc_disconnect(vif, reason_code);
+   ret = wilc_disconnect(vif);
if (ret != 0) {
netdev_err(priv->dev, "Error in disconnecting\n");
ret = -EINVAL;
-- 
2.7.4



[PATCH 25/29] staging: wilc1000: handle get_station() ops callback in cfg80211 context

2018-12-02 Thread Ajay.Kathat
From: Ajay Singh 

Refactor code to handle the get_station() callback from cfg80211
context. Provided different API's to fetch the station statistics
information in sync or async call. From cfg80211 get_station() ops
callback calls the sync version of API.

Signed-off-by: Ajay Singh 
---
 drivers/staging/wilc1000/host_interface.c | 38 +++
 drivers/staging/wilc1000/host_interface.h |  3 +-
 drivers/staging/wilc1000/wilc_wfi_cfgoperations.c |  2 +-
 3 files changed, 21 insertions(+), 22 deletions(-)

diff --git a/drivers/staging/wilc1000/host_interface.c 
b/drivers/staging/wilc1000/host_interface.c
index 4762925..7ab46ef 100644
--- a/drivers/staging/wilc1000/host_interface.c
+++ b/drivers/staging/wilc1000/host_interface.c
@@ -1322,13 +1322,10 @@ void wilc_resolve_disconnect_aberration(struct wilc_vif 
*vif)
wilc_disconnect(vif, 1);
 }
 
-static void handle_get_statistics(struct work_struct *work)
+int wilc_get_statistics(struct wilc_vif *vif, struct rf_info *stats)
 {
-   struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
-   struct wilc_vif *vif = msg->vif;
struct wid wid_list[5];
u32 wid_cnt = 0, result;
-   struct rf_info *stats = (struct rf_info *)msg->body.data;
 
wid_list[wid_cnt].id = WID_LINKSPEED;
wid_list[wid_cnt].type = WID_CHAR;
@@ -1364,8 +1361,10 @@ static void handle_get_statistics(struct work_struct 
*work)
  wid_cnt,
  wilc_get_vif_idx(vif));
 
-   if (result)
+   if (result) {
netdev_err(vif->ndev, "Failed to send scan parameters\n");
+   return result;
+   }
 
if (stats->link_speed > TCP_ACK_FILTER_LINK_SPEED_THRESH &&
stats->link_speed != DEFAULT_LINK_SPEED)
@@ -1373,11 +1372,18 @@ static void handle_get_statistics(struct work_struct 
*work)
else if (stats->link_speed != DEFAULT_LINK_SPEED)
wilc_enable_tcp_ack_filter(vif, false);
 
-   /* free 'msg' for async command, for sync caller will free it */
-   if (msg->is_sync)
-   complete(>work_comp);
-   else
-   kfree(msg);
+   return result;
+}
+
+static void handle_get_statistics(struct work_struct *work)
+{
+   struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
+   struct wilc_vif *vif = msg->vif;
+   struct rf_info *stats = (struct rf_info *)msg->body.data;
+
+   wilc_get_statistics(vif, stats);
+
+   kfree(msg);
 }
 
 static void wilc_hif_pack_sta_param(u8 *cur_byte, const u8 *mac,
@@ -2149,13 +2155,12 @@ int wilc_get_rssi(struct wilc_vif *vif, s8 *rssi_level)
return result;
 }
 
-int
-wilc_get_statistics(struct wilc_vif *vif, struct rf_info *stats, bool is_sync)
+int wilc_get_stats_async(struct wilc_vif *vif, struct rf_info *stats)
 {
int result;
struct host_if_msg *msg;
 
-   msg = wilc_alloc_work(vif, handle_get_statistics, is_sync);
+   msg = wilc_alloc_work(vif, handle_get_statistics, false);
if (IS_ERR(msg))
return PTR_ERR(msg);
 
@@ -2168,11 +2173,6 @@ wilc_get_statistics(struct wilc_vif *vif, struct rf_info 
*stats, bool is_sync)
return result;
}
 
-   if (is_sync) {
-   wait_for_completion(>work_comp);
-   kfree(msg);
-   }
-
return result;
 }
 
@@ -2297,7 +2297,7 @@ static void get_periodic_rssi(struct timer_list *t)
}
 
if (vif->hif_drv->hif_state == HOST_IF_CONNECTED)
-   wilc_get_statistics(vif, >periodic_stat, false);
+   wilc_get_stats_async(vif, >periodic_stat);
 
mod_timer(>periodic_rssi, jiffies + msecs_to_jiffies(5000));
 }
diff --git a/drivers/staging/wilc1000/host_interface.h 
b/drivers/staging/wilc1000/host_interface.h
index 953f0ea..20af5c4 100644
--- a/drivers/staging/wilc1000/host_interface.h
+++ b/drivers/staging/wilc1000/host_interface.h
@@ -297,8 +297,7 @@ void wilc_frame_register(struct wilc_vif *vif, u16 
frame_type, bool reg);
 int wilc_set_wfi_drv_handler(struct wilc_vif *vif, int index, u8 mode,
 u8 ifc_id);
 int wilc_set_operation_mode(struct wilc_vif *vif, u32 mode);
-int wilc_get_statistics(struct wilc_vif *vif, struct rf_info *stats,
-   bool is_sync);
+int wilc_get_statistics(struct wilc_vif *vif, struct rf_info *stats);
 void wilc_resolve_disconnect_aberration(struct wilc_vif *vif);
 int wilc_get_vif_idx(struct wilc_vif *vif);
 int wilc_set_tx_power(struct wilc_vif *vif, u8 tx_power);
diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c 
b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c
index 4c9444e..045e365 100644
--- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c
+++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c
@@ -1039,7 +1039,7 @@ static int get_station(struct wiphy *wiphy, struct 
net_device *dev,
} 

[PATCH 21/29] staging: wilc1000: delete the unused code after code refactor

2018-12-02 Thread Ajay.Kathat
From: Ajay Singh 

After code refactor some of the macro and variables are not required any
more, so deleted the unused code.

Signed-off-by: Ajay Singh 
---
 drivers/staging/wilc1000/host_interface.c | 31 ---
 drivers/staging/wilc1000/host_interface.h | 27 ---
 2 files changed, 58 deletions(-)

diff --git a/drivers/staging/wilc1000/host_interface.c 
b/drivers/staging/wilc1000/host_interface.c
index 596a321..71395d8 100644
--- a/drivers/staging/wilc1000/host_interface.c
+++ b/drivers/staging/wilc1000/host_interface.c
@@ -13,30 +13,6 @@
 
 #define REAL_JOIN_REQ  0
 
-struct host_if_wpa_attr {
-   u8 *key;
-   const u8 *mac_addr;
-   u8 *seq;
-   u8 seq_len;
-   u8 index;
-   u8 key_len;
-   u8 mode;
-};
-
-struct host_if_wep_attr {
-   u8 *key;
-   u8 key_len;
-   u8 index;
-   u8 mode;
-   enum authtype auth_type;
-};
-
-union host_if_key_attr {
-   struct host_if_wep_attr wep;
-   struct host_if_wpa_attr wpa;
-   struct host_if_pmkid_attr pmkid;
-};
-
 struct scan_attr {
u8 src;
u8 type;
@@ -121,20 +97,13 @@ struct wilc_gtk_key {
u8 key[0];
 } __packed;
 
-struct set_ip_addr {
-   u8 *ip_addr;
-   u8 idx;
-};
-
 union message_body {
struct scan_attr scan_info;
struct connect_attr con_info;
struct rcvd_net_info net_info;
struct rcvd_async_info async_info;
-   struct set_ip_addr ip_info;
struct set_multicast multicast_info;
struct get_mac_addr get_mac_info;
-   struct ba_session_info session_info;
struct remain_ch remain_on_ch;
char *data;
 };
diff --git a/drivers/staging/wilc1000/host_interface.h 
b/drivers/staging/wilc1000/host_interface.h
index 477372b..d2f29ea 100644
--- a/drivers/staging/wilc1000/host_interface.h
+++ b/drivers/staging/wilc1000/host_interface.h
@@ -17,13 +17,6 @@ enum {
WILC_CLIENT_MODE = 0x4
 };
 
-enum {
-   WILC_ADD_KEY = 0x1,
-   WILC_REMOVE_KEY = 0x2,
-   WILC_DEFAULT_KEY = 0x4,
-   WILC_ADD_KEY_AP = 0x8
-};
-
 #define WILC_MAX_NUM_STA   9
 #define MAX_NUM_SCANNED_NETWORKS   100
 #define MAX_NUM_SCANNED_NETWORKS_SHADOW130
@@ -31,16 +24,10 @@ enum {
 
 #define TX_MIC_KEY_LEN 8
 #define RX_MIC_KEY_LEN 8
-#define PTK_KEY_LEN16
 
-#define RX_MIC_KEY_MSG_LEN 48
-#define PTK_KEY_MSG_LEN39
-
-#define PMKSA_KEY_LEN  22
 #define WILC_MAX_NUM_PMKIDS16
 #define WILC_ADD_STA_LENGTH40
 #define WILC_NUM_CONCURRENT_IFC2
-#define WILC_DRV_HANDLER_SIZE  5
 
 #define NUM_RSSI5
 
@@ -160,13 +147,6 @@ enum conn_event {
CONN_DISCONN_EVENT_FORCE_32BIT  = 0x
 };
 
-enum KEY_TYPE {
-   WILC_KEY_TYPE_WEP,
-   WILC_KEY_TYPE_WPA_RX_GTK,
-   WILC_KEY_TYPE_WPA_PTK,
-   WILC_KEY_TYPE_PMKSA,
-};
-
 typedef void (*wilc_scan_result)(enum scan_event, struct network_info *,
 void *, void *);
 
@@ -218,13 +198,6 @@ struct get_mac_addr {
u8 *mac_addr;
 };
 
-struct ba_session_info {
-   u8 bssid[ETH_ALEN];
-   u8 tid;
-   u16 buf_size;
-   u16 time_out;
-};
-
 struct remain_ch {
u16 ch;
u32 duration;
-- 
2.7.4



[PATCH 23/29] staging: wilc1000: use correct 'struct remain_ch' variable in scan complete

2018-12-02 Thread Ajay.Kathat
From: Ajay Singh 

Use the correct reference to remain_ch variable in scan complete.
Passing 'msg->body.remain_on_ch' to handle_remain_on_chan is not
correct. So used the correct reference used to store roc related
information during the scan.

Signed-off-by: Ajay Singh 
---
 drivers/staging/wilc1000/host_interface.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/staging/wilc1000/host_interface.c 
b/drivers/staging/wilc1000/host_interface.c
index dc02561..9139e0e 100644
--- a/drivers/staging/wilc1000/host_interface.c
+++ b/drivers/staging/wilc1000/host_interface.c
@@ -1613,7 +1613,8 @@ static void handle_scan_complete(struct work_struct *work)
handle_scan_done(msg->vif, SCAN_EVENT_DONE);
 
if (msg->vif->hif_drv->remain_on_ch_pending)
-   handle_remain_on_chan(msg->vif, >body.remain_on_ch);
+   handle_remain_on_chan(msg->vif,
+ >vif->hif_drv->remain_on_ch);
kfree(msg);
 }
 
-- 
2.7.4



[PATCH 17/29] staging: wilc1000: refactor wilc_set_operation_mode() to avoid deferred handling

2018-12-02 Thread Ajay.Kathat
From: Ajay Singh 

Avoid handling of WID_CURRENT_CHANNEL wid command in deferred approach.
Instead of posting the wid to work queue now handle directly from the
caller context. Use structure to fill in the firmware specific format.

Signed-off-by: Ajay Singh 
---
 drivers/staging/wilc1000/host_interface.c | 49 ++-
 drivers/staging/wilc1000/host_interface.h |  4 ---
 2 files changed, 16 insertions(+), 37 deletions(-)

diff --git a/drivers/staging/wilc1000/host_interface.c 
b/drivers/staging/wilc1000/host_interface.c
index 1910f9a..312c01e 100644
--- a/drivers/staging/wilc1000/host_interface.c
+++ b/drivers/staging/wilc1000/host_interface.c
@@ -85,6 +85,10 @@ struct del_all_sta {
u8 mac[WILC_MAX_NUM_STA][ETH_ALEN];
 };
 
+struct wilc_op_mode {
+   __le32 mode;
+};
+
 struct wilc_reg_frame {
bool reg;
u8 reg_id;
@@ -111,7 +115,6 @@ union message_body {
struct set_ip_addr ip_info;
struct drv_handler drv;
struct set_multicast multicast_info;
-   struct op_mode mode;
struct get_mac_addr get_mac_info;
struct ba_session_info session_info;
struct remain_ch remain_on_ch;
@@ -261,28 +264,6 @@ static void handle_set_wfi_drv_handler(struct work_struct 
*work)
kfree(msg);
 }
 
-static void handle_set_operation_mode(struct work_struct *work)
-{
-   struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
-   struct wilc_vif *vif = msg->vif;
-   struct op_mode *hif_op_mode = >body.mode;
-   int ret;
-   struct wid wid;
-
-   wid.id = WID_SET_OPERATION_MODE;
-   wid.type = WID_INT;
-   wid.val = (s8 *)_op_mode->mode;
-   wid.size = sizeof(u32);
-
-   ret = wilc_send_config_pkt(vif, WILC_SET_CFG, , 1,
-  wilc_get_vif_idx(vif));
-
-   if (ret)
-   netdev_err(vif->ndev, "Failed to set operation mode\n");
-
-   kfree(msg);
-}
-
 static void handle_get_mac_address(struct work_struct *work)
 {
struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
@@ -2550,19 +2531,21 @@ int wilc_set_wfi_drv_handler(struct wilc_vif *vif, int 
index, u8 mode,
 
 int wilc_set_operation_mode(struct wilc_vif *vif, u32 mode)
 {
+   struct wid wid;
+   struct wilc_op_mode op_mode;
int result;
-   struct host_if_msg *msg;
 
-   msg  = wilc_alloc_work(vif, handle_set_operation_mode, false);
-   if (IS_ERR(msg))
-   return PTR_ERR(msg);
+   wid.id = WID_SET_OPERATION_MODE;
+   wid.type = WID_INT;
+   wid.size = sizeof(op_mode);
+   wid.val = (u8 *)_mode;
 
-   msg->body.mode.mode = mode;
-   result = wilc_enqueue_work(msg);
-   if (result) {
-   netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__);
-   kfree(msg);
-   }
+   op_mode.mode = cpu_to_le32(mode);
+
+   result = wilc_send_config_pkt(vif, WILC_SET_CFG, , 1,
+ wilc_get_vif_idx(vif));
+   if (result)
+   netdev_err(vif->ndev, "Failed to set operation mode\n");
 
return result;
 }
diff --git a/drivers/staging/wilc1000/host_interface.h 
b/drivers/staging/wilc1000/host_interface.h
index 10d5627..e958357 100644
--- a/drivers/staging/wilc1000/host_interface.h
+++ b/drivers/staging/wilc1000/host_interface.h
@@ -220,10 +220,6 @@ struct drv_handler {
u8 name;
 };
 
-struct op_mode {
-   u32 mode;
-};
-
 struct get_mac_addr {
u8 *mac_addr;
 };
-- 
2.7.4



[PATCH 22/29] staging: wilc1000: refactor wilc_get_mac_address() to avoid deferred handling

2018-12-02 Thread Ajay.Kathat
From: Ajay Singh 

Avoid handling of WID_MAC_ADDR wid command in deferred approach. Instead
of posting the wid to workqueue now handle directly from the caller
context.

Signed-off-by: Ajay Singh 
---
 drivers/staging/wilc1000/host_interface.c | 43 ++-
 drivers/staging/wilc1000/host_interface.h |  4 ---
 2 files changed, 8 insertions(+), 39 deletions(-)

diff --git a/drivers/staging/wilc1000/host_interface.c 
b/drivers/staging/wilc1000/host_interface.c
index 71395d8..dc02561 100644
--- a/drivers/staging/wilc1000/host_interface.c
+++ b/drivers/staging/wilc1000/host_interface.c
@@ -103,7 +103,6 @@ union message_body {
struct rcvd_net_info net_info;
struct rcvd_async_info async_info;
struct set_multicast multicast_info;
-   struct get_mac_addr get_mac_info;
struct remain_ch remain_on_ch;
char *data;
 };
@@ -208,28 +207,6 @@ static struct wilc_vif *wilc_get_vif_from_idx(struct wilc 
*wilc, int idx)
return wilc->vif[index];
 }
 
-static void handle_get_mac_address(struct work_struct *work)
-{
-   struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
-   struct wilc_vif *vif = msg->vif;
-   struct get_mac_addr *get_mac_addr = >body.get_mac_info;
-   int ret;
-   struct wid wid;
-
-   wid.id = WID_MAC_ADDR;
-   wid.type = WID_STR;
-   wid.val = get_mac_addr->mac_addr;
-   wid.size = ETH_ALEN;
-
-   ret = wilc_send_config_pkt(vif, WILC_GET_CFG, , 1,
-  wilc_get_vif_idx(vif));
-
-   if (ret)
-   netdev_err(vif->ndev, "Failed to get mac address\n");
-   complete(>work_comp);
-   /* free 'msg' data later, in caller */
-}
-
 static int handle_scan_done(struct wilc_vif *vif, enum scan_event evt)
 {
int result = 0;
@@ -1934,21 +1911,17 @@ int wilc_set_pmkid_info(struct wilc_vif *vif, struct 
wilc_pmkid_attr *pmkid)
 int wilc_get_mac_address(struct wilc_vif *vif, u8 *mac_addr)
 {
int result;
-   struct host_if_msg *msg;
-
-   msg = wilc_alloc_work(vif, handle_get_mac_address, true);
-   if (IS_ERR(msg))
-   return PTR_ERR(msg);
+   struct wid wid;
 
-   msg->body.get_mac_info.mac_addr = mac_addr;
+   wid.id = WID_MAC_ADDR;
+   wid.type = WID_STR;
+   wid.size = ETH_ALEN;
+   wid.val = mac_addr;
 
-   result = wilc_enqueue_work(msg);
+   result = wilc_send_config_pkt(vif, WILC_GET_CFG, , 1,
+ wilc_get_vif_idx(vif));
if (result)
-   netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__);
-   else
-   wait_for_completion(>work_comp);
-
-   kfree(msg);
+   netdev_err(vif->ndev, "Failed to get mac address\n");
 
return result;
 }
diff --git a/drivers/staging/wilc1000/host_interface.h 
b/drivers/staging/wilc1000/host_interface.h
index d2f29ea..953f0ea 100644
--- a/drivers/staging/wilc1000/host_interface.h
+++ b/drivers/staging/wilc1000/host_interface.h
@@ -194,10 +194,6 @@ struct user_conn_req {
void *arg;
 };
 
-struct get_mac_addr {
-   u8 *mac_addr;
-};
-
 struct remain_ch {
u16 ch;
u32 duration;
-- 
2.7.4



[PATCH 19/29] staging: wilc1000: refactor wilc_get_inactive_time() to avoid deferred handling

2018-12-02 Thread Ajay.Kathat
From: Ajay Singh 

Avoid handling of inactive time related wid command in deferred manner.
Instead of posting the wid to workqueue now handle directly from the
caller context.

Signed-off-by: Ajay Singh 
---
 drivers/staging/wilc1000/host_interface.c | 91 ---
 1 file changed, 23 insertions(+), 68 deletions(-)

diff --git a/drivers/staging/wilc1000/host_interface.c 
b/drivers/staging/wilc1000/host_interface.c
index ab770d8..e3dc9b6 100644
--- a/drivers/staging/wilc1000/host_interface.c
+++ b/drivers/staging/wilc1000/host_interface.c
@@ -105,18 +105,12 @@ struct set_ip_addr {
u8 idx;
 };
 
-struct sta_inactive_t {
-   u32 inactive_time;
-   u8 mac[6];
-};
-
 union message_body {
struct scan_attr scan_info;
struct connect_attr con_info;
struct rcvd_net_info net_info;
struct rcvd_async_info async_info;
struct key_attr key_info;
-   struct sta_inactive_t mac_info;
struct set_ip_addr ip_info;
struct set_multicast multicast_info;
struct get_mac_addr get_mac_info;
@@ -1678,48 +1672,6 @@ static void handle_get_statistics(struct work_struct 
*work)
kfree(msg);
 }
 
-static void handle_get_inactive_time(struct work_struct *work)
-{
-   struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
-   struct wilc_vif *vif = msg->vif;
-   struct sta_inactive_t *hif_sta_inactive = >body.mac_info;
-   int result;
-   struct wid wid;
-
-   wid.id = WID_SET_STA_MAC_INACTIVE_TIME;
-   wid.type = WID_STR;
-   wid.size = ETH_ALEN;
-   wid.val = kmalloc(wid.size, GFP_KERNEL);
-   if (!wid.val)
-   goto out;
-
-   ether_addr_copy(wid.val, hif_sta_inactive->mac);
-
-   result = wilc_send_config_pkt(vif, WILC_SET_CFG, , 1,
- wilc_get_vif_idx(vif));
-   kfree(wid.val);
-
-   if (result) {
-   netdev_err(vif->ndev, "Failed to set inactive mac\n");
-   goto out;
-   }
-
-   wid.id = WID_GET_INACTIVE_TIME;
-   wid.type = WID_INT;
-   wid.val = (s8 *)_sta_inactive->inactive_time;
-   wid.size = sizeof(u32);
-
-   result = wilc_send_config_pkt(vif, WILC_GET_CFG, , 1,
- wilc_get_vif_idx(vif));
-
-   if (result)
-   netdev_err(vif->ndev, "Failed to get inactive time\n");
-
-out:
-   /* free 'msg' data in caller */
-   complete(>work_comp);
-}
-
 static void wilc_hif_pack_sta_param(u8 *cur_byte, const u8 *mac,
struct station_parameters *params)
 {
@@ -2508,32 +2460,35 @@ int wilc_set_operation_mode(struct wilc_vif *vif, u32 
mode)
return result;
 }
 
-s32 wilc_get_inactive_time(struct wilc_vif *vif, const u8 *mac,
-  u32 *out_val)
+s32 wilc_get_inactive_time(struct wilc_vif *vif, const u8 *mac, u32 *out_val)
 {
+   struct wid wid;
s32 result;
-   struct host_if_msg *msg;
-   struct host_if_drv *hif_drv = vif->hif_drv;
-
-   if (!hif_drv) {
-   netdev_err(vif->ndev, "%s: hif driver is NULL", __func__);
-   return -EFAULT;
-   }
 
-   msg = wilc_alloc_work(vif, handle_get_inactive_time, true);
-   if (IS_ERR(msg))
-   return PTR_ERR(msg);
+   wid.id = WID_SET_STA_MAC_INACTIVE_TIME;
+   wid.type = WID_STR;
+   wid.size = ETH_ALEN;
+   wid.val = kzalloc(wid.size, GFP_KERNEL);
+   if (!wid.val)
+   return -ENOMEM;
 
-   memcpy(msg->body.mac_info.mac, mac, ETH_ALEN);
+   ether_addr_copy(wid.val, mac);
+   result = wilc_send_config_pkt(vif, WILC_SET_CFG, , 1,
+ wilc_get_vif_idx(vif));
+   kfree(wid.val);
+   if (result) {
+   netdev_err(vif->ndev, "Failed to set inactive mac\n");
+   return result;
+   }
 
-   result = wilc_enqueue_work(msg);
+   wid.id = WID_GET_INACTIVE_TIME;
+   wid.type = WID_INT;
+   wid.val = (s8 *)out_val;
+   wid.size = sizeof(u32);
+   result = wilc_send_config_pkt(vif, WILC_GET_CFG, , 1,
+ wilc_get_vif_idx(vif));
if (result)
-   netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__);
-   else
-   wait_for_completion(>work_comp);
-
-   *out_val = msg->body.mac_info.inactive_time;
-   kfree(msg);
+   netdev_err(vif->ndev, "Failed to get inactive time\n");
 
return result;
 }
-- 
2.7.4



[PATCH 15/29] staging: wilc1000: refactor wilc_hif_set_cfg() to avoid deferred handling

2018-12-02 Thread Ajay.Kathat
From: Ajay Singh 

Avoid handling configuration params wid command in deferred approach.
Instead of posting to workqueue now handle directly from the caller
context. Reduce the size of wid array from 32 to 4 as maximum only 4 wid
used at a time.

Signed-off-by: Ajay Singh 
---
 drivers/staging/wilc1000/host_interface.c | 95 +++
 1 file changed, 32 insertions(+), 63 deletions(-)

diff --git a/drivers/staging/wilc1000/host_interface.c 
b/drivers/staging/wilc1000/host_interface.c
index f6bd76c..6b1c9e3 100644
--- a/drivers/staging/wilc1000/host_interface.c
+++ b/drivers/staging/wilc1000/host_interface.c
@@ -107,7 +107,6 @@ union message_body {
struct rcvd_net_info net_info;
struct rcvd_async_info async_info;
struct key_attr key_info;
-   struct cfg_param_attr cfg_info;
struct sta_inactive_t mac_info;
struct set_ip_addr ip_info;
struct drv_handler drv;
@@ -306,53 +305,6 @@ static void handle_get_mac_address(struct work_struct 
*work)
/* free 'msg' data later, in caller */
 }
 
-static void handle_cfg_param(struct work_struct *work)
-{
-   struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
-   struct wilc_vif *vif = msg->vif;
-   struct cfg_param_attr *param = >body.cfg_info;
-   int ret;
-   struct wid wid_list[32];
-   int i = 0;
-
-   if (param->flag & WILC_CFG_PARAM_RETRY_SHORT) {
-   wid_list[i].id = WID_SHORT_RETRY_LIMIT;
-   wid_list[i].val = (s8 *)>short_retry_limit;
-   wid_list[i].type = WID_SHORT;
-   wid_list[i].size = sizeof(u16);
-   i++;
-   }
-   if (param->flag & WILC_CFG_PARAM_RETRY_LONG) {
-   wid_list[i].id = WID_LONG_RETRY_LIMIT;
-   wid_list[i].val = (s8 *)>long_retry_limit;
-   wid_list[i].type = WID_SHORT;
-   wid_list[i].size = sizeof(u16);
-   i++;
-   }
-   if (param->flag & WILC_CFG_PARAM_FRAG_THRESHOLD) {
-   wid_list[i].id = WID_FRAG_THRESHOLD;
-   wid_list[i].val = (s8 *)>frag_threshold;
-   wid_list[i].type = WID_SHORT;
-   wid_list[i].size = sizeof(u16);
-   i++;
-   }
-   if (param->flag & WILC_CFG_PARAM_RTS_THRESHOLD) {
-   wid_list[i].id = WID_RTS_THRESHOLD;
-   wid_list[i].val = (s8 *)>rts_threshold;
-   wid_list[i].type = WID_SHORT;
-   wid_list[i].size = sizeof(u16);
-   i++;
-   }
-
-   ret = wilc_send_config_pkt(vif, WILC_SET_CFG, wid_list,
-  i, wilc_get_vif_idx(vif));
-
-   if (ret)
-   netdev_err(vif->ndev, "Error in setting CFG params\n");
-
-   kfree(msg);
-}
-
 static int handle_scan_done(struct wilc_vif *vif, enum scan_event evt)
 {
int result = 0;
@@ -2797,26 +2749,43 @@ int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 
scan_type,
return result;
 }
 
-int wilc_hif_set_cfg(struct wilc_vif *vif,
-struct cfg_param_attr *cfg_param)
+int wilc_hif_set_cfg(struct wilc_vif *vif, struct cfg_param_attr *param)
 {
-   struct host_if_msg *msg;
-   struct host_if_drv *hif_drv = vif->hif_drv;
+   struct wid wid_list[4];
+   int i = 0;
int result;
 
-   if (!hif_drv) {
-   netdev_err(vif->ndev, "%s: hif driver is NULL", __func__);
-   return -EFAULT;
+   if (param->flag & WILC_CFG_PARAM_RETRY_SHORT) {
+   wid_list[i].id = WID_SHORT_RETRY_LIMIT;
+   wid_list[i].val = (s8 *)>short_retry_limit;
+   wid_list[i].type = WID_SHORT;
+   wid_list[i].size = sizeof(u16);
+   i++;
+   }
+   if (param->flag & WILC_CFG_PARAM_RETRY_LONG) {
+   wid_list[i].id = WID_LONG_RETRY_LIMIT;
+   wid_list[i].val = (s8 *)>long_retry_limit;
+   wid_list[i].type = WID_SHORT;
+   wid_list[i].size = sizeof(u16);
+   i++;
+   }
+   if (param->flag & WILC_CFG_PARAM_FRAG_THRESHOLD) {
+   wid_list[i].id = WID_FRAG_THRESHOLD;
+   wid_list[i].val = (s8 *)>frag_threshold;
+   wid_list[i].type = WID_SHORT;
+   wid_list[i].size = sizeof(u16);
+   i++;
+   }
+   if (param->flag & WILC_CFG_PARAM_RTS_THRESHOLD) {
+   wid_list[i].id = WID_RTS_THRESHOLD;
+   wid_list[i].val = (s8 *)>rts_threshold;
+   wid_list[i].type = WID_SHORT;
+   wid_list[i].size = sizeof(u16);
+   i++;
}
 
-   msg = wilc_alloc_work(vif, handle_cfg_param, false);
-   if (IS_ERR(msg))
-   return PTR_ERR(msg);
-
-   msg->body.cfg_info = *cfg_param;
-   result = wilc_enqueue_work(msg);
-   if (result)
-   kfree(msg);
+   result = wilc_send_config_pkt(vif, WILC_SET_CFG, wid_list,
+   

[PATCH 16/29] staging: wilc1000: handle station dump cfg ops from cfg80211 context

2018-12-02 Thread Ajay.Kathat
From: Ajay Singh 

Refactor code to handle dump_station() callback from cfg80211 context.
Instead of deferring issue of wid command now send it directly from cfg
context. Also making use of wilc_get_rssi() error status in case there
is a failure to post the wid command to the firmware.

Signed-off-by: Ajay Singh 
---
 drivers/staging/wilc1000/host_interface.c | 51 ---
 drivers/staging/wilc1000/wilc_wfi_cfgoperations.c |  5 ++-
 2 files changed, 13 insertions(+), 43 deletions(-)

diff --git a/drivers/staging/wilc1000/host_interface.c 
b/drivers/staging/wilc1000/host_interface.c
index 6b1c9e3..1910f9a 100644
--- a/drivers/staging/wilc1000/host_interface.c
+++ b/drivers/staging/wilc1000/host_interface.c
@@ -1678,27 +1678,6 @@ void wilc_resolve_disconnect_aberration(struct wilc_vif 
*vif)
wilc_disconnect(vif, 1);
 }
 
-static void handle_get_rssi(struct work_struct *work)
-{
-   struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
-   struct wilc_vif *vif = msg->vif;
-   int result;
-   struct wid wid;
-
-   wid.id = WID_RSSI;
-   wid.type = WID_CHAR;
-   wid.val = msg->body.data;
-   wid.size = sizeof(char);
-
-   result = wilc_send_config_pkt(vif, WILC_GET_CFG, , 1,
- wilc_get_vif_idx(vif));
-   if (result)
-   netdev_err(vif->ndev, "Failed to get RSSI value\n");
-
-   complete(>work_comp);
-   /* free 'msg' data in caller */
-}
-
 static void handle_get_statistics(struct work_struct *work)
 {
struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
@@ -2620,34 +2599,22 @@ s32 wilc_get_inactive_time(struct wilc_vif *vif, const 
u8 *mac,
 
 int wilc_get_rssi(struct wilc_vif *vif, s8 *rssi_level)
 {
+   struct wid wid;
int result;
-   struct host_if_msg *msg;
 
if (!rssi_level) {
netdev_err(vif->ndev, "%s: RSSI level is NULL\n", __func__);
return -EFAULT;
}
 
-   msg = wilc_alloc_work(vif, handle_get_rssi, true);
-   if (IS_ERR(msg))
-   return PTR_ERR(msg);
-
-   msg->body.data = kzalloc(sizeof(s8), GFP_KERNEL);
-   if (!msg->body.data) {
-   kfree(msg);
-   return -ENOMEM;
-   }
-
-   result = wilc_enqueue_work(msg);
-   if (result) {
-   netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__);
-   } else {
-   wait_for_completion(>work_comp);
-   *rssi_level = *msg->body.data;
-   }
-
-   kfree(msg->body.data);
-   kfree(msg);
+   wid.id = WID_RSSI;
+   wid.type = WID_CHAR;
+   wid.size = sizeof(char);
+   wid.val = rssi_level;
+   result = wilc_send_config_pkt(vif, WILC_GET_CFG, , 1,
+ wilc_get_vif_idx(vif));
+   if (result)
+   netdev_err(vif->ndev, "Failed to get RSSI value\n");
 
return result;
 }
diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c 
b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c
index 18370ef..4802ce9 100644
--- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c
+++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c
@@ -1659,13 +1659,16 @@ static int dump_station(struct wiphy *wiphy, struct 
net_device *dev,
 {
struct wilc_priv *priv = wiphy_priv(wiphy);
struct wilc_vif *vif = netdev_priv(priv->dev);
+   int ret;
 
if (idx != 0)
return -ENOENT;
 
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_SIGNAL);
 
-   wilc_get_rssi(vif, >signal);
+   ret = wilc_get_rssi(vif, >signal);
+   if (ret)
+   return ret;
 
memcpy(mac, priv->associated_bss, ETH_ALEN);
return 0;
-- 
2.7.4



[PATCH 18/29] staging: wilc1000: refactor wilc_set_wfi_drv_handler() to avoid deferred handling

2018-12-02 Thread Ajay.Kathat
From: Ajay Singh 

Avoid handling of WID_SET_DRV_HANDLER wid command in deferred approach.
Instead of posting the wid to work queue now handle directly from the
caller context. Remove 'is_sync' parameter from the API as it's not
required anymore.

Signed-off-by: Ajay Singh 
---
 drivers/staging/wilc1000/host_interface.c | 82 ++-
 drivers/staging/wilc1000/host_interface.h |  8 +--
 drivers/staging/wilc1000/linux_wlan.c |  3 +-
 drivers/staging/wilc1000/wilc_wfi_cfgoperations.c |  2 +-
 4 files changed, 23 insertions(+), 72 deletions(-)

diff --git a/drivers/staging/wilc1000/host_interface.c 
b/drivers/staging/wilc1000/host_interface.c
index 312c01e..ab770d8 100644
--- a/drivers/staging/wilc1000/host_interface.c
+++ b/drivers/staging/wilc1000/host_interface.c
@@ -95,6 +95,11 @@ struct wilc_reg_frame {
__le32 frame_type;
 } __packed;
 
+struct wilc_drv_handler {
+   __le32 handler;
+   u8 mode;
+} __packed;
+
 struct set_ip_addr {
u8 *ip_addr;
u8 idx;
@@ -113,7 +118,6 @@ union message_body {
struct key_attr key_info;
struct sta_inactive_t mac_info;
struct set_ip_addr ip_info;
-   struct drv_handler drv;
struct set_multicast multicast_info;
struct get_mac_addr get_mac_info;
struct ba_session_info session_info;
@@ -221,49 +225,6 @@ static struct wilc_vif *wilc_get_vif_from_idx(struct wilc 
*wilc, int idx)
return wilc->vif[index];
 }
 
-static void handle_set_wfi_drv_handler(struct work_struct *work)
-{
-   struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
-   struct wilc_vif *vif = msg->vif;
-   struct drv_handler *hif_drv_handler = >body.drv;
-   int ret;
-   struct wid wid;
-   u8 *currbyte, *buffer;
-   struct host_if_drv *hif_drv;
-
-   if (!vif->hif_drv || !hif_drv_handler)
-   goto free_msg;
-
-   hif_drv = vif->hif_drv;
-
-   buffer = kzalloc(WILC_DRV_HANDLER_SIZE, GFP_KERNEL);
-   if (!buffer)
-   goto free_msg;
-
-   currbyte = buffer;
-   put_unaligned_le32(hif_drv->driver_handler_id, currbyte);
-   currbyte += 4;
-   *currbyte = (hif_drv_handler->name | (hif_drv_handler->mode << 1));
-
-   wid.id = WID_SET_DRV_HANDLER;
-   wid.type = WID_STR;
-   wid.val = (s8 *)buffer;
-   wid.size = WILC_DRV_HANDLER_SIZE;
-
-   ret = wilc_send_config_pkt(vif, WILC_SET_CFG, , 1,
-  hif_drv->driver_handler_id);
-   if (ret)
-   netdev_err(vif->ndev, "Failed to set driver handler\n");
-
-   kfree(buffer);
-
-free_msg:
-   if (msg->is_sync)
-   complete(>work_comp);
-
-   kfree(msg);
-}
-
 static void handle_get_mac_address(struct work_struct *work)
 {
struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
@@ -2503,28 +2464,25 @@ int wilc_set_mac_chnl_num(struct wilc_vif *vif, u8 
channel)
 }
 
 int wilc_set_wfi_drv_handler(struct wilc_vif *vif, int index, u8 mode,
-u8 ifc_id, bool is_sync)
+u8 ifc_id)
 {
+   struct wid wid;
+   struct host_if_drv *hif_drv = vif->hif_drv;
int result;
-   struct host_if_msg *msg;
-
-   msg = wilc_alloc_work(vif, handle_set_wfi_drv_handler, is_sync);
-   if (IS_ERR(msg))
-   return PTR_ERR(msg);
+   struct wilc_drv_handler drv;
 
-   msg->body.drv.handler = index;
-   msg->body.drv.mode = mode;
-   msg->body.drv.name = ifc_id;
+   wid.id = WID_SET_DRV_HANDLER;
+   wid.type = WID_STR;
+   wid.size = sizeof(drv);
+   wid.val = (u8 *)
 
-   result = wilc_enqueue_work(msg);
-   if (result) {
-   netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__);
-   kfree(msg);
-   return result;
-   }
+   drv.handler = cpu_to_le32(index);
+   drv.mode = (ifc_id | (mode << 1));
 
-   if (is_sync)
-   wait_for_completion(>work_comp);
+   result = wilc_send_config_pkt(vif, WILC_SET_CFG, , 1,
+ hif_drv->driver_handler_id);
+   if (result)
+   netdev_err(vif->ndev, "Failed to set driver handler\n");
 
return result;
 }
@@ -2814,7 +2772,7 @@ int wilc_deinit(struct wilc_vif *vif)
del_timer_sync(>periodic_rssi);
del_timer_sync(_drv->remain_on_ch_timer);
 
-   wilc_set_wfi_drv_handler(vif, 0, 0, 0, true);
+   wilc_set_wfi_drv_handler(vif, 0, 0, 0);
 
if (hif_drv->usr_scan_req.scan_result) {
hif_drv->usr_scan_req.scan_result(SCAN_EVENT_ABORTED, NULL,
diff --git a/drivers/staging/wilc1000/host_interface.h 
b/drivers/staging/wilc1000/host_interface.h
index e958357..7748f65 100644
--- a/drivers/staging/wilc1000/host_interface.h
+++ b/drivers/staging/wilc1000/host_interface.h
@@ -214,12 +214,6 @@ struct user_conn_req {
void *arg;
 };
 

[PATCH 20/29] staging: wilc1000: handle key related cfg operation from cfg80211 context

2018-12-02 Thread Ajay.Kathat
From: Ajay Singh 

Refactor add/delete key operation to handle directly from cfg80211
context. Also, avoid an extra copy of the information in hif layer and
directly fill the buffer in firmware format.

Signed-off-by: Ajay Singh 
---
 drivers/staging/wilc1000/host_interface.c | 691 ++
 drivers/staging/wilc1000/host_interface.h |  13 +-
 drivers/staging/wilc1000/wilc_wfi_cfgoperations.c |   4 +-
 drivers/staging/wilc1000/wilc_wfi_netdevice.h |   2 +-
 4 files changed, 204 insertions(+), 506 deletions(-)

diff --git a/drivers/staging/wilc1000/host_interface.c 
b/drivers/staging/wilc1000/host_interface.c
index e3dc9b6..596a321 100644
--- a/drivers/staging/wilc1000/host_interface.c
+++ b/drivers/staging/wilc1000/host_interface.c
@@ -37,12 +37,6 @@ union host_if_key_attr {
struct host_if_pmkid_attr pmkid;
 };
 
-struct key_attr {
-   enum KEY_TYPE type;
-   u8 action;
-   union host_if_key_attr attr;
-};
-
 struct scan_attr {
u8 src;
u8 type;
@@ -100,6 +94,33 @@ struct wilc_drv_handler {
u8 mode;
 } __packed;
 
+struct wilc_wep_key {
+   u8 index;
+   u8 key_len;
+   u8 key[0];
+} __packed;
+
+struct wilc_sta_wpa_ptk {
+   u8 mac_addr[ETH_ALEN];
+   u8 key_len;
+   u8 key[0];
+} __packed;
+
+struct wilc_ap_wpa_ptk {
+   u8 mac_addr[ETH_ALEN];
+   u8 index;
+   u8 key_len;
+   u8 key[0];
+} __packed;
+
+struct wilc_gtk_key {
+   u8 mac_addr[ETH_ALEN];
+   u8 rsc[8];
+   u8 index;
+   u8 key_len;
+   u8 key[0];
+} __packed;
+
 struct set_ip_addr {
u8 *ip_addr;
u8 idx;
@@ -110,7 +131,6 @@ union message_body {
struct connect_attr con_info;
struct rcvd_net_info net_info;
struct rcvd_async_info async_info;
-   struct key_attr key_info;
struct set_ip_addr ip_info;
struct set_multicast multicast_info;
struct get_mac_addr get_mac_info;
@@ -1275,264 +1295,6 @@ static void handle_rcvd_gnrl_async_info(struct 
work_struct *work)
kfree(msg);
 }
 
-static int wilc_pmksa_key_copy(struct wilc_vif *vif, struct key_attr *hif_key)
-{
-   int i;
-   int ret;
-   struct wid wid;
-   u8 *key_buf;
-
-   key_buf = kmalloc((hif_key->attr.pmkid.numpmkid * PMKSA_KEY_LEN) + 1,
- GFP_KERNEL);
-   if (!key_buf)
-   return -ENOMEM;
-
-   key_buf[0] = hif_key->attr.pmkid.numpmkid;
-
-   for (i = 0; i < hif_key->attr.pmkid.numpmkid; i++) {
-   memcpy(key_buf + ((PMKSA_KEY_LEN * i) + 1),
-  hif_key->attr.pmkid.pmkidlist[i].bssid, ETH_ALEN);
-   memcpy(key_buf + ((PMKSA_KEY_LEN * i) + ETH_ALEN + 1),
-  hif_key->attr.pmkid.pmkidlist[i].pmkid, WLAN_PMKID_LEN);
-   }
-
-   wid.id = WID_PMKID_INFO;
-   wid.type = WID_STR;
-   wid.val = (s8 *)key_buf;
-   wid.size = (hif_key->attr.pmkid.numpmkid * PMKSA_KEY_LEN) + 1;
-
-   ret = wilc_send_config_pkt(vif, WILC_SET_CFG, , 1,
-  wilc_get_vif_idx(vif));
-
-   kfree(key_buf);
-
-   return ret;
-}
-
-static void handle_key(struct work_struct *work)
-{
-   struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
-   struct wilc_vif *vif = msg->vif;
-   struct key_attr *hif_key = >body.key_info;
-   int result = 0;
-   struct wid wid;
-   struct wid wid_list[5];
-   u8 *key_buf;
-   struct host_if_drv *hif_drv = vif->hif_drv;
-
-   switch (hif_key->type) {
-   case WILC_KEY_TYPE_WEP:
-
-   if (hif_key->action & WILC_ADD_KEY_AP) {
-   wid_list[0].id = WID_11I_MODE;
-   wid_list[0].type = WID_CHAR;
-   wid_list[0].size = sizeof(char);
-   wid_list[0].val = (s8 *)_key->attr.wep.mode;
-
-   wid_list[1].id = WID_AUTH_TYPE;
-   wid_list[1].type = WID_CHAR;
-   wid_list[1].size = sizeof(char);
-   wid_list[1].val = (s8 *)_key->attr.wep.auth_type;
-
-   key_buf = kmalloc(hif_key->attr.wep.key_len + 2,
- GFP_KERNEL);
-   if (!key_buf) {
-   result = -ENOMEM;
-   goto out_wep;
-   }
-
-   key_buf[0] = hif_key->attr.wep.index;
-   key_buf[1] = hif_key->attr.wep.key_len;
-
-   memcpy(_buf[2], hif_key->attr.wep.key,
-  hif_key->attr.wep.key_len);
-
-   wid_list[2].id = WID_WEP_KEY_VALUE;
-   wid_list[2].type = WID_STR;
-   wid_list[2].size = hif_key->attr.wep.key_len + 2;
-   wid_list[2].val = (s8 *)key_buf;
-
-   result = wilc_send_config_pkt(vif, 

[PATCH 24/29] staging: wilc1000: handle remain on channel cfg ops from cfg80211 context

2018-12-02 Thread Ajay.Kathat
From: Ajay Singh 

Refactor wilc_remain_on_channel() to handle remain_on_channel callback
from cfg80211 context.

Signed-off-by: Ajay Singh 
---
 drivers/staging/wilc1000/host_interface.c | 36 ++-
 1 file changed, 11 insertions(+), 25 deletions(-)

diff --git a/drivers/staging/wilc1000/host_interface.c 
b/drivers/staging/wilc1000/host_interface.c
index 9139e0e..4762925 100644
--- a/drivers/staging/wilc1000/host_interface.c
+++ b/drivers/staging/wilc1000/host_interface.c
@@ -1592,14 +1592,6 @@ static void handle_scan_timer(struct work_struct *work)
kfree(msg);
 }
 
-static void handle_remain_on_chan_work(struct work_struct *work)
-{
-   struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
-
-   handle_remain_on_chan(msg->vif, >body.remain_on_ch);
-   kfree(msg);
-}
-
 static void handle_scan_complete(struct work_struct *work)
 {
struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
@@ -2527,25 +2519,19 @@ int wilc_remain_on_channel(struct wilc_vif *vif, u32 
session_id,
   wilc_remain_on_chan_ready ready,
   void *user_arg)
 {
+   struct remain_ch roc;
int result;
-   struct host_if_msg *msg;
-
-   msg = wilc_alloc_work(vif, handle_remain_on_chan_work, false);
-   if (IS_ERR(msg))
-   return PTR_ERR(msg);
 
-   msg->body.remain_on_ch.ch = chan;
-   msg->body.remain_on_ch.expired = expired;
-   msg->body.remain_on_ch.ready = ready;
-   msg->body.remain_on_ch.arg = user_arg;
-   msg->body.remain_on_ch.duration = duration;
-   msg->body.remain_on_ch.id = session_id;
-
-   result = wilc_enqueue_work(msg);
-   if (result) {
-   netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__);
-   kfree(msg);
-   }
+   roc.ch = chan;
+   roc.expired = expired;
+   roc.ready = ready;
+   roc.arg = user_arg;
+   roc.duration = duration;
+   roc.id = session_id;
+   result = handle_remain_on_chan(vif, );
+   if (result)
+   netdev_err(vif->ndev, "%s: failed to set remain on channel\n",
+  __func__);
 
return result;
 }
-- 
2.7.4



[PATCH 10/29] staging: wilc1000: use is_zero_ether_addr() API to check mac address

2018-12-02 Thread Ajay.Kathat
From: Ajay Singh 

Use is_zero_ether_addr() API to check if mac address value is zero.

Signed-off-by: Ajay Singh 
---
 drivers/staging/wilc1000/host_interface.c | 3 +--
 drivers/staging/wilc1000/linux_wlan.c | 3 +--
 2 files changed, 2 insertions(+), 4 deletions(-)

diff --git a/drivers/staging/wilc1000/host_interface.c 
b/drivers/staging/wilc1000/host_interface.c
index 8ce56a3..310138d 100644
--- a/drivers/staging/wilc1000/host_interface.c
+++ b/drivers/staging/wilc1000/host_interface.c
@@ -3400,13 +3400,12 @@ int wilc_del_allstation(struct wilc_vif *vif, u8 
mac_addr[][ETH_ALEN])
struct wid wid;
int result;
int i;
-   u8 zero_addr[ETH_ALEN] = {0};
u8 assoc_sta = 0;
struct del_all_sta del_sta;
 
memset(_sta, 0x0, sizeof(del_sta));
for (i = 0; i < WILC_MAX_NUM_STA; i++) {
-   if (memcmp(mac_addr[i], zero_addr, ETH_ALEN)) {
+   if (!is_zero_ether_addr(mac_addr[i])) {
assoc_sta++;
ether_addr_copy(del_sta.mac[i], mac_addr[i]);
}
diff --git a/drivers/staging/wilc1000/linux_wlan.c 
b/drivers/staging/wilc1000/linux_wlan.c
index e246d18..142816a 100644
--- a/drivers/staging/wilc1000/linux_wlan.c
+++ b/drivers/staging/wilc1000/linux_wlan.c
@@ -205,11 +205,10 @@ void wilc_wlan_set_bssid(struct net_device *wilc_netdev, 
u8 *bssid, u8 mode)
 int wilc_wlan_get_num_conn_ifcs(struct wilc *wilc)
 {
u8 i = 0;
-   u8 null_bssid[6] = {0};
u8 ret_val = 0;
 
for (i = 0; i < wilc->vif_num; i++)
-   if (memcmp(wilc->vif[i]->bssid, null_bssid, 6))
+   if (!is_zero_ether_addr(wilc->vif[i]->bssid))
ret_val++;
 
return ret_val;
-- 
2.7.4



[PATCH 08/29] staging: wilc1000: use void return for wilc_hif_pack_sta_param()

2018-12-02 Thread Ajay.Kathat
From: Ajay Singh 

Change the return type from u32 to void for wilc_hif_pack_sta_param() as
its value is not used. Also remove the use of extra pointer as it's not
required now.

Signed-off-by: Ajay Singh 
---
 drivers/staging/wilc1000/host_interface.c | 14 --
 1 file changed, 4 insertions(+), 10 deletions(-)

diff --git a/drivers/staging/wilc1000/host_interface.c 
b/drivers/staging/wilc1000/host_interface.c
index fedcff8..40477ca 100644
--- a/drivers/staging/wilc1000/host_interface.c
+++ b/drivers/staging/wilc1000/host_interface.c
@@ -1960,12 +1960,9 @@ static void handle_del_beacon(struct work_struct *work)
kfree(msg);
 }
 
-static u32 wilc_hif_pack_sta_param(u8 *buff, const u8 *mac,
-  struct station_parameters *params)
+static void wilc_hif_pack_sta_param(u8 *cur_byte, const u8 *mac,
+   struct station_parameters *params)
 {
-   u8 *cur_byte;
-
-   cur_byte = buff;
ether_addr_copy(cur_byte, mac);
cur_byte += ETH_ALEN;
 
@@ -1990,9 +1987,6 @@ static u32 wilc_hif_pack_sta_param(u8 *buff, const u8 
*mac,
put_unaligned_le16(params->sta_flags_mask, cur_byte);
cur_byte += 2;
put_unaligned_le16(params->sta_flags_set, cur_byte);
-   cur_byte += 2;
-
-   return cur_byte - buff;
 }
 
 static void handle_del_all_sta(struct work_struct *work)
@@ -3440,7 +3434,7 @@ int wilc_add_station(struct wilc_vif *vif, const u8 *mac,
return -ENOMEM;
 
cur_byte = wid.val;
-   cur_byte += wilc_hif_pack_sta_param(cur_byte, mac, params);
+   wilc_hif_pack_sta_param(cur_byte, mac, params);
 
result = wilc_send_config_pkt(vif, WILC_SET_CFG, , 1,
  wilc_get_vif_idx(vif));
@@ -3532,7 +3526,7 @@ int wilc_edit_station(struct wilc_vif *vif, const u8 *mac,
return -ENOMEM;
 
cur_byte = wid.val;
-   cur_byte += wilc_hif_pack_sta_param(cur_byte, mac, params);
+   wilc_hif_pack_sta_param(cur_byte, mac, params);
 
result = wilc_send_config_pkt(vif, WILC_SET_CFG, , 1,
  wilc_get_vif_idx(vif));
-- 
2.7.4



[PATCH 13/29] staging: wilc1000: handle mgmt_frame_register ops from cfg82011 context

2018-12-02 Thread Ajay.Kathat
From: Ajay Singh 

Avoid handling of mgmt_frame_register operation callback in a deferred
manner. Now set the wid command to firmware directly from caller
context.

Signed-off-by: Ajay Singh 
---
 drivers/staging/wilc1000/host_interface.c | 70 ++-
 drivers/staging/wilc1000/host_interface.h |  6 ---
 2 files changed, 22 insertions(+), 54 deletions(-)

diff --git a/drivers/staging/wilc1000/host_interface.c 
b/drivers/staging/wilc1000/host_interface.c
index 97b84d2..4d1fa4a 100644
--- a/drivers/staging/wilc1000/host_interface.c
+++ b/drivers/staging/wilc1000/host_interface.c
@@ -89,6 +89,12 @@ struct del_all_sta {
u8 mac[WILC_MAX_NUM_STA][ETH_ALEN];
 };
 
+struct wilc_reg_frame {
+   bool reg;
+   u8 reg_id;
+   __le32 frame_type;
+} __packed;
+
 struct set_ip_addr {
u8 *ip_addr;
u8 idx;
@@ -115,7 +121,6 @@ union message_body {
struct get_mac_addr get_mac_info;
struct ba_session_info session_info;
struct remain_ch remain_on_ch;
-   struct reg_frame reg_frame;
char *data;
 };
 
@@ -1963,39 +1968,6 @@ static int handle_remain_on_chan(struct wilc_vif *vif,
return result;
 }
 
-static void handle_register_frame(struct work_struct *work)
-{
-   struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
-   struct wilc_vif *vif = msg->vif;
-   struct reg_frame *hif_reg_frame = >body.reg_frame;
-   int result;
-   struct wid wid;
-   u8 *cur_byte;
-
-   wid.id = WID_REGISTER_FRAME;
-   wid.type = WID_STR;
-   wid.val = kmalloc(sizeof(u16) + 2, GFP_KERNEL);
-   if (!wid.val)
-   goto out;
-
-   cur_byte = wid.val;
-
-   *cur_byte++ = hif_reg_frame->reg;
-   *cur_byte++ = hif_reg_frame->reg_id;
-   memcpy(cur_byte, _reg_frame->frame_type, sizeof(u16));
-
-   wid.size = sizeof(u16) + 2;
-
-   result = wilc_send_config_pkt(vif, WILC_SET_CFG, , 1,
- wilc_get_vif_idx(vif));
-   kfree(wid.val);
-   if (result)
-   netdev_err(vif->ndev, "Failed to frame register\n");
-
-out:
-   kfree(msg);
-}
-
 static void handle_listen_state_expired(struct work_struct *work)
 {
struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
@@ -3162,33 +3134,35 @@ int wilc_listen_state_expired(struct wilc_vif *vif, u32 
session_id)
 
 void wilc_frame_register(struct wilc_vif *vif, u16 frame_type, bool reg)
 {
+   struct wid wid;
int result;
-   struct host_if_msg *msg;
+   struct wilc_reg_frame reg_frame;
 
-   msg = wilc_alloc_work(vif, handle_register_frame, false);
-   if (IS_ERR(msg))
-   return;
+   wid.id = WID_REGISTER_FRAME;
+   wid.type = WID_STR;
+   wid.size = sizeof(reg_frame);
+   wid.val = (u8 *)_frame;
+
+   memset(_frame, 0x0, sizeof(reg_frame));
+   reg_frame.reg = reg;
 
switch (frame_type) {
case IEEE80211_STYPE_ACTION:
-   msg->body.reg_frame.reg_id = WILC_FW_ACTION_FRM_IDX;
+   reg_frame.reg_id = WILC_FW_ACTION_FRM_IDX;
break;
 
case IEEE80211_STYPE_PROBE_REQ:
-   msg->body.reg_frame.reg_id = WILC_FW_PROBE_REQ_IDX;
+   reg_frame.reg_id = WILC_FW_PROBE_REQ_IDX;
break;
 
default:
break;
}
-   msg->body.reg_frame.frame_type = frame_type;
-   msg->body.reg_frame.reg = reg;
-
-   result = wilc_enqueue_work(msg);
-   if (result) {
-   netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__);
-   kfree(msg);
-   }
+   reg_frame.frame_type = cpu_to_le16(frame_type);
+   result = wilc_send_config_pkt(vif, WILC_SET_CFG, , 1,
+ wilc_get_vif_idx(vif));
+   if (result)
+   netdev_err(vif->ndev, "Failed to frame register\n");
 }
 
 int wilc_add_beacon(struct wilc_vif *vif, u32 interval, u32 dtim_period,
diff --git a/drivers/staging/wilc1000/host_interface.h 
b/drivers/staging/wilc1000/host_interface.h
index 647a1af..10d5627 100644
--- a/drivers/staging/wilc1000/host_interface.h
+++ b/drivers/staging/wilc1000/host_interface.h
@@ -244,12 +244,6 @@ struct remain_ch {
u32 id;
 };
 
-struct reg_frame {
-   bool reg;
-   u16 frame_type;
-   u8 reg_id;
-};
-
 struct wilc;
 struct host_if_drv {
struct user_scan_req usr_scan_req;
-- 
2.7.4



[PATCH 02/29] staging: wilc1000: make use of put_unaligned_le32 in handle_set_wfi_drv_handler()

2018-12-02 Thread Ajay.Kathat
From: Ajay Singh 

Make use of put_unaligned_le32() function to pack the wid command buffer
for firmware.

Signed-off-by: Ajay Singh 
---
 drivers/staging/wilc1000/host_interface.c | 10 ++
 drivers/staging/wilc1000/host_interface.h |  1 -
 2 files changed, 2 insertions(+), 9 deletions(-)

diff --git a/drivers/staging/wilc1000/host_interface.c 
b/drivers/staging/wilc1000/host_interface.c
index 3f3b013..e179a8e 100644
--- a/drivers/staging/wilc1000/host_interface.c
+++ b/drivers/staging/wilc1000/host_interface.c
@@ -289,14 +289,8 @@ static void handle_set_wfi_drv_handler(struct work_struct 
*work)
goto free_msg;
 
currbyte = buffer;
-   *currbyte = hif_drv->driver_handler_id & DRV_HANDLER_MASK;
-   currbyte++;
-   *currbyte = (u32)0 & DRV_HANDLER_MASK;
-   currbyte++;
-   *currbyte = (u32)0 & DRV_HANDLER_MASK;
-   currbyte++;
-   *currbyte = (u32)0 & DRV_HANDLER_MASK;
-   currbyte++;
+   put_unaligned_le32(hif_drv->driver_handler_id, currbyte);
+   currbyte += 4;
*currbyte = (hif_drv_handler->name | (hif_drv_handler->mode << 1));
 
wid.id = WID_SET_DRV_HANDLER;
diff --git a/drivers/staging/wilc1000/host_interface.h 
b/drivers/staging/wilc1000/host_interface.h
index 8279345..7a71cb6 100644
--- a/drivers/staging/wilc1000/host_interface.h
+++ b/drivers/staging/wilc1000/host_interface.h
@@ -41,7 +41,6 @@ enum {
 #define WILC_ADD_STA_LENGTH40
 #define WILC_NUM_CONCURRENT_IFC2
 #define WILC_DRV_HANDLER_SIZE  5
-#define DRV_HANDLER_MASK   0x00FF
 
 #define NUM_RSSI5
 
-- 
2.7.4



[PATCH 01/29] staging: wilc1000: remove unnecessary checks in wilc_mac_close()

2018-12-02 Thread Ajay.Kathat
From: Ajay Singh 

Remove unnecessary 'if' check in wilc_mac_close() as those conditions
will not happen.

Signed-off-by: Ajay Singh 
---
 drivers/staging/wilc1000/linux_wlan.c | 22 +-
 1 file changed, 1 insertion(+), 21 deletions(-)

diff --git a/drivers/staging/wilc1000/linux_wlan.c 
b/drivers/staging/wilc1000/linux_wlan.c
index 66fb988..c92ee79 100644
--- a/drivers/staging/wilc1000/linux_wlan.c
+++ b/drivers/staging/wilc1000/linux_wlan.c
@@ -896,31 +896,11 @@ netdev_tx_t wilc_mac_xmit(struct sk_buff *skb, struct 
net_device *ndev)
 
 static int wilc_mac_close(struct net_device *ndev)
 {
-   struct wilc_priv *priv;
struct wilc_vif *vif = netdev_priv(ndev);
-   struct host_if_drv *hif_drv;
-   struct wilc *wl;
-
-   if (!vif || !vif->ndev || !vif->ndev->ieee80211_ptr ||
-   !vif->ndev->ieee80211_ptr->wiphy)
-   return 0;
-
-   priv = wiphy_priv(vif->ndev->ieee80211_ptr->wiphy);
-   wl = vif->wilc;
-
-   if (!priv)
-   return 0;
-
-   hif_drv = (struct host_if_drv *)priv->hif_drv;
+   struct wilc *wl = vif->wilc;
 
netdev_dbg(ndev, "Mac close\n");
 
-   if (!wl)
-   return 0;
-
-   if (!hif_drv)
-   return 0;
-
if (wl->open_ifcs > 0)
wl->open_ifcs--;
else
-- 
2.7.4



[PATCH 11/29] staging: wilc1000: handle delete beacon cfg ops from cfg80211 context()

2018-12-02 Thread Ajay.Kathat
From: Ajay Singh 

Refactor the code to handle delete beacon cfg operation from cfg80211
context.

Signed-off-by: Ajay Singh 
---
 drivers/staging/wilc1000/host_interface.c | 39 ---
 1 file changed, 10 insertions(+), 29 deletions(-)

diff --git a/drivers/staging/wilc1000/host_interface.c 
b/drivers/staging/wilc1000/host_interface.c
index 310138d..995ca65 100644
--- a/drivers/staging/wilc1000/host_interface.c
+++ b/drivers/staging/wilc1000/host_interface.c
@@ -1934,26 +1934,6 @@ static void handle_add_beacon(struct work_struct *work)
kfree(msg);
 }
 
-static void handle_del_beacon(struct work_struct *work)
-{
-   struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
-   struct wilc_vif *vif = msg->vif;
-   int result;
-   struct wid wid;
-   u8 del_beacon = 0;
-
-   wid.id = WID_DEL_BEACON;
-   wid.type = WID_CHAR;
-   wid.size = sizeof(char);
-   wid.val = _beacon;
-
-   result = wilc_send_config_pkt(vif, WILC_SET_CFG, , 1,
- wilc_get_vif_idx(vif));
-   if (result)
-   netdev_err(vif->ndev, "Failed to send delete beacon\n");
-   kfree(msg);
-}
-
 static void wilc_hif_pack_sta_param(u8 *cur_byte, const u8 *mac,
struct station_parameters *params)
 {
@@ -3326,17 +3306,18 @@ int wilc_add_beacon(struct wilc_vif *vif, u32 interval, 
u32 dtim_period,
 int wilc_del_beacon(struct wilc_vif *vif)
 {
int result;
-   struct host_if_msg *msg;
+   struct wid wid;
+   u8 del_beacon = 0;
 
-   msg = wilc_alloc_work(vif, handle_del_beacon, false);
-   if (IS_ERR(msg))
-   return PTR_ERR(msg);
+   wid.id = WID_DEL_BEACON;
+   wid.type = WID_CHAR;
+   wid.size = sizeof(char);
+   wid.val = _beacon;
 
-   result = wilc_enqueue_work(msg);
-   if (result) {
-   netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__);
-   kfree(msg);
-   }
+   result = wilc_send_config_pkt(vif, WILC_SET_CFG, , 1,
+ wilc_get_vif_idx(vif));
+   if (result)
+   netdev_err(vif->ndev, "Failed to send delete beacon\n");
 
return result;
 }
-- 
2.7.4



[PATCH 09/29] staging: wilc1000: handle delete station related callback ops from cfg80211 context

2018-12-02 Thread Ajay.Kathat
From: Ajay Singh 

Refactor the code to handle delete/delete_all station operation callback
from cfg80211 context.

Signed-off-by: Ajay Singh 
---
 drivers/staging/wilc1000/host_interface.c | 147 +++---
 1 file changed, 33 insertions(+), 114 deletions(-)

diff --git a/drivers/staging/wilc1000/host_interface.c 
b/drivers/staging/wilc1000/host_interface.c
index 40477ca..8ce56a3 100644
--- a/drivers/staging/wilc1000/host_interface.c
+++ b/drivers/staging/wilc1000/host_interface.c
@@ -94,12 +94,8 @@ struct set_multicast {
 };
 
 struct del_all_sta {
-   u8 del_all_sta[WILC_MAX_NUM_STA][ETH_ALEN];
u8 assoc_sta;
-};
-
-struct del_sta {
-   u8 mac_addr[ETH_ALEN];
+   u8 mac[WILC_MAX_NUM_STA][ETH_ALEN];
 };
 
 struct set_ip_addr {
@@ -121,7 +117,6 @@ union message_body {
struct cfg_param_attr cfg_info;
struct channel_attr channel_info;
struct beacon_attr beacon_info;
-   struct del_sta del_sta_info;
struct sta_inactive_t mac_info;
struct set_ip_addr ip_info;
struct drv_handler drv;
@@ -132,7 +127,6 @@ union message_body {
struct remain_ch remain_on_ch;
struct reg_frame reg_frame;
char *data;
-   struct del_all_sta del_all_sta_info;
 };
 
 struct host_if_msg {
@@ -1989,78 +1983,6 @@ static void wilc_hif_pack_sta_param(u8 *cur_byte, const 
u8 *mac,
put_unaligned_le16(params->sta_flags_set, cur_byte);
 }
 
-static void handle_del_all_sta(struct work_struct *work)
-{
-   struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
-   struct wilc_vif *vif = msg->vif;
-   struct del_all_sta *param = >body.del_all_sta_info;
-   int result;
-   struct wid wid;
-   u8 *curr_byte;
-   u8 i;
-   u8 zero_buff[6] = {0};
-
-   wid.id = WID_DEL_ALL_STA;
-   wid.type = WID_STR;
-   wid.size = (param->assoc_sta * ETH_ALEN) + 1;
-
-   wid.val = kmalloc((param->assoc_sta * ETH_ALEN) + 1, GFP_KERNEL);
-   if (!wid.val)
-   goto error;
-
-   curr_byte = wid.val;
-
-   *(curr_byte++) = param->assoc_sta;
-
-   for (i = 0; i < WILC_MAX_NUM_STA; i++) {
-   if (memcmp(param->del_all_sta[i], zero_buff, ETH_ALEN))
-   memcpy(curr_byte, param->del_all_sta[i], ETH_ALEN);
-   else
-   continue;
-
-   curr_byte += ETH_ALEN;
-   }
-
-   result = wilc_send_config_pkt(vif, WILC_SET_CFG, , 1,
- wilc_get_vif_idx(vif));
-   if (result)
-   netdev_err(vif->ndev, "Failed to send delete all station\n");
-
-error:
-   kfree(wid.val);
-
-   /* free 'msg' data in caller */
-   complete(>work_comp);
-}
-
-static void handle_del_station(struct work_struct *work)
-{
-   struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
-   struct wilc_vif *vif = msg->vif;
-   struct del_sta *param = >body.del_sta_info;
-   int result;
-   struct wid wid;
-
-   wid.id = WID_REMOVE_STA;
-   wid.type = WID_BIN;
-   wid.size = ETH_ALEN;
-
-   wid.val = kmalloc(wid.size, GFP_KERNEL);
-   if (!wid.val)
-   goto error;
-
-   ether_addr_copy(wid.val, param->mac_addr);
-
-   result = wilc_send_config_pkt(vif, WILC_SET_CFG, , 1,
- wilc_get_vif_idx(vif));
-   if (result)
-   netdev_err(vif->ndev, "Failed to del station\n");
-
-error:
-   kfree(wid.val);
-   kfree(msg);
-}
-
 static int handle_remain_on_chan(struct wilc_vif *vif,
 struct remain_ch *hif_remain_ch)
 {
@@ -3448,65 +3370,62 @@ int wilc_add_station(struct wilc_vif *vif, const u8 
*mac,
 
 int wilc_del_station(struct wilc_vif *vif, const u8 *mac_addr)
 {
+   struct wid wid;
int result;
-   struct host_if_msg *msg;
-   struct del_sta *del_sta_info;
-
-   msg = wilc_alloc_work(vif, handle_del_station, false);
-   if (IS_ERR(msg))
-   return PTR_ERR(msg);
 
-   del_sta_info = >body.del_sta_info;
+   wid.id = WID_REMOVE_STA;
+   wid.type = WID_BIN;
+   wid.size = ETH_ALEN;
+   wid.val = kzalloc(wid.size, GFP_KERNEL);
+   if (!wid.val)
+   return -ENOMEM;
 
if (!mac_addr)
-   eth_broadcast_addr(del_sta_info->mac_addr);
+   eth_broadcast_addr(wid.val);
else
-   memcpy(del_sta_info->mac_addr, mac_addr, ETH_ALEN);
+   ether_addr_copy(wid.val, mac_addr);
+
+   result = wilc_send_config_pkt(vif, WILC_SET_CFG, , 1,
+ wilc_get_vif_idx(vif));
+   if (result)
+   netdev_err(vif->ndev, "Failed to del station\n");
+
+   kfree(wid.val);
 
-   result = wilc_enqueue_work(msg);
-   if (result) {
-   netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__);
-   kfree(msg);
-   }
  

[PATCH 14/29] staging: wilc1000: refactor wilc_set_mac_chnl_num() to avoid deferred handling

2018-12-02 Thread Ajay.Kathat
From: Ajay Singh 

Avoid handling of WID_CURRENT_CHANNEL wid command in deferred approach.
Instead of posting the wid to workqueue now handle directly from the
caller context.

Signed-off-by: Ajay Singh 
---
 drivers/staging/wilc1000/host_interface.c | 46 ++-
 1 file changed, 9 insertions(+), 37 deletions(-)

diff --git a/drivers/staging/wilc1000/host_interface.c 
b/drivers/staging/wilc1000/host_interface.c
index 4d1fa4a..f6bd76c 100644
--- a/drivers/staging/wilc1000/host_interface.c
+++ b/drivers/staging/wilc1000/host_interface.c
@@ -74,10 +74,6 @@ struct rcvd_async_info {
u32 len;
 };
 
-struct channel_attr {
-   u8 set_ch;
-};
-
 struct set_multicast {
bool enabled;
u32 cnt;
@@ -112,7 +108,6 @@ union message_body {
struct rcvd_async_info async_info;
struct key_attr key_info;
struct cfg_param_attr cfg_info;
-   struct channel_attr channel_info;
struct sta_inactive_t mac_info;
struct set_ip_addr ip_info;
struct drv_handler drv;
@@ -224,27 +219,6 @@ static struct wilc_vif *wilc_get_vif_from_idx(struct wilc 
*wilc, int idx)
return wilc->vif[index];
 }
 
-static void handle_set_channel(struct work_struct *work)
-{
-   struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
-   struct wilc_vif *vif = msg->vif;
-   struct channel_attr *hif_set_ch = >body.channel_info;
-   int ret;
-   struct wid wid;
-
-   wid.id = WID_CURRENT_CHANNEL;
-   wid.type = WID_CHAR;
-   wid.val = (char *)_set_ch->set_ch;
-   wid.size = sizeof(char);
-
-   ret = wilc_send_config_pkt(vif, WILC_SET_CFG, , 1,
-  wilc_get_vif_idx(vif));
-
-   if (ret)
-   netdev_err(vif->ndev, "Failed to set channel\n");
-   kfree(msg);
-}
-
 static void handle_set_wfi_drv_handler(struct work_struct *work)
 {
struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
@@ -2600,20 +2574,18 @@ int wilc_disconnect(struct wilc_vif *vif, u16 
reason_code)
 
 int wilc_set_mac_chnl_num(struct wilc_vif *vif, u8 channel)
 {
+   struct wid wid;
int result;
-   struct host_if_msg *msg;
 
-   msg = wilc_alloc_work(vif, handle_set_channel, false);
-   if (IS_ERR(msg))
-   return PTR_ERR(msg);
-
-   msg->body.channel_info.set_ch = channel;
+   wid.id = WID_CURRENT_CHANNEL;
+   wid.type = WID_CHAR;
+   wid.size = sizeof(char);
+   wid.val = 
 
-   result = wilc_enqueue_work(msg);
-   if (result) {
-   netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__);
-   kfree(msg);
-   }
+   result = wilc_send_config_pkt(vif, WILC_SET_CFG, , 1,
+ wilc_get_vif_idx(vif));
+   if (result)
+   netdev_err(vif->ndev, "Failed to set channel\n");
 
return result;
 }
-- 
2.7.4



[PATCH 12/29] staging: wilc1000: handle add beacon operation callback from cfg80211 context

2018-12-02 Thread Ajay.Kathat
From: Ajay Singh 

Refactor add/change beacon cfg80211 operation callback to handle from
cfg context. Also avoided extra copy of information by packing directly
in firmware expected format.

Signed-off-by: Ajay Singh 
---
 drivers/staging/wilc1000/host_interface.c | 128 +-
 drivers/staging/wilc1000/host_interface.h |   2 +-
 drivers/staging/wilc1000/wilc_wfi_cfgoperations.c |  10 +-
 3 files changed, 32 insertions(+), 108 deletions(-)

diff --git a/drivers/staging/wilc1000/host_interface.c 
b/drivers/staging/wilc1000/host_interface.c
index 995ca65..97b84d2 100644
--- a/drivers/staging/wilc1000/host_interface.c
+++ b/drivers/staging/wilc1000/host_interface.c
@@ -78,15 +78,6 @@ struct channel_attr {
u8 set_ch;
 };
 
-struct beacon_attr {
-   u32 interval;
-   u32 dtim_period;
-   u32 head_len;
-   u8 *head;
-   u32 tail_len;
-   u8 *tail;
-};
-
 struct set_multicast {
bool enabled;
u32 cnt;
@@ -116,7 +107,6 @@ union message_body {
struct key_attr key_info;
struct cfg_param_attr cfg_info;
struct channel_attr channel_info;
-   struct beacon_attr beacon_info;
struct sta_inactive_t mac_info;
struct set_ip_addr ip_info;
struct drv_handler drv;
@@ -1878,62 +1868,6 @@ static void handle_get_inactive_time(struct work_struct 
*work)
complete(>work_comp);
 }
 
-static void handle_add_beacon(struct work_struct *work)
-{
-   struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
-   struct wilc_vif *vif = msg->vif;
-   struct beacon_attr *param = >body.beacon_info;
-   int result;
-   struct wid wid;
-   u8 *cur_byte;
-
-   wid.id = WID_ADD_BEACON;
-   wid.type = WID_BIN;
-   wid.size = param->head_len + param->tail_len + 16;
-   wid.val = kmalloc(wid.size, GFP_KERNEL);
-   if (!wid.val)
-   goto error;
-
-   cur_byte = wid.val;
-   *cur_byte++ = (param->interval & 0xFF);
-   *cur_byte++ = ((param->interval >> 8) & 0xFF);
-   *cur_byte++ = ((param->interval >> 16) & 0xFF);
-   *cur_byte++ = ((param->interval >> 24) & 0xFF);
-
-   *cur_byte++ = (param->dtim_period & 0xFF);
-   *cur_byte++ = ((param->dtim_period >> 8) & 0xFF);
-   *cur_byte++ = ((param->dtim_period >> 16) & 0xFF);
-   *cur_byte++ = ((param->dtim_period >> 24) & 0xFF);
-
-   *cur_byte++ = (param->head_len & 0xFF);
-   *cur_byte++ = ((param->head_len >> 8) & 0xFF);
-   *cur_byte++ = ((param->head_len >> 16) & 0xFF);
-   *cur_byte++ = ((param->head_len >> 24) & 0xFF);
-
-   memcpy(cur_byte, param->head, param->head_len);
-   cur_byte += param->head_len;
-
-   *cur_byte++ = (param->tail_len & 0xFF);
-   *cur_byte++ = ((param->tail_len >> 8) & 0xFF);
-   *cur_byte++ = ((param->tail_len >> 16) & 0xFF);
-   *cur_byte++ = ((param->tail_len >> 24) & 0xFF);
-
-   if (param->tail)
-   memcpy(cur_byte, param->tail, param->tail_len);
-   cur_byte += param->tail_len;
-
-   result = wilc_send_config_pkt(vif, WILC_SET_CFG, , 1,
- wilc_get_vif_idx(vif));
-   if (result)
-   netdev_err(vif->ndev, "Failed to send add beacon\n");
-
-error:
-   kfree(wid.val);
-   kfree(param->head);
-   kfree(param->tail);
-   kfree(msg);
-}
-
 static void wilc_hif_pack_sta_param(u8 *cur_byte, const u8 *mac,
struct station_parameters *params)
 {
@@ -3258,47 +3192,43 @@ void wilc_frame_register(struct wilc_vif *vif, u16 
frame_type, bool reg)
 }
 
 int wilc_add_beacon(struct wilc_vif *vif, u32 interval, u32 dtim_period,
-   u32 head_len, u8 *head, u32 tail_len, u8 *tail)
+   struct cfg80211_beacon_data *params)
 {
+   struct wid wid;
int result;
-   struct host_if_msg *msg;
-   struct beacon_attr *beacon_info;
+   u8 *cur_byte;
 
-   msg = wilc_alloc_work(vif, handle_add_beacon, false);
-   if (IS_ERR(msg))
-   return PTR_ERR(msg);
+   wid.id = WID_ADD_BEACON;
+   wid.type = WID_BIN;
+   wid.size = params->head_len + params->tail_len + 16;
+   wid.val = kzalloc(wid.size, GFP_KERNEL);
+   if (!wid.val)
+   return -ENOMEM;
 
-   beacon_info = >body.beacon_info;
-   beacon_info->interval = interval;
-   beacon_info->dtim_period = dtim_period;
-   beacon_info->head_len = head_len;
-   beacon_info->head = kmemdup(head, head_len, GFP_KERNEL);
-   if (!beacon_info->head) {
-   result = -ENOMEM;
-   goto error;
-   }
-   beacon_info->tail_len = tail_len;
+   cur_byte = wid.val;
+   put_unaligned_le32(interval, cur_byte);
+   cur_byte += 4;
+   put_unaligned_le32(dtim_period, cur_byte);
+   cur_byte += 4;
+   put_unaligned_le32(params->head_len, cur_byte);
+   cur_byte += 4;
 
-   if (tail_len > 

[PATCH 04/29] staging: wilc1000: use mutex lock to synchronized sending 'wid' cmd to firmware

2018-12-02 Thread Ajay.Kathat
From: Ajay Singh 

Use mutex lock to protect the issuing of wid cmd to the firmware.
Currently the wid commands are synchronized by use of hif_workqueue work
queue.
Now, these changes are required to synchronize the access to wid
command, so the commands can be issued directly from cfg80211 context
and 'WILC_wq' thread.

Signed-off-by: Ajay Singh 
---
 drivers/staging/wilc1000/linux_wlan.c |  2 ++
 drivers/staging/wilc1000/wilc_wfi_netdevice.h |  3 ++-
 drivers/staging/wilc1000/wilc_wlan.c  | 21 ++---
 3 files changed, 14 insertions(+), 12 deletions(-)

diff --git a/drivers/staging/wilc1000/linux_wlan.c 
b/drivers/staging/wilc1000/linux_wlan.c
index c92ee79..e246d18 100644
--- a/drivers/staging/wilc1000/linux_wlan.c
+++ b/drivers/staging/wilc1000/linux_wlan.c
@@ -531,6 +531,7 @@ static void wlan_deinit_locks(struct net_device *dev)
 
mutex_destroy(>hif_cs);
mutex_destroy(>rxq_cs);
+   mutex_destroy(>cfg_cmd_lock);
mutex_destroy(>txq_add_to_head_cs);
 }
 
@@ -592,6 +593,7 @@ static void wlan_init_locks(struct net_device *dev)
 
mutex_init(>hif_cs);
mutex_init(>rxq_cs);
+   mutex_init(>cfg_cmd_lock);
 
spin_lock_init(>txq_spinlock);
mutex_init(>txq_add_to_head_cs);
diff --git a/drivers/staging/wilc1000/wilc_wfi_netdevice.h 
b/drivers/staging/wilc1000/wilc_wfi_netdevice.h
index e71d949..02970c3 100644
--- a/drivers/staging/wilc1000/wilc_wfi_netdevice.h
+++ b/drivers/staging/wilc1000/wilc_wfi_netdevice.h
@@ -247,7 +247,8 @@ struct wilc {
struct task_struct *txq_thread;
 
int quit;
-   int cfg_frame_in_use;
+   /* lock to protect issue of wid command to firmware */
+   struct mutex cfg_cmd_lock;
struct wilc_cfg_frame cfg_frame;
u32 cfg_frame_offset;
int cfg_seq_no;
diff --git a/drivers/staging/wilc1000/wilc_wlan.c 
b/drivers/staging/wilc1000/wilc_wlan.c
index f0b10e2..3c5e9e0 100644
--- a/drivers/staging/wilc1000/wilc_wlan.c
+++ b/drivers/staging/wilc1000/wilc_wlan.c
@@ -1122,8 +1122,7 @@ int wilc_wlan_cfg_set(struct wilc_vif *vif, int start, 
u16 wid, u8 *buffer,
int ret_size;
struct wilc *wilc = vif->wilc;
 
-   if (wilc->cfg_frame_in_use)
-   return 0;
+   mutex_lock(>cfg_cmd_lock);
 
if (start)
wilc->cfg_frame_offset = 0;
@@ -1134,11 +1133,12 @@ int wilc_wlan_cfg_set(struct wilc_vif *vif, int start, 
u16 wid, u8 *buffer,
offset += ret_size;
wilc->cfg_frame_offset = offset;
 
-   if (!commit)
+   if (!commit) {
+   mutex_unlock(>cfg_cmd_lock);
return ret_size;
+   }
 
netdev_dbg(vif->ndev, "%s: seqno[%d]\n", __func__, wilc->cfg_seq_no);
-   wilc->cfg_frame_in_use = 1;
 
if (wilc_wlan_cfg_commit(vif, WILC_CFG_SET, drv_handler))
ret_size = 0;
@@ -1149,9 +1149,9 @@ int wilc_wlan_cfg_set(struct wilc_vif *vif, int start, 
u16 wid, u8 *buffer,
ret_size = 0;
}
 
-   wilc->cfg_frame_in_use = 0;
wilc->cfg_frame_offset = 0;
wilc->cfg_seq_no += 1;
+   mutex_unlock(>cfg_cmd_lock);
 
return ret_size;
 }
@@ -1163,8 +1163,7 @@ int wilc_wlan_cfg_get(struct wilc_vif *vif, int start, 
u16 wid, int commit,
int ret_size;
struct wilc *wilc = vif->wilc;
 
-   if (wilc->cfg_frame_in_use)
-   return 0;
+   mutex_lock(>cfg_cmd_lock);
 
if (start)
wilc->cfg_frame_offset = 0;
@@ -1174,10 +1173,10 @@ int wilc_wlan_cfg_get(struct wilc_vif *vif, int start, 
u16 wid, int commit,
offset += ret_size;
wilc->cfg_frame_offset = offset;
 
-   if (!commit)
+   if (!commit) {
+   mutex_unlock(>cfg_cmd_lock);
return ret_size;
-
-   wilc->cfg_frame_in_use = 1;
+   }
 
if (wilc_wlan_cfg_commit(vif, WILC_CFG_QUERY, drv_handler))
ret_size = 0;
@@ -1187,9 +1186,9 @@ int wilc_wlan_cfg_get(struct wilc_vif *vif, int start, 
u16 wid, int commit,
netdev_dbg(vif->ndev, "%s: Timed Out\n", __func__);
ret_size = 0;
}
-   wilc->cfg_frame_in_use = 0;
wilc->cfg_frame_offset = 0;
wilc->cfg_seq_no += 1;
+   mutex_unlock(>cfg_cmd_lock);
 
return ret_size;
 }
-- 
2.7.4



[PATCH 06/29] staging: wilc1000: handle setting power management from cfg80211 context

2018-12-02 Thread Ajay.Kathat
From: Ajay Singh 

Refactor the code to handle the power management cfg operation from the
caller context.

Signed-off-by: Ajay Singh 
---
 drivers/staging/wilc1000/host_interface.c | 56 +++
 1 file changed, 13 insertions(+), 43 deletions(-)

diff --git a/drivers/staging/wilc1000/host_interface.c 
b/drivers/staging/wilc1000/host_interface.c
index 88d9010..4074a37 100644
--- a/drivers/staging/wilc1000/host_interface.c
+++ b/drivers/staging/wilc1000/host_interface.c
@@ -102,11 +102,6 @@ struct del_sta {
u8 mac_addr[ETH_ALEN];
 };
 
-struct power_mgmt_param {
-   bool enabled;
-   u32 timeout;
-};
-
 struct set_ip_addr {
u8 *ip_addr;
u8 idx;
@@ -129,7 +124,6 @@ union message_body {
struct add_sta_param add_sta_info;
struct del_sta del_sta_info;
struct add_sta_param edit_sta_info;
-   struct power_mgmt_param pwr_mgmt_info;
struct sta_inactive_t mac_info;
struct set_ip_addr ip_info;
struct drv_handler drv;
@@ -2298,32 +2292,6 @@ static void listen_timer_cb(struct timer_list *t)
}
 }
 
-static void handle_power_management(struct work_struct *work)
-{
-   struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
-   struct wilc_vif *vif = msg->vif;
-   struct power_mgmt_param *pm_param = >body.pwr_mgmt_info;
-   int result;
-   struct wid wid;
-   s8 power_mode;
-
-   wid.id = WID_POWER_MANAGEMENT;
-
-   if (pm_param->enabled)
-   power_mode = WILC_FW_MIN_FAST_PS;
-   else
-   power_mode = WILC_FW_NO_POWERSAVE;
-
-   wid.val = _mode;
-   wid.size = sizeof(char);
-
-   result = wilc_send_config_pkt(vif, WILC_SET_CFG, , 1,
- wilc_get_vif_idx(vif));
-   if (result)
-   netdev_err(vif->ndev, "Failed to send power management\n");
-   kfree(msg);
-}
-
 static void handle_set_mcast_filter(struct work_struct *work)
 {
struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
@@ -3647,24 +3615,26 @@ int wilc_edit_station(struct wilc_vif *vif,
 
 int wilc_set_power_mgmt(struct wilc_vif *vif, bool enabled, u32 timeout)
 {
+   struct wid wid;
int result;
-   struct host_if_msg *msg;
+   s8 power_mode;
 
if (wilc_wlan_get_num_conn_ifcs(vif->wilc) == 2 && enabled)
return 0;
 
-   msg = wilc_alloc_work(vif, handle_power_management, false);
-   if (IS_ERR(msg))
-   return PTR_ERR(msg);
+   if (enabled)
+   power_mode = WILC_FW_MIN_FAST_PS;
+   else
+   power_mode = WILC_FW_NO_POWERSAVE;
 
-   msg->body.pwr_mgmt_info.enabled = enabled;
-   msg->body.pwr_mgmt_info.timeout = timeout;
+   wid.id = WID_POWER_MANAGEMENT;
+   wid.val = _mode;
+   wid.size = sizeof(char);
+   result = wilc_send_config_pkt(vif, WILC_SET_CFG, , 1,
+ wilc_get_vif_idx(vif));
+   if (result)
+   netdev_err(vif->ndev, "Failed to send power management\n");
 
-   result = wilc_enqueue_work(msg);
-   if (result) {
-   netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__);
-   kfree(msg);
-   }
return result;
 }
 
-- 
2.7.4



[PATCH 05/29] staging: wilc1000: handle tx power related callback from cfg80211 context

2018-12-02 Thread Ajay.Kathat
From: Ajay Singh 

Avoid the use of internal work queue to defer the handling of tx power
related cfg operations callback. Now issuing the wid command to firmware
directly from the caller context.

Signed-off-by: Ajay Singh 
---
 drivers/staging/wilc1000/host_interface.c | 85 +--
 1 file changed, 14 insertions(+), 71 deletions(-)

diff --git a/drivers/staging/wilc1000/host_interface.c 
b/drivers/staging/wilc1000/host_interface.c
index e179a8e..88d9010 100644
--- a/drivers/staging/wilc1000/host_interface.c
+++ b/drivers/staging/wilc1000/host_interface.c
@@ -117,10 +117,6 @@ struct sta_inactive_t {
u8 mac[6];
 };
 
-struct tx_power {
-   u8 tx_pwr;
-};
-
 union message_body {
struct scan_attr scan_info;
struct connect_attr con_info;
@@ -145,7 +141,6 @@ union message_body {
struct reg_frame reg_frame;
char *data;
struct del_all_sta del_all_sta_info;
-   struct tx_power tx_power;
 };
 
 struct host_if_msg {
@@ -2371,48 +2366,6 @@ static void handle_set_mcast_filter(struct work_struct 
*work)
kfree(msg);
 }
 
-static void handle_set_tx_pwr(struct work_struct *work)
-{
-   struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
-   struct wilc_vif *vif = msg->vif;
-   u8 tx_pwr = msg->body.tx_power.tx_pwr;
-   int ret;
-   struct wid wid;
-
-   wid.id = WID_TX_POWER;
-   wid.type = WID_CHAR;
-   wid.val = _pwr;
-   wid.size = sizeof(char);
-
-   ret = wilc_send_config_pkt(vif, WILC_SET_CFG, , 1,
-  wilc_get_vif_idx(vif));
-   if (ret)
-   netdev_err(vif->ndev, "Failed to set TX PWR\n");
-   kfree(msg);
-}
-
-/* Note: 'msg' will be free after using data */
-static void handle_get_tx_pwr(struct work_struct *work)
-{
-   struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
-   struct wilc_vif *vif = msg->vif;
-   u8 *tx_pwr = >body.tx_power.tx_pwr;
-   int ret;
-   struct wid wid;
-
-   wid.id = WID_TX_POWER;
-   wid.type = WID_CHAR;
-   wid.val = (s8 *)tx_pwr;
-   wid.size = sizeof(char);
-
-   ret = wilc_send_config_pkt(vif, WILC_GET_CFG, , 1,
-  wilc_get_vif_idx(vif));
-   if (ret)
-   netdev_err(vif->ndev, "Failed to get TX PWR\n");
-
-   complete(>work_comp);
-}
-
 static void handle_scan_timer(struct work_struct *work)
 {
struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
@@ -3740,19 +3693,15 @@ int wilc_setup_multicast_filter(struct wilc_vif *vif, 
bool enabled, u32 count,
 int wilc_set_tx_power(struct wilc_vif *vif, u8 tx_power)
 {
int ret;
-   struct host_if_msg *msg;
-
-   msg = wilc_alloc_work(vif, handle_set_tx_pwr, false);
-   if (IS_ERR(msg))
-   return PTR_ERR(msg);
+   struct wid wid;
 
-   msg->body.tx_power.tx_pwr = tx_power;
+   wid.id = WID_TX_POWER;
+   wid.type = WID_CHAR;
+   wid.val = _power;
+   wid.size = sizeof(char);
 
-   ret = wilc_enqueue_work(msg);
-   if (ret) {
-   netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__);
-   kfree(msg);
-   }
+   ret = wilc_send_config_pkt(vif, WILC_SET_CFG, , 1,
+  wilc_get_vif_idx(vif));
 
return ret;
 }
@@ -3760,21 +3709,15 @@ int wilc_set_tx_power(struct wilc_vif *vif, u8 tx_power)
 int wilc_get_tx_power(struct wilc_vif *vif, u8 *tx_power)
 {
int ret;
-   struct host_if_msg *msg;
+   struct wid wid;
 
-   msg = wilc_alloc_work(vif, handle_get_tx_pwr, true);
-   if (IS_ERR(msg))
-   return PTR_ERR(msg);
+   wid.id = WID_TX_POWER;
+   wid.type = WID_CHAR;
+   wid.val = tx_power;
+   wid.size = sizeof(char);
 
-   ret = wilc_enqueue_work(msg);
-   if (ret) {
-   netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__);
-   } else {
-   wait_for_completion(>work_comp);
-   *tx_power = msg->body.tx_power.tx_pwr;
-   }
+   ret = wilc_send_config_pkt(vif, WILC_GET_CFG, , 1,
+  wilc_get_vif_idx(vif));
 
-   /* free 'msg' after copying data */
-   kfree(msg);
return ret;
 }
-- 
2.7.4



[PATCH 07/29] staging: wilc1000: handle add and edit station from the cfg80211 context

2018-12-02 Thread Ajay.Kathat
From: Ajay Singh 

Refactor the code to avoid handling of add/edit stations using work
queue and now set the wid value from caller context.
Avoid making an extra copy of buffer and directly copy the data in
firmware expected format.

Signed-off-by: Ajay Singh 
---
 drivers/staging/wilc1000/host_interface.c | 192 +++---
 drivers/staging/wilc1000/host_interface.h |   7 +-
 drivers/staging/wilc1000/wilc_wfi_cfgoperations.c |  35 +---
 3 files changed, 67 insertions(+), 167 deletions(-)

diff --git a/drivers/staging/wilc1000/host_interface.c 
b/drivers/staging/wilc1000/host_interface.c
index 4074a37..fedcff8 100644
--- a/drivers/staging/wilc1000/host_interface.c
+++ b/drivers/staging/wilc1000/host_interface.c
@@ -121,9 +121,7 @@ union message_body {
struct cfg_param_attr cfg_info;
struct channel_attr channel_info;
struct beacon_attr beacon_info;
-   struct add_sta_param add_sta_info;
struct del_sta del_sta_info;
-   struct add_sta_param edit_sta_info;
struct sta_inactive_t mac_info;
struct set_ip_addr ip_info;
struct drv_handler drv;
@@ -1962,67 +1960,41 @@ static void handle_del_beacon(struct work_struct *work)
kfree(msg);
 }
 
-static u32 wilc_hif_pack_sta_param(u8 *buff, struct add_sta_param *param)
+static u32 wilc_hif_pack_sta_param(u8 *buff, const u8 *mac,
+  struct station_parameters *params)
 {
u8 *cur_byte;
 
cur_byte = buff;
-
-   memcpy(cur_byte, param->bssid, ETH_ALEN);
-   cur_byte +=  ETH_ALEN;
-
-   *cur_byte++ = param->aid & 0xFF;
-   *cur_byte++ = (param->aid >> 8) & 0xFF;
-
-   *cur_byte++ = param->rates_len;
-   if (param->rates_len > 0)
-   memcpy(cur_byte, param->rates, param->rates_len);
-   cur_byte += param->rates_len;
-
-   *cur_byte++ = param->ht_supported;
-   memcpy(cur_byte, >ht_capa, sizeof(struct ieee80211_ht_cap));
+   ether_addr_copy(cur_byte, mac);
+   cur_byte += ETH_ALEN;
+
+   put_unaligned_le16(params->aid, cur_byte);
+   cur_byte += 2;
+
+   *cur_byte++ = params->supported_rates_len;
+   if (params->supported_rates_len > 0)
+   memcpy(cur_byte, params->supported_rates,
+  params->supported_rates_len);
+   cur_byte += params->supported_rates_len;
+
+   if (params->ht_capa) {
+   *cur_byte++ = true;
+   memcpy(cur_byte, >ht_capa,
+  sizeof(struct ieee80211_ht_cap));
+   } else {
+   *cur_byte++ = false;
+   }
cur_byte += sizeof(struct ieee80211_ht_cap);
 
-   *cur_byte++ = param->flags_mask & 0xFF;
-   *cur_byte++ = (param->flags_mask >> 8) & 0xFF;
-
-   *cur_byte++ = param->flags_set & 0xFF;
-   *cur_byte++ = (param->flags_set >> 8) & 0xFF;
+   put_unaligned_le16(params->sta_flags_mask, cur_byte);
+   cur_byte += 2;
+   put_unaligned_le16(params->sta_flags_set, cur_byte);
+   cur_byte += 2;
 
return cur_byte - buff;
 }
 
-static void handle_add_station(struct work_struct *work)
-{
-   struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
-   struct wilc_vif *vif = msg->vif;
-   struct add_sta_param *param = >body.add_sta_info;
-   int result;
-   struct wid wid;
-   u8 *cur_byte;
-
-   wid.id = WID_ADD_STA;
-   wid.type = WID_BIN;
-   wid.size = WILC_ADD_STA_LENGTH + param->rates_len;
-
-   wid.val = kmalloc(wid.size, GFP_KERNEL);
-   if (!wid.val)
-   goto error;
-
-   cur_byte = wid.val;
-   cur_byte += wilc_hif_pack_sta_param(cur_byte, param);
-
-   result = wilc_send_config_pkt(vif, WILC_SET_CFG, , 1,
- wilc_get_vif_idx(vif));
-   if (result != 0)
-   netdev_err(vif->ndev, "Failed to send add station\n");
-
-error:
-   kfree(param->rates);
-   kfree(wid.val);
-   kfree(msg);
-}
-
 static void handle_del_all_sta(struct work_struct *work)
 {
struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
@@ -2095,37 +2067,6 @@ static void handle_del_station(struct work_struct *work)
kfree(msg);
 }
 
-static void handle_edit_station(struct work_struct *work)
-{
-   struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
-   struct wilc_vif *vif = msg->vif;
-   struct add_sta_param *param = >body.edit_sta_info;
-   int result;
-   struct wid wid;
-   u8 *cur_byte;
-
-   wid.id = WID_EDIT_STA;
-   wid.type = WID_BIN;
-   wid.size = WILC_ADD_STA_LENGTH + param->rates_len;
-
-   wid.val = kmalloc(wid.size, GFP_KERNEL);
-   if (!wid.val)
-   goto error;
-
-   cur_byte = wid.val;
-   cur_byte += wilc_hif_pack_sta_param(cur_byte, param);
-
-   result = wilc_send_config_pkt(vif, WILC_SET_CFG, , 1,
- 

[PATCH 03/29] staging: wilc1000: avoid the use of the static variable to configure wiphy struct

2018-12-02 Thread Ajay.Kathat
From: Ajay Singh 

Refactor code to avoid the use of static variables to configure the
'wiphy' structure. Now move static variables as part of 'priv' data so
it helped to maintain this information per interface.

Signed-off-by: Ajay Singh 
---
 drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 92 +--
 drivers/staging/wilc1000/wilc_wfi_netdevice.h | 60 +++
 2 files changed, 80 insertions(+), 72 deletions(-)

diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c 
b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c
index 1dec6bb..69b181f 100644
--- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c
+++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c
@@ -32,14 +32,6 @@
 #define nl80211_SCAN_RESULT_EXPIRE (3 * HZ)
 #define SCAN_RESULT_EXPIRE (40 * HZ)
 
-static const u32 cipher_suites[] = {
-   WLAN_CIPHER_SUITE_WEP40,
-   WLAN_CIPHER_SUITE_WEP104,
-   WLAN_CIPHER_SUITE_TKIP,
-   WLAN_CIPHER_SUITE_CCMP,
-   WLAN_CIPHER_SUITE_AES_CMAC,
-};
-
 static const struct ieee80211_txrx_stypes
wilc_wfi_cfg80211_mgmt_types[NUM_NL80211_IFTYPES] = {
[NL80211_IFTYPE_STATION] = {
@@ -73,53 +65,6 @@ static const struct wiphy_wowlan_support wowlan_support = {
.flags = WIPHY_WOWLAN_ANY
 };
 
-#define CHAN2G(_channel, _freq, _flags) {   \
-   .band = NL80211_BAND_2GHZ, \
-   .center_freq  = (_freq), \
-   .hw_value = (_channel),  \
-   .flags= (_flags),\
-   .max_antenna_gain = 0,   \
-   .max_power= 30,  \
-}
-
-static struct ieee80211_channel ieee80211_2ghz_channels[] = {
-   CHAN2G(1,  2412, 0),
-   CHAN2G(2,  2417, 0),
-   CHAN2G(3,  2422, 0),
-   CHAN2G(4,  2427, 0),
-   CHAN2G(5,  2432, 0),
-   CHAN2G(6,  2437, 0),
-   CHAN2G(7,  2442, 0),
-   CHAN2G(8,  2447, 0),
-   CHAN2G(9,  2452, 0),
-   CHAN2G(10, 2457, 0),
-   CHAN2G(11, 2462, 0),
-   CHAN2G(12, 2467, 0),
-   CHAN2G(13, 2472, 0),
-   CHAN2G(14, 2484, 0),
-};
-
-#define RATETAB_ENT(_rate, _hw_value, _flags) {\
-   .bitrate  = (_rate),\
-   .hw_value = (_hw_value),\
-   .flags= (_flags),   \
-}
-
-static struct ieee80211_rate ieee80211_bitrates[] = {
-   RATETAB_ENT(10,  0,  0),
-   RATETAB_ENT(20,  1,  0),
-   RATETAB_ENT(55,  2,  0),
-   RATETAB_ENT(110, 3,  0),
-   RATETAB_ENT(60,  9,  0),
-   RATETAB_ENT(90,  6,  0),
-   RATETAB_ENT(120, 7,  0),
-   RATETAB_ENT(180, 8,  0),
-   RATETAB_ENT(240, 9,  0),
-   RATETAB_ENT(360, 10, 0),
-   RATETAB_ENT(480, 11, 0),
-   RATETAB_ENT(540, 12, 0),
-};
-
 struct p2p_mgmt_data {
int size;
u8 *buff;
@@ -130,13 +75,6 @@ static u8 curr_channel;
 static u8 p2p_oui[] = {0x50, 0x6f, 0x9A, 0x09};
 static u8 p2p_vendor_spec[] = {0xdd, 0x05, 0x00, 0x08, 0x40, 0x03};
 
-static struct ieee80211_supported_band wilc_band_2ghz = {
-   .channels = ieee80211_2ghz_channels,
-   .n_channels = ARRAY_SIZE(ieee80211_2ghz_channels),
-   .bitrates = ieee80211_bitrates,
-   .n_bitrates = ARRAY_SIZE(ieee80211_bitrates),
-};
-
 #define AGING_TIME (9 * 1000)
 #define DURING_IP_TIME_OUT 15000
 
@@ -2110,14 +2048,6 @@ static struct wireless_dev *wilc_wfi_cfg_alloc(void)
if (!wdev->wiphy)
goto free_mem;
 
-   wilc_band_2ghz.ht_cap.ht_supported = 1;
-   wilc_band_2ghz.ht_cap.cap |= (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT);
-   wilc_band_2ghz.ht_cap.mcs.rx_mask[0] = 0xff;
-   wilc_band_2ghz.ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_8K;
-   wilc_band_2ghz.ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_NONE;
-
-   wdev->wiphy->bands[NL80211_BAND_2GHZ] = _band_2ghz;
-
return wdev;
 
 free_mem:
@@ -2141,6 +2071,22 @@ struct wireless_dev *wilc_create_wiphy(struct net_device 
*net,
 
priv = wdev_priv(wdev);
priv->wdev = wdev;
+
+   memcpy(priv->bitrates, wilc_bitrates, sizeof(wilc_bitrates));
+   memcpy(priv->channels, wilc_2ghz_channels, sizeof(wilc_2ghz_channels));
+   priv->band.bitrates = priv->bitrates;
+   priv->band.n_bitrates = ARRAY_SIZE(priv->bitrates);
+   priv->band.channels = priv->channels;
+   priv->band.n_channels = ARRAY_SIZE(wilc_2ghz_channels);
+
+   priv->band.ht_cap.ht_supported = 1;
+   priv->band.ht_cap.cap |= (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT);
+   priv->band.ht_cap.mcs.rx_mask[0] = 0xff;
+   priv->band.ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_8K;
+   priv->band.ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_NONE;
+
+   wdev->wiphy->bands[NL80211_BAND_2GHZ] = >band;
+
wdev->wiphy->max_scan_ssids = WILC_MAX_NUM_PROBED_SSID;
 #ifdef CONFIG_PM
wdev->wiphy->wowlan = 

[PATCH 00/29] staging: wilc1000: avoid deferring of cfg80211 operation callback

2018-12-02 Thread Ajay.Kathat
From: Ajay Singh 

This patch series mainly contains the change to handle the cfg80211
operation from its context. Now the WID commands are sent to firmware
directly from the caller context.
Also added few more patches to address the review comment received
earlier in series[1].

[1]. https://www.spinics.net/lists/linux-wireless/msg178705.html
 https://www.spinics.net/lists/linux-wireless/msg178707.html
 https://www.spinics.net/lists/linux-wireless/msg178709.html

Ajay Singh (29):
  staging: wilc1000: remove unnecessary checks in wilc_mac_close()
  staging: wilc1000: make use of put_unaligned_le32 in
handle_set_wfi_drv_handler()
  staging: wilc1000: avoid the use of the static variable to configure
wiphy struct
  staging: wilc1000: use mutex lock to synchronized sending 'wid' cmd to
firmware
  staging: wilc1000: handle tx power related callback from cfg80211
context
  staging: wilc1000: handle setting power management from cfg80211
context
  staging: wilc1000: handle add and edit station from the cfg80211
context
  staging: wilc1000: use void return for wilc_hif_pack_sta_param()
  staging: wilc1000: handle delete station related callback ops from
cfg80211 context
  staging: wilc1000: use is_zero_ether_addr() API to check mac address
  staging: wilc1000: handle delete beacon cfg ops from cfg80211
context()
  staging: wilc1000: handle add beacon operation callback from cfg80211
context
  staging: wilc1000: handle mgmt_frame_register ops from cfg82011
context
  staging: wilc1000: refactor wilc_set_mac_chnl_num() to avoid deferred
handling
  staging: wilc1000: refactor wilc_hif_set_cfg() to avoid deferred
handling
  staging: wilc1000: handle station dump cfg ops from cfg80211 context
  staging: wilc1000: refactor wilc_set_operation_mode() to avoid
deferred handling
  staging: wilc1000: refactor wilc_set_wfi_drv_handler() to avoid
deferred handling
  staging: wilc1000: refactor wilc_get_inactive_time() to avoid deferred
handling
  staging: wilc1000: handle key related cfg operation from cfg80211
context
  staging: wilc1000: delete the unused code after code refactor
  staging: wilc1000: refactor wilc_get_mac_address() to avoid deferred
handling
  staging: wilc1000: use correct 'struct remain_ch' variable in scan
complete
  staging: wilc1000: handle remain on channel cfg ops from cfg80211
context
  staging: wilc1000: handle get_station() ops callback in cfg80211
context
  staging: wilc1000: avoid deferred handling of cfg80211 disconnect
callback
  staging: wilc1000: handle connect ops callback from cfg80211 context
  staging: wilc1000: avoid extra buffer copy while connect cfg ops
  staging: wilc1000: handle scan operation callback from cfg80211
context

 drivers/staging/wilc1000/host_interface.c | 2405 ++---
 drivers/staging/wilc1000/host_interface.h |   79 +-
 drivers/staging/wilc1000/linux_wlan.c |   30 +-
 drivers/staging/wilc1000/wilc_wfi_cfgoperations.c |  167 +-
 drivers/staging/wilc1000/wilc_wfi_netdevice.h |   65 +-
 drivers/staging/wilc1000/wilc_wlan.c  |   21 +-
 6 files changed, 755 insertions(+), 2012 deletions(-)

-- 
2.7.4



Re: [PATCH] mac80211: allow AP_VLAN operation on crypto controlled devices

2018-12-02 Thread Sebastian Gottschall
yes you just missed that ap_vlan is used for 4addr ap's / wds too so 
that might be related to the weired handling


Sebastian

Am 02.12.2018 um 14:02 schrieb Alexander Wetzel:

Hello,


From: Manikanta Pubbisetty 

In the current implementation, mac80211 advertises the support of
AP_VLANs based on the driver's support for AP mode; it also
blocks encrypted AP_VLAN operation on devices advertising
SW_CRYPTO_CONTROL.

The implementation seems weird in it's current form and could be
often confusing, this is because there can be drivers advertising
both SW_CRYPTO_CONTROL and AP mode support (ex: ath10k) in which case
AP_VLAN will still be supported but only in open BSS and not in
secured BSS.

When SW_CRYPTO_CONTROL is enabled, it makes more sense if the decision
to support AP_VLANs is left to the driver. Mac80211 can then allow
AP_VLAN operations depending on the driver support.


This first part of the patch contradicts my current understanding of 
how Software crypto fallback can be triggered: We have a driver 
actively telling us to only fall back to sw crypto when it returns 1 
on set_key, BUT we ignore that when the interface is set to 
@NL80211_IFTYPE_AP_VLAN and allow software encryption unconditionally?


Here the code:
    case WLAN_CIPHER_SUITE_GCMP:
    case WLAN_CIPHER_SUITE_GCMP_256:
    /* all of these we can do in software - if driver can */
    if (ret == 1)
    return 0;
    if (ieee80211_hw_check(>local->hw,
   SW_CRYPTO_CONTROL)) {
    if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
    return 0;
    return -EINVAL;
    }
    return 0;
    default:
    return -EINVAL;
    }


Wouldn't it be preferable to just return "ret" or "-EINVAL" instead of 
"0" when the interface has @NL80211_IFTYPE_AP_VLAN set?

As it is this basically overrides SW_CRYPTO_CONTROL in AP Vlan mode!

For me it looks like the old behavior in this section was already fine 
and does not hurt the intention of this patch: A driver setting 
SW_CRYPTO_CONTROL won't get support for AP VLANs as long as the driver 
is not opting in to it.


Therefore I would like to undo this part of the patch again:

-    if (ieee80211_hw_check(>local->hw,
   SW_CRYPTO_CONTROL))
+    if (ieee80211_hw_check(>local->hw,
   SW_CRYPTO_CONTROL)) {
+    if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
+    return 0;
 return -EINVAL;
+    }


Do I miss something here and would anyone have issues when I revert 
that in another patch?


Alexander



Re: [PATCH] mac80211: allow AP_VLAN operation on crypto controlled devices

2018-12-02 Thread Alexander Wetzel

Hello,


From: Manikanta Pubbisetty 

In the current implementation, mac80211 advertises the support of
AP_VLANs based on the driver's support for AP mode; it also
blocks encrypted AP_VLAN operation on devices advertising
SW_CRYPTO_CONTROL.

The implementation seems weird in it's current form and could be
often confusing, this is because there can be drivers advertising
both SW_CRYPTO_CONTROL and AP mode support (ex: ath10k) in which case
AP_VLAN will still be supported but only in open BSS and not in
secured BSS.

When SW_CRYPTO_CONTROL is enabled, it makes more sense if the decision
to support AP_VLANs is left to the driver. Mac80211 can then allow
AP_VLAN operations depending on the driver support.


This first part of the patch contradicts my current understanding of how 
Software crypto fallback can be triggered: We have a driver actively 
telling us to only fall back to sw crypto when it returns 1 on set_key, 
BUT we ignore that when the interface is set to @NL80211_IFTYPE_AP_VLAN 
and allow software encryption unconditionally?


Here the code:
case WLAN_CIPHER_SUITE_GCMP:
case WLAN_CIPHER_SUITE_GCMP_256:
/* all of these we can do in software - if driver can */
if (ret == 1)
return 0;
if (ieee80211_hw_check(>local->hw,
   SW_CRYPTO_CONTROL)) {
if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
return 0;
return -EINVAL;
}
return 0;
default:
return -EINVAL;
}


Wouldn't it be preferable to just return "ret" or "-EINVAL" instead of 
"0" when the interface has @NL80211_IFTYPE_AP_VLAN set?

As it is this basically overrides SW_CRYPTO_CONTROL in AP Vlan mode!

For me it looks like the old behavior in this section was already fine 
and does not hurt the intention of this patch: A driver setting 
SW_CRYPTO_CONTROL won't get support for AP VLANs as long as the driver 
is not opting in to it.


Therefore I would like to undo this part of the patch again:

-   if (ieee80211_hw_check(>local->hw,
   SW_CRYPTO_CONTROL))
+   if (ieee80211_hw_check(>local->hw,
   SW_CRYPTO_CONTROL)) {
+   if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
+   return 0;
return -EINVAL;
+   }


Do I miss something here and would anyone have issues when I revert that 
in another patch?


Alexander


Re: wlcore update breaks on 4.9 and 4.4 kernel branches

2018-12-02 Thread Sasha Levin

On Thu, Nov 29, 2018 at 05:56:31PM -0500, Dietmar May wrote:
I've run into some problems which appear due to (a) recent patch(es) 
on the wlcore wifi driver.


4.4.160 - commit 3fdd34643ffc378b5924941fad40352c04610294
4.9.131 - commit afeeecc764436f31d4447575bb9007732333818c

Earlier versions (4.9.130 and 4.4.159 - tested back to 4.4.49) do not 
exhibit this problem. It is still present in 4.9.141.


master as of 4.20.0-rc4 does not exhibit this problem.

Basically, during client association when in AP mode (running 
hostapd), handshake may or may not complete following a noticeable 
delay. If successful, then the driver fails consistently in 
warn_slowpath_null during disassociation. If unsuccessful, the wifi 
client attempts multiple times, sometimes failing repeatedly. I've had 
clients unable to connect for 3-5 minutes during testing, with the 
syslog filled with dozens of backtraces. syslog details are below.


I'm working on an embedded device with a TI 3352 ARM processor and a 
murata wl1271 module in sdio mode. We're running a fully patched 
ubuntu 18.04 ARM build, with a kernel built from kernel.org's 
stable/linux repo . 
Relevant parts of the kernel config are included below.


The commit message states:

/I've only seen this few times with the runtime PM patches enabled 
so this one is probably not needed before that. This seems to work 
currently based on the current PM implementation timer. Let's apply 
this separately though in case others are hitting this issue./
We're not doing anything explicit with power management. The device is 
an IoT edge gateway with battery backup, normally running on wall 
power. The battery is currently used solely to shut down the system 
cleanly to avoid filesystem corruption.


The device tree is configured to keep power in suspend; but the device 
should never suspend, so in our case, there is no need to call 
wl1271_ps_elp_wakeup() or wl1271_ps_elp_sleep(), as occurs in the 
patch.


Given that this patch went in through AUTOSEL, I've queued up a revert
of it (sorry for the trouble!).

I'll link this mail in the revert message. If anyone feels that this
patch should be in any of the LTS trees then either reply to this thread
or start a new one on sta...@vger.kernel.org.

--
Thanks,
Sasha


[PATCH] mt76: Add missing include of linux/module.h

2018-12-02 Thread Hauke Mehrtens
MODULE_FIRMWARE() is used in usb_mcu.c and provided by linux/module.h,
but this header file is not directly included. This causes problems in
backports with some kernel versions.

Add the missing include.

Signed-off-by: Hauke Mehrtens 
---
 drivers/net/wireless/mediatek/mt76/mt76x0/usb_mcu.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/usb_mcu.c 
b/drivers/net/wireless/mediatek/mt76/mt76x0/usb_mcu.c
index a9f14d5149d1..b2b3fd0db4bb 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/usb_mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/usb_mcu.c
@@ -15,6 +15,7 @@
  */
 #include 
 #include 
+#include 
 
 #include "mt76x0.h"
 #include "mcu.h"
-- 
2.11.0



[PATCH 10/12] wil6210: check null pointer in _wil_cfg80211_merge_extra_ies

2018-12-02 Thread Maya Erez
From: Alexei Avshalom Lazar 

ies1 or ies2 might be null when code inside
_wil_cfg80211_merge_extra_ies access them.
Add explicit check for null and make sure ies1/ies2 are not accessed in
such a case.
spos might be null and be accessed inside _wil_cfg80211_merge_extra_ies.
Add explicit check for null in the while condition statement and make
sure spos is not accessed in such a case.

Signed-off-by: Alexei Avshalom Lazar 
Signed-off-by: Maya Erez 
---
 drivers/net/wireless/ath/wil6210/cfg80211.c | 14 +++---
 1 file changed, 11 insertions(+), 3 deletions(-)

diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c 
b/drivers/net/wireless/ath/wil6210/cfg80211.c
index ad5ac7d..f3fa1a0 100644
--- a/drivers/net/wireless/ath/wil6210/cfg80211.c
+++ b/drivers/net/wireless/ath/wil6210/cfg80211.c
@@ -1576,6 +1576,12 @@ static int _wil_cfg80211_merge_extra_ies(const u8 *ies1, 
u16 ies1_len,
u8 *buf, *dpos;
const u8 *spos;
 
+   if (!ies1)
+   ies1_len = 0;
+
+   if (!ies2)
+   ies2_len = 0;
+
if (ies1_len == 0 && ies2_len == 0) {
*merged_ies = NULL;
*merged_len = 0;
@@ -1585,17 +1591,19 @@ static int _wil_cfg80211_merge_extra_ies(const u8 
*ies1, u16 ies1_len,
buf = kmalloc(ies1_len + ies2_len, GFP_KERNEL);
if (!buf)
return -ENOMEM;
-   memcpy(buf, ies1, ies1_len);
+   if (ies1)
+   memcpy(buf, ies1, ies1_len);
dpos = buf + ies1_len;
spos = ies2;
-   while (spos + 1 < ies2 + ies2_len) {
+   while (spos && (spos + 1 < ies2 + ies2_len)) {
/* IE tag at offset 0, length at offset 1 */
u16 ielen = 2 + spos[1];
 
if (spos + ielen > ies2 + ies2_len)
break;
if (spos[0] == WLAN_EID_VENDOR_SPECIFIC &&
-   !_wil_cfg80211_find_ie(ies1, ies1_len, spos, ielen)) {
+   (!ies1 || !_wil_cfg80211_find_ie(ies1, ies1_len,
+spos, ielen))) {
memcpy(dpos, spos, ielen);
dpos += ielen;
}
-- 
1.9.1



[PATCH 11/12] wil6210: align to latest auto generated wmi.h

2018-12-02 Thread Maya Erez
From: Alexei Avshalom Lazar 

Align to latest version of the auto generated wmi file
describing the interface with FW.

Signed-off-by: Alexei Avshalom Lazar 
Signed-off-by: Maya Erez 
---
 drivers/net/wireless/ath/wil6210/wmi.c |  7 +
 drivers/net/wireless/ath/wil6210/wmi.h | 48 +-
 2 files changed, 54 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/ath/wil6210/wmi.c 
b/drivers/net/wireless/ath/wil6210/wmi.c
index 509a255..88269e3 100644
--- a/drivers/net/wireless/ath/wil6210/wmi.c
+++ b/drivers/net/wireless/ath/wil6210/wmi.c
@@ -2954,6 +2954,10 @@ static const char *suspend_status2name(u8 status)
switch (status) {
case WMI_TRAFFIC_SUSPEND_REJECTED_LINK_NOT_IDLE:
return "LINK_NOT_IDLE";
+   case WMI_TRAFFIC_SUSPEND_REJECTED_DISCONNECT:
+   return "DISCONNECT";
+   case WMI_TRAFFIC_SUSPEND_REJECTED_OTHER:
+   return "OTHER";
default:
return "Untracked status";
}
@@ -3043,6 +3047,9 @@ static void resume_triggers2string(u32 triggers, char 
*string, int str_size)
 
if (triggers & WMI_RESUME_TRIGGER_WMI_EVT)
strlcat(string, " WMI_EVT", str_size);
+
+   if (triggers & WMI_RESUME_TRIGGER_DISCONNECT)
+   strlcat(string, " DISCONNECT", str_size);
 }
 
 int wmi_resume(struct wil6210_priv *wil)
diff --git a/drivers/net/wireless/ath/wil6210/wmi.h 
b/drivers/net/wireless/ath/wil6210/wmi.h
index b668758..cce5270 100644
--- a/drivers/net/wireless/ath/wil6210/wmi.h
+++ b/drivers/net/wireless/ath/wil6210/wmi.h
@@ -1982,6 +1982,7 @@ enum wmi_event_id {
WMI_BEAMFORMING_MGMT_DONE_EVENTID   = 0x1836,
WMI_BF_TXSS_MGMT_DONE_EVENTID   = 0x1837,
WMI_BF_RXSS_MGMT_DONE_EVENTID   = 0x1839,
+   WMI_BF_TRIG_EVENTID = 0x183A,
WMI_RS_MGMT_DONE_EVENTID= 0x1852,
WMI_RF_MGMT_STATUS_EVENTID  = 0x1853,
WMI_BF_SM_MGMT_DONE_EVENTID = 0x1838,
@@ -2267,7 +2268,9 @@ struct wmi_notify_req_done_event {
__le32 status;
__le64 tsf;
s8 rssi;
-   u8 reserved0[3];
+   /* enum wmi_edmg_tx_mode */
+   u8 tx_mode;
+   u8 reserved0[2];
__le32 tx_tpt;
__le32 tx_goodput;
__le32 rx_goodput;
@@ -3168,6 +3171,30 @@ struct wmi_brp_set_ant_limit_event {
u8 reserved[3];
 } __packed;
 
+enum wmi_bf_type {
+   WMI_BF_TYPE_SLS = 0x00,
+   WMI_BF_TYPE_BRP_RX  = 0x01,
+};
+
+/* WMI_BF_TRIG_CMDID */
+struct wmi_bf_trig_cmd {
+   /* enum wmi_bf_type - type of requested beamforming */
+   u8 bf_type;
+   /* used only for WMI_BF_TYPE_BRP_RX */
+   u8 cid;
+   /* used only for WMI_BF_TYPE_SLS */
+   u8 dst_mac[WMI_MAC_LEN];
+   u8 reserved[4];
+} __packed;
+
+/* WMI_BF_TRIG_EVENTID */
+struct wmi_bf_trig_event {
+   /* enum wmi_fw_status */
+   u8 status;
+   u8 cid;
+   u8 reserved[2];
+} __packed;
+
 /* broadcast connection ID */
 #define WMI_LINK_MAINTAIN_CFG_CID_BROADCAST(0x)
 
@@ -3263,6 +3290,8 @@ struct wmi_link_maintain_cfg_read_done_event {
 enum wmi_traffic_suspend_status {
WMI_TRAFFIC_SUSPEND_APPROVED= 0x0,
WMI_TRAFFIC_SUSPEND_REJECTED_LINK_NOT_IDLE  = 0x1,
+   WMI_TRAFFIC_SUSPEND_REJECTED_DISCONNECT = 0x2,
+   WMI_TRAFFIC_SUSPEND_REJECTED_OTHER  = 0x3,
 };
 
 /* WMI_TRAFFIC_SUSPEND_EVENTID */
@@ -3282,6 +3311,7 @@ enum wmi_resume_trigger {
WMI_RESUME_TRIGGER_UCAST_RX = 0x2,
WMI_RESUME_TRIGGER_BCAST_RX = 0x4,
WMI_RESUME_TRIGGER_WMI_EVT  = 0x8,
+   WMI_RESUME_TRIGGER_DISCONNECT   = 0x10,
 };
 
 /* WMI_TRAFFIC_RESUME_EVENTID */
@@ -4057,4 +4087,20 @@ struct wmi_set_vring_priority_event {
u8 reserved[3];
 } __packed;
 
+/* WMI_RADAR_PCI_CTRL_BLOCK struct */
+struct wmi_radar_pci_ctrl_block {
+   /* last fw tail address index */
+   __le32 fw_tail_index;
+   /* last SW head address index known to FW */
+   __le32 sw_head_index;
+   __le32 last_wr_pulse_tsf_low;
+   __le32 last_wr_pulse_count;
+   __le32 last_wr_in_bytes;
+   __le32 last_wr_pulse_id;
+   __le32 last_wr_burst_id;
+   /* When pre overflow detected, advance sw head in unit of pulses */
+   __le32 sw_head_inc;
+   __le32 reserved[8];
+} __packed;
+
 #endif /* __WILOCITY_WMI_H__ */
-- 
1.9.1



[PATCH 00/12] wil6210 patches

2018-12-02 Thread Maya Erez
The following set of patches include:
- Use platform specific configuration instead of wil6210 module parameters
- Various wil6210 fixes.

Ahmad Masri (5):
  wil6210: support ndo_select_queue in net_device_ops
  wil6210: add support for AC queues per station
  wil6210: support up to 20 stations in AP mode
  wil6210: accessing 802.3 addresses via utility functions
  wil6210: prevent device memory access while in reset or suspend

Alexei Avshalom Lazar (2):
  wil6210: check null pointer in _wil_cfg80211_merge_extra_ies
  wil6210: align to latest auto generated wmi.h

Dedy Lansky (2):
  wil6210: add option to drop Tx packets when tx ring is full
  wil6210: fix invalid sta statistics update

Maya Erez (3):
  wil6210: remove rtap_include_phy_info module param
  wil6210: use platform specific configuration
  wil6210: ignore HALP ICR if already handled

 drivers/net/wireless/ath/wil6210/cfg80211.c   |  41 ++-
 drivers/net/wireless/ath/wil6210/debugfs.c|  46 ++-
 drivers/net/wireless/ath/wil6210/interrupt.c  |  10 +-
 drivers/net/wireless/ath/wil6210/main.c   | 160 +
 drivers/net/wireless/ath/wil6210/netdev.c |  75 +++-
 drivers/net/wireless/ath/wil6210/pcie_bus.c   |  31 +-
 drivers/net/wireless/ath/wil6210/pm.c |  29 +-
 drivers/net/wireless/ath/wil6210/rx_reorder.c |   8 +-
 drivers/net/wireless/ath/wil6210/trace.h  |   2 +-
 drivers/net/wireless/ath/wil6210/txrx.c   | 405 +++---
 drivers/net/wireless/ath/wil6210/txrx.h   |  49 ++-
 drivers/net/wireless/ath/wil6210/txrx_edma.c  |  12 +-
 drivers/net/wireless/ath/wil6210/wil6210.h|  68 ++--
 drivers/net/wireless/ath/wil6210/wil_crash_dump.c |  16 +-
 drivers/net/wireless/ath/wil6210/wil_platform.h   |  28 ++
 drivers/net/wireless/ath/wil6210/wmi.c| 109 --
 drivers/net/wireless/ath/wil6210/wmi.h|  48 ++-
 17 files changed, 793 insertions(+), 344 deletions(-)

-- 
1.9.1



[PATCH 12/12] wil6210: prevent device memory access while in reset or suspend

2018-12-02 Thread Maya Erez
From: Ahmad Masri 

Accessing some of the memory of the device while the device is
resetting or suspending may cause unexpected error as the HW is still
not in a stable state. Prevent this access to guarantee successful
read/write memory operations.

Signed-off-by: Ahmad Masri 
Signed-off-by: Maya Erez 
---
 drivers/net/wireless/ath/wil6210/debugfs.c| 26 +++---
 drivers/net/wireless/ath/wil6210/main.c   | 41 +--
 drivers/net/wireless/ath/wil6210/pm.c | 27 +--
 drivers/net/wireless/ath/wil6210/wil6210.h|  5 ++-
 drivers/net/wireless/ath/wil6210/wil_crash_dump.c | 16 +++--
 5 files changed, 79 insertions(+), 36 deletions(-)

diff --git a/drivers/net/wireless/ath/wil6210/debugfs.c 
b/drivers/net/wireless/ath/wil6210/debugfs.c
index 4980678..3373e54 100644
--- a/drivers/net/wireless/ath/wil6210/debugfs.c
+++ b/drivers/net/wireless/ath/wil6210/debugfs.c
@@ -280,6 +280,11 @@ static void wil_print_mbox_ring(struct seq_file *s, const 
char *prefix,
 
wil_halp_vote(wil);
 
+   if (wil_mem_access_lock(wil)) {
+   wil_halp_unvote(wil);
+   return;
+   }
+
wil_memcpy_fromio_32(, off, sizeof(r));
wil_mbox_ring_le2cpus();
/*
@@ -345,6 +350,7 @@ static void wil_print_mbox_ring(struct seq_file *s, const 
char *prefix,
}
  out:
seq_puts(s, "}\n");
+   wil_mem_access_unlock(wil);
wil_halp_unvote(wil);
 }
 
@@ -634,6 +640,12 @@ static int wil_memread_debugfs_show(struct seq_file *s, 
void *data)
if (ret < 0)
return ret;
 
+   ret = wil_mem_access_lock(wil);
+   if (ret) {
+   wil_pm_runtime_put(wil);
+   return ret;
+   }
+
a = wmi_buffer(wil, cpu_to_le32(mem_addr));
 
if (a)
@@ -641,6 +653,8 @@ static int wil_memread_debugfs_show(struct seq_file *s, 
void *data)
else
seq_printf(s, "[0x%08x] = INVALID\n", mem_addr);
 
+   wil_mem_access_unlock(wil);
+
wil_pm_runtime_put(wil);
 
return 0;
@@ -670,10 +684,6 @@ static ssize_t wil_read_file_ioblob(struct file *file, 
char __user *user_buf,
size_t unaligned_bytes, aligned_count, ret;
int rc;
 
-   if (test_bit(wil_status_suspending, wil_blob->wil->status) ||
-   test_bit(wil_status_suspended, wil_blob->wil->status))
-   return 0;
-
if (pos < 0)
return -EINVAL;
 
@@ -700,11 +710,19 @@ static ssize_t wil_read_file_ioblob(struct file *file, 
char __user *user_buf,
return rc;
}
 
+   rc = wil_mem_access_lock(wil);
+   if (rc) {
+   kfree(buf);
+   wil_pm_runtime_put(wil);
+   return rc;
+   }
+
wil_memcpy_fromio_32(buf, (const void __iomem *)
 wil_blob->blob.data + aligned_pos, aligned_count);
 
ret = copy_to_user(user_buf, buf + unaligned_bytes, count);
 
+   wil_mem_access_unlock(wil);
wil_pm_runtime_put(wil);
 
kfree(buf);
diff --git a/drivers/net/wireless/ath/wil6210/main.c 
b/drivers/net/wireless/ath/wil6210/main.c
index 524e0ef..cb97766 100644
--- a/drivers/net/wireless/ath/wil6210/main.c
+++ b/drivers/net/wireless/ath/wil6210/main.c
@@ -139,6 +139,28 @@ void wil_memcpy_toio_32(volatile void __iomem *dst, const 
void *src,
}
 }
 
+/* Device memory access is prohibited while reset or suspend.
+ * wil_mem_access_lock protects accessing device memory in these cases
+ */
+int wil_mem_access_lock(struct wil6210_priv *wil)
+{
+   if (!down_read_trylock(>mem_lock))
+   return -EBUSY;
+
+   if (test_bit(wil_status_suspending, wil->status) ||
+   test_bit(wil_status_suspended, wil->status)) {
+   up_read(>mem_lock);
+   return -EBUSY;
+   }
+
+   return 0;
+}
+
+void wil_mem_access_unlock(struct wil6210_priv *wil)
+{
+   up_read(>mem_lock);
+}
+
 static void wil_ring_fini_tx(struct wil6210_priv *wil, int id)
 {
struct wil_ring *ring = >ring_tx[id];
@@ -680,6 +702,7 @@ int wil_priv_init(struct wil6210_priv *wil)
spin_lock_init(>wmi_ev_lock);
spin_lock_init(>net_queue_lock);
init_waitqueue_head(>wq);
+   init_rwsem(>mem_lock);
 
wil->wmi_wq = create_singlethread_workqueue(WIL_NAME "_wmi");
if (!wil->wmi_wq)
@@ -1579,15 +1602,6 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw)
}
 
set_bit(wil_status_resetting, wil->status);
-   if (test_bit(wil_status_collecting_dumps, wil->status)) {
-   /* Device collects crash dump, cancel the reset.
-* following crash dump collection, reset would take place.
-*/
-   wil_dbg_misc(wil, "reject reset while collecting crash dump\n");
-   rc = -EBUSY;
-   goto out;
-   }
-
mutex_lock(>vif_mutex);
wil_abort_scan_all_vifs(wil, 

[PATCH 01/12] wil6210: remove rtap_include_phy_info module param

2018-12-02 Thread Maya Erez
rtap_include_phy_info is not in use, hence can be removed.

Signed-off-by: Maya Erez 
---
 drivers/net/wireless/ath/wil6210/txrx.c | 85 +
 drivers/net/wireless/ath/wil6210/txrx.h |  5 --
 drivers/net/wireless/ath/wil6210/wmi.c  |  2 +-
 3 files changed, 13 insertions(+), 79 deletions(-)

diff --git a/drivers/net/wireless/ath/wil6210/txrx.c 
b/drivers/net/wireless/ath/wil6210/txrx.c
index 3e1c831..364f7880 100644
--- a/drivers/net/wireless/ath/wil6210/txrx.c
+++ b/drivers/net/wireless/ath/wil6210/txrx.c
@@ -30,11 +30,6 @@
 #include "trace.h"
 #include "txrx_edma.h"
 
-static bool rtap_include_phy_info;
-module_param(rtap_include_phy_info, bool, 0444);
-MODULE_PARM_DESC(rtap_include_phy_info,
-" Include PHY info in the radiotap header, default - no");
-
 bool rx_align_2;
 module_param(rx_align_2, bool, 0444);
 MODULE_PARM_DESC(rx_align_2, " align Rx buffers on 4*n+2, default - no");
@@ -332,87 +327,31 @@ static void wil_rx_add_radiotap_header(struct 
wil6210_priv *wil,
u8 mcs_flags;
u8 mcs_index;
} __packed;
-   struct wil6210_rtap_vendor {
-   struct wil6210_rtap rtap;
-   /* vendor */
-   u8 vendor_oui[3] __aligned(2);
-   u8 vendor_ns;
-   __le16 vendor_skip;
-   u8 vendor_data[0];
-   } __packed;
struct vring_rx_desc *d = wil_skb_rxdesc(skb);
-   struct wil6210_rtap_vendor *rtap_vendor;
+   struct wil6210_rtap *rtap;
int rtap_len = sizeof(struct wil6210_rtap);
-   int phy_length = 0; /* phy info header size, bytes */
-   static char phy_data[128];
struct ieee80211_channel *ch = wil->monitor_chandef.chan;
 
-   if (rtap_include_phy_info) {
-   rtap_len = sizeof(*rtap_vendor) + sizeof(*d);
-   /* calculate additional length */
-   if (d->dma.status & RX_DMA_STATUS_PHY_INFO) {
-   /**
-* PHY info starts from 8-byte boundary
-* there are 8-byte lines, last line may be partially
-* written (HW bug), thus FW configures for last line
-* to be excessive. Driver skips this last line.
-*/
-   int len = min_t(int, 8 + sizeof(phy_data),
-   wil_rxdesc_phy_length(d));
-
-   if (len > 8) {
-   void *p = skb_tail_pointer(skb);
-   void *pa = PTR_ALIGN(p, 8);
-
-   if (skb_tailroom(skb) >= len + (pa - p)) {
-   phy_length = len - 8;
-   memcpy(phy_data, pa, phy_length);
-   }
-   }
-   }
-   rtap_len += phy_length;
-   }
-
if (skb_headroom(skb) < rtap_len &&
pskb_expand_head(skb, rtap_len, 0, GFP_ATOMIC)) {
wil_err(wil, "Unable to expand headroom to %d\n", rtap_len);
return;
}
 
-   rtap_vendor = skb_push(skb, rtap_len);
-   memset(rtap_vendor, 0, rtap_len);
-
-   rtap_vendor->rtap.rthdr.it_version = PKTHDR_RADIOTAP_VERSION;
-   rtap_vendor->rtap.rthdr.it_len = cpu_to_le16(rtap_len);
-   rtap_vendor->rtap.rthdr.it_present = cpu_to_le32(
-   (1 << IEEE80211_RADIOTAP_FLAGS) |
+   rtap->rthdr.it_version = PKTHDR_RADIOTAP_VERSION;
+   rtap->rthdr.it_len = cpu_to_le16(rtap_len);
+   rtap->rthdr.it_present = cpu_to_le32((1 << IEEE80211_RADIOTAP_FLAGS) |
(1 << IEEE80211_RADIOTAP_CHANNEL) |
(1 << IEEE80211_RADIOTAP_MCS));
if (d->dma.status & RX_DMA_STATUS_ERROR)
-   rtap_vendor->rtap.flags |= IEEE80211_RADIOTAP_F_BADFCS;
-
-   rtap_vendor->rtap.chnl_freq = cpu_to_le16(ch ? ch->center_freq : 58320);
-   rtap_vendor->rtap.chnl_flags = cpu_to_le16(0);
-
-   rtap_vendor->rtap.mcs_present = IEEE80211_RADIOTAP_MCS_HAVE_MCS;
-   rtap_vendor->rtap.mcs_flags = 0;
-   rtap_vendor->rtap.mcs_index = wil_rxdesc_mcs(d);
-
-   if (rtap_include_phy_info) {
-   rtap_vendor->rtap.rthdr.it_present |= cpu_to_le32(1 <<
-   IEEE80211_RADIOTAP_VENDOR_NAMESPACE);
-   /* OUI for Wilocity 04:ce:14 */
-   rtap_vendor->vendor_oui[0] = 0x04;
-   rtap_vendor->vendor_oui[1] = 0xce;
-   rtap_vendor->vendor_oui[2] = 0x14;
-   rtap_vendor->vendor_ns = 1;
-   /* Rx descriptor + PHY data  */
-   rtap_vendor->vendor_skip = cpu_to_le16(sizeof(*d) +
-  phy_length);
-   memcpy(rtap_vendor->vendor_data, (void *)d, sizeof(*d));
-   memcpy(rtap_vendor->vendor_data + sizeof(*d), phy_data,
-  

[PATCH 07/12] wil6210: accessing 802.3 addresses via utility functions

2018-12-02 Thread Maya Erez
From: Ahmad Masri 

Rearrange the code by having functions to access 802.3 header
members, source and destination addresses.

Signed-off-by: Ahmad Masri 
Signed-off-by: Maya Erez 
---
 drivers/net/wireless/ath/wil6210/netdev.c |  6 +++---
 drivers/net/wireless/ath/wil6210/txrx.c   | 33 ++-
 drivers/net/wireless/ath/wil6210/txrx.h   | 18 +++--
 3 files changed, 34 insertions(+), 23 deletions(-)

diff --git a/drivers/net/wireless/ath/wil6210/netdev.c 
b/drivers/net/wireless/ath/wil6210/netdev.c
index 74e90a3..41620c2 100644
--- a/drivers/net/wireless/ath/wil6210/netdev.c
+++ b/drivers/net/wireless/ath/wil6210/netdev.c
@@ -123,18 +123,18 @@ static u16 wil_select_queue(struct net_device *ndev,
 {
struct wil6210_vif *vif = ndev_to_vif(ndev);
struct wil6210_priv *wil = vif_to_wil(vif);
-   struct ethhdr *eth = (void *)skb->data;
+   const u8 *da = wil_skb_get_da(skb);
u16 qid = 0;
bool mcast;
 
if (!WIL_Q_PER_STA_USED(vif))
goto out;
 
-   mcast = is_multicast_ether_addr(eth->h_dest);
+   mcast = is_multicast_ether_addr(da);
if (mcast) {
qid = wil->config.max_assoc_sta;
} else {
-   qid = wil_find_cid(wil, vif->mid, eth->h_dest);
+   qid = wil_find_cid(wil, vif->mid, da);
 
/* the MCAST queues also used as default queues */
if (qid < 0)
diff --git a/drivers/net/wireless/ath/wil6210/txrx.c 
b/drivers/net/wireless/ath/wil6210/txrx.c
index 471f85e..4c833fc 100644
--- a/drivers/net/wireless/ath/wil6210/txrx.c
+++ b/drivers/net/wireless/ath/wil6210/txrx.c
@@ -373,7 +373,6 @@ static int wil_rx_get_cid_by_skb(struct wil6210_priv *wil, 
struct sk_buff *skb)
 */
int cid = wil_rxdesc_cid(d);
unsigned int snaplen = wil_rx_snaplen(wil);
-   struct ethhdr *eth;
struct ieee80211_hdr_3addr *hdr;
int i;
unsigned char *ta;
@@ -391,8 +390,7 @@ static int wil_rx_get_cid_by_skb(struct wil6210_priv *wil, 
struct sk_buff *skb)
skb->len);
return -ENOENT;
}
-   eth = (void *)skb->data;
-   ta = eth->h_source;
+   ta = wil_skb_get_sa(skb);
} else {
if (unlikely(skb->len < sizeof(struct ieee80211_hdr_3addr))) {
wil_err_ratelimited(wil, "Short frame, len = %d\n",
@@ -730,11 +728,11 @@ void wil_netif_rx_any(struct sk_buff *skb, struct 
net_device *ndev)
unsigned int len = skb->len;
int cid;
int security;
-   struct ethhdr *eth = (void *)skb->data;
+   u8 *sa, *da = wil_skb_get_da(skb);
/* here looking for DA, not A1, thus Rxdesc's 'mcast' indication
 * is not suitable, need to look at data
 */
-   int mcast = is_multicast_ether_addr(eth->h_dest);
+   int mcast = is_multicast_ether_addr(da);
struct wil_net_stats *stats;
struct sk_buff *xmit_skb = NULL;
static const char * const gro_res_str[] = {
@@ -765,7 +763,8 @@ void wil_netif_rx_any(struct sk_buff *skb, struct 
net_device *ndev)
}
 
if (wdev->iftype == NL80211_IFTYPE_STATION) {
-   if (mcast && ether_addr_equal(eth->h_source, ndev->dev_addr)) {
+   sa = wil_skb_get_sa(skb);
+   if (mcast && ether_addr_equal(sa, ndev->dev_addr)) {
/* mcast packet looped back to us */
rc = GRO_DROP;
dev_kfree_skb(skb);
@@ -778,8 +777,7 @@ void wil_netif_rx_any(struct sk_buff *skb, struct 
net_device *ndev)
 */
xmit_skb = skb_copy(skb, GFP_ATOMIC);
} else {
-   int xmit_cid = wil_find_cid(wil, vif->mid,
-   eth->h_dest);
+   int xmit_cid = wil_find_cid(wil, vif->mid, da);
 
if (xmit_cid >= 0) {
/* The destination station is associated to
@@ -1234,7 +1232,7 @@ static struct wil_ring *wil_find_tx_ucast(struct 
wil6210_priv *wil,
  struct sk_buff *skb)
 {
int i, cid;
-   struct ethhdr *eth = (void *)skb->data;
+   const u8 *da = wil_skb_get_da(skb);
int min_ring_id = wil_get_min_tx_ring_id(wil);
 
if (WIL_Q_PER_STA_USED(vif))
@@ -1245,7 +1243,7 @@ static struct wil_ring *wil_find_tx_ucast(struct 
wil6210_priv *wil,
skb_get_queue_mapping(skb) / WIL6210_TX_AC_QUEUES :
skb_get_queue_mapping(skb);
else
-   cid = wil_find_cid(wil, vif->mid, eth->h_dest);
+   cid = wil_find_cid(wil, vif->mid, da);
 
if (cid < 0 || cid >= wil->config.max_assoc_sta)
return NULL;
@@ -1260,7 +1258,7 @@ static struct wil_ring 

[PATCH 02/12] wil6210: use platform specific configuration

2018-12-02 Thread Maya Erez
Some of wil6210 configuration variables are platform specific.
Add platform op to allow the platform driver to change the wil6210
default configuration.

Signed-off-by: Maya Erez 
---
 drivers/net/wireless/ath/wil6210/cfg80211.c | 13 +---
 drivers/net/wireless/ath/wil6210/main.c | 94 ++---
 drivers/net/wireless/ath/wil6210/netdev.c   |  2 +-
 drivers/net/wireless/ath/wil6210/pcie_bus.c | 31 
 drivers/net/wireless/ath/wil6210/pm.c   |  2 +-
 drivers/net/wireless/ath/wil6210/txrx.c | 15 ++--
 drivers/net/wireless/ath/wil6210/wil6210.h  | 11 ++-
 drivers/net/wireless/ath/wil6210/wil_platform.h | 22 ++
 drivers/net/wireless/ath/wil6210/wmi.c  | 23 +++---
 9 files changed, 105 insertions(+), 108 deletions(-)

diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c 
b/drivers/net/wireless/ath/wil6210/cfg80211.c
index 9b2f9f5..e51dc3f 100644
--- a/drivers/net/wireless/ath/wil6210/cfg80211.c
+++ b/drivers/net/wireless/ath/wil6210/cfg80211.c
@@ -25,10 +25,6 @@
 
 #define WIL_MAX_ROC_DURATION_MS 5000
 
-bool disable_ap_sme;
-module_param(disable_ap_sme, bool, 0444);
-MODULE_PARM_DESC(disable_ap_sme, " let user space handle AP mode SME");
-
 #ifdef CONFIG_PM
 static struct wiphy_wowlan_support wil_wowlan_support = {
.flags = WIPHY_WOWLAN_ANY | WIPHY_WOWLAN_DISCONNECT,
@@ -1991,7 +1987,7 @@ static int wil_cfg80211_add_station(struct wiphy *wiphy,
 mac, params->aid, vif->mid,
 params->sta_flags_mask, params->sta_flags_set);
 
-   if (!disable_ap_sme) {
+   if (!wil->config.disable_ap_sme) {
wil_err(wil, "not supported with AP SME enabled\n");
return -EOPNOTSUPP;
}
@@ -2036,7 +2032,7 @@ static int wil_cfg80211_change_station(struct wiphy 
*wiphy,
 mac, params->sta_flags_mask, params->sta_flags_set,
 vif->mid);
 
-   if (!disable_ap_sme) {
+   if (!wil->config.disable_ap_sme) {
wil_dbg_misc(wil, "not supported with AP SME enabled\n");
return -EOPNOTSUPP;
}
@@ -2411,10 +2407,7 @@ static void wil_wiphy_init(struct wiphy *wiphy)
wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL |
WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD |
WIPHY_FLAG_PS_ON_BY_DEFAULT;
-   if (!disable_ap_sme)
-   wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME;
-   dev_dbg(wiphy_dev(wiphy), "%s : flags = 0x%08x\n",
-   __func__, wiphy->flags);
+
wiphy->probe_resp_offload =
NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS |
NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2 |
diff --git a/drivers/net/wireless/ath/wil6210/main.c 
b/drivers/net/wireless/ath/wil6210/main.c
index ba6a2ee..bd687ad 100644
--- a/drivers/net/wireless/ath/wil6210/main.c
+++ b/drivers/net/wireless/ath/wil6210/main.c
@@ -31,10 +31,6 @@
 #define WIL_DEFAULT_NUM_RX_STATUS_RINGS 1
 #define WIL_BOARD_FILE_MAX_NAMELEN 128
 
-bool debug_fw; /* = false; */
-module_param(debug_fw, bool, 0444);
-MODULE_PARM_DESC(debug_fw, " do not perform card reset. For FW debug");
-
 static u8 oob_mode;
 module_param(oob_mode, byte, 0444);
 MODULE_PARM_DESC(oob_mode,
@@ -44,14 +40,6 @@
 module_param(no_fw_recovery, bool, 0644);
 MODULE_PARM_DESC(no_fw_recovery, " disable automatic FW error recovery");
 
-/* if not set via modparam, will be set to default value of 1/8 of
- * rx ring size during init flow
- */
-unsigned short rx_ring_overflow_thrsh = WIL6210_RX_HIGH_TRSH_INIT;
-module_param(rx_ring_overflow_thrsh, ushort, 0444);
-MODULE_PARM_DESC(rx_ring_overflow_thrsh,
-" RX ring overflow threshold in descriptors.");
-
 /* We allow allocation of more than 1 page buffers to support large packets.
  * It is suboptimal behavior performance wise in case MTU above page size.
  */
@@ -81,39 +69,6 @@ static int mtu_max_set(const char *val, const struct 
kernel_param *kp)
 module_param_cb(mtu_max, _max_ops, _max, 0444);
 MODULE_PARM_DESC(mtu_max, " Max MTU value.");
 
-static uint rx_ring_order;
-static uint tx_ring_order = WIL_TX_RING_SIZE_ORDER_DEFAULT;
-static uint bcast_ring_order = WIL_BCAST_RING_SIZE_ORDER_DEFAULT;
-
-static int ring_order_set(const char *val, const struct kernel_param *kp)
-{
-   int ret;
-   uint x;
-
-   ret = kstrtouint(val, 0, );
-   if (ret)
-   return ret;
-
-   if ((x < WIL_RING_SIZE_ORDER_MIN) || (x > WIL_RING_SIZE_ORDER_MAX))
-   return -EINVAL;
-
-   *((uint *)kp->arg) = x;
-
-   return 0;
-}
-
-static const struct kernel_param_ops ring_order_ops = {
-   .set = ring_order_set,
-   .get = param_get_uint,
-};
-
-module_param_cb(rx_ring_order, _order_ops, _ring_order, 0444);
-MODULE_PARM_DESC(rx_ring_order, " Rx ring order; size = 1 << order");
-module_param_cb(tx_ring_order, _order_ops, _ring_order, 0444);
-MODULE_PARM_DESC(tx_ring_order, " Tx ring order; size = 1 

[PATCH 09/12] wil6210: ignore HALP ICR if already handled

2018-12-02 Thread Maya Erez
HALP ICR is set as long as the FW should stay awake.
To prevent its multiple handling the driver masks this IRQ bit.
However, if there is a different MISC ICR before the driver clears
this bit, there is a risk of race condition between HALP mask and
unmask. This race leads to HALP timeout, in case it is mistakenly
masked.
Add a flag to indicate if HALP ICR should be handled.

Signed-off-by: Maya Erez 
---
 drivers/net/wireless/ath/wil6210/interrupt.c | 10 +++---
 drivers/net/wireless/ath/wil6210/main.c  |  3 +++
 drivers/net/wireless/ath/wil6210/wil6210.h   |  1 +
 3 files changed, 11 insertions(+), 3 deletions(-)

diff --git a/drivers/net/wireless/ath/wil6210/interrupt.c 
b/drivers/net/wireless/ath/wil6210/interrupt.c
index 5d287a8..e0eaeea 100644
--- a/drivers/net/wireless/ath/wil6210/interrupt.c
+++ b/drivers/net/wireless/ath/wil6210/interrupt.c
@@ -575,10 +575,14 @@ static irqreturn_t wil6210_irq_misc(int irq, void *cookie)
}
 
if (isr & BIT_DMA_EP_MISC_ICR_HALP) {
-   wil_dbg_irq(wil, "irq_misc: HALP IRQ invoked\n");
-   wil6210_mask_halp(wil);
isr &= ~BIT_DMA_EP_MISC_ICR_HALP;
-   complete(>halp.comp);
+   if (wil->halp.handle_icr) {
+   /* no need to handle HALP ICRs until next vote */
+   wil->halp.handle_icr = false;
+   wil_dbg_irq(wil, "irq_misc: HALP IRQ invoked\n");
+   wil6210_mask_halp(wil);
+   complete(>halp.comp);
+   }
}
 
wil->isr_misc = isr;
diff --git a/drivers/net/wireless/ath/wil6210/main.c 
b/drivers/net/wireless/ath/wil6210/main.c
index 14c908f..524e0ef 100644
--- a/drivers/net/wireless/ath/wil6210/main.c
+++ b/drivers/net/wireless/ath/wil6210/main.c
@@ -1901,11 +1901,14 @@ void wil_halp_vote(struct wil6210_priv *wil)
 
if (++wil->halp.ref_cnt == 1) {
reinit_completion(>halp.comp);
+   /* mark to IRQ context to handle HALP ICR */
+   wil->halp.handle_icr = true;
wil6210_set_halp(wil);
rc = wait_for_completion_timeout(>halp.comp, to_jiffies);
if (!rc) {
wil_err(wil, "HALP vote timed out\n");
/* Mask HALP as done in case the interrupt is raised */
+   wil->halp.handle_icr = false;
wil6210_mask_halp(wil);
} else {
wil_dbg_irq(wil,
diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h 
b/drivers/net/wireless/ath/wil6210/wil6210.h
index d614f57..f9eacfd 100644
--- a/drivers/net/wireless/ath/wil6210/wil6210.h
+++ b/drivers/net/wireless/ath/wil6210/wil6210.h
@@ -781,6 +781,7 @@ struct wil_halp {
struct mutexlock; /* protect halp ref_cnt */
unsigned intref_cnt;
struct completion   comp;
+   boolhandle_icr;
 };
 
 struct wil_blob_wrapper {
-- 
1.9.1



[PATCH 08/12] wil6210: fix invalid sta statistics update

2018-12-02 Thread Maya Erez
From: Dedy Lansky 

Upon status ring handling, in case there are both unicast and
multicast (cid == max) status messages to handle, wrong sta statistics
might get updated.
Fix this by setting stats to NULL upon invalid cid
(e.g. == max_assoc_sta).

Signed-off-by: Dedy Lansky 
Signed-off-by: Maya Erez 
---
 drivers/net/wireless/ath/wil6210/txrx_edma.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/net/wireless/ath/wil6210/txrx_edma.c 
b/drivers/net/wireless/ath/wil6210/txrx_edma.c
index ac03526..abcf6dd 100644
--- a/drivers/net/wireless/ath/wil6210/txrx_edma.c
+++ b/drivers/net/wireless/ath/wil6210/txrx_edma.c
@@ -1137,7 +1137,7 @@ int wil_tx_sring_handler(struct wil6210_priv *wil,
/* Total number of completed descriptors in all descriptor rings */
int desc_cnt = 0;
int cid;
-   struct wil_net_stats *stats = NULL;
+   struct wil_net_stats *stats;
struct wil_tx_enhanced_desc *_d;
unsigned int ring_id;
unsigned int num_descs;
@@ -1187,8 +1187,8 @@ int wil_tx_sring_handler(struct wil6210_priv *wil,
ndev = vif_to_ndev(vif);
 
cid = wil->ring2cid_tid[ring_id][0];
-   if (cid < wil->config.max_assoc_sta)
-   stats = >sta[cid].stats;
+   stats = (cid < wil->config.max_assoc_sta ?
+   >sta[cid].stats : NULL);
 
wil_dbg_txrx(wil,
 "tx_status: completed desc_ring (%d), num_descs 
(%d)\n",
-- 
1.9.1



[PATCH 04/12] wil6210: add support for AC queues per station

2018-12-02 Thread Maya Erez
From: Ahmad Masri 

Until now all stations (notably in AP mode) would share the same
queue/s exposed via netdev. This meant that whenever a single
station's ring became full all queues got stopped.

With the queues per station feature each station will have its own
net queue/s and it will not block other stations' transmission in
case its vring is full.

Driver will add queue/s per station when creating a new netdev.
The mapping between a station and its queues will be by sta cid.
Once a new sta connects the driver will open its queues
(can be one or four AC queues) for transmit. The driver uses the
same logic of ring capacity usage to wake the net queues.

Last four netdev queues are used for unclassified traffic
(e.g. when there's no cid for given DA) which is mostly multicast.

This feature is controlled by a q_per_sta module param
which is disabled by default.

Signed-off-by: Ahmad Masri 
Signed-off-by: Maya Erez 
---
 drivers/net/wireless/ath/wil6210/cfg80211.c |   8 ++
 drivers/net/wireless/ath/wil6210/main.c |  14 ++-
 drivers/net/wireless/ath/wil6210/netdev.c   |  58 +++---
 drivers/net/wireless/ath/wil6210/txrx.c | 148 ++--
 drivers/net/wireless/ath/wil6210/txrx_edma.c|   2 +-
 drivers/net/wireless/ath/wil6210/wil6210.h  |  24 +++-
 drivers/net/wireless/ath/wil6210/wil_platform.h |   2 +
 drivers/net/wireless/ath/wil6210/wmi.c  |   2 +-
 8 files changed, 226 insertions(+), 32 deletions(-)

diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c 
b/drivers/net/wireless/ath/wil6210/cfg80211.c
index e51dc3f..2e00f10 100644
--- a/drivers/net/wireless/ath/wil6210/cfg80211.c
+++ b/drivers/net/wireless/ath/wil6210/cfg80211.c
@@ -1776,6 +1776,10 @@ static int _wil_cfg80211_start_ap(struct wiphy *wiphy,
if (rc)
goto err_bcast;
 
+   /* wake default net queue - used mainly for multicast */
+   if (wil->config.q_per_sta)
+   wil_update_cid_net_queues_bh(wil, vif, WIL6210_MAX_CID, false);
+
goto out; /* success */
 
 err_bcast:
@@ -1965,6 +1969,10 @@ static int wil_cfg80211_stop_ap(struct wiphy *wiphy,
memset(vif->gtk, 0, WMI_MAX_KEY_LEN);
vif->gtk_len = 0;
 
+   /* stop default net queue - used mainly for multicast */
+   if (wil->config.q_per_sta)
+   wil_update_cid_net_queues_bh(wil, vif, WIL6210_MAX_CID, true);
+
if (last)
__wil_down(wil);
else
diff --git a/drivers/net/wireless/ath/wil6210/main.c 
b/drivers/net/wireless/ath/wil6210/main.c
index bd687ad..c02526c 100644
--- a/drivers/net/wireless/ath/wil6210/main.c
+++ b/drivers/net/wireless/ath/wil6210/main.c
@@ -210,6 +210,9 @@ static void wil_disconnect_cid_complete(struct wil6210_vif 
*vif, int cid,
case NL80211_IFTYPE_P2P_GO:
/* AP-like interface */
cfg80211_del_sta(ndev, sta->addr, GFP_KERNEL);
+   if (WIL_Q_PER_STA_USED(vif))
+   wil_update_cid_net_queues_bh(wil, vif,
+cid, true);
break;
default:
break;
@@ -311,12 +314,14 @@ static void _wil6210_disconnect_complete(struct 
wil6210_vif *vif,
case NL80211_IFTYPE_AP:
case NL80211_IFTYPE_P2P_GO:
if (!wil_vif_is_connected(wil, vif->mid)) {
-   wil_update_net_queues_bh(wil, vif, NULL, true);
+   if (!WIL_Q_PER_STA_USED(vif))
+   wil_update_net_queues_bh(wil, vif, NULL, true);
if (test_and_clear_bit(wil_vif_fwconnected,
   vif->status))
atomic_dec(>connected_vifs);
-   } else {
-   wil_update_net_queues_bh(wil, vif, NULL, false);
+   } else if (!WIL_Q_PER_STA_USED(vif)) {
+   wil_update_net_queues_bh(wil, vif,
+NULL, false);
}
break;
default:
@@ -433,6 +438,9 @@ void wil_disconnect_worker(struct work_struct *work)
return;
}
 
+   /* disconnect worker runs only from client/sta vif.
+* stop all queues in case failed to connect
+*/
wil_update_net_queues_bh(wil, vif, NULL, true);
netif_carrier_off(ndev);
cfg80211_connect_result(ndev, NULL, NULL, 0, NULL, 0,
diff --git a/drivers/net/wireless/ath/wil6210/netdev.c 
b/drivers/net/wireless/ath/wil6210/netdev.c
index bab457d..b617059 100644
--- a/drivers/net/wireless/ath/wil6210/netdev.c
+++ b/drivers/net/wireless/ath/wil6210/netdev.c
@@ -20,8 +20,6 @@
 #include "wil6210.h"
 #include "txrx.h"
 
-#define WIL6210_TX_QUEUES (4)
-
 bool wil_has_other_active_ifaces(struct wil6210_priv *wil,
 struct net_device 

[PATCH 06/12] wil6210: support up to 20 stations in AP mode

2018-12-02 Thread Maya Erez
From: Ahmad Masri 

New FW added support for upto 20 clients in AP mode. Change the driver
to support this as well. FW reports it's max supported associations in
WMI_READY_EVENT. Some WMI commands/events use cidxtid field which is
limited to 16 cids. Use new cid/tid fields instead.

For Rx packets cid from rx descriptor is limited to 3 bits (0..7),
to find the real cid, compare transmitter address with the stored
stations mac address in the driver sta array.

EDMA FW still supports 8 stations. Extending the support to 20
stations will come later.

Signed-off-by: Ahmad Masri 
Signed-off-by: Maya Erez 
---
 drivers/net/wireless/ath/wil6210/cfg80211.c   |  10 +-
 drivers/net/wireless/ath/wil6210/debugfs.c|  20 ++--
 drivers/net/wireless/ath/wil6210/main.c   |   8 +-
 drivers/net/wireless/ath/wil6210/netdev.c |   4 +-
 drivers/net/wireless/ath/wil6210/rx_reorder.c |   8 +-
 drivers/net/wireless/ath/wil6210/trace.h  |   2 +-
 drivers/net/wireless/ath/wil6210/txrx.c   | 142 --
 drivers/net/wireless/ath/wil6210/txrx.h   |  26 +
 drivers/net/wireless/ath/wil6210/txrx_edma.c  |   6 +-
 drivers/net/wireless/ath/wil6210/wil6210.h|  27 ++---
 drivers/net/wireless/ath/wil6210/wmi.c|  79 +++---
 11 files changed, 242 insertions(+), 90 deletions(-)

diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c 
b/drivers/net/wireless/ath/wil6210/cfg80211.c
index 2e00f10..ad5ac7d 100644
--- a/drivers/net/wireless/ath/wil6210/cfg80211.c
+++ b/drivers/net/wireless/ath/wil6210/cfg80211.c
@@ -391,7 +391,7 @@ static int wil_find_cid_by_idx(struct wil6210_priv *wil, u8 
mid, int idx)
 {
int i;
 
-   for (i = 0; i < ARRAY_SIZE(wil->sta); i++) {
+   for (i = 0; i < wil->config.max_assoc_sta; i++) {
if (wil->sta[i].status == wil_sta_unused)
continue;
if (wil->sta[i].mid != mid)
@@ -1778,7 +1778,8 @@ static int _wil_cfg80211_start_ap(struct wiphy *wiphy,
 
/* wake default net queue - used mainly for multicast */
if (wil->config.q_per_sta)
-   wil_update_cid_net_queues_bh(wil, vif, WIL6210_MAX_CID, false);
+   wil_update_cid_net_queues_bh(wil, vif,
+wil->config.max_assoc_sta, false);
 
goto out; /* success */
 
@@ -1971,7 +1972,8 @@ static int wil_cfg80211_stop_ap(struct wiphy *wiphy,
 
/* stop default net queue - used mainly for multicast */
if (wil->config.q_per_sta)
-   wil_update_cid_net_queues_bh(wil, vif, WIL6210_MAX_CID, true);
+   wil_update_cid_net_queues_bh(wil, vif,
+wil->config.max_assoc_sta, true);
 
if (last)
__wil_down(wil);
@@ -3008,7 +3010,7 @@ static int wil_rf_sector_set_selected(struct wiphy *wiphy,
wil, vif->mid, WMI_INVALID_RF_SECTOR_INDEX,
sector_type, WIL_CID_ALL);
if (rc == -EINVAL) {
-   for (i = 0; i < WIL6210_MAX_CID; i++) {
+   for (i = 0; i < wil->config.max_assoc_sta; i++) {
if (wil->sta[i].mid != vif->mid)
continue;
rc = wil_rf_sector_wmi_set_selected(
diff --git a/drivers/net/wireless/ath/wil6210/debugfs.c 
b/drivers/net/wireless/ath/wil6210/debugfs.c
index 20dd4d0..4980678 100644
--- a/drivers/net/wireless/ath/wil6210/debugfs.c
+++ b/drivers/net/wireless/ath/wil6210/debugfs.c
@@ -162,7 +162,7 @@ static int wil_ring_debugfs_show(struct seq_file *s, void 
*data)
 
snprintf(name, sizeof(name), "tx_%2d", i);
 
-   if (cid < WIL6210_MAX_CID)
+   if (cid < wil->config.max_assoc_sta)
seq_printf(s,
   "\n%pM CID %d TID %d 1x%s BACK([%u] 
%u TU A%s) [%3d|%3d] idle %s\n",
   wil->sta[cid].addr, cid, tid,
@@ -836,14 +836,14 @@ static ssize_t wil_write_back(struct file *file, const 
char __user *buf,
"BACK: del_rx require at least 2 params\n");
return -EINVAL;
}
-   if (p1 < 0 || p1 >= WIL6210_MAX_CID) {
+   if (p1 < 0 || p1 >= wil->config.max_assoc_sta) {
wil_err(wil, "BACK: invalid CID %d\n", p1);
return -EINVAL;
}
if (rc < 4)
p3 = WLAN_REASON_QSTA_LEAVE_QBSS;
sta = >sta[p1];
-   wmi_delba_rx(wil, sta->mid, mk_cidxtid(p1, p2), p3);
+   wmi_delba_rx(wil, sta->mid, p1, p2, p3);
} else {
wil_err(wil, "BACK: Unrecognized command \"%s\"\n", cmd);
return -EINVAL;
@@ -1322,7 +1322,7 @@ static int wil_bf_debugfs_show(struct seq_file 

[PATCH 03/12] wil6210: support ndo_select_queue in net_device_ops

2018-12-02 Thread Maya Erez
From: Ahmad Masri 

Add support for Access Category to select queue for transmit packets.
The callback wil_select_queue will return the queue id [0..3] to use for
the current skb transmission.

This feature is disabled by default. Use ac_queues module param to enable.

Signed-off-by: Ahmad Masri 
Signed-off-by: Maya Erez 
---
 drivers/net/wireless/ath/wil6210/netdev.c   | 43 +++--
 drivers/net/wireless/ath/wil6210/wil_platform.h |  2 ++
 2 files changed, 43 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/ath/wil6210/netdev.c 
b/drivers/net/wireless/ath/wil6210/netdev.c
index b99470c..bab457d 100644
--- a/drivers/net/wireless/ath/wil6210/netdev.c
+++ b/drivers/net/wireless/ath/wil6210/netdev.c
@@ -20,6 +20,8 @@
 #include "wil6210.h"
 #include "txrx.h"
 
+#define WIL6210_TX_QUEUES (4)
+
 bool wil_has_other_active_ifaces(struct wil6210_priv *wil,
 struct net_device *ndev, bool up, bool ok)
 {
@@ -91,10 +93,43 @@ static int wil_stop(struct net_device *ndev)
return rc;
 }
 
+/**
+ * AC to queue mapping
+ *
+ * AC_VO -> queue 3
+ * AC_VI -> queue 2
+ * AC_BE -> queue 1
+ * AC_BK -> queue 0
+ */
+static u16 wil_select_queue(struct net_device *ndev,
+   struct sk_buff *skb,
+   struct net_device *sb_dev,
+   select_queue_fallback_t fallback)
+{
+   static const u16 wil_1d_to_queue[8] = {1, 0, 0, 1, 2, 2, 3, 3};
+   struct wil6210_priv *wil = ndev_to_wil(ndev);
+   u16 qid;
+
+   if (!wil->config.ac_queues)
+   return 0;
+
+   /* determine the priority */
+   if (skb->priority == 0 || skb->priority > 7)
+   skb->priority = cfg80211_classify8021d(skb, NULL);
+
+   qid = wil_1d_to_queue[skb->priority];
+
+   wil_dbg_txrx(wil, "select queue for priority %d -> queue %d\n",
+skb->priority, qid);
+
+   return qid;
+}
+
 static const struct net_device_ops wil_netdev_ops = {
.ndo_open   = wil_open,
.ndo_stop   = wil_stop,
.ndo_start_xmit = wil_start_xmit,
+   .ndo_select_queue   = wil_select_queue,
.ndo_set_mac_address= eth_mac_addr,
.ndo_validate_addr  = eth_validate_addr,
 };
@@ -317,8 +352,12 @@ struct wil6210_vif *
return ERR_PTR(-EINVAL);
}
 
-   ndev = alloc_netdev(sizeof(*vif), name, name_assign_type,
-   wil_dev_setup);
+   if (wil->config.ac_queues)
+   ndev = alloc_netdev_mqs(sizeof(*vif), name, name_assign_type,
+   wil_dev_setup, WIL6210_TX_QUEUES, 1);
+   else
+   ndev = alloc_netdev(sizeof(*vif), name, name_assign_type,
+   wil_dev_setup);
if (!ndev) {
dev_err(wil_to_dev(wil), "alloc_netdev failed\n");
return ERR_PTR(-ENOMEM);
diff --git a/drivers/net/wireless/ath/wil6210/wil_platform.h 
b/drivers/net/wireless/ath/wil6210/wil_platform.h
index 7090e68..ac47e9d 100644
--- a/drivers/net/wireless/ath/wil6210/wil_platform.h
+++ b/drivers/net/wireless/ath/wil6210/wil_platform.h
@@ -59,6 +59,8 @@ struct wil_platform_config {
bool disable_ap_sme;
/* Max number of stations associated to the AP */
unsigned int max_assoc_sta;
+   /* enable access category for transmit packets, default - no */
+   bool ac_queues;
 };
 
 /**
-- 
1.9.1



[PATCH 05/12] wil6210: add option to drop Tx packets when tx ring is full

2018-12-02 Thread Maya Erez
From: Dedy Lansky 

In AP mode with multiple clients, driver stops net queue
(netif_tx_stop_queue) upon first ring (serving specific client)
becoming full. This can have negative effect on transmission to
other clients which may still have room in their corresponding rings.

Implement new policy in which stop/wake net queue are not used. In
case there is no room in the ring for a transmitted packet, drop the
packet.
New policy is disabled by default and can be enabled with new
drop_if_ring_full module param.

Signed-off-by: Dedy Lansky 
Signed-off-by: Maya Erez 
---
 drivers/net/wireless/ath/wil6210/txrx.c | 6 ++
 drivers/net/wireless/ath/wil6210/wil_platform.h | 2 ++
 2 files changed, 8 insertions(+)

diff --git a/drivers/net/wireless/ath/wil6210/txrx.c 
b/drivers/net/wireless/ath/wil6210/txrx.c
index 714ca0f..1e715ba 100644
--- a/drivers/net/wireless/ath/wil6210/txrx.c
+++ b/drivers/net/wireless/ath/wil6210/txrx.c
@@ -2064,6 +2064,10 @@ static inline void __wil_update_net_queues(struct 
wil6210_priv *wil,
wil_dbg_txrx(wil, "check_stop=%d, mid=%d, stopped=%d",
 check_stop, vif->mid, vif->net_queue_stopped);
 
+   if (ring && wil->config.drop_if_ring_full)
+   /* no need to stop/wake net queues */
+   return;
+
if (ring && WIL_Q_PER_STA_USED(vif)) {
__wil_update_net_queues_per_sta(wil, vif, ring, check_stop);
return;
@@ -2227,6 +2231,8 @@ netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct 
net_device *ndev)
dev_kfree_skb_any(skb);
return NETDEV_TX_OK;
case -ENOMEM:
+   if (wil->config.drop_if_ring_full)
+   goto drop;
return NETDEV_TX_BUSY;
default:
break; /* goto drop; */
diff --git a/drivers/net/wireless/ath/wil6210/wil_platform.h 
b/drivers/net/wireless/ath/wil6210/wil_platform.h
index 60b4abc..c90ab7577 100644
--- a/drivers/net/wireless/ath/wil6210/wil_platform.h
+++ b/drivers/net/wireless/ath/wil6210/wil_platform.h
@@ -63,6 +63,8 @@ struct wil_platform_config {
bool ac_queues;
/* enable allocating tx queue(s) per station, default - no */
bool q_per_sta;
+   /* drop Tx packets in case tx ring is full, default - no */
+   bool drop_if_ring_full;
 };
 
 /**
-- 
1.9.1