Skip to content

Commit 26e1456

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 26e1456

File tree

6 files changed

+166
-16
lines changed

6 files changed

+166
-16
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_STA_AP_MODE
92+
bool "Simultaneous STA and AP mode"
93+
depends on WIFI_NRF7002
94+
select NRF70_AP_MODE
95+
select NRF70_STA_MODE
96+
default n
97+
help
98+
Select this option to operate both STA an AP mode simultaneously
99+
100+
91101
config NRF70_P2P_MODE
92102
bool "P2P support in driver"
93103

drivers/wifi/nrf_wifi/inc/fmac_main.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,15 @@ struct nrf_wifi_vif_ctx_map {
9393
const char *ifname;
9494
struct nrf_wifi_vif_ctx_zep *vif_ctx;
9595
};
96+
97+
#ifdef CONFIG_NRF70_STA_AP_MODE
98+
struct nrf_wifi_vif_cmd_event {
99+
void *fifo_reserved;
100+
unsigned int vif_event; // Event to expect
101+
unsigned int vif_idx; // VIF ID expecting the event
102+
};
103+
#endif
104+
96105
#endif /* !CONFIG_NRF70_RADIO_TEST */
97106

98107
struct nrf_wifi_ctx_zep {
@@ -103,6 +112,7 @@ struct nrf_wifi_ctx_zep {
103112
bool rf_test_run;
104113
unsigned char rf_test;
105114
#else /* CONFIG_NRF70_RADIO_TEST */
115+
unsigned int vif_ctx_cnt; // Variable to keep track for multiple interfaces
106116
struct nrf_wifi_vif_ctx_zep vif_ctx_zep[MAX_NUM_VIFS];
107117
#ifdef CONFIG_NRF70_UTIL
108118
struct rpu_conf_params conf_params;
@@ -138,6 +148,11 @@ const char *nrf_wifi_get_drv_version(void);
138148
enum nrf_wifi_status nrf_wifi_fmac_dev_add_zep(struct nrf_wifi_drv_priv_zep *drv_priv_zep);
139149
enum nrf_wifi_status nrf_wifi_fmac_dev_rem_zep(struct nrf_wifi_drv_priv_zep *drv_priv_zep);
140150
struct nrf_wifi_vif_ctx_zep *nrf_wifi_get_vif_ctx(struct net_if *iface);
151+
struct nrf_wifi_vif_ctx_zep *nrf_wifi_get_vif_ctx_by_idx(int index);
152+
#ifdef CONFIG_NRF70_STA_AP_MODE
153+
void nrf_wifi_enqueue_cmd_event(unsigned int event, unsigned int if_idx);
154+
struct nrf_wifi_vif_cmd_event* nrf_wifi_dequeue_cmd_event(void);
155+
#endif
141156
#ifdef CONFIG_NRF_WIFI_RPU_RECOVERY
142157
void nrf_wifi_rpu_recovery_cb(void *vif_ctx,
143158
void *event_data,

drivers/wifi/nrf_wifi/src/fmac_main.c

Lines changed: 75 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -106,24 +106,63 @@ static const unsigned int rx3_buf_sz = 1000;
106106
struct nrf_wifi_drv_priv_zep rpu_drv_priv_zep;
107107
static K_MUTEX_DEFINE(reg_lock);
108108

109+
#ifdef CONFIG_NRF70_STA_AP_MODE
110+
static K_FIFO_DEFINE(vif_cmd_event_q);
111+
112+
void nrf_wifi_enqueue_cmd_event(unsigned int event, unsigned int if_idx)
113+
{
114+
struct nrf_wifi_vif_cmd_event *cmd = k_malloc(sizeof(struct nrf_wifi_vif_cmd_event));
115+
if (cmd != NULL) {
116+
cmd->vif_event = event;
117+
cmd->vif_idx = if_idx;
118+
k_fifo_put(&vif_cmd_event_q, cmd);
119+
}
120+
}
121+
122+
struct nrf_wifi_vif_cmd_event* nrf_wifi_dequeue_cmd_event(void)
123+
{
124+
return k_fifo_get(&vif_cmd_event_q, K_NO_WAIT);
125+
}
126+
#endif
127+
109128
const char *nrf_wifi_get_drv_version(void)
110129
{
111130
return NRF70_DRIVER_VERSION;
112131
}
113132

133+
/* If the interface is not Wi-Fi then errors are expected, so, fail silently */
134+
struct nrf_wifi_vif_ctx_zep *nrf_wifi_get_vif_ctx_by_idx(int index)
135+
{
136+
struct nrf_wifi_vif_ctx_zep *vif_ctx_zep = NULL;
137+
struct nrf_wifi_ctx_zep *rpu_ctx_zep = &rpu_drv_priv_zep.rpu_ctx_zep;
138+
139+
if (index < 0 || !rpu_ctx_zep || !rpu_ctx_zep->rpu_ctx) {
140+
return NULL;
141+
}
142+
143+
for (int i = 0; i < rpu_ctx_zep->vif_ctx_cnt; i++) {
144+
if (rpu_ctx_zep->vif_ctx_zep[i].vif_idx == index) {
145+
vif_ctx_zep = &rpu_ctx_zep->vif_ctx_zep[i];
146+
break;
147+
}
148+
}
149+
150+
return vif_ctx_zep;
151+
}
152+
114153
/* If the interface is not Wi-Fi then errors are expected, so, fail silently */
115154
struct nrf_wifi_vif_ctx_zep *nrf_wifi_get_vif_ctx(struct net_if *iface)
116155
{
117156
struct nrf_wifi_vif_ctx_zep *vif_ctx_zep = NULL;
118-
struct nrf_wifi_ctx_zep *rpu_ctx = &rpu_drv_priv_zep.rpu_ctx_zep;
157+
struct nrf_wifi_ctx_zep *rpu_ctx_zep = &rpu_drv_priv_zep.rpu_ctx_zep;
119158

120-
if (!iface || !rpu_ctx || !rpu_ctx->rpu_ctx) {
159+
if (!iface || !rpu_ctx_zep || !rpu_ctx_zep->rpu_ctx) {
121160
return NULL;
122161
}
123162

124-
for (int i = 0; i < ARRAY_SIZE(rpu_ctx->vif_ctx_zep); i++) {
125-
if (rpu_ctx->vif_ctx_zep[i].zep_net_if_ctx == iface) {
126-
vif_ctx_zep = &rpu_ctx->vif_ctx_zep[i];
163+
for (int i = 0; i < rpu_ctx_zep->vif_ctx_cnt; i++) {
164+
if (rpu_ctx_zep->vif_ctx_zep[i].zep_net_if_ctx == iface) {
165+
vif_ctx_zep = &rpu_ctx_zep->vif_ctx_zep[i];
127166
break;
128167
}
129168
}
@@ -423,7 +462,9 @@ void nrf_wifi_event_proc_cookie_rsp(void *vif_ctx,
423462
cookie_rsp_event->mac_addr[4],
424463
cookie_rsp_event->mac_addr[5]);
425464

426-
vif_ctx_zep->cookie_resp_received = true;
465+
for(int i = 0; i < rpu_ctx_zep->vif_ctx_cnt; ++i) {
466+
rpu_ctx_zep->vif_ctx_zep[i].cookie_resp_received = true;
467+
}
427468
/* TODO: When supp_callbk_fns.mgmt_tx_status is implemented, add logic
428469
* here to use the cookie and host_cookie to map requests to responses.
429470
*/
@@ -695,8 +736,20 @@ static int nrf_wifi_drv_main_zep(const struct device *dev)
695736
struct nrf_wifi_data_config_params data_config = { 0 };
696737
struct rx_buf_pool_params rx_buf_pools[MAX_NUM_OF_RX_QUEUES];
697738
struct nrf_wifi_vif_ctx_zep *vif_ctx_zep = dev->data;
739+
struct nrf_wifi_ctx_zep *rpu_ctx_zep = &rpu_drv_priv_zep.rpu_ctx_zep;
698740

699-
vif_ctx_zep->rpu_ctx_zep = &rpu_drv_priv_zep.rpu_ctx_zep;
741+
vif_ctx_zep->rpu_ctx_zep = rpu_ctx_zep;
742+
743+
if(rpu_ctx_zep->vif_ctx_cnt >= MAX_NUM_VIFS){
744+
LOG_ERR("%s: Max number of VIFs reached", __func__);
745+
return -ENOMEM;
746+
}
747+
748+
rpu_ctx_zep->vif_ctx_cnt++;
749+
if (rpu_ctx_zep->vif_ctx_cnt > 1) {
750+
// FMAC is already initialized for VIF-0
751+
return 0;
752+
}
700753

701754
#ifdef CONFIG_NRF70_DATA_TX
702755
data_config.aggregation = aggregation;
@@ -923,6 +976,21 @@ ETH_NET_DEVICE_DT_INST_DEFINE(0,
923976
CONFIG_WIFI_INIT_PRIORITY, /* prio */
924977
&wifi_offload_ops, /* api */
925978
CONFIG_NRF_WIFI_IFACE_MTU); /*mtu */
979+
#ifdef CONFIG_NRF70_STA_AP_MODE
980+
// Register second interface
981+
ETH_NET_DEVICE_DT_INST_DEFINE(1,
982+
nrf_wifi_drv_main_zep, /* init_fn */
983+
NULL, /* pm_action_cb */
984+
&rpu_drv_priv_zep.rpu_ctx_zep.vif_ctx_zep[1], /* data */
985+
#ifdef CONFIG_NRF70_STA_MODE
986+
&wpa_supp_ops, /* cfg */
987+
#else /* CONFIG_NRF70_STA_MODE */
988+
NULL, /* cfg */
989+
#endif /* !CONFIG_NRF70_STA_MODE */
990+
CONFIG_WIFI_INIT_PRIORITY, /* prio */
991+
&wifi_offload_ops, /* api */
992+
CONFIG_NRF_WIFI_IFACE_MTU); /*mtu */
993+
#endif
926994
#else
927995
DEVICE_DT_INST_DEFINE(0,
928996
nrf_wifi_drv_main_zep, /* init_fn */

drivers/wifi/nrf_wifi/src/net_if.c

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@ 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+
#ifdef CONFIG_NRF70_STA_AP_MODE
45+
struct nrf_wifi_vif_cmd_event* vif_evt = NULL;
46+
#endif
4447

4548
if (!os_vif_ctx) {
4649
LOG_ERR("%s: Invalid parameters",
@@ -58,6 +61,17 @@ void nrf_wifi_set_iface_event_handler(void *os_vif_ctx,
5861

5962
vif_ctx_zep = os_vif_ctx;
6063

64+
#ifdef CONFIG_NRF70_STA_AP_MODE
65+
while ((vif_evt = nrf_wifi_dequeue_cmd_event()) != NULL) {
66+
if(vif_evt->vif_event == NRF_WIFI_UMAC_EVENT_SET_INTERFACE) {
67+
vif_ctx_zep = nrf_wifi_get_vif_ctx_by_idx(vif_evt->vif_idx);
68+
k_free(vif_evt);
69+
break;
70+
}
71+
k_free(vif_evt);
72+
}
73+
#endif
74+
6175
vif_ctx_zep->set_if_event_received = true;
6276
vif_ctx_zep->set_if_status = event->return_value;
6377

@@ -760,7 +774,7 @@ int nrf_wifi_if_start_zep(const struct device *dev)
760774
}
761775

762776
k_mutex_init(&vif_ctx_zep->vif_lock);
763-
rpu_ctx_zep->vif_ctx_zep[vif_ctx_zep->vif_idx].if_type =
777+
vif_ctx_zep->if_type =
764778
add_vif_info.iftype;
765779

766780
/* Check if user has provided a valid MAC address, if not

drivers/wifi/nrf_wifi/src/wpa_supp_if.c

Lines changed: 43 additions & 2 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,9 @@ 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+
#ifdef CONFIG_NRF70_STA_AP_MODE
1594+
struct nrf_wifi_vif_cmd_event* vif_evt = NULL;
1595+
#endif
15901596

15911597
if (!if_priv || !wiphy_info || !event_len) {
15921598
LOG_ERR("%s: Invalid parameters", __func__);
@@ -1597,7 +1603,16 @@ void nrf_wifi_wpa_supp_event_get_wiphy(void *if_priv,
15971603
rpu_ctx_zep = vif_ctx_zep->rpu_ctx_zep;
15981604

15991605
memset(&band, 0, sizeof(band));
1600-
1606+
#ifdef CONFIG_NRF70_STA_AP_MODE
1607+
while ((vif_evt = nrf_wifi_dequeue_cmd_event()) != NULL) {
1608+
if(vif_evt->vif_event == NRF_WIFI_UMAC_EVENT_NEW_WIPHY) {
1609+
vif_ctx_zep = nrf_wifi_get_vif_ctx_by_idx(vif_evt->vif_idx);
1610+
k_free(vif_evt);
1611+
break;
1612+
}
1613+
k_free(vif_evt);
1614+
}
1615+
#endif
16011616
for (int i = 0; i < NRF_WIFI_EVENT_GET_WIPHY_NUM_BANDS; i++) {
16021617
if (nrf_wifi_parse_sband(&wiphy_info->sband[i], &band) != WLAN_STATUS_SUCCESS) {
16031618
continue;
@@ -1660,6 +1675,9 @@ int nrf_wifi_supp_get_wiphy(void *if_priv)
16601675
goto out;
16611676
}
16621677

1678+
#ifdef CONFIG_NRF70_STA_AP_MODE
1679+
nrf_wifi_enqueue_cmd_event(NRF_WIFI_UMAC_EVENT_NEW_WIPHY, vif_ctx_zep->vif_idx);
1680+
#endif
16631681
status = nrf_wifi_sys_fmac_get_wiphy(rpu_ctx_zep->rpu_ctx, vif_ctx_zep->vif_idx);
16641682

16651683
if (status != NRF_WIFI_STATUS_SUCCESS) {
@@ -1847,6 +1865,9 @@ int nrf_wifi_supp_get_conn_info(void *if_priv, struct wpa_conn_info *info)
18471865
fmac_dev_ctx = rpu_ctx_zep->rpu_ctx;
18481866

18491867
vif_ctx_zep->conn_info = info;
1868+
#ifdef CONFIG_NRF70_STA_AP_MODE
1869+
nrf_wifi_enqueue_cmd_event(NRF_WIFI_UMAC_EVENT_GET_CONNECTION_INFO, vif_ctx_zep->vif_idx);
1870+
#endif
18501871
ret = nrf_wifi_sys_fmac_get_conn_info(rpu_ctx_zep->rpu_ctx, vif_ctx_zep->vif_idx);
18511872
if (ret != NRF_WIFI_STATUS_SUCCESS) {
18521873
LOG_ERR("%s: nrf_wifi_sys_fmac_get_conn_info failed", __func__);
@@ -1946,12 +1967,28 @@ void nrf_wifi_supp_event_proc_get_conn_info(void *if_priv,
19461967
struct nrf_wifi_vif_ctx_zep *vif_ctx_zep = NULL;
19471968
struct wpa_conn_info *conn_info = NULL;
19481969

1970+
#ifdef CONFIG_NRF70_STA_AP_MODE
1971+
struct nrf_wifi_vif_cmd_event* vif_evt = NULL;
1972+
#endif
1973+
19491974
if (!if_priv || !info) {
19501975
LOG_ERR("%s: Invalid params", __func__);
19511976
k_sem_give(&wait_for_event_sem);
19521977
return;
19531978
}
19541979
vif_ctx_zep = if_priv;
1980+
1981+
#ifdef CONFIG_NRF70_STA_AP_MODE
1982+
while ((vif_evt = nrf_wifi_dequeue_cmd_event()) != NULL) {
1983+
if(vif_evt->vif_event == NRF_WIFI_UMAC_EVENT_GET_CONNECTION_INFO) {
1984+
vif_ctx_zep = nrf_wifi_get_vif_ctx_by_idx(vif_evt->vif_idx);
1985+
k_free(vif_evt);
1986+
break;
1987+
}
1988+
k_free(vif_evt);
1989+
}
1990+
#endif
1991+
19551992
conn_info = vif_ctx_zep->conn_info;
19561993

19571994
conn_info->beacon_interval = info->beacon_interval;
@@ -2051,6 +2088,10 @@ static int nrf_wifi_iftype_change(struct nrf_wifi_vif_ctx_zep *vif_ctx_zep, int
20512088
chg_vif_info.iftype = iftype;
20522089
vif_ctx_zep->set_if_event_received = false;
20532090
vif_ctx_zep->set_if_status = 0;
2091+
2092+
#ifdef CONFIG_NRF70_STA_AP_MODE
2093+
nrf_wifi_enqueue_cmd_event(NRF_WIFI_UMAC_EVENT_SET_INTERFACE, vif_ctx_zep->vif_idx);
2094+
#endif
20542095
status = nrf_wifi_sys_fmac_chg_vif(rpu_ctx_zep->rpu_ctx,
20552096
vif_ctx_zep->vif_idx,
20562097
&chg_vif_info);

modules/hostap/src/supp_api.c

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ static K_WORK_DELAYABLE_DEFINE(wpa_supp_status_work,
8686
#define wpa_cli_cmd_v(cmd, ...) ({ \
8787
bool status; \
8888
\
89-
if (zephyr_wpa_cli_cmd_v(cmd, ##__VA_ARGS__) < 0) { \
89+
if (zephyr_wpa_cli_cmd_v(wpa_s->ctrl_conn, cmd, ##__VA_ARGS__) < 0) { \
9090
wpa_printf(MSG_ERROR, \
9191
"Failed to execute wpa_cli command: %s", \
9292
cmd); \
@@ -937,7 +937,7 @@ static int wpas_add_and_config_network(struct wpa_supplicant *wpa_s,
937937
goto out;
938938
}
939939

940-
ret = z_wpa_ctrl_add_network(&resp);
940+
ret = z_wpa_ctrl_add_network(wpa_s->ctrl_conn, &resp);
941941
if (ret) {
942942
wpa_printf(MSG_ERROR, "Failed to add network");
943943
goto out;
@@ -1626,7 +1626,7 @@ int supplicant_status(const struct device *dev, struct wifi_iface_status *status
16261626
status->channel = channel;
16271627

16281628
if (ssid_len == 0) {
1629-
int _res = z_wpa_ctrl_status(&cli_status);
1629+
int _res = z_wpa_ctrl_status(wpa_s->ctrl_conn, &cli_status);
16301630

16311631
if (_res < 0) {
16321632
ssid_len = 0;
@@ -1655,7 +1655,7 @@ int supplicant_status(const struct device *dev, struct wifi_iface_status *status
16551655

16561656
status->rssi = -WPA_INVALID_NOISE;
16571657
if (status->iface_mode == WIFI_MODE_INFRA) {
1658-
ret = z_wpa_ctrl_signal_poll(&signal_poll);
1658+
ret = z_wpa_ctrl_signal_poll(wpa_s->ctrl_conn, &signal_poll);
16591659
if (!ret) {
16601660
status->rssi = signal_poll.rssi;
16611661
status->current_phy_tx_rate = signal_poll.current_txrate;
@@ -1805,6 +1805,7 @@ int supplicant_11k_cfg(const struct device *dev, struct wifi_11k_params *params)
18051805
int supplicant_11k_neighbor_request(const struct device *dev, struct wifi_11k_params *params)
18061806
{
18071807
int ssid_len = strlen(params->ssid);
1808+
struct wpa_supplicant *wpa_s = get_wpa_s_handle(dev);
18081809

18091810
if (params != NULL && ssid_len > 0) {
18101811
if (ssid_len > WIFI_SSID_MAX_LEN) {
@@ -2071,7 +2072,8 @@ int supplicant_bss_ext_capab(const struct device *dev, int capab)
20712072
int supplicant_legacy_roam(const struct device *dev)
20722073
{
20732074
int ret = -1;
2074-
2075+
struct wpa_supplicant *wpa_s = get_wpa_s_handle(dev);
2076+
20752077
k_mutex_lock(&wpa_supplicant_mutex, K_FOREVER);
20762078
if (!wpa_cli_cmd_v("scan")) {
20772079
goto out;
@@ -2179,7 +2181,7 @@ static int supplicant_wps_pin(const struct device *dev, struct wifi_wps_config_p
21792181
}
21802182

21812183
if (params->oper == WIFI_WPS_PIN_GET) {
2182-
if (zephyr_wpa_cli_cmd_resp(get_pin_cmd, params->pin)) {
2184+
if (zephyr_wpa_cli_cmd_resp(wpa_s->ctrl_conn, get_pin_cmd, params->pin)) {
21832185
goto out;
21842186
}
21852187
} else if (params->oper == WIFI_WPS_PIN_SET) {

0 commit comments

Comments
 (0)