1 /*
2  * Copyright (c) 2025 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 /**
8  * @brief File containing API definitions for the
9  * HAL Layer of the Wi-Fi driver in the system mode of operation.
10  */
11 
12 #include "queue.h"
13 #include "common/hal_structs_common.h"
14 #include "common/hal_common.h"
15 #include "common/hal_reg.h"
16 #include "common/hal_mem.h"
17 #include "common/hal_interrupt.h"
18 #include "common/pal.h"
19 #include "system/hal_api.h"
20 
21 
22 static enum nrf_wifi_status
nrf_wifi_sys_hal_rpu_pktram_buf_map_init(struct nrf_wifi_hal_dev_ctx * hal_dev_ctx)23 nrf_wifi_sys_hal_rpu_pktram_buf_map_init(struct nrf_wifi_hal_dev_ctx *hal_dev_ctx)
24 {
25 	enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
26 	unsigned int pool_idx = 0;
27 
28 	status = pal_rpu_addr_offset_get(RPU_MEM_PKT_BASE,
29 					 &hal_dev_ctx->addr_rpu_pktram_base,
30 					 hal_dev_ctx->curr_proc);
31 
32 	if (status != NRF_WIFI_STATUS_SUCCESS) {
33 		nrf_wifi_osal_log_err("%s: pal_rpu_addr_offset_get failed",
34 				      __func__);
35 		goto out;
36 	}
37 
38 	hal_dev_ctx->addr_rpu_pktram_base_tx = hal_dev_ctx->addr_rpu_pktram_base;
39 
40 	hal_dev_ctx->addr_rpu_pktram_base_rx_pool[0] =
41 		 (hal_dev_ctx->addr_rpu_pktram_base + RPU_PKTRAM_SIZE) -
42 		 (NRF70_RX_NUM_BUFS * NRF70_RX_MAX_DATA_SIZE);
43 
44 	for (pool_idx = 1; pool_idx < MAX_NUM_OF_RX_QUEUES; pool_idx++) {
45 		hal_dev_ctx->addr_rpu_pktram_base_rx_pool[pool_idx] =
46 			hal_dev_ctx->addr_rpu_pktram_base_rx_pool[pool_idx - 1] +
47 			(hal_dev_ctx->hpriv->cfg_params.rx_buf_pool[pool_idx - 1].num_bufs *
48 			 hal_dev_ctx->hpriv->cfg_params.rx_buf_pool[pool_idx - 1].buf_sz);
49 	}
50 
51 	status = NRF_WIFI_STATUS_SUCCESS;
52 out:
53 	return status;
54 }
55 
56 
event_tasklet_fn(unsigned long data)57 static void event_tasklet_fn(unsigned long data)
58 {
59 	enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
60 	struct nrf_wifi_hal_dev_ctx *hal_dev_ctx = NULL;
61 	unsigned long flags = 0;
62 
63 	hal_dev_ctx = (struct nrf_wifi_hal_dev_ctx *)data;
64 
65 	nrf_wifi_osal_spinlock_irq_take(hal_dev_ctx->lock_rx,
66 					&flags);
67 
68 	if (hal_dev_ctx->hal_status != NRF_WIFI_HAL_STATUS_ENABLED) {
69 		/* Ignore the interrupt if the HAL is not enabled */
70 		status = NRF_WIFI_STATUS_SUCCESS;
71 		goto out;
72 	}
73 
74 	status = hal_rpu_eventq_process(hal_dev_ctx);
75 
76 	if (status != NRF_WIFI_STATUS_SUCCESS) {
77 		nrf_wifi_osal_log_err("%s: Event queue processing failed",
78 				      __func__);
79 	}
80 
81 out:
82 	nrf_wifi_osal_spinlock_irq_rel(hal_dev_ctx->lock_rx,
83 				       &flags);
84 }
85 
86 
hal_rpu_recovery(struct nrf_wifi_hal_dev_ctx * hal_dev_ctx)87 static enum nrf_wifi_status hal_rpu_recovery(struct nrf_wifi_hal_dev_ctx *hal_dev_ctx)
88 {
89 	enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
90 
91 	if (!hal_dev_ctx->hpriv->rpu_recovery_callbk_fn) {
92 		nrf_wifi_osal_log_dbg("%s: RPU recovery callback not registered",
93 				      __func__);
94 		goto out;
95 	}
96 
97 	status = hal_dev_ctx->hpriv->rpu_recovery_callbk_fn(hal_dev_ctx->mac_dev_ctx, NULL, 0);
98 	if (status != NRF_WIFI_STATUS_SUCCESS) {
99 		nrf_wifi_osal_log_err("%s: RPU recovery failed",
100 				      __func__);
101 		goto out;
102 	}
103 
104 out:
105 	return status;
106 }
107 
recovery_tasklet_fn(unsigned long data)108 static void recovery_tasklet_fn(unsigned long data)
109 {
110 	struct nrf_wifi_hal_dev_ctx *hal_dev_ctx = NULL;
111 	unsigned long flags = 0;
112 
113 	hal_dev_ctx = (struct nrf_wifi_hal_dev_ctx *)data;
114 	if (!hal_dev_ctx) {
115 		nrf_wifi_osal_log_err("%s: Invalid hal_dev_ctx",
116 				      __func__);
117 		return;
118 	}
119 
120 	nrf_wifi_osal_spinlock_irq_take(hal_dev_ctx->lock_recovery,
121 					&flags);
122 	hal_rpu_recovery(hal_dev_ctx);
123 	nrf_wifi_osal_spinlock_irq_rel(hal_dev_ctx->lock_recovery,
124 				       &flags);
125 }
126 
127 
nrf_wifi_sys_hal_buf_map_rx(struct nrf_wifi_hal_dev_ctx * hal_dev_ctx,unsigned long buf,unsigned int buf_len,unsigned int pool_id,unsigned int buf_id)128 unsigned long nrf_wifi_sys_hal_buf_map_rx(struct nrf_wifi_hal_dev_ctx *hal_dev_ctx,
129 					  unsigned long buf,
130 					  unsigned int buf_len,
131 					  unsigned int pool_id,
132 					  unsigned int buf_id)
133 {
134 	struct nrf_wifi_hal_buf_map_info *rx_buf_info = NULL;
135 	unsigned long addr_to_map = 0;
136 	unsigned long bounce_buf_addr = 0;
137 	unsigned long rpu_addr = 0;
138 
139 	if (!hal_dev_ctx || !hal_dev_ctx->rx_buf_info[pool_id]) {
140 		nrf_wifi_osal_log_err("%s: Invalid parameters\n",
141 				      __func__);
142 		goto out;
143 	}
144 
145 	rx_buf_info = &hal_dev_ctx->rx_buf_info[pool_id][buf_id];
146 
147 	if (rx_buf_info->mapped) {
148 		nrf_wifi_osal_log_err("%s: Called for already mapped RX buffer",
149 				      __func__);
150 		goto out;
151 	}
152 
153 	rx_buf_info->virt_addr = buf;
154 	rx_buf_info->buf_len = buf_len;
155 
156 	if (buf_len != hal_dev_ctx->hpriv->cfg_params.rx_buf_pool[pool_id].buf_sz) {
157 		nrf_wifi_osal_log_err("%s: Invalid buf_len (%d) for pool_id (%d)",
158 				      __func__,
159 				      buf_len,
160 				      pool_id);
161 		goto out;
162 	}
163 
164 	bounce_buf_addr = hal_dev_ctx->addr_rpu_pktram_base_rx_pool[pool_id] +
165 		(buf_id * buf_len);
166 
167 	rpu_addr = RPU_MEM_PKT_BASE + (bounce_buf_addr - hal_dev_ctx->addr_rpu_pktram_base);
168 
169 	hal_rpu_mem_write(hal_dev_ctx,
170 			  (unsigned int)rpu_addr,
171 			  (void *)buf,
172 			  hal_dev_ctx->hpriv->cfg_params.rx_buf_headroom_sz);
173 
174 	addr_to_map = bounce_buf_addr + hal_dev_ctx->hpriv->cfg_params.rx_buf_headroom_sz;
175 
176 	rx_buf_info->phy_addr = nrf_wifi_bal_dma_map(hal_dev_ctx->bal_dev_ctx,
177 						     addr_to_map,
178 						     buf_len,
179 						     NRF_WIFI_OSAL_DMA_DIR_FROM_DEV);
180 
181 	if (!rx_buf_info->phy_addr) {
182 		nrf_wifi_osal_log_err("%s: DMA map failed",
183 				      __func__);
184 		goto out;
185 	}
186 
187 out:
188 	if (rx_buf_info->phy_addr) {
189 		rx_buf_info->mapped = true;
190 	}
191 
192 	return rx_buf_info->phy_addr;
193 }
194 
195 
nrf_wifi_sys_hal_buf_unmap_rx(struct nrf_wifi_hal_dev_ctx * hal_dev_ctx,unsigned int data_len,unsigned int pool_id,unsigned int buf_id)196 unsigned long nrf_wifi_sys_hal_buf_unmap_rx(struct nrf_wifi_hal_dev_ctx *hal_dev_ctx,
197 					    unsigned int data_len,
198 					    unsigned int pool_id,
199 					    unsigned int buf_id)
200 {
201 	struct nrf_wifi_hal_buf_map_info *rx_buf_info = NULL;
202 	unsigned long unmapped_addr = 0;
203 	unsigned long virt_addr = 0;
204 	unsigned long rpu_addr = 0;
205 
206 	rx_buf_info = &hal_dev_ctx->rx_buf_info[pool_id][buf_id];
207 
208 	if (!rx_buf_info->mapped) {
209 		nrf_wifi_osal_log_err("%s: Called for unmapped RX buffer",
210 				      __func__);
211 		goto out;
212 	}
213 
214 	unmapped_addr = nrf_wifi_bal_dma_unmap(hal_dev_ctx->bal_dev_ctx,
215 					       rx_buf_info->phy_addr,
216 					       rx_buf_info->buf_len,
217 					       NRF_WIFI_OSAL_DMA_DIR_FROM_DEV);
218 
219 	rpu_addr = RPU_MEM_PKT_BASE + (unmapped_addr - hal_dev_ctx->addr_rpu_pktram_base);
220 
221 	if (data_len) {
222 		if (!unmapped_addr) {
223 			nrf_wifi_osal_log_err("%s: DMA unmap failed",
224 					      __func__);
225 			goto out;
226 		}
227 
228 		hal_rpu_mem_read(hal_dev_ctx,
229 				 (void *)(rx_buf_info->virt_addr +
230 					  hal_dev_ctx->hpriv->cfg_params.rx_buf_headroom_sz),
231 				 (unsigned int)rpu_addr,
232 				 data_len);
233 	}
234 
235 	virt_addr = rx_buf_info->virt_addr;
236 
237 	nrf_wifi_osal_mem_set(rx_buf_info,
238 			      0,
239 			      sizeof(*rx_buf_info));
240 out:
241 	return virt_addr;
242 }
243 
244 
nrf_wifi_sys_hal_buf_map_tx(struct nrf_wifi_hal_dev_ctx * hal_dev_ctx,unsigned long buf,unsigned int buf_len,unsigned int desc_id,unsigned int token,unsigned int buf_indx)245 unsigned long nrf_wifi_sys_hal_buf_map_tx(struct nrf_wifi_hal_dev_ctx *hal_dev_ctx,
246 					  unsigned long buf,
247 					  unsigned int buf_len,
248 					  unsigned int desc_id,
249 					  unsigned int token,
250 					  unsigned int buf_indx)
251 {
252 	struct nrf_wifi_hal_buf_map_info *tx_buf_info = NULL;
253 	unsigned long addr_to_map = 0;
254 	unsigned long bounce_buf_addr = 0;
255 	unsigned long tx_token_base_addr = hal_dev_ctx->addr_rpu_pktram_base_tx +
256 		(token * hal_dev_ctx->hpriv->cfg_params.max_ampdu_len_per_token);
257 	unsigned long rpu_addr = 0;
258 
259 	tx_buf_info = &hal_dev_ctx->tx_buf_info[desc_id];
260 
261 	if (tx_buf_info->mapped) {
262 		nrf_wifi_osal_log_err("%s: Called for already mapped TX buffer",
263 				      __func__);
264 		goto out;
265 	}
266 
267 	tx_buf_info->virt_addr = buf;
268 
269 	if (buf_len > (hal_dev_ctx->hpriv->cfg_params.max_tx_frm_sz -
270 		       hal_dev_ctx->hpriv->cfg_params.tx_buf_headroom_sz)) {
271 		nrf_wifi_osal_log_err("%s: Invalid TX buf_len (%d) for (%d)",
272 				      __func__,
273 				      buf_len,
274 				      desc_id);
275 		goto out;
276 	}
277 
278 	if (buf_indx == 0) {
279 		hal_dev_ctx->tx_frame_offset = tx_token_base_addr;
280 	}
281 
282 	bounce_buf_addr = hal_dev_ctx->tx_frame_offset;
283 
284 	/* Align bounce buffer and buffer length to 4-byte boundary */
285 	bounce_buf_addr = (bounce_buf_addr + 3) & ~3;
286 	buf_len = (buf_len + 3) & ~3;
287 
288 	hal_dev_ctx->tx_frame_offset += (bounce_buf_addr - hal_dev_ctx->tx_frame_offset) +
289 		buf_len + hal_dev_ctx->hpriv->cfg_params.tx_buf_headroom_sz;
290 
291 	rpu_addr = RPU_MEM_PKT_BASE + (bounce_buf_addr - hal_dev_ctx->addr_rpu_pktram_base);
292 
293 	nrf_wifi_osal_log_dbg("%s: bounce_buf_addr: 0x%lx, rpu_addr: 0x%lx, buf_len: %d off:%d",
294 	       __func__,
295 	       bounce_buf_addr,
296 	       rpu_addr,
297 	       buf_len,
298 	       hal_dev_ctx->tx_frame_offset);
299 
300 	hal_rpu_mem_write(hal_dev_ctx,
301 			  (unsigned int)rpu_addr,
302 			  (void *)buf,
303 			  buf_len);
304 
305 	addr_to_map = bounce_buf_addr;
306 
307 	tx_buf_info->phy_addr = nrf_wifi_bal_dma_map(hal_dev_ctx->bal_dev_ctx,
308 						     addr_to_map,
309 						     buf_len,
310 						     NRF_WIFI_OSAL_DMA_DIR_TO_DEV);
311 
312 	if (!tx_buf_info->phy_addr) {
313 		nrf_wifi_osal_log_err("%s: DMA map failed",
314 				      __func__);
315 		goto out;
316 	}
317 	tx_buf_info->buf_len = buf_len;
318 
319 out:
320 	if (tx_buf_info->phy_addr) {
321 		tx_buf_info->mapped = true;
322 	}
323 
324 	return tx_buf_info->phy_addr;
325 }
326 
327 
nrf_wifi_sys_hal_buf_unmap_tx(struct nrf_wifi_hal_dev_ctx * hal_dev_ctx,unsigned int desc_id)328 unsigned long nrf_wifi_sys_hal_buf_unmap_tx(struct nrf_wifi_hal_dev_ctx *hal_dev_ctx,
329 					    unsigned int desc_id)
330 {
331 	struct nrf_wifi_hal_buf_map_info *tx_buf_info = NULL;
332 	unsigned long unmapped_addr = 0;
333 	unsigned long virt_addr = 0;
334 
335 	tx_buf_info = &hal_dev_ctx->tx_buf_info[desc_id];
336 
337 	if (!tx_buf_info->mapped) {
338 		nrf_wifi_osal_log_err("%s: Called for unmapped TX buffer",
339 				      __func__);
340 		goto out;
341 	}
342 
343 	unmapped_addr = nrf_wifi_bal_dma_unmap(hal_dev_ctx->bal_dev_ctx,
344 					       tx_buf_info->phy_addr,
345 					       tx_buf_info->buf_len,
346 					       NRF_WIFI_OSAL_DMA_DIR_TO_DEV);
347 
348 	if (!unmapped_addr) {
349 		nrf_wifi_osal_log_err("%s: DMA unmap failed",
350 				      __func__);
351 		goto out;
352 	}
353 
354 	virt_addr = tx_buf_info->virt_addr;
355 
356 	nrf_wifi_osal_mem_set(tx_buf_info,
357 			      0,
358 			      sizeof(*tx_buf_info));
359 out:
360 	return virt_addr;
361 }
362 
nrf_wifi_sys_hal_data_cmd_send(struct nrf_wifi_hal_dev_ctx * hal_dev_ctx,enum NRF_WIFI_HAL_MSG_TYPE cmd_type,void * cmd,unsigned int cmd_size,unsigned int desc_id,unsigned int pool_id)363 enum nrf_wifi_status nrf_wifi_sys_hal_data_cmd_send(struct nrf_wifi_hal_dev_ctx *hal_dev_ctx,
364 						    enum NRF_WIFI_HAL_MSG_TYPE cmd_type,
365 						    void *cmd,
366 						    unsigned int cmd_size,
367 						    unsigned int desc_id,
368 						    unsigned int pool_id)
369 {
370 	enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
371 	unsigned int addr_base = 0;
372 	unsigned int max_cmd_size = 0;
373 	unsigned int addr = 0;
374 	unsigned int host_addr = 0;
375 
376 
377 	nrf_wifi_osal_spinlock_take(hal_dev_ctx->lock_hal);
378 
379 	if (cmd_type == NRF_WIFI_HAL_MSG_TYPE_CMD_DATA_RX) {
380 		addr_base = hal_dev_ctx->rpu_info.rx_cmd_base;
381 		max_cmd_size = RPU_DATA_CMD_SIZE_MAX_RX;
382 	} else if (cmd_type == NRF_WIFI_HAL_MSG_TYPE_CMD_DATA_TX) {
383 		addr_base = hal_dev_ctx->rpu_info.tx_cmd_base;
384 		max_cmd_size = RPU_DATA_CMD_SIZE_MAX_TX;
385 	} else {
386 		nrf_wifi_osal_log_err("%s: Invalid data command type %d",
387 				      __func__,
388 				      cmd_type);
389 	}
390 
391 	addr = addr_base + (max_cmd_size * desc_id);
392 	host_addr = addr;
393 
394 	/* This is a indrect write to core memory */
395 	if (cmd_type == NRF_WIFI_HAL_MSG_TYPE_CMD_DATA_RX) {
396 		host_addr &= RPU_ADDR_MASK_OFFSET;
397 		host_addr |= RPU_MCU_CORE_INDIRECT_BASE;
398 	}
399 
400 	/* Copy the information to the suggested address */
401 	status = hal_rpu_mem_write(hal_dev_ctx,
402 				   host_addr,
403 				   cmd,
404 				   cmd_size);
405 
406 	if (status != NRF_WIFI_STATUS_SUCCESS) {
407 		nrf_wifi_osal_log_err("%s: Copying data cmd(%d) to RPU failed",
408 				      __func__,
409 				      cmd_type);
410 		goto out;
411 	}
412 
413 	/* Post the updated information to the RPU */
414 	status = hal_rpu_msg_post(hal_dev_ctx,
415 				  cmd_type,
416 				  pool_id,
417 				  addr);
418 
419 	if (status != NRF_WIFI_STATUS_SUCCESS) {
420 		nrf_wifi_osal_log_err("%s: Posting RX buf info to RPU failed",
421 				      __func__);
422 		goto out;
423 	}
424 out:
425 	nrf_wifi_osal_spinlock_rel(hal_dev_ctx->lock_hal);
426 
427 
428 	return status;
429 }
430 
431 
nrf_wifi_sys_hal_dev_add(struct nrf_wifi_hal_priv * hpriv,void * mac_dev_ctx)432 struct nrf_wifi_hal_dev_ctx *nrf_wifi_sys_hal_dev_add(struct nrf_wifi_hal_priv *hpriv,
433 						      void *mac_dev_ctx)
434 {
435 	enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
436 	struct nrf_wifi_hal_dev_ctx *hal_dev_ctx = NULL;
437 	unsigned int i = 0;
438 	unsigned int num_rx_bufs = 0;
439 	unsigned int size = 0;
440 
441 	hal_dev_ctx = nrf_wifi_osal_mem_zalloc(sizeof(*hal_dev_ctx));
442 
443 	if (!hal_dev_ctx) {
444 		nrf_wifi_osal_log_err("%s: Unable to allocate hal_dev_ctx",
445 				      __func__);
446 		goto err;
447 	}
448 
449 	hal_dev_ctx->hpriv = hpriv;
450 	hal_dev_ctx->mac_dev_ctx = mac_dev_ctx;
451 	hal_dev_ctx->idx = hpriv->num_devs++;
452 
453 	hal_dev_ctx->num_cmds = RPU_CMD_START_MAGIC;
454 
455 	hal_dev_ctx->cmd_q = nrf_wifi_utils_q_alloc();
456 
457 	if (!hal_dev_ctx->cmd_q) {
458 		nrf_wifi_osal_log_err("%s: Unable to allocate command queue",
459 				      __func__);
460 		goto hal_dev_free;
461 	}
462 
463 	hal_dev_ctx->event_q = nrf_wifi_utils_q_alloc();
464 
465 	if (!hal_dev_ctx->event_q) {
466 		nrf_wifi_osal_log_err("%s: Unable to allocate event queue",
467 				      __func__);
468 		goto cmd_q_free;
469 	}
470 
471 	hal_dev_ctx->lock_hal = nrf_wifi_osal_spinlock_alloc();
472 
473 	if (!hal_dev_ctx->lock_hal) {
474 		nrf_wifi_osal_log_err("%s: Unable to allocate HAL lock", __func__);
475 		hal_dev_ctx = NULL;
476 		goto event_q_free;
477 	}
478 
479 	nrf_wifi_osal_spinlock_init(hal_dev_ctx->lock_hal);
480 
481 	hal_dev_ctx->lock_rx = nrf_wifi_osal_spinlock_alloc();
482 
483 	if (!hal_dev_ctx->lock_rx) {
484 		nrf_wifi_osal_log_err("%s: Unable to allocate HAL lock",
485 				      __func__);
486 		goto lock_hal_free;
487 	}
488 
489 	nrf_wifi_osal_spinlock_init(hal_dev_ctx->lock_rx);
490 
491 	hal_dev_ctx->event_tasklet = nrf_wifi_osal_tasklet_alloc(NRF_WIFI_TASKLET_TYPE_BH);
492 
493 	if (!hal_dev_ctx->event_tasklet) {
494 		nrf_wifi_osal_log_err("%s: Unable to allocate event_tasklet",
495 				      __func__);
496 		goto lock_rx_free;
497 	}
498 
499 	nrf_wifi_osal_tasklet_init(hal_dev_ctx->event_tasklet,
500 				   event_tasklet_fn,
501 				   (unsigned long)hal_dev_ctx);
502 
503 	hal_dev_ctx->recovery_tasklet = nrf_wifi_osal_tasklet_alloc(NRF_WIFI_TASKLET_TYPE_BH);
504 	if (!hal_dev_ctx->recovery_tasklet) {
505 		nrf_wifi_osal_log_err("%s: Unable to allocate recovery_tasklet",
506 				      __func__);
507 		goto event_tasklet_free;
508 	}
509 	nrf_wifi_osal_tasklet_init(hal_dev_ctx->recovery_tasklet,
510 				   recovery_tasklet_fn,
511 				   (unsigned long)hal_dev_ctx);
512 
513 	hal_dev_ctx->lock_recovery = nrf_wifi_osal_spinlock_alloc();
514 	if (!hal_dev_ctx->lock_recovery) {
515 		nrf_wifi_osal_log_err("%s: Unable to allocate recovery lock",
516 				      __func__);
517 		goto recovery_tasklet_free;
518 	}
519 
520 	nrf_wifi_osal_spinlock_init(hal_dev_ctx->lock_recovery);
521 #ifdef NRF_WIFI_LOW_POWER
522 	status = hal_rpu_ps_init(hal_dev_ctx);
523 
524 	if (status != NRF_WIFI_STATUS_SUCCESS) {
525 		nrf_wifi_osal_log_err("%s: hal_rpu_ps_init failed",
526 				      __func__);
527 		goto lock_recovery_free;
528 	}
529 #endif /* NRF_WIFI_LOW_POWER */
530 
531 	hal_dev_ctx->bal_dev_ctx = nrf_wifi_bal_dev_add(hpriv->bpriv,
532 							hal_dev_ctx);
533 
534 	if (!hal_dev_ctx->bal_dev_ctx) {
535 		nrf_wifi_osal_log_err("%s: nrf_wifi_bal_dev_add failed",
536 				      __func__);
537 		goto lock_recovery_free;
538 	}
539 
540 	status = hal_rpu_irq_enable(hal_dev_ctx);
541 
542 	if (status != NRF_WIFI_STATUS_SUCCESS) {
543 		nrf_wifi_osal_log_err("%s: hal_rpu_irq_enable failed",
544 				      __func__);
545 		goto bal_dev_free;
546 	}
547 
548 	for (i = 0; i < MAX_NUM_OF_RX_QUEUES; i++) {
549 		num_rx_bufs = hal_dev_ctx->hpriv->cfg_params.rx_buf_pool[i].num_bufs;
550 
551 		size = (num_rx_bufs * sizeof(struct nrf_wifi_hal_buf_map_info));
552 
553 		hal_dev_ctx->rx_buf_info[i] = nrf_wifi_osal_mem_zalloc(size);
554 
555 		if (!hal_dev_ctx->rx_buf_info[i]) {
556 			nrf_wifi_osal_log_err("%s: No space for RX buf info[%d]",
557 					      __func__,
558 					      i);
559 			goto bal_dev_free;
560 		}
561 	}
562 #ifdef NRF70_DATA_TX
563 	size = (hal_dev_ctx->hpriv->cfg_params.max_tx_frms *
564 		sizeof(struct nrf_wifi_hal_buf_map_info));
565 
566 	hal_dev_ctx->tx_buf_info = nrf_wifi_osal_mem_zalloc(size);
567 
568 	if (!hal_dev_ctx->tx_buf_info) {
569 		nrf_wifi_osal_log_err("%s: No space for TX buf info",
570 				      __func__);
571 		goto rx_buf_free;
572 	}
573 #endif /* NRF70_DATA_TX */
574 
575 	status = nrf_wifi_sys_hal_rpu_pktram_buf_map_init(hal_dev_ctx);
576 
577 	if (status != NRF_WIFI_STATUS_SUCCESS) {
578 		nrf_wifi_osal_log_err("%s: Buffer map init failed",
579 				      __func__);
580 #ifdef NRF70_DATA_TX
581 		goto tx_buf_free;
582 #endif /* NRF70_DATA_TX */
583 	}
584 
585 	return hal_dev_ctx;
586 
587 #ifdef NRF70_DATA_TX
588 tx_buf_free:
589 	nrf_wifi_osal_mem_free(hal_dev_ctx->tx_buf_info);
590 	hal_dev_ctx->tx_buf_info = NULL;
591 rx_buf_free:
592 
593 	for (i = 0; i < MAX_NUM_OF_RX_QUEUES; i++) {
594 		nrf_wifi_osal_mem_free(hal_dev_ctx->rx_buf_info[i]);
595 		hal_dev_ctx->rx_buf_info[i] = NULL;
596 	}
597 #endif /* NRF70_DATA_TX */
598 bal_dev_free:
599 	nrf_wifi_bal_dev_rem(hal_dev_ctx->bal_dev_ctx);
600 lock_recovery_free:
601 	nrf_wifi_osal_spinlock_free(hal_dev_ctx->lock_recovery);
602 recovery_tasklet_free:
603 	nrf_wifi_osal_tasklet_free(hal_dev_ctx->recovery_tasklet);
604 event_tasklet_free:
605 	nrf_wifi_osal_tasklet_free(hal_dev_ctx->event_tasklet);
606 lock_rx_free:
607 	nrf_wifi_osal_spinlock_free(hal_dev_ctx->lock_rx);
608 lock_hal_free:
609 	nrf_wifi_osal_spinlock_free(hal_dev_ctx->lock_hal);
610 event_q_free:
611 	nrf_wifi_utils_q_free(hal_dev_ctx->event_q);
612 cmd_q_free:
613 	nrf_wifi_utils_q_free(hal_dev_ctx->cmd_q);
614 hal_dev_free:
615 	nrf_wifi_osal_mem_free(hal_dev_ctx);
616 	hal_dev_ctx = NULL;
617 err:
618 	return NULL;
619 }
620 
621 
nrf_wifi_sys_hal_lock_rx(struct nrf_wifi_hal_dev_ctx * hal_dev_ctx)622 void nrf_wifi_sys_hal_lock_rx(struct nrf_wifi_hal_dev_ctx *hal_dev_ctx)
623 {
624 	unsigned long flags = 0;
625 
626 	nrf_wifi_osal_spinlock_irq_take(hal_dev_ctx->lock_rx,
627 					&flags);
628 }
629 
nrf_wifi_sys_hal_unlock_rx(struct nrf_wifi_hal_dev_ctx * hal_dev_ctx)630 void nrf_wifi_sys_hal_unlock_rx(struct nrf_wifi_hal_dev_ctx *hal_dev_ctx)
631 {
632 	unsigned long flags = 0;
633 
634 	nrf_wifi_osal_spinlock_irq_rel(hal_dev_ctx->lock_rx,
635 				       &flags);
636 }