1 /*
2 * Copyright (c) 2024 Nordic Semiconductor ASA
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7 /**
8 * @brief File containing interrupt handler specific definitions for the
9 * HAL Layer of the Wi-Fi driver.
10 */
11
12 #include "queue.h"
13 #include "common/hal_reg.h"
14 #include "common/hal_mem.h"
15 #include "common/hal_common.h"
16 #include "common/hal_interrupt.h"
17
18
hal_rpu_irq_enable(struct nrf_wifi_hal_dev_ctx * hal_dev_ctx)19 enum nrf_wifi_status hal_rpu_irq_enable(struct nrf_wifi_hal_dev_ctx *hal_dev_ctx)
20 {
21 enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
22 unsigned int val = 0;
23
24 /* First enable the blockwise interrupt for the relevant block in the
25 * master register
26 */
27 status = hal_rpu_reg_read(hal_dev_ctx,
28 &val,
29 RPU_REG_INT_FROM_RPU_CTRL);
30
31 if (status != NRF_WIFI_STATUS_SUCCESS) {
32 nrf_wifi_osal_log_err("%s: Reading from Root interrupt register failed",
33 __func__);
34 goto out;
35 }
36
37 val |= (1 << RPU_REG_BIT_INT_FROM_RPU_CTRL);
38
39 status = hal_rpu_reg_write(hal_dev_ctx,
40 RPU_REG_INT_FROM_RPU_CTRL,
41 val);
42
43 if (status != NRF_WIFI_STATUS_SUCCESS) {
44 nrf_wifi_osal_log_err("%s: Enabling Root interrupt failed",
45 __func__);
46 goto out;
47 }
48
49 /* Now enable the relevant MCU interrupt line */
50 val = (1 << RPU_REG_BIT_INT_FROM_MCU_CTRL);
51
52 status = hal_rpu_reg_write(hal_dev_ctx,
53 RPU_REG_INT_FROM_MCU_CTRL,
54 val);
55
56 if (status != NRF_WIFI_STATUS_SUCCESS) {
57 nrf_wifi_osal_log_err("%s:Enabling MCU interrupt failed",
58 __func__);
59 goto out;
60 }
61
62 out:
63 return status;
64 }
65
66
hal_rpu_irq_disable(struct nrf_wifi_hal_dev_ctx * hal_dev_ctx)67 enum nrf_wifi_status hal_rpu_irq_disable(struct nrf_wifi_hal_dev_ctx *hal_dev_ctx)
68 {
69 enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
70 unsigned int val = 0;
71
72 status = hal_rpu_reg_read(hal_dev_ctx,
73 &val,
74 RPU_REG_INT_FROM_RPU_CTRL);
75
76 if (status != NRF_WIFI_STATUS_SUCCESS) {
77 nrf_wifi_osal_log_err("%s: Reading from Root interrupt register failed",
78 __func__);
79 goto out;
80 }
81
82 val &= ~((unsigned int)(1 << RPU_REG_BIT_INT_FROM_RPU_CTRL));
83
84 status = hal_rpu_reg_write(hal_dev_ctx,
85 RPU_REG_INT_FROM_RPU_CTRL,
86 val);
87
88 if (status != NRF_WIFI_STATUS_SUCCESS) {
89 nrf_wifi_osal_log_err("%s: Disabling Root interrupt failed",
90 __func__);
91 goto out;
92 }
93
94 val = ~((unsigned int)(1 << RPU_REG_BIT_INT_FROM_MCU_CTRL));
95
96 status = hal_rpu_reg_write(hal_dev_ctx,
97 RPU_REG_INT_FROM_MCU_CTRL,
98 val);
99
100 if (status != NRF_WIFI_STATUS_SUCCESS) {
101 nrf_wifi_osal_log_err("%s: Disabling MCU interrupt failed",
102 __func__);
103 goto out;
104 }
105
106 out:
107 return status;
108 }
109
110
hal_rpu_irq_ack(struct nrf_wifi_hal_dev_ctx * hal_dev_ctx)111 static enum nrf_wifi_status hal_rpu_irq_ack(struct nrf_wifi_hal_dev_ctx *hal_dev_ctx)
112 {
113 enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
114 unsigned int val = 0;
115
116 val = (1 << RPU_REG_BIT_INT_FROM_MCU_ACK);
117
118 status = hal_rpu_reg_write(hal_dev_ctx,
119 RPU_REG_INT_FROM_MCU_ACK,
120 val);
121
122 return status;
123 }
124
125
hal_rpu_irq_wdog_chk(struct nrf_wifi_hal_dev_ctx * hal_dev_ctx)126 static bool hal_rpu_irq_wdog_chk(struct nrf_wifi_hal_dev_ctx *hal_dev_ctx)
127 {
128 enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
129 unsigned int val = 0;
130 bool ret = false;
131 unsigned int i, max_read_retries = 10;
132
133 for (i = 0; i < max_read_retries; i++) {
134 status = hal_rpu_reg_read(hal_dev_ctx,
135 &val,
136 RPU_REG_MIPS_MCU_UCCP_INT_STATUS);
137
138 if (status != NRF_WIFI_STATUS_SUCCESS) {
139 nrf_wifi_osal_log_err("%s: Reading from interrupt status register failed\n",
140 __func__);
141 goto out;
142 }
143
144 if (val != 0xAAAAAAAA) {
145 break;
146 }
147
148 nrf_wifi_osal_log_err("%s: Reading from interrupt status register failed 0x%x\n",
149 __func__,
150 val);
151 }
152
153 if (i == max_read_retries) {
154 nrf_wifi_osal_log_err("%s: Reading from interrupt status register failed 0x%x\n",
155 __func__,
156 val);
157 goto out;
158 }
159
160 if (val & (1 << RPU_REG_BIT_MIPS_WATCHDOG_INT_STATUS)) {
161 ret = true;
162 }
163 out:
164 return ret;
165
166 }
167
168
hal_rpu_irq_wdog_ack(struct nrf_wifi_hal_dev_ctx * hal_dev_ctx)169 static enum nrf_wifi_status hal_rpu_irq_wdog_ack(struct nrf_wifi_hal_dev_ctx *hal_dev_ctx)
170 {
171 enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
172
173 status = hal_rpu_reg_write(hal_dev_ctx,
174 RPU_REG_MIPS_MCU_UCCP_INT_CLEAR,
175 1 << RPU_REG_BIT_MIPS_WATCHDOG_INT_CLEAR);
176
177 if (status != NRF_WIFI_STATUS_SUCCESS) {
178 nrf_wifi_osal_log_err("%s: Acknowledging watchdog interrupt failed",
179 __func__);
180 goto out;
181 }
182
183 out:
184 return status;
185
186 }
187
hal_rpu_irq_wdog_rearm(struct nrf_wifi_hal_dev_ctx * hal_dev_ctx)188 static enum nrf_wifi_status hal_rpu_irq_wdog_rearm(struct nrf_wifi_hal_dev_ctx *hal_dev_ctx)
189 {
190 enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
191
192 status = hal_rpu_reg_write(hal_dev_ctx,
193 RPU_REG_MIPS_MCU_TIMER,
194 RPU_REG_MIPS_MCU_TIMER_RESET_VAL);
195
196 if (status != NRF_WIFI_STATUS_SUCCESS) {
197 nrf_wifi_osal_log_err("%s: Rearming watchdog interrupt failed",
198 __func__);
199 goto out;
200 }
201 out:
202 return status;
203 }
204
205
hal_rpu_event_free(struct nrf_wifi_hal_dev_ctx * hal_dev_ctx,unsigned int event_addr)206 static enum nrf_wifi_status hal_rpu_event_free(struct nrf_wifi_hal_dev_ctx *hal_dev_ctx,
207 unsigned int event_addr)
208 {
209 enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
210
211 status = hal_rpu_hpq_enqueue(hal_dev_ctx,
212 &hal_dev_ctx->rpu_info.hpqm_info.event_avl_queue,
213 event_addr);
214
215 if (status != NRF_WIFI_STATUS_SUCCESS) {
216 nrf_wifi_osal_log_err("%s: Enqueueing of event failed",
217 __func__);
218 goto out;
219 }
220
221 out:
222 return status;
223 }
224
225
hal_rpu_event_get(struct nrf_wifi_hal_dev_ctx * hal_dev_ctx,unsigned int event_addr)226 static enum nrf_wifi_status hal_rpu_event_get(struct nrf_wifi_hal_dev_ctx *hal_dev_ctx,
227 unsigned int event_addr)
228 {
229 enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
230 struct nrf_wifi_hal_msg *event = NULL;
231 struct host_rpu_msg_hdr *rpu_msg_hdr = NULL;
232 unsigned int rpu_msg_len = 0;
233 unsigned int event_data_size = 0;
234 /* QSPI : avoid global vars as they can be unaligned */
235 unsigned char event_data_typical[RPU_EVENT_COMMON_SIZE_MAX];
236
237 nrf_wifi_osal_mem_set(event_data_typical,
238 0,
239 sizeof(event_data_typical));
240
241 if (!hal_dev_ctx->event_data_pending) {
242 /* Copy data worth the maximum size of frequently occurring events from
243 * the RPU to a local buffer
244 */
245 status = hal_rpu_mem_read(hal_dev_ctx,
246 event_data_typical,
247 event_addr,
248 sizeof(event_data_typical));
249
250 if (status != NRF_WIFI_STATUS_SUCCESS) {
251 nrf_wifi_osal_log_err("%s: Reading of the event failed",
252 __func__);
253 goto out;
254 }
255
256 rpu_msg_hdr = (struct host_rpu_msg_hdr *)event_data_typical;
257
258 rpu_msg_len = rpu_msg_hdr->len;
259
260 /* Allocate space to assemble the entire event */
261 hal_dev_ctx->event_data = nrf_wifi_osal_mem_zalloc(rpu_msg_len);
262
263 if (!hal_dev_ctx->event_data) {
264 nrf_wifi_osal_log_err("%s: Unable to alloc buff for event data",
265 __func__);
266 goto out;
267 } else {
268 hal_dev_ctx->event_data_curr = hal_dev_ctx->event_data;
269 }
270
271 hal_dev_ctx->event_data_len = rpu_msg_len;
272 hal_dev_ctx->event_data_pending = rpu_msg_len;
273 hal_dev_ctx->event_resubmit = rpu_msg_hdr->resubmit;
274
275 /* Fragmented event */
276 if (rpu_msg_len > hal_dev_ctx->hpriv->cfg_params.max_event_size) {
277 status = hal_rpu_mem_read(hal_dev_ctx,
278 hal_dev_ctx->event_data_curr,
279 event_addr,
280 hal_dev_ctx->hpriv->cfg_params.max_event_size);
281
282
283 if (status != NRF_WIFI_STATUS_SUCCESS) {
284 nrf_wifi_osal_log_err("%s: Reading of first event fragment failed",
285 __func__);
286 nrf_wifi_osal_mem_free(hal_dev_ctx->event_data);
287 hal_dev_ctx->event_data = NULL;
288 goto out;
289 }
290
291 /* Free up the event in the RPU if necessary */
292 if (hal_dev_ctx->event_resubmit) {
293 status = hal_rpu_event_free(hal_dev_ctx,
294 event_addr);
295
296 if (status != NRF_WIFI_STATUS_SUCCESS) {
297 nrf_wifi_osal_log_err("%s: Freeing up of the event failed",
298 __func__);
299 nrf_wifi_osal_mem_free(hal_dev_ctx->event_data);
300 hal_dev_ctx->event_data = NULL;
301 goto out;
302 }
303 }
304
305 hal_dev_ctx->event_data_pending -=
306 hal_dev_ctx->hpriv->cfg_params.max_event_size;
307 hal_dev_ctx->event_data_curr +=
308 hal_dev_ctx->hpriv->cfg_params.max_event_size;
309 } else {
310 /* If this is not part of a fragmented event check if we need to
311 * copy any additional data i.e. if the event is a corner case
312 * event of large size.
313 */
314 if (rpu_msg_len > RPU_EVENT_COMMON_SIZE_MAX) {
315 status = hal_rpu_mem_read(hal_dev_ctx,
316 hal_dev_ctx->event_data_curr,
317 event_addr,
318 rpu_msg_len);
319
320 if (status != NRF_WIFI_STATUS_SUCCESS) {
321 nrf_wifi_osal_log_err("%s: Reading of large event failed",
322 __func__);
323 nrf_wifi_osal_mem_free(hal_dev_ctx->event_data);
324 hal_dev_ctx->event_data = NULL;
325 goto out;
326 }
327 } else {
328 nrf_wifi_osal_mem_cpy(hal_dev_ctx->event_data_curr,
329 event_data_typical,
330 rpu_msg_len);
331 }
332
333 /* Free up the event in the RPU if necessary */
334 if (hal_dev_ctx->event_resubmit) {
335 status = hal_rpu_event_free(hal_dev_ctx,
336 event_addr);
337
338 if (status != NRF_WIFI_STATUS_SUCCESS) {
339 nrf_wifi_osal_log_err("%s: Freeing up of the event failed",
340 __func__);
341 nrf_wifi_osal_mem_free(hal_dev_ctx->event_data);
342 hal_dev_ctx->event_data = NULL;
343 goto out;
344 }
345 }
346
347 hal_dev_ctx->event_data_pending -= rpu_msg_len;
348 hal_dev_ctx->event_data_curr += rpu_msg_len;
349
350 }
351 } else {
352 event_data_size = (hal_dev_ctx->event_data_pending >
353 hal_dev_ctx->hpriv->cfg_params.max_event_size) ?
354 hal_dev_ctx->hpriv->cfg_params.max_event_size :
355 hal_dev_ctx->event_data_pending;
356
357 if (hal_dev_ctx->event_data) {
358 status = hal_rpu_mem_read(hal_dev_ctx,
359 hal_dev_ctx->event_data_curr,
360 event_addr,
361 event_data_size);
362
363 if (status != NRF_WIFI_STATUS_SUCCESS) {
364 nrf_wifi_osal_log_err("%s: Reading of large event failed",
365 __func__);
366 nrf_wifi_osal_mem_free(hal_dev_ctx->event_data);
367 hal_dev_ctx->event_data = NULL;
368 goto out;
369 }
370 }
371
372 /* Free up the event in the RPU if necessary */
373 if (hal_dev_ctx->event_resubmit) {
374 status = hal_rpu_event_free(hal_dev_ctx,
375 event_addr);
376
377 if (status != NRF_WIFI_STATUS_SUCCESS) {
378 nrf_wifi_osal_log_err("%s: Freeing up of the event failed",
379 __func__);
380 nrf_wifi_osal_mem_free(hal_dev_ctx->event_data);
381 hal_dev_ctx->event_data = NULL;
382 goto out;
383 }
384 }
385
386 hal_dev_ctx->event_data_pending -= event_data_size;
387 hal_dev_ctx->event_data_curr += event_data_size;
388 }
389
390 /* This is either a unfragmented event or the last fragment of a
391 * fragmented event
392 */
393 if (!hal_dev_ctx->event_data_pending) {
394 event = nrf_wifi_osal_mem_zalloc(sizeof(*event) + hal_dev_ctx->event_data_len);
395
396 if (!event) {
397 nrf_wifi_osal_log_err("%s: Unable to alloc HAL msg for event (%d bytes)",
398 __func__,
399 hal_dev_ctx->event_data_len);
400 nrf_wifi_osal_mem_free(hal_dev_ctx->event_data);
401 hal_dev_ctx->event_data = NULL;
402 goto out;
403 }
404
405 nrf_wifi_osal_mem_cpy(event->data,
406 hal_dev_ctx->event_data,
407 hal_dev_ctx->event_data_len);
408
409 event->len = hal_dev_ctx->event_data_len;
410
411 status = nrf_wifi_utils_q_enqueue(hal_dev_ctx->event_q,
412 event);
413
414 if (status != NRF_WIFI_STATUS_SUCCESS) {
415 nrf_wifi_osal_log_err("%s: Unable to queue event",
416 __func__);
417 nrf_wifi_osal_mem_free(event);
418 event = NULL;
419 nrf_wifi_osal_mem_free(hal_dev_ctx->event_data);
420 hal_dev_ctx->event_data = NULL;
421 goto out;
422 }
423
424 /* Reset the state variables */
425 nrf_wifi_osal_mem_free(hal_dev_ctx->event_data);
426 hal_dev_ctx->event_data = NULL;
427 hal_dev_ctx->event_data_curr = NULL;
428 hal_dev_ctx->event_data_len = 0;
429 hal_dev_ctx->event_resubmit = 0;
430 }
431 out:
432 return status;
433 }
434
435
hal_rpu_event_get_all(struct nrf_wifi_hal_dev_ctx * hal_dev_ctx)436 static unsigned int hal_rpu_event_get_all(struct nrf_wifi_hal_dev_ctx *hal_dev_ctx)
437 {
438 enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
439 unsigned int num_events = 0;
440 unsigned int event_addr = 0;
441
442 while (1) {
443 event_addr = 0;
444
445 /* First get the event address */
446 status = hal_rpu_hpq_dequeue(hal_dev_ctx,
447 &hal_dev_ctx->rpu_info.hpqm_info.event_busy_queue,
448 &event_addr);
449
450 if (status != NRF_WIFI_STATUS_SUCCESS) {
451 nrf_wifi_osal_log_err("%s: Failed to get event addr",
452 __func__);
453 goto out;
454 }
455
456 /* No more events to read. Sometimes when low power mode is enabled
457 * we see a wrong address, but it work after a while, so, add a
458 * check for that.
459 */
460 if (!event_addr || event_addr == 0xAAAAAAAA) {
461 break;
462 }
463
464 /* Now get the event for further processing */
465 status = hal_rpu_event_get(hal_dev_ctx,
466 event_addr);
467
468 if (status != NRF_WIFI_STATUS_SUCCESS) {
469 nrf_wifi_osal_log_err("%s: Failed to queue event",
470 __func__);
471 goto out;
472 }
473
474 num_events++;
475 }
476
477 out:
478 return num_events;
479 }
480
481 #ifdef NRF_WIFI_RPU_RECOVERY
is_rpu_recovery_needed(struct nrf_wifi_hal_dev_ctx * hal_dev_ctx)482 static inline bool is_rpu_recovery_needed(struct nrf_wifi_hal_dev_ctx *hal_dev_ctx)
483 {
484 unsigned int rpu_sleep_opp_diff_ms = nrf_wifi_osal_time_elapsed_ms(
485 hal_dev_ctx->last_rpu_sleep_opp_time_ms);
486
487 #ifdef WIFI_RPU_RECOVERY_DEBUG
488 nrf_wifi_osal_log_info(
489 "RPU sleep opp diff: %d ms, last RPU sleep opp time: %lu",
490 rpu_sleep_opp_diff_ms,
491 hal_dev_ctx->last_rpu_sleep_opp_time_ms);
492 #else
493 nrf_wifi_osal_log_dbg(
494 "RPU sleep opp diff: %d ms, last RPU sleep opp time: %lu",
495 rpu_sleep_opp_diff_ms,
496 hal_dev_ctx->last_rpu_sleep_opp_time_ms);
497 #endif /* WIFI_RPU_RECOVERY_DEBUG */
498
499 if (rpu_sleep_opp_diff_ms >= NRF_WIFI_RPU_RECOVERY_PS_ACTIVE_TIMEOUT_MS) {
500 return false;
501 }
502
503 return true;
504 }
505 #endif /* NRF_WIFI_RPU_RECOVERY */
506
hal_rpu_process_wdog(struct nrf_wifi_hal_dev_ctx * hal_dev_ctx,bool * do_rpu_recovery)507 static enum nrf_wifi_status hal_rpu_process_wdog(struct nrf_wifi_hal_dev_ctx *hal_dev_ctx,
508 bool *do_rpu_recovery)
509 {
510 enum nrf_wifi_status nrf_wifi_status = NRF_WIFI_STATUS_FAIL;
511 bool rpu_recovery = false;
512
513 #ifdef WIFI_RPU_RECOVERY_DEBUG
514 nrf_wifi_osal_log_info("Processing watchdog interrupt");
515 #else
516 nrf_wifi_osal_log_dbg("Processing watchdog interrupt");
517 #endif
518
519 #ifdef NRF_WIFI_RPU_RECOVERY
520 /* Check if host has asserted WAKEUP_NOW or if the RPU has been in
521 * PS_ACTIVE state for more than the timeout period
522 */
523 if (!is_rpu_recovery_needed(hal_dev_ctx)) {
524 hal_dev_ctx->wdt_irq_ignored++;
525 #ifdef NRF_WIFI_RPU_RECOVERY_DEBUG
526 nrf_wifi_osal_log_info("Ignore watchdog interrupt, RPU recovery not needed");
527 #else
528 nrf_wifi_osal_log_dbg("Ignore watchdog interrupt, RPU recovery not needed");
529 #endif /* NRF_WIFI_RPU_RECOVERY_DEBUG */
530 goto out;
531 }
532
533 rpu_recovery = true;
534 #endif /* NRF_WIFI_RPU_RECOVERY */
535
536 if (!rpu_recovery) {
537 hal_rpu_irq_wdog_rearm(hal_dev_ctx);
538 goto out;
539 }
540
541
542 #ifdef NRF_WIFI_RPU_RECOVERY
543 #ifdef NRF_WIFI_RPU_RECOVERY_DEBUG
544 nrf_wifi_osal_log_info("RPU recovery needed");
545 #else
546 nrf_wifi_osal_log_dbg("RPU recovery needed");
547 #endif /* NRF_WIFI_RPU_RECOVERY_DEBUG */
548 #endif /* NRF_WIFI_RPU_RECOVERY */
549 out:
550 /* TODO: Ideally this should be done after successful recovery */
551 hal_rpu_irq_wdog_rearm(hal_dev_ctx);
552
553
554 nrf_wifi_status = NRF_WIFI_STATUS_SUCCESS;
555 *do_rpu_recovery = rpu_recovery;
556
557 return nrf_wifi_status;
558 }
559
hal_rpu_irq_process(struct nrf_wifi_hal_dev_ctx * hal_dev_ctx,bool * do_rpu_recovery)560 enum nrf_wifi_status hal_rpu_irq_process(struct nrf_wifi_hal_dev_ctx *hal_dev_ctx,
561 bool *do_rpu_recovery)
562 {
563 enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
564 unsigned int num_events = 0;
565
566
567 /* Get all the events in the queue. It is possible that there are no
568 * events in the queue. This is a valid scenario as per our present
569 * design (as discussed with LMAC team), since the RPU will raise
570 * interrupts for every event, irrespective of whether the host has
571 * acknowledged the previous event or not. This is being done to
572 * address an issue with FPGA platform where some interrupts are
573 * getting lost. Also RPU does not provide a register to check if
574 * the interrupt is from the RPU, so presently host cannot identify
575 * the interrupt source. This will be a problem in shared interrupt
576 * scenarios and has to be taken care by the SOC designers.
577 */
578 num_events = hal_rpu_event_get_all(hal_dev_ctx);
579
580 if (hal_rpu_irq_wdog_chk(hal_dev_ctx)) {
581 #ifdef NRF_WIFI_RPU_RECOVERY
582 hal_dev_ctx->wdt_irq_received++;
583 #endif /* NRF_WIFI_RPU_RECOVERY */
584 nrf_wifi_osal_log_dbg("Received watchdog interrupt");
585
586 status = hal_rpu_process_wdog(hal_dev_ctx, do_rpu_recovery);
587 if (status == NRF_WIFI_STATUS_FAIL) {
588 nrf_wifi_osal_log_err("%s: hal_rpu_process_wdog failed",
589 __func__);
590 goto out;
591 }
592
593 status = hal_rpu_irq_wdog_ack(hal_dev_ctx);
594 if (status == NRF_WIFI_STATUS_FAIL) {
595 nrf_wifi_osal_log_err("%s: hal_rpu_irq_wdog_ack failed",
596 __func__);
597 goto out;
598 }
599 }
600
601 if (!num_events) {
602 status = NRF_WIFI_STATUS_SUCCESS;
603 goto out;
604 }
605
606 status = hal_rpu_irq_ack(hal_dev_ctx);
607
608 if (status == NRF_WIFI_STATUS_FAIL) {
609 nrf_wifi_osal_log_err("%s: hal_rpu_irq_ack failed",
610 __func__);
611 goto out;
612 }
613 out:
614 return status;
615 }
616