blob: 3c0af95916f7763b83152c2ba12ca5697dec2237 [file] [log] [blame]
Saurabh Misra09dddeb2014-09-30 16:38:07 -07001/*
2 **************************************************************************
Stephen Wangaed46332016-12-12 17:29:03 -08003 * Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
Saurabh Misra09dddeb2014-09-30 16:38:07 -07004 * 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 /*
18 * nss_capwap.h
19 * NSS CAPWAP driver interface APIs
20 */
21#include "nss_core.h"
Saurabh Misra09dddeb2014-09-30 16:38:07 -070022#include "nss_capwap.h"
Stephen Wang1f6ad492016-01-27 23:42:06 -080023#include "nss_cmn.h"
24#include "nss_tx_rx_common.h"
Saurabh Misra09dddeb2014-09-30 16:38:07 -070025
26/*
27 * Spinlock for protecting tunnel operations colliding with a tunnel destroy
28 */
29DEFINE_SPINLOCK(nss_capwap_spinlock);
30
31/*
32 * Array of pointer for NSS CAPWAP handles. Each handle has per-tunnel
33 * stats based on the if_num which is an index.
34 *
35 * Per CAPWAP tunnel/interface number instance.
36 */
37struct nss_capwap_handle {
38 atomic_t refcnt; /**< Reference count on the tunnel */
Saurabh Misraf4a05632015-02-27 17:49:41 -080039 uint32_t if_num; /**< Interface number */
Saurabh Misra09dddeb2014-09-30 16:38:07 -070040 uint32_t tunnel_status; /**< 0=disable, 1=enabled */
41 struct nss_ctx_instance *ctx; /**< Pointer to context */
42 nss_capwap_msg_callback_t msg_callback; /**< Msg callback */
43 void *app_data; /**< App data (argument) */
44 struct nss_capwap_tunnel_stats stats; /**< Stats per-interface number */
45};
46static struct nss_capwap_handle *nss_capwap_hdl[NSS_MAX_DYNAMIC_INTERFACES];
47
48/*
Saurabh Misra09dddeb2014-09-30 16:38:07 -070049 * nss_capwap_verify_if_num()
50 * Verify if_num passed to us.
51 */
52static bool nss_capwap_verify_if_num(uint32_t if_num)
53{
54 if (nss_is_dynamic_interface(if_num) == false) {
55 return false;
56 }
57
Stephen Wange8b8d0d2017-02-24 17:05:22 -080058 if (nss_dynamic_interface_get_type(nss_capwap_get_ctx(), if_num) != NSS_DYNAMIC_INTERFACE_TYPE_CAPWAP) {
Saurabh Misra09dddeb2014-09-30 16:38:07 -070059 return false;
60 }
61
62 return true;
63}
64
65/*
66 * nss_capwap_refcnt_inc()
67 * Increments refcnt on the tunnel.
68 */
69static void nss_capwap_refcnt_inc(int32_t if_num)
70{
71 if_num = if_num - NSS_DYNAMIC_IF_START;
72 atomic_inc(&nss_capwap_hdl[if_num]->refcnt);
73 nss_assert(atomic_read(&nss_capwap_hdl[if_num]->refcnt) > 0);
74}
75
76/*
77 * nss_capwap_refcnt_dec()
78 * Decrements refcnt on the tunnel.
79 */
80static void nss_capwap_refcnt_dec(int32_t if_num)
81{
82 if_num = if_num - NSS_DYNAMIC_IF_START;
83 nss_assert(atomic_read(&nss_capwap_hdl[if_num]->refcnt) > 0);
84 atomic_dec(&nss_capwap_hdl[if_num]->refcnt);
85}
86
87/*
Saurabh Misraf4a05632015-02-27 17:49:41 -080088 * nss_capwap_refcnt()
Saurabh Misra09dddeb2014-09-30 16:38:07 -070089 * Get refcnt on the tunnel.
90 */
Saurabh Misraf4a05632015-02-27 17:49:41 -080091static uint32_t nss_capwap_refcnt(int32_t if_num)
Saurabh Misra09dddeb2014-09-30 16:38:07 -070092{
93 if_num = if_num - NSS_DYNAMIC_IF_START;
94 return atomic_read(&nss_capwap_hdl[if_num]->refcnt);
95}
96
97/*
98 * nss_capwap_set_msg_callback()
99 * This sets the message callback handler and its associated context
100 */
101static void nss_capwap_set_msg_callback(int32_t if_num, nss_capwap_msg_callback_t cb, void *app_data)
102{
103 struct nss_capwap_handle *h;
104
105 h = nss_capwap_hdl[if_num - NSS_DYNAMIC_IF_START];
106 if (!h) {
107 return;
108 }
109
110 h->app_data = app_data;
111 h->msg_callback = cb;
112}
113
114/*
Saurabh Misra3e9f8b02015-03-16 13:30:57 -0700115 * nss_capwap_get_msg_callback()
Saurabh Misra09dddeb2014-09-30 16:38:07 -0700116 * This gets the message callback handler and its associated context
117 */
Saurabh Misra3e9f8b02015-03-16 13:30:57 -0700118static nss_capwap_msg_callback_t nss_capwap_get_msg_callback(int32_t if_num, void **app_data)
Saurabh Misra09dddeb2014-09-30 16:38:07 -0700119{
120 struct nss_capwap_handle *h;
121
122 h = nss_capwap_hdl[if_num - NSS_DYNAMIC_IF_START];
123 if (!h) {
124 *app_data = NULL;
125 return NULL;
126 }
127
128 *app_data = h->app_data;
129 return h->msg_callback;
130}
131
132/*
133 * nss_capwapmgr_update_stats()
134 * Update per-tunnel stats for each CAPWAP interface.
135 */
136static void nss_capwapmgr_update_stats(struct nss_capwap_handle *handle, struct nss_capwap_stats_msg *fstats)
137{
138 struct nss_capwap_tunnel_stats *stats;
139
140 stats = &handle->stats;
141
142 stats->rx_segments += fstats->rx_segments;
Saurabh Misra09dddeb2014-09-30 16:38:07 -0700143 stats->dtls_pkts += fstats->dtls_pkts;
Saurabh Misra6db99b52014-12-08 10:33:08 -0800144
145 stats->rx_dup_frag += fstats->rx_dup_frag;
Saurabh Misra3f66e872015-04-03 11:30:42 -0700146 stats->rx_oversize_drops += fstats->rx_oversize_drops;
147 stats->rx_frag_timeout_drops += fstats->rx_frag_timeout_drops;
Saurabh Misra09dddeb2014-09-30 16:38:07 -0700148 stats->rx_queue_full_drops += fstats->rx_queue_full_drops;
149 stats->rx_n2h_queue_full_drops += fstats->rx_n2h_queue_full_drops;
150 stats->rx_mem_failure_drops += fstats->rx_mem_failure_drops;
Saurabh Misra3f66e872015-04-03 11:30:42 -0700151 stats->rx_csum_drops += fstats->rx_csum_drops;
152 stats->rx_malformed += fstats->rx_malformed;
153 stats->rx_frag_gap_drops += fstats->rx_frag_gap_drops;
Saurabh Misra09dddeb2014-09-30 16:38:07 -0700154
Saurabh Misra3f66e872015-04-03 11:30:42 -0700155 stats->tx_segments += fstats->tx_segments;
Saurabh Misra09dddeb2014-09-30 16:38:07 -0700156 stats->tx_queue_full_drops += fstats->tx_queue_full_drops;
157 stats->tx_mem_failure_drops += fstats->tx_mem_failure_drops;
Saurabh Misra3f66e872015-04-03 11:30:42 -0700158 stats->tx_dropped_sg_ref += fstats->tx_dropped_sg_ref;
159 stats->tx_dropped_ver_mis += fstats->tx_dropped_ver_mis;
160 stats->tx_dropped_hroom += fstats->tx_dropped_hroom;
161 stats->tx_dropped_dtls += fstats->tx_dropped_dtls;
162 stats->tx_dropped_nwireless += fstats->tx_dropped_nwireless;
163 stats->tx_dropped_unalign += fstats->tx_dropped_unalign;
Saurabh Misra6db99b52014-12-08 10:33:08 -0800164
Saurabh Misra09dddeb2014-09-30 16:38:07 -0700165 /*
166 * add pnode stats now.
167 */
168 stats->pnode_stats.rx_packets += fstats->pnode_stats.rx_packets;
169 stats->pnode_stats.rx_bytes += fstats->pnode_stats.rx_bytes;
170 stats->pnode_stats.rx_dropped += fstats->pnode_stats.rx_dropped;
171 stats->pnode_stats.tx_packets += fstats->pnode_stats.tx_packets;
172 stats->pnode_stats.tx_bytes += fstats->pnode_stats.tx_bytes;
173}
174
175/*
176 * nss_capwap_handler()
177 * Handle NSS -> HLOS messages for CAPWAP
178 */
Saurabh Misra3e9f8b02015-03-16 13:30:57 -0700179static void nss_capwap_msg_handler(struct nss_ctx_instance *nss_ctx, struct nss_cmn_msg *ncm, __attribute__((unused))void *app_data)
Saurabh Misra09dddeb2014-09-30 16:38:07 -0700180{
181 struct nss_capwap_msg *ntm = (struct nss_capwap_msg *)ncm;
182 nss_capwap_msg_callback_t cb;
183
184 /*
185 * Is this a valid request/response packet?
186 */
187 if (ncm->type > NSS_CAPWAP_MSG_TYPE_MAX) {
188 nss_warning("%p: received invalid message %d for CAPWAP interface", nss_ctx, ncm->type);
189 return;
190 }
191
Suruchi Agarwalef8a8702016-01-08 12:40:08 -0800192 if (nss_cmn_get_msg_len(ncm) > sizeof(struct nss_capwap_msg)) {
193 nss_warning("%p: Length of message is greater than required: %d", nss_ctx, nss_cmn_get_msg_len(ncm));
Saurabh Misra09dddeb2014-09-30 16:38:07 -0700194 return;
195 }
196
197 nss_core_log_msg_failures(nss_ctx, ncm);
198
199 switch (ntm->cm.type) {
200 case NSS_CAPWAP_MSG_TYPE_SYNC_STATS: {
201 uint32_t if_num;
202
203 if_num = ncm->interface - NSS_DYNAMIC_IF_START;
204 if (nss_capwap_hdl[if_num] != NULL) {
205 nss_capwapmgr_update_stats(nss_capwap_hdl[if_num], &ntm->msg.stats);
206 }
207 }
208 }
209
210 /*
211 * Update the callback and app_data for NOTIFY messages.
212 */
213 if (ncm->response == NSS_CMM_RESPONSE_NOTIFY) {
Stephen Wangaed46332016-12-12 17:29:03 -0800214 ncm->cb = (nss_ptr_t)nss_capwap_get_msg_callback(ncm->interface, (void **)&ncm->app_data);
Saurabh Misra09dddeb2014-09-30 16:38:07 -0700215 }
216
217 /*
218 * Do we have a callback
219 */
220 if (!ncm->cb) {
221 nss_trace("%p: cb is null for interface %d", nss_ctx, ncm->interface);
222 return;
223 }
224
225 cb = (nss_capwap_msg_callback_t)ncm->cb;
Saurabh Misra3e9f8b02015-03-16 13:30:57 -0700226 cb((void *)ncm->app_data, ntm);
Saurabh Misra09dddeb2014-09-30 16:38:07 -0700227}
228
229/*
230 * nss_capwap_instance_alloc()
231 * Allocate CAPWAP tunnel instance
232 */
233static bool nss_capwap_instance_alloc(struct nss_ctx_instance *nss_ctx, uint32_t if_num)
234{
235 struct nss_capwap_handle *h;
236
237 /*
238 * Allocate a handle
239 */
240 h = kmalloc(sizeof(struct nss_capwap_handle), GFP_ATOMIC);
241 if (h == NULL) {
242 nss_warning("%p: no memory for allocating CAPWAP instance for interface : %d", nss_ctx, if_num);
243 return false;
244 }
Saurabh Misraf4a05632015-02-27 17:49:41 -0800245
246 memset(h, 0, sizeof(struct nss_capwap_handle));
247 h->if_num = if_num;
Saurabh Misra09dddeb2014-09-30 16:38:07 -0700248
249 spin_lock(&nss_capwap_spinlock);
250 if (nss_capwap_hdl[if_num - NSS_DYNAMIC_IF_START] != NULL) {
251 spin_unlock(&nss_capwap_spinlock);
252 kfree(h);
253 nss_warning("%p: Another thread is already allocated instance for :%d", nss_ctx, if_num);
254 return false;
255 }
256
257 nss_capwap_hdl[if_num - NSS_DYNAMIC_IF_START] = h;
258 spin_unlock(&nss_capwap_spinlock);
259
260 return true;
261}
262
263/*
264 * nss_capwap_tx_msg()
265 * Transmit a CAPWAP message to NSS FW. Don't call this from softirq/interrupts.
266 */
267nss_tx_status_t nss_capwap_tx_msg(struct nss_ctx_instance *nss_ctx, struct nss_capwap_msg *msg)
268{
269 struct nss_capwap_msg *nm;
270 struct nss_cmn_msg *ncm = &msg->cm;
271 struct sk_buff *nbuf;
272 int32_t status;
273 int32_t if_num;
274
275 BUG_ON(in_interrupt());
276 BUG_ON(in_softirq());
277 BUG_ON(in_serving_softirq());
278
279 if (nss_capwap_verify_if_num(msg->cm.interface) == false) {
280 return NSS_TX_FAILURE_BAD_PARAM;
281 }
282
283 if (ncm->type >= NSS_CAPWAP_MSG_TYPE_MAX) {
284 return NSS_TX_FAILURE_BAD_PARAM;
285 }
286
287 if_num = msg->cm.interface - NSS_DYNAMIC_IF_START;
288 spin_lock(&nss_capwap_spinlock);
289 if (!nss_capwap_hdl[if_num]) {
290 spin_unlock(&nss_capwap_spinlock);
291 nss_warning("%p: capwap tunnel if_num is not there: %d", nss_ctx, msg->cm.interface);
292 return NSS_TX_FAILURE_BAD_PARAM;
293 }
294 nss_capwap_refcnt_inc(msg->cm.interface);
295 spin_unlock(&nss_capwap_spinlock);
296
297 if (unlikely(nss_ctx->state != NSS_CORE_STATE_INITIALIZED)) {
298 nss_warning("%p: capwap msg dropped as core not ready", nss_ctx);
299 status = NSS_TX_FAILURE_NOT_READY;
300 goto out;
301 }
302
Suruchi Agarwalef8a8702016-01-08 12:40:08 -0800303 if (nss_cmn_get_msg_len(ncm) > sizeof(struct nss_capwap_msg)) {
304 nss_warning("%p: message length is invalid: %d", nss_ctx, nss_cmn_get_msg_len(ncm));
Saurabh Misra09dddeb2014-09-30 16:38:07 -0700305 status = NSS_TX_FAILURE_BAD_PARAM;
306 goto out;
307 }
308
309 nbuf = dev_alloc_skb(NSS_NBUF_PAYLOAD_SIZE);
310 if (unlikely(!nbuf)) {
Sundarajan Srinivasan62fee7e2015-01-22 11:13:10 -0800311 NSS_PKT_STATS_INCREMENT(nss_ctx, &nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_NBUF_ALLOC_FAILS]);
Saurabh Misra09dddeb2014-09-30 16:38:07 -0700312 nss_warning("%p: msg dropped as command allocation failed", nss_ctx);
313 status = NSS_TX_FAILURE;
314 goto out;
315 }
316
317 /*
318 * Copy the message to our skb
319 */
320 nm = (struct nss_capwap_msg *)skb_put(nbuf, sizeof(struct nss_capwap_msg));
321 memcpy(nm, msg, sizeof(struct nss_capwap_msg));
322
323 status = nss_core_send_buffer(nss_ctx, 0, nbuf, NSS_IF_CMD_QUEUE, H2N_BUFFER_CTRL, 0);
324 if (status != NSS_CORE_STATUS_SUCCESS) {
325 dev_kfree_skb_any(nbuf);
326 nss_warning("%p: Unable to enqueue 'capwap message' \n", nss_ctx);
327 goto out;
328 }
329
Stephen Wang90c67de2016-04-26 15:15:59 -0700330 nss_hal_send_interrupt(nss_ctx, NSS_H2N_INTR_DATA_COMMAND_QUEUE);
Saurabh Misra09dddeb2014-09-30 16:38:07 -0700331
332 NSS_PKT_STATS_INCREMENT(nss_ctx, &nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_TX_CMD_REQ]);
333
334out:
335 nss_capwap_refcnt_dec(msg->cm.interface);
336 return status;
337}
338EXPORT_SYMBOL(nss_capwap_tx_msg);
339
340/*
Stephen Wangcf9c21c2016-02-18 17:54:16 -0800341 * nss_capwap_tx_buf()
Saurabh Misra09dddeb2014-09-30 16:38:07 -0700342 * Transmit data buffer (skb) to a NSS interface number
343 */
Stephen Wangcf9c21c2016-02-18 17:54:16 -0800344nss_tx_status_t nss_capwap_tx_buf(struct nss_ctx_instance *nss_ctx, struct sk_buff *os_buf, uint32_t if_num)
Saurabh Misra09dddeb2014-09-30 16:38:07 -0700345{
Stephen Wangcf9c21c2016-02-18 17:54:16 -0800346 int32_t status;
Stephen Wangcf9c21c2016-02-18 17:54:16 -0800347
348 NSS_VERIFY_CTX_MAGIC(nss_ctx);
349
350 if (unlikely(nss_ctx->state != NSS_CORE_STATE_INITIALIZED)) {
351 nss_warning("%p: NSS core is not ready", nss_ctx);
352 return NSS_TX_FAILURE_NOT_READY;
353 }
354
355 BUG_ON(!nss_capwap_verify_if_num(if_num));
356
Stephen Wangcf9c21c2016-02-18 17:54:16 -0800357 status = nss_core_send_buffer(nss_ctx, if_num, os_buf, NSS_IF_DATA_QUEUE_0, H2N_BUFFER_PACKET, H2N_BIT_FLAG_VIRTUAL_BUFFER);
358 if (unlikely(status != NSS_CORE_STATUS_SUCCESS)) {
359 nss_warning("%p: Unable to enqueue capwap packet\n", nss_ctx);
360 if (status == NSS_CORE_STATUS_FAILURE_QUEUE) {
361 return NSS_TX_FAILURE_QUEUE;
362 }
363 return NSS_TX_FAILURE;
364 }
365
Stephen Wang90c67de2016-04-26 15:15:59 -0700366 nss_hal_send_interrupt(nss_ctx, NSS_H2N_INTR_DATA_COMMAND_QUEUE);
Stephen Wangcf9c21c2016-02-18 17:54:16 -0800367
368 NSS_PKT_STATS_INCREMENT(nss_ctx, &nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_TX_PACKET]);
369 return NSS_TX_SUCCESS;
Saurabh Misra09dddeb2014-09-30 16:38:07 -0700370}
Stephen Wangcf9c21c2016-02-18 17:54:16 -0800371EXPORT_SYMBOL(nss_capwap_tx_buf);
Saurabh Misra09dddeb2014-09-30 16:38:07 -0700372
373/*
374 ***********************************
375 * Register/Unregister/Miscellaneous APIs
376 ***********************************
377 */
378
379/*
380 * nss_capwap_get_stats()
381 * API for getting stats from a CAPWAP tunnel interface stats
382 */
383bool nss_capwap_get_stats(uint32_t if_num, struct nss_capwap_tunnel_stats *stats)
384{
385 if (nss_capwap_verify_if_num(if_num) == false) {
386 return false;
387 }
388
389 if_num = if_num - NSS_DYNAMIC_IF_START;
390 spin_lock(&nss_capwap_spinlock);
391 if (nss_capwap_hdl[if_num] == NULL) {
392 spin_unlock(&nss_capwap_spinlock);
393 return false;
394 }
395
396 memcpy(stats, &nss_capwap_hdl[if_num]->stats, sizeof(struct nss_capwap_tunnel_stats));
397 spin_unlock(&nss_capwap_spinlock);
398 return true;
399}
400EXPORT_SYMBOL(nss_capwap_get_stats);
401
402/*
403 * nss_capwap_notify_register()
404 * Registers a message notifier with NSS FW. It should not be called from
405 * softirq or interrupts.
406 */
407struct nss_ctx_instance *nss_capwap_notify_register(uint32_t if_num, nss_capwap_msg_callback_t cb, void *app_data)
408{
409 struct nss_ctx_instance *nss_ctx;
410
411 nss_ctx = &nss_top_main.nss[nss_top_main.capwap_handler_id];
412
413 if (nss_capwap_verify_if_num(if_num) == false) {
414 nss_warning("%p: notfiy register received for invalid interface %d", nss_ctx, if_num);
415 return NULL;
416 }
417
418 spin_lock(&nss_capwap_spinlock);
419 if (nss_capwap_hdl[if_num - NSS_DYNAMIC_IF_START] != NULL) {
420 spin_unlock(&nss_capwap_spinlock);
421 nss_warning("%p: notfiy register tunnel already exists for interface %d", nss_ctx, if_num);
422 return NULL;
423 }
424 spin_unlock(&nss_capwap_spinlock);
425
426 return nss_ctx;
427}
428EXPORT_SYMBOL(nss_capwap_notify_register);
429
430/*
431 * nss_capwap_notify_unregister()
432 * unregister the CAPWAP notifier for the given interface number (if_num).
433 * It shouldn't be called from softirq or interrupts.
434 */
435nss_tx_status_t nss_capwap_notify_unregister(struct nss_ctx_instance *nss_ctx, uint32_t if_num)
436{
437 struct nss_top_instance *nss_top;
438 int index;
439
440 if (nss_capwap_verify_if_num(if_num) == false) {
441 nss_warning("%p: notify unregister received for invalid interface %d", nss_ctx, if_num);
442 return NSS_TX_FAILURE_BAD_PARAM;
443 }
444
445 nss_top = nss_ctx->nss_top;
446 if (nss_top == NULL) {
447 nss_warning("%p: notify unregister received for invalid nss_top %d", nss_ctx, if_num);
448 return NSS_TX_FAILURE_BAD_PARAM;
449 }
450
451 index = if_num - NSS_DYNAMIC_IF_START;
452 spin_lock(&nss_capwap_spinlock);
453 if (nss_capwap_hdl[index] == NULL) {
454 spin_unlock(&nss_capwap_spinlock);
455 nss_warning("%p: notify unregister received for unallocated if_num: %d", nss_ctx, if_num);
456 return NSS_TX_FAILURE_BAD_PARAM;
457 }
458
459 /*
460 * It's the responsibility of caller to wait and call us again. We return failure saying
461 * that we can't remove msg handler now.
462 */
Saurabh Misraf4a05632015-02-27 17:49:41 -0800463 if (nss_capwap_refcnt(if_num) != 0) {
Saurabh Misra09dddeb2014-09-30 16:38:07 -0700464 spin_unlock(&nss_capwap_spinlock);
465 nss_warning("%p: notify unregister tunnel %d: has reference", nss_ctx, if_num);
466 return NSS_TX_FAILURE_QUEUE;
467 }
468
469 nss_capwap_set_msg_callback(if_num, NULL, NULL);
470 spin_unlock(&nss_capwap_spinlock);
471
472 return NSS_TX_SUCCESS;
473}
474EXPORT_SYMBOL(nss_capwap_notify_unregister);
475
476/*
477 * nss_capwap_data_register()
478 * Registers a data packet notifier with NSS FW.
479 */
Sundarajan Srinivasan70374842014-11-19 15:22:52 -0800480struct nss_ctx_instance *nss_capwap_data_register(uint32_t if_num, nss_capwap_buf_callback_t cb, struct net_device *netdev, uint32_t features)
Saurabh Misra09dddeb2014-09-30 16:38:07 -0700481{
482 struct nss_ctx_instance *nss_ctx;
483 int core_status;
484
485 nss_ctx = nss_capwap_get_ctx();
486 if (nss_capwap_verify_if_num(if_num) == false) {
487 nss_warning("%p: data register received for invalid interface %d", nss_ctx, if_num);
488 return NULL;
489 }
490
491 spin_lock(&nss_capwap_spinlock);
Stephen Wang84e0e992016-09-07 12:31:40 -0700492 if (nss_ctx->subsys_dp_register[if_num].ndev != NULL) {
Saurabh Misra09dddeb2014-09-30 16:38:07 -0700493 spin_unlock(&nss_capwap_spinlock);
494 return NULL;
495 }
496 spin_unlock(&nss_capwap_spinlock);
497
Thomas Wu91f4bdf2017-06-09 12:03:02 -0700498 core_status = nss_core_register_handler(nss_ctx, if_num, nss_capwap_msg_handler, NULL);
Saurabh Misra09dddeb2014-09-30 16:38:07 -0700499 if (core_status != NSS_CORE_STATUS_SUCCESS) {
500 nss_warning("%p: nss core register handler failed for if_num:%d with error :%d", nss_ctx, if_num, core_status);
501 return NULL;
502 }
503
504 if (nss_capwap_instance_alloc(nss_ctx, if_num) == false) {
505 nss_warning("%p: couldn't allocate tunnel instance for if_num:%d", nss_ctx, if_num);
506 return NULL;
507 }
508
Stephen Wang84e0e992016-09-07 12:31:40 -0700509 nss_ctx->subsys_dp_register[if_num].cb = cb;
510 nss_ctx->subsys_dp_register[if_num].app_data = NULL;
511 nss_ctx->subsys_dp_register[if_num].ndev = netdev;
512 nss_ctx->subsys_dp_register[if_num].features = features;
Saurabh Misra09dddeb2014-09-30 16:38:07 -0700513
514 return nss_ctx;
515}
516EXPORT_SYMBOL(nss_capwap_data_register);
517
518/*
519 * nss_capwap_data_unregister()
520 * Unregister a data packet notifier with NSS FW
521 */
522bool nss_capwap_data_unregister(uint32_t if_num)
523{
524 struct nss_ctx_instance *nss_ctx;
525 struct nss_capwap_handle *h;
526
527 nss_ctx = nss_capwap_get_ctx();
528 if (nss_capwap_verify_if_num(if_num) == false) {
529 nss_warning("%p: data unregister received for invalid interface %d", nss_ctx, if_num);
530 return false;
531 }
532
533 spin_lock(&nss_capwap_spinlock);
534 /*
535 * It's the responsibility of caller to wait and call us again.
536 */
Saurabh Misraf4a05632015-02-27 17:49:41 -0800537 if (nss_capwap_refcnt(if_num) != 0) {
Saurabh Misra09dddeb2014-09-30 16:38:07 -0700538 spin_unlock(&nss_capwap_spinlock);
539 nss_warning("%p: notify unregister tunnel %d: has reference", nss_ctx, if_num);
540 return false;
541 }
542 h = nss_capwap_hdl[if_num - NSS_DYNAMIC_IF_START];
543 nss_capwap_hdl[if_num - NSS_DYNAMIC_IF_START] = NULL;
544 spin_unlock(&nss_capwap_spinlock);
545
Thomas Wu91f4bdf2017-06-09 12:03:02 -0700546 (void) nss_core_unregister_handler(nss_ctx, if_num);
Saurabh Misra09dddeb2014-09-30 16:38:07 -0700547
Stephen Wang84e0e992016-09-07 12:31:40 -0700548 nss_ctx->subsys_dp_register[if_num].cb = NULL;
549 nss_ctx->subsys_dp_register[if_num].app_data = NULL;
550 nss_ctx->subsys_dp_register[if_num].ndev = NULL;
551 nss_ctx->subsys_dp_register[if_num].features = 0;
Sundarajan Srinivasan70374842014-11-19 15:22:52 -0800552
Saurabh Misra09dddeb2014-09-30 16:38:07 -0700553 kfree(h);
554 return true;
555}
556EXPORT_SYMBOL(nss_capwap_data_unregister);
557
558/*
559 * nss_capwap_get_ctx()
560 * Return a CAPWAP NSS context.
561 */
562struct nss_ctx_instance *nss_capwap_get_ctx()
563{
564 struct nss_ctx_instance *nss_ctx;
565
566 nss_ctx = &nss_top_main.nss[nss_top_main.capwap_handler_id];
567 return nss_ctx;
568}
569EXPORT_SYMBOL(nss_capwap_get_ctx);
570
571/*
Stephen Wang1f6ad492016-01-27 23:42:06 -0800572 * nss_capwap_ifnum_with_core_id()
573 * Append core id to capwap interface num
574 */
575int nss_capwap_ifnum_with_core_id(int if_num)
576{
577 struct nss_ctx_instance *nss_ctx = nss_capwap_get_ctx();
578
579 NSS_VERIFY_CTX_MAGIC(nss_ctx);
580 if (nss_is_dynamic_interface(if_num) == false) {
581 nss_info("%p: Invalid if_num: %d, must be a dynamic interface\n", nss_ctx, if_num);
582 return 0;
583 }
584 return NSS_INTERFACE_NUM_APPEND_COREID(nss_ctx, if_num);
585}
586EXPORT_SYMBOL(nss_capwap_ifnum_with_core_id);
587
588/*
Sundarajan Srinivasan40bea952014-12-02 13:19:34 -0800589 * nss_capwap_get_max_buf_size()
590 * Return a CAPWAP NSS max_buf_size.
591 */
592uint32_t nss_capwap_get_max_buf_size(struct nss_ctx_instance *nss_ctx)
593{
594 return nss_core_get_max_buf_size(nss_ctx);
595}
596EXPORT_SYMBOL(nss_capwap_get_max_buf_size);
597
598/*
Saurabh Misra09dddeb2014-09-30 16:38:07 -0700599 * nss_capwap_init()
600 * Initializes CAPWAP. Gets called from nss_init.c
601 */
602void nss_capwap_init()
603{
604 memset(&nss_capwap_hdl, 0, sizeof(nss_capwap_hdl));
605}
Sundarajan Srinivasan02e6c2b2014-10-06 11:51:12 -0700606
607/*
608 * nss_capwap_msg_init()
609 * Initialize capwap message.
610 */
611void nss_capwap_msg_init(struct nss_capwap_msg *ncm, uint16_t if_num, uint32_t type, uint32_t len,
Sundarajan Srinivasan30a53d42015-01-30 10:52:08 -0800612 nss_capwap_msg_callback_t cb, void *app_data)
Sundarajan Srinivasan02e6c2b2014-10-06 11:51:12 -0700613{
614 nss_cmn_msg_init(&ncm->cm, if_num, type, len, (void*)cb, app_data);
615}
616EXPORT_SYMBOL(nss_capwap_msg_init);