blob: 0010fdaad5dfd7c86768567bfa5f7bbcb0cfa265 [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;
72 stats->stats_txrx[index][NSS_STATS_WIFILI_RX_SG_RCV_FAIL] +=
73 devstats->rx_data_stats[index].rx_sg_recv_fail;
74
75 /*
76 * Tx stats
77 */
78 stats->stats_txrx[index][NSS_STATS_WIFILI_TX_ENQUEUE] +=
79 devstats->tx_data_stats[index].tx_enqueue_cnt;
80 stats->stats_txrx[index][NSS_STATS_WIFILI_TX_ENQUEUE_DROP] +=
81 devstats->tx_data_stats[index].tx_enqueue_dropped;
82 stats->stats_txrx[index][NSS_STATS_WIFILI_TX_DEQUEUE] +=
83 devstats->tx_data_stats[index].tx_dequeue_cnt;
84 stats->stats_txrx[index][NSS_STATS_WIFILI_TX_HW_ENQUEUE_FAIL] +=
85 devstats->tx_data_stats[index].tx_send_fail_cnt;
86 stats->stats_txrx[index][NSS_STATS_WIFILI_TX_SENT_COUNT] +=
87 devstats->tx_data_stats[index].tx_processed_pkt;
88 }
89
90 /*
91 * update the tcl ring stats
92 */
93 for (index = 0; index < NSS_WIFILI_MAX_TCL_DATA_RINGS_MSG; index++) {
94 stats->stats_tcl_ring[index][NSS_STATS_WIFILI_TCL_NO_HW_DESC] +=
95 devstats->tcl_stats[index].tcl_no_hw_desc;
96 stats->stats_tcl_ring[index][NSS_STATS_WIFILI_TCL_RING_FULL] +=
97 devstats->tcl_stats[index].tcl_ring_full;
98 stats->stats_tcl_ring[index][NSS_STATS_WIFILI_TCL_RING_SENT] +=
99 devstats->tcl_stats[index].tcl_ring_sent;
100 }
101
102 /*
103 * update the tcl comp stats
104 */
105 for (index = 0; index < NSS_WIFILI_MAX_TCL_DATA_RINGS_MSG; index++) {
106 stats->stats_tx_comp[index][NSS_STATS_WIFILI_TX_DESC_FREE_INV_BUFSRC] +=
107 devstats->txcomp_stats[index].invalid_bufsrc;
108 stats->stats_tx_comp[index][NSS_STATS_WIFILI_TX_DESC_FREE_INV_COOKIE] +=
109 devstats->txcomp_stats[index].invalid_cookie;
110 stats->stats_tx_comp[index][NSS_STATS_WIFILI_TX_DESC_FREE_HW_RING_EMPTY] +=
111 devstats->txcomp_stats[index].hw_ring_empty;
112 stats->stats_tx_comp[index][NSS_STATS_WIFILI_TX_DESC_FREE_REAPED] +=
113 devstats->txcomp_stats[index].ring_reaped;
114 }
115
116 /*
117 * update reo ring stats
118 */
119 for (index = 0; index < NSS_WIFILI_MAX_REO_DATA_RINGS_MSG; index++) {
120 stats->stats_reo[index][NSS_STATS_WIFILI_REO_ERROR] +=
121 devstats->rxreo_stats[index].ring_error;
122 stats->stats_reo[index][NSS_STATS_WIFILI_REO_REAPED] +=
123 devstats->rxreo_stats[index].ring_reaped;
124 stats->stats_reo[index][NSS_STATS_WIFILI_REO_INV_COOKIE] +=
125 devstats->rxreo_stats[index].invalid_cookie;
126 }
127
128 /*
129 * update tx sw pool
130 */
131 for (index = 0; index < NSS_WIFILI_MAX_TXDESC_POOLS_MSG; index++) {
132 stats->stats_tx_desc[index][NSS_STATS_WIFILI_TX_DESC_IN_USE] =
133 devstats->tx_sw_pool_stats[index].desc_alloc;
134 stats->stats_tx_desc[index][NSS_STATS_WIFILI_TX_DESC_ALLOC_FAIL] +=
135 devstats->tx_sw_pool_stats[index].desc_alloc_fail;
136 stats->stats_tx_desc[index][NSS_STATS_WIFILI_TX_DESC_ALREADY_ALLOCATED] +=
137 devstats->tx_sw_pool_stats[index].desc_already_allocated;
138 stats->stats_tx_desc[index][NSS_STATS_WIFILI_TX_DESC_INVALID_FREE] +=
139 devstats->tx_sw_pool_stats[index].desc_invalid_free;
140 stats->stats_tx_desc[index][NSS_STATS_WIFILI_TX_DESC_FREE_SRC_FW] +=
141 devstats->tx_sw_pool_stats[index].tx_rel_src_fw;
142 stats->stats_tx_desc[index][NSS_STATS_WIFILI_TX_DESC_FREE_COMPLETION] +=
143 devstats->tx_sw_pool_stats[index].tx_rel_tx_desc;
144 stats->stats_tx_desc[index][NSS_STATS_WIFILI_TX_DESC_NO_PB] +=
145 devstats->tx_sw_pool_stats[index].tx_rel_no_pb;
146 }
147
148 /*
149 * update ext tx desc pool stats
150 */
151 for (index = 0; index < NSS_WIFILI_MAX_TX_EXT_DESC_POOLS_MSG; index++) {
152 stats->stats_ext_tx_desc[index][NSS_STATS_WIFILI_EXT_TX_DESC_IN_USE] =
153 devstats->tx_ext_sw_pool_stats[index].desc_alloc;
154 stats->stats_ext_tx_desc[index][NSS_STATS_WIFILI_EXT_TX_DESC_ALLOC_FAIL] +=
155 devstats->tx_ext_sw_pool_stats[index].desc_alloc_fail;
156 stats->stats_ext_tx_desc[index][NSS_STATS_WIFILI_EXT_TX_DESC_ALREADY_ALLOCATED] +=
157 devstats->tx_ext_sw_pool_stats[index].desc_already_allocated;
158 stats->stats_ext_tx_desc[index][NSS_STATS_WIFILI_EXT_TX_DESC_INVALID_FREE] +=
159 devstats->tx_ext_sw_pool_stats[index].desc_invalid_free;
160 }
161
162 /*
163 * update rx desc pool stats
164 */
165 for (index = 0; index < NSS_WIFILI_MAX_PDEV_NUM_MSG; index++) {
166 stats->stats_rx_desc[index][NSS_STATS_WIFILI_RX_DESC_NO_PB] +=
167 devstats->rx_sw_pool_stats[index].rx_no_pb;
168 stats->stats_rx_desc[index][NSS_STATS_WIFILI_RX_DESC_ALLOC_FAIL] +=
169 devstats->rx_sw_pool_stats[index].desc_alloc_fail;
170 stats->stats_rx_desc[index][NSS_STATS_WIFILI_RX_DESC_IN_USE] =
171 devstats->rx_sw_pool_stats[index].desc_alloc;
172 }
173
174 /*
175 * update rx dma ring stats
176 */
177 for (index = 0; index < NSS_WIFILI_MAX_PDEV_NUM_MSG; index++) {
178 stats->stats_rxdma[index][NSS_STATS_WIFILI_RXDMA_DESC_UNAVAILABLE] +=
179 devstats->rxdma_stats[index].rx_hw_desc_unavailable;
180 }
181
182 /*
183 * update wbm ring stats
184 */
185 stats->stats_wbm[NSS_STATS_WIFILI_WBM_SRC_DMA] += devstats->rxwbm_stats.err_src_rxdma;
186 stats->stats_wbm[NSS_STATS_WIFILI_WBM_SRC_DMA_CODE_INV] += devstats->rxwbm_stats.err_src_rxdma_code_inv;
187 stats->stats_wbm[NSS_STATS_WIFILI_WBM_SRC_REO] += devstats->rxwbm_stats.err_src_reo;
188 stats->stats_wbm[NSS_STATS_WIFILI_WBM_SRC_REO_CODE_NULLQ] += devstats->rxwbm_stats.err_src_reo_code_nullq;
189 stats->stats_wbm[NSS_STATS_WIFILI_WBM_SRC_REO_CODE_INV] += devstats->rxwbm_stats.err_src_reo_code_inv;
190 stats->stats_wbm[NSS_STATS_WIFILI_WBM_SRC_INV] += devstats->rxwbm_stats.err_src_invalid;
191 spin_unlock_bh(&nss_top->stats_lock);
Varsha Mishrae58d93b2017-05-20 20:54:41 +0530192 return;
193}
194
195/*
196 * nss_wifili_handler()
197 * Handle NSS -> HLOS messages for wifi
198 */
199static void nss_wifili_handler(struct nss_ctx_instance *nss_ctx, struct nss_cmn_msg *ncm, __attribute__((unused))void *app_data)
200{
201 struct nss_wifili_msg *ntm = (struct nss_wifili_msg *)ncm;
202 void *ctx;
203 nss_wifili_msg_callback_t cb;
204
205 nss_info("%p: NSS->HLOS message for wifili\n", nss_ctx);
206
207 /*
208 * The interface number shall be wifili soc interface or wifili radio interface
209 */
210 BUG_ON((nss_is_dynamic_interface(ncm->interface)) || ncm->interface != NSS_WIFILI_INTERFACE);
211
212 /*
213 * Is this a valid request/response packet?
214 */
215 if (ncm->type >= NSS_WIFILI_MAX_MSG) {
216 nss_warning("%p: Received invalid message %d for wifili interface", nss_ctx, ncm->type);
217 return;
218 }
219
220 if (nss_cmn_get_msg_len(ncm) > sizeof(struct nss_wifili_msg)) {
221 nss_warning("%p: Length of message is greater than required: %d", nss_ctx, nss_cmn_get_msg_len(ncm));
222 return;
223 }
224
225 /*
226 * Snoop messages for local driver and handle
227 */
228 switch (ntm->cm.type) {
Aniruddha Paul1b170c22017-05-29 12:30:39 +0530229 case NSS_WIFILI_STATS_MSG:
Varsha Mishrae58d93b2017-05-20 20:54:41 +0530230 nss_wifili_stats_sync(nss_ctx, &ntm->msg.wlsoc_stats, ncm->interface);
231 break;
232 }
233
234 /*
235 * Update the callback and app_data for notify messages, wifili sends all notify messages
236 * to the same callback/app_data.
237 */
238 if (ncm->response == NSS_CMM_RESPONSE_NOTIFY) {
239 ncm->cb = (nss_ptr_t)nss_ctx->nss_top->wifili_msg_callback;
240 }
241
242 /*
243 * Log failures
244 */
245 nss_core_log_msg_failures(nss_ctx, ncm);
246
247 /*
248 * Do we have a call back
249 */
250 if (!ncm->cb) {
251 nss_info("%p: cb null for wifili interface %d", nss_ctx, ncm->interface);
252 return;
253 }
254
255 /*
256 * Get callback & context
257 */
258 cb = (nss_wifili_msg_callback_t)ncm->cb;
259 ctx = nss_ctx->subsys_dp_register[ncm->interface].ndev;
260
261 /*
262 * call wifili msg callback
263 */
264 if (!ctx) {
265 nss_warning("%p: Event received for wifili interface %d before registration", nss_ctx, ncm->interface);
266 return;
267 }
268
269 cb(ctx, ntm);
270}
271
272/*
273 * nss_wifili_callback()
274 * Callback to handle the completion of NSS->HLOS messages.
275 */
276static void nss_wifili_callback(void *app_data, struct nss_wifili_msg *nvm)
277{
278 nss_wifili_msg_callback_t callback = (nss_wifili_msg_callback_t)wifili_pvt.cb;
279 void *data = wifili_pvt.app_data;
280
281 wifili_pvt.response = NSS_TX_SUCCESS;
282 wifili_pvt.cb = NULL;
283 wifili_pvt.app_data = NULL;
284
285 if (nvm->cm.response != NSS_CMN_RESPONSE_ACK) {
286 nss_warning("wifili error response %d\n", nvm->cm.response);
287 wifili_pvt.response = nvm->cm.response;
288 }
289
290 if (callback) {
291 callback(data, nvm);
292 }
293 complete(&wifili_pvt.complete);
294}
295
296/*
297 * nss_wifili_tx_msg
298 * Transmit a wifili message to NSS FW
299 *
300 * NOTE: The caller is expected to handle synchronous wait for message
301 * response if needed.
302 */
303nss_tx_status_t nss_wifili_tx_msg(struct nss_ctx_instance *nss_ctx, struct nss_wifili_msg *msg)
304{
305 struct nss_wifili_msg *nm;
306 struct nss_cmn_msg *ncm = &msg->cm;
307 struct sk_buff *nbuf;
308 int32_t status;
309
310 NSS_VERIFY_CTX_MAGIC(nss_ctx);
311
312 if (unlikely(nss_ctx->state != NSS_CORE_STATE_INITIALIZED)) {
313 nss_warning("%p: wifili message dropped as core not ready", nss_ctx);
314 return NSS_TX_FAILURE_NOT_READY;
315 }
316
317 if (ncm->type >= NSS_WIFILI_MAX_MSG) {
318 nss_warning("%p: wifili message type out of range: %d", nss_ctx, ncm->type);
319 return NSS_TX_FAILURE;
320 }
321
322 if (nss_cmn_get_msg_len(ncm) > sizeof(struct nss_wifili_msg)) {
323 nss_warning("%p: wifili message length is invalid: %d", nss_ctx, nss_cmn_get_msg_len(ncm));
324 return NSS_TX_FAILURE;
325 }
326
327 /*
328 * The interface number shall be wifili soc interface or wifili radio interface
329 */
330 if (ncm->interface != NSS_WIFILI_INTERFACE) {
331 nss_warning("%p: tx request for interface that is not a wifili: %d", nss_ctx, ncm->interface);
332 return NSS_TX_FAILURE;
333 }
334
335 nbuf = dev_alloc_skb(NSS_NBUF_PAYLOAD_SIZE);
336 if (unlikely(!nbuf)) {
337 spin_lock_bh(&nss_ctx->nss_top->stats_lock);
338 NSS_PKT_STATS_INCREMENT(nss_ctx, &nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_NBUF_ALLOC_FAILS]);
339 spin_unlock_bh(&nss_ctx->nss_top->stats_lock);
340 nss_warning("%p: wifili message failed as command allocation failed", nss_ctx);
341 return NSS_TX_FAILURE;
342 }
343
344 /*
345 * Copy the message to our skb
346 */
347 nm = (struct nss_wifili_msg *)skb_put(nbuf, sizeof(struct nss_wifili_msg));
348 memcpy(nm, msg, sizeof(struct nss_wifili_msg));
349
350 status = nss_core_send_buffer(nss_ctx, 0, nbuf, NSS_IF_CMD_QUEUE, H2N_BUFFER_CTRL, 0);
351 if (status != NSS_CORE_STATUS_SUCCESS) {
352 dev_kfree_skb_any(nbuf);
353 nss_warning("%p: Unable to enqueue 'wifili message'", nss_ctx);
354 return NSS_TX_FAILURE;
355 }
356
357 nss_hal_send_interrupt(nss_ctx, NSS_H2N_INTR_DATA_COMMAND_QUEUE);
358
359 NSS_PKT_STATS_INCREMENT(nss_ctx, &nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_TX_CMD_REQ]);
360
361 return NSS_TX_SUCCESS;
362}
363EXPORT_SYMBOL(nss_wifili_tx_msg);
364
365/*
366 * nss_wifili_tx_msg_sync()
367 * Transmit a wifili message to NSS firmware synchronously.
368 */
369nss_tx_status_t nss_wifili_tx_msg_sync(struct nss_ctx_instance *nss_ctx, struct nss_wifili_msg *nvm)
370{
371 nss_tx_status_t status;
372 int ret = 0;
373
374 down(&wifili_pvt.sem);
375 wifili_pvt.cb = (void *)nvm->cm.cb;
376 wifili_pvt.app_data = (void *)nvm->cm.app_data;
377
378 nvm->cm.cb = (nss_ptr_t)nss_wifili_callback;
379 nvm->cm.app_data = (nss_ptr_t)NULL;
380
381 status = nss_wifili_tx_msg(nss_ctx, nvm);
382 if (status != NSS_TX_SUCCESS) {
383 nss_warning("%p: wifili_tx_msg failed\n", nss_ctx);
384 up(&wifili_pvt.sem);
385 return status;
386 }
387
388 ret = wait_for_completion_timeout(&wifili_pvt.complete, msecs_to_jiffies(NSS_WIFILI_TX_TIMEOUT));
389 if (!ret) {
390 nss_warning("%p: wifili msg tx failed due to timeout\n", nss_ctx);
391 wifili_pvt.response = NSS_TX_FAILURE;
392 }
393
394 status = wifili_pvt.response;
395 up(&wifili_pvt.sem);
396 return status;
397}
398EXPORT_SYMBOL(nss_wifili_tx_msg_sync);
399
400/*
401 * nss_wifili_get_context()
402 */
403struct nss_ctx_instance *nss_wifili_get_context(void)
404{
405 return (struct nss_ctx_instance *)&nss_top_main.nss[nss_top_main.wifi_handler_id];
406}
407EXPORT_SYMBOL(nss_wifili_get_context);
408
409/*
410 * nss_wifili_msg_init()
411 * Initialize nss_wifili_msg.
412 */
413void nss_wifili_msg_init(struct nss_wifili_msg *ncm, uint16_t if_num, uint32_t type, uint32_t len, void *cb, void *app_data)
414{
415 nss_cmn_msg_init(&ncm->cm, if_num, type, len, cb, app_data);
416}
417EXPORT_SYMBOL(nss_wifili_msg_init);
418
419/*
420 ****************************************
421 * Register/Unregister/Miscellaneous APIs
422 ****************************************
423 */
424
425/*
426 * nss_register_wifili_if()
427 * Register wifili with nss driver
428 */
429struct nss_ctx_instance *nss_register_wifili_if(uint32_t if_num, nss_wifili_callback_t wifili_callback,
430 nss_wifili_callback_t wifili_ext_callback,
431 nss_wifili_msg_callback_t event_callback, struct net_device *netdev, uint32_t features)
432{
433 struct nss_ctx_instance *nss_ctx = (struct nss_ctx_instance *)&nss_top_main.nss[nss_top_main.wifi_handler_id];
434
435 /*
436 * The interface number shall be wifili soc interface
437 */
438 nss_assert(if_num == NSS_WIFILI_INTERFACE);
439
Aniruddha Paul1b170c22017-05-29 12:30:39 +0530440 nss_info("nss_register_wifili_if if_num %d wifictx %p", if_num, netdev);
Varsha Mishrae58d93b2017-05-20 20:54:41 +0530441
442 nss_ctx->subsys_dp_register[if_num].ndev = netdev;
443 nss_ctx->subsys_dp_register[if_num].cb = wifili_callback;
444 nss_ctx->subsys_dp_register[if_num].ext_cb = wifili_ext_callback;
445 nss_ctx->subsys_dp_register[if_num].app_data = NULL;
446 nss_ctx->subsys_dp_register[if_num].features = features;
447
448 nss_top_main.wifili_msg_callback = event_callback;
449 nss_core_register_handler(if_num, nss_wifili_handler, NULL);
450
451 return (struct nss_ctx_instance *)&nss_top_main.nss[nss_top_main.wifi_handler_id];
452}
453EXPORT_SYMBOL(nss_register_wifili_if);
454
455/*
456 * nss_unregister_wifili_if()
457 * Unregister wifili with nss driver
458 */
459void nss_unregister_wifili_if(uint32_t if_num)
460{
461 struct nss_ctx_instance *nss_ctx = (struct nss_ctx_instance *)&nss_top_main.nss[nss_top_main.wifi_handler_id];
462
463 /*
464 * The interface number shall be wifili soc interface
465 */
466 nss_assert(if_num == NSS_WIFILI_INTERFACE);
467
468 nss_ctx->subsys_dp_register[if_num].ndev = NULL;
469 nss_ctx->subsys_dp_register[if_num].cb = NULL;
470 nss_ctx->subsys_dp_register[if_num].ext_cb = NULL;
471 nss_ctx->subsys_dp_register[if_num].app_data = NULL;
472 nss_ctx->subsys_dp_register[if_num].features = 0;
473}
474EXPORT_SYMBOL(nss_unregister_wifili_if);
475
476/*
477 * nss_register_wifili_radio_if()
478 * Register wifili radio with nss driver
479 */
480struct nss_ctx_instance *nss_register_wifili_radio_if(uint32_t if_num, nss_wifili_callback_t wifili_callback,
481 nss_wifili_callback_t wifili_ext_callback,
482 nss_wifili_msg_callback_t event_callback, struct net_device *netdev, uint32_t features)
483{
484 struct nss_ctx_instance *nss_ctx = (struct nss_ctx_instance *)&nss_top_main.nss[nss_top_main.wifi_handler_id];
485
486 /*
487 * The interface number shall be wifili radio dynamic interface
488 */
489 nss_assert(nss_is_dynamic_interface(if_num));
Aniruddha Paul1b170c22017-05-29 12:30:39 +0530490 nss_info("nss_register_wifili_if if_num %d wifictx %p", if_num, netdev);
Varsha Mishrae58d93b2017-05-20 20:54:41 +0530491
492 nss_ctx->subsys_dp_register[if_num].ndev = netdev;
493 nss_ctx->subsys_dp_register[if_num].cb = wifili_callback;
494 nss_ctx->subsys_dp_register[if_num].ext_cb = wifili_ext_callback;
495 nss_ctx->subsys_dp_register[if_num].app_data = NULL;
496 nss_ctx->subsys_dp_register[if_num].features = features;
497
498 return (struct nss_ctx_instance *)&nss_top_main.nss[nss_top_main.wifi_handler_id];
499}
500EXPORT_SYMBOL(nss_register_wifili_radio_if);
501
502/*
503 * nss_unregister_wifili_radio_if()
504 * Unregister wifili radio with nss driver
505 */
506void nss_unregister_wifili_radio_if(uint32_t if_num)
507{
508 struct nss_ctx_instance *nss_ctx = (struct nss_ctx_instance *)&nss_top_main.nss[nss_top_main.wifi_handler_id];
509
510 /*
511 * The interface number shall be wifili radio dynamic interface
512 */
513 nss_assert(nss_is_dynamic_interface(if_num));
514
515 nss_ctx->subsys_dp_register[if_num].ndev = NULL;
516 nss_ctx->subsys_dp_register[if_num].cb = NULL;
517 nss_ctx->subsys_dp_register[if_num].ext_cb = NULL;
518 nss_ctx->subsys_dp_register[if_num].app_data = NULL;
519 nss_ctx->subsys_dp_register[if_num].features = 0;
520}
521EXPORT_SYMBOL(nss_unregister_wifili_radio_if);
522
523/*
524 * nss_wifili_register_handler()
525 * Register handle for notfication messages received on wifi interface
526 */
Aniruddha Paul1b170c22017-05-29 12:30:39 +0530527void nss_wifili_register_handler(void)
Varsha Mishrae58d93b2017-05-20 20:54:41 +0530528{
529 nss_info("nss_wifili_register_handler");
530 nss_core_register_handler(NSS_WIFILI_INTERFACE, nss_wifili_handler, NULL);
531
532 sema_init(&wifili_pvt.sem, 1);
533 init_completion(&wifili_pvt.complete);
534}