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