1 /*
2  * Copyright (c) 2024 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 /**
8  * @brief File containing VIF handling specific definitions for the
9  * FMAC IF Layer of the Wi-Fi driver.
10  */
11 
12 #include "system/fmac_vif.h"
13 #include "host_rpu_umac_if.h"
14 #include "common/fmac_util.h"
15 
16 
nrf_wifi_fmac_vif_check_if_limit(struct nrf_wifi_fmac_dev_ctx * fmac_dev_ctx,int if_type)17 int nrf_wifi_fmac_vif_check_if_limit(struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx,
18 				     int if_type)
19 {
20 	struct nrf_wifi_sys_fmac_dev_ctx *sys_dev_ctx;
21 
22 	sys_dev_ctx = wifi_dev_priv(fmac_dev_ctx);
23 
24 	switch (if_type) {
25 	case NRF_WIFI_IFTYPE_STATION:
26 	case NRF_WIFI_IFTYPE_P2P_CLIENT:
27 		if (sys_dev_ctx->num_sta >= MAX_NUM_STAS) {
28 			nrf_wifi_osal_log_err("%s: Maximum STA Interface type exceeded",
29 					      __func__);
30 			return -1;
31 		}
32 		break;
33 	case NRF_WIFI_IFTYPE_AP:
34 	case NRF_WIFI_IFTYPE_P2P_GO:
35 		if (sys_dev_ctx->num_ap >= MAX_NUM_APS) {
36 			nrf_wifi_osal_log_err("%s: Maximum AP Interface type exceeded",
37 					      __func__);
38 			return -1;
39 		}
40 		break;
41 	default:
42 		nrf_wifi_osal_log_err("%s: Interface type not supported",
43 				      __func__);
44 		return -1;
45 	}
46 
47 	return 0;
48 }
49 
50 
nrf_wifi_fmac_vif_incr_if_type(struct nrf_wifi_fmac_dev_ctx * fmac_dev_ctx,int if_type)51 void nrf_wifi_fmac_vif_incr_if_type(struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx,
52 				    int if_type)
53 {
54 	struct nrf_wifi_sys_fmac_dev_ctx *sys_dev_ctx;
55 
56 	sys_dev_ctx = wifi_dev_priv(fmac_dev_ctx);
57 
58 	switch (if_type) {
59 	case NRF_WIFI_IFTYPE_STATION:
60 	case NRF_WIFI_IFTYPE_P2P_CLIENT:
61 		sys_dev_ctx->num_sta++;
62 		break;
63 	case NRF_WIFI_IFTYPE_AP:
64 	case NRF_WIFI_IFTYPE_P2P_GO:
65 		sys_dev_ctx->num_ap++;
66 		break;
67 	default:
68 		nrf_wifi_osal_log_err("%s:Unsupported VIF type",
69 				      __func__);
70 	}
71 }
72 
73 
nrf_wifi_fmac_vif_decr_if_type(struct nrf_wifi_fmac_dev_ctx * fmac_dev_ctx,int if_type)74 void nrf_wifi_fmac_vif_decr_if_type(struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx,
75 				    int if_type)
76 {
77 	struct nrf_wifi_sys_fmac_dev_ctx *sys_dev_ctx;
78 
79 	sys_dev_ctx = wifi_dev_priv(fmac_dev_ctx);
80 
81 	switch (if_type) {
82 	case NRF_WIFI_IFTYPE_STATION:
83 	case NRF_WIFI_IFTYPE_P2P_CLIENT:
84 		sys_dev_ctx->num_sta--;
85 		break;
86 	case NRF_WIFI_IFTYPE_AP:
87 	case NRF_WIFI_IFTYPE_P2P_GO:
88 		sys_dev_ctx->num_ap--;
89 		break;
90 	default:
91 		nrf_wifi_osal_log_err("%s:Unsupported VIF type",
92 				      __func__);
93 	}
94 }
95 
96 
nrf_wifi_fmac_vif_clear_ctx(void * dev_ctx,unsigned char if_idx)97 void nrf_wifi_fmac_vif_clear_ctx(void *dev_ctx,
98 				 unsigned char if_idx)
99 {
100 	struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx = NULL;
101 	struct nrf_wifi_fmac_vif_ctx *vif_ctx = NULL;
102 	struct nrf_wifi_sys_fmac_dev_ctx *sys_dev_ctx;
103 
104 	fmac_dev_ctx = dev_ctx;
105 	sys_dev_ctx = wifi_dev_priv(fmac_dev_ctx);
106 
107 	vif_ctx = sys_dev_ctx->vif_ctx[if_idx];
108 
109 	nrf_wifi_osal_mem_free(vif_ctx);
110 	sys_dev_ctx->vif_ctx[if_idx] = NULL;
111 }
112 
113 
nrf_wifi_fmac_vif_update_if_type(void * dev_ctx,unsigned char if_idx,int if_type)114 void nrf_wifi_fmac_vif_update_if_type(void *dev_ctx,
115 				      unsigned char if_idx,
116 				      int if_type)
117 {
118 	struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx = NULL;
119 	struct nrf_wifi_fmac_vif_ctx *vif_ctx = NULL;
120 	struct nrf_wifi_sys_fmac_dev_ctx *sys_dev_ctx = NULL;
121 
122 	fmac_dev_ctx = dev_ctx;
123 	sys_dev_ctx = wifi_dev_priv(fmac_dev_ctx);
124 
125 	vif_ctx = sys_dev_ctx->vif_ctx[if_idx];
126 
127 	nrf_wifi_fmac_vif_decr_if_type(fmac_dev_ctx,
128 				       vif_ctx->if_type);
129 
130 	nrf_wifi_fmac_vif_incr_if_type(fmac_dev_ctx,
131 				       if_type);
132 
133 	vif_ctx->if_type = if_type;
134 }
135 
nrf_wifi_fmac_get_num_vifs(void * dev_ctx)136 unsigned int nrf_wifi_fmac_get_num_vifs(void *dev_ctx)
137 {
138 	struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx = dev_ctx;
139 	struct nrf_wifi_sys_fmac_dev_ctx *sys_dev_ctx = NULL;
140 
141 	sys_dev_ctx = wifi_dev_priv(fmac_dev_ctx);
142 
143 	if (!fmac_dev_ctx) {
144 		/* Don't return error here, as FMAC might be initialized based
145 		 * the number of VIFs.
146 		 */
147 		return 0;
148 	}
149 
150 	return sys_dev_ctx->num_sta + sys_dev_ctx->num_ap;
151 }
152