Linux wireless drivers development
 help / color / mirror / Atom feed
* [PATCH 8/8] staging: wilc1000: rename 'host_interface' source and header
From: Ajay.Kathat @ 2019-06-26 12:41 UTC (permalink / raw)
  To: linux-wireless; +Cc: devel, gregkh, Adham.Abozaeid, johannes, Ajay.Kathat
In-Reply-To: <1561552810-8933-1-git-send-email-ajay.kathat@microchip.com>

From: Ajay Singh <ajay.kathat@microchip.com>

Rename 'host_interface' source and header file to include the 'wilc_'
prefix in its name.

Signed-off-by: Ajay Singh <ajay.kathat@microchip.com>
---
 drivers/staging/wilc1000/Makefile                         | 2 +-
 drivers/staging/wilc1000/{host_interface.c => wilc_hif.c} | 0
 drivers/staging/wilc1000/{host_interface.h => wilc_hif.h} | 0
 drivers/staging/wilc1000/wilc_wfi_netdevice.h             | 2 +-
 4 files changed, 2 insertions(+), 2 deletions(-)
 rename drivers/staging/wilc1000/{host_interface.c => wilc_hif.c} (100%)
 rename drivers/staging/wilc1000/{host_interface.h => wilc_hif.h} (100%)

diff --git a/drivers/staging/wilc1000/Makefile b/drivers/staging/wilc1000/Makefile
index 2ad3fee..a5a8e80 100644
--- a/drivers/staging/wilc1000/Makefile
+++ b/drivers/staging/wilc1000/Makefile
@@ -5,7 +5,7 @@ ccflags-y += -DFIRMWARE_1002=\"atmel/wilc1002_firmware.bin\" \
 		-DFIRMWARE_1003=\"atmel/wilc1003_firmware.bin\"
 
 wilc1000-objs := wilc_wfi_cfgoperations.o wilc_netdev.o wilc_mon.o \
-			host_interface.o wilc_wlan_cfg.o wilc_wlan.o
+			wilc_hif.o wilc_wlan_cfg.o wilc_wlan.o
 
 obj-$(CONFIG_WILC1000_SDIO) += wilc1000-sdio.o
 wilc1000-sdio-objs += wilc_sdio.o
diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/wilc_hif.c
similarity index 100%
rename from drivers/staging/wilc1000/host_interface.c
rename to drivers/staging/wilc1000/wilc_hif.c
diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/wilc_hif.h
similarity index 100%
rename from drivers/staging/wilc1000/host_interface.h
rename to drivers/staging/wilc1000/wilc_hif.h
diff --git a/drivers/staging/wilc1000/wilc_wfi_netdevice.h b/drivers/staging/wilc1000/wilc_wfi_netdevice.h
index e28c8de..1e74a08 100644
--- a/drivers/staging/wilc1000/wilc_wfi_netdevice.h
+++ b/drivers/staging/wilc1000/wilc_wfi_netdevice.h
@@ -14,7 +14,7 @@
 #include <linux/if_arp.h>
 #include <linux/gpio/consumer.h>
 
-#include "host_interface.h"
+#include "wilc_hif.h"
 #include "wilc_wlan.h"
 #include "wilc_wlan_cfg.h"
 
-- 
2.7.4


^ permalink raw reply related

* [PATCH 4/8] staging: wilc1000: remove use of driver_handler_id & ifc_id
From: Ajay.Kathat @ 2019-06-26 12:40 UTC (permalink / raw)
  To: linux-wireless; +Cc: devel, gregkh, Adham.Abozaeid, johannes, Ajay.Kathat
In-Reply-To: <1561552810-8933-1-git-send-email-ajay.kathat@microchip.com>

From: Ajay Singh <ajay.kathat@microchip.com>

Removed the 'driver_handler_id' & 'ifc_id' elements and used 'idx' to
identify the handler.

Signed-off-by: Ajay Singh <ajay.kathat@microchip.com>
---
 drivers/staging/wilc1000/host_interface.c         | 3 +--
 drivers/staging/wilc1000/host_interface.h         | 1 -
 drivers/staging/wilc1000/wilc_netdev.c            | 3 +--
 drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 5 ++---
 drivers/staging/wilc1000/wilc_wfi_netdevice.h     | 1 -
 5 files changed, 4 insertions(+), 9 deletions(-)

diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c
index b505990..389f9f8c 100644
--- a/drivers/staging/wilc1000/host_interface.c
+++ b/drivers/staging/wilc1000/host_interface.c
@@ -1472,7 +1472,7 @@ int wilc_set_wfi_drv_handler(struct wilc_vif *vif, int index, u8 mode,
 	drv.mode = (ifc_id | (mode << 1));
 
 	result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
-				      hif_drv->driver_handler_id);
+				      wilc_get_vif_idx(vif));
 	if (result)
 		netdev_err(vif->ndev, "Failed to set driver handler\n");
 
@@ -1644,7 +1644,6 @@ int wilc_init(struct net_device *dev, struct host_if_drv **hif_drv_handler)
 	for (i = 0; i < wilc->vif_num; i++)
 		if (dev == wilc->vif[i]->ndev) {
 			wilc->vif[i]->hif_drv = hif_drv;
-			hif_drv->driver_handler_id = i + 1;
 			break;
 		}
 
diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h
index 4fcc7a3..be1d249 100644
--- a/drivers/staging/wilc1000/host_interface.h
+++ b/drivers/staging/wilc1000/host_interface.h
@@ -166,7 +166,6 @@ struct host_if_drv {
 	struct wilc_vif *remain_on_ch_timer_vif;
 
 	bool ifc_up;
-	int driver_handler_id;
 	u8 assoc_resp[WILC_MAX_ASSOC_RESP_FRAME_SIZE];
 };
 
diff --git a/drivers/staging/wilc1000/wilc_netdev.c b/drivers/staging/wilc1000/wilc_netdev.c
index 9006111..ad04744 100644
--- a/drivers/staging/wilc1000/wilc_netdev.c
+++ b/drivers/staging/wilc1000/wilc_netdev.c
@@ -636,7 +636,7 @@ static int wilc_mac_open(struct net_device *ndev)
 	for (i = 0; i < wl->vif_num; i++) {
 		if (ndev == wl->vif[i]->ndev) {
 			wilc_set_wfi_drv_handler(vif, wilc_get_vif_idx(vif),
-						 vif->iftype, vif->ifc_id);
+						 vif->iftype, vif->idx);
 			wilc_set_operation_mode(vif, vif->iftype);
 			break;
 		}
@@ -995,7 +995,6 @@ struct wilc_vif *wilc_netdev_ifc_init(struct wilc *wl, const char *name,
 	ndev->needs_free_netdev = true;
 	vif->iftype = vif_type;
 	vif->wilc->vif[wl->vif_num] = vif;
-	vif->ifc_id = wl->vif_num;
 	vif->idx = wl->vif_num;
 	wl->vif_num += 1;
 	vif->mac_opened = 0;
diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c
index 012e325..1580909 100644
--- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c
+++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c
@@ -1462,7 +1462,7 @@ static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev,
 
 		if (wl->initialized) {
 			wilc_set_wfi_drv_handler(vif, wilc_get_vif_idx(vif),
-						 0, vif->ifc_id);
+						 0, vif->idx);
 			wilc_set_operation_mode(vif, WILC_AP_MODE);
 			wilc_set_power_mgmt(vif, 0, 0);
 		}
@@ -1693,11 +1693,10 @@ static int del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev)
 			wl->vif[i] = NULL;
 		} else {
 			vif = wl->vif[i + 1];
-			vif->ifc_id = i;
 			vif->idx = i;
 			wl->vif[i] = vif;
 			wilc_set_wfi_drv_handler(vif, wilc_get_vif_idx(vif),
-						 vif->iftype, vif->ifc_id);
+						 vif->iftype, vif->idx);
 		}
 	}
 	wl->vif_num--;
diff --git a/drivers/staging/wilc1000/wilc_wfi_netdevice.h b/drivers/staging/wilc1000/wilc_wfi_netdevice.h
index fca3380..d5d830d 100644
--- a/drivers/staging/wilc1000/wilc_wfi_netdevice.h
+++ b/drivers/staging/wilc1000/wilc_wfi_netdevice.h
@@ -203,7 +203,6 @@ struct wilc_vif {
 	struct host_if_drv *hif_drv;
 	struct net_device *ndev;
 	u8 mode;
-	u8 ifc_id;
 	struct timer_list during_ip_timer;
 	bool obtaining_ip;
 	struct timer_list periodic_rssi;
-- 
2.7.4


^ permalink raw reply related

* [PATCH 7/8] staging: wilc1000: remove extra argument passing to wilc_send_config_pkt()
From: Ajay.Kathat @ 2019-06-26 12:41 UTC (permalink / raw)
  To: linux-wireless; +Cc: devel, gregkh, Adham.Abozaeid, johannes, Ajay.Kathat
In-Reply-To: <1561552810-8933-1-git-send-email-ajay.kathat@microchip.com>

From: Ajay Singh <ajay.kathat@microchip.com>

Cleanup patch to remove the passing of driver handler, get the 'idx'
value inside the called function.

Signed-off-by: Ajay Singh <ajay.kathat@microchip.com>
---
 drivers/staging/wilc1000/host_interface.c | 116 ++++++++++--------------------
 drivers/staging/wilc1000/wilc_wlan.c      |   3 +-
 drivers/staging/wilc1000/wilc_wlan.h      |   2 +-
 3 files changed, 40 insertions(+), 81 deletions(-)

diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c
index 3688088..9345cab 100644
--- a/drivers/staging/wilc1000/host_interface.c
+++ b/drivers/staging/wilc1000/host_interface.c
@@ -205,9 +205,7 @@ static int handle_scan_done(struct wilc_vif *vif, enum scan_event evt)
 		wid.val = (s8 *)&abort_running_scan;
 		wid.size = sizeof(char);
 
-		result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
-					      wilc_get_vif_idx(vif));
-
+		result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
 		if (result) {
 			netdev_err(vif->ndev, "Failed to set abort running\n");
 			result = -EFAULT;
@@ -328,9 +326,7 @@ int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type,
 	hif_drv->usr_scan_req.scan_result = scan_result_fn;
 	hif_drv->usr_scan_req.arg = user_arg;
 
-	result = wilc_send_config_pkt(vif, WILC_SET_CFG, wid_list,
-				      index,
-				      wilc_get_vif_idx(vif));
+	result = wilc_send_config_pkt(vif, WILC_SET_CFG, wid_list, index);
 	if (result) {
 		netdev_err(vif->ndev, "Failed to send scan parameters\n");
 		goto error;
@@ -380,9 +376,7 @@ static int wilc_send_connect_wid(struct wilc_vif *vif)
 	wid_list[wid_cnt].val = (u8 *)bss_param;
 	wid_cnt++;
 
-	result = wilc_send_config_pkt(vif, WILC_SET_CFG, wid_list,
-				      wid_cnt,
-				      wilc_get_vif_idx(vif));
+	result = wilc_send_config_pkt(vif, WILC_SET_CFG, wid_list, wid_cnt);
 	if (result) {
 		netdev_err(vif->ndev, "failed to send config packet\n");
 		goto error;
@@ -430,8 +424,7 @@ static void handle_connect_timeout(struct work_struct *work)
 	wid.val = (s8 *)&dummy_reason_code;
 	wid.size = sizeof(char);
 
-	result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
-				      wilc_get_vif_idx(vif));
+	result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
 	if (result)
 		netdev_err(vif->ndev, "Failed to send disconnect\n");
 
@@ -619,8 +612,7 @@ static void host_int_get_assoc_res_info(struct wilc_vif *vif,
 	wid.val = assoc_resp_info;
 	wid.size = max_assoc_resp_info_len;
 
-	result = wilc_send_config_pkt(vif, WILC_GET_CFG, &wid, 1,
-				      wilc_get_vif_idx(vif));
+	result = wilc_send_config_pkt(vif, WILC_GET_CFG, &wid, 1);
 	if (result) {
 		*rcvd_assoc_resp_info_len = 0;
 		netdev_err(vif->ndev, "Failed to send association response\n");
@@ -783,8 +775,7 @@ int wilc_disconnect(struct wilc_vif *vif)
 	vif->obtaining_ip = false;
 	wilc_set_power_mgmt(vif, 0, 0);
 
-	result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
-				      wilc_get_vif_idx(vif));
+	result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
 	if (result) {
 		netdev_err(vif->ndev, "Failed to send disconnect\n");
 		return result;
@@ -864,10 +855,7 @@ int wilc_get_statistics(struct wilc_vif *vif, struct rf_info *stats)
 	wid_list[wid_cnt].val = (s8 *)&stats->tx_fail_cnt;
 	wid_cnt++;
 
-	result = wilc_send_config_pkt(vif, WILC_GET_CFG, wid_list,
-				      wid_cnt,
-				      wilc_get_vif_idx(vif));
-
+	result = wilc_send_config_pkt(vif, WILC_GET_CFG, wid_list, wid_cnt);
 	if (result) {
 		netdev_err(vif->ndev, "Failed to send scan parameters\n");
 		return result;
@@ -950,8 +938,7 @@ static int handle_remain_on_chan(struct wilc_vif *vif,
 	wid.val[0] = remain_on_chan_flag;
 	wid.val[1] = (s8)hif_remain_ch->ch;
 
-	result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
-				      wilc_get_vif_idx(vif));
+	result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
 	kfree(wid.val);
 	if (result)
 		return -EBUSY;
@@ -986,8 +973,7 @@ static int wilc_handle_roc_expired(struct wilc_vif *vif, u64 cookie)
 		wid.val[0] = remain_on_chan_flag;
 		wid.val[1] = WILC_FALSE_FRMWR_CHANNEL;
 
-		result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
-					      wilc_get_vif_idx(vif));
+		result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
 		kfree(wid.val);
 		if (result != 0) {
 			netdev_err(vif->ndev, "Failed to set remain channel\n");
@@ -1062,8 +1048,7 @@ static void handle_set_mcast_filter(struct work_struct *work)
 	if (set_mc->cnt > 0 && set_mc->mc_list)
 		memcpy(cur_byte, set_mc->mc_list, set_mc->cnt * ETH_ALEN);
 
-	result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
-				      wilc_get_vif_idx(vif));
+	result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
 	if (result)
 		netdev_err(vif->ndev, "Failed to send setup multicast\n");
 
@@ -1139,8 +1124,7 @@ int wilc_remove_wep_key(struct wilc_vif *vif, u8 index)
 	wid.size = sizeof(char);
 	wid.val = &index;
 
-	result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
-				      wilc_get_vif_idx(vif));
+	result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
 	if (result)
 		netdev_err(vif->ndev,
 			   "Failed to send remove wep key config packet\n");
@@ -1156,8 +1140,7 @@ int wilc_set_wep_default_keyid(struct wilc_vif *vif, u8 index)
 	wid.type = WID_CHAR;
 	wid.size = sizeof(char);
 	wid.val = &index;
-	result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
-				      wilc_get_vif_idx(vif));
+	result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
 	if (result)
 		netdev_err(vif->ndev,
 			   "Failed to send wep default key config packet\n");
@@ -1185,8 +1168,7 @@ int wilc_add_wep_key_bss_sta(struct wilc_vif *vif, const u8 *key, u8 len,
 	wep_key->key_len = len;
 	memcpy(wep_key->key, key, len);
 
-	result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
-				      wilc_get_vif_idx(vif));
+	result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
 	if (result)
 		netdev_err(vif->ndev,
 			   "Failed to add wep key config packet\n");
@@ -1225,8 +1207,7 @@ int wilc_add_wep_key_bss_ap(struct wilc_vif *vif, const u8 *key, u8 len,
 	wep_key->key_len = len;
 	memcpy(wep_key->key, key, len);
 	result = wilc_send_config_pkt(vif, WILC_SET_CFG, wid_list,
-				      ARRAY_SIZE(wid_list),
-				      wilc_get_vif_idx(vif));
+				      ARRAY_SIZE(wid_list));
 	if (result)
 		netdev_err(vif->ndev,
 			   "Failed to add wep ap key config packet\n");
@@ -1273,8 +1254,7 @@ int wilc_add_ptk(struct wilc_vif *vif, const u8 *ptk, u8 ptk_key_len,
 		wid_list[1].size = sizeof(*key_buf) + t_key_len;
 		wid_list[1].val = (u8 *)key_buf;
 		result = wilc_send_config_pkt(vif, WILC_SET_CFG, wid_list,
-					      ARRAY_SIZE(wid_list),
-					      wilc_get_vif_idx(vif));
+					      ARRAY_SIZE(wid_list));
 		kfree(key_buf);
 	} else if (mode == WILC_STATION_MODE) {
 		struct wid wid;
@@ -1300,8 +1280,7 @@ int wilc_add_ptk(struct wilc_vif *vif, const u8 *ptk, u8 ptk_key_len,
 		wid.type = WID_STR;
 		wid.size = sizeof(*key_buf) + t_key_len;
 		wid.val = (s8 *)key_buf;
-		result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
-					      wilc_get_vif_idx(vif));
+		result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
 		kfree(key_buf);
 	}
 
@@ -1353,8 +1332,7 @@ int wilc_add_rx_gtk(struct wilc_vif *vif, const u8 *rx_gtk, u8 gtk_key_len,
 		wid_list[1].val = (u8 *)gtk_key;
 
 		result = wilc_send_config_pkt(vif, WILC_SET_CFG, wid_list,
-					      ARRAY_SIZE(wid_list),
-					      wilc_get_vif_idx(vif));
+					      ARRAY_SIZE(wid_list));
 	} else if (mode == WILC_STATION_MODE) {
 		struct wid wid;
 
@@ -1362,8 +1340,7 @@ int wilc_add_rx_gtk(struct wilc_vif *vif, const u8 *rx_gtk, u8 gtk_key_len,
 		wid.type = WID_STR;
 		wid.size = sizeof(*gtk_key) + t_key_len;
 		wid.val = (u8 *)gtk_key;
-		result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
-					      wilc_get_vif_idx(vif));
+		result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
 	}
 
 	kfree(gtk_key);
@@ -1379,8 +1356,7 @@ int wilc_set_pmkid_info(struct wilc_vif *vif, struct wilc_pmkid_attr *pmkid)
 	wid.size = (pmkid->numpmkid * sizeof(struct wilc_pmkid)) + 1;
 	wid.val = (u8 *)pmkid;
 
-	return wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
-				    wilc_get_vif_idx(vif));
+	return wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
 }
 
 int wilc_get_mac_address(struct wilc_vif *vif, u8 *mac_addr)
@@ -1393,8 +1369,7 @@ int wilc_get_mac_address(struct wilc_vif *vif, u8 *mac_addr)
 	wid.size = ETH_ALEN;
 	wid.val = mac_addr;
 
-	result = wilc_send_config_pkt(vif, WILC_GET_CFG, &wid, 1,
-				      wilc_get_vif_idx(vif));
+	result = wilc_send_config_pkt(vif, WILC_GET_CFG, &wid, 1);
 	if (result)
 		netdev_err(vif->ndev, "Failed to get mac address\n");
 
@@ -1444,8 +1419,7 @@ int wilc_set_mac_chnl_num(struct wilc_vif *vif, u8 channel)
 	wid.size = sizeof(char);
 	wid.val = &channel;
 
-	result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
-				      wilc_get_vif_idx(vif));
+	result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
 	if (result)
 		netdev_err(vif->ndev, "Failed to set channel\n");
 
@@ -1471,8 +1445,7 @@ int wilc_set_wfi_drv_handler(struct wilc_vif *vif, int index, u8 mode,
 	drv.handler = cpu_to_le32(index);
 	drv.mode = (ifc_id | (mode << 1));
 
-	result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
-				      wilc_get_vif_idx(vif));
+	result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
 	if (result)
 		netdev_err(vif->ndev, "Failed to set driver handler\n");
 
@@ -1492,8 +1465,7 @@ int wilc_set_operation_mode(struct wilc_vif *vif, u32 mode)
 
 	op_mode.mode = cpu_to_le32(mode);
 
-	result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
-				      wilc_get_vif_idx(vif));
+	result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
 	if (result)
 		netdev_err(vif->ndev, "Failed to set operation mode\n");
 
@@ -1513,8 +1485,7 @@ s32 wilc_get_inactive_time(struct wilc_vif *vif, const u8 *mac, u32 *out_val)
 		return -ENOMEM;
 
 	ether_addr_copy(wid.val, mac);
-	result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
-				      wilc_get_vif_idx(vif));
+	result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
 	kfree(wid.val);
 	if (result) {
 		netdev_err(vif->ndev, "Failed to set inactive mac\n");
@@ -1525,8 +1496,7 @@ s32 wilc_get_inactive_time(struct wilc_vif *vif, const u8 *mac, u32 *out_val)
 	wid.type = WID_INT;
 	wid.val = (s8 *)out_val;
 	wid.size = sizeof(u32);
-	result = wilc_send_config_pkt(vif, WILC_GET_CFG, &wid, 1,
-				      wilc_get_vif_idx(vif));
+	result = wilc_send_config_pkt(vif, WILC_GET_CFG, &wid, 1);
 	if (result)
 		netdev_err(vif->ndev, "Failed to get inactive time\n");
 
@@ -1547,8 +1517,7 @@ int wilc_get_rssi(struct wilc_vif *vif, s8 *rssi_level)
 	wid.type = WID_CHAR;
 	wid.size = sizeof(char);
 	wid.val = rssi_level;
-	result = wilc_send_config_pkt(vif, WILC_GET_CFG, &wid, 1,
-				      wilc_get_vif_idx(vif));
+	result = wilc_send_config_pkt(vif, WILC_GET_CFG, &wid, 1);
 	if (result)
 		netdev_err(vif->ndev, "Failed to get RSSI value\n");
 
@@ -1610,8 +1579,7 @@ int wilc_hif_set_cfg(struct wilc_vif *vif, struct cfg_param_attr *param)
 		i++;
 	}
 
-	return wilc_send_config_pkt(vif, WILC_SET_CFG, wid_list,
-				    i, wilc_get_vif_idx(vif));
+	return wilc_send_config_pkt(vif, WILC_SET_CFG, wid_list, i);
 }
 
 static void get_periodic_rssi(struct timer_list *t)
@@ -1876,8 +1844,7 @@ void wilc_frame_register(struct wilc_vif *vif, u16 frame_type, bool reg)
 		break;
 	}
 	reg_frame.frame_type = cpu_to_le16(frame_type);
-	result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
-				      wilc_get_vif_idx(vif));
+	result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
 	if (result)
 		netdev_err(vif->ndev, "Failed to frame register\n");
 }
@@ -1914,8 +1881,7 @@ int wilc_add_beacon(struct wilc_vif *vif, u32 interval, u32 dtim_period,
 	if (params->tail_len > 0)
 		memcpy(cur_byte, params->tail, params->tail_len);
 
-	result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
-				      wilc_get_vif_idx(vif));
+	result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
 	if (result)
 		netdev_err(vif->ndev, "Failed to send add beacon\n");
 
@@ -1935,8 +1901,7 @@ int wilc_del_beacon(struct wilc_vif *vif)
 	wid.size = sizeof(char);
 	wid.val = &del_beacon;
 
-	result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
-				      wilc_get_vif_idx(vif));
+	result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
 	if (result)
 		netdev_err(vif->ndev, "Failed to send delete beacon\n");
 
@@ -1960,8 +1925,7 @@ int wilc_add_station(struct wilc_vif *vif, const u8 *mac,
 	cur_byte = wid.val;
 	wilc_hif_pack_sta_param(cur_byte, mac, params);
 
-	result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
-				      wilc_get_vif_idx(vif));
+	result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
 	if (result != 0)
 		netdev_err(vif->ndev, "Failed to send add station\n");
 
@@ -1987,8 +1951,7 @@ int wilc_del_station(struct wilc_vif *vif, const u8 *mac_addr)
 	else
 		ether_addr_copy(wid.val, mac_addr);
 
-	result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
-				      wilc_get_vif_idx(vif));
+	result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
 	if (result)
 		netdev_err(vif->ndev, "Failed to del station\n");
 
@@ -2023,8 +1986,7 @@ int wilc_del_allstation(struct wilc_vif *vif, u8 mac_addr[][ETH_ALEN])
 	wid.size = (assoc_sta * ETH_ALEN) + 1;
 	wid.val = (u8 *)&del_sta;
 
-	result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
-				      wilc_get_vif_idx(vif));
+	result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
 	if (result)
 		netdev_err(vif->ndev, "Failed to send delete all station\n");
 
@@ -2048,8 +2010,7 @@ int wilc_edit_station(struct wilc_vif *vif, const u8 *mac,
 	cur_byte = wid.val;
 	wilc_hif_pack_sta_param(cur_byte, mac, params);
 
-	result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
-				      wilc_get_vif_idx(vif));
+	result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
 	if (result)
 		netdev_err(vif->ndev, "Failed to send edit station\n");
 
@@ -2074,8 +2035,7 @@ int wilc_set_power_mgmt(struct wilc_vif *vif, bool enabled, u32 timeout)
 	wid.id = WID_POWER_MANAGEMENT;
 	wid.val = &power_mode;
 	wid.size = sizeof(char);
-	result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
-				      wilc_get_vif_idx(vif));
+	result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
 	if (result)
 		netdev_err(vif->ndev, "Failed to send power management\n");
 
@@ -2113,8 +2073,7 @@ int wilc_set_tx_power(struct wilc_vif *vif, u8 tx_power)
 	wid.val = &tx_power;
 	wid.size = sizeof(char);
 
-	return wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
-				   wilc_get_vif_idx(vif));
+	return wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
 }
 
 int wilc_get_tx_power(struct wilc_vif *vif, u8 *tx_power)
@@ -2126,6 +2085,5 @@ int wilc_get_tx_power(struct wilc_vif *vif, u8 *tx_power)
 	wid.val = tx_power;
 	wid.size = sizeof(char);
 
-	return wilc_send_config_pkt(vif, WILC_GET_CFG, &wid, 1,
-				    wilc_get_vif_idx(vif));
+	return wilc_send_config_pkt(vif, WILC_GET_CFG, &wid, 1);
 }
diff --git a/drivers/staging/wilc1000/wilc_wlan.c b/drivers/staging/wilc1000/wilc_wlan.c
index bd2ffc3..d46876e 100644
--- a/drivers/staging/wilc1000/wilc_wlan.c
+++ b/drivers/staging/wilc1000/wilc_wlan.c
@@ -1202,10 +1202,11 @@ int wilc_wlan_cfg_get_val(struct wilc *wl, u16 wid, u8 *buffer, u32 buffer_size)
 }
 
 int wilc_send_config_pkt(struct wilc_vif *vif, u8 mode, struct wid *wids,
-			 u32 count, u32 drv)
+			 u32 count)
 {
 	int i;
 	int ret = 0;
+	u32 drv = wilc_get_vif_idx(vif);
 
 	if (mode == WILC_GET_CFG) {
 		for (i = 0; i < count; i++) {
diff --git a/drivers/staging/wilc1000/wilc_wlan.h b/drivers/staging/wilc1000/wilc_wlan.h
index 3e54a56..d2eef7b 100644
--- a/drivers/staging/wilc1000/wilc_wlan.h
+++ b/drivers/staging/wilc1000/wilc_wlan.h
@@ -307,7 +307,7 @@ void host_sleep_notify(struct wilc *wilc);
 void chip_allow_sleep(struct wilc *wilc);
 void chip_wakeup(struct wilc *wilc);
 int wilc_send_config_pkt(struct wilc_vif *vif, u8 mode, struct wid *wids,
-			 u32 count, u32 drv);
+			 u32 count);
 int wilc_wlan_init(struct net_device *dev);
 u32 wilc_get_chipid(struct wilc *wilc, bool update);
 #endif
-- 
2.7.4


^ permalink raw reply related

* [PATCH 5/8] staging: wilc1000: remove unnecessary loop to traverse vif interfaces
From: Ajay.Kathat @ 2019-06-26 12:40 UTC (permalink / raw)
  To: linux-wireless; +Cc: devel, gregkh, Adham.Abozaeid, johannes, Ajay.Kathat
In-Reply-To: <1561552810-8933-1-git-send-email-ajay.kathat@microchip.com>

From: Ajay Singh <ajay.kathat@microchip.com>

Cleanup patch to avoid loop to traverse the interfaces instead make use
of vif received from net_device priv data.

Signed-off-by: Ajay Singh <ajay.kathat@microchip.com>
---
 drivers/staging/wilc1000/host_interface.c |  7 +------
 drivers/staging/wilc1000/wilc_netdev.c    | 16 +++++-----------
 2 files changed, 6 insertions(+), 17 deletions(-)

diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c
index 389f9f8c..3688088 100644
--- a/drivers/staging/wilc1000/host_interface.c
+++ b/drivers/staging/wilc1000/host_interface.c
@@ -1634,19 +1634,14 @@ int wilc_init(struct net_device *dev, struct host_if_drv **hif_drv_handler)
 	struct host_if_drv *hif_drv;
 	struct wilc_vif *vif = netdev_priv(dev);
 	struct wilc *wilc = vif->wilc;
-	int i;
 
 	hif_drv  = kzalloc(sizeof(*hif_drv), GFP_KERNEL);
 	if (!hif_drv)
 		return -ENOMEM;
 
 	*hif_drv_handler = hif_drv;
-	for (i = 0; i < wilc->vif_num; i++)
-		if (dev == wilc->vif[i]->ndev) {
-			wilc->vif[i]->hif_drv = hif_drv;
-			break;
-		}
 
+	vif->hif_drv = hif_drv;
 	vif->obtaining_ip = false;
 
 	if (wilc->clients_count == 0)
diff --git a/drivers/staging/wilc1000/wilc_netdev.c b/drivers/staging/wilc1000/wilc_netdev.c
index ad04744..0af60b2 100644
--- a/drivers/staging/wilc1000/wilc_netdev.c
+++ b/drivers/staging/wilc1000/wilc_netdev.c
@@ -614,7 +614,6 @@ static int wilc_mac_open(struct net_device *ndev)
 	struct wilc_priv *priv = wdev_priv(vif->ndev->ieee80211_ptr);
 	unsigned char mac_add[ETH_ALEN] = {0};
 	int ret = 0;
-	int i = 0;
 
 	if (!wl || !wl->dev) {
 		netdev_err(ndev, "device not ready\n");
@@ -633,19 +632,14 @@ static int wilc_mac_open(struct net_device *ndev)
 		return ret;
 	}
 
-	for (i = 0; i < wl->vif_num; i++) {
-		if (ndev == wl->vif[i]->ndev) {
-			wilc_set_wfi_drv_handler(vif, wilc_get_vif_idx(vif),
-						 vif->iftype, vif->idx);
-			wilc_set_operation_mode(vif, vif->iftype);
-			break;
-		}
-	}
+	wilc_set_wfi_drv_handler(vif, wilc_get_vif_idx(vif), vif->iftype,
+				 vif->idx);
+	wilc_set_operation_mode(vif, vif->iftype);
 
 	wilc_get_mac_address(vif, mac_add);
 	netdev_dbg(ndev, "Mac address: %pM\n", mac_add);
-	memcpy(wl->vif[i]->src_addr, mac_add, ETH_ALEN);
-	memcpy(ndev->dev_addr, wl->vif[i]->src_addr, ETH_ALEN);
+	memcpy(vif->src_addr, mac_add, ETH_ALEN);
+	memcpy(ndev->dev_addr, vif->src_addr, ETH_ALEN);
 
 	if (!is_valid_ether_addr(ndev->dev_addr)) {
 		netdev_err(ndev, "Wrong MAC address\n");
-- 
2.7.4


^ permalink raw reply related

* [PATCH 3/8] staging: wilc1000: added support to dynamically add/remove interfaces
From: Ajay.Kathat @ 2019-06-26 12:40 UTC (permalink / raw)
  To: linux-wireless; +Cc: devel, gregkh, Adham.Abozaeid, johannes, Ajay.Kathat
In-Reply-To: <1561552810-8933-1-git-send-email-ajay.kathat@microchip.com>

From: Ajay Singh <ajay.kathat@microchip.com>

Removed the use of two hardcoded interfaces and added support to
add/remove the network interfaces dynamically.
Now the driver will have single default interface with name 'wlan0' and
later other interface can be added from user space application e.g
using 'iw add' command.
Also taken care to maintain 'wilc_vif' as part of 'net_device'
private data and 'wilc' struct as 'wiphy' private data.

Signed-off-by: Ajay Singh <ajay.kathat@microchip.com>
---
 drivers/staging/wilc1000/wilc_mon.c               |   9 +-
 drivers/staging/wilc1000/wilc_netdev.c            | 269 ++++-------
 drivers/staging/wilc1000/wilc_sdio.c              |   7 +-
 drivers/staging/wilc1000/wilc_spi.c               |   3 +-
 drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 535 ++++++++++++++--------
 drivers/staging/wilc1000/wilc_wfi_cfgoperations.h |  13 +-
 drivers/staging/wilc1000/wilc_wfi_netdevice.h     |  20 +-
 drivers/staging/wilc1000/wilc_wlan.c              |  20 +-
 drivers/staging/wilc1000/wilc_wlan.h              |   6 +-
 9 files changed, 492 insertions(+), 390 deletions(-)

diff --git a/drivers/staging/wilc1000/wilc_mon.c b/drivers/staging/wilc1000/wilc_mon.c
index 9fe19a3..7d7933d4 100644
--- a/drivers/staging/wilc1000/wilc_mon.c
+++ b/drivers/staging/wilc1000/wilc_mon.c
@@ -233,6 +233,7 @@ struct net_device *wilc_wfi_init_mon_interface(struct wilc *wl,
 	strncpy(wl->monitor_dev->name, name, IFNAMSIZ);
 	wl->monitor_dev->name[IFNAMSIZ - 1] = 0;
 	wl->monitor_dev->netdev_ops = &wilc_wfi_netdev_ops;
+	wl->monitor_dev->needs_free_netdev = true;
 
 	if (register_netdevice(wl->monitor_dev)) {
 		netdev_err(real_dev, "register_netdevice failed\n");
@@ -247,12 +248,14 @@ struct net_device *wilc_wfi_init_mon_interface(struct wilc *wl,
 	return wl->monitor_dev;
 }
 
-void wilc_wfi_deinit_mon_interface(struct wilc *wl)
+void wilc_wfi_deinit_mon_interface(struct wilc *wl, bool rtnl_locked)
 {
 	if (!wl->monitor_dev)
 		return;
 
-	unregister_netdev(wl->monitor_dev);
-	free_netdev(wl->monitor_dev);
+	if (rtnl_locked)
+		unregister_netdevice(wl->monitor_dev);
+	else
+		unregister_netdev(wl->monitor_dev);
 	wl->monitor_dev = NULL;
 }
diff --git a/drivers/staging/wilc1000/wilc_netdev.c b/drivers/staging/wilc1000/wilc_netdev.c
index 0e0a4ee..9006111 100644
--- a/drivers/staging/wilc1000/wilc_netdev.c
+++ b/drivers/staging/wilc1000/wilc_netdev.c
@@ -97,22 +97,29 @@ static struct net_device *get_if_handler(struct wilc *wilc, u8 *mac_header)
 {
 	u8 *bssid, *bssid1;
 	int i = 0;
+	struct net_device *ndev = NULL;
 
 	bssid = mac_header + 10;
 	bssid1 = mac_header + 4;
 
+	mutex_lock(&wilc->vif_mutex);
 	for (i = 0; i < wilc->vif_num; i++) {
 		if (wilc->vif[i]->mode == WILC_STATION_MODE)
 			if (ether_addr_equal_unaligned(bssid,
-						       wilc->vif[i]->bssid))
-				return wilc->vif[i]->ndev;
+						       wilc->vif[i]->bssid)) {
+				ndev = wilc->vif[i]->ndev;
+				goto out;
+			}
 		if (wilc->vif[i]->mode == WILC_AP_MODE)
 			if (ether_addr_equal_unaligned(bssid1,
-						       wilc->vif[i]->bssid))
-				return wilc->vif[i]->ndev;
+						       wilc->vif[i]->bssid)) {
+				ndev = wilc->vif[i]->ndev;
+				goto out;
+			}
 	}
-
-	return NULL;
+out:
+	mutex_unlock(&wilc->vif_mutex);
+	return ndev;
 }
 
 void wilc_wlan_set_bssid(struct net_device *wilc_netdev, u8 *bssid, u8 mode)
@@ -143,9 +150,7 @@ static int wilc_txq_task(void *vp)
 {
 	int ret;
 	u32 txq_count;
-	struct net_device *dev = vp;
-	struct wilc_vif *vif = netdev_priv(dev);
-	struct wilc *wl = vif->wilc;
+	struct wilc *wl = vp;
 
 	complete(&wl->txq_thread_started);
 	while (1) {
@@ -159,14 +164,18 @@ static int wilc_txq_task(void *vp)
 			break;
 		}
 		do {
-			ret = wilc_wlan_handle_txq(dev, &txq_count);
+			ret = wilc_wlan_handle_txq(wl, &txq_count);
 			if (txq_count < FLOW_CONTROL_LOWER_THRESHOLD) {
-				if (wl->vif[0]->mac_opened &&
-				    netif_queue_stopped(wl->vif[0]->ndev))
-					netif_wake_queue(wl->vif[0]->ndev);
-				if (wl->vif[1]->mac_opened &&
-				    netif_queue_stopped(wl->vif[1]->ndev))
-					netif_wake_queue(wl->vif[1]->ndev);
+				int i;
+				struct wilc_vif *ifc;
+
+				mutex_lock(&wl->vif_mutex);
+				for (i = 0; i < wl->vif_num; i++) {
+					ifc = wl->vif[i];
+					if (ifc->mac_opened && ifc->ndev)
+						netif_wake_queue(ifc->ndev);
+				}
+				mutex_unlock(&wl->vif_mutex);
 			}
 		} while (ret == -ENOBUFS && !wl->close);
 	}
@@ -245,14 +254,13 @@ static int wilc1000_firmware_download(struct net_device *dev)
 
 static int wilc_init_fw_config(struct net_device *dev, struct wilc_vif *vif)
 {
-	struct wilc_priv *priv;
+	struct wilc_priv *priv = &vif->priv;
 	struct host_if_drv *hif_drv;
 	u8 b;
 	u16 hw;
 	u32 w;
 
 	netdev_dbg(dev, "Start configuring Firmware\n");
-	priv = wiphy_priv(dev->ieee80211_ptr->wiphy);
 	hif_drv = (struct host_if_drv *)priv->hif_drv;
 	netdev_dbg(dev, "Host = %p\n", hif_drv);
 
@@ -424,6 +432,7 @@ static void wlan_deinit_locks(struct net_device *dev)
 	mutex_destroy(&wilc->rxq_cs);
 	mutex_destroy(&wilc->cfg_cmd_lock);
 	mutex_destroy(&wilc->txq_add_to_head_cs);
+	mutex_destroy(&wilc->vif_mutex);
 }
 
 static void wlan_deinitialize_threads(struct net_device *dev)
@@ -477,31 +486,12 @@ static void wilc_wlan_deinitialize(struct net_device *dev)
 	}
 }
 
-static void wlan_init_locks(struct net_device *dev)
-{
-	struct wilc_vif *vif = netdev_priv(dev);
-	struct wilc *wl = vif->wilc;
-
-	mutex_init(&wl->hif_cs);
-	mutex_init(&wl->rxq_cs);
-	mutex_init(&wl->cfg_cmd_lock);
-
-	spin_lock_init(&wl->txq_spinlock);
-	mutex_init(&wl->txq_add_to_head_cs);
-
-	init_completion(&wl->txq_event);
-
-	init_completion(&wl->cfg_event);
-	init_completion(&wl->sync_event);
-	init_completion(&wl->txq_thread_started);
-}
-
 static int wlan_initialize_threads(struct net_device *dev)
 {
 	struct wilc_vif *vif = netdev_priv(dev);
 	struct wilc *wilc = vif->wilc;
 
-	wilc->txq_thread = kthread_run(wilc_txq_task, (void *)dev,
+	wilc->txq_thread = kthread_run(wilc_txq_task, (void *)wilc,
 				       "K_TXQ_TASK");
 	if (IS_ERR(wilc->txq_thread)) {
 		netdev_err(dev, "couldn't create TXQ thread\n");
@@ -513,6 +503,12 @@ static int wlan_initialize_threads(struct net_device *dev)
 	return 0;
 }
 
+static int dev_state_ev_handler(struct notifier_block *this,
+				unsigned long event, void *ptr);
+static struct notifier_block g_dev_notifier = {
+	.notifier_call = dev_state_ev_handler
+};
+
 static int wilc_wlan_initialize(struct net_device *dev, struct wilc_vif *vif)
 {
 	int ret = 0;
@@ -522,13 +518,9 @@ static int wilc_wlan_initialize(struct net_device *dev, struct wilc_vif *vif)
 		wl->mac_status = WILC_MAC_STATUS_INIT;
 		wl->close = 0;
 
-		wlan_init_locks(dev);
-
 		ret = wilc_wlan_init(dev);
-		if (ret < 0) {
-			ret = -EIO;
-			goto fail_locks;
-		}
+		if (ret < 0)
+			return -EIO;
 
 		ret = wlan_initialize_threads(dev);
 		if (ret < 0) {
@@ -582,7 +574,7 @@ static int wilc_wlan_initialize(struct net_device *dev, struct wilc_vif *vif)
 			ret = -EIO;
 			goto fail_fw_start;
 		}
-
+		register_inetaddr_notifier(&g_dev_notifier);
 		wl->initialized = true;
 		return 0;
 
@@ -600,8 +592,6 @@ static int wilc_wlan_initialize(struct net_device *dev, struct wilc_vif *vif)
 		wlan_deinitialize_threads(dev);
 fail_wilc_wlan:
 		wilc_wlan_cleanup(dev);
-fail_locks:
-		wlan_deinit_locks(dev);
 		netdev_err(dev, "WLAN initialization FAILED\n");
 	} else {
 		netdev_dbg(dev, "wilc1000 already initialized\n");
@@ -758,16 +748,19 @@ netdev_tx_t wilc_mac_xmit(struct sk_buff *skb, struct net_device *ndev)
 
 	vif->netstats.tx_packets++;
 	vif->netstats.tx_bytes += tx_data->size;
-	tx_data->bssid = wilc->vif[vif->idx]->bssid;
 	queue_count = wilc_wlan_txq_add_net_pkt(ndev, (void *)tx_data,
 						tx_data->buff, tx_data->size,
 						wilc_tx_complete);
 
 	if (queue_count > FLOW_CONTROL_UPPER_THRESHOLD) {
-		if (wilc->vif[0]->mac_opened)
-			netif_stop_queue(wilc->vif[0]->ndev);
-		if (wilc->vif[1]->mac_opened)
-			netif_stop_queue(wilc->vif[1]->ndev);
+		int i;
+
+		mutex_lock(&wilc->vif_mutex);
+		for (i = 0; i < wilc->vif_num; i++) {
+			if (wilc->vif[i]->mac_opened)
+				netif_stop_queue(wilc->vif[i]->ndev);
+		}
+		mutex_unlock(&wilc->vif_mutex);
 	}
 
 	return 0;
@@ -794,6 +787,7 @@ static int wilc_mac_close(struct net_device *ndev)
 	if (wl->open_ifcs == 0) {
 		netdev_dbg(ndev, "Deinitializing wilc1000\n");
 		wl->close = 1;
+		unregister_inetaddr_notifier(&g_dev_notifier);
 		wilc_wlan_deinitialize(ndev);
 	}
 
@@ -848,18 +842,23 @@ void wilc_wfi_mgmt_rx(struct wilc *wilc, u8 *buff, u32 size)
 	int i = 0;
 	struct wilc_vif *vif;
 
+	mutex_lock(&wilc->vif_mutex);
 	for (i = 0; i < wilc->vif_num; i++) {
+		u16 type = le16_to_cpup((__le16 *)buff);
+
 		vif = netdev_priv(wilc->vif[i]->ndev);
+		if ((type == vif->frame_reg[0].type && vif->frame_reg[0].reg) ||
+		    (type == vif->frame_reg[1].type && vif->frame_reg[1].reg)) {
+			wilc_wfi_p2p_rx(vif, buff, size);
+			break;
+		}
+
 		if (vif->monitor_flag) {
 			wilc_wfi_monitor_rx(wilc->monitor_dev, buff, size);
-			return;
+			break;
 		}
 	}
-
-	vif = netdev_priv(wilc->vif[1]->ndev);
-	if ((buff[0] == vif->frame_reg[0].type && vif->frame_reg[0].reg) ||
-	    (buff[0] == vif->frame_reg[1].type && vif->frame_reg[1].reg))
-		wilc_wfi_p2p_rx(wilc->vif[1]->ndev, buff, size);
+	mutex_unlock(&wilc->vif_mutex);
 }
 
 static const struct net_device_ops wilc_netdev_ops = {
@@ -890,14 +889,10 @@ static int dev_state_ev_handler(struct notifier_block *this,
 	if (!dev->ieee80211_ptr || !dev->ieee80211_ptr->wiphy)
 		return NOTIFY_DONE;
 
-	priv = wiphy_priv(dev->ieee80211_ptr->wiphy);
-	if (!priv)
-		return NOTIFY_DONE;
+	vif = netdev_priv(dev);
+	priv = &vif->priv;
 
 	hif_drv = (struct host_if_drv *)priv->hif_drv;
-	vif = netdev_priv(dev);
-	if (!vif || !hif_drv)
-		return NOTIFY_DONE;
 
 	switch (event) {
 	case NETDEV_UP:
@@ -932,10 +927,6 @@ static int dev_state_ev_handler(struct notifier_block *this,
 	return NOTIFY_DONE;
 }
 
-static struct notifier_block g_dev_notifier = {
-	.notifier_call = dev_state_ev_handler
-};
-
 void wilc_netdev_cleanup(struct wilc *wilc)
 {
 	int i;
@@ -943,136 +934,72 @@ void wilc_netdev_cleanup(struct wilc *wilc)
 	if (!wilc)
 		return;
 
-	if (wilc->vif[0]->ndev || wilc->vif[1]->ndev)
-		unregister_inetaddr_notifier(&g_dev_notifier);
-
 	if (wilc->firmware) {
 		release_firmware(wilc->firmware);
 		wilc->firmware = NULL;
 	}
 
-	for (i = 0; i < WILC_NUM_CONCURRENT_IFC; i++) {
-		if (wilc->vif[i] && wilc->vif[i]->ndev) {
+	for (i = 0; i < wilc->vif_num; i++) {
+		if (wilc->vif[i] && wilc->vif[i]->ndev)
 			unregister_netdev(wilc->vif[i]->ndev);
-			wilc_free_wiphy(wilc->vif[i]->ndev);
-			free_netdev(wilc->vif[i]->ndev);
-		}
 	}
 
-	wilc_wfi_deinit_mon_interface(wilc);
+	wilc_wfi_deinit_mon_interface(wilc, false);
 	flush_workqueue(wilc->hif_workqueue);
 	destroy_workqueue(wilc->hif_workqueue);
 	wilc_wlan_cfg_deinit(wilc);
 	kfree(wilc->bus_data);
-	kfree(wilc);
+	wiphy_unregister(wilc->wiphy);
+	wiphy_free(wilc->wiphy);
 }
 EXPORT_SYMBOL_GPL(wilc_netdev_cleanup);
 
-int wilc_netdev_init(struct wilc **wilc, struct device *dev, int io_type,
-		     const struct wilc_hif_func *ops)
+struct wilc_vif *wilc_netdev_ifc_init(struct wilc *wl, const char *name,
+				      int vif_type, enum nl80211_iftype type,
+				      bool rtnl_locked)
 {
-	int i, ret;
-	struct wilc_vif *vif;
 	struct net_device *ndev;
-	struct wilc *wl;
-
-	wl = kzalloc(sizeof(*wl), GFP_KERNEL);
-	if (!wl)
-		return -ENOMEM;
-
-	ret = wilc_wlan_cfg_init(wl);
-	if (ret)
-		goto free_wl;
-
-	*wilc = wl;
-	wl->io_type = io_type;
-	wl->hif_func = ops;
-	wl->enable_ps = true;
-	wl->chip_ps_state = WILC_CHIP_WAKEDUP;
-	INIT_LIST_HEAD(&wl->txq_head.list);
-	INIT_LIST_HEAD(&wl->rxq_head.list);
-
-	wl->hif_workqueue = create_singlethread_workqueue("WILC_wq");
-	if (!wl->hif_workqueue) {
-		ret = -ENOMEM;
-		goto free_cfg;
-	}
-
-	register_inetaddr_notifier(&g_dev_notifier);
-
-	for (i = 0; i < WILC_NUM_CONCURRENT_IFC; i++) {
-		struct wireless_dev *wdev;
+	struct wilc_vif *vif;
+	int ret;
 
-		ndev = alloc_etherdev(sizeof(struct wilc_vif));
-		if (!ndev) {
-			ret = -ENOMEM;
-			goto free_ndev;
-		}
+	ndev = alloc_etherdev(sizeof(*vif));
+	if (!ndev)
+		return ERR_PTR(-ENOMEM);
 
-		vif = netdev_priv(ndev);
+	vif = netdev_priv(ndev);
+	ndev->ieee80211_ptr = &vif->priv.wdev;
+	strcpy(ndev->name, name);
+	vif->wilc = wl;
+	vif->ndev = ndev;
+	ndev->ml_priv = vif;
 
-		if (i == 0) {
-			strcpy(ndev->name, "wlan%d");
-			vif->ifc_id = 1;
-		} else {
-			strcpy(ndev->name, "p2p%d");
-			vif->ifc_id = 0;
-		}
-		vif->wilc = *wilc;
-		vif->ndev = ndev;
-		wl->vif[i] = vif;
-		wl->vif_num = i + 1;
-		vif->idx = i;
-
-		ndev->netdev_ops = &wilc_netdev_ops;
-
-		wdev = wilc_create_wiphy(ndev, dev);
-		if (!wdev) {
-			netdev_err(ndev, "Can't register WILC Wiphy\n");
-			ret = -ENOMEM;
-			goto free_ndev;
-		}
+	ndev->netdev_ops = &wilc_netdev_ops;
 
-		SET_NETDEV_DEV(ndev, dev);
+	SET_NETDEV_DEV(ndev, wiphy_dev(wl->wiphy));
 
-		vif->ndev->ieee80211_ptr = wdev;
-		vif->ndev->ml_priv = vif;
-		wdev->netdev = vif->ndev;
-		vif->netstats.rx_packets = 0;
-		vif->netstats.tx_packets = 0;
-		vif->netstats.rx_bytes = 0;
-		vif->netstats.tx_bytes = 0;
+	vif->priv.wdev.wiphy = wl->wiphy;
+	vif->priv.wdev.netdev = ndev;
+	vif->priv.wdev.iftype = type;
+	vif->priv.dev = ndev;
 
+	if (rtnl_locked)
+		ret = register_netdevice(ndev);
+	else
 		ret = register_netdev(ndev);
-		if (ret)
-			goto free_ndev;
 
-		vif->iftype = WILC_STATION_MODE;
-		vif->mac_opened = 0;
+	if (ret) {
+		free_netdev(ndev);
+		return ERR_PTR(-EFAULT);
 	}
 
-	return 0;
-
-free_ndev:
-	for (; i >= 0; i--) {
-		if (wl->vif[i]) {
-			if (wl->vif[i]->iftype == WILC_STATION_MODE)
-				unregister_netdev(wl->vif[i]->ndev);
-
-			if (wl->vif[i]->ndev) {
-				wilc_free_wiphy(wl->vif[i]->ndev);
-				free_netdev(wl->vif[i]->ndev);
-			}
-		}
-	}
-	unregister_inetaddr_notifier(&g_dev_notifier);
-	destroy_workqueue(wl->hif_workqueue);
-free_cfg:
-	wilc_wlan_cfg_deinit(wl);
-free_wl:
-	kfree(wl);
-	return ret;
+	ndev->needs_free_netdev = true;
+	vif->iftype = vif_type;
+	vif->wilc->vif[wl->vif_num] = vif;
+	vif->ifc_id = wl->vif_num;
+	vif->idx = wl->vif_num;
+	wl->vif_num += 1;
+	vif->mac_opened = 0;
+	return vif;
 }
-EXPORT_SYMBOL_GPL(wilc_netdev_init);
 
 MODULE_LICENSE("GPL");
diff --git a/drivers/staging/wilc1000/wilc_sdio.c b/drivers/staging/wilc1000/wilc_sdio.c
index b789c57..4c1c81f 100644
--- a/drivers/staging/wilc1000/wilc_sdio.c
+++ b/drivers/staging/wilc1000/wilc_sdio.c
@@ -8,6 +8,7 @@
 #include <linux/mmc/host.h>
 
 #include "wilc_wfi_netdevice.h"
+#include "wilc_wfi_cfgoperations.h"
 
 #define SDIO_MODALIAS "wilc1000_sdio"
 
@@ -139,11 +140,9 @@ static int wilc_sdio_probe(struct sdio_func *func,
 		}
 	}
 
-	dev_dbg(&func->dev, "Initializing netdev\n");
-	ret = wilc_netdev_init(&wilc, &func->dev, WILC_HIF_SDIO,
-			       &wilc_hif_sdio);
+	ret = wilc_cfg80211_init(&wilc, &func->dev, WILC_HIF_SDIO,
+				 &wilc_hif_sdio);
 	if (ret) {
-		dev_err(&func->dev, "Couldn't initialize netdev\n");
 		kfree(sdio_priv);
 		return ret;
 	}
diff --git a/drivers/staging/wilc1000/wilc_spi.c b/drivers/staging/wilc1000/wilc_spi.c
index d8910bf..3c1ae9e 100644
--- a/drivers/staging/wilc1000/wilc_spi.c
+++ b/drivers/staging/wilc1000/wilc_spi.c
@@ -7,6 +7,7 @@
 #include <linux/spi/spi.h>
 
 #include "wilc_wfi_netdevice.h"
+#include "wilc_wfi_cfgoperations.h"
 
 struct wilc_spi {
 	int crc_off;
@@ -120,7 +121,7 @@ static int wilc_bus_probe(struct spi_device *spi)
 			dev_err(&spi->dev, "failed to get the irq gpio\n");
 	}
 
-	ret = wilc_netdev_init(&wilc, NULL, WILC_HIF_SPI, &wilc_hif_spi);
+	ret = wilc_cfg80211_init(&wilc, &spi->dev, WILC_HIF_SPI, &wilc_hif_spi);
 	if (ret) {
 		kfree(spi_priv);
 		return ret;
diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c
index b0daa11..012e325 100644
--- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c
+++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c
@@ -183,48 +183,67 @@ static void cfg_connect_result(enum conn_event conn_disconn_evt, u8 mac_status,
 		eth_zero_addr(priv->associated_bss);
 		wilc_wlan_set_bssid(priv->dev, NULL, WILC_STATION_MODE);
 
-		if (vif->iftype != WILC_CLIENT_MODE)
+		if (vif->iftype != WILC_CLIENT_MODE) {
 			wl->sta_ch = WILC_INVALID_CHANNEL;
-
-		if (wfi_drv->ifc_up && dev == wl->vif[1]->ndev)
-			reason = 3;
-		else if (!wfi_drv->ifc_up && dev == wl->vif[1]->ndev)
-			reason = 1;
+		} else {
+			if (wfi_drv->ifc_up)
+				reason = 3;
+			else
+				reason = 1;
+		}
 
 		cfg80211_disconnected(dev, reason, NULL, 0, false, GFP_KERNEL);
 	}
 }
 
+static struct wilc_vif *wilc_get_wl_to_vif(struct wilc *wl)
+{
+	int i;
+
+	for (i = 0; i < wl->vif_num; i++)
+		if (wl->vif[i])
+			return wl->vif[i];
+
+	return ERR_PTR(-EINVAL);
+}
+
 static int set_channel(struct wiphy *wiphy,
 		       struct cfg80211_chan_def *chandef)
 {
-	u32 channelnum = 0;
-	struct wilc_priv *priv = wiphy_priv(wiphy);
-	struct wilc_vif *vif = netdev_priv(priv->dev);
-	int result = 0;
+	struct wilc *wl = wiphy_priv(wiphy);
+	struct wilc_vif *vif;
+	u32 channelnum;
+	int result;
+
+	mutex_lock(&wl->vif_mutex);
+	vif = wilc_get_wl_to_vif(wl);
+	if (IS_ERR(vif)) {
+		mutex_unlock(&wl->vif_mutex);
+		return PTR_ERR(vif);
+	}
 
 	channelnum = ieee80211_frequency_to_channel(chandef->chan->center_freq);
 
-	vif->wilc->op_ch = channelnum;
+	wl->op_ch = channelnum;
 	result = wilc_set_mac_chnl_num(vif, channelnum);
+	if (result)
+		netdev_err(vif->ndev, "Error in setting channel\n");
 
-	if (result != 0)
-		netdev_err(priv->dev, "Error in setting channel\n");
-
+	mutex_unlock(&wl->vif_mutex);
 	return result;
 }
 
 static int scan(struct wiphy *wiphy, struct cfg80211_scan_request *request)
 {
-	struct wilc_priv *priv = wiphy_priv(wiphy);
-	struct wilc_vif *vif = netdev_priv(priv->dev);
+	struct wilc_vif *vif = netdev_priv(request->wdev->netdev);
+	struct wilc_priv *priv = &vif->priv;
 	u32 i;
 	int ret = 0;
 	u8 scan_ch_list[WILC_MAX_NUM_SCANNED_CH];
 	u8 scan_type;
 
 	if (request->n_channels > WILC_MAX_NUM_SCANNED_CH) {
-		netdev_err(priv->dev, "Requested scanned channels over\n");
+		netdev_err(vif->ndev, "Requested scanned channels over\n");
 		return -EINVAL;
 	}
 
@@ -256,8 +275,8 @@ static int scan(struct wiphy *wiphy, struct cfg80211_scan_request *request)
 static int connect(struct wiphy *wiphy, struct net_device *dev,
 		   struct cfg80211_connect_params *sme)
 {
-	struct wilc_priv *priv = wiphy_priv(wiphy);
-	struct wilc_vif *vif = netdev_priv(priv->dev);
+	struct wilc_vif *vif = netdev_priv(dev);
+	struct wilc_priv *priv = &vif->priv;
 	struct host_if_drv *wfi_drv = priv->hif_drv;
 	int ret;
 	u32 i;
@@ -410,8 +429,8 @@ static int connect(struct wiphy *wiphy, struct net_device *dev,
 static int disconnect(struct wiphy *wiphy, struct net_device *dev,
 		      u16 reason_code)
 {
-	struct wilc_priv *priv = wiphy_priv(wiphy);
-	struct wilc_vif *vif = netdev_priv(priv->dev);
+	struct wilc_vif *vif = netdev_priv(dev);
+	struct wilc_priv *priv = &vif->priv;
 	struct wilc *wilc = vif->wilc;
 	int ret;
 
@@ -501,17 +520,17 @@ static int add_key(struct wiphy *wiphy, struct net_device *netdev, u8 key_index,
 
 {
 	int ret = 0, keylen = params->key_len;
-	struct wilc_priv *priv = wiphy_priv(wiphy);
 	const u8 *rx_mic = NULL;
 	const u8 *tx_mic = NULL;
 	u8 mode = WILC_FW_SEC_NO;
 	u8 op_mode;
 	struct wilc_vif *vif = netdev_priv(netdev);
+	struct wilc_priv *priv = &vif->priv;
 
 	switch (params->cipher) {
 	case WLAN_CIPHER_SUITE_WEP40:
 	case WLAN_CIPHER_SUITE_WEP104:
-		if (priv->wdev->iftype == NL80211_IFTYPE_AP) {
+		if (priv->wdev.iftype == NL80211_IFTYPE_AP) {
 			wilc_wfi_cfg_copy_wep_info(priv, key_index, params);
 
 			if (params->cipher == WLAN_CIPHER_SUITE_WEP40)
@@ -538,8 +557,8 @@ static int add_key(struct wiphy *wiphy, struct net_device *netdev, u8 key_index,
 
 	case WLAN_CIPHER_SUITE_TKIP:
 	case WLAN_CIPHER_SUITE_CCMP:
-		if (priv->wdev->iftype == NL80211_IFTYPE_AP ||
-		    priv->wdev->iftype == NL80211_IFTYPE_P2P_GO) {
+		if (priv->wdev.iftype == NL80211_IFTYPE_AP ||
+		    priv->wdev.iftype == NL80211_IFTYPE_P2P_GO) {
 			struct wilc_wfi_key *key;
 
 			ret = wilc_wfi_cfg_allocate_wpa_entry(priv, key_index);
@@ -611,9 +630,9 @@ static int del_key(struct wiphy *wiphy, struct net_device *netdev,
 		   bool pairwise,
 		   const u8 *mac_addr)
 {
-	struct wilc_priv *priv = wiphy_priv(wiphy);
+	struct wilc *wl = wiphy_priv(wiphy);
 	struct wilc_vif *vif = netdev_priv(netdev);
-	struct wilc *wl = vif->wilc;
+	struct wilc_priv *priv = &vif->priv;
 
 	if (netdev == wl->vif[0]->ndev) {
 		if (priv->wilc_gtk[key_index]) {
@@ -650,7 +669,8 @@ static int get_key(struct wiphy *wiphy, struct net_device *netdev, u8 key_index,
 		   bool pairwise, const u8 *mac_addr, void *cookie,
 		   void (*callback)(void *cookie, struct key_params *))
 {
-	struct wilc_priv *priv = wiphy_priv(wiphy);
+	struct wilc_vif *vif = netdev_priv(netdev);
+	struct wilc_priv *priv = &vif->priv;
 	struct  key_params key_params;
 
 	if (!pairwise) {
@@ -675,8 +695,7 @@ static int get_key(struct wiphy *wiphy, struct net_device *netdev, u8 key_index,
 static int set_default_key(struct wiphy *wiphy, struct net_device *netdev,
 			   u8 key_index, bool unicast, bool multicast)
 {
-	struct wilc_priv *priv = wiphy_priv(wiphy);
-	struct wilc_vif *vif = netdev_priv(priv->dev);
+	struct wilc_vif *vif = netdev_priv(netdev);
 
 	wilc_set_wep_default_keyid(vif, key_index);
 
@@ -686,8 +705,8 @@ static int set_default_key(struct wiphy *wiphy, struct net_device *netdev,
 static int get_station(struct wiphy *wiphy, struct net_device *dev,
 		       const u8 *mac, struct station_info *sinfo)
 {
-	struct wilc_priv *priv = wiphy_priv(wiphy);
 	struct wilc_vif *vif = netdev_priv(dev);
+	struct wilc_priv *priv = &vif->priv;
 	u32 i = 0;
 	u32 associatedsta = ~0;
 	u32 inactive_time = 0;
@@ -743,13 +762,35 @@ static int change_bss(struct wiphy *wiphy, struct net_device *dev,
 	return 0;
 }
 
+struct wilc_vif *wilc_get_interface(struct wilc *wl)
+{
+	int i;
+	struct wilc_vif *vif = NULL;
+
+	mutex_lock(&wl->vif_mutex);
+	for (i = 0; i < wl->vif_num; i++) {
+		if (wl->vif[i]) {
+			vif = wl->vif[i];
+			break;
+		}
+	}
+	mutex_unlock(&wl->vif_mutex);
+	return vif;
+}
+
 static int set_wiphy_params(struct wiphy *wiphy, u32 changed)
 {
 	int ret;
 	struct cfg_param_attr cfg_param_val;
-	struct wilc_priv *priv = wiphy_priv(wiphy);
-	struct wilc_vif *vif = netdev_priv(priv->dev);
+	struct wilc *wl = wiphy_priv(wiphy);
+	struct wilc_vif *vif;
+	struct wilc_priv *priv;
 
+	vif = wilc_get_interface(wl);
+	if (!vif)
+		return -EINVAL;
+
+	priv = &vif->priv;
 	cfg_param_val.flag = 0;
 
 	if (changed & WIPHY_PARAM_RETRY_SHORT) {
@@ -804,8 +845,8 @@ static int set_wiphy_params(struct wiphy *wiphy, u32 changed)
 static int set_pmksa(struct wiphy *wiphy, struct net_device *netdev,
 		     struct cfg80211_pmksa *pmksa)
 {
-	struct wilc_priv *priv = wiphy_priv(wiphy);
-	struct wilc_vif *vif = netdev_priv(priv->dev);
+	struct wilc_vif *vif = netdev_priv(netdev);
+	struct wilc_priv *priv = &vif->priv;
 	u32 i;
 	int ret = 0;
 	u8 flag = 0;
@@ -840,7 +881,8 @@ static int del_pmksa(struct wiphy *wiphy, struct net_device *netdev,
 {
 	u32 i;
 	int ret = 0;
-	struct wilc_priv *priv = wiphy_priv(wiphy);
+	struct wilc_vif *vif = netdev_priv(netdev);
+	struct wilc_priv *priv = &vif->priv;
 
 	for (i = 0; i < priv->pmkid_list.numpmkid; i++)	{
 		if (!memcmp(pmksa->bssid, priv->pmkid_list.pmkidlist[i].bssid,
@@ -870,9 +912,9 @@ static int del_pmksa(struct wiphy *wiphy, struct net_device *netdev,
 
 static int flush_pmksa(struct wiphy *wiphy, struct net_device *netdev)
 {
-	struct wilc_priv *priv = wiphy_priv(wiphy);
+	struct wilc_vif *vif = netdev_priv(netdev);
 
-	memset(&priv->pmkid_list, 0, sizeof(struct wilc_pmkid_attr));
+	memset(&vif->priv.pmkid_list, 0, sizeof(struct wilc_pmkid_attr));
 
 	return 0;
 }
@@ -987,12 +1029,11 @@ static void wilc_wfi_cfg_parse_rx_vendor_spec(struct wilc_priv *priv, u8 *buff,
 	}
 }
 
-void wilc_wfi_p2p_rx(struct net_device *dev, u8 *buff, u32 size)
+void wilc_wfi_p2p_rx(struct wilc_vif *vif, u8 *buff, u32 size)
 {
-	struct wilc_priv *priv = wiphy_priv(dev->ieee80211_ptr->wiphy);
-	struct host_if_drv *wfi_drv = priv->hif_drv;
-	struct wilc_vif *vif = netdev_priv(dev);
 	struct wilc *wl = vif->wilc;
+	struct wilc_priv *priv = &vif->priv;
+	struct host_if_drv *wfi_drv = priv->hif_drv;
 	u32 header, pkt_offset;
 	s32 freq;
 	__le16 fc;
@@ -1008,8 +1049,8 @@ void wilc_wfi_p2p_rx(struct net_device *dev, u8 *buff, u32 size)
 		    pkt_offset & IS_MGMT_STATUS_SUCCES)
 			ack = true;
 
-		cfg80211_mgmt_tx_status(priv->wdev, priv->tx_cookie, buff, size,
-					ack, GFP_KERNEL);
+		cfg80211_mgmt_tx_status(&priv->wdev, priv->tx_cookie, buff,
+					size, ack, GFP_KERNEL);
 		return;
 	}
 
@@ -1017,13 +1058,13 @@ void wilc_wfi_p2p_rx(struct net_device *dev, u8 *buff, u32 size)
 
 	fc = ((struct ieee80211_hdr *)buff)->frame_control;
 	if (!ieee80211_is_action(fc)) {
-		cfg80211_rx_mgmt(priv->wdev, freq, 0, buff, size, 0);
+		cfg80211_rx_mgmt(&priv->wdev, freq, 0, buff, size, 0);
 		return;
 	}
 
 	if (priv->cfg_scanning &&
 	    time_after_eq(jiffies, (unsigned long)wfi_drv->p2p_timeout)) {
-		netdev_dbg(dev, "Receiving action wrong ch\n");
+		netdev_dbg(vif->ndev, "Receiving action wrong ch\n");
 		return;
 	}
 	if (buff[ACTION_CAT_ID] == PUB_ACTION_ATTR_ID) {
@@ -1046,14 +1087,14 @@ void wilc_wfi_p2p_rx(struct net_device *dev, u8 *buff, u32 size)
 			break;
 
 		default:
-			netdev_dbg(dev,
+			netdev_dbg(vif->ndev,
 				   "%s: Not handled action frame type:%x\n",
 				   __func__, buff[ACTION_SUBTYPE_ID]);
 			break;
 		}
 	}
 
-	cfg80211_rx_mgmt(priv->wdev, freq, 0, buff, size, 0);
+	cfg80211_rx_mgmt(&priv->wdev, freq, 0, buff, size, 0);
 }
 
 static void wilc_wfi_mgmt_tx_complete(void *priv, int status)
@@ -1066,7 +1107,8 @@ static void wilc_wfi_mgmt_tx_complete(void *priv, int status)
 
 static void wilc_wfi_remain_on_channel_expired(void *data, u64 cookie)
 {
-	struct wilc_priv *priv = data;
+	struct wilc_vif *vif = data;
+	struct wilc_priv *priv = &vif->priv;
 	struct wilc_wfi_p2p_listen_params *params = &priv->remain_on_ch_params;
 
 	if (cookie != params->listen_cookie)
@@ -1074,7 +1116,7 @@ static void wilc_wfi_remain_on_channel_expired(void *data, u64 cookie)
 
 	priv->p2p_listen_state = false;
 
-	cfg80211_remain_on_channel_expired(priv->wdev, params->listen_cookie,
+	cfg80211_remain_on_channel_expired(&priv->wdev, params->listen_cookie,
 					   params->listen_ch, GFP_KERNEL);
 }
 
@@ -1084,8 +1126,8 @@ static int remain_on_channel(struct wiphy *wiphy,
 			     unsigned int duration, u64 *cookie)
 {
 	int ret = 0;
-	struct wilc_priv *priv = wiphy_priv(wiphy);
-	struct wilc_vif *vif = netdev_priv(priv->dev);
+	struct wilc_vif *vif = netdev_priv(wdev->netdev);
+	struct wilc_priv *priv = &vif->priv;
 	u64 id;
 
 	if (wdev->iftype == NL80211_IFTYPE_AP) {
@@ -1099,7 +1141,7 @@ static int remain_on_channel(struct wiphy *wiphy,
 
 	ret = wilc_remain_on_channel(vif, id, duration, chan->hw_value,
 				     wilc_wfi_remain_on_channel_expired,
-				     (void *)priv);
+				     (void *)vif);
 	if (ret)
 		return ret;
 
@@ -1122,8 +1164,8 @@ static int cancel_remain_on_channel(struct wiphy *wiphy,
 				    struct wireless_dev *wdev,
 				    u64 cookie)
 {
-	struct wilc_priv *priv = wiphy_priv(wiphy);
-	struct wilc_vif *vif = netdev_priv(priv->dev);
+	struct wilc_vif *vif = netdev_priv(wdev->netdev);
+	struct wilc_priv *priv = &vif->priv;
 
 	if (cookie != priv->remain_on_ch_params.listen_cookie)
 		return -ENOENT;
@@ -1193,9 +1235,9 @@ static int mgmt_tx(struct wiphy *wiphy,
 	size_t len = params->len;
 	const struct ieee80211_mgmt *mgmt;
 	struct wilc_p2p_mgmt_data *mgmt_tx;
-	struct wilc_priv *priv = wiphy_priv(wiphy);
-	struct host_if_drv *wfi_drv = priv->hif_drv;
 	struct wilc_vif *vif = netdev_priv(wdev->netdev);
+	struct wilc_priv *priv = &vif->priv;
+	struct host_if_drv *wfi_drv = priv->hif_drv;
 	u32 buf_len = len + sizeof(p2p_vendor_spec) +
 			sizeof(priv->p2p.local_random);
 	int ret = 0;
@@ -1279,7 +1321,8 @@ static int mgmt_tx_cancel_wait(struct wiphy *wiphy,
 			       struct wireless_dev *wdev,
 			       u64 cookie)
 {
-	struct wilc_priv *priv = wiphy_priv(wiphy);
+	struct wilc_vif *vif = netdev_priv(wdev->netdev);
+	struct wilc_priv *priv = &vif->priv;
 	struct host_if_drv *wfi_drv = priv->hif_drv;
 
 	wfi_drv->p2p_timeout = jiffies;
@@ -1289,7 +1332,7 @@ static int mgmt_tx_cancel_wait(struct wiphy *wiphy,
 
 		params = &priv->remain_on_ch_params;
 
-		cfg80211_remain_on_channel_expired(priv->wdev,
+		cfg80211_remain_on_channel_expired(wdev,
 						   params->listen_cookie,
 						   params->listen_ch,
 						   GFP_KERNEL);
@@ -1301,9 +1344,8 @@ static int mgmt_tx_cancel_wait(struct wiphy *wiphy,
 void wilc_mgmt_frame_register(struct wiphy *wiphy, struct wireless_dev *wdev,
 			      u16 frame_type, bool reg)
 {
-	struct wilc_priv *priv = wiphy_priv(wiphy);
-	struct wilc_vif *vif = netdev_priv(priv->wdev->netdev);
-	struct wilc *wl = vif->wilc;
+	struct wilc *wl = wiphy_priv(wiphy);
+	struct wilc_vif *vif = netdev_priv(wdev->netdev);
 
 	if (!frame_type)
 		return;
@@ -1337,8 +1379,7 @@ static int set_cqm_rssi_config(struct wiphy *wiphy, struct net_device *dev,
 static int dump_station(struct wiphy *wiphy, struct net_device *dev,
 			int idx, u8 *mac, struct station_info *sinfo)
 {
-	struct wilc_priv *priv = wiphy_priv(wiphy);
-	struct wilc_vif *vif = netdev_priv(priv->dev);
+	struct wilc_vif *vif = netdev_priv(dev);
 	int ret;
 
 	if (idx != 0)
@@ -1350,15 +1391,15 @@ static int dump_station(struct wiphy *wiphy, struct net_device *dev,
 	if (ret)
 		return ret;
 
-	memcpy(mac, priv->associated_bss, ETH_ALEN);
+	memcpy(mac, vif->priv.associated_bss, ETH_ALEN);
 	return 0;
 }
 
 static int set_power_mgmt(struct wiphy *wiphy, struct net_device *dev,
 			  bool enabled, int timeout)
 {
-	struct wilc_priv *priv = wiphy_priv(wiphy);
-	struct wilc_vif *vif = netdev_priv(priv->dev);
+	struct wilc_vif *vif = netdev_priv(dev);
+	struct wilc_priv *priv = &vif->priv;
 
 	if (!priv->hif_drv)
 		return -EIO;
@@ -1373,9 +1414,9 @@ static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev,
 			       enum nl80211_iftype type,
 			       struct vif_params *params)
 {
-	struct wilc_priv *priv = wiphy_priv(wiphy);
+	struct wilc *wl = wiphy_priv(wiphy);
 	struct wilc_vif *vif = netdev_priv(dev);
-	struct wilc *wl = vif->wilc;
+	struct wilc_priv *priv = &vif->priv;
 
 	priv->p2p.local_random = 0x01;
 	priv->p2p.recv_random = 0x00;
@@ -1387,8 +1428,10 @@ static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev,
 	case NL80211_IFTYPE_STATION:
 		vif->connecting = false;
 		dev->ieee80211_ptr->iftype = type;
-		priv->wdev->iftype = type;
+		priv->wdev.iftype = type;
 		vif->monitor_flag = 0;
+		if (vif->iftype == WILC_AP_MODE || vif->iftype == WILC_GO_MODE)
+			wilc_wfi_deinit_mon_interface(wl, true);
 		vif->iftype = WILC_STATION_MODE;
 		wilc_set_operation_mode(vif, WILC_STATION_MODE);
 
@@ -1402,7 +1445,7 @@ static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev,
 	case NL80211_IFTYPE_P2P_CLIENT:
 		vif->connecting = false;
 		dev->ieee80211_ptr->iftype = type;
-		priv->wdev->iftype = type;
+		priv->wdev.iftype = type;
 		vif->monitor_flag = 0;
 		vif->iftype = WILC_CLIENT_MODE;
 		wilc_set_operation_mode(vif, WILC_STATION_MODE);
@@ -1414,7 +1457,7 @@ static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev,
 	case NL80211_IFTYPE_AP:
 		wl->enable_ps = false;
 		dev->ieee80211_ptr->iftype = type;
-		priv->wdev->iftype = type;
+		priv->wdev.iftype = type;
 		vif->iftype = WILC_AP_MODE;
 
 		if (wl->initialized) {
@@ -1431,7 +1474,7 @@ static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev,
 			  jiffies + msecs_to_jiffies(WILC_IP_TIMEOUT_MS));
 		wilc_set_operation_mode(vif, WILC_AP_MODE);
 		dev->ieee80211_ptr->iftype = type;
-		priv->wdev->iftype = type;
+		priv->wdev.iftype = type;
 		vif->iftype = WILC_GO_MODE;
 
 		wl->enable_ps = false;
@@ -1450,14 +1493,13 @@ static int start_ap(struct wiphy *wiphy, struct net_device *dev,
 		    struct cfg80211_ap_settings *settings)
 {
 	struct wilc_vif *vif = netdev_priv(dev);
-	struct wilc *wl = vif->wilc;
 	int ret;
 
 	ret = set_channel(wiphy, &settings->chandef);
 	if (ret != 0)
 		netdev_err(dev, "Error in setting channel\n");
 
-	wilc_wlan_set_bssid(dev, wl->vif[vif->idx]->src_addr, WILC_AP_MODE);
+	wilc_wlan_set_bssid(dev, vif->src_addr, WILC_AP_MODE);
 	wilc_set_power_mgmt(vif, 0, 0);
 
 	return wilc_add_beacon(vif, settings->beacon_interval,
@@ -1467,8 +1509,7 @@ static int start_ap(struct wiphy *wiphy, struct net_device *dev,
 static int change_beacon(struct wiphy *wiphy, struct net_device *dev,
 			 struct cfg80211_beacon_data *beacon)
 {
-	struct wilc_priv *priv = wiphy_priv(wiphy);
-	struct wilc_vif *vif = netdev_priv(priv->dev);
+	struct wilc_vif *vif = netdev_priv(dev);
 
 	return wilc_add_beacon(vif, 0, 0, beacon);
 }
@@ -1476,8 +1517,7 @@ static int change_beacon(struct wiphy *wiphy, struct net_device *dev,
 static int stop_ap(struct wiphy *wiphy, struct net_device *dev)
 {
 	int ret;
-	struct wilc_priv *priv = wiphy_priv(wiphy);
-	struct wilc_vif *vif = netdev_priv(priv->dev);
+	struct wilc_vif *vif = netdev_priv(dev);
 
 	wilc_wlan_set_bssid(dev, NULL, WILC_AP_MODE);
 
@@ -1493,8 +1533,8 @@ static int add_station(struct wiphy *wiphy, struct net_device *dev,
 		       const u8 *mac, struct station_parameters *params)
 {
 	int ret = 0;
-	struct wilc_priv *priv = wiphy_priv(wiphy);
 	struct wilc_vif *vif = netdev_priv(dev);
+	struct wilc_priv *priv = &vif->priv;
 
 	if (vif->iftype == WILC_AP_MODE || vif->iftype == WILC_GO_MODE) {
 		memcpy(priv->assoc_stainfo.sta_associated_bss[params->aid], mac,
@@ -1513,8 +1553,8 @@ static int del_station(struct wiphy *wiphy, struct net_device *dev,
 {
 	const u8 *mac = params->mac;
 	int ret = 0;
-	struct wilc_priv *priv = wiphy_priv(wiphy);
 	struct wilc_vif *vif = netdev_priv(dev);
+	struct wilc_priv *priv = &vif->priv;
 	struct sta_info *info;
 
 	if (!(vif->iftype == WILC_AP_MODE || vif->iftype == WILC_GO_MODE))
@@ -1545,60 +1585,158 @@ static int change_station(struct wiphy *wiphy, struct net_device *dev,
 	return ret;
 }
 
+static int wilc_get_vif_from_type(struct wilc *wl, int type)
+{
+	int i;
+
+	mutex_lock(&wl->vif_mutex);
+	for (i = 0; i < wl->vif_num; i++) {
+		if (wl->vif[i]->iftype == type) {
+			mutex_unlock(&wl->vif_mutex);
+			return i;
+		}
+	}
+	mutex_unlock(&wl->vif_mutex);
+
+	return -EINVAL;
+}
+
 static struct wireless_dev *add_virtual_intf(struct wiphy *wiphy,
 					     const char *name,
 					     unsigned char name_assign_type,
 					     enum nl80211_iftype type,
 					     struct vif_params *params)
 {
-	struct wilc_priv *priv = wiphy_priv(wiphy);
-	struct wilc_vif *vif = netdev_priv(priv->wdev->netdev);
-	struct net_device *new_ifc;
+	struct wilc *wl = wiphy_priv(wiphy);
+	struct wilc_vif *vif;
+	struct wireless_dev *wdev;
+	int iftype;
+	int ret;
 
 	if (type == NL80211_IFTYPE_MONITOR) {
-		new_ifc = wilc_wfi_init_mon_interface(vif->wilc, name,
-						      vif->ndev);
-		if (new_ifc) {
-			vif = netdev_priv(priv->wdev->netdev);
-			vif->monitor_flag = 1;
+		struct net_device *ndev;
+		int ap_index = wilc_get_vif_from_type(wl, WILC_AP_MODE);
+
+		if (ap_index < 0) {
+			ap_index = wilc_get_vif_from_type(wl, WILC_GO_MODE);
+			if (ap_index < 0)
+				goto validate_interface;
 		}
+
+		vif  = wl->vif[ap_index];
+		if (vif->monitor_flag)
+			goto validate_interface;
+
+		ndev = wilc_wfi_init_mon_interface(wl, name, vif->ndev);
+		if (ndev)
+			vif->monitor_flag = 1;
+		else
+			return ERR_PTR(-EINVAL);
+
+		wdev = &vif->priv.wdev;
+		return wdev;
+	}
+
+validate_interface:
+	mutex_lock(&wl->vif_mutex);
+	if (wl->vif_num == WILC_NUM_CONCURRENT_IFC) {
+		pr_err("Reached maximum number of interface\n");
+		ret = -EINVAL;
+		goto out_err;
+	}
+
+	switch (type) {
+	case NL80211_IFTYPE_STATION:
+		iftype = WILC_STATION_MODE;
+		break;
+	case NL80211_IFTYPE_AP:
+		iftype = WILC_AP_MODE;
+		break;
+	default:
+		ret = -EOPNOTSUPP;
+		goto out_err;
+	}
+
+	vif = wilc_netdev_ifc_init(wl, name, iftype, type, true);
+	if (IS_ERR(vif)) {
+		ret = PTR_ERR(vif);
+		goto out_err;
 	}
-	return priv->wdev;
+
+	mutex_unlock(&wl->vif_mutex);
+
+	return &vif->priv.wdev;
+
+out_err:
+	mutex_unlock(&wl->vif_mutex);
+	return ERR_PTR(ret);
 }
 
 static int del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev)
 {
+	struct wilc *wl = wiphy_priv(wiphy);
+	struct wilc_vif *vif;
+	int i;
+
+	if (wdev->iftype == NL80211_IFTYPE_AP ||
+	    wdev->iftype == NL80211_IFTYPE_P2P_GO)
+		wilc_wfi_deinit_mon_interface(wl, true);
+	vif = netdev_priv(wdev->netdev);
+	cfg80211_stop_iface(wiphy, wdev, GFP_KERNEL);
+	unregister_netdevice(vif->ndev);
+	vif->monitor_flag = 0;
+
+	mutex_lock(&wl->vif_mutex);
+	wilc_set_wfi_drv_handler(vif, 0, 0, 0);
+	for (i = vif->idx; i < wl->vif_num ; i++) {
+		if ((i + 1) >= wl->vif_num) {
+			wl->vif[i] = NULL;
+		} else {
+			vif = wl->vif[i + 1];
+			vif->ifc_id = i;
+			vif->idx = i;
+			wl->vif[i] = vif;
+			wilc_set_wfi_drv_handler(vif, wilc_get_vif_idx(vif),
+						 vif->iftype, vif->ifc_id);
+		}
+	}
+	wl->vif_num--;
+	mutex_unlock(&wl->vif_mutex);
+
 	return 0;
 }
 
 static int wilc_suspend(struct wiphy *wiphy, struct cfg80211_wowlan *wow)
 {
-	struct wilc_priv *priv = wiphy_priv(wiphy);
-	struct wilc_vif *vif = netdev_priv(priv->dev);
+	struct wilc *wl = wiphy_priv(wiphy);
 
-	if (!wow && wilc_wlan_get_num_conn_ifcs(vif->wilc))
-		vif->wilc->suspend_event = true;
+	if (!wow && wilc_wlan_get_num_conn_ifcs(wl))
+		wl->suspend_event = true;
 	else
-		vif->wilc->suspend_event = false;
+		wl->suspend_event = false;
 
 	return 0;
 }
 
 static int wilc_resume(struct wiphy *wiphy)
 {
-	struct wilc_priv *priv = wiphy_priv(wiphy);
-	struct wilc_vif *vif = netdev_priv(priv->dev);
-
-	netdev_info(vif->ndev, "cfg resume\n");
 	return 0;
 }
 
 static void wilc_set_wakeup(struct wiphy *wiphy, bool enabled)
 {
-	struct wilc_priv *priv = wiphy_priv(wiphy);
-	struct wilc_vif *vif = netdev_priv(priv->dev);
+	struct wilc *wl = wiphy_priv(wiphy);
+	struct wilc_vif *vif;
+
+	mutex_lock(&wl->vif_mutex);
+	vif = wilc_get_wl_to_vif(wl);
+	if (IS_ERR(vif)) {
+		mutex_unlock(&wl->vif_mutex);
+		return;
+	}
 
 	netdev_info(vif->ndev, "cfg set wake up = %d\n", enabled);
+	mutex_unlock(&wl->vif_mutex);
 }
 
 static int set_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev,
@@ -1606,8 +1744,7 @@ static int set_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev,
 {
 	int ret;
 	s32 tx_power = MBM_TO_DBM(mbm);
-	struct wilc_priv *priv = wiphy_priv(wiphy);
-	struct wilc_vif *vif = netdev_priv(priv->dev);
+	struct wilc_vif *vif = netdev_priv(wdev->netdev);
 
 	if (tx_power < 0)
 		tx_power = 0;
@@ -1624,8 +1761,7 @@ static int get_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev,
 			int *dbm)
 {
 	int ret;
-	struct wilc_priv *priv = wiphy_priv(wiphy);
-	struct wilc_vif *vif = netdev_priv(priv->dev);
+	struct wilc_vif *vif = netdev_priv(wdev->netdev);
 	struct wilc *wl = vif->wilc;
 
 	/* If firmware is not started, return. */
@@ -1682,98 +1818,137 @@ static const struct cfg80211_ops wilc_cfg80211_ops = {
 
 };
 
-static struct wireless_dev *wilc_wfi_cfg_alloc(void)
+static void wlan_init_locks(struct wilc *wl)
 {
-	struct wireless_dev *wdev;
+	mutex_init(&wl->hif_cs);
+	mutex_init(&wl->rxq_cs);
+	mutex_init(&wl->cfg_cmd_lock);
+	mutex_init(&wl->vif_mutex);
+
+	spin_lock_init(&wl->txq_spinlock);
+	mutex_init(&wl->txq_add_to_head_cs);
+
+	init_completion(&wl->txq_event);
+	init_completion(&wl->cfg_event);
+	init_completion(&wl->sync_event);
+	init_completion(&wl->txq_thread_started);
+}
 
-	wdev = kzalloc(sizeof(*wdev), GFP_KERNEL);
-	if (!wdev)
-		goto out;
+int wilc_cfg80211_init(struct wilc **wilc, struct device *dev, int io_type,
+		       const struct wilc_hif_func *ops)
+{
+	struct wilc *wl;
+	struct wilc_vif *vif;
+	int ret;
 
-	wdev->wiphy = wiphy_new(&wilc_cfg80211_ops, sizeof(struct wilc_priv));
-	if (!wdev->wiphy)
-		goto free_mem;
+	wl = wilc_create_wiphy(dev);
+	if (!wl)
+		return -EINVAL;
 
-	return wdev;
+	ret = wilc_wlan_cfg_init(wl);
+	if (ret)
+		goto free_wl;
+
+	*wilc = wl;
+	wl->io_type = io_type;
+	wl->hif_func = ops;
+	wl->enable_ps = false;
+	wl->chip_ps_state = WILC_CHIP_WAKEDUP;
+	INIT_LIST_HEAD(&wl->txq_head.list);
+	INIT_LIST_HEAD(&wl->rxq_head.list);
+
+	wl->hif_workqueue = create_singlethread_workqueue("WILC_wq");
+	if (!wl->hif_workqueue) {
+		ret = -ENOMEM;
+		goto free_cfg;
+	}
+	vif = wilc_netdev_ifc_init(wl, "wlan%d", WILC_STATION_MODE,
+				   NL80211_IFTYPE_STATION, false);
+	if (IS_ERR(vif)) {
+		ret = PTR_ERR(vif);
+		goto free_hq;
+	}
 
-free_mem:
-	kfree(wdev);
-out:
-	return NULL;
+	wlan_init_locks(wl);
+
+	return 0;
+
+free_hq:
+	destroy_workqueue(wl->hif_workqueue);
+
+free_cfg:
+	wilc_wlan_cfg_deinit(wl);
+
+free_wl:
+	wiphy_unregister(wl->wiphy);
+	wiphy_free(wl->wiphy);
+	return ret;
 }
+EXPORT_SYMBOL_GPL(wilc_cfg80211_init);
 
-struct wireless_dev *wilc_create_wiphy(struct net_device *net,
-				       struct device *dev)
+struct wilc *wilc_create_wiphy(struct device *dev)
 {
-	struct wilc_priv *priv;
-	struct wireless_dev *wdev;
+	struct wiphy *wiphy;
+	struct wilc *wl;
 	int ret;
 
-	wdev = wilc_wfi_cfg_alloc();
-	if (!wdev) {
-		netdev_err(net, "wiphy new allocate failed\n");
+	wiphy = wiphy_new(&wilc_cfg80211_ops, sizeof(*wl));
+	if (!wiphy)
 		return NULL;
-	}
 
-	priv = wdev_priv(wdev);
-	priv->wdev = wdev;
+	wl = wiphy_priv(wiphy);
 
-	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);
+	memcpy(wl->bitrates, wilc_bitrates, sizeof(wilc_bitrates));
+	memcpy(wl->channels, wilc_2ghz_channels, sizeof(wilc_2ghz_channels));
+	wl->band.bitrates = wl->bitrates;
+	wl->band.n_bitrates = ARRAY_SIZE(wl->bitrates);
+	wl->band.channels = wl->channels;
+	wl->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;
+	wl->band.ht_cap.ht_supported = 1;
+	wl->band.ht_cap.cap |= (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT);
+	wl->band.ht_cap.mcs.rx_mask[0] = 0xff;
+	wl->band.ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_8K;
+	wl->band.ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_NONE;
 
-	wdev->wiphy->bands[NL80211_BAND_2GHZ] = &priv->band;
+	wiphy->bands[NL80211_BAND_2GHZ] = &wl->band;
 
-	wdev->wiphy->max_scan_ssids = WILC_MAX_NUM_PROBED_SSID;
+	wiphy->max_scan_ssids = WILC_MAX_NUM_PROBED_SSID;
 #ifdef CONFIG_PM
-	wdev->wiphy->wowlan = &wowlan_support;
+	wiphy->wowlan = &wowlan_support;
 #endif
-	wdev->wiphy->max_num_pmkids = WILC_MAX_NUM_PMKIDS;
-	wdev->wiphy->max_scan_ie_len = 1000;
-	wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
-	memcpy(priv->cipher_suites, wilc_cipher_suites,
+	wiphy->max_num_pmkids = WILC_MAX_NUM_PMKIDS;
+	wiphy->max_scan_ie_len = 1000;
+	wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
+	memcpy(wl->cipher_suites, wilc_cipher_suites,
 	       sizeof(wilc_cipher_suites));
-	wdev->wiphy->cipher_suites = priv->cipher_suites;
-	wdev->wiphy->n_cipher_suites = ARRAY_SIZE(wilc_cipher_suites);
-	wdev->wiphy->mgmt_stypes = wilc_wfi_cfg80211_mgmt_types;
-
-	wdev->wiphy->max_remain_on_channel_duration = 500;
-	wdev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
-					BIT(NL80211_IFTYPE_AP) |
-					BIT(NL80211_IFTYPE_MONITOR) |
-					BIT(NL80211_IFTYPE_P2P_GO) |
-					BIT(NL80211_IFTYPE_P2P_CLIENT);
-	wdev->wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
-	wdev->iftype = NL80211_IFTYPE_STATION;
-
-	set_wiphy_dev(wdev->wiphy, dev);
-
-	ret = wiphy_register(wdev->wiphy);
+	wiphy->cipher_suites = wl->cipher_suites;
+	wiphy->n_cipher_suites = ARRAY_SIZE(wilc_cipher_suites);
+	wiphy->mgmt_stypes = wilc_wfi_cfg80211_mgmt_types;
+
+	wiphy->max_remain_on_channel_duration = 500;
+	wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
+				BIT(NL80211_IFTYPE_AP) |
+				BIT(NL80211_IFTYPE_MONITOR) |
+				BIT(NL80211_IFTYPE_P2P_GO) |
+				BIT(NL80211_IFTYPE_P2P_CLIENT);
+	wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
+
+	set_wiphy_dev(wiphy, dev);
+	wl->wiphy = wiphy;
+	ret = wiphy_register(wiphy);
 	if (ret) {
-		netdev_err(net, "Cannot register wiphy device\n");
-		wiphy_free(wdev->wiphy);
-		kfree(wdev);
+		wiphy_free(wiphy);
 		return NULL;
 	}
-
-	priv->dev = net;
-	return wdev;
+	return wl;
 }
 
 int wilc_init_host_int(struct net_device *net)
 {
 	int ret;
-	struct wilc_priv *priv = wdev_priv(net->ieee80211_ptr);
-	struct wilc_vif *vif = netdev_priv(priv->dev);
+	struct wilc_vif *vif = netdev_priv(net);
+	struct wilc_priv *priv = &vif->priv;
 
 	timer_setup(&vif->during_ip_timer, clear_during_ip, 0);
 
@@ -1790,8 +1965,8 @@ int wilc_init_host_int(struct net_device *net)
 void wilc_deinit_host_int(struct net_device *net)
 {
 	int ret;
-	struct wilc_priv *priv = wdev_priv(net->ieee80211_ptr);
-	struct wilc_vif *vif = netdev_priv(priv->dev);
+	struct wilc_vif *vif = netdev_priv(net);
+	struct wilc_priv *priv = &vif->priv;
 
 	priv->p2p_listen_state = false;
 
@@ -1804,19 +1979,3 @@ void wilc_deinit_host_int(struct net_device *net)
 		netdev_err(net, "Error while deinitializing host interface\n");
 }
 
-void wilc_free_wiphy(struct net_device *net)
-{
-	if (!net)
-		return;
-
-	if (!net->ieee80211_ptr)
-		return;
-
-	if (!net->ieee80211_ptr->wiphy)
-		return;
-
-	wiphy_unregister(net->ieee80211_ptr->wiphy);
-
-	wiphy_free(net->ieee80211_ptr->wiphy);
-	kfree(net->ieee80211_ptr);
-}
diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.h b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.h
index 31dfa1f..234faaa 100644
--- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.h
+++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.h
@@ -8,17 +8,20 @@
 #define NM_WFI_CFGOPERATIONS
 #include "wilc_wfi_netdevice.h"
 
-struct wireless_dev *wilc_create_wiphy(struct net_device *net,
-				       struct device *dev);
-void wilc_free_wiphy(struct net_device *net);
+struct wiphy *wilc_cfg_alloc(void);
+int wilc_cfg80211_init(struct wilc **wilc, struct device *dev, int io_type,
+		       const struct wilc_hif_func *ops);
+struct wilc *wilc_create_wiphy(struct device *dev);
 void wilc_deinit_host_int(struct net_device *net);
 int wilc_init_host_int(struct net_device *net);
 void wilc_wfi_monitor_rx(struct net_device *mon_dev, u8 *buff, u32 size);
-void wilc_wfi_deinit_mon_interface(struct wilc *wl);
+struct wilc_vif *wilc_netdev_interface(struct wilc *wl, const char *name,
+				       enum nl80211_iftype type);
+void wilc_wfi_deinit_mon_interface(struct wilc *wl, bool rtnl_locked);
 struct net_device *wilc_wfi_init_mon_interface(struct wilc *wl,
 					       const char *name,
 					       struct net_device *real_dev);
 void wilc_mgmt_frame_register(struct wiphy *wiphy, struct wireless_dev *wdev,
 			      u16 frame_type, bool reg);
-
+struct wilc_vif *wilc_get_interface(struct wilc *wl);
 #endif
diff --git a/drivers/staging/wilc1000/wilc_wfi_netdevice.h b/drivers/staging/wilc1000/wilc_wfi_netdevice.h
index df00762..fca3380 100644
--- a/drivers/staging/wilc1000/wilc_wfi_netdevice.h
+++ b/drivers/staging/wilc1000/wilc_wfi_netdevice.h
@@ -129,7 +129,7 @@ static struct ieee80211_rate wilc_bitrates[] = {
 };
 
 struct wilc_priv {
-	struct wireless_dev *wdev;
+	struct wireless_dev wdev;
 	struct cfg80211_scan_request *scan_req;
 
 	struct wilc_wfi_p2p_listen_params remain_on_ch_params;
@@ -156,10 +156,6 @@ struct wilc_priv {
 	int scanned_cnt;
 	struct wilc_p2p_var p2p;
 
-	struct ieee80211_channel channels[ARRAY_SIZE(wilc_2ghz_channels)];
-	struct ieee80211_rate bitrates[ARRAY_SIZE(wilc_bitrates)];
-	struct ieee80211_supported_band band;
-	u32 cipher_suites[ARRAY_SIZE(wilc_cipher_suites)];
 	u64 inc_roc_cookie;
 };
 
@@ -214,9 +210,11 @@ struct wilc_vif {
 	struct rf_info periodic_stat;
 	struct tcp_ack_filter ack_filter;
 	bool connecting;
+	struct wilc_priv priv;
 };
 
 struct wilc {
+	struct wiphy *wiphy;
 	const struct wilc_hif_func *hif_func;
 	int io_type;
 	s8 mac_status;
@@ -226,6 +224,8 @@ struct wilc {
 	int close;
 	u8 vif_num;
 	struct wilc_vif *vif[WILC_NUM_CONCURRENT_IFC];
+	/*protect vif list*/
+	struct mutex vif_mutex;
 	u8 open_ifcs;
 	/*protect head of transmit queue*/
 	struct mutex txq_add_to_head_cs;
@@ -275,6 +275,10 @@ struct wilc {
 	struct mutex deinit_lock;
 	u8 sta_ch;
 	u8 op_ch;
+	struct ieee80211_channel channels[ARRAY_SIZE(wilc_2ghz_channels)];
+	struct ieee80211_rate bitrates[ARRAY_SIZE(wilc_bitrates)];
+	struct ieee80211_supported_band band;
+	u32 cipher_suites[ARRAY_SIZE(wilc_cipher_suites)];
 };
 
 struct wilc_wfi_mon_priv {
@@ -284,9 +288,9 @@ struct wilc_wfi_mon_priv {
 void wilc_frmw_to_host(struct wilc *wilc, u8 *buff, u32 size, u32 pkt_offset);
 void wilc_mac_indicate(struct wilc *wilc);
 void wilc_netdev_cleanup(struct wilc *wilc);
-int wilc_netdev_init(struct wilc **wilc, struct device *dev, int io_type,
-		     const struct wilc_hif_func *ops);
 void wilc_wfi_mgmt_rx(struct wilc *wilc, u8 *buff, u32 size);
 void wilc_wlan_set_bssid(struct net_device *wilc_netdev, u8 *bssid, u8 mode);
-
+struct wilc_vif *wilc_netdev_ifc_init(struct wilc *wl, const char *name,
+				      int vif_type, enum nl80211_iftype type,
+				      bool rtnl_locked);
 #endif
diff --git a/drivers/staging/wilc1000/wilc_wlan.c b/drivers/staging/wilc1000/wilc_wlan.c
index dcd7285..bd2ffc3 100644
--- a/drivers/staging/wilc1000/wilc_wlan.c
+++ b/drivers/staging/wilc1000/wilc_wlan.c
@@ -6,7 +6,7 @@
 
 #include <linux/if_ether.h>
 #include <linux/ip.h>
-#include "wilc_wfi_netdevice.h"
+#include "wilc_wfi_cfgoperations.h"
 #include "wilc_wlan_cfg.h"
 
 static inline bool is_wilc1000(u32 id)
@@ -267,6 +267,7 @@ static int wilc_wlan_txq_add_cfg_pkt(struct wilc_vif *vif, u8 *buffer,
 	tqe->tx_complete_func = NULL;
 	tqe->priv = NULL;
 	tqe->ack_idx = NOT_TCP_ACK;
+	tqe->vif = vif;
 
 	wilc_wlan_txq_add_to_head(vif, tqe);
 
@@ -295,6 +296,7 @@ int wilc_wlan_txq_add_net_pkt(struct net_device *dev, void *priv, u8 *buffer,
 	tqe->buffer_size = buffer_size;
 	tqe->tx_complete_func = tx_complete_fn;
 	tqe->priv = priv;
+	tqe->vif = vif;
 
 	tqe->ack_idx = NOT_TCP_ACK;
 	if (vif->ack_filter.enabled)
@@ -326,6 +328,7 @@ int wilc_wlan_txq_add_mgmt_pkt(struct net_device *dev, void *priv, u8 *buffer,
 	tqe->tx_complete_func = tx_complete_fn;
 	tqe->priv = priv;
 	tqe->ack_idx = NOT_TCP_ACK;
+	tqe->vif = vif;
 	wilc_wlan_txq_add_to_tail(dev, tqe);
 	return 1;
 }
@@ -482,7 +485,7 @@ void host_sleep_notify(struct wilc *wilc)
 }
 EXPORT_SYMBOL_GPL(host_sleep_notify);
 
-int wilc_wlan_handle_txq(struct net_device *dev, u32 *txq_count)
+int wilc_wlan_handle_txq(struct wilc *wilc, u32 *txq_count)
 {
 	int i, entries = 0;
 	u32 sum;
@@ -494,17 +497,20 @@ int wilc_wlan_handle_txq(struct net_device *dev, u32 *txq_count)
 	int counter;
 	int timeout;
 	u32 vmm_table[WILC_VMM_TBL_SIZE];
-	struct wilc_vif *vif = netdev_priv(dev);
-	struct wilc *wilc = vif->wilc;
 	const struct wilc_hif_func *func;
 	u8 *txb = wilc->tx_buffer;
+	struct net_device *dev;
+	struct wilc_vif *vif;
 
 	if (wilc->quit)
 		goto out;
 
 	mutex_lock(&wilc->txq_add_to_head_cs);
-	wilc_wlan_txq_filter_dup_tcp_ack(dev);
 	tqe = wilc_wlan_txq_get_first(wilc);
+	if (!tqe)
+		goto out;
+	dev = tqe->vif->ndev;
+	wilc_wlan_txq_filter_dup_tcp_ack(dev);
 	i = 0;
 	sum = 0;
 	do {
@@ -629,6 +635,7 @@ int wilc_wlan_handle_txq(struct net_device *dev, u32 *txq_count)
 		if (!tqe)
 			break;
 
+		vif = tqe->vif;
 		if (vmm_table[i] == 0)
 			break;
 
@@ -648,8 +655,7 @@ int wilc_wlan_handle_txq(struct net_device *dev, u32 *txq_count)
 		if (tqe->type == WILC_CFG_PKT) {
 			buffer_offset = ETH_CONFIG_PKT_HDR_OFFSET;
 		} else if (tqe->type == WILC_NET_PKT) {
-			bssid = ((struct tx_complete_data *)(tqe->priv))->bssid;
-
+			bssid = tqe->vif->bssid;
 			buffer_offset = ETH_ETHERNET_HDR_OFFSET;
 			memcpy(&txb[offset + 8], bssid, 6);
 		} else {
diff --git a/drivers/staging/wilc1000/wilc_wlan.h b/drivers/staging/wilc1000/wilc_wlan.h
index 1a27f62..3e54a56 100644
--- a/drivers/staging/wilc1000/wilc_wlan.h
+++ b/drivers/staging/wilc1000/wilc_wlan.h
@@ -216,6 +216,7 @@ struct txq_entry_t {
 	int buffer_size;
 	void *priv;
 	int status;
+	struct wilc_vif *vif;
 	void (*tx_complete_func)(void *priv, int status);
 };
 
@@ -253,7 +254,6 @@ struct wilc_hif_func {
 struct tx_complete_data {
 	int size;
 	void *buff;
-	u8 *bssid;
 	struct sk_buff *skb;
 };
 
@@ -284,7 +284,7 @@ int wilc_wlan_stop(struct wilc *wilc);
 int wilc_wlan_txq_add_net_pkt(struct net_device *dev, void *priv, u8 *buffer,
 			      u32 buffer_size,
 			      void (*tx_complete_fn)(void *, int));
-int wilc_wlan_handle_txq(struct net_device *dev, u32 *txq_count);
+int wilc_wlan_handle_txq(struct wilc *wl, u32 *txq_count);
 void wilc_handle_isr(struct wilc *wilc);
 void wilc_wlan_cleanup(struct net_device *dev);
 int wilc_wlan_cfg_set(struct wilc_vif *vif, int start, u16 wid, u8 *buffer,
@@ -301,7 +301,7 @@ void wilc_enable_tcp_ack_filter(struct wilc_vif *vif, bool value);
 int wilc_wlan_get_num_conn_ifcs(struct wilc *wilc);
 netdev_tx_t wilc_mac_xmit(struct sk_buff *skb, struct net_device *dev);
 
-void wilc_wfi_p2p_rx(struct net_device *dev, u8 *buff, u32 size);
+void wilc_wfi_p2p_rx(struct wilc_vif *vif, u8 *buff, u32 size);
 void host_wakeup_notify(struct wilc *wilc);
 void host_sleep_notify(struct wilc *wilc);
 void chip_allow_sleep(struct wilc *wilc);
-- 
2.7.4


^ permalink raw reply related

* [PATCH 2/8] staging: wilc1000: fix error path cleanup in wilc_wlan_initialize()
From: Ajay.Kathat @ 2019-06-26 12:40 UTC (permalink / raw)
  To: linux-wireless
  Cc: devel, gregkh, Adham.Abozaeid, johannes, Ajay.Kathat, stable
In-Reply-To: <1561552810-8933-1-git-send-email-ajay.kathat@microchip.com>

From: Ajay Singh <ajay.kathat@microchip.com>

For the error path in wilc_wlan_initialize(), the resources are not
cleanup in the correct order. Reverted the previous changes and use the
correct order to free during error condition.

Fixes: b46d68825c2d ("staging: wilc1000: remove COMPLEMENT_BOOT")
Cc: <stable@vger.kernel.org>
Signed-off-by: Ajay Singh <ajay.kathat@microchip.com>
---
 drivers/staging/wilc1000/wilc_netdev.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/staging/wilc1000/wilc_netdev.c b/drivers/staging/wilc1000/wilc_netdev.c
index c4efec2..0e0a4ee 100644
--- a/drivers/staging/wilc1000/wilc_netdev.c
+++ b/drivers/staging/wilc1000/wilc_netdev.c
@@ -530,17 +530,17 @@ static int wilc_wlan_initialize(struct net_device *dev, struct wilc_vif *vif)
 			goto fail_locks;
 		}
 
-		if (wl->gpio_irq && init_irq(dev)) {
-			ret = -EIO;
-			goto fail_locks;
-		}
-
 		ret = wlan_initialize_threads(dev);
 		if (ret < 0) {
 			ret = -EIO;
 			goto fail_wilc_wlan;
 		}
 
+		if (wl->gpio_irq && init_irq(dev)) {
+			ret = -EIO;
+			goto fail_threads;
+		}
+
 		if (!wl->dev_irq_num &&
 		    wl->hif_func->enable_interrupt &&
 		    wl->hif_func->enable_interrupt(wl)) {
@@ -596,7 +596,7 @@ static int wilc_wlan_initialize(struct net_device *dev, struct wilc_vif *vif)
 fail_irq_init:
 		if (wl->dev_irq_num)
 			deinit_irq(dev);
-
+fail_threads:
 		wlan_deinitialize_threads(dev);
 fail_wilc_wlan:
 		wilc_wlan_cleanup(dev);
-- 
2.7.4


^ permalink raw reply related

* [PATCH 1/8] staging: wilc1000: handle p2p operations in caller context
From: Ajay.Kathat @ 2019-06-26 12:40 UTC (permalink / raw)
  To: linux-wireless; +Cc: devel, gregkh, Adham.Abozaeid, johannes, Ajay.Kathat
In-Reply-To: <1561552810-8933-1-git-send-email-ajay.kathat@microchip.com>

From: Ajay Singh <ajay.kathat@microchip.com>

Moved the handling of p2p related operation in the caller context instead
of using workqueue.

Signed-off-by: Ajay Singh <ajay.kathat@microchip.com>
---
 drivers/staging/wilc1000/host_interface.c | 46 ++++++++++++-------------------
 1 file changed, 17 insertions(+), 29 deletions(-)

diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c
index 13c991535..b505990 100644
--- a/drivers/staging/wilc1000/host_interface.c
+++ b/drivers/staging/wilc1000/host_interface.c
@@ -965,11 +965,8 @@ static int handle_remain_on_chan(struct wilc_vif *vif,
 	return 0;
 }
 
-static void handle_listen_state_expired(struct work_struct *work)
+static int wilc_handle_roc_expired(struct wilc_vif *vif, u64 cookie)
 {
-	struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
-	struct wilc_vif *vif = msg->vif;
-	struct wilc_remain_ch *hif_remain_ch = &msg->body.remain_on_ch;
 	u8 remain_on_chan_flag;
 	struct wid wid;
 	int result;
@@ -981,10 +978,10 @@ static void handle_listen_state_expired(struct work_struct *work)
 		wid.id = WID_REMAIN_ON_CHAN;
 		wid.type = WID_STR;
 		wid.size = 2;
-		wid.val = kmalloc(wid.size, GFP_KERNEL);
 
+		wid.val = kmalloc(wid.size, GFP_KERNEL);
 		if (!wid.val)
-			goto free_msg;
+			return -ENOMEM;
 
 		wid.val[0] = remain_on_chan_flag;
 		wid.val[1] = WILC_FALSE_FRMWR_CHANNEL;
@@ -994,18 +991,25 @@ static void handle_listen_state_expired(struct work_struct *work)
 		kfree(wid.val);
 		if (result != 0) {
 			netdev_err(vif->ndev, "Failed to set remain channel\n");
-			goto free_msg;
+			return -EINVAL;
 		}
 
 		if (hif_drv->remain_on_ch.expired) {
 			hif_drv->remain_on_ch.expired(hif_drv->remain_on_ch.arg,
-						      hif_remain_ch->cookie);
+						      cookie);
 		}
 	} else {
 		netdev_dbg(vif->ndev, "Not in listen state\n");
 	}
 
-free_msg:
+	return 0;
+}
+
+static void wilc_handle_listen_state_expired(struct work_struct *work)
+{
+	struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
+
+	wilc_handle_roc_expired(msg->vif, msg->body.remain_on_ch.cookie);
 	kfree(msg);
 }
 
@@ -1019,7 +1023,7 @@ static void listen_timer_cb(struct timer_list *t)
 
 	del_timer(&vif->hif_drv->remain_on_ch_timer);
 
-	msg = wilc_alloc_work(vif, handle_listen_state_expired, false);
+	msg = wilc_alloc_work(vif, wilc_handle_listen_state_expired, false);
 	if (IS_ERR(msg))
 		return;
 
@@ -1841,30 +1845,14 @@ int wilc_remain_on_channel(struct wilc_vif *vif, u64 cookie,
 
 int wilc_listen_state_expired(struct wilc_vif *vif, u64 cookie)
 {
-	int result;
-	struct host_if_msg *msg;
-	struct host_if_drv *hif_drv = vif->hif_drv;
-
-	if (!hif_drv) {
+	if (!vif->hif_drv) {
 		netdev_err(vif->ndev, "%s: hif driver is NULL", __func__);
 		return -EFAULT;
 	}
 
-	del_timer(&hif_drv->remain_on_ch_timer);
-
-	msg = wilc_alloc_work(vif, handle_listen_state_expired, false);
-	if (IS_ERR(msg))
-		return PTR_ERR(msg);
-
-	msg->body.remain_on_ch.cookie = cookie;
-
-	result = wilc_enqueue_work(msg);
-	if (result) {
-		netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__);
-		kfree(msg);
-	}
+	del_timer(&vif->hif_drv->remain_on_ch_timer);
 
-	return result;
+	return wilc_handle_roc_expired(vif, cookie);
 }
 
 void wilc_frame_register(struct wilc_vif *vif, u16 frame_type, bool reg)
-- 
2.7.4


^ permalink raw reply related

* [PATCH 0/8] staging: wilc1000: dynamically add/delete interfaces & cleanup fixes
From: Ajay.Kathat @ 2019-06-26 12:40 UTC (permalink / raw)
  To: linux-wireless; +Cc: devel, gregkh, Adham.Abozaeid, johannes, Ajay.Kathat

From: Ajay Singh <ajay.kathat@microchip.com>

This patch series mainly contains the changes to support the
add/delete of wlan0/p2p0 network interfaces dynamically. The driver
will be loaded with a single default interface and later new interfaces
can be added or removed.
Also included few cleanup patches in this series.

Ajay Singh (8):
  staging: wilc1000: handle p2p operations in caller context
  staging: wilc1000: fix error path cleanup in wilc_wlan_initialize()
  staging: wilc1000: added support to dynamically add/remove interfaces
  staging: wilc1000: remove use of driver_handler_id & ifc_id
  staging: wilc1000: remove unnecessary loop to traverse vif interfaces
  staging: wilc1000: remove use of 'src_addr' element in 'wilc_vif'
    struct
  staging: wilc1000: remove extra argument passing to
    wilc_send_config_pkt()
  staging: wilc1000: rename 'host_interface' source and header

 drivers/staging/wilc1000/Makefile                  |   2 +-
 .../wilc1000/{host_interface.c => wilc_hif.c}      | 170 +++----
 .../wilc1000/{host_interface.h => wilc_hif.h}      |   1 -
 drivers/staging/wilc1000/wilc_mon.c                |   9 +-
 drivers/staging/wilc1000/wilc_netdev.c             | 293 ++++-------
 drivers/staging/wilc1000/wilc_sdio.c               |   7 +-
 drivers/staging/wilc1000/wilc_spi.c                |   3 +-
 drivers/staging/wilc1000/wilc_wfi_cfgoperations.c  | 536 +++++++++++++--------
 drivers/staging/wilc1000/wilc_wfi_cfgoperations.h  |  13 +-
 drivers/staging/wilc1000/wilc_wfi_netdevice.h      |  24 +-
 drivers/staging/wilc1000/wilc_wlan.c               |  23 +-
 drivers/staging/wilc1000/wilc_wlan.h               |   8 +-
 12 files changed, 560 insertions(+), 529 deletions(-)
 rename drivers/staging/wilc1000/{host_interface.c => wilc_hif.c} (91%)
 rename drivers/staging/wilc1000/{host_interface.h => wilc_hif.h} (99%)

-- 
2.7.4


^ permalink raw reply

* [PATCH] libertas: Fix a double free in if_spi_c2h_data()
From: Dan Carpenter @ 2019-06-26 10:09 UTC (permalink / raw)
  To: Kalle Valo, Philip Rakity
  Cc: Allison Randal, Lubomir Rintel, libertas-dev, linux-wireless,
	kernel-janitors

The lbs_process_rxed_packet() frees the skb.  It didn't originally, but
we fixed it in commit f54930f36311 ("libertas: don't leak skb on receive
error").

Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
---
 drivers/net/wireless/marvell/libertas/if_spi.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/wireless/marvell/libertas/if_spi.c b/drivers/net/wireless/marvell/libertas/if_spi.c
index 27067e79e83f..e38f02d1f2e4 100644
--- a/drivers/net/wireless/marvell/libertas/if_spi.c
+++ b/drivers/net/wireless/marvell/libertas/if_spi.c
@@ -772,7 +772,7 @@ static int if_spi_c2h_data(struct if_spi_card *card)
 	/* pass the SKB to libertas */
 	err = lbs_process_rxed_packet(card->priv, skb);
 	if (err)
-		goto free_skb;
+		goto out;  /* lbs_process_rxed_packet() frees skb */
 
 	/* success */
 	goto out;
-- 
2.20.1


^ permalink raw reply related

* Re: [RFC 0/5] add hw dfs pattern detector support to mt7615 driver
From: Ryder Lee @ 2019-06-26  9:46 UTC (permalink / raw)
  To: Lorenzo Bianconi; +Cc: nbd, lorenzo.bianconi, linux-wireless, royluo, yf.luo
In-Reply-To: <cover.1561499275.git.lorenzo@kernel.org>

On Wed, 2019-06-26 at 00:01 +0200, Lorenzo Bianconi wrote:
> Introduce radar pattern detection support to mt7615 driver. Please note I have
> tested this series just through the radar pattern test knob added to debugfs
> and not through I real radar signal generator.
> CSA is currently missing (I am currently working on it).
> This series is based on 'mt76: move nl80211_dfs_regions in mt76_dev data
> structure' https://patchwork.kernel.org/patch/11010723/
> 
> Lorenzo Bianconi (5):
>   mt76: mt7615: introduce mt7615_regd_notifier
>   mt76: mt7615: add hw dfs pattern detector support
>   mt76: mt7615: do not perform txcalibration before cac is complited
>   mt76: mt7615: unlock dfs bands
>   mt76: mt7615: add radar pattern test knob to debugfs
> 
>  .../wireless/mediatek/mt76/mt7615/Makefile    |   3 +-
>  .../wireless/mediatek/mt76/mt7615/debugfs.c   |  38 ++++++
>  .../net/wireless/mediatek/mt76/mt7615/dma.c   |   2 +-
>  .../net/wireless/mediatek/mt76/mt7615/init.c  |  43 +++++--
>  .../net/wireless/mediatek/mt76/mt7615/mac.c   |  88 +++++++++++++
>  .../net/wireless/mediatek/mt76/mt7615/main.c  |   6 +
>  .../net/wireless/mediatek/mt76/mt7615/mcu.c   | 121 ++++++++++++++++--
>  .../net/wireless/mediatek/mt76/mt7615/mcu.h   |  23 ++++
>  .../wireless/mediatek/mt76/mt7615/mt7615.h    |  55 ++++++++
>  9 files changed, 356 insertions(+), 23 deletions(-)
>  create mode 100644 drivers/net/wireless/mediatek/mt76/mt7615/debugfs.c
> 
For the series
Acked-by: Ryder Lee <ryder.lee@mediatek.com>


^ permalink raw reply

* [PATCH] ath10k: Move non-fatal warn logs to dbg level for SDIO chip
From: Wen Gong @ 2019-06-26  2:29 UTC (permalink / raw)
  To: ath10k; +Cc: linux-wireless

ath10k will receive some message with invalid peer id from firmware.
reason is:
There are incoming frames to MAC hardware that NOT find relative
address search table, then peer id is invalid set by MAC hardware,
it is hardware's logic, so fix it in ath10k will be more convenient.

log:
ath10k_sdio mmc1:0001:1: Got RX ind from invalid peer: 65535

Tested with QCA6174 SDIO with firmware
WLAN.RMH.4.4.1-00007-QCARMSWP-1.

Signed-off-by: Wen Gong <wgong@codeaurora.org>
---
 drivers/net/wireless/ath/ath10k/htt_rx.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c
index a20ea27..14b838f 100644
--- a/drivers/net/wireless/ath/ath10k/htt_rx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
@@ -2082,7 +2082,7 @@ static bool ath10k_htt_rx_proc_rx_ind_hl(struct ath10k_htt *htt,
 	spin_lock_bh(&ar->data_lock);
 	peer = ath10k_peer_find_by_id(ar, peer_id);
 	spin_unlock_bh(&ar->data_lock);
-	if (!peer)
+	if (!peer && peer_id != HTT_INVALID_PEERID)
 		ath10k_warn(ar, "Got RX ind from invalid peer: %u\n", peer_id);
 
 	num_mpdu_ranges = MS(__le32_to_cpu(rx->hdr.info1),
-- 
1.9.1


^ permalink raw reply related

* [PATCH] ath10k: destroy sdio workqueue while remove sdio module
From: Wen Gong @ 2019-06-26  2:25 UTC (permalink / raw)
  To: ath10k; +Cc: linux-wireless

The workqueue need to flush and destory while remove sdio module,
otherwise it will have thread which is not destory after remove
sdio modules.

Tested with QCA6174 SDIO with firmware
WLAN.RMH.4.4.1-00007-QCARMSWP-1.

Signed-off-by: Wen Gong <wgong@codeaurora.org>
---
 drivers/net/wireless/ath/ath10k/sdio.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/net/wireless/ath/ath10k/sdio.c b/drivers/net/wireless/ath/ath10k/sdio.c
index fae56c6..40c3b4b 100644
--- a/drivers/net/wireless/ath/ath10k/sdio.c
+++ b/drivers/net/wireless/ath/ath10k/sdio.c
@@ -2077,6 +2077,9 @@ static void ath10k_sdio_remove(struct sdio_func *func)
 	cancel_work_sync(&ar_sdio->wr_async_work);
 	ath10k_core_unregister(ar);
 	ath10k_core_destroy(ar);
+
+	flush_workqueue(ar_sdio->workqueue);
+	destroy_workqueue(ar_sdio->workqueue);
 }
 
 static const struct sdio_device_id ath10k_sdio_devices[] = {
-- 
1.9.1


^ permalink raw reply related

* Re: [PATCH v4 5/7] lib/hexdump.c: Allow multiple groups to be separated by lines '|'
From: Alastair D'Silva @ 2019-06-26  1:28 UTC (permalink / raw)
  To: Joe Perches
  Cc: Jani Nikula, Joonas Lahtinen, Rodrigo Vivi, David Airlie,
	Daniel Vetter, Dan Carpenter, Karsten Keil, Jassi Brar,
	Tom Lendacky, David S. Miller, Jose Abreu, Kalle Valo,
	Stanislaw Gruszka, Benson Leung, Enric Balletbo i Serra,
	James E.J. Bottomley, Martin K. Petersen, Greg Kroah-Hartman,
	Alexander Viro, Petr Mladek, Sergey Senozhatsky, Steven Rostedt,
	David Laight, Andrew Morton, intel-gfx, dri-devel, linux-kernel,
	netdev, ath10k, linux-wireless, linux-scsi, linux-fbdev, devel,
	linux-fsdevel
In-Reply-To: <c364c36338d385eba60c523828ad8995c792ae4d.camel@perches.com>

On Mon, 2019-06-24 at 22:37 -0700, Joe Perches wrote:
> On Tue, 2019-06-25 at 13:17 +1000, Alastair D'Silva wrote:
> > From: Alastair D'Silva <alastair@d-silva.org>
> > 
> > With the wider display format, it can become hard to identify how
> > many
> > bytes into the line you are looking at.
> > 
> > The patch adds new flags to hex_dump_to_buffer() and
> > print_hex_dump() to
> > print vertical lines to separate every N groups of bytes.
> > 
> > eg.
> > buf:00000000: 454d414e 43415053|4e495f45
> > 00584544  NAMESPAC|E_INDEX.
> > buf:00000010: 00000000 00000002|00000000
> > 00000000  ........|........
> > 
> > Signed-off-by: Alastair D'Silva <alastair@d-silva.org>
> > ---
> >  include/linux/printk.h |  3 +++
> >  lib/hexdump.c          | 59 ++++++++++++++++++++++++++++++++++++
> > ------
> >  2 files changed, 54 insertions(+), 8 deletions(-)
> > 
> > diff --git a/include/linux/printk.h b/include/linux/printk.h
> []
> > @@ -485,6 +485,9 @@ enum {
> >  
> >  #define HEXDUMP_ASCII			BIT(0)
> >  #define HEXDUMP_SUPPRESS_REPEATED	BIT(1)
> > +#define HEXDUMP_2_GRP_LINES		BIT(2)
> > +#define HEXDUMP_4_GRP_LINES		BIT(3)
> > +#define HEXDUMP_8_GRP_LINES		BIT(4)
> 
> These aren't really bits as only one value should be set
> as 8 overrides 4 and 4 overrides 2.

This should be the other way around, as we should be emitting alternate
seperators based on the smallest grouping (2 implies 4 and 8, and 4
implies 8). I'll fix the logic.

I can't come up with a better way to represent these without making the
API more complex, if you have a suggestion, I'm happy to hear it.

> 
> I would also expect this to be a value of 2 in your above
> example, rather than 8.  It's described as groups not bytes.
> 
> The example is showing a what would normally be a space ' '
> separator as a vertical bar '|' every 2nd grouping.
> 

The above example shows a group size of 4 bytes, and
HEXDUMP_2_GRP_LINES set, with 2 groups being 8 bytes.

I'll make that clearer in the commit message.

-- 
Alastair D'Silva           mob: 0423 762 819
skype: alastair_dsilva    
Twitter: @EvilDeece
blog: http://alastair.d-silva.org



^ permalink raw reply

* Re: [PATCH v4 4/7] lib/hexdump.c: Replace ascii bool in hex_dump_to_buffer with flags
From: Alastair D'Silva @ 2019-06-26  1:27 UTC (permalink / raw)
  To: Joe Perches
  Cc: Jani Nikula, Joonas Lahtinen, Rodrigo Vivi, David Airlie,
	Daniel Vetter, Dan Carpenter, Karsten Keil, Jassi Brar,
	Tom Lendacky, David S. Miller, Jose Abreu, Kalle Valo,
	Stanislaw Gruszka, Benson Leung, Enric Balletbo i Serra,
	James E.J. Bottomley, Martin K. Petersen, Greg Kroah-Hartman,
	Alexander Viro, Petr Mladek, Sergey Senozhatsky, Steven Rostedt,
	David Laight, Andrew Morton, intel-gfx, dri-devel, linux-kernel,
	netdev, ath10k, linux-wireless, linux-scsi, linux-fbdev, devel,
	linux-fsdevel
In-Reply-To: <4ba3b835fb3675ea685390903a082bf8b7f9e955.camel@perches.com>

On Mon, 2019-06-24 at 22:19 -0700, Joe Perches wrote:
> On Tue, 2019-06-25 at 15:06 +1000, Alastair D'Silva wrote:
> > The change actions Jani's suggestion:
> > https://lkml.org/lkml/2019/6/20/343
> 
> I suggest not changing any of the existing uses of
> hex_dump_to_buffer and only use hex_dump_to_buffer_ext
> when necessary for your extended use cases.
> 
> 

I disagree, adding a wrapper for the benefit of avoiding touching a
handful of call sites that are easily amended would be adding technical
debt.

-- 
Alastair D'Silva           mob: 0423 762 819
skype: alastair_dsilva    
Twitter: @EvilDeece
blog: http://alastair.d-silva.org



^ permalink raw reply

* Re: [PATCH v4 4/7] lib/hexdump.c: Replace ascii bool in hex_dump_to_buffer with flags
From: Alastair D'Silva @ 2019-06-26  1:27 UTC (permalink / raw)
  To: Joe Perches
  Cc: Jani Nikula, Joonas Lahtinen, Rodrigo Vivi, David Airlie,
	Daniel Vetter, Dan Carpenter, Karsten Keil, Jassi Brar,
	Tom Lendacky, David S. Miller, Jose Abreu, Kalle Valo,
	Stanislaw Gruszka, Benson Leung, Enric Balletbo i Serra,
	James E.J. Bottomley, Martin K. Petersen, Greg Kroah-Hartman,
	Alexander Viro, Petr Mladek, Sergey Senozhatsky, Steven Rostedt,
	David Laight, Andrew Morton, intel-gfx, dri-devel, linux-kernel,
	netdev, ath10k, linux-wireless, linux-scsi, linux-fbdev, devel,
	linux-fsdevel
In-Reply-To: <3340b520a57e00a483eae170be97316c8d18c22c.camel@perches.com>

On Mon, 2019-06-24 at 22:01 -0700, Joe Perches wrote:
> On Tue, 2019-06-25 at 13:17 +1000, Alastair D'Silva wrote:
> > From: Alastair D'Silva <alastair@d-silva.org>
> > 
> > In order to support additional features, rename hex_dump_to_buffer
> > to
> > hex_dump_to_buffer_ext, and replace the ascii bool parameter with
> > flags.
> []
> > diff --git a/drivers/gpu/drm/i915/intel_engine_cs.c
> > b/drivers/gpu/drm/i915/intel_engine_cs.c
> []
> > @@ -1338,9 +1338,8 @@ static void hexdump(struct drm_printer *m,
> > const void *buf, size_t len)
> >  		}
> >  
> >  		WARN_ON_ONCE(hex_dump_to_buffer(buf + pos, len - pos,
> > -						rowsize, sizeof(u32),
> > -						line, sizeof(line),
> > -						false) >=
> > sizeof(line));
> > +						rowsize, sizeof(u32),
> > line,
> > +						sizeof(line)) >=
> > sizeof(line));
> 
> Huh?  Why do this?

The ascii parameter was removed from the simple API as per Jani's
suggestion. The remainder was reformatted to avoid exceeding the line
length limits.

> 
> > diff --git a/drivers/isdn/hardware/mISDN/mISDNisar.c
> > b/drivers/isdn/hardware/mISDN/mISDNisar.c
> []
> > @@ -70,8 +70,9 @@ send_mbox(struct isar_hw *isar, u8 his, u8 creg,
> > u8 len, u8 *msg)
> >  			int l = 0;
> >  
> >  			while (l < (int)len) {
> > -				hex_dump_to_buffer(msg + l, len - l,
> > 32, 1,
> > -						   isar->log, 256, 1);
> > +				hex_dump_to_buffer_ext(msg + l, len -
> > l, 32, 1,
> > +						       isar->log, 256,
> > +						       HEXDUMP_ASCII);
> 
> Again, why do any of these?
> 
> The point of the wrapper is to avoid changing these.

Jani made a pretty good point that about half the callers didn't want
an ASCII dump, and presenting a simplified API makes sense.

I would actually put forward that we consider dropping rowsize from the
simplified API too, as most callers use 32, and those that use 16 would
probably be OK with 32.

Your proposal, on the other hand, only makes sense if there were many
callers, and even so, not in the form that you presented, since that
result in a mix of booleans & bitfields that you were critical of.

-- 
Alastair D'Silva           mob: 0423 762 819
skype: alastair_dsilva    
Twitter: @EvilDeece
blog: http://alastair.d-silva.org



^ permalink raw reply

* Re: [PATCH v4 0/7] Hexdump Enhancements
From: Alastair D'Silva @ 2019-06-26  1:02 UTC (permalink / raw)
  To: Joe Perches
  Cc: Jani Nikula, Joonas Lahtinen, Rodrigo Vivi, David Airlie,
	Daniel Vetter, Dan Carpenter, Karsten Keil, Jassi Brar,
	Tom Lendacky, David S. Miller, Jose Abreu, Kalle Valo,
	Stanislaw Gruszka, Benson Leung, Enric Balletbo i Serra,
	James E.J. Bottomley, Martin K. Petersen, Greg Kroah-Hartman,
	Alexander Viro, Petr Mladek, Sergey Senozhatsky, Steven Rostedt,
	David Laight, Andrew Morton, intel-gfx, dri-devel, linux-kernel,
	netdev, ath10k, linux-wireless, linux-scsi, linux-fbdev, devel,
	linux-fsdevel
In-Reply-To: <3ae4c1a4a72f8ee6b75c45adfbe543fc0a7b5da1.camel@perches.com>

On Mon, 2019-06-24 at 22:01 -0700, Joe Perches wrote:
> On Tue, 2019-06-25 at 13:17 +1000, Alastair D'Silva wrote:
> > From: Alastair D'Silva <alastair@d-silva.org>
> > 
> > Apologies for the large CC list, it's a heads up for those
> > responsible
> > for subsystems where a prototype change in generic code causes a
> > change
> > in those subsystems.
> []
> > The default behaviour of hexdump is unchanged, however, the
> > prototype
> > for hex_dump_to_buffer() has changed, and print_hex_dump() has been
> > renamed to print_hex_dump_ext(), with a wrapper replacing it for
> > compatibility with existing code, which would have been too
> > invasive to
> > change.
> 
> I believe this cover letter is misleading.
> 
> The point of the wrapper is to avoid unnecessary changes
> in existing
> code.
> 
> 

The wrapper is for print_hex_dump(), which has many callers.

The changes to existing code are for hex_dump_to_buffer(), which is
called in relatively few places.

-- 
Alastair D'Silva           mob: 0423 762 819
skype: alastair_dsilva    
Twitter: @EvilDeece
blog: http://alastair.d-silva.org



^ permalink raw reply

* Re: [PATCH v4 4/7] lib/hexdump.c: Replace ascii bool in hex_dump_to_buffer with flags
From: kbuild test robot @ 2019-06-25 22:52 UTC (permalink / raw)
  To: Alastair D'Silva
  Cc: kbuild-all, alastair, Jani Nikula, Joonas Lahtinen, Rodrigo Vivi,
	David Airlie, Daniel Vetter, Dan Carpenter, Karsten Keil,
	Jassi Brar, Tom Lendacky, David S. Miller, Jose Abreu, Kalle Valo,
	Stanislaw Gruszka, Benson Leung, Enric Balletbo i Serra,
	James E.J. Bottomley, Martin K. Petersen, Greg Kroah-Hartman,
	Alexander Viro, Petr Mladek, Sergey Senozhatsky, Steven Rostedt,
	David Laight, Andrew Morton, intel-gfx, dri-devel, linux-kernel,
	netdev, ath10k, linux-wireless, linux-scsi, linux-fbdev, devel,
	linux-fsdevel
In-Reply-To: <20190625031726.12173-5-alastair@au1.ibm.com>

Hi Alastair,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on linus/master]
[also build test WARNING on v5.2-rc6 next-20190625]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Alastair-D-Silva/Hexdump-Enhancements/20190625-224046
reproduce:
        # apt-get install sparse
        # sparse version: v0.6.1-rc1-7-g2b96cd8-dirty
        make ARCH=x86_64 allmodconfig
        make C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__'

If you fix the issue, kindly add following tag
Reported-by: kbuild test robot <lkp@intel.com>


sparse warnings: (new ones prefixed by >>)

   sound/soc/intel/skylake/skl-debug.c:191:34: sparse: sparse: incorrect type in argument 1 (different address spaces) @@    expected void [noderef] <asn:2> *to @@    got eref] <asn:2> *to @@
   sound/soc/intel/skylake/skl-debug.c:191:34: sparse:    expected void [noderef] <asn:2> *to
   sound/soc/intel/skylake/skl-debug.c:191:34: sparse:    got unsigned char *
   sound/soc/intel/skylake/skl-debug.c:191:51: sparse: sparse: incorrect type in argument 2 (different address spaces) @@    expected void const *from @@    got void [noderef] <asn:2> void const *from @@
   sound/soc/intel/skylake/skl-debug.c:191:51: sparse:    expected void const *from
   sound/soc/intel/skylake/skl-debug.c:191:51: sparse:    got void [noderef] <asn:2> *[assigned] fw_reg_addr
>> sound/soc/intel/skylake/skl-debug.c:195:35: sparse: sparse: too many arguments for function hex_dump_to_buffer
--
>> drivers/gpu/drm/tinydrm/core/tinydrm-helpers.c:93:27: sparse: sparse: too many arguments for function hex_dump_to_buffer
--
>> sound/soc/sof/xtensa/core.c:125:35: sparse: sparse: too many arguments for function hex_dump_to_buffer

vim +195 sound/soc/intel/skylake/skl-debug.c

d14700a0 Vinod Koul  2017-06-30  170  
bdd0384a Vunny Sodhi 2017-06-30  171  static ssize_t fw_softreg_read(struct file *file, char __user *user_buf,
bdd0384a Vunny Sodhi 2017-06-30  172  			       size_t count, loff_t *ppos)
bdd0384a Vunny Sodhi 2017-06-30  173  {
bdd0384a Vunny Sodhi 2017-06-30  174  	struct skl_debug *d = file->private_data;
bdd0384a Vunny Sodhi 2017-06-30  175  	struct sst_dsp *sst = d->skl->skl_sst->dsp;
bdd0384a Vunny Sodhi 2017-06-30  176  	size_t w0_stat_sz = sst->addr.w0_stat_sz;
bdd0384a Vunny Sodhi 2017-06-30  177  	void __iomem *in_base = sst->mailbox.in_base;
bdd0384a Vunny Sodhi 2017-06-30  178  	void __iomem *fw_reg_addr;
bdd0384a Vunny Sodhi 2017-06-30  179  	unsigned int offset;
bdd0384a Vunny Sodhi 2017-06-30  180  	char *tmp;
bdd0384a Vunny Sodhi 2017-06-30  181  	ssize_t ret = 0;
bdd0384a Vunny Sodhi 2017-06-30  182  
bdd0384a Vunny Sodhi 2017-06-30  183  	tmp = kzalloc(FW_REG_BUF, GFP_KERNEL);
bdd0384a Vunny Sodhi 2017-06-30  184  	if (!tmp)
bdd0384a Vunny Sodhi 2017-06-30  185  		return -ENOMEM;
bdd0384a Vunny Sodhi 2017-06-30  186  
bdd0384a Vunny Sodhi 2017-06-30  187  	fw_reg_addr = in_base - w0_stat_sz;
bdd0384a Vunny Sodhi 2017-06-30  188  	memset(d->fw_read_buff, 0, FW_REG_BUF);
bdd0384a Vunny Sodhi 2017-06-30  189  
bdd0384a Vunny Sodhi 2017-06-30  190  	if (w0_stat_sz > 0)
bdd0384a Vunny Sodhi 2017-06-30 @191  		__iowrite32_copy(d->fw_read_buff, fw_reg_addr, w0_stat_sz >> 2);
bdd0384a Vunny Sodhi 2017-06-30  192  
bdd0384a Vunny Sodhi 2017-06-30  193  	for (offset = 0; offset < FW_REG_SIZE; offset += 16) {
bdd0384a Vunny Sodhi 2017-06-30  194  		ret += snprintf(tmp + ret, FW_REG_BUF - ret, "%#.4x: ", offset);
bdd0384a Vunny Sodhi 2017-06-30 @195  		hex_dump_to_buffer(d->fw_read_buff + offset, 16, 16, 4,
bdd0384a Vunny Sodhi 2017-06-30  196  				   tmp + ret, FW_REG_BUF - ret, 0);
bdd0384a Vunny Sodhi 2017-06-30  197  		ret += strlen(tmp + ret);
bdd0384a Vunny Sodhi 2017-06-30  198  
bdd0384a Vunny Sodhi 2017-06-30  199  		/* print newline for each offset */
bdd0384a Vunny Sodhi 2017-06-30  200  		if (FW_REG_BUF - ret > 0)
bdd0384a Vunny Sodhi 2017-06-30  201  			tmp[ret++] = '\n';
bdd0384a Vunny Sodhi 2017-06-30  202  	}
bdd0384a Vunny Sodhi 2017-06-30  203  
bdd0384a Vunny Sodhi 2017-06-30  204  	ret = simple_read_from_buffer(user_buf, count, ppos, tmp, ret);
bdd0384a Vunny Sodhi 2017-06-30  205  	kfree(tmp);
bdd0384a Vunny Sodhi 2017-06-30  206  
bdd0384a Vunny Sodhi 2017-06-30  207  	return ret;
bdd0384a Vunny Sodhi 2017-06-30  208  }
bdd0384a Vunny Sodhi 2017-06-30  209  

:::::: The code at line 195 was first introduced by commit
:::::: bdd0384a5ada8bb5745e5f29c10a5ba88827efad ASoC: Intel: Skylake: Add support to read firmware registers

:::::: TO: Vunny Sodhi <vunnyx.sodhi@intel.com>
:::::: CC: Mark Brown <broonie@kernel.org>

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

^ permalink raw reply

* Re: iwlwifi module crash
From: b.K.il.h.u+tigbuh @ 2019-06-25 22:17 UTC (permalink / raw)
  To: Balakrishnan Balasubramanian; +Cc: Emmanuel Grumbach, linux-wireless
In-Reply-To: <2221997.PNfK1iNeOp@zadesk>

Maybe we don't have the same issue, but today this one solved it for
me: `rmmod iwlmvm; rmmod iwlwifi; modprobe iwlwifi`. Well, kind of. It
couldn't really connect to any network afterwards, but after another
such dance it was finally back to normal.

The device disappears from iwconfig for me when this happens, so it is
easy to detect and correct with few lines of shell. It can also be
gone from lspci as well. Another alternative would be to set up a
syslog-ng program destination triggered by a patterndb sample matching
the noted failures among the kernel messages.

If it gets stuck without a visible sign, you could watch Inactive time
and tx failures in `iw dev wlan0 station dump` increase sharply in
case of issues. If you need a bit more reliability, it is easy to ping
the AP or gateway every second and refresh the connection in case of
too many consecutive missing replies.

On Mon, Jun 24, 2019 at 11:36 PM Balakrishnan Balasubramanian
<linux-wireless-list@balki.me> wrote:
>
> Thanks for the tip. In my system the path to remove was below:
>
> /sys/devices/pci0000:00/0000:00:1c.2/0000:02:00.0/remove
> Also symlinked here:
> /sys/module/iwlwifi/drivers/pci:iwlwifi/0000:02:00.0/remove
>
> I am now able to restore internet without system restart. Now I need to find a
> way to do this automatically whenever internet goes down.
>
> Thanks,
> Bala
>
> On Sunday, June 23, 2019 5:08:32 AM EDT b.K.il.h.u+tigbuh@gmail.com wrote:
> > devices/ is probably just a symlink. Try to find it manually:
> > find /sys -iname remove
> > lspci
> >
> > The interesting thing is that my iwlwifi card started to do the same
> > thing just recently (some weeks ago). However, I do suspend a lot and
> > it only happens after resuming, but not after every resume (maybe
> > 5-10%). It always came back after restarting except on one day when it
> > needed three restarts, so maybe mine would be more about needing to
> > reseat the card.
> >
> > > On Fri, Jun 14, 2019 at 4:54 AM Balakrishnan Balasubramanian <linux-
> wireless-list@balki.me> wrote:
> > >> The issue occured again today. I tried to restart the module
> > >>
> > >> > echo 1 > /sys/module/iwlwifi/devices/0000\:02\:00.0/remove
> > >>
> > >> There is no folder 'devices'
> > >>
> > >> zadesk% ls /sys/module/iwlwifi
> > >> coresize  drivers  holders  initsize  initstate  notes  parameters
> > >> refcnt
> > >> sections  srcversion  taint  uevent
> > >>
> > >> > echo 1 > /sys/bus/pci/rescan
> > >>
> > >> Attached the error when trying to rescan.
> > >>
> > >> Thanks,
> > >> Bala
>
>
>
>

^ permalink raw reply

* [RFC 5/5] mt76: mt7615: add radar pattern test knob to debugfs
From: Lorenzo Bianconi @ 2019-06-25 22:01 UTC (permalink / raw)
  To: nbd; +Cc: lorenzo.bianconi, linux-wireless, ryder.lee, royluo, yf.luo
In-Reply-To: <cover.1561499275.git.lorenzo@kernel.org>

Introduce mt7615_mcu_rdd_send_pattern routine to trigger a radar pattern
detection. Moreover move debugfs related routines in a dedicated source
file.

Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
 .../wireless/mediatek/mt76/mt7615/Makefile    |  3 +-
 .../wireless/mediatek/mt76/mt7615/debugfs.c   | 38 +++++++++++++++++++
 .../net/wireless/mediatek/mt76/mt7615/init.c  | 13 -------
 .../net/wireless/mediatek/mt76/mt7615/mcu.c   | 31 +++++++++++++++
 .../net/wireless/mediatek/mt76/mt7615/mcu.h   |  1 +
 .../wireless/mediatek/mt76/mt7615/mt7615.h    |  9 +++++
 6 files changed, 81 insertions(+), 14 deletions(-)
 create mode 100644 drivers/net/wireless/mediatek/mt76/mt7615/debugfs.c

diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/Makefile b/drivers/net/wireless/mediatek/mt76/mt7615/Makefile
index 6397552f6ee3..5aaac69849d6 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/Makefile
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/Makefile
@@ -2,4 +2,5 @@
 
 obj-$(CONFIG_MT7615E) += mt7615e.o
 
-mt7615e-y := pci.o init.o dma.o eeprom.o main.o mcu.o mac.o
+mt7615e-y := pci.o init.o dma.o eeprom.o main.o mcu.o mac.o \
+	     debugfs.o
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/debugfs.c b/drivers/net/wireless/mediatek/mt76/mt7615/debugfs.c
new file mode 100644
index 000000000000..e884fad9b7ac
--- /dev/null
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/debugfs.c
@@ -0,0 +1,38 @@
+/* SPDX-License-Identifier: ISC */
+
+#include "mt7615.h"
+
+static int
+mt7615_radar_pattern_set(void *data, u64 val)
+{
+	struct mt7615_dev *dev = data;
+
+	return mt7615_mcu_rdd_send_pattern(dev);
+}
+
+DEFINE_DEBUGFS_ATTRIBUTE(fops_radar_pattern, NULL,
+			 mt7615_radar_pattern_set, "%lld\n");
+
+int mt7615_init_debugfs(struct mt7615_dev *dev)
+{
+	struct dentry *dir;
+
+	dir = mt76_register_debugfs(&dev->mt76);
+	if (!dir)
+		return -ENOMEM;
+
+	debugfs_create_u32("dfs_hw_pattern", 0400, dir, &dev->hw_pattern);
+	/* test pattern knobs */
+	debugfs_create_u8("pattern_len", 0600, dir,
+			  &dev->radar_pattern.n_pulses);
+	debugfs_create_u32("pattern_period", 0600, dir,
+			   &dev->radar_pattern.period);
+	debugfs_create_u16("pulse_width", 0600, dir,
+			   &dev->radar_pattern.width);
+	debugfs_create_u16("pulse_power", 0600, dir,
+			   &dev->radar_pattern.power);
+	debugfs_create_file("radar_trigger", 0200, dir, dev,
+			    &fops_radar_pattern);
+
+	return 0;
+}
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/init.c b/drivers/net/wireless/mediatek/mt76/mt7615/init.c
index 6d336d82cafe..2b9b001a3fc9 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/init.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/init.c
@@ -161,19 +161,6 @@ static const struct ieee80211_iface_combination if_comb[] = {
 	}
 };
 
-static int mt7615_init_debugfs(struct mt7615_dev *dev)
-{
-	struct dentry *dir;
-
-	dir = mt76_register_debugfs(&dev->mt76);
-	if (!dir)
-		return -ENOMEM;
-
-	debugfs_create_u32("dfs_hw_pattern", 0400, dir, &dev->hw_pattern);
-
-	return 0;
-}
-
 static void
 mt7615_init_txpower(struct mt7615_dev *dev,
 		    struct ieee80211_supported_band *sband)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c
index 31bdab1b5df6..a738770439ac 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c
@@ -1277,6 +1277,37 @@ int mt7615_mcu_rdd_cmd(struct mt7615_dev *dev,
 				   &req, sizeof(req), true);
 }
 
+int mt7615_mcu_rdd_send_pattern(struct mt7615_dev *dev)
+{
+	struct {
+		u8 pulse_num;
+		u8 rsv[3];
+		struct {
+			u32 start_time;
+			u16 width;
+			s16 power;
+		} pattern[32];
+	} req = {
+		.pulse_num = dev->radar_pattern.n_pulses,
+	};
+	u32 start_time = ktime_to_ms(ktime_get_boottime());
+	int i;
+
+	if (dev->radar_pattern.n_pulses > ARRAY_SIZE(req.pattern))
+		return -EINVAL;
+
+	/* TODO: add some noise here */
+	for (i = 0; i < dev->radar_pattern.n_pulses; i++) {
+		req.pattern[i].width = dev->radar_pattern.width;
+		req.pattern[i].power = dev->radar_pattern.power;
+		req.pattern[i].start_time = start_time +
+					    i * dev->radar_pattern.period;
+	}
+
+	return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_SET_RDD_PATTERN,
+				   &req, sizeof(req), false);
+}
+
 int mt7615_mcu_set_channel(struct mt7615_dev *dev)
 {
 	struct cfg80211_chan_def *chandef = &dev->mt76.chandef;
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h
index 5fe492189f56..ae14ee380626 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h
@@ -103,6 +103,7 @@ enum {
 	MCU_EXT_CMD_MAC_INIT_CTRL = 0x46,
 	MCU_EXT_CMD_BCN_OFFLOAD = 0x49,
 	MCU_EXT_CMD_SET_RX_PATH = 0x4e,
+	MCU_EXT_CMD_SET_RDD_PATTERN = 0x7d,
 };
 
 enum {
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h
index d113fa30115e..3713db874ef4 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h
@@ -68,6 +68,12 @@ struct mt7615_dev {
 	u32 vif_mask;
 	u32 omac_mask;
 
+	struct {
+		u8 n_pulses;
+		u32 period;
+		u16 width;
+		s16 power;
+	} radar_pattern;
 	u32 hw_pattern;
 	int dfs_state;
 
@@ -177,6 +183,7 @@ int mt7615_mcu_rdd_cmd(struct mt7615_dev *dev,
 		       u8 rx_sel, u8 val);
 int mt7615_dfs_start_radar_detector(struct mt7615_dev *dev);
 int mt7615_dfs_stop_radar_detector(struct mt7615_dev *dev);
+int mt7615_mcu_rdd_send_pattern(struct mt7615_dev *dev);
 
 static inline void mt7615_dfs_check_channel(struct mt7615_dev *dev)
 {
@@ -240,4 +247,6 @@ void mt7615_txp_skb_unmap(struct mt76_dev *dev,
 int mt76_dfs_start_rdd(struct mt7615_dev *dev, bool force);
 int mt7615_dfs_init_radar_detector(struct mt7615_dev *dev);
 
+int mt7615_init_debugfs(struct mt7615_dev *dev);
+
 #endif
-- 
2.21.0


^ permalink raw reply related

* [RFC 4/5] mt76: mt7615: unlock dfs bands
From: Lorenzo Bianconi @ 2019-06-25 22:01 UTC (permalink / raw)
  To: nbd; +Cc: lorenzo.bianconi, linux-wireless, ryder.lee, royluo, yf.luo
In-Reply-To: <cover.1561499275.git.lorenzo@kernel.org>

Unlock dfs channels since now mt7615 driver supports radar detection

Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
 drivers/net/wireless/mediatek/mt76/mt7615/init.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/init.c b/drivers/net/wireless/mediatek/mt76/mt7615/init.c
index 5dc4cced5789..6d336d82cafe 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/init.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/init.c
@@ -152,6 +152,12 @@ static const struct ieee80211_iface_combination if_comb[] = {
 		.max_interfaces = 4,
 		.num_different_channels = 1,
 		.beacon_int_infra_match = true,
+		.radar_detect_widths = BIT(NL80211_CHAN_WIDTH_20_NOHT) |
+				       BIT(NL80211_CHAN_WIDTH_20) |
+				       BIT(NL80211_CHAN_WIDTH_40) |
+				       BIT(NL80211_CHAN_WIDTH_80) |
+				       BIT(NL80211_CHAN_WIDTH_160) |
+				       BIT(NL80211_CHAN_WIDTH_80P80),
 	}
 };
 
-- 
2.21.0


^ permalink raw reply related

* [RFC 3/5] mt76: mt7615: do not perform txcalibration before cac is complited
From: Lorenzo Bianconi @ 2019-06-25 22:01 UTC (permalink / raw)
  To: nbd; +Cc: lorenzo.bianconi, linux-wireless, ryder.lee, royluo, yf.luo
In-Reply-To: <cover.1561499275.git.lorenzo@kernel.org>

Delay channel calibration after Channel Availability Check. Add some
code cleanup to mt7615_mcu_set_channel

Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
 .../net/wireless/mediatek/mt76/mt7615/mcu.c   | 25 +++++++++++--------
 1 file changed, 15 insertions(+), 10 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c
index c0fd0ad805b5..31bdab1b5df6 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c
@@ -1279,7 +1279,8 @@ int mt7615_mcu_rdd_cmd(struct mt7615_dev *dev,
 
 int mt7615_mcu_set_channel(struct mt7615_dev *dev)
 {
-	struct cfg80211_chan_def *chdef = &dev->mt76.chandef;
+	struct cfg80211_chan_def *chandef = &dev->mt76.chandef;
+	int freq1 = chandef->center_freq1, freq2 = chandef->center_freq2;
 	struct {
 		u8 control_chan;
 		u8 center_chan;
@@ -1298,17 +1299,20 @@ int mt7615_mcu_set_channel(struct mt7615_dev *dev)
 		u8 rsv1[3];
 		u8 txpower_sku[53];
 		u8 rsv2[3];
-	} req = {0};
+	} req = {
+		.control_chan = chandef->chan->hw_value,
+		.center_chan = ieee80211_frequency_to_channel(freq1),
+		.tx_streams = (dev->mt76.chainmask >> 8) & 0xf,
+		.rx_streams_mask = dev->mt76.antenna_mask,
+		.center_chan2 = ieee80211_frequency_to_channel(freq2),
+	};
 	int ret;
 
-	req.control_chan = chdef->chan->hw_value;
-	req.center_chan = ieee80211_frequency_to_channel(chdef->center_freq1);
-	req.tx_streams = (dev->mt76.chainmask >> 8) & 0xf;
-	req.rx_streams_mask = dev->mt76.antenna_mask;
-	req.switch_reason = CH_SWITCH_NORMAL;
-	req.band_idx = 0;
-	req.center_chan2 = ieee80211_frequency_to_channel(chdef->center_freq2);
-	req.txpower_drop = 0;
+	if ((chandef->chan->flags & IEEE80211_CHAN_RADAR) &&
+	    chandef->chan->dfs_state != NL80211_DFS_AVAILABLE)
+		req.switch_reason = CH_SWITCH_DFS;
+	else
+		req.switch_reason = CH_SWITCH_NORMAL;
 
 	switch (dev->mt76.chandef.width) {
 	case NL80211_CHAN_WIDTH_40:
@@ -1333,6 +1337,7 @@ int mt7615_mcu_set_channel(struct mt7615_dev *dev)
 	case NL80211_CHAN_WIDTH_20:
 	default:
 		req.bw = CMD_CBW_20MHZ;
+		break;
 	}
 	memset(req.txpower_sku, 0x3f, 49);
 
-- 
2.21.0


^ permalink raw reply related

* [RFC 2/5] mt76: mt7615: add hw dfs pattern detector support
From: Lorenzo Bianconi @ 2019-06-25 22:01 UTC (permalink / raw)
  To: nbd; +Cc: lorenzo.bianconi, linux-wireless, ryder.lee, royluo, yf.luo
In-Reply-To: <cover.1561499275.git.lorenzo@kernel.org>

Add hw radar detection support to mt7615 driver in order to
unlock dfs channels on 5GHz band

Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
 .../net/wireless/mediatek/mt76/mt7615/dma.c   |  2 +-
 .../net/wireless/mediatek/mt76/mt7615/init.c  | 17 ++++
 .../net/wireless/mediatek/mt76/mt7615/mac.c   | 88 +++++++++++++++++++
 .../net/wireless/mediatek/mt76/mt7615/main.c  |  6 ++
 .../net/wireless/mediatek/mt76/mt7615/mcu.c   | 65 ++++++++++++++
 .../net/wireless/mediatek/mt76/mt7615/mcu.h   | 22 +++++
 .../wireless/mediatek/mt76/mt7615/mt7615.h    | 46 ++++++++++
 7 files changed, 245 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/dma.c b/drivers/net/wireless/mediatek/mt76/mt7615/dma.c
index 6a70273d4a69..3fe24d92d4fa 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/dma.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/dma.c
@@ -76,7 +76,7 @@ void mt7615_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
 		mt7615_mac_tx_free(dev, skb);
 		break;
 	case PKT_TYPE_RX_EVENT:
-		mt76_mcu_rx_event(&dev->mt76, skb);
+		mt7615_mcu_rx_event(dev, skb);
 		break;
 	case PKT_TYPE_NORMAL:
 		if (!mt7615_mac_fill_rx(dev, skb)) {
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/init.c b/drivers/net/wireless/mediatek/mt76/mt7615/init.c
index edce96ce79a4..5dc4cced5789 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/init.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/init.c
@@ -163,6 +163,8 @@ static int mt7615_init_debugfs(struct mt7615_dev *dev)
 	if (!dir)
 		return -ENOMEM;
 
+	debugfs_create_u32("dfs_hw_pattern", 0400, dir, &dev->hw_pattern);
+
 	return 0;
 }
 
@@ -214,8 +216,22 @@ mt7615_regd_notifier(struct wiphy *wiphy,
 {
 	struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
 	struct mt7615_dev *dev = hw->priv;
+	struct cfg80211_chan_def *chandef = &dev->mt76.chandef;
+
+	if (request->dfs_region == dev->mt76.region)
+		return;
 
 	dev->mt76.region = request->dfs_region;
+
+	if (!(chandef->chan->flags & IEEE80211_CHAN_RADAR))
+		return;
+
+	mt7615_dfs_stop_radar_detector(dev);
+	if (request->dfs_region == NL80211_DFS_UNSET)
+		mt7615_mcu_rdd_cmd(dev, RDD_CAC_END, MT_HW_RDD0,
+				   MT_RX_SEL0, 0);
+	else
+		mt7615_dfs_start_radar_detector(dev);
 }
 
 int mt7615_register_device(struct mt7615_dev *dev)
@@ -254,6 +270,7 @@ int mt7615_register_device(struct mt7615_dev *dev)
 			IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
 	dev->mt76.chainmask = 0x404;
 	dev->mt76.antenna_mask = 0xf;
+	dev->dfs_state = -1;
 
 	wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
 #ifdef CONFIG_MAC80211_MESH
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c
index d1ae491dd31f..d66c3b18c142 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c
@@ -726,3 +726,91 @@ void mt7615_mac_work(struct work_struct *work)
 	ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mt76.mac_work,
 				     MT7615_WATCHDOG_TIME);
 }
+
+int mt7615_dfs_stop_radar_detector(struct mt7615_dev *dev)
+{
+	struct cfg80211_chan_def *chandef = &dev->mt76.chandef;
+	int err;
+
+	err = mt7615_mcu_rdd_cmd(dev, RDD_STOP, MT_HW_RDD0,
+				 MT_RX_SEL0, 0);
+	if (err < 0)
+		return err;
+
+	if (chandef->width == NL80211_CHAN_WIDTH_160 ||
+	    chandef->width == NL80211_CHAN_WIDTH_80P80)
+		err = mt7615_mcu_rdd_cmd(dev, RDD_STOP, MT_HW_RDD1,
+					 MT_RX_SEL0, 0);
+	return err;
+}
+
+static int mt7615_dfs_start_rdd(struct mt7615_dev *dev, int chain)
+{
+	int err;
+
+	err = mt7615_mcu_rdd_cmd(dev, RDD_START, chain, MT_RX_SEL0, 0);
+	if (err < 0)
+		return err;
+
+	return mt7615_mcu_rdd_cmd(dev, RDD_DET_MODE, chain,
+				  MT_RX_SEL0, 1);
+}
+
+int mt7615_dfs_start_radar_detector(struct mt7615_dev *dev)
+{
+	struct cfg80211_chan_def *chandef = &dev->mt76.chandef;
+	int err;
+
+	/* start CAC */
+	err = mt7615_mcu_rdd_cmd(dev, RDD_CAC_START, MT_HW_RDD0,
+				 MT_RX_SEL0, 0);
+	if (err < 0)
+		return err;
+
+	/* TODO: DBDC support */
+
+	err = mt7615_dfs_start_rdd(dev, MT_HW_RDD0);
+	if (err < 0)
+		return err;
+
+	if (chandef->width == NL80211_CHAN_WIDTH_160 ||
+	    chandef->width == NL80211_CHAN_WIDTH_80P80) {
+		err = mt7615_dfs_start_rdd(dev, MT_HW_RDD1);
+		if (err < 0)
+			return err;
+	}
+
+	return 0;
+}
+
+int mt7615_dfs_init_radar_detector(struct mt7615_dev *dev)
+{
+	struct cfg80211_chan_def *chandef = &dev->mt76.chandef;
+	int err;
+
+	if (dev->mt76.region == NL80211_DFS_UNSET)
+		return 0;
+
+	if (test_bit(MT76_SCANNING, &dev->mt76.state))
+		return 0;
+
+	if (dev->dfs_state == chandef->chan->dfs_state)
+		return 0;
+
+	dev->dfs_state = chandef->chan->dfs_state;
+
+	if (chandef->chan->flags & IEEE80211_CHAN_RADAR) {
+		if (chandef->chan->dfs_state != NL80211_DFS_AVAILABLE)
+			return mt7615_dfs_start_radar_detector(dev);
+		else
+			return mt7615_mcu_rdd_cmd(dev, RDD_CAC_END, MT_HW_RDD0,
+						  MT_RX_SEL0, 0);
+	} else {
+		err = mt7615_mcu_rdd_cmd(dev, RDD_NORMAL_START,
+					 MT_HW_RDD0, MT_RX_SEL0, 0);
+		if (err < 0)
+			return err;
+
+		return mt7615_dfs_stop_radar_detector(dev);
+	}
+}
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/main.c b/drivers/net/wireless/mediatek/mt76/mt7615/main.c
index ea6b2315c6e5..f883bb073897 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/main.c
@@ -137,12 +137,18 @@ static int mt7615_set_channel(struct mt7615_dev *dev)
 	cancel_delayed_work_sync(&dev->mt76.mac_work);
 	set_bit(MT76_RESET, &dev->mt76.state);
 
+	mt7615_dfs_check_channel(dev);
+
 	mt76_set_channel(&dev->mt76);
 
 	ret = mt7615_mcu_set_channel(dev);
 	if (ret)
 		return ret;
 
+	ret = mt7615_dfs_init_radar_detector(dev);
+	if (ret < 0)
+		return ret;
+
 	clear_bit(MT76_RESET, &dev->mt76.state);
 
 	mt76_txq_schedule_all(&dev->mt76);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c
index 248c14e4b28d..c0fd0ad805b5 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c
@@ -159,6 +159,50 @@ mt7615_mcu_msg_send(struct mt76_dev *mdev, int cmd, const void *data,
 	return ret;
 }
 
+static void
+mt7615_mcu_rx_ext_event(struct mt7615_dev *dev, struct sk_buff *skb)
+{
+	struct mt7615_mcu_rxd *rxd = (struct mt7615_mcu_rxd *)skb->data;
+
+	switch (rxd->ext_eid) {
+	case MCU_EXT_EVENT_RDD_REPORT:
+		ieee80211_radar_detected(dev->mt76.hw);
+		dev->hw_pattern++;
+		break;
+	default:
+		break;
+	}
+}
+
+static void
+mt7615_mcu_rx_unsolicited_event(struct mt7615_dev *dev, struct sk_buff *skb)
+{
+	struct mt7615_mcu_rxd *rxd = (struct mt7615_mcu_rxd *)skb->data;
+
+	switch (rxd->eid) {
+	case MCU_EVENT_EXT:
+		mt7615_mcu_rx_ext_event(dev, skb);
+		break;
+	default:
+		break;
+	}
+	dev_kfree_skb(skb);
+}
+
+void mt7615_mcu_rx_event(struct mt7615_dev *dev, struct sk_buff *skb)
+{
+	struct mt7615_mcu_rxd *rxd = (struct mt7615_mcu_rxd *)skb->data;
+
+	if (rxd->ext_eid == MCU_EXT_EVENT_THERMAL_PROTECT ||
+	    rxd->ext_eid == MCU_EXT_EVENT_FW_LOG_2_HOST ||
+	    rxd->ext_eid == MCU_EXT_EVENT_ASSERT_DUMP ||
+	    rxd->ext_eid == MCU_EXT_EVENT_PS_SYNC ||
+	    !rxd->seq)
+		mt7615_mcu_rx_unsolicited_event(dev, skb);
+	else
+		mt76_mcu_rx_event(&dev->mt76, skb);
+}
+
 static int mt7615_mcu_init_download(struct mt7615_dev *dev, u32 addr,
 				    u32 len, u32 mode)
 {
@@ -1212,6 +1256,27 @@ int mt7615_mcu_set_tx_power(struct mt7615_dev *dev)
 	return ret;
 }
 
+int mt7615_mcu_rdd_cmd(struct mt7615_dev *dev,
+		       enum mt7615_rdd_cmd cmd, u8 index,
+		       u8 rx_sel, u8 val)
+{
+	struct {
+		u8 ctrl;
+		u8 rdd_idx;
+		u8 rdd_rx_sel;
+		u8 val;
+		u8 rsv[4];
+	} req = {
+		.ctrl = cmd,
+		.rdd_idx = index,
+		.rdd_rx_sel = rx_sel,
+		.val = val,
+	};
+
+	return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_SET_RDD_CTRL,
+				   &req, sizeof(req), true);
+}
+
 int mt7615_mcu_set_channel(struct mt7615_dev *dev)
 {
 	struct cfg80211_chan_def *chdef = &dev->mt76.chandef;
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h
index f8b51ad25220..5fe492189f56 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h
@@ -23,6 +23,27 @@ struct mt7615_mcu_txd {
 	u32 reserved[5];
 } __packed __aligned(4);
 
+/* event table */
+enum {
+	MCU_EVENT_TARGET_ADDRESS_LEN = 0x01,
+	MCU_EVENT_FW_START = 0x01,
+	MCU_EVENT_GENERIC = 0x01,
+	MCU_EVENT_ACCESS_REG = 0x02,
+	MCU_EVENT_MT_PATCH_SEM = 0x04,
+	MCU_EVENT_CH_PRIVILEGE = 0x18,
+	MCU_EVENT_EXT = 0xed,
+	MCU_EVENT_RESTART_DL = 0xef,
+};
+
+/* ext event table */
+enum {
+	MCU_EXT_EVENT_PS_SYNC = 0x5,
+	MCU_EXT_EVENT_FW_LOG_2_HOST = 0x13,
+	MCU_EXT_EVENT_THERMAL_PROTECT = 0x22,
+	MCU_EXT_EVENT_ASSERT_DUMP = 0x23,
+	MCU_EXT_EVENT_RDD_REPORT = 0x3a,
+};
+
 struct mt7615_mcu_rxd {
 	__le32 rxd[4];
 
@@ -77,6 +98,7 @@ enum {
 	MCU_EXT_CMD_EDCA_UPDATE = 0x27,
 	MCU_EXT_CMD_DEV_INFO_UPDATE = 0x2A,
 	MCU_EXT_CMD_WTBL_UPDATE = 0x32,
+	MCU_EXT_CMD_SET_RDD_CTRL = 0x3a,
 	MCU_EXT_CMD_PROTECT_CTRL = 0x3e,
 	MCU_EXT_CMD_MAC_INIT_CTRL = 0x46,
 	MCU_EXT_CMD_BCN_OFFLOAD = 0x49,
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h
index f02ffcffe637..d113fa30115e 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h
@@ -68,6 +68,9 @@ struct mt7615_dev {
 	u32 vif_mask;
 	u32 omac_mask;
 
+	u32 hw_pattern;
+	int dfs_state;
+
 	spinlock_t token_lock;
 	struct idr token;
 };
@@ -97,6 +100,30 @@ enum {
 	EXT_BSSID_END
 };
 
+enum {
+	MT_HW_RDD0,
+	MT_HW_RDD1,
+};
+
+enum {
+	MT_RX_SEL0,
+	MT_RX_SEL1,
+};
+
+enum mt7615_rdd_cmd {
+	RDD_STOP,
+	RDD_START,
+	RDD_DET_MODE,
+	RDD_DET_STOP,
+	RDD_CAC_START,
+	RDD_CAC_END,
+	RDD_NORMAL_START,
+	RDD_DISABLE_DFS_CAL,
+	RDD_PULSE_DBG,
+	RDD_READ_PULSE,
+	RDD_RESUME_BF,
+};
+
 extern const struct ieee80211_ops mt7615_ops;
 extern struct pci_driver mt7615_pci_driver;
 
@@ -144,6 +171,23 @@ int mt7615_mcu_set_rx_ba(struct mt7615_dev *dev,
 			 bool add);
 int mt7615_mcu_set_ht_cap(struct mt7615_dev *dev, struct ieee80211_vif *vif,
 			  struct ieee80211_sta *sta);
+void mt7615_mcu_rx_event(struct mt7615_dev *dev, struct sk_buff *skb);
+int mt7615_mcu_rdd_cmd(struct mt7615_dev *dev,
+		       enum mt7615_rdd_cmd cmd, u8 index,
+		       u8 rx_sel, u8 val);
+int mt7615_dfs_start_radar_detector(struct mt7615_dev *dev);
+int mt7615_dfs_stop_radar_detector(struct mt7615_dev *dev);
+
+static inline void mt7615_dfs_check_channel(struct mt7615_dev *dev)
+{
+	enum nl80211_chan_width width = dev->mt76.chandef.width;
+	u32 freq = dev->mt76.chandef.chan->center_freq;
+	struct ieee80211_hw *hw = mt76_hw(dev);
+
+	if (hw->conf.chandef.chan->center_freq != freq ||
+	    hw->conf.chandef.width != width)
+		dev->dfs_state = -1;
+}
 
 static inline void mt7615_irq_enable(struct mt7615_dev *dev, u32 mask)
 {
@@ -193,5 +237,7 @@ void mt7615_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,
 void mt7615_mac_work(struct work_struct *work);
 void mt7615_txp_skb_unmap(struct mt76_dev *dev,
 			  struct mt76_txwi_cache *txwi);
+int mt76_dfs_start_rdd(struct mt7615_dev *dev, bool force);
+int mt7615_dfs_init_radar_detector(struct mt7615_dev *dev);
 
 #endif
-- 
2.21.0


^ permalink raw reply related

* [RFC 1/5] mt76: mt7615: introduce mt7615_regd_notifier
From: Lorenzo Bianconi @ 2019-06-25 22:01 UTC (permalink / raw)
  To: nbd; +Cc: lorenzo.bianconi, linux-wireless, ryder.lee, royluo, yf.luo
In-Reply-To: <cover.1561499275.git.lorenzo@kernel.org>

Introduce mt7615_regd_notifier callback. This is a preliminary patch to
add radar detection support to mt7615 driver

Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
 drivers/net/wireless/mediatek/mt76/mt7615/init.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/init.c b/drivers/net/wireless/mediatek/mt76/mt7615/init.c
index 859de2454ec6..edce96ce79a4 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/init.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/init.c
@@ -208,6 +208,16 @@ mt7615_init_txpower(struct mt7615_dev *dev,
 	}
 }
 
+static void
+mt7615_regd_notifier(struct wiphy *wiphy,
+		     struct regulatory_request *request)
+{
+	struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
+	struct mt7615_dev *dev = hw->priv;
+
+	dev->mt76.region = request->dfs_region;
+}
+
 int mt7615_register_device(struct mt7615_dev *dev)
 {
 	struct ieee80211_hw *hw = mt76_hw(dev);
@@ -230,6 +240,7 @@ int mt7615_register_device(struct mt7615_dev *dev)
 
 	wiphy->iface_combinations = if_comb;
 	wiphy->n_iface_combinations = ARRAY_SIZE(if_comb);
+	wiphy->reg_notifier = mt7615_regd_notifier;
 
 	ieee80211_hw_set(hw, SUPPORTS_REORDERING_BUFFER);
 	ieee80211_hw_set(hw, TX_STATUS_NO_AMPDU_LEN);
-- 
2.21.0


^ permalink raw reply related

* [RFC 0/5] add hw dfs pattern detector support to mt7615 driver
From: Lorenzo Bianconi @ 2019-06-25 22:01 UTC (permalink / raw)
  To: nbd; +Cc: lorenzo.bianconi, linux-wireless, ryder.lee, royluo, yf.luo

Introduce radar pattern detection support to mt7615 driver. Please note I have
tested this series just through the radar pattern test knob added to debugfs
and not through I real radar signal generator.
CSA is currently missing (I am currently working on it).
This series is based on 'mt76: move nl80211_dfs_regions in mt76_dev data
structure' https://patchwork.kernel.org/patch/11010723/

Lorenzo Bianconi (5):
  mt76: mt7615: introduce mt7615_regd_notifier
  mt76: mt7615: add hw dfs pattern detector support
  mt76: mt7615: do not perform txcalibration before cac is complited
  mt76: mt7615: unlock dfs bands
  mt76: mt7615: add radar pattern test knob to debugfs

 .../wireless/mediatek/mt76/mt7615/Makefile    |   3 +-
 .../wireless/mediatek/mt76/mt7615/debugfs.c   |  38 ++++++
 .../net/wireless/mediatek/mt76/mt7615/dma.c   |   2 +-
 .../net/wireless/mediatek/mt76/mt7615/init.c  |  43 +++++--
 .../net/wireless/mediatek/mt76/mt7615/mac.c   |  88 +++++++++++++
 .../net/wireless/mediatek/mt76/mt7615/main.c  |   6 +
 .../net/wireless/mediatek/mt76/mt7615/mcu.c   | 121 ++++++++++++++++--
 .../net/wireless/mediatek/mt76/mt7615/mcu.h   |  23 ++++
 .../wireless/mediatek/mt76/mt7615/mt7615.h    |  55 ++++++++
 9 files changed, 356 insertions(+), 23 deletions(-)
 create mode 100644 drivers/net/wireless/mediatek/mt76/mt7615/debugfs.c

-- 
2.21.0


^ permalink raw reply

* Re: [PATCH 1/4] b43legacy: remove b43legacy_dma_set_mask
From: Larry Finger @ 2019-06-25 21:45 UTC (permalink / raw)
  To: Christoph Hellwig, Kalle Valo
  Cc: b43-dev, linux-wireless, netdev, linux-kernel
In-Reply-To: <20190625102932.32257-2-hch@lst.de>

On 6/25/19 5:29 AM, Christoph Hellwig wrote:
> These days drivers are not required to fallback to smaller DMA masks,
> but can just set the largest mask they support, removing the need for
> this trial and error logic.
> 
> Signed-off-by: Christoph Hellwig <hch@lst.de>
> ---
>   drivers/net/wireless/broadcom/b43legacy/dma.c | 39 +------------------
>   1 file changed, 1 insertion(+), 38 deletions(-)

The patches work for PPC32 for both b43legacy and b43.

Tested-by: Larry Finger <Larry.Finger@lwfinger.net>

Thanks,

Larry

> 
> diff --git a/drivers/net/wireless/broadcom/b43legacy/dma.c b/drivers/net/wireless/broadcom/b43legacy/dma.c
> index 2ce1537d983c..0c2de20622e3 100644
> --- a/drivers/net/wireless/broadcom/b43legacy/dma.c
> +++ b/drivers/net/wireless/broadcom/b43legacy/dma.c
> @@ -797,43 +797,6 @@ void b43legacy_dma_free(struct b43legacy_wldev *dev)
>   	dma->tx_ring0 = NULL;
>   }
>   
> -static int b43legacy_dma_set_mask(struct b43legacy_wldev *dev, u64 mask)
> -{
> -	u64 orig_mask = mask;
> -	bool fallback = false;
> -	int err;
> -
> -	/* Try to set the DMA mask. If it fails, try falling back to a
> -	 * lower mask, as we can always also support a lower one. */
> -	while (1) {
> -		err = dma_set_mask_and_coherent(dev->dev->dma_dev, mask);
> -		if (!err)
> -			break;
> -		if (mask == DMA_BIT_MASK(64)) {
> -			mask = DMA_BIT_MASK(32);
> -			fallback = true;
> -			continue;
> -		}
> -		if (mask == DMA_BIT_MASK(32)) {
> -			mask = DMA_BIT_MASK(30);
> -			fallback = true;
> -			continue;
> -		}
> -		b43legacyerr(dev->wl, "The machine/kernel does not support "
> -		       "the required %u-bit DMA mask\n",
> -		       (unsigned int)dma_mask_to_engine_type(orig_mask));
> -		return -EOPNOTSUPP;
> -	}
> -	if (fallback) {
> -		b43legacyinfo(dev->wl, "DMA mask fallback from %u-bit to %u-"
> -			"bit\n",
> -			(unsigned int)dma_mask_to_engine_type(orig_mask),
> -			(unsigned int)dma_mask_to_engine_type(mask));
> -	}
> -
> -	return 0;
> -}
> -
>   int b43legacy_dma_init(struct b43legacy_wldev *dev)
>   {
>   	struct b43legacy_dma *dma = &dev->dma;
> @@ -844,7 +807,7 @@ int b43legacy_dma_init(struct b43legacy_wldev *dev)
>   
>   	dmamask = supported_dma_mask(dev);
>   	type = dma_mask_to_engine_type(dmamask);
> -	err = b43legacy_dma_set_mask(dev, dmamask);
> +	err = dma_set_mask_and_coherent(dev->dev->dma_dev, dmamask);
>   	if (err) {
>   #ifdef CONFIG_B43LEGACY_PIO
>   		b43legacywarn(dev->wl, "DMA for this device not supported. "
> 


^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox