blob: 70946d5c7d61e9be3fed14ce01568fd9e0ebf4aa [file] [log] [blame]
Varsha Mishrae58d93b2017-05-20 20:54:41 +05301/*
2 **************************************************************************
3 * Copyright (c) 2017, The Linux Foundation. All rights reserved.
4 * Permission to use, copy, modify, and/or distribute this software for
5 * any purpose with or without fee is hereby granted, provided that the
6 * above copyright notice and this permission notice appear in all copies.
7 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
10 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
12 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
13 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14 **************************************************************************
15 */
16
17#include "nss_tx_rx_common.h"
18
19#define NSS_WIFILI_TX_TIMEOUT 1000 /* Millisecond to jiffies*/
20
21/*
22 * nss_wifili_pvt
23 * Private data structure
24 */
25static struct nss_wifili_pvt {
26 struct semaphore sem;
27 struct completion complete;
28 int response;
29 void *cb;
30 void *app_data;
31} wifili_pvt;
32
33/*
34 * nss_wifili_stats_sync()
35 * Handle the syncing of WIFI stats.
36 */
37static void nss_wifili_stats_sync(struct nss_ctx_instance *nss_ctx,
Aniruddha Paul1b170c22017-05-29 12:30:39 +053038 struct nss_wifili_stats_sync_msg *wlsoc_stats, uint16_t interface)
Varsha Mishrae58d93b2017-05-20 20:54:41 +053039{
Aniruddha Paul1b170c22017-05-29 12:30:39 +053040 struct nss_top_instance *nss_top = nss_ctx->nss_top;
41 struct nss_wifili_stats *stats = &nss_top->stats_wifili;
42 struct nss_wifili_device_stats *devstats = &wlsoc_stats->stats;
43 uint32_t index;
44
45 spin_lock_bh(&nss_top->stats_lock);
46
47 for (index = 0; index < NSS_WIFILI_MAX_PDEV_NUM_MSG; index++) {
48 /*
49 * Rx stats
50 */
51 stats->stats_txrx[index][NSS_STATS_WIFILI_RX_MSDU_ERROR] +=
52 devstats->rx_data_stats[index].rx_msdu_err;
53 stats->stats_txrx[index][NSS_STATS_WIFILI_RX_INV_PEER_RCV] +=
54 (devstats->rx_data_stats[index].rx_inv_peer +
55 devstats->rx_data_stats[index].rx_scatter_inv_peer);
56 stats->stats_txrx[index][NSS_STATS_WIFILI_RX_WDS_SRCPORT_EXCEPTION] +=
57 devstats->rx_data_stats[index].rx_wds_learn_send;
58 stats->stats_txrx[index][NSS_STATS_WIFILI_RX_WDS_SRCPORT_EXCEPTION_FAIL] +=
59 devstats->rx_data_stats[index].rx_wds_learn_send_fail;
60 stats->stats_txrx[index][NSS_STATS_WIFILI_RX_DELIVERD] +=
61 devstats->rx_data_stats[index].rx_deliver_cnt;
62 stats->stats_txrx[index][NSS_STATS_WIFILI_RX_DELIVER_DROPPED] +=
63 devstats->rx_data_stats[index].rx_deliver_cnt_fail;
64 stats->stats_txrx[index][NSS_STATS_WIFILI_RX_INTRA_BSS_UCAST] +=
65 devstats->rx_data_stats[index].rx_intra_bss_ucast_send;
66 stats->stats_txrx[index][NSS_STATS_WIFILI_RX_INTRA_BSS_UCAST_FAIL] +=
67 devstats->rx_data_stats[index].rx_intra_bss_ucast_send_fail;
68 stats->stats_txrx[index][NSS_STATS_WIFILI_RX_INTRA_BSS_MCAST] +=
69 devstats->rx_data_stats[index].rx_intra_bss_mcast_send;
70 stats->stats_txrx[index][NSS_STATS_WIFILI_RX_INTRA_BSS_MCAST_FAIL] +=
71 devstats->rx_data_stats[index].rx_intra_bss_mcast_send_fail;
Aniruddha Paul1dc00782017-06-05 13:38:48 +053072 stats->stats_txrx[index][NSS_STATS_WIFILI_RX_SG_RCV_SEND] +=
73 devstats->rx_data_stats[index].rx_sg_recv_send;
Aniruddha Paul1b170c22017-05-29 12:30:39 +053074 stats->stats_txrx[index][NSS_STATS_WIFILI_RX_SG_RCV_FAIL] +=
75 devstats->rx_data_stats[index].rx_sg_recv_fail;
76
77 /*
78 * Tx stats
79 */
80 stats->stats_txrx[index][NSS_STATS_WIFILI_TX_ENQUEUE] +=
81 devstats->tx_data_stats[index].tx_enqueue_cnt;
82 stats->stats_txrx[index][NSS_STATS_WIFILI_TX_ENQUEUE_DROP] +=
83 devstats->tx_data_stats[index].tx_enqueue_dropped;
84 stats->stats_txrx[index][NSS_STATS_WIFILI_TX_DEQUEUE] +=
85 devstats->tx_data_stats[index].tx_dequeue_cnt;
86 stats->stats_txrx[index][NSS_STATS_WIFILI_TX_HW_ENQUEUE_FAIL] +=
87 devstats->tx_data_stats[index].tx_send_fail_cnt;
88 stats->stats_txrx[index][NSS_STATS_WIFILI_TX_SENT_COUNT] +=
89 devstats->tx_data_stats[index].tx_processed_pkt;
90 }
91
92 /*
93 * update the tcl ring stats
94 */
95 for (index = 0; index < NSS_WIFILI_MAX_TCL_DATA_RINGS_MSG; index++) {
96 stats->stats_tcl_ring[index][NSS_STATS_WIFILI_TCL_NO_HW_DESC] +=
97 devstats->tcl_stats[index].tcl_no_hw_desc;
98 stats->stats_tcl_ring[index][NSS_STATS_WIFILI_TCL_RING_FULL] +=
99 devstats->tcl_stats[index].tcl_ring_full;
100 stats->stats_tcl_ring[index][NSS_STATS_WIFILI_TCL_RING_SENT] +=
101 devstats->tcl_stats[index].tcl_ring_sent;
102 }
103
104 /*
105 * update the tcl comp stats
106 */
107 for (index = 0; index < NSS_WIFILI_MAX_TCL_DATA_RINGS_MSG; index++) {
108 stats->stats_tx_comp[index][NSS_STATS_WIFILI_TX_DESC_FREE_INV_BUFSRC] +=
109 devstats->txcomp_stats[index].invalid_bufsrc;
110 stats->stats_tx_comp[index][NSS_STATS_WIFILI_TX_DESC_FREE_INV_COOKIE] +=
111 devstats->txcomp_stats[index].invalid_cookie;
112 stats->stats_tx_comp[index][NSS_STATS_WIFILI_TX_DESC_FREE_HW_RING_EMPTY] +=
113 devstats->txcomp_stats[index].hw_ring_empty;
114 stats->stats_tx_comp[index][NSS_STATS_WIFILI_TX_DESC_FREE_REAPED] +=
115 devstats->txcomp_stats[index].ring_reaped;
116 }
117
118 /*
119 * update reo ring stats
120 */
121 for (index = 0; index < NSS_WIFILI_MAX_REO_DATA_RINGS_MSG; index++) {
122 stats->stats_reo[index][NSS_STATS_WIFILI_REO_ERROR] +=
123 devstats->rxreo_stats[index].ring_error;
124 stats->stats_reo[index][NSS_STATS_WIFILI_REO_REAPED] +=
125 devstats->rxreo_stats[index].ring_reaped;
126 stats->stats_reo[index][NSS_STATS_WIFILI_REO_INV_COOKIE] +=
127 devstats->rxreo_stats[index].invalid_cookie;
128 }
129
130 /*
131 * update tx sw pool
132 */
133 for (index = 0; index < NSS_WIFILI_MAX_TXDESC_POOLS_MSG; index++) {
134 stats->stats_tx_desc[index][NSS_STATS_WIFILI_TX_DESC_IN_USE] =
135 devstats->tx_sw_pool_stats[index].desc_alloc;
136 stats->stats_tx_desc[index][NSS_STATS_WIFILI_TX_DESC_ALLOC_FAIL] +=
137 devstats->tx_sw_pool_stats[index].desc_alloc_fail;
138 stats->stats_tx_desc[index][NSS_STATS_WIFILI_TX_DESC_ALREADY_ALLOCATED] +=
139 devstats->tx_sw_pool_stats[index].desc_already_allocated;
140 stats->stats_tx_desc[index][NSS_STATS_WIFILI_TX_DESC_INVALID_FREE] +=
141 devstats->tx_sw_pool_stats[index].desc_invalid_free;
142 stats->stats_tx_desc[index][NSS_STATS_WIFILI_TX_DESC_FREE_SRC_FW] +=
143 devstats->tx_sw_pool_stats[index].tx_rel_src_fw;
144 stats->stats_tx_desc[index][NSS_STATS_WIFILI_TX_DESC_FREE_COMPLETION] +=
145 devstats->tx_sw_pool_stats[index].tx_rel_tx_desc;
146 stats->stats_tx_desc[index][NSS_STATS_WIFILI_TX_DESC_NO_PB] +=
147 devstats->tx_sw_pool_stats[index].tx_rel_no_pb;
148 }
149
150 /*
151 * update ext tx desc pool stats
152 */
153 for (index = 0; index < NSS_WIFILI_MAX_TX_EXT_DESC_POOLS_MSG; index++) {
154 stats->stats_ext_tx_desc[index][NSS_STATS_WIFILI_EXT_TX_DESC_IN_USE] =
155 devstats->tx_ext_sw_pool_stats[index].desc_alloc;
156 stats->stats_ext_tx_desc[index][NSS_STATS_WIFILI_EXT_TX_DESC_ALLOC_FAIL] +=
157 devstats->tx_ext_sw_pool_stats[index].desc_alloc_fail;
158 stats->stats_ext_tx_desc[index][NSS_STATS_WIFILI_EXT_TX_DESC_ALREADY_ALLOCATED] +=
159 devstats->tx_ext_sw_pool_stats[index].desc_already_allocated;
160 stats->stats_ext_tx_desc[index][NSS_STATS_WIFILI_EXT_TX_DESC_INVALID_FREE] +=
161 devstats->tx_ext_sw_pool_stats[index].desc_invalid_free;
162 }
163
164 /*
165 * update rx desc pool stats
166 */
167 for (index = 0; index < NSS_WIFILI_MAX_PDEV_NUM_MSG; index++) {
168 stats->stats_rx_desc[index][NSS_STATS_WIFILI_RX_DESC_NO_PB] +=
169 devstats->rx_sw_pool_stats[index].rx_no_pb;
170 stats->stats_rx_desc[index][NSS_STATS_WIFILI_RX_DESC_ALLOC_FAIL] +=
171 devstats->rx_sw_pool_stats[index].desc_alloc_fail;
172 stats->stats_rx_desc[index][NSS_STATS_WIFILI_RX_DESC_IN_USE] =
173 devstats->rx_sw_pool_stats[index].desc_alloc;
174 }
175
176 /*
177 * update rx dma ring stats
178 */
179 for (index = 0; index < NSS_WIFILI_MAX_PDEV_NUM_MSG; index++) {
180 stats->stats_rxdma[index][NSS_STATS_WIFILI_RXDMA_DESC_UNAVAILABLE] +=
181 devstats->rxdma_stats[index].rx_hw_desc_unavailable;
182 }
183
184 /*
185 * update wbm ring stats
186 */
187 stats->stats_wbm[NSS_STATS_WIFILI_WBM_SRC_DMA] += devstats->rxwbm_stats.err_src_rxdma;
188 stats->stats_wbm[NSS_STATS_WIFILI_WBM_SRC_DMA_CODE_INV] += devstats->rxwbm_stats.err_src_rxdma_code_inv;
189 stats->stats_wbm[NSS_STATS_WIFILI_WBM_SRC_REO] += devstats->rxwbm_stats.err_src_reo;
190 stats->stats_wbm[NSS_STATS_WIFILI_WBM_SRC_REO_CODE_NULLQ] += devstats->rxwbm_stats.err_src_reo_code_nullq;
191 stats->stats_wbm[NSS_STATS_WIFILI_WBM_SRC_REO_CODE_INV] += devstats->rxwbm_stats.err_src_reo_code_inv;
192 stats->stats_wbm[NSS_STATS_WIFILI_WBM_SRC_INV] += devstats->rxwbm_stats.err_src_invalid;
193 spin_unlock_bh(&nss_top->stats_lock);
Varsha Mishrae58d93b2017-05-20 20:54:41 +0530194 return;
195}
196
197/*
198 * nss_wifili_handler()
199 * Handle NSS -> HLOS messages for wifi
200 */
201static void nss_wifili_handler(struct nss_ctx_instance *nss_ctx, struct nss_cmn_msg *ncm, __attribute__((unused))void *app_data)
202{
203 struct nss_wifili_msg *ntm = (struct nss_wifili_msg *)ncm;
204 void *ctx;
205 nss_wifili_msg_callback_t cb;
206
207 nss_info("%p: NSS->HLOS message for wifili\n", nss_ctx);
208
209 /*
210 * The interface number shall be wifili soc interface or wifili radio interface
211 */
212 BUG_ON((nss_is_dynamic_interface(ncm->interface)) || ncm->interface != NSS_WIFILI_INTERFACE);
213
214 /*
215 * Is this a valid request/response packet?
216 */
217 if (ncm->type >= NSS_WIFILI_MAX_MSG) {
218 nss_warning("%p: Received invalid message %d for wifili interface", nss_ctx, ncm->type);
219 return;
220 }
221
222 if (nss_cmn_get_msg_len(ncm) > sizeof(struct nss_wifili_msg)) {
223 nss_warning("%p: Length of message is greater than required: %d", nss_ctx, nss_cmn_get_msg_len(ncm));
224 return;
225 }
226
227 /*
228 * Snoop messages for local driver and handle
229 */
230 switch (ntm->cm.type) {
Aniruddha Paul1b170c22017-05-29 12:30:39 +0530231 case NSS_WIFILI_STATS_MSG:
Varsha Mishrae58d93b2017-05-20 20:54:41 +0530232 nss_wifili_stats_sync(nss_ctx, &ntm->msg.wlsoc_stats, ncm->interface);
233 break;
234 }
235
236 /*
237 * Update the callback and app_data for notify messages, wifili sends all notify messages
238 * to the same callback/app_data.
239 */
240 if (ncm->response == NSS_CMM_RESPONSE_NOTIFY) {
241 ncm->cb = (nss_ptr_t)nss_ctx->nss_top->wifili_msg_callback;
242 }
243
244 /*
245 * Log failures
246 */
247 nss_core_log_msg_failures(nss_ctx, ncm);
248
249 /*
250 * Do we have a call back
251 */
252 if (!ncm->cb) {
253 nss_info("%p: cb null for wifili interface %d", nss_ctx, ncm->interface);
254 return;
255 }
256
257 /*
258 * Get callback & context
259 */
260 cb = (nss_wifili_msg_callback_t)ncm->cb;
261 ctx = nss_ctx->subsys_dp_register[ncm->interface].ndev;
262
263 /*
264 * call wifili msg callback
265 */
266 if (!ctx) {
267 nss_warning("%p: Event received for wifili interface %d before registration", nss_ctx, ncm->interface);
268 return;
269 }
270
271 cb(ctx, ntm);
272}
273
274/*
275 * nss_wifili_callback()
276 * Callback to handle the completion of NSS->HLOS messages.
277 */
278static void nss_wifili_callback(void *app_data, struct nss_wifili_msg *nvm)
279{
280 nss_wifili_msg_callback_t callback = (nss_wifili_msg_callback_t)wifili_pvt.cb;
281 void *data = wifili_pvt.app_data;
282
283 wifili_pvt.response = NSS_TX_SUCCESS;
284 wifili_pvt.cb = NULL;
285 wifili_pvt.app_data = NULL;
286
287 if (nvm->cm.response != NSS_CMN_RESPONSE_ACK) {
288 nss_warning("wifili error response %d\n", nvm->cm.response);
289 wifili_pvt.response = nvm->cm.response;
290 }
291
292 if (callback) {
293 callback(data, nvm);
294 }
295 complete(&wifili_pvt.complete);
296}
297
298/*
299 * nss_wifili_tx_msg
300 * Transmit a wifili message to NSS FW
301 *
302 * NOTE: The caller is expected to handle synchronous wait for message
303 * response if needed.
304 */
305nss_tx_status_t nss_wifili_tx_msg(struct nss_ctx_instance *nss_ctx, struct nss_wifili_msg *msg)
306{
307 struct nss_wifili_msg *nm;
308 struct nss_cmn_msg *ncm = &msg->cm;
309 struct sk_buff *nbuf;
310 int32_t status;
311
312 NSS_VERIFY_CTX_MAGIC(nss_ctx);
313
314 if (unlikely(nss_ctx->state != NSS_CORE_STATE_INITIALIZED)) {
315 nss_warning("%p: wifili message dropped as core not ready", nss_ctx);
316 return NSS_TX_FAILURE_NOT_READY;
317 }
318
319 if (ncm->type >= NSS_WIFILI_MAX_MSG) {
320 nss_warning("%p: wifili message type out of range: %d", nss_ctx, ncm->type);
321 return NSS_TX_FAILURE;
322 }
323
324 if (nss_cmn_get_msg_len(ncm) > sizeof(struct nss_wifili_msg)) {
325 nss_warning("%p: wifili message length is invalid: %d", nss_ctx, nss_cmn_get_msg_len(ncm));
326 return NSS_TX_FAILURE;
327 }
328
329 /*
330 * The interface number shall be wifili soc interface or wifili radio interface
331 */
332 if (ncm->interface != NSS_WIFILI_INTERFACE) {
333 nss_warning("%p: tx request for interface that is not a wifili: %d", nss_ctx, ncm->interface);
334 return NSS_TX_FAILURE;
335 }
336
337 nbuf = dev_alloc_skb(NSS_NBUF_PAYLOAD_SIZE);
338 if (unlikely(!nbuf)) {
339 spin_lock_bh(&nss_ctx->nss_top->stats_lock);
340 NSS_PKT_STATS_INCREMENT(nss_ctx, &nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_NBUF_ALLOC_FAILS]);
341 spin_unlock_bh(&nss_ctx->nss_top->stats_lock);
342 nss_warning("%p: wifili message failed as command allocation failed", nss_ctx);
343 return NSS_TX_FAILURE;
344 }
345
346 /*
347 * Copy the message to our skb
348 */
349 nm = (struct nss_wifili_msg *)skb_put(nbuf, sizeof(struct nss_wifili_msg));
350 memcpy(nm, msg, sizeof(struct nss_wifili_msg));
351
352 status = nss_core_send_buffer(nss_ctx, 0, nbuf, NSS_IF_CMD_QUEUE, H2N_BUFFER_CTRL, 0);
353 if (status != NSS_CORE_STATUS_SUCCESS) {
354 dev_kfree_skb_any(nbuf);
355 nss_warning("%p: Unable to enqueue 'wifili message'", nss_ctx);
356 return NSS_TX_FAILURE;
357 }
358
359 nss_hal_send_interrupt(nss_ctx, NSS_H2N_INTR_DATA_COMMAND_QUEUE);
360
361 NSS_PKT_STATS_INCREMENT(nss_ctx, &nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_TX_CMD_REQ]);
362
363 return NSS_TX_SUCCESS;
364}
365EXPORT_SYMBOL(nss_wifili_tx_msg);
366
367/*
368 * nss_wifili_tx_msg_sync()
369 * Transmit a wifili message to NSS firmware synchronously.
370 */
371nss_tx_status_t nss_wifili_tx_msg_sync(struct nss_ctx_instance *nss_ctx, struct nss_wifili_msg *nvm)
372{
373 nss_tx_status_t status;
374 int ret = 0;
375
376 down(&wifili_pvt.sem);
377 wifili_pvt.cb = (void *)nvm->cm.cb;
378 wifili_pvt.app_data = (void *)nvm->cm.app_data;
379
380 nvm->cm.cb = (nss_ptr_t)nss_wifili_callback;
381 nvm->cm.app_data = (nss_ptr_t)NULL;
382
383 status = nss_wifili_tx_msg(nss_ctx, nvm);
384 if (status != NSS_TX_SUCCESS) {
385 nss_warning("%p: wifili_tx_msg failed\n", nss_ctx);
386 up(&wifili_pvt.sem);
387 return status;
388 }
389
390 ret = wait_for_completion_timeout(&wifili_pvt.complete, msecs_to_jiffies(NSS_WIFILI_TX_TIMEOUT));
391 if (!ret) {
392 nss_warning("%p: wifili msg tx failed due to timeout\n", nss_ctx);
393 wifili_pvt.response = NSS_TX_FAILURE;
394 }
395
396 status = wifili_pvt.response;
397 up(&wifili_pvt.sem);
398 return status;
399}
400EXPORT_SYMBOL(nss_wifili_tx_msg_sync);
401
402/*
403 * nss_wifili_get_context()
404 */
405struct nss_ctx_instance *nss_wifili_get_context(void)
406{
407 return (struct nss_ctx_instance *)&nss_top_main.nss[nss_top_main.wifi_handler_id];
408}
409EXPORT_SYMBOL(nss_wifili_get_context);
410
411/*
412 * nss_wifili_msg_init()
413 * Initialize nss_wifili_msg.
414 */
415void nss_wifili_msg_init(struct nss_wifili_msg *ncm, uint16_t if_num, uint32_t type, uint32_t len, void *cb, void *app_data)
416{
417 nss_cmn_msg_init(&ncm->cm, if_num, type, len, cb, app_data);
418}
419EXPORT_SYMBOL(nss_wifili_msg_init);
420
421/*
422 ****************************************
423 * Register/Unregister/Miscellaneous APIs
424 ****************************************
425 */
426
427/*
428 * nss_register_wifili_if()
429 * Register wifili with nss driver
430 */
431struct nss_ctx_instance *nss_register_wifili_if(uint32_t if_num, nss_wifili_callback_t wifili_callback,
432 nss_wifili_callback_t wifili_ext_callback,
433 nss_wifili_msg_callback_t event_callback, struct net_device *netdev, uint32_t features)
434{
435 struct nss_ctx_instance *nss_ctx = (struct nss_ctx_instance *)&nss_top_main.nss[nss_top_main.wifi_handler_id];
436
437 /*
438 * The interface number shall be wifili soc interface
439 */
440 nss_assert(if_num == NSS_WIFILI_INTERFACE);
441
Aniruddha Paul1b170c22017-05-29 12:30:39 +0530442 nss_info("nss_register_wifili_if if_num %d wifictx %p", if_num, netdev);
Varsha Mishrae58d93b2017-05-20 20:54:41 +0530443
Jackson Bockus7ca70ec2017-07-17 13:47:29 -0700444 nss_core_register_subsys_dp(nss_ctx, if_num, wifili_callback, wifili_ext_callback, NULL, netdev, features);
Varsha Mishrae58d93b2017-05-20 20:54:41 +0530445
446 nss_top_main.wifili_msg_callback = event_callback;
Thomas Wu91f4bdf2017-06-09 12:03:02 -0700447 nss_core_register_handler(nss_ctx, if_num, nss_wifili_handler, NULL);
Varsha Mishrae58d93b2017-05-20 20:54:41 +0530448
449 return (struct nss_ctx_instance *)&nss_top_main.nss[nss_top_main.wifi_handler_id];
450}
451EXPORT_SYMBOL(nss_register_wifili_if);
452
453/*
454 * nss_unregister_wifili_if()
455 * Unregister wifili with nss driver
456 */
457void nss_unregister_wifili_if(uint32_t if_num)
458{
459 struct nss_ctx_instance *nss_ctx = (struct nss_ctx_instance *)&nss_top_main.nss[nss_top_main.wifi_handler_id];
460
461 /*
462 * The interface number shall be wifili soc interface
463 */
464 nss_assert(if_num == NSS_WIFILI_INTERFACE);
465
Jackson Bockus7ca70ec2017-07-17 13:47:29 -0700466 nss_core_unregister_subsys_dp(nss_ctx, if_num);
Varsha Mishrae58d93b2017-05-20 20:54:41 +0530467}
468EXPORT_SYMBOL(nss_unregister_wifili_if);
469
470/*
471 * nss_register_wifili_radio_if()
472 * Register wifili radio with nss driver
473 */
474struct nss_ctx_instance *nss_register_wifili_radio_if(uint32_t if_num, nss_wifili_callback_t wifili_callback,
475 nss_wifili_callback_t wifili_ext_callback,
476 nss_wifili_msg_callback_t event_callback, struct net_device *netdev, uint32_t features)
477{
478 struct nss_ctx_instance *nss_ctx = (struct nss_ctx_instance *)&nss_top_main.nss[nss_top_main.wifi_handler_id];
479
480 /*
481 * The interface number shall be wifili radio dynamic interface
482 */
483 nss_assert(nss_is_dynamic_interface(if_num));
Aniruddha Paul1b170c22017-05-29 12:30:39 +0530484 nss_info("nss_register_wifili_if if_num %d wifictx %p", if_num, netdev);
Varsha Mishrae58d93b2017-05-20 20:54:41 +0530485
Jackson Bockus7ca70ec2017-07-17 13:47:29 -0700486 nss_core_register_subsys_dp(nss_ctx, if_num, wifili_callback, wifili_ext_callback, NULL, netdev, features);
Varsha Mishrae58d93b2017-05-20 20:54:41 +0530487
488 return (struct nss_ctx_instance *)&nss_top_main.nss[nss_top_main.wifi_handler_id];
489}
490EXPORT_SYMBOL(nss_register_wifili_radio_if);
491
492/*
493 * nss_unregister_wifili_radio_if()
494 * Unregister wifili radio with nss driver
495 */
496void nss_unregister_wifili_radio_if(uint32_t if_num)
497{
498 struct nss_ctx_instance *nss_ctx = (struct nss_ctx_instance *)&nss_top_main.nss[nss_top_main.wifi_handler_id];
499
500 /*
501 * The interface number shall be wifili radio dynamic interface
502 */
503 nss_assert(nss_is_dynamic_interface(if_num));
504
Jackson Bockus7ca70ec2017-07-17 13:47:29 -0700505 nss_core_unregister_subsys_dp(nss_ctx, if_num);
Varsha Mishrae58d93b2017-05-20 20:54:41 +0530506}
507EXPORT_SYMBOL(nss_unregister_wifili_radio_if);
508
509/*
510 * nss_wifili_register_handler()
511 * Register handle for notfication messages received on wifi interface
512 */
Aniruddha Paul1b170c22017-05-29 12:30:39 +0530513void nss_wifili_register_handler(void)
Varsha Mishrae58d93b2017-05-20 20:54:41 +0530514{
Thomas Wu91f4bdf2017-06-09 12:03:02 -0700515 struct nss_ctx_instance *nss_ctx = (struct nss_ctx_instance *)&nss_top_main.nss[nss_top_main.wifi_handler_id];
516
Varsha Mishrae58d93b2017-05-20 20:54:41 +0530517 nss_info("nss_wifili_register_handler");
Thomas Wu91f4bdf2017-06-09 12:03:02 -0700518 nss_core_register_handler(nss_ctx, NSS_WIFILI_INTERFACE, nss_wifili_handler, NULL);
Varsha Mishrae58d93b2017-05-20 20:54:41 +0530519
520 sema_init(&wifili_pvt.sem, 1);
521 init_completion(&wifili_pvt.complete);
522}