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