blob: c4cb85fcfb439a0a32702abe886fae148c52df5f [file] [log] [blame]
Abhishek Rastogi84d95d02014-03-26 19:31:31 +05301/*
2 **************************************************************************
Vijay Dewangan488e5372014-12-29 21:40:11 -08003 * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
Abhishek Rastogi84d95d02014-03-26 19:31:31 +05304 * 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/*
Sundarajan Srinivasanf1e57462014-09-17 15:24:01 -070018 * nss_n2h.c
Abhishek Rastogi84d95d02014-03-26 19:31:31 +053019 * NSS N2H node APIs
20 */
21
22#include "nss_tx_rx_common.h"
23
Vijay Dewangan488e5372014-12-29 21:40:11 -080024#define NSS_CORE_0 0
25#define NSS_CORE_1 1
Pamidipati, Vijayefcc4692014-05-09 14:47:38 +053026
27/*
Vijay Dewangan488e5372014-12-29 21:40:11 -080028 * This number is chosen becuase currently default IPV4 + IPV6
29 * connection size is 1024 + 1024 = 2048.
30 * FYI: However this doesnt have any impact on n2h/ipv6 connections
Pamidipati, Vijayefcc4692014-05-09 14:47:38 +053031 */
Vijay Dewangan488e5372014-12-29 21:40:11 -080032#define NSS_N2H_MIN_EMPTY_POOL_BUF_SZ 2048
33#define NSS_N2H_DEFAULT_EMPTY_POOL_BUF_SZ 8192
Pamidipati, Vijayefcc4692014-05-09 14:47:38 +053034
Vijay Dewangan488e5372014-12-29 21:40:11 -080035int nss_n2h_empty_pool_buf_cfg[NSS_MAX_CORES] __read_mostly = {NSS_N2H_DEFAULT_EMPTY_POOL_BUF_SZ, NSS_N2H_DEFAULT_EMPTY_POOL_BUF_SZ};
Pamidipati, Vijayefcc4692014-05-09 14:47:38 +053036
Vijay Dewangan488e5372014-12-29 21:40:11 -080037struct nss_n2h_registered_data {
38 nss_n2h_msg_callback_t n2h_callback;
39 void *app_data;
40};
Pamidipati, Vijayefcc4692014-05-09 14:47:38 +053041
Vijay Dewangan488e5372014-12-29 21:40:11 -080042static struct nss_n2h_cfg_pvt nss_n2h_nepbcfgp[NSS_MAX_CORES];
43static struct nss_n2h_registered_data nss_n2h_rd[NSS_MAX_CORES];
Pamidipati, Vijayefcc4692014-05-09 14:47:38 +053044
45/*
Sundarajan Srinivasanf1e57462014-09-17 15:24:01 -070046 * nss_n2h_stats_sync()
Abhishek Rastogi84d95d02014-03-26 19:31:31 +053047 * Handle the syncing of NSS statistics.
48 */
Sundarajan Srinivasanf1e57462014-09-17 15:24:01 -070049static void nss_n2h_stats_sync(struct nss_ctx_instance *nss_ctx, struct nss_n2h_stats_sync *nnss)
Abhishek Rastogi84d95d02014-03-26 19:31:31 +053050{
51 struct nss_top_instance *nss_top = nss_ctx->nss_top;
52
53 spin_lock_bh(&nss_top->stats_lock);
54
55 /*
56 * common node stats
57 */
58 nss_ctx->stats_n2h[NSS_STATS_NODE_RX_PKTS] += nnss->node_stats.rx_packets;
59 nss_ctx->stats_n2h[NSS_STATS_NODE_RX_BYTES] += nnss->node_stats.rx_bytes;
60 nss_ctx->stats_n2h[NSS_STATS_NODE_RX_DROPPED] += nnss->node_stats.rx_dropped;
61 nss_ctx->stats_n2h[NSS_STATS_NODE_TX_PKTS] += nnss->node_stats.tx_packets;
62 nss_ctx->stats_n2h[NSS_STATS_NODE_TX_BYTES] += nnss->node_stats.tx_bytes;
63
64 /*
65 * General N2H stats
66 */
Murat Sezgin0c0561d2014-04-09 18:55:58 -070067 nss_ctx->stats_n2h[NSS_STATS_N2H_QUEUE_DROPPED] += nnss->queue_dropped;
68 nss_ctx->stats_n2h[NSS_STATS_N2H_TOTAL_TICKS] += nnss->total_ticks;
69 nss_ctx->stats_n2h[NSS_STATS_N2H_WORST_CASE_TICKS] += nnss->worst_case_ticks;
70 nss_ctx->stats_n2h[NSS_STATS_N2H_ITERATIONS] += nnss->iterations;
Abhishek Rastogi84d95d02014-03-26 19:31:31 +053071
72 /*
Thomas Wu3fd8dd72014-06-11 15:57:05 -070073 * pbuf manager ocm and default pool stats
Abhishek Rastogi84d95d02014-03-26 19:31:31 +053074 */
Thomas Wu3fd8dd72014-06-11 15:57:05 -070075 nss_ctx->stats_n2h[NSS_STATS_N2H_PBUF_OCM_ALLOC_FAILS] += nnss->pbuf_ocm_stats.pbuf_alloc_fails;
76 nss_ctx->stats_n2h[NSS_STATS_N2H_PBUF_OCM_FREE_COUNT] = nnss->pbuf_ocm_stats.pbuf_free_count;
77 nss_ctx->stats_n2h[NSS_STATS_N2H_PBUF_OCM_TOTAL_COUNT] = nnss->pbuf_ocm_stats.pbuf_total_count;
78
79 nss_ctx->stats_n2h[NSS_STATS_N2H_PBUF_DEFAULT_ALLOC_FAILS] += nnss->pbuf_default_stats.pbuf_alloc_fails;
80 nss_ctx->stats_n2h[NSS_STATS_N2H_PBUF_DEFAULT_FREE_COUNT] = nnss->pbuf_default_stats.pbuf_free_count;
81 nss_ctx->stats_n2h[NSS_STATS_N2H_PBUF_DEFAULT_TOTAL_COUNT] = nnss->pbuf_default_stats.pbuf_total_count;
82
83 /*
84 * payload mgr stats
85 */
Abhishek Rastogi84d95d02014-03-26 19:31:31 +053086 nss_ctx->stats_n2h[NSS_STATS_N2H_PAYLOAD_ALLOC_FAILS] += nnss->payload_alloc_fails;
Thomas Wu53679842015-01-22 13:37:35 -080087 nss_ctx->stats_n2h[NSS_STATS_N2H_PAYLOAD_FREE_COUNT] = nnss->payload_free_count;
Abhishek Rastogi84d95d02014-03-26 19:31:31 +053088
Sakthi Vignesh Radhakrishnan2a8ee962014-11-22 13:35:38 -080089 /*
90 * Host <=> NSS control traffic stats
91 */
92 nss_ctx->stats_n2h[NSS_STATS_N2H_H2N_CONTROL_PACKETS] += nnss->h2n_ctrl_pkts;
93 nss_ctx->stats_n2h[NSS_STATS_N2H_H2N_CONTROL_BYTES] += nnss->h2n_ctrl_bytes;
94 nss_ctx->stats_n2h[NSS_STATS_N2H_N2H_CONTROL_PACKETS] += nnss->n2h_ctrl_pkts;
95 nss_ctx->stats_n2h[NSS_STATS_N2H_N2H_CONTROL_BYTES] += nnss->n2h_ctrl_bytes;
96
97 /*
98 * Host <=> NSS control data traffic stats
99 */
100 nss_ctx->stats_n2h[NSS_STATS_N2H_H2N_DATA_PACKETS] += nnss->h2n_data_pkts;
101 nss_ctx->stats_n2h[NSS_STATS_N2H_H2N_DATA_BYTES] += nnss->h2n_data_bytes;
102 nss_ctx->stats_n2h[NSS_STATS_N2H_N2H_DATA_PACKETS] += nnss->n2h_data_pkts;
103 nss_ctx->stats_n2h[NSS_STATS_N2H_N2H_DATA_BYTES] += nnss->n2h_data_bytes;
104
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530105 spin_unlock_bh(&nss_top->stats_lock);
106}
107
108/*
Sundarajan Srinivasanf1e57462014-09-17 15:24:01 -0700109 * nss_n2h_interface_handler()
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530110 * Handle NSS -> HLOS messages for N2H node
111 */
Sundarajan Srinivasanf1e57462014-09-17 15:24:01 -0700112static void nss_n2h_interface_handler(struct nss_ctx_instance *nss_ctx, struct nss_cmn_msg *ncm, __attribute__((unused))void *app_data)
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530113{
114 struct nss_n2h_msg *nnm = (struct nss_n2h_msg *)ncm;
Vijay Dewangan488e5372014-12-29 21:40:11 -0800115 nss_n2h_msg_callback_t cb;
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530116
Sundarajan Srinivasanf1e57462014-09-17 15:24:01 -0700117 BUG_ON(ncm->interface != NSS_N2H_INTERFACE);
118
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530119 /*
120 * Is this a valid request/response packet?
121 */
122 if (nnm->cm.type >= NSS_METADATA_TYPE_N2H_MAX) {
123 nss_warning("%p: received invalid message %d for Offload stats interface", nss_ctx, nnm->cm.type);
124 return;
125 }
126
127 switch (nnm->cm.type) {
Pamidipati, Vijayefcc4692014-05-09 14:47:38 +0530128 case NSS_TX_METADATA_TYPE_N2H_RPS_CFG:
129 nss_ctx->n2h_rps_en = nnm->msg.rps_cfg.enable;
130 nss_info("NSS N2H rps_en %d \n",nnm->msg.rps_cfg.enable);
Vijay Dewangan488e5372014-12-29 21:40:11 -0800131 break;
132
133 case NSS_TX_METADATA_TYPE_N2H_EMPTY_POOL_BUF_CFG:
134 nss_info("%p: empty pool buf cfg response from FW", nss_ctx);
Pamidipati, Vijayefcc4692014-05-09 14:47:38 +0530135 break;
136
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530137 case NSS_RX_METADATA_TYPE_N2H_STATS_SYNC:
Sundarajan Srinivasanf1e57462014-09-17 15:24:01 -0700138 nss_n2h_stats_sync(nss_ctx, &nnm->msg.stats_sync);
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530139 break;
140
141 default:
142 if (ncm->response != NSS_CMN_RESPONSE_ACK) {
143 /*
144 * Check response
145 */
146 nss_info("%p: Received response %d for type %d, interface %d",
147 nss_ctx, ncm->response, ncm->type, ncm->interface);
148 }
149 }
Vijay Dewangan488e5372014-12-29 21:40:11 -0800150
151 /*
152 * Update the callback and app_data for NOTIFY messages, IPv4 sends all notify messages
153 * to the same callback/app_data.
154 */
155 if (nnm->cm.response == NSS_CMM_RESPONSE_NOTIFY) {
156 /*
157 * Place holder for the user to create right call
158 * back and app data when response is NSS_CMM_RESPONSE_NOTIFY
159 */
160 ncm->cb = (uint32_t)nss_n2h_rd[nss_ctx->id].n2h_callback;
161 ncm->app_data = (uint32_t)nss_n2h_rd[nss_ctx->id].app_data;
162 }
163
164 /*
165 * Do we have a callback?
166 */
167 if (!ncm->cb) {
168 return;
169 }
170
171 /*
172 * Callback
173 */
174 cb = (nss_n2h_msg_callback_t)ncm->cb;
175 cb((void *)ncm->app_data, nnm);
176}
177
178/*
179 * nss_n2h_empty_pool_buf_cfg_core1_callback()
180 * call back function for the n2h connection configuration handler
181 */
182static void nss_n2h_empty_pool_buf_cfg_callback(void *app_data,
183 struct nss_n2h_msg *nnm)
184{
185 int core_num = (int)app_data;
186 if (nnm->cm.response != NSS_CMN_RESPONSE_ACK) {
187 struct nss_n2h_empty_pool_buf *nnepbcm;
188 nnepbcm = &nnm->msg.empty_pool_buf_cfg;
189
190 /*
191 * Error, hence we are not updating the nss_n2h_empty_pool_buf
192 * Restore the current_value to its previous state
193 */
194 nss_warning("Core %d empty pool buf set failure: %d\n", core_num, nnm->cm.error);
195 nss_n2h_nepbcfgp[core_num].response = NSS_FAILURE;
196 complete(&nss_n2h_nepbcfgp[core_num].complete);
197 return;
198 }
199
200 /*
201 * Sucess at NSS FW, hence updating nss_n2h_empty_pool_buf, with the valid value
202 * saved at the sysctl handler.
203 */
204 nss_info("Core %d empty pool buf set success: %d\n", core_num, nnm->cm.error);
205 nss_n2h_nepbcfgp[core_num].response = NSS_SUCCESS;
206 complete(&nss_n2h_nepbcfgp[core_num].complete);
207}
208
209/*
210 * nss_n2h_empty_pool_buf_core1_handler()
211 * Sets the number of connections for IPv4
212 */
213static int nss_n2h_set_empty_pool_buf(ctl_table *ctl, int write, void __user *buffer,
214 size_t *lenp, loff_t *ppos,
215 int core_num, int *new_val)
216{
217 struct nss_top_instance *nss_top = &nss_top_main;
218 struct nss_ctx_instance *nss_ctx = &nss_top->nss[core_num];
219 struct nss_n2h_msg nnm;
220 struct nss_n2h_empty_pool_buf *nnepbcm;
221 nss_tx_status_t nss_tx_status;
222 int ret = NSS_FAILURE;
223
224 /*
225 * Acquiring semaphore
226 */
227 down(&nss_n2h_nepbcfgp[core_num].sem);
228
229 /*
230 * Take snap shot of current value
231 */
232 nss_n2h_nepbcfgp[core_num].current_value = *new_val;
233
234 /*
235 * Write the variable with user input
236 */
237 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
238 if (ret || (!write)) {
239 up(&nss_n2h_nepbcfgp[core_num].sem);
240 return ret;
241 }
242
243 /*
244 * Input for n2h should be atleast 2048 to support defalt connections
245 * of 1024 (IPV4) + 1024 (IPV6) connections.
246 */
247 if ((*new_val < NSS_N2H_MIN_EMPTY_POOL_BUF_SZ)) {
248 nss_warning("%p: core %d setting %d is less than minimum number of buffer",
249 nss_ctx, core_num, *new_val);
250
251 /*
252 * Restore the current_value to its previous state
253 */
254 *new_val = nss_n2h_nepbcfgp[core_num].current_value;
255 up(&nss_n2h_nepbcfgp[core_num].sem);
256 return NSS_FAILURE;
257 }
258
259 nss_info("%p: core %d number of empty pool buffer is : %d\n",
260 nss_ctx, core_num, *new_val);
261
262 nss_n2h_msg_init(&nnm, NSS_N2H_INTERFACE,
263 NSS_TX_METADATA_TYPE_N2H_EMPTY_POOL_BUF_CFG,
264 sizeof(struct nss_n2h_empty_pool_buf),
265 (nss_n2h_msg_callback_t *)nss_n2h_empty_pool_buf_cfg_callback,
266 (void *)core_num);
267
268 nnepbcm = &nnm.msg.empty_pool_buf_cfg;
269 nnepbcm->pool_size = htonl(*new_val);
270 nss_tx_status = nss_n2h_tx_msg(nss_ctx, &nnm);
271
272 if (nss_tx_status != NSS_TX_SUCCESS) {
273 nss_warning("%p: core %d nss_tx error setting empty pool buffer: %d\n",
274 nss_ctx, core_num, *new_val);
275
276 /*
277 * Restore the current_value to its previous state
278 */
279 *new_val = nss_n2h_nepbcfgp[core_num].current_value;
280 up(&nss_n2h_nepbcfgp[core_num].sem);
281 return NSS_FAILURE;
282 }
283
284 /*
285 * Blocking call, wait till we get ACK for this msg.
286 */
287 ret = wait_for_completion_timeout(&nss_n2h_nepbcfgp[core_num].complete, msecs_to_jiffies(NSS_CONN_CFG_TIMEOUT));
288 if (ret == 0) {
289 nss_warning("%p: core %d Waiting for ack timed out\n", nss_ctx, core_num);
290
291 /*
292 * Restore the current_value to its previous state
293 */
294 *new_val = nss_n2h_nepbcfgp[core_num].current_value;
295 up(&nss_n2h_nepbcfgp[core_num].sem);
296 return NSS_FAILURE;
297 }
298
299 /*
300 * ACK/NACK received from NSS FW
301 * If ACK: Callback function will update nss_n2h_empty_pool_buf with
302 * nss_n2h_nepbcfgp.num_conn_valid, which holds the user input
303 */
304 if (NSS_FAILURE == nss_n2h_nepbcfgp[core_num].response) {
305
306 /*
307 * Restore the current_value to its previous state
308 */
309 *new_val = nss_n2h_nepbcfgp[core_num].current_value;
310 up(&nss_n2h_nepbcfgp[core_num].sem);
311 return NSS_FAILURE;
312 }
313
314 up(&nss_n2h_nepbcfgp[core_num].sem);
315 return NSS_SUCCESS;
316}
317
318/*
319 * nss_n2h_empty_pool_buf_core1_handler()
320 * Sets the number of empty buffer for core 1
321 */
322static int nss_n2h_empty_pool_buf_cfg_core1_handler(ctl_table *ctl,
323 int write, void __user *buffer,
324 size_t *lenp, loff_t *ppos)
325{
326 return nss_n2h_set_empty_pool_buf(ctl, write, buffer, lenp, ppos,
327 NSS_CORE_1, &nss_n2h_empty_pool_buf_cfg[NSS_CORE_1]);
328}
329
330/*
331 * nss_n2h_empty_pool_buf_core0_handler()
332 * Sets the number of empty buffer for core 0
333 */
334static int nss_n2h_empty_pool_buf_cfg_core0_handler(ctl_table *ctl,
335 int write, void __user *buffer,
336 size_t *lenp, loff_t *ppos)
337{
338 return nss_n2h_set_empty_pool_buf(ctl, write, buffer, lenp, ppos,
339 NSS_CORE_0, &nss_n2h_empty_pool_buf_cfg[NSS_CORE_0]);
340}
341
342static ctl_table nss_n2h_table[] = {
343 {
344 .procname = "n2h_empty_pool_buf_core0",
345 .data = &nss_n2h_empty_pool_buf_cfg[NSS_CORE_0],
346 .maxlen = sizeof(int),
347 .mode = 0644,
348 .proc_handler = &nss_n2h_empty_pool_buf_cfg_core0_handler,
349 },
350 {
351 .procname = "n2h_empty_pool_buf_core1",
352 .data = &nss_n2h_empty_pool_buf_cfg[NSS_CORE_1],
353 .maxlen = sizeof(int),
354 .mode = 0644,
355 .proc_handler = &nss_n2h_empty_pool_buf_cfg_core1_handler,
356 },
357
358 { }
359};
360
361static ctl_table nss_n2h_dir[] = {
362 {
363 .procname = "n2hcfg",
364 .mode = 0555,
365 .child = nss_n2h_table,
366 },
367 { }
368};
369
370
371static ctl_table nss_n2h_root_dir[] = {
372 {
373 .procname = "nss",
374 .mode = 0555,
375 .child = nss_n2h_dir,
376 },
377 { }
378};
379
380static ctl_table nss_n2h_root[] = {
381 {
382 .procname = "dev",
383 .mode = 0555,
384 .child = nss_n2h_root_dir,
385 },
386 { }
387};
388
389static struct ctl_table_header *nss_n2h_header;
390
391/*
392 * nss_n2h_msg_init()
393 * Initialize IPv4 message.
394 */
395void nss_n2h_msg_init(struct nss_n2h_msg *nim, uint16_t if_num, uint32_t type,
396 uint32_t len, nss_n2h_msg_callback_t *cb, void *app_data)
397{
398 nss_cmn_msg_init(&nim->cm, if_num, type, len, (void *)cb, app_data);
399}
400
401
402/*
403 * nss_n2h_register_sysctl()
404 * Register sysctl specific to n2h
405 */
406void nss_n2h_empty_pool_buf_register_sysctl(void)
407{
408 /*
409 * Register sysctl table.
410 */
411 nss_n2h_header = register_sysctl_table(nss_n2h_root);
412
413 /*
414 * Core0
415 */
416 sema_init(&nss_n2h_nepbcfgp[NSS_CORE_0].sem, 1);
417 init_completion(&nss_n2h_nepbcfgp[NSS_CORE_0].complete);
418 nss_n2h_nepbcfgp[NSS_CORE_0].current_value = nss_n2h_empty_pool_buf_cfg[NSS_CORE_0];
419
420 /*
421 * Core1
422 */
423 sema_init(&nss_n2h_nepbcfgp[NSS_CORE_1].sem, 1);
424 init_completion(&nss_n2h_nepbcfgp[NSS_CORE_1].complete);
425 nss_n2h_nepbcfgp[NSS_CORE_1].current_value = nss_n2h_empty_pool_buf_cfg[NSS_CORE_1];
426}
427
428/*
429 * nss_n2h_unregister_sysctl()
430 * Unregister sysctl specific to n2h
431 */
432void nss_n2h_empty_pool_buf_unregister_sysctl(void)
433{
434 /*
435 * Unregister sysctl table.
436 */
437 if (nss_n2h_header) {
438 unregister_sysctl_table(nss_n2h_header);
439 }
440}
441
442/*
443 * nss_n2h_tx_msg()
444 * Send messages to NSS n2h pacakge
445 */
446nss_tx_status_t nss_n2h_tx_msg(struct nss_ctx_instance *nss_ctx, struct nss_n2h_msg *nnm)
447{
448 struct nss_n2h_msg *nnm2;
449 struct nss_cmn_msg *ncm = &nnm->cm;
450 struct sk_buff *nbuf;
451 nss_tx_status_t status;
452
453 NSS_VERIFY_CTX_MAGIC(nss_ctx);
454 if (unlikely(nss_ctx->state != NSS_CORE_STATE_INITIALIZED)) {
455 return NSS_TX_FAILURE_NOT_READY;
456 }
457
458 /*
459 * Sanity check the message
460 */
461 if (ncm->interface != NSS_N2H_INTERFACE) {
462 nss_warning("%p: tx request for another interface: %d", nss_ctx, ncm->interface);
463 return NSS_TX_FAILURE;
464 }
465
466 if (ncm->type >= NSS_METADATA_TYPE_N2H_MAX) {
467 nss_warning("%p: message type out of range: %d", nss_ctx, ncm->type);
468 return NSS_TX_FAILURE;
469 }
470
471 if (ncm->len > sizeof(struct nss_n2h_msg)) {
472 nss_warning("%p: tx request for another interface: %d", nss_ctx, ncm->interface);
473 return NSS_TX_FAILURE;
474 }
475
476
477 nbuf = dev_alloc_skb(NSS_NBUF_PAYLOAD_SIZE);
478 if (unlikely(!nbuf)) {
479 spin_lock_bh(&nss_ctx->nss_top->stats_lock);
480 nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_NBUF_ALLOC_FAILS]++;
481 spin_unlock_bh(&nss_ctx->nss_top->stats_lock);
482 return NSS_TX_FAILURE;
483 }
484
485 /*
486 * Copy the message to our skb.
487 */
488 nnm2 = (struct nss_n2h_msg *)skb_put(nbuf, sizeof(struct nss_n2h_msg));
489 memcpy(nnm2, nnm, sizeof(struct nss_n2h_msg));
490 status = nss_core_send_buffer(nss_ctx, 0, nbuf, NSS_IF_CMD_QUEUE, H2N_BUFFER_CTRL, 0);
491 if (status != NSS_CORE_STATUS_SUCCESS) {
492 dev_kfree_skb_any(nbuf);
493 nss_info("%p: unable to enqueue 'nss frequency change' - marked as stopped\n", nss_ctx);
494 return NSS_TX_FAILURE;
495 }
496
497 nss_hal_send_interrupt(nss_ctx->nmap,
498 nss_ctx->h2n_desc_rings[NSS_IF_CMD_QUEUE].desc_ring.int_bit,
499 NSS_REGS_H2N_INTR_STATUS_DATA_COMMAND_QUEUE);
500 NSS_PKT_STATS_INCREMENT(nss_ctx, &nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_TX_CMD_REQ]);
501 return NSS_TX_SUCCESS;
502}
503
504
505/*
506 * nss_n2h_tx()
507 * Send Message to NSS to enable RPS.
508 *
509 * This API could be used for any additional RPS related
510 * configuration in future.
511 *
512 * TODO: rename to _rps and rewrite assignment from handler to a callback.
513 */
514nss_tx_status_t nss_n2h_tx(struct nss_ctx_instance *nss_ctx, uint32_t enable_rps)
515{
516 struct sk_buff *nbuf;
517 nss_tx_status_t status;
518 struct nss_n2h_msg *nnhm;
519 struct nss_n2h_rps *rps_cfg;
520
521 NSS_VERIFY_CTX_MAGIC(nss_ctx);
522 if (unlikely(nss_ctx->state != NSS_CORE_STATE_INITIALIZED)) {
523 return NSS_TX_FAILURE_NOT_READY;
524 }
525
526 nbuf = dev_alloc_skb(NSS_NBUF_PAYLOAD_SIZE);
527 if (unlikely(!nbuf)) {
528 spin_lock_bh(&nss_ctx->nss_top->stats_lock);
529 nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_NBUF_ALLOC_FAILS]++;
530 spin_unlock_bh(&nss_ctx->nss_top->stats_lock);
531 return NSS_TX_FAILURE;
532 }
533
534 nnhm = (struct nss_n2h_msg *)skb_put(nbuf, sizeof(struct nss_n2h_msg));
535
536 nss_n2h_msg_init(nnhm, NSS_N2H_INTERFACE, NSS_TX_METADATA_TYPE_N2H_RPS_CFG,
537 sizeof(struct nss_n2h_rps),
538 NULL, NULL);
539
540 rps_cfg = &nnhm->msg.rps_cfg;
541
542 rps_cfg->enable = enable_rps;
543
544 nss_info("n22_n2h_rps_configure %d \n", enable_rps);
545
546 status = nss_core_send_buffer(nss_ctx, 0, nbuf, NSS_IF_CMD_QUEUE, H2N_BUFFER_CTRL, 0);
547 if (status != NSS_CORE_STATUS_SUCCESS) {
548 dev_kfree_skb_any(nbuf);
549 nss_info("%p: unable to enqueue 'nss frequency change' - marked as stopped\n", nss_ctx);
550 return NSS_TX_FAILURE;
551 }
552
553 nss_hal_send_interrupt(nss_ctx->nmap,
554 nss_ctx->h2n_desc_rings[NSS_IF_CMD_QUEUE].desc_ring.int_bit,
555 NSS_REGS_H2N_INTR_STATUS_DATA_COMMAND_QUEUE);
556
557 return NSS_TX_SUCCESS;
558}
559
560/*
561 * nss_n2h_notify_register()
562 * Register to received N2H events.
563 *
564 * NOTE: Do we want to pass an nss_ctx here so that we can register for n2h on any core?
565 */
566struct nss_ctx_instance *nss_n2h_notify_register(int core, nss_n2h_msg_callback_t cb, void *app_data)
567{
568 if (core >= NSS_MAX_CORES) {
569 nss_warning("Input core number %d is wrong \n", core);
570 return NULL;
571 }
572 /*
573 * TODO: We need to have a new array in support of the new API
574 * TODO: If we use a per-context array, we would move the array into nss_ctx based.
575 */
576 nss_n2h_rd[core].n2h_callback = cb;
577 nss_n2h_rd[core].app_data = app_data;
578 return &nss_top_main.nss[core];
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530579}
580
581/*
582 * nss_n2h_register_handler()
583 */
584void nss_n2h_register_handler()
585{
Sundarajan Srinivasanf1e57462014-09-17 15:24:01 -0700586 nss_core_register_handler(NSS_N2H_INTERFACE, nss_n2h_interface_handler, NULL);
587
Vijay Dewangan488e5372014-12-29 21:40:11 -0800588 nss_n2h_notify_register(NSS_CORE_0, NULL, NULL);
589 nss_n2h_notify_register(NSS_CORE_1, NULL, NULL);
590
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530591}
Vijay Dewangan488e5372014-12-29 21:40:11 -0800592
593EXPORT_SYMBOL(nss_n2h_notify_register);
Vijay Dewanganac7efc42015-02-09 16:04:53 -0800594EXPORT_SYMBOL(nss_n2h_empty_pool_buf_register_sysctl);