blob: b12509f606c56ae6fd2f8154649328ac020b38a0 [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
Saurabh Misra71034db2015-06-04 16:18:38 -070027#define NSS_N2H_MIN_EMPTY_POOL_BUF_SZ 32
Vijay Dewangan488e5372014-12-29 21:40:11 -080028#define NSS_N2H_DEFAULT_EMPTY_POOL_BUF_SZ 8192
Pamidipati, Vijayefcc4692014-05-09 14:47:38 +053029
Saurabh Misra71034db2015-06-04 16:18:38 -070030int nss_n2h_empty_pool_buf_cfg[NSS_MAX_CORES] __read_mostly = {-1, -1};
31int nss_n2h_water_mark[NSS_MAX_CORES][2] __read_mostly = {{-1, -1}, {-1, -1} };
Pamidipati, Vijayefcc4692014-05-09 14:47:38 +053032
Vijay Dewangan488e5372014-12-29 21:40:11 -080033struct nss_n2h_registered_data {
34 nss_n2h_msg_callback_t n2h_callback;
35 void *app_data;
36};
Pamidipati, Vijayefcc4692014-05-09 14:47:38 +053037
Vijay Dewangan488e5372014-12-29 21:40:11 -080038static struct nss_n2h_cfg_pvt nss_n2h_nepbcfgp[NSS_MAX_CORES];
39static struct nss_n2h_registered_data nss_n2h_rd[NSS_MAX_CORES];
Vijay Dewangan634ce592015-01-07 17:21:09 -080040static struct nss_n2h_cfg_pvt nss_n2h_rcp;
Pamidipati, Vijayefcc4692014-05-09 14:47:38 +053041
42/*
Sundarajan Srinivasanf1e57462014-09-17 15:24:01 -070043 * nss_n2h_stats_sync()
Abhishek Rastogi84d95d02014-03-26 19:31:31 +053044 * Handle the syncing of NSS statistics.
45 */
Sundarajan Srinivasanf1e57462014-09-17 15:24:01 -070046static void nss_n2h_stats_sync(struct nss_ctx_instance *nss_ctx, struct nss_n2h_stats_sync *nnss)
Abhishek Rastogi84d95d02014-03-26 19:31:31 +053047{
48 struct nss_top_instance *nss_top = nss_ctx->nss_top;
49
50 spin_lock_bh(&nss_top->stats_lock);
51
52 /*
53 * common node stats
54 */
55 nss_ctx->stats_n2h[NSS_STATS_NODE_RX_PKTS] += nnss->node_stats.rx_packets;
56 nss_ctx->stats_n2h[NSS_STATS_NODE_RX_BYTES] += nnss->node_stats.rx_bytes;
57 nss_ctx->stats_n2h[NSS_STATS_NODE_RX_DROPPED] += nnss->node_stats.rx_dropped;
58 nss_ctx->stats_n2h[NSS_STATS_NODE_TX_PKTS] += nnss->node_stats.tx_packets;
59 nss_ctx->stats_n2h[NSS_STATS_NODE_TX_BYTES] += nnss->node_stats.tx_bytes;
60
61 /*
62 * General N2H stats
63 */
Murat Sezgin0c0561d2014-04-09 18:55:58 -070064 nss_ctx->stats_n2h[NSS_STATS_N2H_QUEUE_DROPPED] += nnss->queue_dropped;
65 nss_ctx->stats_n2h[NSS_STATS_N2H_TOTAL_TICKS] += nnss->total_ticks;
66 nss_ctx->stats_n2h[NSS_STATS_N2H_WORST_CASE_TICKS] += nnss->worst_case_ticks;
67 nss_ctx->stats_n2h[NSS_STATS_N2H_ITERATIONS] += nnss->iterations;
Abhishek Rastogi84d95d02014-03-26 19:31:31 +053068
69 /*
Thomas Wu3fd8dd72014-06-11 15:57:05 -070070 * pbuf manager ocm and default pool stats
Abhishek Rastogi84d95d02014-03-26 19:31:31 +053071 */
Thomas Wu3fd8dd72014-06-11 15:57:05 -070072 nss_ctx->stats_n2h[NSS_STATS_N2H_PBUF_OCM_ALLOC_FAILS] += nnss->pbuf_ocm_stats.pbuf_alloc_fails;
73 nss_ctx->stats_n2h[NSS_STATS_N2H_PBUF_OCM_FREE_COUNT] = nnss->pbuf_ocm_stats.pbuf_free_count;
74 nss_ctx->stats_n2h[NSS_STATS_N2H_PBUF_OCM_TOTAL_COUNT] = nnss->pbuf_ocm_stats.pbuf_total_count;
75
76 nss_ctx->stats_n2h[NSS_STATS_N2H_PBUF_DEFAULT_ALLOC_FAILS] += nnss->pbuf_default_stats.pbuf_alloc_fails;
77 nss_ctx->stats_n2h[NSS_STATS_N2H_PBUF_DEFAULT_FREE_COUNT] = nnss->pbuf_default_stats.pbuf_free_count;
78 nss_ctx->stats_n2h[NSS_STATS_N2H_PBUF_DEFAULT_TOTAL_COUNT] = nnss->pbuf_default_stats.pbuf_total_count;
79
80 /*
81 * payload mgr stats
82 */
Abhishek Rastogi84d95d02014-03-26 19:31:31 +053083 nss_ctx->stats_n2h[NSS_STATS_N2H_PAYLOAD_ALLOC_FAILS] += nnss->payload_alloc_fails;
Thomas Wu53679842015-01-22 13:37:35 -080084 nss_ctx->stats_n2h[NSS_STATS_N2H_PAYLOAD_FREE_COUNT] = nnss->payload_free_count;
Abhishek Rastogi84d95d02014-03-26 19:31:31 +053085
Sakthi Vignesh Radhakrishnan2a8ee962014-11-22 13:35:38 -080086 /*
87 * Host <=> NSS control traffic stats
88 */
89 nss_ctx->stats_n2h[NSS_STATS_N2H_H2N_CONTROL_PACKETS] += nnss->h2n_ctrl_pkts;
90 nss_ctx->stats_n2h[NSS_STATS_N2H_H2N_CONTROL_BYTES] += nnss->h2n_ctrl_bytes;
91 nss_ctx->stats_n2h[NSS_STATS_N2H_N2H_CONTROL_PACKETS] += nnss->n2h_ctrl_pkts;
92 nss_ctx->stats_n2h[NSS_STATS_N2H_N2H_CONTROL_BYTES] += nnss->n2h_ctrl_bytes;
93
94 /*
95 * Host <=> NSS control data traffic stats
96 */
97 nss_ctx->stats_n2h[NSS_STATS_N2H_H2N_DATA_PACKETS] += nnss->h2n_data_pkts;
98 nss_ctx->stats_n2h[NSS_STATS_N2H_H2N_DATA_BYTES] += nnss->h2n_data_bytes;
99 nss_ctx->stats_n2h[NSS_STATS_N2H_N2H_DATA_PACKETS] += nnss->n2h_data_pkts;
100 nss_ctx->stats_n2h[NSS_STATS_N2H_N2H_DATA_BYTES] += nnss->n2h_data_bytes;
101
Saurabh Misra71034db2015-06-04 16:18:38 -0700102 /*
103 * Payloads related stats
104 */
105 nss_ctx->stats_n2h[NSS_STATS_N2H_N2H_TOT_PAYLOADS] = nnss->tot_payloads;
106
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530107 spin_unlock_bh(&nss_top->stats_lock);
108}
109
110/*
Sundarajan Srinivasanf1e57462014-09-17 15:24:01 -0700111 * nss_n2h_interface_handler()
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530112 * Handle NSS -> HLOS messages for N2H node
113 */
Vijay Dewangan634ce592015-01-07 17:21:09 -0800114static void nss_n2h_interface_handler(struct nss_ctx_instance *nss_ctx,
115 struct nss_cmn_msg *ncm,
116 __attribute__((unused))void *app_data)
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530117{
118 struct nss_n2h_msg *nnm = (struct nss_n2h_msg *)ncm;
Vijay Dewangan488e5372014-12-29 21:40:11 -0800119 nss_n2h_msg_callback_t cb;
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530120
Sundarajan Srinivasanf1e57462014-09-17 15:24:01 -0700121 BUG_ON(ncm->interface != NSS_N2H_INTERFACE);
122
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530123 /*
124 * Is this a valid request/response packet?
125 */
126 if (nnm->cm.type >= NSS_METADATA_TYPE_N2H_MAX) {
127 nss_warning("%p: received invalid message %d for Offload stats interface", nss_ctx, nnm->cm.type);
128 return;
129 }
130
131 switch (nnm->cm.type) {
Pamidipati, Vijayefcc4692014-05-09 14:47:38 +0530132 case NSS_TX_METADATA_TYPE_N2H_RPS_CFG:
Pamidipati, Vijayefcc4692014-05-09 14:47:38 +0530133 nss_info("NSS N2H rps_en %d \n",nnm->msg.rps_cfg.enable);
Vijay Dewangan488e5372014-12-29 21:40:11 -0800134 break;
135
136 case NSS_TX_METADATA_TYPE_N2H_EMPTY_POOL_BUF_CFG:
137 nss_info("%p: empty pool buf cfg response from FW", nss_ctx);
Pamidipati, Vijayefcc4692014-05-09 14:47:38 +0530138 break;
139
Radha krishna Simha Jiguru7f424d52015-02-10 19:41:01 +0530140 case NSS_TX_METADATA_TYPE_N2H_FLUSH_PAYLOADS:
141 nss_info("%p: flush payloads cmd response from FW", nss_ctx);
142 break;
143
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530144 case NSS_RX_METADATA_TYPE_N2H_STATS_SYNC:
Sundarajan Srinivasanf1e57462014-09-17 15:24:01 -0700145 nss_n2h_stats_sync(nss_ctx, &nnm->msg.stats_sync);
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530146 break;
147
148 default:
149 if (ncm->response != NSS_CMN_RESPONSE_ACK) {
150 /*
151 * Check response
152 */
153 nss_info("%p: Received response %d for type %d, interface %d",
154 nss_ctx, ncm->response, ncm->type, ncm->interface);
155 }
156 }
Vijay Dewangan488e5372014-12-29 21:40:11 -0800157
158 /*
159 * Update the callback and app_data for NOTIFY messages, IPv4 sends all notify messages
160 * to the same callback/app_data.
161 */
162 if (nnm->cm.response == NSS_CMM_RESPONSE_NOTIFY) {
163 /*
164 * Place holder for the user to create right call
165 * back and app data when response is NSS_CMM_RESPONSE_NOTIFY
166 */
167 ncm->cb = (uint32_t)nss_n2h_rd[nss_ctx->id].n2h_callback;
168 ncm->app_data = (uint32_t)nss_n2h_rd[nss_ctx->id].app_data;
169 }
170
171 /*
172 * Do we have a callback?
173 */
174 if (!ncm->cb) {
175 return;
176 }
177
178 /*
179 * Callback
180 */
181 cb = (nss_n2h_msg_callback_t)ncm->cb;
182 cb((void *)ncm->app_data, nnm);
183}
184
185/*
Vijay Dewangan634ce592015-01-07 17:21:09 -0800186 * nss_n2h_rps_cfg_callback()
187 * call back function for rps configuration
188 */
189static void nss_n2h_rps_cfg_callback(void *app_data, struct nss_n2h_msg *nnm)
190{
191 struct nss_ctx_instance *nss_ctx = (struct nss_ctx_instance *)app_data;
192 if (nnm->cm.response != NSS_CMN_RESPONSE_ACK) {
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_n2h_rcp.response = NSS_FAILURE;
199 complete(&nss_n2h_rcp.complete);
200 nss_warning("%p: RPS configuration failed : %d\n", nss_ctx,
201 nnm->cm.error);
202 return;
203 }
204
205 nss_info("%p: RPS configuration succeeded: %d\n", nss_ctx,
206 nnm->cm.error);
207 nss_ctx->n2h_rps_en = nnm->msg.rps_cfg.enable;
208 nss_n2h_rcp.response = NSS_SUCCESS;
209 complete(&nss_n2h_rcp.complete);
210}
211
212/*
Saurabh Misra71034db2015-06-04 16:18:38 -0700213 * nss_n2h_payload_stats_callback()
214 * It gets called response to payload accounting.
Vijay Dewangan488e5372014-12-29 21:40:11 -0800215 */
Saurabh Misra71034db2015-06-04 16:18:38 -0700216static void nss_n2h_payload_stats_callback(void *app_data,
217 struct nss_n2h_msg *nnm)
Vijay Dewangan488e5372014-12-29 21:40:11 -0800218{
219 int core_num = (int)app_data;
Saurabh Misra71034db2015-06-04 16:18:38 -0700220
Vijay Dewangan488e5372014-12-29 21:40:11 -0800221 if (nnm->cm.response != NSS_CMN_RESPONSE_ACK) {
222 struct nss_n2h_empty_pool_buf *nnepbcm;
223 nnepbcm = &nnm->msg.empty_pool_buf_cfg;
224
Saurabh Misra71034db2015-06-04 16:18:38 -0700225 nss_warning("%d: core empty pool buf set failure: %d\n",
226 core_num, nnm->cm.error);
Vijay Dewangan488e5372014-12-29 21:40:11 -0800227 nss_n2h_nepbcfgp[core_num].response = NSS_FAILURE;
228 complete(&nss_n2h_nepbcfgp[core_num].complete);
229 return;
230 }
231
Saurabh Misra71034db2015-06-04 16:18:38 -0700232 if (nnm->cm.type == NSS_TX_METADATA_TYPE_GET_PAYLOAD_INFO) {
233 nss_n2h_nepbcfgp[core_num].empty_buf_pool =
234 ntohl(nnm->msg.payload_info.pool_size);
235 nss_n2h_nepbcfgp[core_num].low_water =
236 ntohl(nnm->msg.payload_info.low_water);
237 nss_n2h_nepbcfgp[core_num].high_water =
238 ntohl(nnm->msg.payload_info.high_water);
239 }
240
Vijay Dewangan488e5372014-12-29 21:40:11 -0800241 nss_n2h_nepbcfgp[core_num].response = NSS_SUCCESS;
242 complete(&nss_n2h_nepbcfgp[core_num].complete);
243}
244
245/*
Saurabh Misra71034db2015-06-04 16:18:38 -0700246 * nss_n2h_get_payload_info()
247 * Gets Payload information
Vijay Dewangan488e5372014-12-29 21:40:11 -0800248 */
Saurabh Misra71034db2015-06-04 16:18:38 -0700249static int nss_n2h_get_payload_info(ctl_table *ctl, int write,
250 void __user *buffer, size_t *lenp, loff_t *ppos,
251 int core_num)
252{
253 struct nss_top_instance *nss_top = &nss_top_main;
254 struct nss_ctx_instance *nss_ctx = &nss_top->nss[core_num];
255 struct nss_n2h_msg nnm;
256 struct nss_n2h_payload_info *nnepbcm;
257 nss_tx_status_t nss_tx_status;
258 int ret = NSS_FAILURE;
259
260 /*
261 * Note that semaphore should be already held.
262 */
263
264 nss_n2h_msg_init(&nnm, NSS_N2H_INTERFACE,
265 NSS_TX_METADATA_TYPE_GET_PAYLOAD_INFO,
266 sizeof(struct nss_n2h_payload_info),
267 nss_n2h_payload_stats_callback,
268 (void *)core_num);
269
270 nnepbcm = &nnm.msg.payload_info;
271 nss_tx_status = nss_n2h_tx_msg(nss_ctx, &nnm);
272
273 if (nss_tx_status != NSS_TX_SUCCESS) {
274 nss_warning("%p: core %d nss_tx error errorn",
275 nss_ctx, core_num);
276 return NSS_FAILURE;
277 }
278
279 /*
280 * Blocking call, wait till we get ACK for this msg.
281 */
282 ret = wait_for_completion_timeout(&nss_n2h_nepbcfgp[core_num].complete,
283 msecs_to_jiffies(NSS_CONN_CFG_TIMEOUT));
284 if (ret == 0) {
285 nss_warning("%p: core %d waiting for ack timed out\n", nss_ctx,
286 core_num);
287 return NSS_FAILURE;
288 }
289
290 if (NSS_FAILURE == nss_n2h_nepbcfgp[core_num].response) {
291 nss_warning("%p: core %d response returned failure\n", nss_ctx,
292 core_num);
293 return NSS_FAILURE;
294 }
295
296 return NSS_SUCCESS;
297}
298
299/*
300 * nss_n2h_set_empty_pool_buf()
301 * Sets empty pool buffer
302 */
303static int nss_n2h_set_empty_pool_buf(ctl_table *ctl, int write,
304 void __user *buffer,
305 size_t *lenp, loff_t *ppos,
306 int core_num, int *new_val)
Vijay Dewangan488e5372014-12-29 21:40:11 -0800307{
308 struct nss_top_instance *nss_top = &nss_top_main;
309 struct nss_ctx_instance *nss_ctx = &nss_top->nss[core_num];
310 struct nss_n2h_msg nnm;
311 struct nss_n2h_empty_pool_buf *nnepbcm;
312 nss_tx_status_t nss_tx_status;
313 int ret = NSS_FAILURE;
314
315 /*
316 * Acquiring semaphore
317 */
318 down(&nss_n2h_nepbcfgp[core_num].sem);
319
320 /*
321 * Take snap shot of current value
322 */
Saurabh Misra71034db2015-06-04 16:18:38 -0700323 nss_n2h_nepbcfgp[core_num].empty_buf_pool = *new_val;
Vijay Dewangan488e5372014-12-29 21:40:11 -0800324
Saurabh Misra71034db2015-06-04 16:18:38 -0700325 if (!write) {
326 ret = nss_n2h_get_payload_info(ctl, write, buffer, lenp, ppos,
327 core_num);
328 *new_val = nss_n2h_nepbcfgp[core_num].empty_buf_pool;
329 if (ret == NSS_FAILURE) {
330 up(&nss_n2h_nepbcfgp[core_num].sem);
331 return -EBUSY;
332 }
333
334 up(&nss_n2h_nepbcfgp[core_num].sem);
335
336 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
337 return ret;
338 }
339
Vijay Dewangan488e5372014-12-29 21:40:11 -0800340 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
Saurabh Misra71034db2015-06-04 16:18:38 -0700341 if (ret) {
Vijay Dewangan488e5372014-12-29 21:40:11 -0800342 up(&nss_n2h_nepbcfgp[core_num].sem);
343 return ret;
344 }
345
Vijay Dewangan488e5372014-12-29 21:40:11 -0800346 if ((*new_val < NSS_N2H_MIN_EMPTY_POOL_BUF_SZ)) {
Saurabh Misra71034db2015-06-04 16:18:38 -0700347 nss_warning("%p: core %d setting %d < min number of buffer",
Vijay Dewangan488e5372014-12-29 21:40:11 -0800348 nss_ctx, core_num, *new_val);
Stephen Wang06761022015-03-03 16:38:42 -0800349 goto failure;
Vijay Dewangan488e5372014-12-29 21:40:11 -0800350 }
351
352 nss_info("%p: core %d number of empty pool buffer is : %d\n",
353 nss_ctx, core_num, *new_val);
354
355 nss_n2h_msg_init(&nnm, NSS_N2H_INTERFACE,
356 NSS_TX_METADATA_TYPE_N2H_EMPTY_POOL_BUF_CFG,
357 sizeof(struct nss_n2h_empty_pool_buf),
Saurabh Misra71034db2015-06-04 16:18:38 -0700358 nss_n2h_payload_stats_callback,
Vijay Dewangan488e5372014-12-29 21:40:11 -0800359 (void *)core_num);
360
361 nnepbcm = &nnm.msg.empty_pool_buf_cfg;
362 nnepbcm->pool_size = htonl(*new_val);
363 nss_tx_status = nss_n2h_tx_msg(nss_ctx, &nnm);
364
365 if (nss_tx_status != NSS_TX_SUCCESS) {
Saurabh Misra71034db2015-06-04 16:18:38 -0700366 nss_warning("%p: core %d nss_tx error empty pool buffer: %d\n",
Vijay Dewangan488e5372014-12-29 21:40:11 -0800367 nss_ctx, core_num, *new_val);
Stephen Wang06761022015-03-03 16:38:42 -0800368 goto failure;
Vijay Dewangan488e5372014-12-29 21:40:11 -0800369 }
370
371 /*
372 * Blocking call, wait till we get ACK for this msg.
373 */
Saurabh Misra71034db2015-06-04 16:18:38 -0700374 ret = wait_for_completion_timeout(&nss_n2h_nepbcfgp[core_num].complete,
375 msecs_to_jiffies(NSS_CONN_CFG_TIMEOUT));
Vijay Dewangan488e5372014-12-29 21:40:11 -0800376 if (ret == 0) {
Saurabh Misra71034db2015-06-04 16:18:38 -0700377 nss_warning("%p: core %d Waiting for ack timed out\n", nss_ctx,
378 core_num);
Stephen Wang06761022015-03-03 16:38:42 -0800379 goto failure;
Vijay Dewangan488e5372014-12-29 21:40:11 -0800380 }
381
382 /*
383 * ACK/NACK received from NSS FW
384 * If ACK: Callback function will update nss_n2h_empty_pool_buf with
385 * nss_n2h_nepbcfgp.num_conn_valid, which holds the user input
386 */
387 if (NSS_FAILURE == nss_n2h_nepbcfgp[core_num].response) {
Stephen Wang06761022015-03-03 16:38:42 -0800388 goto failure;
Vijay Dewangan488e5372014-12-29 21:40:11 -0800389 }
390
391 up(&nss_n2h_nepbcfgp[core_num].sem);
Thomas Wu651b3902015-05-12 11:21:09 -0700392 return 0;
Stephen Wang06761022015-03-03 16:38:42 -0800393
394failure:
395 /*
396 * Restore the current_value to its previous state
397 */
Saurabh Misra71034db2015-06-04 16:18:38 -0700398 *new_val = nss_n2h_nepbcfgp[core_num].empty_buf_pool;
399 up(&nss_n2h_nepbcfgp[core_num].sem);
400 return NSS_FAILURE;
401}
402
403/*
404 * nss_n2h_set_water_mark()
405 * Sets water mark for N2H SOS
406 */
407static int nss_n2h_set_water_mark(ctl_table *ctl, int write,
408 void __user *buffer,
409 size_t *lenp, loff_t *ppos,
410 int core_num, int *low, int *high)
411{
412 struct nss_top_instance *nss_top = &nss_top_main;
413 struct nss_ctx_instance *nss_ctx = &nss_top->nss[core_num];
414 struct nss_n2h_msg nnm;
415 struct nss_n2h_water_mark *wm;
416 nss_tx_status_t nss_tx_status;
417 int ret = NSS_FAILURE;
418
419 /*
420 * Acquiring semaphore
421 */
422 down(&nss_n2h_nepbcfgp[core_num].sem);
423
424 /*
425 * Take snap shot of current value
426 */
427 nss_n2h_nepbcfgp[core_num].low_water = *low;
428 nss_n2h_nepbcfgp[core_num].high_water = *high;
429
430 if (!write) {
431 ret = nss_n2h_get_payload_info(ctl, write, buffer, lenp, ppos,
432 core_num);
433 *low = nss_n2h_nepbcfgp[core_num].low_water;
434 *high = nss_n2h_nepbcfgp[core_num].high_water;
435
436 if (ret == NSS_FAILURE) {
437 up(&nss_n2h_nepbcfgp[core_num].sem);
438 return -EBUSY;
439 }
440
441 up(&nss_n2h_nepbcfgp[core_num].sem);
442 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
443 return ret;
444 }
445
446 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
447 if (ret) {
448 up(&nss_n2h_nepbcfgp[core_num].sem);
449 return ret;
450 }
451
452 /*
453 * If either low or high water mark is not set then we do
454 * nothing.
455 */
456 if (*low == -1 || *high == -1)
457 goto failure;
458
459 if ((*low < NSS_N2H_MIN_EMPTY_POOL_BUF_SZ) ||
460 (*high < NSS_N2H_MIN_EMPTY_POOL_BUF_SZ)) {
461 nss_warning("%p: core %d setting %d, %d < min number of buffer",
462 nss_ctx, core_num, *low, *high);
463 goto failure;
464 }
465
466 if ((*low > (NSS_N2H_DEFAULT_EMPTY_POOL_BUF_SZ * 2)) ||
467 (*high > (NSS_N2H_DEFAULT_EMPTY_POOL_BUF_SZ * 2))) {
468 nss_warning("%p: core %d setting %d, %d is > upper limit",
469 nss_ctx, core_num, *low, *high);
470 goto failure;
471 }
472
473 if (*low > *high) {
474 nss_warning("%p: core %d setting low %d is more than high %d",
475 nss_ctx, core_num, *low, *high);
476 goto failure;
477 }
478
479 nss_info("%p: core %d number of low : %d and high : %d\n",
480 nss_ctx, core_num, *low, *high);
481
482 nss_n2h_msg_init(&nnm, NSS_N2H_INTERFACE,
483 NSS_TX_METADATA_TYPE_SET_WATER_MARK,
484 sizeof(struct nss_n2h_water_mark),
485 nss_n2h_payload_stats_callback,
486 (void *)core_num);
487
488 wm = &nnm.msg.wm;
489 wm->low_water = htonl(*low);
490 wm->high_water = htonl(*high);
491 nss_tx_status = nss_n2h_tx_msg(nss_ctx, &nnm);
492
493 if (nss_tx_status != NSS_TX_SUCCESS) {
494 nss_warning("%p: core %d nss_tx error setting : %d, %d\n",
495 nss_ctx, core_num, *low, *high);
496 goto failure;
497 }
498
499 /*
500 * Blocking call, wait till we get ACK for this msg.
501 */
502 ret = wait_for_completion_timeout(&nss_n2h_nepbcfgp[core_num].complete,
503 msecs_to_jiffies(NSS_CONN_CFG_TIMEOUT));
504 if (ret == 0) {
505 nss_warning("%p: core %d Waiting for ack timed out\n", nss_ctx,
506 core_num);
507 goto failure;
508 }
509
510 /*
511 * ACK/NACK received from NSS FW
512 */
513 if (NSS_FAILURE == nss_n2h_nepbcfgp[core_num].response)
514 goto failure;
515
516 up(&nss_n2h_nepbcfgp[core_num].sem);
517 return NSS_SUCCESS;
518
519failure:
520 /*
521 * Restore the current_value to its previous state
522 */
523 *low = nss_n2h_nepbcfgp[core_num].low_water;
524 *high = nss_n2h_nepbcfgp[core_num].high_water;
Stephen Wang06761022015-03-03 16:38:42 -0800525 up(&nss_n2h_nepbcfgp[core_num].sem);
Thomas Wu651b3902015-05-12 11:21:09 -0700526 return -EINVAL;
Vijay Dewangan488e5372014-12-29 21:40:11 -0800527}
528
529/*
Radha krishna Simha Jiguru7f424d52015-02-10 19:41:01 +0530530 * nss_n2h_flush_payloads()
531 * Sends a command down to NSS for flushing all payloads
532 */
533nss_tx_status_t nss_n2h_flush_payloads(struct nss_ctx_instance *nss_ctx)
534{
535 struct nss_n2h_msg nnm;
536 struct nss_n2h_flush_payloads *nnflshpl;
537 nss_tx_status_t nss_tx_status;
538
539 nnflshpl = &nnm.msg.flush_payloads;
540
541 /*
542 * TODO: No additional information sent in message
543 * as of now. Need to initialize message content accordingly
544 * if needed.
545 */
546 nss_n2h_msg_init(&nnm, NSS_N2H_INTERFACE,
547 NSS_TX_METADATA_TYPE_N2H_FLUSH_PAYLOADS,
548 sizeof(struct nss_n2h_flush_payloads),
549 NULL,
550 NULL);
551
552 nss_tx_status = nss_n2h_tx_msg(nss_ctx, &nnm);
553 if (nss_tx_status != NSS_TX_SUCCESS) {
554 nss_warning("%p: failed to send flush payloads command to NSS\n",
555 nss_ctx);
556
557 return NSS_TX_FAILURE;
558 }
559
560 return NSS_TX_SUCCESS;
561}
562
563/*
Vijay Dewangan488e5372014-12-29 21:40:11 -0800564 * nss_n2h_empty_pool_buf_core1_handler()
565 * Sets the number of empty buffer for core 1
566 */
567static int nss_n2h_empty_pool_buf_cfg_core1_handler(ctl_table *ctl,
Saurabh Misra71034db2015-06-04 16:18:38 -0700568 int write, void __user *buffer,
569 size_t *lenp, loff_t *ppos)
Vijay Dewangan488e5372014-12-29 21:40:11 -0800570{
571 return nss_n2h_set_empty_pool_buf(ctl, write, buffer, lenp, ppos,
Saurabh Misra71034db2015-06-04 16:18:38 -0700572 NSS_CORE_1, &nss_n2h_empty_pool_buf_cfg[NSS_CORE_1]);
Vijay Dewangan488e5372014-12-29 21:40:11 -0800573}
574
575/*
576 * nss_n2h_empty_pool_buf_core0_handler()
577 * Sets the number of empty buffer for core 0
578 */
579static int nss_n2h_empty_pool_buf_cfg_core0_handler(ctl_table *ctl,
Saurabh Misra71034db2015-06-04 16:18:38 -0700580 int write, void __user *buffer,
581 size_t *lenp, loff_t *ppos)
Vijay Dewangan488e5372014-12-29 21:40:11 -0800582{
583 return nss_n2h_set_empty_pool_buf(ctl, write, buffer, lenp, ppos,
Saurabh Misra71034db2015-06-04 16:18:38 -0700584 NSS_CORE_0, &nss_n2h_empty_pool_buf_cfg[NSS_CORE_0]);
585}
586
587/*
588 * nss_n2h_water_mark_core1_handler()
589 * Sets water mark for core 1
590 */
591static int nss_n2h_water_mark_core1_handler(ctl_table *ctl,
592 int write, void __user *buffer,
593 size_t *lenp, loff_t *ppos)
594{
595 return nss_n2h_set_water_mark(ctl, write, buffer, lenp, ppos,
596 NSS_CORE_1, &nss_n2h_water_mark[NSS_CORE_1][0],
597 &nss_n2h_water_mark[NSS_CORE_1][1]);
598}
599
600/*
601 * nss_n2h_water_mark_core0_handler()
602 * Sets water mark for core 0
603 */
604static int nss_n2h_water_mark_core0_handler(ctl_table *ctl,
605 int write, void __user *buffer,
606 size_t *lenp, loff_t *ppos)
607{
608 return nss_n2h_set_water_mark(ctl, write, buffer, lenp, ppos,
609 NSS_CORE_0, &nss_n2h_water_mark[NSS_CORE_0][0],
610 &nss_n2h_water_mark[NSS_CORE_0][1]);
Vijay Dewangan488e5372014-12-29 21:40:11 -0800611}
612
Vijay Dewangan634ce592015-01-07 17:21:09 -0800613/*
614 * nss_n2h_rps_cfg()
615 * Send Message to NSS to enable RPS.
616 */
617nss_tx_status_t nss_n2h_rps_cfg(struct nss_ctx_instance *nss_ctx, int enable_rps)
618{
619 struct nss_n2h_msg nnm;
620 struct nss_n2h_rps *rps_cfg;
621 nss_tx_status_t nss_tx_status;
622 int ret;
623
624 down(&nss_n2h_rcp.sem);
625 nss_n2h_msg_init(&nnm, NSS_N2H_INTERFACE, NSS_TX_METADATA_TYPE_N2H_RPS_CFG,
626 sizeof(struct nss_n2h_rps),
627 nss_n2h_rps_cfg_callback,
628 (void *)nss_ctx);
629
630 rps_cfg = &nnm.msg.rps_cfg;
631 rps_cfg->enable = enable_rps;
632
633 nss_tx_status = nss_n2h_tx_msg(nss_ctx, &nnm);
634
635 if (nss_tx_status != NSS_TX_SUCCESS) {
636 nss_warning("%p: nss_tx error setting rps\n", nss_ctx);
637
638 up(&nss_n2h_rcp.sem);
639 return NSS_FAILURE;
640 }
641
642 /*
643 * Blocking call, wait till we get ACK for this msg.
644 */
645 ret = wait_for_completion_timeout(&nss_n2h_rcp.complete, msecs_to_jiffies(NSS_CONN_CFG_TIMEOUT));
646 if (ret == 0) {
647 nss_warning("%p: Waiting for ack timed out\n", nss_ctx);
648 up(&nss_n2h_rcp.sem);
649 return NSS_FAILURE;
650 }
651
652 /*
653 * ACK/NACK received from NSS FW
654 * If ACK: Callback function will update nss_n2h_empty_pool_buf with
655 * nss_n2h_nepbcfgp.num_conn_valid, which holds the user input
656 */
657 if (NSS_FAILURE == nss_n2h_rcp.response) {
658 up(&nss_n2h_rcp.sem);
659 return NSS_FAILURE;
660 }
661
662 up(&nss_n2h_rcp.sem);
663 return NSS_SUCCESS;
664}
665
Vijay Dewangan488e5372014-12-29 21:40:11 -0800666static ctl_table nss_n2h_table[] = {
667 {
Saurabh Misra71034db2015-06-04 16:18:38 -0700668 .procname = "n2h_empty_pool_buf_core0",
669 .data = &nss_n2h_empty_pool_buf_cfg[NSS_CORE_0],
670 .maxlen = sizeof(int),
671 .mode = 0644,
672 .proc_handler = &nss_n2h_empty_pool_buf_cfg_core0_handler,
Vijay Dewangan488e5372014-12-29 21:40:11 -0800673 },
674 {
Saurabh Misra71034db2015-06-04 16:18:38 -0700675 .procname = "n2h_empty_pool_buf_core1",
676 .data = &nss_n2h_empty_pool_buf_cfg[NSS_CORE_1],
677 .maxlen = sizeof(int),
678 .mode = 0644,
679 .proc_handler = &nss_n2h_empty_pool_buf_cfg_core1_handler,
680 },
681 {
682 .procname = "n2h_low_water_core0",
683 .data = &nss_n2h_water_mark[NSS_CORE_0][0],
684 .maxlen = sizeof(int),
685 .mode = 0644,
686 .proc_handler = &nss_n2h_water_mark_core0_handler,
687 },
688 {
689 .procname = "n2h_low_water_core1",
690 .data = &nss_n2h_water_mark[NSS_CORE_1][0],
691 .maxlen = sizeof(int),
692 .mode = 0644,
693 .proc_handler = &nss_n2h_water_mark_core1_handler,
694 },
695 {
696 .procname = "n2h_high_water_core0",
697 .data = &nss_n2h_water_mark[NSS_CORE_0][1],
698 .maxlen = sizeof(int),
699 .mode = 0644,
700 .proc_handler = &nss_n2h_water_mark_core0_handler,
701 },
702 {
703 .procname = "n2h_high_water_core1",
704 .data = &nss_n2h_water_mark[NSS_CORE_1][1],
705 .maxlen = sizeof(int),
706 .mode = 0644,
707 .proc_handler = &nss_n2h_water_mark_core1_handler,
Vijay Dewangan488e5372014-12-29 21:40:11 -0800708 },
709
710 { }
711};
712
713static ctl_table nss_n2h_dir[] = {
714 {
715 .procname = "n2hcfg",
716 .mode = 0555,
717 .child = nss_n2h_table,
718 },
719 { }
720};
721
722
723static ctl_table nss_n2h_root_dir[] = {
724 {
725 .procname = "nss",
726 .mode = 0555,
727 .child = nss_n2h_dir,
728 },
729 { }
730};
731
732static ctl_table nss_n2h_root[] = {
733 {
734 .procname = "dev",
735 .mode = 0555,
736 .child = nss_n2h_root_dir,
737 },
738 { }
739};
740
741static struct ctl_table_header *nss_n2h_header;
742
743/*
744 * nss_n2h_msg_init()
745 * Initialize IPv4 message.
746 */
747void nss_n2h_msg_init(struct nss_n2h_msg *nim, uint16_t if_num, uint32_t type,
Vijay Dewangan634ce592015-01-07 17:21:09 -0800748 uint32_t len, nss_n2h_msg_callback_t cb, void *app_data)
Vijay Dewangan488e5372014-12-29 21:40:11 -0800749{
750 nss_cmn_msg_init(&nim->cm, if_num, type, len, (void *)cb, app_data);
751}
752
Vijay Dewangan488e5372014-12-29 21:40:11 -0800753/*
754 * nss_n2h_register_sysctl()
755 * Register sysctl specific to n2h
756 */
757void nss_n2h_empty_pool_buf_register_sysctl(void)
758{
759 /*
760 * Register sysctl table.
761 */
762 nss_n2h_header = register_sysctl_table(nss_n2h_root);
763
764 /*
765 * Core0
766 */
767 sema_init(&nss_n2h_nepbcfgp[NSS_CORE_0].sem, 1);
768 init_completion(&nss_n2h_nepbcfgp[NSS_CORE_0].complete);
Saurabh Misra71034db2015-06-04 16:18:38 -0700769 nss_n2h_nepbcfgp[NSS_CORE_0].empty_buf_pool =
770 nss_n2h_empty_pool_buf_cfg[NSS_CORE_0];
771 nss_n2h_nepbcfgp[NSS_CORE_0].low_water =
772 nss_n2h_water_mark[NSS_CORE_0][0];
773 nss_n2h_nepbcfgp[NSS_CORE_0].high_water =
774 nss_n2h_water_mark[NSS_CORE_0][1];
Vijay Dewangan488e5372014-12-29 21:40:11 -0800775
776 /*
777 * Core1
778 */
779 sema_init(&nss_n2h_nepbcfgp[NSS_CORE_1].sem, 1);
780 init_completion(&nss_n2h_nepbcfgp[NSS_CORE_1].complete);
Saurabh Misra71034db2015-06-04 16:18:38 -0700781 nss_n2h_nepbcfgp[NSS_CORE_1].empty_buf_pool =
782 nss_n2h_empty_pool_buf_cfg[NSS_CORE_1];
783 nss_n2h_nepbcfgp[NSS_CORE_1].low_water =
784 nss_n2h_water_mark[NSS_CORE_1][0];
785 nss_n2h_nepbcfgp[NSS_CORE_1].high_water =
786 nss_n2h_water_mark[NSS_CORE_1][1];
Vijay Dewangan488e5372014-12-29 21:40:11 -0800787}
788
789/*
790 * nss_n2h_unregister_sysctl()
791 * Unregister sysctl specific to n2h
792 */
793void nss_n2h_empty_pool_buf_unregister_sysctl(void)
794{
795 /*
796 * Unregister sysctl table.
797 */
798 if (nss_n2h_header) {
799 unregister_sysctl_table(nss_n2h_header);
800 }
801}
802
803/*
804 * nss_n2h_tx_msg()
805 * Send messages to NSS n2h pacakge
806 */
807nss_tx_status_t nss_n2h_tx_msg(struct nss_ctx_instance *nss_ctx, struct nss_n2h_msg *nnm)
808{
809 struct nss_n2h_msg *nnm2;
810 struct nss_cmn_msg *ncm = &nnm->cm;
811 struct sk_buff *nbuf;
812 nss_tx_status_t status;
813
814 NSS_VERIFY_CTX_MAGIC(nss_ctx);
815 if (unlikely(nss_ctx->state != NSS_CORE_STATE_INITIALIZED)) {
816 return NSS_TX_FAILURE_NOT_READY;
817 }
818
819 /*
820 * Sanity check the message
821 */
822 if (ncm->interface != NSS_N2H_INTERFACE) {
823 nss_warning("%p: tx request for another interface: %d", nss_ctx, ncm->interface);
824 return NSS_TX_FAILURE;
825 }
826
827 if (ncm->type >= NSS_METADATA_TYPE_N2H_MAX) {
828 nss_warning("%p: message type out of range: %d", nss_ctx, ncm->type);
829 return NSS_TX_FAILURE;
830 }
831
832 if (ncm->len > sizeof(struct nss_n2h_msg)) {
833 nss_warning("%p: tx request for another interface: %d", nss_ctx, ncm->interface);
834 return NSS_TX_FAILURE;
835 }
836
837
838 nbuf = dev_alloc_skb(NSS_NBUF_PAYLOAD_SIZE);
839 if (unlikely(!nbuf)) {
Sundarajan Srinivasan62fee7e2015-01-22 11:13:10 -0800840 NSS_PKT_STATS_INCREMENT(nss_ctx, &nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_NBUF_ALLOC_FAILS]);
Vijay Dewangan488e5372014-12-29 21:40:11 -0800841 return NSS_TX_FAILURE;
842 }
843
844 /*
845 * Copy the message to our skb.
846 */
847 nnm2 = (struct nss_n2h_msg *)skb_put(nbuf, sizeof(struct nss_n2h_msg));
848 memcpy(nnm2, nnm, sizeof(struct nss_n2h_msg));
849 status = nss_core_send_buffer(nss_ctx, 0, nbuf, NSS_IF_CMD_QUEUE, H2N_BUFFER_CTRL, 0);
850 if (status != NSS_CORE_STATUS_SUCCESS) {
851 dev_kfree_skb_any(nbuf);
852 nss_info("%p: unable to enqueue 'nss frequency change' - marked as stopped\n", nss_ctx);
853 return NSS_TX_FAILURE;
854 }
855
856 nss_hal_send_interrupt(nss_ctx->nmap,
857 nss_ctx->h2n_desc_rings[NSS_IF_CMD_QUEUE].desc_ring.int_bit,
858 NSS_REGS_H2N_INTR_STATUS_DATA_COMMAND_QUEUE);
859 NSS_PKT_STATS_INCREMENT(nss_ctx, &nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_TX_CMD_REQ]);
860 return NSS_TX_SUCCESS;
861}
862
Vijay Dewangan488e5372014-12-29 21:40:11 -0800863/*
864 * nss_n2h_notify_register()
865 * Register to received N2H events.
866 *
867 * NOTE: Do we want to pass an nss_ctx here so that we can register for n2h on any core?
868 */
869struct nss_ctx_instance *nss_n2h_notify_register(int core, nss_n2h_msg_callback_t cb, void *app_data)
870{
871 if (core >= NSS_MAX_CORES) {
872 nss_warning("Input core number %d is wrong \n", core);
873 return NULL;
874 }
875 /*
876 * TODO: We need to have a new array in support of the new API
877 * TODO: If we use a per-context array, we would move the array into nss_ctx based.
878 */
879 nss_n2h_rd[core].n2h_callback = cb;
880 nss_n2h_rd[core].app_data = app_data;
881 return &nss_top_main.nss[core];
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530882}
883
884/*
885 * nss_n2h_register_handler()
886 */
887void nss_n2h_register_handler()
888{
Sundarajan Srinivasanf1e57462014-09-17 15:24:01 -0700889 nss_core_register_handler(NSS_N2H_INTERFACE, nss_n2h_interface_handler, NULL);
890
Vijay Dewangan634ce592015-01-07 17:21:09 -0800891 /*
892 * RPS sema init
893 */
894 sema_init(&nss_n2h_rcp.sem, 1);
895 init_completion(&nss_n2h_rcp.complete);
896
897
Vijay Dewangan488e5372014-12-29 21:40:11 -0800898 nss_n2h_notify_register(NSS_CORE_0, NULL, NULL);
899 nss_n2h_notify_register(NSS_CORE_1, NULL, NULL);
900
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530901}
Vijay Dewangan488e5372014-12-29 21:40:11 -0800902
903EXPORT_SYMBOL(nss_n2h_notify_register);
Vijay Dewanganac7efc42015-02-09 16:04:53 -0800904EXPORT_SYMBOL(nss_n2h_empty_pool_buf_register_sysctl);