blob: 827bab707411a9cc40eac91a85e4caebed4ca554 [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
Radha krishna Simha Jiguru7f424d52015-02-10 19:41:01 +0530137 case NSS_TX_METADATA_TYPE_N2H_FLUSH_PAYLOADS:
138 nss_info("%p: flush payloads cmd response from FW", nss_ctx);
139 break;
140
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530141 case NSS_RX_METADATA_TYPE_N2H_STATS_SYNC:
Sundarajan Srinivasanf1e57462014-09-17 15:24:01 -0700142 nss_n2h_stats_sync(nss_ctx, &nnm->msg.stats_sync);
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530143 break;
144
145 default:
146 if (ncm->response != NSS_CMN_RESPONSE_ACK) {
147 /*
148 * Check response
149 */
150 nss_info("%p: Received response %d for type %d, interface %d",
151 nss_ctx, ncm->response, ncm->type, ncm->interface);
152 }
153 }
Vijay Dewangan488e5372014-12-29 21:40:11 -0800154
155 /*
156 * Update the callback and app_data for NOTIFY messages, IPv4 sends all notify messages
157 * to the same callback/app_data.
158 */
159 if (nnm->cm.response == NSS_CMM_RESPONSE_NOTIFY) {
160 /*
161 * Place holder for the user to create right call
162 * back and app data when response is NSS_CMM_RESPONSE_NOTIFY
163 */
164 ncm->cb = (uint32_t)nss_n2h_rd[nss_ctx->id].n2h_callback;
165 ncm->app_data = (uint32_t)nss_n2h_rd[nss_ctx->id].app_data;
166 }
167
168 /*
169 * Do we have a callback?
170 */
171 if (!ncm->cb) {
172 return;
173 }
174
175 /*
176 * Callback
177 */
178 cb = (nss_n2h_msg_callback_t)ncm->cb;
179 cb((void *)ncm->app_data, nnm);
180}
181
182/*
183 * nss_n2h_empty_pool_buf_cfg_core1_callback()
184 * call back function for the n2h connection configuration handler
185 */
186static void nss_n2h_empty_pool_buf_cfg_callback(void *app_data,
187 struct nss_n2h_msg *nnm)
188{
189 int core_num = (int)app_data;
190 if (nnm->cm.response != NSS_CMN_RESPONSE_ACK) {
191 struct nss_n2h_empty_pool_buf *nnepbcm;
192 nnepbcm = &nnm->msg.empty_pool_buf_cfg;
193
194 /*
195 * Error, hence we are not updating the nss_n2h_empty_pool_buf
196 * Restore the current_value to its previous state
197 */
198 nss_warning("Core %d empty pool buf set failure: %d\n", core_num, nnm->cm.error);
199 nss_n2h_nepbcfgp[core_num].response = NSS_FAILURE;
200 complete(&nss_n2h_nepbcfgp[core_num].complete);
201 return;
202 }
203
204 /*
205 * Sucess at NSS FW, hence updating nss_n2h_empty_pool_buf, with the valid value
206 * saved at the sysctl handler.
207 */
208 nss_info("Core %d empty pool buf set success: %d\n", core_num, nnm->cm.error);
209 nss_n2h_nepbcfgp[core_num].response = NSS_SUCCESS;
210 complete(&nss_n2h_nepbcfgp[core_num].complete);
211}
212
213/*
214 * nss_n2h_empty_pool_buf_core1_handler()
215 * Sets the number of connections for IPv4
216 */
217static int nss_n2h_set_empty_pool_buf(ctl_table *ctl, int write, void __user *buffer,
218 size_t *lenp, loff_t *ppos,
219 int core_num, int *new_val)
220{
221 struct nss_top_instance *nss_top = &nss_top_main;
222 struct nss_ctx_instance *nss_ctx = &nss_top->nss[core_num];
223 struct nss_n2h_msg nnm;
224 struct nss_n2h_empty_pool_buf *nnepbcm;
225 nss_tx_status_t nss_tx_status;
226 int ret = NSS_FAILURE;
227
228 /*
229 * Acquiring semaphore
230 */
231 down(&nss_n2h_nepbcfgp[core_num].sem);
232
233 /*
234 * Take snap shot of current value
235 */
236 nss_n2h_nepbcfgp[core_num].current_value = *new_val;
237
238 /*
239 * Write the variable with user input
240 */
241 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
242 if (ret || (!write)) {
243 up(&nss_n2h_nepbcfgp[core_num].sem);
244 return ret;
245 }
246
247 /*
248 * Input for n2h should be atleast 2048 to support defalt connections
249 * of 1024 (IPV4) + 1024 (IPV6) connections.
250 */
251 if ((*new_val < NSS_N2H_MIN_EMPTY_POOL_BUF_SZ)) {
252 nss_warning("%p: core %d setting %d is less than minimum number of buffer",
253 nss_ctx, core_num, *new_val);
254
255 /*
256 * Restore the current_value to its previous state
257 */
258 *new_val = nss_n2h_nepbcfgp[core_num].current_value;
259 up(&nss_n2h_nepbcfgp[core_num].sem);
260 return NSS_FAILURE;
261 }
262
263 nss_info("%p: core %d number of empty pool buffer is : %d\n",
264 nss_ctx, core_num, *new_val);
265
266 nss_n2h_msg_init(&nnm, NSS_N2H_INTERFACE,
267 NSS_TX_METADATA_TYPE_N2H_EMPTY_POOL_BUF_CFG,
268 sizeof(struct nss_n2h_empty_pool_buf),
269 (nss_n2h_msg_callback_t *)nss_n2h_empty_pool_buf_cfg_callback,
270 (void *)core_num);
271
272 nnepbcm = &nnm.msg.empty_pool_buf_cfg;
273 nnepbcm->pool_size = htonl(*new_val);
274 nss_tx_status = nss_n2h_tx_msg(nss_ctx, &nnm);
275
276 if (nss_tx_status != NSS_TX_SUCCESS) {
277 nss_warning("%p: core %d nss_tx error setting empty pool buffer: %d\n",
278 nss_ctx, core_num, *new_val);
279
280 /*
281 * Restore the current_value to its previous state
282 */
283 *new_val = nss_n2h_nepbcfgp[core_num].current_value;
284 up(&nss_n2h_nepbcfgp[core_num].sem);
285 return NSS_FAILURE;
286 }
287
288 /*
289 * Blocking call, wait till we get ACK for this msg.
290 */
291 ret = wait_for_completion_timeout(&nss_n2h_nepbcfgp[core_num].complete, msecs_to_jiffies(NSS_CONN_CFG_TIMEOUT));
292 if (ret == 0) {
293 nss_warning("%p: core %d Waiting for ack timed out\n", nss_ctx, core_num);
294
295 /*
296 * Restore the current_value to its previous state
297 */
298 *new_val = nss_n2h_nepbcfgp[core_num].current_value;
299 up(&nss_n2h_nepbcfgp[core_num].sem);
300 return NSS_FAILURE;
301 }
302
303 /*
304 * ACK/NACK received from NSS FW
305 * If ACK: Callback function will update nss_n2h_empty_pool_buf with
306 * nss_n2h_nepbcfgp.num_conn_valid, which holds the user input
307 */
308 if (NSS_FAILURE == nss_n2h_nepbcfgp[core_num].response) {
309
310 /*
311 * Restore the current_value to its previous state
312 */
313 *new_val = nss_n2h_nepbcfgp[core_num].current_value;
314 up(&nss_n2h_nepbcfgp[core_num].sem);
315 return NSS_FAILURE;
316 }
317
318 up(&nss_n2h_nepbcfgp[core_num].sem);
319 return NSS_SUCCESS;
320}
321
322/*
Radha krishna Simha Jiguru7f424d52015-02-10 19:41:01 +0530323 * nss_n2h_flush_payloads()
324 * Sends a command down to NSS for flushing all payloads
325 */
326nss_tx_status_t nss_n2h_flush_payloads(struct nss_ctx_instance *nss_ctx)
327{
328 struct nss_n2h_msg nnm;
329 struct nss_n2h_flush_payloads *nnflshpl;
330 nss_tx_status_t nss_tx_status;
331
332 nnflshpl = &nnm.msg.flush_payloads;
333
334 /*
335 * TODO: No additional information sent in message
336 * as of now. Need to initialize message content accordingly
337 * if needed.
338 */
339 nss_n2h_msg_init(&nnm, NSS_N2H_INTERFACE,
340 NSS_TX_METADATA_TYPE_N2H_FLUSH_PAYLOADS,
341 sizeof(struct nss_n2h_flush_payloads),
342 NULL,
343 NULL);
344
345 nss_tx_status = nss_n2h_tx_msg(nss_ctx, &nnm);
346 if (nss_tx_status != NSS_TX_SUCCESS) {
347 nss_warning("%p: failed to send flush payloads command to NSS\n",
348 nss_ctx);
349
350 return NSS_TX_FAILURE;
351 }
352
353 return NSS_TX_SUCCESS;
354}
355
356/*
Vijay Dewangan488e5372014-12-29 21:40:11 -0800357 * nss_n2h_empty_pool_buf_core1_handler()
358 * Sets the number of empty buffer for core 1
359 */
360static int nss_n2h_empty_pool_buf_cfg_core1_handler(ctl_table *ctl,
361 int write, void __user *buffer,
362 size_t *lenp, loff_t *ppos)
363{
364 return nss_n2h_set_empty_pool_buf(ctl, write, buffer, lenp, ppos,
365 NSS_CORE_1, &nss_n2h_empty_pool_buf_cfg[NSS_CORE_1]);
366}
367
368/*
369 * nss_n2h_empty_pool_buf_core0_handler()
370 * Sets the number of empty buffer for core 0
371 */
372static int nss_n2h_empty_pool_buf_cfg_core0_handler(ctl_table *ctl,
373 int write, void __user *buffer,
374 size_t *lenp, loff_t *ppos)
375{
376 return nss_n2h_set_empty_pool_buf(ctl, write, buffer, lenp, ppos,
377 NSS_CORE_0, &nss_n2h_empty_pool_buf_cfg[NSS_CORE_0]);
378}
379
380static ctl_table nss_n2h_table[] = {
381 {
382 .procname = "n2h_empty_pool_buf_core0",
383 .data = &nss_n2h_empty_pool_buf_cfg[NSS_CORE_0],
384 .maxlen = sizeof(int),
385 .mode = 0644,
386 .proc_handler = &nss_n2h_empty_pool_buf_cfg_core0_handler,
387 },
388 {
389 .procname = "n2h_empty_pool_buf_core1",
390 .data = &nss_n2h_empty_pool_buf_cfg[NSS_CORE_1],
391 .maxlen = sizeof(int),
392 .mode = 0644,
393 .proc_handler = &nss_n2h_empty_pool_buf_cfg_core1_handler,
394 },
395
396 { }
397};
398
399static ctl_table nss_n2h_dir[] = {
400 {
401 .procname = "n2hcfg",
402 .mode = 0555,
403 .child = nss_n2h_table,
404 },
405 { }
406};
407
408
409static ctl_table nss_n2h_root_dir[] = {
410 {
411 .procname = "nss",
412 .mode = 0555,
413 .child = nss_n2h_dir,
414 },
415 { }
416};
417
418static ctl_table nss_n2h_root[] = {
419 {
420 .procname = "dev",
421 .mode = 0555,
422 .child = nss_n2h_root_dir,
423 },
424 { }
425};
426
427static struct ctl_table_header *nss_n2h_header;
428
429/*
430 * nss_n2h_msg_init()
431 * Initialize IPv4 message.
432 */
433void nss_n2h_msg_init(struct nss_n2h_msg *nim, uint16_t if_num, uint32_t type,
434 uint32_t len, nss_n2h_msg_callback_t *cb, void *app_data)
435{
436 nss_cmn_msg_init(&nim->cm, if_num, type, len, (void *)cb, app_data);
437}
438
439
440/*
441 * nss_n2h_register_sysctl()
442 * Register sysctl specific to n2h
443 */
444void nss_n2h_empty_pool_buf_register_sysctl(void)
445{
446 /*
447 * Register sysctl table.
448 */
449 nss_n2h_header = register_sysctl_table(nss_n2h_root);
450
451 /*
452 * Core0
453 */
454 sema_init(&nss_n2h_nepbcfgp[NSS_CORE_0].sem, 1);
455 init_completion(&nss_n2h_nepbcfgp[NSS_CORE_0].complete);
456 nss_n2h_nepbcfgp[NSS_CORE_0].current_value = nss_n2h_empty_pool_buf_cfg[NSS_CORE_0];
457
458 /*
459 * Core1
460 */
461 sema_init(&nss_n2h_nepbcfgp[NSS_CORE_1].sem, 1);
462 init_completion(&nss_n2h_nepbcfgp[NSS_CORE_1].complete);
463 nss_n2h_nepbcfgp[NSS_CORE_1].current_value = nss_n2h_empty_pool_buf_cfg[NSS_CORE_1];
464}
465
466/*
467 * nss_n2h_unregister_sysctl()
468 * Unregister sysctl specific to n2h
469 */
470void nss_n2h_empty_pool_buf_unregister_sysctl(void)
471{
472 /*
473 * Unregister sysctl table.
474 */
475 if (nss_n2h_header) {
476 unregister_sysctl_table(nss_n2h_header);
477 }
478}
479
480/*
481 * nss_n2h_tx_msg()
482 * Send messages to NSS n2h pacakge
483 */
484nss_tx_status_t nss_n2h_tx_msg(struct nss_ctx_instance *nss_ctx, struct nss_n2h_msg *nnm)
485{
486 struct nss_n2h_msg *nnm2;
487 struct nss_cmn_msg *ncm = &nnm->cm;
488 struct sk_buff *nbuf;
489 nss_tx_status_t status;
490
491 NSS_VERIFY_CTX_MAGIC(nss_ctx);
492 if (unlikely(nss_ctx->state != NSS_CORE_STATE_INITIALIZED)) {
493 return NSS_TX_FAILURE_NOT_READY;
494 }
495
496 /*
497 * Sanity check the message
498 */
499 if (ncm->interface != NSS_N2H_INTERFACE) {
500 nss_warning("%p: tx request for another interface: %d", nss_ctx, ncm->interface);
501 return NSS_TX_FAILURE;
502 }
503
504 if (ncm->type >= NSS_METADATA_TYPE_N2H_MAX) {
505 nss_warning("%p: message type out of range: %d", nss_ctx, ncm->type);
506 return NSS_TX_FAILURE;
507 }
508
509 if (ncm->len > sizeof(struct nss_n2h_msg)) {
510 nss_warning("%p: tx request for another interface: %d", nss_ctx, ncm->interface);
511 return NSS_TX_FAILURE;
512 }
513
514
515 nbuf = dev_alloc_skb(NSS_NBUF_PAYLOAD_SIZE);
516 if (unlikely(!nbuf)) {
517 spin_lock_bh(&nss_ctx->nss_top->stats_lock);
518 nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_NBUF_ALLOC_FAILS]++;
519 spin_unlock_bh(&nss_ctx->nss_top->stats_lock);
520 return NSS_TX_FAILURE;
521 }
522
523 /*
524 * Copy the message to our skb.
525 */
526 nnm2 = (struct nss_n2h_msg *)skb_put(nbuf, sizeof(struct nss_n2h_msg));
527 memcpy(nnm2, nnm, sizeof(struct nss_n2h_msg));
528 status = nss_core_send_buffer(nss_ctx, 0, nbuf, NSS_IF_CMD_QUEUE, H2N_BUFFER_CTRL, 0);
529 if (status != NSS_CORE_STATUS_SUCCESS) {
530 dev_kfree_skb_any(nbuf);
531 nss_info("%p: unable to enqueue 'nss frequency change' - marked as stopped\n", nss_ctx);
532 return NSS_TX_FAILURE;
533 }
534
535 nss_hal_send_interrupt(nss_ctx->nmap,
536 nss_ctx->h2n_desc_rings[NSS_IF_CMD_QUEUE].desc_ring.int_bit,
537 NSS_REGS_H2N_INTR_STATUS_DATA_COMMAND_QUEUE);
538 NSS_PKT_STATS_INCREMENT(nss_ctx, &nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_TX_CMD_REQ]);
539 return NSS_TX_SUCCESS;
540}
541
542
543/*
544 * nss_n2h_tx()
545 * Send Message to NSS to enable RPS.
546 *
547 * This API could be used for any additional RPS related
548 * configuration in future.
549 *
550 * TODO: rename to _rps and rewrite assignment from handler to a callback.
551 */
552nss_tx_status_t nss_n2h_tx(struct nss_ctx_instance *nss_ctx, uint32_t enable_rps)
553{
554 struct sk_buff *nbuf;
555 nss_tx_status_t status;
556 struct nss_n2h_msg *nnhm;
557 struct nss_n2h_rps *rps_cfg;
558
559 NSS_VERIFY_CTX_MAGIC(nss_ctx);
560 if (unlikely(nss_ctx->state != NSS_CORE_STATE_INITIALIZED)) {
561 return NSS_TX_FAILURE_NOT_READY;
562 }
563
564 nbuf = dev_alloc_skb(NSS_NBUF_PAYLOAD_SIZE);
565 if (unlikely(!nbuf)) {
566 spin_lock_bh(&nss_ctx->nss_top->stats_lock);
567 nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_NBUF_ALLOC_FAILS]++;
568 spin_unlock_bh(&nss_ctx->nss_top->stats_lock);
569 return NSS_TX_FAILURE;
570 }
571
572 nnhm = (struct nss_n2h_msg *)skb_put(nbuf, sizeof(struct nss_n2h_msg));
573
574 nss_n2h_msg_init(nnhm, NSS_N2H_INTERFACE, NSS_TX_METADATA_TYPE_N2H_RPS_CFG,
575 sizeof(struct nss_n2h_rps),
576 NULL, NULL);
577
578 rps_cfg = &nnhm->msg.rps_cfg;
579
580 rps_cfg->enable = enable_rps;
581
582 nss_info("n22_n2h_rps_configure %d \n", enable_rps);
583
584 status = nss_core_send_buffer(nss_ctx, 0, nbuf, NSS_IF_CMD_QUEUE, H2N_BUFFER_CTRL, 0);
585 if (status != NSS_CORE_STATUS_SUCCESS) {
586 dev_kfree_skb_any(nbuf);
587 nss_info("%p: unable to enqueue 'nss frequency change' - marked as stopped\n", nss_ctx);
588 return NSS_TX_FAILURE;
589 }
590
591 nss_hal_send_interrupt(nss_ctx->nmap,
592 nss_ctx->h2n_desc_rings[NSS_IF_CMD_QUEUE].desc_ring.int_bit,
593 NSS_REGS_H2N_INTR_STATUS_DATA_COMMAND_QUEUE);
594
595 return NSS_TX_SUCCESS;
596}
597
598/*
599 * nss_n2h_notify_register()
600 * Register to received N2H events.
601 *
602 * NOTE: Do we want to pass an nss_ctx here so that we can register for n2h on any core?
603 */
604struct nss_ctx_instance *nss_n2h_notify_register(int core, nss_n2h_msg_callback_t cb, void *app_data)
605{
606 if (core >= NSS_MAX_CORES) {
607 nss_warning("Input core number %d is wrong \n", core);
608 return NULL;
609 }
610 /*
611 * TODO: We need to have a new array in support of the new API
612 * TODO: If we use a per-context array, we would move the array into nss_ctx based.
613 */
614 nss_n2h_rd[core].n2h_callback = cb;
615 nss_n2h_rd[core].app_data = app_data;
616 return &nss_top_main.nss[core];
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530617}
618
619/*
620 * nss_n2h_register_handler()
621 */
622void nss_n2h_register_handler()
623{
Sundarajan Srinivasanf1e57462014-09-17 15:24:01 -0700624 nss_core_register_handler(NSS_N2H_INTERFACE, nss_n2h_interface_handler, NULL);
625
Vijay Dewangan488e5372014-12-29 21:40:11 -0800626 nss_n2h_notify_register(NSS_CORE_0, NULL, NULL);
627 nss_n2h_notify_register(NSS_CORE_1, NULL, NULL);
628
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530629}
Vijay Dewangan488e5372014-12-29 21:40:11 -0800630
631EXPORT_SYMBOL(nss_n2h_notify_register);
Vijay Dewanganac7efc42015-02-09 16:04:53 -0800632EXPORT_SYMBOL(nss_n2h_empty_pool_buf_register_sysctl);