1 /*
2  * Copyright (c) 2024 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 /**
8  * @brief File containing peer handling specific definitions for the
9  * FMAC IF Layer of the Wi-Fi driver.
10  */
11 
12 #include "common/hal_mem.h"
13 #include "system/fmac_peer.h"
14 #include "host_rpu_umac_if.h"
15 #include "common/fmac_util.h"
16 
nrf_wifi_fmac_peer_get_id(struct nrf_wifi_fmac_dev_ctx * fmac_dev_ctx,const unsigned char * mac_addr)17 int nrf_wifi_fmac_peer_get_id(struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx,
18 			      const unsigned char *mac_addr)
19 {
20 	int i;
21 	struct peers_info *peer;
22 	struct nrf_wifi_sys_fmac_dev_ctx *sys_dev_ctx = NULL;
23 
24 	sys_dev_ctx = wifi_dev_priv(fmac_dev_ctx);
25 
26 	if (nrf_wifi_util_is_multicast_addr(mac_addr)) {
27 		return MAX_PEERS;
28 	}
29 
30 	for (i = 0; i < MAX_PEERS; i++) {
31 		peer = &sys_dev_ctx->tx_config.peers[i];
32 		if (peer->peer_id == -1) {
33 			continue;
34 		}
35 
36 		if ((nrf_wifi_util_ether_addr_equal(mac_addr,
37 						    (void *)peer->ra_addr))) {
38 			return peer->peer_id;
39 		}
40 	}
41 	return -1;
42 }
43 
nrf_wifi_fmac_peer_add(struct nrf_wifi_fmac_dev_ctx * fmac_dev_ctx,unsigned char if_idx,const unsigned char * mac_addr,unsigned char is_legacy,unsigned char qos_supported)44 int nrf_wifi_fmac_peer_add(struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx,
45 			   unsigned char if_idx,
46 			   const unsigned char *mac_addr,
47 			   unsigned char is_legacy,
48 			   unsigned char qos_supported)
49 {
50 	int i;
51 	struct peers_info *peer;
52 	struct nrf_wifi_fmac_vif_ctx *vif_ctx = NULL;
53 	struct nrf_wifi_sys_fmac_dev_ctx *sys_dev_ctx = NULL;
54 
55 	sys_dev_ctx = wifi_dev_priv(fmac_dev_ctx);
56 
57 	vif_ctx = sys_dev_ctx->vif_ctx[if_idx];
58 
59 	if (nrf_wifi_util_is_multicast_addr(mac_addr)
60 	    && (vif_ctx->if_type == NRF_WIFI_IFTYPE_AP)) {
61 
62 		sys_dev_ctx->tx_config.peers[MAX_PEERS].if_idx = if_idx;
63 		sys_dev_ctx->tx_config.peers[MAX_PEERS].peer_id = MAX_PEERS;
64 		sys_dev_ctx->tx_config.peers[MAX_PEERS].is_legacy = 1;
65 
66 
67 		return MAX_PEERS;
68 	}
69 
70 	for (i = 0; i < MAX_PEERS; i++) {
71 		peer = &sys_dev_ctx->tx_config.peers[i];
72 
73 		if (peer->peer_id == -1) {
74 			nrf_wifi_osal_mem_cpy(peer->ra_addr,
75 					      mac_addr,
76 					      NRF_WIFI_ETH_ADDR_LEN);
77 			peer->if_idx = if_idx;
78 			peer->peer_id = i;
79 			peer->is_legacy = is_legacy;
80 			peer->qos_supported = qos_supported;
81 			if (vif_ctx->if_type == NRF_WIFI_IFTYPE_AP) {
82 				hal_rpu_mem_write(fmac_dev_ctx->hal_dev_ctx,
83 						  (RPU_MEM_UMAC_PEND_Q_BMP +
84 						  sizeof(struct sap_client_pend_frames_bitmap) * i),
85 						  peer->ra_addr,
86 						  NRF_WIFI_FMAC_ETH_ADDR_LEN);
87 			}
88 			return i;
89 		}
90 	}
91 
92 	nrf_wifi_osal_log_err("%s: Failed !! No Space Available",
93 			      __func__);
94 
95 	return -1;
96 }
97 
98 
nrf_wifi_fmac_peer_remove(struct nrf_wifi_fmac_dev_ctx * fmac_dev_ctx,unsigned char if_idx,int peer_id)99 void nrf_wifi_fmac_peer_remove(struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx,
100 			       unsigned char if_idx,
101 			       int peer_id)
102 {
103 	struct peers_info *peer;
104 	struct nrf_wifi_fmac_vif_ctx *vif_ctx = NULL;
105 	struct nrf_wifi_sys_fmac_dev_ctx *sys_dev_ctx = NULL;
106 
107 	if (peer_id == -1 || peer_id >= MAX_PEERS) {
108 		return;
109 	}
110 
111 	sys_dev_ctx = wifi_dev_priv(fmac_dev_ctx);
112 
113 	vif_ctx = sys_dev_ctx->vif_ctx[if_idx];
114 	peer = &sys_dev_ctx->tx_config.peers[peer_id];
115 
116 	if (!peer || peer->peer_id == -1 || peer->peer_id >= MAX_PEERS ||
117 	    peer->if_idx != if_idx) {
118 		return;
119 	}
120 
121 	if (vif_ctx->if_type == NRF_WIFI_IFTYPE_AP) {
122 		hal_rpu_mem_write(fmac_dev_ctx->hal_dev_ctx,
123 				  (RPU_MEM_UMAC_PEND_Q_BMP +
124 				   (sizeof(struct sap_client_pend_frames_bitmap) * peer_id)),
125 				  peer->ra_addr,
126 				  NRF_WIFI_FMAC_ETH_ADDR_LEN);
127 	}
128 
129 	nrf_wifi_osal_mem_set(peer,
130 			      0x0,
131 			      sizeof(struct peers_info));
132 	peer->peer_id = -1;
133 }
134 
135 
nrf_wifi_fmac_peers_flush(struct nrf_wifi_fmac_dev_ctx * fmac_dev_ctx,unsigned char if_idx)136 void nrf_wifi_fmac_peers_flush(struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx,
137 			       unsigned char if_idx)
138 {
139 	struct nrf_wifi_fmac_vif_ctx *vif_ctx = NULL;
140 	unsigned int i = 0;
141 	struct peers_info *peer = NULL;
142 	struct nrf_wifi_sys_fmac_dev_ctx *sys_dev_ctx = NULL;
143 
144 	sys_dev_ctx = wifi_dev_priv(fmac_dev_ctx);
145 
146 	vif_ctx = sys_dev_ctx->vif_ctx[if_idx];
147 	sys_dev_ctx->tx_config.peers[MAX_PEERS].peer_id = -1;
148 
149 	for (i = 0; i < MAX_PEERS; i++) {
150 		peer = &sys_dev_ctx->tx_config.peers[i];
151 
152 		if (peer->peer_id == -1)
153 			continue;
154 
155 		if (peer->if_idx == if_idx) {
156 
157 			nrf_wifi_osal_mem_set(peer,
158 					      0x0,
159 					      sizeof(struct peers_info));
160 			peer->peer_id = -1;
161 
162 			if (vif_ctx->if_type == NRF_WIFI_IFTYPE_AP) {
163 				hal_rpu_mem_write(fmac_dev_ctx->hal_dev_ctx,
164 						  (RPU_MEM_UMAC_PEND_Q_BMP +
165 						  sizeof(struct sap_client_pend_frames_bitmap) * i),
166 						  peer->ra_addr,
167 						  NRF_WIFI_FMAC_ETH_ADDR_LEN);
168 			}
169 		}
170 	}
171 }
172