Skip to content

Commit 55c2e41

Browse files
committed
drivers: wifi: nrf7002: Add support for multiple virtual interfaces (VIFs)
Description: The nRF7002 firmware supports two virtual interfaces (VIFs) that can operate in different modes (e.g., AP and STA). However, the existing Zephyr driver only utilizes a single VIF, preventing full multi-interface support. This commit extends the nRF7002 driver to support multiple VIFs by making the following modifications: * The driver already contains an array of vif_ctx_zep, but only the first item was being used. Now, a second Ethernet device is registered using vif_ctx_zep[1], enabling multi-VIF operation. * Introduced vif_ctx_cnt to keep track of active interfaces and manage their state effectively. * Ensured that FMAC (Firmware MAC) is initialized only once, avoiding redundant initializations when multiple VIFs are present. * The UMAC control commands previously did not associate responses with the issuing VIF. A queue is now introduced to track the originating VIF for each command and correctly route the response event to the corresponding interface. Signed-off-by: Hanan Arshad <hananarshad619@gmail.com>
1 parent 5736aed commit 55c2e41

File tree

5 files changed

+141
-44
lines changed

5 files changed

+141
-44
lines changed

drivers/wifi/nrf_wifi/Kconfig.nrfwifi

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,16 @@ config NRF70_AP_MODE
8888
depends on WIFI_NM_WPA_SUPPLICANT_AP
8989
default y if WIFI_NM_WPA_SUPPLICANT_AP
9090

91+
config NRF70_WIFI_ENABLE_DUAL_VIF
92+
bool "Enable dual virtual Wi-Fi interfaces"
93+
default y if WIFI_NM_MAX_MANAGED_INTERFACES = 2
94+
default n
95+
depends on WIFI_NRF7002 && NET_L2_ETHERNET
96+
help
97+
Enable support for two virtual Wi-Fi interfaces (VIFs).
98+
When enabled, the driver can operate two VIFs simultaneously,
99+
allowing use cases such as one interface in AP mode and another in STA mode.
100+
91101
config NRF70_P2P_MODE
92102
bool "P2P support in driver"
93103

drivers/wifi/nrf_wifi/inc/fmac_main.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ const char *nrf_wifi_get_drv_version(void);
138138
enum nrf_wifi_status nrf_wifi_fmac_dev_add_zep(struct nrf_wifi_drv_priv_zep *drv_priv_zep);
139139
enum nrf_wifi_status nrf_wifi_fmac_dev_rem_zep(struct nrf_wifi_drv_priv_zep *drv_priv_zep);
140140
struct nrf_wifi_vif_ctx_zep *nrf_wifi_get_vif_ctx(struct net_if *iface);
141+
struct nrf_wifi_vif_ctx_zep *nrf_wifi_get_vif_ctx_by_idx(int index);
141142
#ifdef CONFIG_NRF_WIFI_RPU_RECOVERY
142143
void nrf_wifi_rpu_recovery_cb(void *vif_ctx,
143144
void *event_data,

drivers/wifi/nrf_wifi/src/fmac_main.c

Lines changed: 53 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,25 @@ const char *nrf_wifi_get_drv_version(void)
111111
return NRF70_DRIVER_VERSION;
112112
}
113113

114+
struct nrf_wifi_vif_ctx_zep *nrf_wifi_get_vif_ctx_by_idx(int index)
115+
{
116+
struct nrf_wifi_vif_ctx_zep *vif_ctx_zep = NULL;
117+
struct nrf_wifi_ctx_zep *rpu_ctx_zep = &rpu_drv_priv_zep.rpu_ctx_zep;
118+
119+
if (index < 0 || !rpu_ctx_zep || !rpu_ctx_zep->rpu_ctx) {
120+
return NULL;
121+
}
122+
123+
for (int i = 0; i < ARRAY_SIZE(rpu_ctx_zep->vif_ctx_zep); i++) {
124+
if (rpu_ctx_zep->vif_ctx_zep[i].vif_idx == index) {
125+
vif_ctx_zep = &rpu_ctx_zep->vif_ctx_zep[i];
126+
break;
127+
}
128+
}
129+
130+
return vif_ctx_zep;
131+
}
132+
114133
/* If the interface is not Wi-Fi then errors are expected, so, fail silently */
115134
struct nrf_wifi_vif_ctx_zep *nrf_wifi_get_vif_ctx(struct net_if *iface)
116135
{
@@ -402,6 +421,7 @@ void nrf_wifi_event_proc_cookie_rsp(void *vif_ctx,
402421
struct nrf_wifi_vif_ctx_zep *vif_ctx_zep = NULL;
403422
struct nrf_wifi_ctx_zep *rpu_ctx_zep = NULL;
404423
struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx = NULL;
424+
unsigned int vif_ctx_cnt = 0;
405425

406426
vif_ctx_zep = vif_ctx;
407427

@@ -412,6 +432,7 @@ void nrf_wifi_event_proc_cookie_rsp(void *vif_ctx,
412432

413433
rpu_ctx_zep = vif_ctx_zep->rpu_ctx_zep;
414434
fmac_dev_ctx = rpu_ctx_zep->rpu_ctx;
435+
vif_ctx_cnt = nrf_wifi_fmac_get_num_vifs(rpu_ctx_zep->rpu_ctx);
415436

416437
LOG_DBG("%s: cookie_rsp_event->cookie = %llx", __func__, cookie_rsp_event->cookie);
417438
LOG_DBG("%s: host_cookie = %llx", __func__, cookie_rsp_event->host_cookie);
@@ -423,7 +444,12 @@ void nrf_wifi_event_proc_cookie_rsp(void *vif_ctx,
423444
cookie_rsp_event->mac_addr[4],
424445
cookie_rsp_event->mac_addr[5]);
425446

426-
vif_ctx_zep->cookie_resp_received = true;
447+
/* Notify all vif */
448+
for(int idx = 0; idx < vif_ctx_cnt; ++idx) {
449+
vif_ctx_zep = nrf_wifi_get_vif_ctx_by_idx(idx);
450+
if(vif_ctx_zep)
451+
vif_ctx_zep->cookie_resp_received = true;
452+
}
427453
/* TODO: When supp_callbk_fns.mgmt_tx_status is implemented, add logic
428454
* here to use the cookie and host_cookie to map requests to responses.
429455
*/
@@ -695,8 +721,18 @@ static int nrf_wifi_drv_main_zep(const struct device *dev)
695721
struct nrf_wifi_data_config_params data_config = { 0 };
696722
struct rx_buf_pool_params rx_buf_pools[MAX_NUM_OF_RX_QUEUES];
697723
struct nrf_wifi_vif_ctx_zep *vif_ctx_zep = dev->data;
724+
struct nrf_wifi_ctx_zep *rpu_ctx_zep = &rpu_drv_priv_zep.rpu_ctx_zep;
725+
unsigned int vif_ctx_cnt = nrf_wifi_fmac_get_num_vifs(rpu_ctx_zep->rpu_ctx);
698726

699-
vif_ctx_zep->rpu_ctx_zep = &rpu_drv_priv_zep.rpu_ctx_zep;
727+
if(vif_ctx_cnt >= MAX_NUM_VIFS){
728+
LOG_ERR("%s: Max number of VIFs reached", __func__);
729+
return -ENOMEM;
730+
}
731+
732+
if (vif_ctx_cnt > 1) {
733+
// FMAC is already initialized for VIF-0
734+
return 0;
735+
}
700736

701737
#ifdef CONFIG_NRF70_DATA_TX
702738
data_config.aggregation = aggregation;
@@ -923,6 +959,21 @@ ETH_NET_DEVICE_DT_INST_DEFINE(0,
923959
CONFIG_WIFI_INIT_PRIORITY, /* prio */
924960
&wifi_offload_ops, /* api */
925961
CONFIG_NRF_WIFI_IFACE_MTU); /*mtu */
962+
#ifdef CONFIG_NRF70_WIFI_ENABLE_DUAL_VIF
963+
// Register second interface
964+
ETH_NET_DEVICE_DT_INST_DEFINE(1,
965+
nrf_wifi_drv_main_zep, /* init_fn */
966+
NULL, /* pm_action_cb */
967+
&rpu_drv_priv_zep.rpu_ctx_zep.vif_ctx_zep[1], /* data */
968+
#ifdef CONFIG_NRF70_STA_MODE
969+
&wpa_supp_ops, /* cfg */
970+
#else /* CONFIG_NRF70_STA_MODE */
971+
NULL, /* cfg */
972+
#endif /* !CONFIG_NRF70_STA_MODE */
973+
CONFIG_WIFI_INIT_PRIORITY, /* prio */
974+
&wifi_offload_ops, /* api */
975+
CONFIG_NRF_WIFI_IFACE_MTU); /*mtu */
976+
#endif
926977
#else
927978
DEVICE_DT_INST_DEFINE(0,
928979
nrf_wifi_drv_main_zep, /* init_fn */

drivers/wifi/nrf_wifi/src/net_if.c

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ void nrf_wifi_set_iface_event_handler(void *os_vif_ctx,
4141
unsigned int event_len)
4242
{
4343
struct nrf_wifi_vif_ctx_zep *vif_ctx_zep = NULL;
44+
struct nrf_wifi_ctx_zep *rpu_ctx_zep = NULL;
45+
unsigned int vif_ctx_cnt = 0;
4446

4547
if (!os_vif_ctx) {
4648
LOG_ERR("%s: Invalid parameters",
@@ -57,9 +59,18 @@ void nrf_wifi_set_iface_event_handler(void *os_vif_ctx,
5759
(void)event_len;
5860

5961
vif_ctx_zep = os_vif_ctx;
60-
61-
vif_ctx_zep->set_if_event_received = true;
62-
vif_ctx_zep->set_if_status = event->return_value;
62+
rpu_ctx_zep = vif_ctx_zep->rpu_ctx_zep;
63+
vif_ctx_cnt = nrf_wifi_fmac_get_num_vifs(rpu_ctx_zep->rpu_ctx);
64+
65+
/* Notify all vif */
66+
for(int idx = 0; idx < vif_ctx_cnt; ++idx) {
67+
vif_ctx_zep = nrf_wifi_get_vif_ctx_by_idx(idx);
68+
if(vif_ctx_zep)
69+
{
70+
vif_ctx_zep->set_if_event_received = true;
71+
vif_ctx_zep->set_if_status = event->return_value;
72+
}
73+
}
6374

6475
out:
6576
return;
@@ -760,8 +771,7 @@ int nrf_wifi_if_start_zep(const struct device *dev)
760771
}
761772

762773
k_mutex_init(&vif_ctx_zep->vif_lock);
763-
rpu_ctx_zep->vif_ctx_zep[vif_ctx_zep->vif_idx].if_type =
764-
add_vif_info.iftype;
774+
vif_ctx_zep->if_type = add_vif_info.iftype;
765775

766776
/* Check if user has provided a valid MAC address, if not
767777
* fetch it from OTP.

drivers/wifi/nrf_wifi/src/wpa_supp_if.c

Lines changed: 62 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -443,7 +443,10 @@ void *nrf_wifi_wpa_supp_dev_init(void *supp_drv_if_ctx, const char *iface_name,
443443
struct zep_wpa_supp_dev_callbk_fns *supp_callbk_fns)
444444
{
445445
struct nrf_wifi_vif_ctx_zep *vif_ctx_zep = NULL;
446-
const struct device *device = DEVICE_DT_GET(DT_CHOSEN(zephyr_wifi));
446+
// Get device for Each interface
447+
const int if_idx = net_if_get_by_name(iface_name);
448+
struct net_if* iface = net_if_get_by_index(if_idx);
449+
const struct device *device = net_if_get_device(iface);
447450

448451
if (!device) {
449452
LOG_ERR("%s: Interface %s not found", __func__, iface_name);
@@ -1587,6 +1590,7 @@ void nrf_wifi_wpa_supp_event_get_wiphy(void *if_priv,
15871590
struct nrf_wifi_vif_ctx_zep *vif_ctx_zep = NULL;
15881591
struct nrf_wifi_ctx_zep *rpu_ctx_zep = NULL;
15891592
struct wpa_supp_event_supported_band band;
1593+
unsigned int vif_ctx_cnt = 0;
15901594

15911595
if (!if_priv || !wiphy_info || !event_len) {
15921596
LOG_ERR("%s: Invalid parameters", __func__);
@@ -1595,44 +1599,53 @@ void nrf_wifi_wpa_supp_event_get_wiphy(void *if_priv,
15951599

15961600
vif_ctx_zep = if_priv;
15971601
rpu_ctx_zep = vif_ctx_zep->rpu_ctx_zep;
1602+
vif_ctx_cnt = nrf_wifi_fmac_get_num_vifs(rpu_ctx_zep->rpu_ctx);
15981603

15991604
memset(&band, 0, sizeof(band));
1600-
1601-
for (int i = 0; i < NRF_WIFI_EVENT_GET_WIPHY_NUM_BANDS; i++) {
1602-
if (nrf_wifi_parse_sband(&wiphy_info->sband[i], &band) != WLAN_STATUS_SUCCESS) {
1605+
1606+
for(int idx = 0; idx < vif_ctx_cnt; ++idx) {
1607+
vif_ctx_zep = nrf_wifi_get_vif_ctx_by_idx(idx);
1608+
if(vif_ctx_zep == NULL)
16031609
continue;
1604-
}
1605-
if (vif_ctx_zep->supp_drv_if_ctx && vif_ctx_zep->supp_callbk_fns.get_wiphy_res) {
1606-
vif_ctx_zep->supp_callbk_fns.get_wiphy_res(vif_ctx_zep->supp_drv_if_ctx,
1607-
&band);
1608-
}
1609-
}
1610-
1611-
if ((wiphy_info->params_valid & NRF_WIFI_GET_WIPHY_VALID_EXTENDED_CAPABILITIES) &&
1612-
rpu_ctx_zep->extended_capa == NULL) {
16131610

1614-
rpu_ctx_zep->extended_capa = k_malloc(wiphy_info->extended_capabilities_len);
1615-
1616-
if (rpu_ctx_zep->extended_capa) {
1617-
memcpy(rpu_ctx_zep->extended_capa, wiphy_info->extended_capabilities,
1618-
wiphy_info->extended_capabilities_len);
1611+
for (int i = 0; i < NRF_WIFI_EVENT_GET_WIPHY_NUM_BANDS; i++) {
1612+
if (nrf_wifi_parse_sband(&wiphy_info->sband[i], &band) != WLAN_STATUS_SUCCESS) {
1613+
continue;
1614+
}
1615+
if (vif_ctx_zep->supp_drv_if_ctx && vif_ctx_zep->supp_callbk_fns.get_wiphy_res) {
1616+
vif_ctx_zep->supp_callbk_fns.get_wiphy_res(vif_ctx_zep->supp_drv_if_ctx,
1617+
&band);
1618+
}
16191619
}
16201620

1621-
rpu_ctx_zep->extended_capa_mask = k_malloc(wiphy_info->extended_capabilities_len);
1622-
1623-
if (rpu_ctx_zep->extended_capa_mask) {
1624-
memcpy(rpu_ctx_zep->extended_capa_mask,
1625-
wiphy_info->extended_capabilities_mask,
1626-
wiphy_info->extended_capabilities_len);
1627-
} else {
1628-
free(rpu_ctx_zep->extended_capa);
1629-
rpu_ctx_zep->extended_capa = NULL;
1630-
rpu_ctx_zep->extended_capa_len = 0;
1621+
if ((wiphy_info->params_valid & NRF_WIFI_GET_WIPHY_VALID_EXTENDED_CAPABILITIES) &&
1622+
rpu_ctx_zep->extended_capa == NULL) {
1623+
/* To avoid overflowing the 100 column limit */
1624+
unsigned char ec_len = wiphy_info->extended_capabilities_len;
1625+
1626+
rpu_ctx_zep->extended_capa = k_malloc(wiphy_info->extended_capabilities_len);
1627+
1628+
if (rpu_ctx_zep->extended_capa) {
1629+
memcpy(rpu_ctx_zep->extended_capa, wiphy_info->extended_capabilities,
1630+
wiphy_info->extended_capabilities_len);
1631+
}
1632+
1633+
rpu_ctx_zep->extended_capa_mask = k_malloc(wiphy_info->extended_capabilities_len);
1634+
1635+
if (rpu_ctx_zep->extended_capa_mask) {
1636+
memcpy(rpu_ctx_zep->extended_capa_mask,
1637+
wiphy_info->extended_capabilities_mask,
1638+
ec_len);
1639+
} else {
1640+
nrf_wifi_osal_mem_free(rpu_ctx_zep->extended_capa);
1641+
rpu_ctx_zep->extended_capa = NULL;
1642+
rpu_ctx_zep->extended_capa_len = 0;
1643+
}
16311644
}
1632-
}
16331645

1634-
if (vif_ctx_zep->supp_drv_if_ctx && vif_ctx_zep->supp_callbk_fns.get_wiphy_res) {
1635-
vif_ctx_zep->supp_callbk_fns.get_wiphy_res(vif_ctx_zep->supp_drv_if_ctx, NULL);
1646+
if (vif_ctx_zep->supp_drv_if_ctx && vif_ctx_zep->supp_callbk_fns.get_wiphy_res) {
1647+
vif_ctx_zep->supp_callbk_fns.get_wiphy_res(vif_ctx_zep->supp_drv_if_ctx, NULL);
1648+
}
16361649
}
16371650
}
16381651

@@ -1945,19 +1958,31 @@ void nrf_wifi_supp_event_proc_get_conn_info(void *if_priv,
19451958
{
19461959
struct nrf_wifi_vif_ctx_zep *vif_ctx_zep = NULL;
19471960
struct wpa_conn_info *conn_info = NULL;
1961+
struct nrf_wifi_ctx_zep *rpu_ctx_zep = NULL;
1962+
unsigned int vif_ctx_cnt = 0;
19481963

19491964
if (!if_priv || !info) {
19501965
LOG_ERR("%s: Invalid params", __func__);
19511966
k_sem_give(&wait_for_event_sem);
19521967
return;
19531968
}
19541969
vif_ctx_zep = if_priv;
1955-
conn_info = vif_ctx_zep->conn_info;
1956-
1957-
conn_info->beacon_interval = info->beacon_interval;
1958-
conn_info->dtim_period = info->dtim_interval;
1959-
conn_info->twt_capable = info->twt_capable;
1960-
k_sem_give(&wait_for_event_sem);
1970+
rpu_ctx_zep = vif_ctx_zep->rpu_ctx_zep;
1971+
vif_ctx_cnt = nrf_wifi_fmac_get_num_vifs(rpu_ctx_zep->rpu_ctx);
1972+
1973+
/* Notify all vif */
1974+
for(int idx = 0; idx < vif_ctx_cnt; ++idx) {
1975+
vif_ctx_zep = nrf_wifi_get_vif_ctx_by_idx(idx);
1976+
if(vif_ctx_zep)
1977+
{
1978+
conn_info = vif_ctx_zep->conn_info;
1979+
1980+
conn_info->beacon_interval = info->beacon_interval;
1981+
conn_info->dtim_period = info->dtim_interval;
1982+
conn_info->twt_capable = info->twt_capable;
1983+
k_sem_give(&wait_for_event_sem);
1984+
}
1985+
}
19611986
}
19621987

19631988
#ifdef CONFIG_NRF70_AP_MODE

0 commit comments

Comments
 (0)