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 offloaded raw TX
10 * mode of operation
11 */
12
13 #include "queue.h"
14 #include "common/hal_structs_common.h"
15 #include "common/hal_common.h"
16 #include "common/hal_reg.h"
17 #include "common/hal_mem.h"
18 #include "common/hal_interrupt.h"
19 #include "common/pal.h"
20 #include "offload_raw_tx/hal_api.h"
21
event_tasklet_fn(unsigned long data)22 static void event_tasklet_fn(unsigned long data)
23 {
24 enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
25 struct nrf_wifi_hal_dev_ctx *hal_dev_ctx = NULL;
26 unsigned long flags = 0;
27
28 hal_dev_ctx = (struct nrf_wifi_hal_dev_ctx *)data;
29
30 nrf_wifi_osal_spinlock_irq_take(hal_dev_ctx->lock_rx,
31 &flags);
32
33 if (hal_dev_ctx->hal_status != NRF_WIFI_HAL_STATUS_ENABLED) {
34 /* Ignore the interrupt if the HAL is not enabled */
35 status = NRF_WIFI_STATUS_SUCCESS;
36 goto out;
37 }
38
39 status = hal_rpu_eventq_process(hal_dev_ctx);
40
41 if (status != NRF_WIFI_STATUS_SUCCESS) {
42 nrf_wifi_osal_log_err("%s: Event queue processing failed",
43 __func__);
44 }
45
46 out:
47 nrf_wifi_osal_spinlock_irq_rel(hal_dev_ctx->lock_rx,
48 &flags);
49 }
50
51
hal_rpu_recovery(struct nrf_wifi_hal_dev_ctx * hal_dev_ctx)52 static enum nrf_wifi_status hal_rpu_recovery(struct nrf_wifi_hal_dev_ctx *hal_dev_ctx)
53 {
54 enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
55
56 if (!hal_dev_ctx->hpriv->rpu_recovery_callbk_fn) {
57 nrf_wifi_osal_log_dbg("%s: RPU recovery callback not registered",
58 __func__);
59 goto out;
60 }
61
62 status = hal_dev_ctx->hpriv->rpu_recovery_callbk_fn(hal_dev_ctx->mac_dev_ctx, NULL, 0);
63 if (status != NRF_WIFI_STATUS_SUCCESS) {
64 nrf_wifi_osal_log_err("%s: RPU recovery failed",
65 __func__);
66 goto out;
67 }
68
69 out:
70 return status;
71 }
72
recovery_tasklet_fn(unsigned long data)73 static void recovery_tasklet_fn(unsigned long data)
74 {
75 struct nrf_wifi_hal_dev_ctx *hal_dev_ctx = NULL;
76 unsigned long flags = 0;
77
78 hal_dev_ctx = (struct nrf_wifi_hal_dev_ctx *)data;
79 if (!hal_dev_ctx) {
80 nrf_wifi_osal_log_err("%s: Invalid hal_dev_ctx",
81 __func__);
82 return;
83 }
84
85 nrf_wifi_osal_spinlock_irq_take(hal_dev_ctx->lock_recovery,
86 &flags);
87 hal_rpu_recovery(hal_dev_ctx);
88 nrf_wifi_osal_spinlock_irq_rel(hal_dev_ctx->lock_recovery,
89 &flags);
90 }
91
92
nrf_wifi_off_raw_tx_hal_dev_add(struct nrf_wifi_hal_priv * hpriv,void * mac_dev_ctx)93 struct nrf_wifi_hal_dev_ctx *nrf_wifi_off_raw_tx_hal_dev_add(struct nrf_wifi_hal_priv *hpriv,
94 void *mac_dev_ctx)
95 {
96 enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
97 struct nrf_wifi_hal_dev_ctx *hal_dev_ctx = NULL;
98
99 hal_dev_ctx = nrf_wifi_osal_mem_zalloc(sizeof(*hal_dev_ctx));
100
101 if (!hal_dev_ctx) {
102 nrf_wifi_osal_log_err("%s: Unable to allocate hal_dev_ctx",
103 __func__);
104 goto err;
105 }
106
107 hal_dev_ctx->hpriv = hpriv;
108 hal_dev_ctx->mac_dev_ctx = mac_dev_ctx;
109 hal_dev_ctx->idx = hpriv->num_devs++;
110
111 hal_dev_ctx->num_cmds = RPU_CMD_START_MAGIC;
112
113 hal_dev_ctx->cmd_q = nrf_wifi_utils_q_alloc();
114
115 if (!hal_dev_ctx->cmd_q) {
116 nrf_wifi_osal_log_err("%s: Unable to allocate command queue",
117 __func__);
118 goto hal_dev_free;
119 }
120
121 hal_dev_ctx->event_q = nrf_wifi_utils_q_alloc();
122
123 if (!hal_dev_ctx->event_q) {
124 nrf_wifi_osal_log_err("%s: Unable to allocate event queue",
125 __func__);
126 goto cmd_q_free;
127 }
128
129 hal_dev_ctx->lock_hal = nrf_wifi_osal_spinlock_alloc();
130
131 if (!hal_dev_ctx->lock_hal) {
132 nrf_wifi_osal_log_err("%s: Unable to allocate HAL lock", __func__);
133 hal_dev_ctx = NULL;
134 goto event_q_free;
135 }
136
137 nrf_wifi_osal_spinlock_init(hal_dev_ctx->lock_hal);
138
139 hal_dev_ctx->lock_rx = nrf_wifi_osal_spinlock_alloc();
140
141 if (!hal_dev_ctx->lock_rx) {
142 nrf_wifi_osal_log_err("%s: Unable to allocate HAL lock",
143 __func__);
144 goto lock_hal_free;
145 }
146
147 nrf_wifi_osal_spinlock_init(hal_dev_ctx->lock_rx);
148
149 hal_dev_ctx->event_tasklet = nrf_wifi_osal_tasklet_alloc(NRF_WIFI_TASKLET_TYPE_BH);
150
151 if (!hal_dev_ctx->event_tasklet) {
152 nrf_wifi_osal_log_err("%s: Unable to allocate event_tasklet",
153 __func__);
154 goto lock_rx_free;
155 }
156
157 nrf_wifi_osal_tasklet_init(hal_dev_ctx->event_tasklet,
158 event_tasklet_fn,
159 (unsigned long)hal_dev_ctx);
160
161 hal_dev_ctx->recovery_tasklet = nrf_wifi_osal_tasklet_alloc(NRF_WIFI_TASKLET_TYPE_BH);
162 if (!hal_dev_ctx->recovery_tasklet) {
163 nrf_wifi_osal_log_err("%s: Unable to allocate recovery_tasklet",
164 __func__);
165 goto event_tasklet_free;
166 }
167 nrf_wifi_osal_tasklet_init(hal_dev_ctx->recovery_tasklet,
168 recovery_tasklet_fn,
169 (unsigned long)hal_dev_ctx);
170
171 hal_dev_ctx->lock_recovery = nrf_wifi_osal_spinlock_alloc();
172 if (!hal_dev_ctx->lock_recovery) {
173 nrf_wifi_osal_log_err("%s: Unable to allocate recovery lock",
174 __func__);
175 goto recovery_tasklet_free;
176 }
177
178 nrf_wifi_osal_spinlock_init(hal_dev_ctx->lock_recovery);
179 #ifdef NRF_WIFI_LOW_POWER
180 status = hal_rpu_ps_init(hal_dev_ctx);
181
182 if (status != NRF_WIFI_STATUS_SUCCESS) {
183 nrf_wifi_osal_log_err("%s: hal_rpu_ps_init failed",
184 __func__);
185 goto lock_recovery_free;
186 }
187 #endif /* NRF_WIFI_LOW_POWER */
188
189 hal_dev_ctx->bal_dev_ctx = nrf_wifi_bal_dev_add(hpriv->bpriv,
190 hal_dev_ctx);
191
192 if (!hal_dev_ctx->bal_dev_ctx) {
193 nrf_wifi_osal_log_err("%s: nrf_wifi_bal_dev_add failed",
194 __func__);
195 goto lock_recovery_free;
196 }
197
198 status = hal_rpu_irq_enable(hal_dev_ctx);
199
200 if (status != NRF_WIFI_STATUS_SUCCESS) {
201 nrf_wifi_osal_log_err("%s: hal_rpu_irq_enable failed",
202 __func__);
203 goto bal_dev_free;
204 }
205
206 return hal_dev_ctx;
207 bal_dev_free:
208 nrf_wifi_bal_dev_rem(hal_dev_ctx->bal_dev_ctx);
209 lock_recovery_free:
210 nrf_wifi_osal_spinlock_free(hal_dev_ctx->lock_recovery);
211 recovery_tasklet_free:
212 nrf_wifi_osal_tasklet_free(hal_dev_ctx->recovery_tasklet);
213 event_tasklet_free:
214 nrf_wifi_osal_tasklet_free(hal_dev_ctx->event_tasklet);
215 lock_rx_free:
216 nrf_wifi_osal_spinlock_free(hal_dev_ctx->lock_rx);
217 lock_hal_free:
218 nrf_wifi_osal_spinlock_free(hal_dev_ctx->lock_hal);
219 event_q_free:
220 nrf_wifi_utils_q_free(hal_dev_ctx->event_q);
221 cmd_q_free:
222 nrf_wifi_utils_q_free(hal_dev_ctx->cmd_q);
223 hal_dev_free:
224 nrf_wifi_osal_mem_free(hal_dev_ctx);
225 hal_dev_ctx = NULL;
226 err:
227 return NULL;
228 }