blob: d37294859e6d1e42ca82c4ead8dd94d2a77eea03 [file] [log] [blame]
Abhishek Rastogi84d95d02014-03-26 19:31:31 +05301/*
2 **************************************************************************
Pamidipati, Vijayee9c2972016-01-10 08:13:19 +05303 * Copyright (c) 2013-2016, 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"
Kalyan Tallapragadab50e8902015-08-06 17:00:54 +053023#include <asm/cacheflush.h>
Abhishek Rastogi84d95d02014-03-26 19:31:31 +053024
Pamidipati, Vijayefcc4692014-05-09 14:47:38 +053025
Saurabh Misra71034db2015-06-04 16:18:38 -070026#define NSS_N2H_MIN_EMPTY_POOL_BUF_SZ 32
Pamidipati, Vijayee9c2972016-01-10 08:13:19 +053027#define NSS_N2H_MAX_EMPTY_POOL_BUF_SZ 65536
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, Vijayee9c2972016-01-10 08:13:19 +053032int nss_n2h_wifi_pool_buf_cfg __read_mostly = -1;
Pamidipati, Vijayefcc4692014-05-09 14:47:38 +053033
Vijay Dewangan488e5372014-12-29 21:40:11 -080034struct nss_n2h_registered_data {
35 nss_n2h_msg_callback_t n2h_callback;
36 void *app_data;
37};
Pamidipati, Vijayefcc4692014-05-09 14:47:38 +053038
Vijay Dewangan488e5372014-12-29 21:40:11 -080039static struct nss_n2h_cfg_pvt nss_n2h_nepbcfgp[NSS_MAX_CORES];
40static struct nss_n2h_registered_data nss_n2h_rd[NSS_MAX_CORES];
Vijay Dewangan634ce592015-01-07 17:21:09 -080041static struct nss_n2h_cfg_pvt nss_n2h_rcp;
Kalyan Tallapragadab50e8902015-08-06 17:00:54 +053042static struct nss_n2h_cfg_pvt nss_n2h_mitigationcp[NSS_CORE_MAX];
43static struct nss_n2h_cfg_pvt nss_n2h_bufcp[NSS_CORE_MAX];
Pamidipati, Vijayee9c2972016-01-10 08:13:19 +053044static struct nss_n2h_cfg_pvt nss_n2h_wp;
Pamidipati, Vijayefcc4692014-05-09 14:47:38 +053045
46/*
Sundarajan Srinivasanf1e57462014-09-17 15:24:01 -070047 * nss_n2h_stats_sync()
Abhishek Rastogi84d95d02014-03-26 19:31:31 +053048 * Handle the syncing of NSS statistics.
49 */
Sundarajan Srinivasanf1e57462014-09-17 15:24:01 -070050static void nss_n2h_stats_sync(struct nss_ctx_instance *nss_ctx, struct nss_n2h_stats_sync *nnss)
Abhishek Rastogi84d95d02014-03-26 19:31:31 +053051{
52 struct nss_top_instance *nss_top = nss_ctx->nss_top;
53
54 spin_lock_bh(&nss_top->stats_lock);
55
56 /*
57 * common node stats
58 */
59 nss_ctx->stats_n2h[NSS_STATS_NODE_RX_PKTS] += nnss->node_stats.rx_packets;
60 nss_ctx->stats_n2h[NSS_STATS_NODE_RX_BYTES] += nnss->node_stats.rx_bytes;
61 nss_ctx->stats_n2h[NSS_STATS_NODE_RX_DROPPED] += nnss->node_stats.rx_dropped;
62 nss_ctx->stats_n2h[NSS_STATS_NODE_TX_PKTS] += nnss->node_stats.tx_packets;
63 nss_ctx->stats_n2h[NSS_STATS_NODE_TX_BYTES] += nnss->node_stats.tx_bytes;
64
65 /*
66 * General N2H stats
67 */
Murat Sezgin0c0561d2014-04-09 18:55:58 -070068 nss_ctx->stats_n2h[NSS_STATS_N2H_QUEUE_DROPPED] += nnss->queue_dropped;
69 nss_ctx->stats_n2h[NSS_STATS_N2H_TOTAL_TICKS] += nnss->total_ticks;
70 nss_ctx->stats_n2h[NSS_STATS_N2H_WORST_CASE_TICKS] += nnss->worst_case_ticks;
71 nss_ctx->stats_n2h[NSS_STATS_N2H_ITERATIONS] += nnss->iterations;
Abhishek Rastogi84d95d02014-03-26 19:31:31 +053072
73 /*
Thomas Wu3fd8dd72014-06-11 15:57:05 -070074 * pbuf manager ocm and default pool stats
Abhishek Rastogi84d95d02014-03-26 19:31:31 +053075 */
Thomas Wu3fd8dd72014-06-11 15:57:05 -070076 nss_ctx->stats_n2h[NSS_STATS_N2H_PBUF_OCM_ALLOC_FAILS] += nnss->pbuf_ocm_stats.pbuf_alloc_fails;
77 nss_ctx->stats_n2h[NSS_STATS_N2H_PBUF_OCM_FREE_COUNT] = nnss->pbuf_ocm_stats.pbuf_free_count;
78 nss_ctx->stats_n2h[NSS_STATS_N2H_PBUF_OCM_TOTAL_COUNT] = nnss->pbuf_ocm_stats.pbuf_total_count;
79
80 nss_ctx->stats_n2h[NSS_STATS_N2H_PBUF_DEFAULT_ALLOC_FAILS] += nnss->pbuf_default_stats.pbuf_alloc_fails;
81 nss_ctx->stats_n2h[NSS_STATS_N2H_PBUF_DEFAULT_FREE_COUNT] = nnss->pbuf_default_stats.pbuf_free_count;
82 nss_ctx->stats_n2h[NSS_STATS_N2H_PBUF_DEFAULT_TOTAL_COUNT] = nnss->pbuf_default_stats.pbuf_total_count;
83
84 /*
85 * payload mgr stats
86 */
Abhishek Rastogi84d95d02014-03-26 19:31:31 +053087 nss_ctx->stats_n2h[NSS_STATS_N2H_PAYLOAD_ALLOC_FAILS] += nnss->payload_alloc_fails;
Thomas Wu53679842015-01-22 13:37:35 -080088 nss_ctx->stats_n2h[NSS_STATS_N2H_PAYLOAD_FREE_COUNT] = nnss->payload_free_count;
Abhishek Rastogi84d95d02014-03-26 19:31:31 +053089
Sakthi Vignesh Radhakrishnan2a8ee962014-11-22 13:35:38 -080090 /*
91 * Host <=> NSS control traffic stats
92 */
93 nss_ctx->stats_n2h[NSS_STATS_N2H_H2N_CONTROL_PACKETS] += nnss->h2n_ctrl_pkts;
94 nss_ctx->stats_n2h[NSS_STATS_N2H_H2N_CONTROL_BYTES] += nnss->h2n_ctrl_bytes;
95 nss_ctx->stats_n2h[NSS_STATS_N2H_N2H_CONTROL_PACKETS] += nnss->n2h_ctrl_pkts;
96 nss_ctx->stats_n2h[NSS_STATS_N2H_N2H_CONTROL_BYTES] += nnss->n2h_ctrl_bytes;
97
98 /*
99 * Host <=> NSS control data traffic stats
100 */
101 nss_ctx->stats_n2h[NSS_STATS_N2H_H2N_DATA_PACKETS] += nnss->h2n_data_pkts;
102 nss_ctx->stats_n2h[NSS_STATS_N2H_H2N_DATA_BYTES] += nnss->h2n_data_bytes;
103 nss_ctx->stats_n2h[NSS_STATS_N2H_N2H_DATA_PACKETS] += nnss->n2h_data_pkts;
104 nss_ctx->stats_n2h[NSS_STATS_N2H_N2H_DATA_BYTES] += nnss->n2h_data_bytes;
105
Saurabh Misra71034db2015-06-04 16:18:38 -0700106 /*
107 * Payloads related stats
108 */
109 nss_ctx->stats_n2h[NSS_STATS_N2H_N2H_TOT_PAYLOADS] = nnss->tot_payloads;
110
Guojun Jin85dfa7b2015-09-02 15:13:56 -0700111 nss_ctx->stats_n2h[NSS_STATS_N2H_N2H_INTERFACE_INVALID] += nnss->data_interface_invalid;
112
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530113 spin_unlock_bh(&nss_top->stats_lock);
114}
115
116/*
Sundarajan Srinivasanf1e57462014-09-17 15:24:01 -0700117 * nss_n2h_interface_handler()
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530118 * Handle NSS -> HLOS messages for N2H node
119 */
Vijay Dewangan634ce592015-01-07 17:21:09 -0800120static void nss_n2h_interface_handler(struct nss_ctx_instance *nss_ctx,
121 struct nss_cmn_msg *ncm,
122 __attribute__((unused))void *app_data)
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530123{
124 struct nss_n2h_msg *nnm = (struct nss_n2h_msg *)ncm;
Vijay Dewangan488e5372014-12-29 21:40:11 -0800125 nss_n2h_msg_callback_t cb;
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530126
Sundarajan Srinivasanf1e57462014-09-17 15:24:01 -0700127 BUG_ON(ncm->interface != NSS_N2H_INTERFACE);
128
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530129 /*
130 * Is this a valid request/response packet?
131 */
132 if (nnm->cm.type >= NSS_METADATA_TYPE_N2H_MAX) {
133 nss_warning("%p: received invalid message %d for Offload stats interface", nss_ctx, nnm->cm.type);
134 return;
135 }
136
137 switch (nnm->cm.type) {
Pamidipati, Vijayefcc4692014-05-09 14:47:38 +0530138 case NSS_TX_METADATA_TYPE_N2H_RPS_CFG:
Pamidipati, Vijayefcc4692014-05-09 14:47:38 +0530139 nss_info("NSS N2H rps_en %d \n",nnm->msg.rps_cfg.enable);
Vijay Dewangan488e5372014-12-29 21:40:11 -0800140 break;
141
Kalyan Tallapragadab50e8902015-08-06 17:00:54 +0530142 case NSS_TX_METADATA_TYPE_N2H_MITIGATION_CFG:
143 nss_info("NSS N2H mitigation_dis %d \n",nnm->msg.mitigation_cfg.enable);
144 break;
145
Vijay Dewangan488e5372014-12-29 21:40:11 -0800146 case NSS_TX_METADATA_TYPE_N2H_EMPTY_POOL_BUF_CFG:
147 nss_info("%p: empty pool buf cfg response from FW", nss_ctx);
Pamidipati, Vijayefcc4692014-05-09 14:47:38 +0530148 break;
149
Radha krishna Simha Jiguru7f424d52015-02-10 19:41:01 +0530150 case NSS_TX_METADATA_TYPE_N2H_FLUSH_PAYLOADS:
151 nss_info("%p: flush payloads cmd response from FW", nss_ctx);
152 break;
153
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530154 case NSS_RX_METADATA_TYPE_N2H_STATS_SYNC:
Sundarajan Srinivasanf1e57462014-09-17 15:24:01 -0700155 nss_n2h_stats_sync(nss_ctx, &nnm->msg.stats_sync);
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530156 break;
157
158 default:
159 if (ncm->response != NSS_CMN_RESPONSE_ACK) {
160 /*
161 * Check response
162 */
163 nss_info("%p: Received response %d for type %d, interface %d",
164 nss_ctx, ncm->response, ncm->type, ncm->interface);
165 }
166 }
Vijay Dewangan488e5372014-12-29 21:40:11 -0800167
168 /*
169 * Update the callback and app_data for NOTIFY messages, IPv4 sends all notify messages
170 * to the same callback/app_data.
171 */
172 if (nnm->cm.response == NSS_CMM_RESPONSE_NOTIFY) {
173 /*
174 * Place holder for the user to create right call
175 * back and app data when response is NSS_CMM_RESPONSE_NOTIFY
176 */
177 ncm->cb = (uint32_t)nss_n2h_rd[nss_ctx->id].n2h_callback;
178 ncm->app_data = (uint32_t)nss_n2h_rd[nss_ctx->id].app_data;
179 }
180
181 /*
182 * Do we have a callback?
183 */
184 if (!ncm->cb) {
185 return;
186 }
187
188 /*
189 * Callback
190 */
191 cb = (nss_n2h_msg_callback_t)ncm->cb;
192 cb((void *)ncm->app_data, nnm);
193}
194
195/*
Vijay Dewangan634ce592015-01-07 17:21:09 -0800196 * nss_n2h_rps_cfg_callback()
197 * call back function for rps configuration
198 */
199static void nss_n2h_rps_cfg_callback(void *app_data, struct nss_n2h_msg *nnm)
200{
201 struct nss_ctx_instance *nss_ctx = (struct nss_ctx_instance *)app_data;
202 if (nnm->cm.response != NSS_CMN_RESPONSE_ACK) {
203
204 /*
205 * Error, hence we are not updating the nss_n2h_empty_pool_buf
206 * Restore the current_value to its previous state
207 */
208 nss_n2h_rcp.response = NSS_FAILURE;
209 complete(&nss_n2h_rcp.complete);
210 nss_warning("%p: RPS configuration failed : %d\n", nss_ctx,
211 nnm->cm.error);
212 return;
213 }
214
215 nss_info("%p: RPS configuration succeeded: %d\n", nss_ctx,
216 nnm->cm.error);
217 nss_ctx->n2h_rps_en = nnm->msg.rps_cfg.enable;
218 nss_n2h_rcp.response = NSS_SUCCESS;
219 complete(&nss_n2h_rcp.complete);
220}
221
222/*
Kalyan Tallapragadab50e8902015-08-06 17:00:54 +0530223 * nss_n2h_mitigation_cfg_callback()
224 * call back function for mitigation configuration
225 */
226static void nss_n2h_mitigation_cfg_callback(void *app_data, struct nss_n2h_msg *nnm)
227{
228 int core_num = (int)app_data;
229 struct nss_top_instance *nss_top = &nss_top_main;
230 struct nss_ctx_instance *nss_ctx = &nss_top->nss[core_num];
231
232 if (nnm->cm.response != NSS_CMN_RESPONSE_ACK) {
233
234 /*
235 * Error, hence we are not updating the nss_n2h_mitigate_en
236 */
237 nss_n2h_mitigationcp[core_num].response = NSS_FAILURE;
238 complete(&nss_n2h_mitigationcp[core_num].complete);
239 nss_warning("core%d: MITIGATION configuration failed : %d\n", core_num, nnm->cm.error);
240 return;
241 }
242
243 nss_info("core%d: MITIGATION configuration succeeded: %d\n", core_num, nnm->cm.error);
244
245 nss_ctx->n2h_mitigate_en = nnm->msg.mitigation_cfg.enable;
246 nss_n2h_mitigationcp[core_num].response = NSS_SUCCESS;
247 complete(&nss_n2h_mitigationcp[core_num].complete);
248}
249
250/*
251 * nss_n2h_buf_cfg_callback()
252 * call back function for pbuf configuration
253 */
254static void nss_n2h_bufs_cfg_callback(void *app_data, struct nss_n2h_msg *nnm)
255{
256 int core_num = (int)app_data;
257 unsigned int allocated_sz;
258
259 struct nss_top_instance *nss_top = &nss_top_main;
260 struct nss_ctx_instance *nss_ctx = &nss_top->nss[core_num];
261
262 if (nnm->cm.response != NSS_CMN_RESPONSE_ACK) {
263 nss_n2h_bufcp[core_num].response = NSS_FAILURE;
264 nss_warning("core%d: buf configuration failed : %d\n", core_num, nnm->cm.error);
265 goto done;
266 }
267
268 nss_info("core%d: buf configuration succeeded: %d\n", core_num, nnm->cm.error);
269
270 allocated_sz = nnm->msg.buf_pool.nss_buf_page_size * nnm->msg.buf_pool.nss_buf_num_pages;
271 nss_ctx->buf_sz_allocated += allocated_sz;
272
273 nss_n2h_bufcp[core_num].response = NSS_SUCCESS;
274
275done:
276 complete(&nss_n2h_bufcp[core_num].complete);
277}
278
279/*
Saurabh Misra71034db2015-06-04 16:18:38 -0700280 * nss_n2h_payload_stats_callback()
281 * It gets called response to payload accounting.
Vijay Dewangan488e5372014-12-29 21:40:11 -0800282 */
Saurabh Misra71034db2015-06-04 16:18:38 -0700283static void nss_n2h_payload_stats_callback(void *app_data,
284 struct nss_n2h_msg *nnm)
Vijay Dewangan488e5372014-12-29 21:40:11 -0800285{
286 int core_num = (int)app_data;
Saurabh Misra71034db2015-06-04 16:18:38 -0700287
Vijay Dewangan488e5372014-12-29 21:40:11 -0800288 if (nnm->cm.response != NSS_CMN_RESPONSE_ACK) {
289 struct nss_n2h_empty_pool_buf *nnepbcm;
290 nnepbcm = &nnm->msg.empty_pool_buf_cfg;
291
Saurabh Misra71034db2015-06-04 16:18:38 -0700292 nss_warning("%d: core empty pool buf set failure: %d\n",
293 core_num, nnm->cm.error);
Vijay Dewangan488e5372014-12-29 21:40:11 -0800294 nss_n2h_nepbcfgp[core_num].response = NSS_FAILURE;
295 complete(&nss_n2h_nepbcfgp[core_num].complete);
296 return;
297 }
298
Saurabh Misra71034db2015-06-04 16:18:38 -0700299 if (nnm->cm.type == NSS_TX_METADATA_TYPE_GET_PAYLOAD_INFO) {
300 nss_n2h_nepbcfgp[core_num].empty_buf_pool =
301 ntohl(nnm->msg.payload_info.pool_size);
302 nss_n2h_nepbcfgp[core_num].low_water =
303 ntohl(nnm->msg.payload_info.low_water);
304 nss_n2h_nepbcfgp[core_num].high_water =
305 ntohl(nnm->msg.payload_info.high_water);
306 }
307
Vijay Dewangan488e5372014-12-29 21:40:11 -0800308 nss_n2h_nepbcfgp[core_num].response = NSS_SUCCESS;
309 complete(&nss_n2h_nepbcfgp[core_num].complete);
310}
311
312/*
Pamidipati, Vijayee9c2972016-01-10 08:13:19 +0530313 * nss_n2h_set_wifi_payloads_callback()
314 * call back function for response to wifi pool configuration
315 *
316 */
317static void nss_n2h_set_wifi_payloads_callback(void *app_data,
318 struct nss_n2h_msg *nnm)
319{
320 struct nss_ctx_instance *nss_ctx = (struct nss_ctx_instance *)app_data;
321 if (nnm->cm.response != NSS_CMN_RESPONSE_ACK) {
322
323 nss_n2h_wp.response = NSS_FAILURE;
324 complete(&nss_n2h_wp.complete);
325 nss_warning("%p: wifi pool configuration failed : %d\n", nss_ctx,
326 nnm->cm.error);
327 return;
328 }
329
330 nss_info("%p: wifi payload configuration succeeded: %d\n", nss_ctx,
331 nnm->cm.error);
332 nss_n2h_wp.response = NSS_SUCCESS;
333 complete(&nss_n2h_wp.complete);
334}
335
336/*
Saurabh Misra71034db2015-06-04 16:18:38 -0700337 * nss_n2h_get_payload_info()
338 * Gets Payload information
Vijay Dewangan488e5372014-12-29 21:40:11 -0800339 */
Saurabh Misra71034db2015-06-04 16:18:38 -0700340static int nss_n2h_get_payload_info(ctl_table *ctl, int write,
341 void __user *buffer, size_t *lenp, loff_t *ppos,
342 int core_num)
343{
344 struct nss_top_instance *nss_top = &nss_top_main;
345 struct nss_ctx_instance *nss_ctx = &nss_top->nss[core_num];
346 struct nss_n2h_msg nnm;
347 struct nss_n2h_payload_info *nnepbcm;
348 nss_tx_status_t nss_tx_status;
349 int ret = NSS_FAILURE;
350
351 /*
352 * Note that semaphore should be already held.
353 */
354
355 nss_n2h_msg_init(&nnm, NSS_N2H_INTERFACE,
356 NSS_TX_METADATA_TYPE_GET_PAYLOAD_INFO,
357 sizeof(struct nss_n2h_payload_info),
358 nss_n2h_payload_stats_callback,
359 (void *)core_num);
360
361 nnepbcm = &nnm.msg.payload_info;
362 nss_tx_status = nss_n2h_tx_msg(nss_ctx, &nnm);
363
364 if (nss_tx_status != NSS_TX_SUCCESS) {
365 nss_warning("%p: core %d nss_tx error errorn",
366 nss_ctx, core_num);
367 return NSS_FAILURE;
368 }
369
370 /*
371 * Blocking call, wait till we get ACK for this msg.
372 */
373 ret = wait_for_completion_timeout(&nss_n2h_nepbcfgp[core_num].complete,
374 msecs_to_jiffies(NSS_CONN_CFG_TIMEOUT));
375 if (ret == 0) {
376 nss_warning("%p: core %d waiting for ack timed out\n", nss_ctx,
377 core_num);
378 return NSS_FAILURE;
379 }
380
381 if (NSS_FAILURE == nss_n2h_nepbcfgp[core_num].response) {
382 nss_warning("%p: core %d response returned failure\n", nss_ctx,
383 core_num);
384 return NSS_FAILURE;
385 }
386
387 return NSS_SUCCESS;
388}
389
390/*
391 * nss_n2h_set_empty_pool_buf()
392 * Sets empty pool buffer
393 */
394static int nss_n2h_set_empty_pool_buf(ctl_table *ctl, int write,
395 void __user *buffer,
396 size_t *lenp, loff_t *ppos,
397 int core_num, int *new_val)
Vijay Dewangan488e5372014-12-29 21:40:11 -0800398{
399 struct nss_top_instance *nss_top = &nss_top_main;
400 struct nss_ctx_instance *nss_ctx = &nss_top->nss[core_num];
401 struct nss_n2h_msg nnm;
402 struct nss_n2h_empty_pool_buf *nnepbcm;
403 nss_tx_status_t nss_tx_status;
404 int ret = NSS_FAILURE;
405
406 /*
407 * Acquiring semaphore
408 */
409 down(&nss_n2h_nepbcfgp[core_num].sem);
410
411 /*
412 * Take snap shot of current value
413 */
Saurabh Misra71034db2015-06-04 16:18:38 -0700414 nss_n2h_nepbcfgp[core_num].empty_buf_pool = *new_val;
Vijay Dewangan488e5372014-12-29 21:40:11 -0800415
Saurabh Misra71034db2015-06-04 16:18:38 -0700416 if (!write) {
417 ret = nss_n2h_get_payload_info(ctl, write, buffer, lenp, ppos,
418 core_num);
419 *new_val = nss_n2h_nepbcfgp[core_num].empty_buf_pool;
420 if (ret == NSS_FAILURE) {
421 up(&nss_n2h_nepbcfgp[core_num].sem);
422 return -EBUSY;
423 }
424
425 up(&nss_n2h_nepbcfgp[core_num].sem);
426
427 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
428 return ret;
429 }
430
Vijay Dewangan488e5372014-12-29 21:40:11 -0800431 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
Saurabh Misra71034db2015-06-04 16:18:38 -0700432 if (ret) {
Vijay Dewangan488e5372014-12-29 21:40:11 -0800433 up(&nss_n2h_nepbcfgp[core_num].sem);
434 return ret;
435 }
436
Vijay Dewangan488e5372014-12-29 21:40:11 -0800437 if ((*new_val < NSS_N2H_MIN_EMPTY_POOL_BUF_SZ)) {
Saurabh Misra71034db2015-06-04 16:18:38 -0700438 nss_warning("%p: core %d setting %d < min number of buffer",
Vijay Dewangan488e5372014-12-29 21:40:11 -0800439 nss_ctx, core_num, *new_val);
Stephen Wang06761022015-03-03 16:38:42 -0800440 goto failure;
Vijay Dewangan488e5372014-12-29 21:40:11 -0800441 }
442
443 nss_info("%p: core %d number of empty pool buffer is : %d\n",
444 nss_ctx, core_num, *new_val);
445
446 nss_n2h_msg_init(&nnm, NSS_N2H_INTERFACE,
447 NSS_TX_METADATA_TYPE_N2H_EMPTY_POOL_BUF_CFG,
448 sizeof(struct nss_n2h_empty_pool_buf),
Saurabh Misra71034db2015-06-04 16:18:38 -0700449 nss_n2h_payload_stats_callback,
Vijay Dewangan488e5372014-12-29 21:40:11 -0800450 (void *)core_num);
451
452 nnepbcm = &nnm.msg.empty_pool_buf_cfg;
453 nnepbcm->pool_size = htonl(*new_val);
454 nss_tx_status = nss_n2h_tx_msg(nss_ctx, &nnm);
455
456 if (nss_tx_status != NSS_TX_SUCCESS) {
Saurabh Misra71034db2015-06-04 16:18:38 -0700457 nss_warning("%p: core %d nss_tx error empty pool buffer: %d\n",
Vijay Dewangan488e5372014-12-29 21:40:11 -0800458 nss_ctx, core_num, *new_val);
Stephen Wang06761022015-03-03 16:38:42 -0800459 goto failure;
Vijay Dewangan488e5372014-12-29 21:40:11 -0800460 }
461
462 /*
463 * Blocking call, wait till we get ACK for this msg.
464 */
Saurabh Misra71034db2015-06-04 16:18:38 -0700465 ret = wait_for_completion_timeout(&nss_n2h_nepbcfgp[core_num].complete,
466 msecs_to_jiffies(NSS_CONN_CFG_TIMEOUT));
Vijay Dewangan488e5372014-12-29 21:40:11 -0800467 if (ret == 0) {
Saurabh Misra71034db2015-06-04 16:18:38 -0700468 nss_warning("%p: core %d Waiting for ack timed out\n", nss_ctx,
469 core_num);
Stephen Wang06761022015-03-03 16:38:42 -0800470 goto failure;
Vijay Dewangan488e5372014-12-29 21:40:11 -0800471 }
472
473 /*
474 * ACK/NACK received from NSS FW
475 * If ACK: Callback function will update nss_n2h_empty_pool_buf with
476 * nss_n2h_nepbcfgp.num_conn_valid, which holds the user input
477 */
478 if (NSS_FAILURE == nss_n2h_nepbcfgp[core_num].response) {
Stephen Wang06761022015-03-03 16:38:42 -0800479 goto failure;
Vijay Dewangan488e5372014-12-29 21:40:11 -0800480 }
481
482 up(&nss_n2h_nepbcfgp[core_num].sem);
Thomas Wu651b3902015-05-12 11:21:09 -0700483 return 0;
Stephen Wang06761022015-03-03 16:38:42 -0800484
485failure:
486 /*
487 * Restore the current_value to its previous state
488 */
Saurabh Misra71034db2015-06-04 16:18:38 -0700489 *new_val = nss_n2h_nepbcfgp[core_num].empty_buf_pool;
490 up(&nss_n2h_nepbcfgp[core_num].sem);
491 return NSS_FAILURE;
492}
493
494/*
495 * nss_n2h_set_water_mark()
496 * Sets water mark for N2H SOS
497 */
498static int nss_n2h_set_water_mark(ctl_table *ctl, int write,
499 void __user *buffer,
500 size_t *lenp, loff_t *ppos,
501 int core_num, int *low, int *high)
502{
503 struct nss_top_instance *nss_top = &nss_top_main;
504 struct nss_ctx_instance *nss_ctx = &nss_top->nss[core_num];
505 struct nss_n2h_msg nnm;
506 struct nss_n2h_water_mark *wm;
507 nss_tx_status_t nss_tx_status;
508 int ret = NSS_FAILURE;
509
510 /*
511 * Acquiring semaphore
512 */
513 down(&nss_n2h_nepbcfgp[core_num].sem);
514
515 /*
516 * Take snap shot of current value
517 */
518 nss_n2h_nepbcfgp[core_num].low_water = *low;
519 nss_n2h_nepbcfgp[core_num].high_water = *high;
520
521 if (!write) {
522 ret = nss_n2h_get_payload_info(ctl, write, buffer, lenp, ppos,
523 core_num);
524 *low = nss_n2h_nepbcfgp[core_num].low_water;
525 *high = nss_n2h_nepbcfgp[core_num].high_water;
526
527 if (ret == NSS_FAILURE) {
528 up(&nss_n2h_nepbcfgp[core_num].sem);
529 return -EBUSY;
530 }
531
532 up(&nss_n2h_nepbcfgp[core_num].sem);
533 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
534 return ret;
535 }
536
537 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
538 if (ret) {
539 up(&nss_n2h_nepbcfgp[core_num].sem);
540 return ret;
541 }
542
543 /*
544 * If either low or high water mark is not set then we do
545 * nothing.
546 */
547 if (*low == -1 || *high == -1)
548 goto failure;
549
550 if ((*low < NSS_N2H_MIN_EMPTY_POOL_BUF_SZ) ||
551 (*high < NSS_N2H_MIN_EMPTY_POOL_BUF_SZ)) {
552 nss_warning("%p: core %d setting %d, %d < min number of buffer",
553 nss_ctx, core_num, *low, *high);
554 goto failure;
555 }
556
Pamidipati, Vijayee9c2972016-01-10 08:13:19 +0530557 if ((*low > NSS_N2H_MAX_EMPTY_POOL_BUF_SZ) ||
558 (*high > NSS_N2H_MAX_EMPTY_POOL_BUF_SZ)) {
Saurabh Misra71034db2015-06-04 16:18:38 -0700559 nss_warning("%p: core %d setting %d, %d is > upper limit",
560 nss_ctx, core_num, *low, *high);
561 goto failure;
562 }
563
564 if (*low > *high) {
565 nss_warning("%p: core %d setting low %d is more than high %d",
566 nss_ctx, core_num, *low, *high);
567 goto failure;
568 }
569
570 nss_info("%p: core %d number of low : %d and high : %d\n",
571 nss_ctx, core_num, *low, *high);
572
573 nss_n2h_msg_init(&nnm, NSS_N2H_INTERFACE,
574 NSS_TX_METADATA_TYPE_SET_WATER_MARK,
575 sizeof(struct nss_n2h_water_mark),
576 nss_n2h_payload_stats_callback,
577 (void *)core_num);
578
579 wm = &nnm.msg.wm;
580 wm->low_water = htonl(*low);
581 wm->high_water = htonl(*high);
582 nss_tx_status = nss_n2h_tx_msg(nss_ctx, &nnm);
583
584 if (nss_tx_status != NSS_TX_SUCCESS) {
585 nss_warning("%p: core %d nss_tx error setting : %d, %d\n",
586 nss_ctx, core_num, *low, *high);
587 goto failure;
588 }
589
590 /*
591 * Blocking call, wait till we get ACK for this msg.
592 */
593 ret = wait_for_completion_timeout(&nss_n2h_nepbcfgp[core_num].complete,
594 msecs_to_jiffies(NSS_CONN_CFG_TIMEOUT));
595 if (ret == 0) {
596 nss_warning("%p: core %d Waiting for ack timed out\n", nss_ctx,
597 core_num);
598 goto failure;
599 }
600
601 /*
602 * ACK/NACK received from NSS FW
603 */
604 if (NSS_FAILURE == nss_n2h_nepbcfgp[core_num].response)
605 goto failure;
606
607 up(&nss_n2h_nepbcfgp[core_num].sem);
608 return NSS_SUCCESS;
609
610failure:
611 /*
612 * Restore the current_value to its previous state
613 */
614 *low = nss_n2h_nepbcfgp[core_num].low_water;
615 *high = nss_n2h_nepbcfgp[core_num].high_water;
Stephen Wang06761022015-03-03 16:38:42 -0800616 up(&nss_n2h_nepbcfgp[core_num].sem);
Thomas Wu651b3902015-05-12 11:21:09 -0700617 return -EINVAL;
Vijay Dewangan488e5372014-12-29 21:40:11 -0800618}
619
620/*
Pamidipati, Vijayee9c2972016-01-10 08:13:19 +0530621 * nss_n2h_cfg_wifi_pool()
622 * Sets number of wifi payloads to adjust high water mark for N2H SoS
623 */
624static int nss_n2h_cfg_wifi_pool(ctl_table *ctl, int write,
625 void __user *buffer,
626 size_t *lenp, loff_t *ppos,
627 int *payloads)
628{
629 struct nss_top_instance *nss_top = &nss_top_main;
630 struct nss_ctx_instance *nss_ctx = &nss_top->nss[0];
631 struct nss_n2h_msg nnm;
632 struct nss_n2h_wifi_payloads *wp;
633 nss_tx_status_t nss_tx_status;
634 int ret = NSS_FAILURE;
635
636 /*
637 * Acquiring semaphore
638 */
639 down(&nss_n2h_wp.sem);
640
641 if (!write) {
642 *payloads = nss_n2h_wp.wifi_pool;
643
644 up(&nss_n2h_wp.sem);
645 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
646 return ret;
647 }
648
649 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
650 if (ret) {
651 up(&nss_n2h_wp.sem);
652 return ret;
653 }
654
655 /*
656 * If payloads parameter is not set, we do
657 * nothing.
658 */
659 if (*payloads == -1)
660 goto failure;
661
662 if ((*payloads < NSS_N2H_MIN_EMPTY_POOL_BUF_SZ)) {
663 nss_warning("%p: wifi setting %d < min number of buffer",
664 nss_ctx, *payloads);
665 goto failure;
666 }
667
668 if ((*payloads > NSS_N2H_MAX_EMPTY_POOL_BUF_SZ)) {
669 nss_warning("%p: wifi setting %d > max number of buffer",
670 nss_ctx, *payloads);
671 goto failure;
672 }
673
674 nss_info("%p: wifi payloads : %d\n",
675 nss_ctx, *payloads);
676
677 nss_n2h_msg_init(&nnm, NSS_N2H_INTERFACE,
678 NSS_TX_METADATA_TYPE_N2H_WIFI_POOL_BUF_CFG,
679 sizeof(struct nss_n2h_wifi_payloads),
680 nss_n2h_set_wifi_payloads_callback,
681 (void *)nss_ctx);
682
683 wp = &nnm.msg.wp;
684 wp->payloads = htonl(*payloads);
685 nss_tx_status = nss_n2h_tx_msg(nss_ctx, &nnm);
686
687 if (nss_tx_status != NSS_TX_SUCCESS) {
688 nss_warning("%p: wifi setting %d nss_tx error",
689 nss_ctx, *payloads);
690 goto failure;
691 }
692
693 /*
694 * Blocking call, wait till we get ACK for this msg.
695 */
696 ret = wait_for_completion_timeout(&nss_n2h_wp.complete,
697 msecs_to_jiffies(NSS_CONN_CFG_TIMEOUT));
698 if (ret == 0) {
699 nss_warning("%p: Waiting for ack timed out\n", nss_ctx);
700 goto failure;
701 }
702
703 /*
704 * ACK/NACK received from NSS FW
705 */
706 if (NSS_FAILURE == nss_n2h_wp.response)
707 goto failure;
708
709 up(&nss_n2h_wp.sem);
710 return NSS_SUCCESS;
711
712failure:
713 up(&nss_n2h_wp.sem);
714 return -EINVAL;
715}
716
717/*
Radha krishna Simha Jiguru7f424d52015-02-10 19:41:01 +0530718 * nss_n2h_flush_payloads()
719 * Sends a command down to NSS for flushing all payloads
720 */
721nss_tx_status_t nss_n2h_flush_payloads(struct nss_ctx_instance *nss_ctx)
722{
723 struct nss_n2h_msg nnm;
724 struct nss_n2h_flush_payloads *nnflshpl;
725 nss_tx_status_t nss_tx_status;
726
727 nnflshpl = &nnm.msg.flush_payloads;
728
729 /*
730 * TODO: No additional information sent in message
731 * as of now. Need to initialize message content accordingly
732 * if needed.
733 */
734 nss_n2h_msg_init(&nnm, NSS_N2H_INTERFACE,
735 NSS_TX_METADATA_TYPE_N2H_FLUSH_PAYLOADS,
736 sizeof(struct nss_n2h_flush_payloads),
737 NULL,
738 NULL);
739
740 nss_tx_status = nss_n2h_tx_msg(nss_ctx, &nnm);
741 if (nss_tx_status != NSS_TX_SUCCESS) {
742 nss_warning("%p: failed to send flush payloads command to NSS\n",
743 nss_ctx);
744
745 return NSS_TX_FAILURE;
746 }
747
748 return NSS_TX_SUCCESS;
749}
750
751/*
Vijay Dewangan488e5372014-12-29 21:40:11 -0800752 * nss_n2h_empty_pool_buf_core1_handler()
753 * Sets the number of empty buffer for core 1
754 */
755static int nss_n2h_empty_pool_buf_cfg_core1_handler(ctl_table *ctl,
Saurabh Misra71034db2015-06-04 16:18:38 -0700756 int write, void __user *buffer,
757 size_t *lenp, loff_t *ppos)
Vijay Dewangan488e5372014-12-29 21:40:11 -0800758{
759 return nss_n2h_set_empty_pool_buf(ctl, write, buffer, lenp, ppos,
Saurabh Misra71034db2015-06-04 16:18:38 -0700760 NSS_CORE_1, &nss_n2h_empty_pool_buf_cfg[NSS_CORE_1]);
Vijay Dewangan488e5372014-12-29 21:40:11 -0800761}
762
763/*
764 * nss_n2h_empty_pool_buf_core0_handler()
765 * Sets the number of empty buffer for core 0
766 */
767static int nss_n2h_empty_pool_buf_cfg_core0_handler(ctl_table *ctl,
Saurabh Misra71034db2015-06-04 16:18:38 -0700768 int write, void __user *buffer,
769 size_t *lenp, loff_t *ppos)
Vijay Dewangan488e5372014-12-29 21:40:11 -0800770{
771 return nss_n2h_set_empty_pool_buf(ctl, write, buffer, lenp, ppos,
Saurabh Misra71034db2015-06-04 16:18:38 -0700772 NSS_CORE_0, &nss_n2h_empty_pool_buf_cfg[NSS_CORE_0]);
773}
774
775/*
776 * nss_n2h_water_mark_core1_handler()
777 * Sets water mark for core 1
778 */
779static int nss_n2h_water_mark_core1_handler(ctl_table *ctl,
780 int write, void __user *buffer,
781 size_t *lenp, loff_t *ppos)
782{
783 return nss_n2h_set_water_mark(ctl, write, buffer, lenp, ppos,
784 NSS_CORE_1, &nss_n2h_water_mark[NSS_CORE_1][0],
785 &nss_n2h_water_mark[NSS_CORE_1][1]);
786}
787
788/*
789 * nss_n2h_water_mark_core0_handler()
790 * Sets water mark for core 0
791 */
792static int nss_n2h_water_mark_core0_handler(ctl_table *ctl,
793 int write, void __user *buffer,
794 size_t *lenp, loff_t *ppos)
795{
796 return nss_n2h_set_water_mark(ctl, write, buffer, lenp, ppos,
797 NSS_CORE_0, &nss_n2h_water_mark[NSS_CORE_0][0],
798 &nss_n2h_water_mark[NSS_CORE_0][1]);
Vijay Dewangan488e5372014-12-29 21:40:11 -0800799}
800
Vijay Dewangan634ce592015-01-07 17:21:09 -0800801/*
Pamidipati, Vijayee9c2972016-01-10 08:13:19 +0530802 * nss_n2h_wifi_payloads_handler()
803 * Sets number of wifi payloads
804 */
805static int nss_n2h_wifi_payloads_handler(ctl_table *ctl,
806 int write, void __user *buffer,
807 size_t *lenp, loff_t *ppos)
808{
809 return nss_n2h_cfg_wifi_pool(ctl, write, buffer, lenp, ppos,
810 &nss_n2h_wifi_pool_buf_cfg);
811}
812
813/*
Vijay Dewangan634ce592015-01-07 17:21:09 -0800814 * nss_n2h_rps_cfg()
815 * Send Message to NSS to enable RPS.
816 */
817nss_tx_status_t nss_n2h_rps_cfg(struct nss_ctx_instance *nss_ctx, int enable_rps)
818{
819 struct nss_n2h_msg nnm;
820 struct nss_n2h_rps *rps_cfg;
821 nss_tx_status_t nss_tx_status;
822 int ret;
823
824 down(&nss_n2h_rcp.sem);
825 nss_n2h_msg_init(&nnm, NSS_N2H_INTERFACE, NSS_TX_METADATA_TYPE_N2H_RPS_CFG,
826 sizeof(struct nss_n2h_rps),
827 nss_n2h_rps_cfg_callback,
828 (void *)nss_ctx);
829
830 rps_cfg = &nnm.msg.rps_cfg;
831 rps_cfg->enable = enable_rps;
832
833 nss_tx_status = nss_n2h_tx_msg(nss_ctx, &nnm);
834
835 if (nss_tx_status != NSS_TX_SUCCESS) {
836 nss_warning("%p: nss_tx error setting rps\n", nss_ctx);
837
838 up(&nss_n2h_rcp.sem);
839 return NSS_FAILURE;
840 }
841
842 /*
843 * Blocking call, wait till we get ACK for this msg.
844 */
845 ret = wait_for_completion_timeout(&nss_n2h_rcp.complete, msecs_to_jiffies(NSS_CONN_CFG_TIMEOUT));
846 if (ret == 0) {
847 nss_warning("%p: Waiting for ack timed out\n", nss_ctx);
848 up(&nss_n2h_rcp.sem);
849 return NSS_FAILURE;
850 }
851
852 /*
853 * ACK/NACK received from NSS FW
854 * If ACK: Callback function will update nss_n2h_empty_pool_buf with
855 * nss_n2h_nepbcfgp.num_conn_valid, which holds the user input
856 */
857 if (NSS_FAILURE == nss_n2h_rcp.response) {
858 up(&nss_n2h_rcp.sem);
859 return NSS_FAILURE;
860 }
861
862 up(&nss_n2h_rcp.sem);
863 return NSS_SUCCESS;
864}
865
Kalyan Tallapragadab50e8902015-08-06 17:00:54 +0530866/*
867 * nss_n2h_mitigation_cfg()
868 * Send Message to NSS to disable MITIGATION.
869 */
870nss_tx_status_t nss_n2h_mitigation_cfg(struct nss_ctx_instance *nss_ctx, int enable_mitigation, nss_core_id_t core_num)
871{
872 struct nss_n2h_msg nnm;
873 struct nss_n2h_mitigation *mitigation_cfg;
874 nss_tx_status_t nss_tx_status;
875 int ret;
876
877 nss_assert(core_num < NSS_CORE_MAX);
878
879 down(&nss_n2h_mitigationcp[core_num].sem);
880 nss_n2h_msg_init(&nnm, NSS_N2H_INTERFACE, NSS_TX_METADATA_TYPE_N2H_MITIGATION_CFG,
881 sizeof(struct nss_n2h_mitigation),
882 nss_n2h_mitigation_cfg_callback,
883 (void *)core_num);
884
885 mitigation_cfg = &nnm.msg.mitigation_cfg;
886 mitigation_cfg->enable = enable_mitigation;
887
888 nss_tx_status = nss_n2h_tx_msg(nss_ctx, &nnm);
889
890 if (nss_tx_status != NSS_TX_SUCCESS) {
891 nss_warning("%p: nss_tx error setting mitigation\n", nss_ctx);
892 goto failure;
893 }
894
895 /*
896 * Blocking call, wait till we get ACK for this msg.
897 */
898 ret = wait_for_completion_timeout(&nss_n2h_mitigationcp[core_num].complete, msecs_to_jiffies(NSS_CONN_CFG_TIMEOUT));
899 if (ret == 0) {
900 nss_warning("%p: Waiting for ack timed out\n", nss_ctx);
901 goto failure;
902 }
903
904 /*
905 * ACK/NACK received from NSS FW
906 */
907 if (NSS_FAILURE == nss_n2h_mitigationcp[core_num].response) {
908 goto failure;
909 }
910
911 up(&nss_n2h_mitigationcp[core_num].sem);
912 return NSS_SUCCESS;
913
914failure:
915 up(&nss_n2h_mitigationcp[core_num].sem);
916 return NSS_FAILURE;
917}
918
919static inline void nss_n2h_buf_pool_free(struct nss_n2h_buf_pool *buf_pool)
920{
921 int page_count;
922 for (page_count = 0; page_count < buf_pool->nss_buf_num_pages; page_count++) {
923 kfree(buf_pool->nss_buf_pool_vaddr[page_count]);
924 }
925}
926
927/*
928 * nss_n2h_buf_cfg()
929 * Send Message to NSS to enable pbufs.
930 */
931nss_tx_status_t nss_n2h_buf_pool_cfg(struct nss_ctx_instance *nss_ctx,
932 int buf_pool_size, nss_core_id_t core_num)
933{
934 static struct nss_n2h_msg nnm;
935 struct nss_n2h_buf_pool *buf_pool;
936 nss_tx_status_t nss_tx_status;
937 int ret;
938 int page_count;
939 int num_pages = ALIGN(buf_pool_size, PAGE_SIZE)/PAGE_SIZE;
940
941 nss_assert(core_num < NSS_CORE_MAX);
942
943 nss_n2h_msg_init(&nnm, NSS_N2H_INTERFACE, NSS_METADATA_TYPE_N2H_ADD_BUF_POOL,
944 sizeof(struct nss_n2h_buf_pool),
945 nss_n2h_bufs_cfg_callback,
946 (void *)core_num);
947
948 do {
949
950 down(&nss_n2h_bufcp[core_num].sem);
951
952 buf_pool = &nnm.msg.buf_pool;
953 buf_pool->nss_buf_page_size = PAGE_SIZE;
954
955 for (page_count = 0; page_count < MAX_PAGES_PER_MSG && num_pages; page_count++, num_pages--) {
956
957 void *kern_addr = kzalloc(PAGE_SIZE, GFP_ATOMIC);
958 if (!kern_addr) {
959 BUG_ON(!page_count);
960 break;
961 }
962 BUG_ON((long unsigned int)kern_addr % PAGE_SIZE);
963
964 buf_pool->nss_buf_pool_vaddr[page_count] = kern_addr;
965 buf_pool->nss_buf_pool_addr[page_count] = dma_map_single(NULL, kern_addr, PAGE_SIZE, DMA_TO_DEVICE);
966 }
967
968 buf_pool->nss_buf_num_pages = page_count;
969 nss_tx_status = nss_n2h_tx_msg(nss_ctx, &nnm);
970 if (nss_tx_status != NSS_TX_SUCCESS) {
971
972 nss_n2h_buf_pool_free(buf_pool);
973 nss_warning("%p: nss_tx error setting pbuf\n", nss_ctx);
974 goto failure;
975 }
976
977 /*
978 * Blocking call, wait till we get ACK for this msg.
979 */
980 ret = wait_for_completion_timeout(&nss_n2h_bufcp[core_num].complete, msecs_to_jiffies(NSS_CONN_CFG_TIMEOUT));
981 if (ret == 0) {
982 nss_warning("%p: Waiting for ack timed out\n", nss_ctx);
983 goto failure;
984 }
985
986 /*
987 * ACK/NACK received from NSS FW
988 */
989 if (NSS_FAILURE == nss_n2h_bufcp[core_num].response) {
990
991 nss_n2h_buf_pool_free(buf_pool);
992 goto failure;
993 }
994
995 up(&nss_n2h_bufcp[core_num].sem);
996 } while(num_pages);
997
998 return NSS_SUCCESS;
999failure:
1000 up(&nss_n2h_bufcp[core_num].sem);
1001 return NSS_FAILURE;
1002}
1003
1004
1005
Vijay Dewangan488e5372014-12-29 21:40:11 -08001006static ctl_table nss_n2h_table[] = {
1007 {
Saurabh Misra71034db2015-06-04 16:18:38 -07001008 .procname = "n2h_empty_pool_buf_core0",
1009 .data = &nss_n2h_empty_pool_buf_cfg[NSS_CORE_0],
1010 .maxlen = sizeof(int),
1011 .mode = 0644,
1012 .proc_handler = &nss_n2h_empty_pool_buf_cfg_core0_handler,
Vijay Dewangan488e5372014-12-29 21:40:11 -08001013 },
1014 {
Saurabh Misra71034db2015-06-04 16:18:38 -07001015 .procname = "n2h_empty_pool_buf_core1",
1016 .data = &nss_n2h_empty_pool_buf_cfg[NSS_CORE_1],
1017 .maxlen = sizeof(int),
1018 .mode = 0644,
1019 .proc_handler = &nss_n2h_empty_pool_buf_cfg_core1_handler,
1020 },
1021 {
1022 .procname = "n2h_low_water_core0",
1023 .data = &nss_n2h_water_mark[NSS_CORE_0][0],
1024 .maxlen = sizeof(int),
1025 .mode = 0644,
1026 .proc_handler = &nss_n2h_water_mark_core0_handler,
1027 },
1028 {
1029 .procname = "n2h_low_water_core1",
1030 .data = &nss_n2h_water_mark[NSS_CORE_1][0],
1031 .maxlen = sizeof(int),
1032 .mode = 0644,
1033 .proc_handler = &nss_n2h_water_mark_core1_handler,
1034 },
1035 {
1036 .procname = "n2h_high_water_core0",
1037 .data = &nss_n2h_water_mark[NSS_CORE_0][1],
1038 .maxlen = sizeof(int),
1039 .mode = 0644,
1040 .proc_handler = &nss_n2h_water_mark_core0_handler,
1041 },
1042 {
1043 .procname = "n2h_high_water_core1",
1044 .data = &nss_n2h_water_mark[NSS_CORE_1][1],
1045 .maxlen = sizeof(int),
1046 .mode = 0644,
1047 .proc_handler = &nss_n2h_water_mark_core1_handler,
Vijay Dewangan488e5372014-12-29 21:40:11 -08001048 },
Pamidipati, Vijayee9c2972016-01-10 08:13:19 +05301049 {
1050 .procname = "n2h_wifi_pool_buf",
1051 .data = &nss_n2h_wifi_pool_buf_cfg,
1052 .maxlen = sizeof(int),
1053 .mode = 0644,
1054 .proc_handler = &nss_n2h_wifi_payloads_handler,
1055 },
Vijay Dewangan488e5372014-12-29 21:40:11 -08001056
1057 { }
1058};
1059
1060static ctl_table nss_n2h_dir[] = {
1061 {
1062 .procname = "n2hcfg",
1063 .mode = 0555,
1064 .child = nss_n2h_table,
1065 },
1066 { }
1067};
1068
1069
1070static ctl_table nss_n2h_root_dir[] = {
1071 {
1072 .procname = "nss",
1073 .mode = 0555,
1074 .child = nss_n2h_dir,
1075 },
1076 { }
1077};
1078
1079static ctl_table nss_n2h_root[] = {
1080 {
1081 .procname = "dev",
1082 .mode = 0555,
1083 .child = nss_n2h_root_dir,
1084 },
1085 { }
1086};
1087
1088static struct ctl_table_header *nss_n2h_header;
1089
1090/*
1091 * nss_n2h_msg_init()
1092 * Initialize IPv4 message.
1093 */
1094void nss_n2h_msg_init(struct nss_n2h_msg *nim, uint16_t if_num, uint32_t type,
Vijay Dewangan634ce592015-01-07 17:21:09 -08001095 uint32_t len, nss_n2h_msg_callback_t cb, void *app_data)
Vijay Dewangan488e5372014-12-29 21:40:11 -08001096{
1097 nss_cmn_msg_init(&nim->cm, if_num, type, len, (void *)cb, app_data);
1098}
1099
Vijay Dewangan488e5372014-12-29 21:40:11 -08001100/*
1101 * nss_n2h_register_sysctl()
1102 * Register sysctl specific to n2h
1103 */
1104void nss_n2h_empty_pool_buf_register_sysctl(void)
1105{
1106 /*
1107 * Register sysctl table.
1108 */
1109 nss_n2h_header = register_sysctl_table(nss_n2h_root);
1110
1111 /*
1112 * Core0
1113 */
1114 sema_init(&nss_n2h_nepbcfgp[NSS_CORE_0].sem, 1);
1115 init_completion(&nss_n2h_nepbcfgp[NSS_CORE_0].complete);
Saurabh Misra71034db2015-06-04 16:18:38 -07001116 nss_n2h_nepbcfgp[NSS_CORE_0].empty_buf_pool =
1117 nss_n2h_empty_pool_buf_cfg[NSS_CORE_0];
1118 nss_n2h_nepbcfgp[NSS_CORE_0].low_water =
1119 nss_n2h_water_mark[NSS_CORE_0][0];
1120 nss_n2h_nepbcfgp[NSS_CORE_0].high_water =
1121 nss_n2h_water_mark[NSS_CORE_0][1];
Vijay Dewangan488e5372014-12-29 21:40:11 -08001122
1123 /*
1124 * Core1
1125 */
1126 sema_init(&nss_n2h_nepbcfgp[NSS_CORE_1].sem, 1);
1127 init_completion(&nss_n2h_nepbcfgp[NSS_CORE_1].complete);
Saurabh Misra71034db2015-06-04 16:18:38 -07001128 nss_n2h_nepbcfgp[NSS_CORE_1].empty_buf_pool =
1129 nss_n2h_empty_pool_buf_cfg[NSS_CORE_1];
1130 nss_n2h_nepbcfgp[NSS_CORE_1].low_water =
1131 nss_n2h_water_mark[NSS_CORE_1][0];
1132 nss_n2h_nepbcfgp[NSS_CORE_1].high_water =
1133 nss_n2h_water_mark[NSS_CORE_1][1];
Pamidipati, Vijayee9c2972016-01-10 08:13:19 +05301134
1135 /*
1136 * WiFi pool buf cfg sema init
1137 */
1138 sema_init(&nss_n2h_wp.sem, 1);
1139 init_completion(&nss_n2h_wp.complete);
Vijay Dewangan488e5372014-12-29 21:40:11 -08001140}
1141
1142/*
1143 * nss_n2h_unregister_sysctl()
1144 * Unregister sysctl specific to n2h
1145 */
1146void nss_n2h_empty_pool_buf_unregister_sysctl(void)
1147{
1148 /*
1149 * Unregister sysctl table.
1150 */
1151 if (nss_n2h_header) {
1152 unregister_sysctl_table(nss_n2h_header);
1153 }
1154}
1155
1156/*
1157 * nss_n2h_tx_msg()
1158 * Send messages to NSS n2h pacakge
1159 */
1160nss_tx_status_t nss_n2h_tx_msg(struct nss_ctx_instance *nss_ctx, struct nss_n2h_msg *nnm)
1161{
1162 struct nss_n2h_msg *nnm2;
1163 struct nss_cmn_msg *ncm = &nnm->cm;
1164 struct sk_buff *nbuf;
1165 nss_tx_status_t status;
1166
1167 NSS_VERIFY_CTX_MAGIC(nss_ctx);
1168 if (unlikely(nss_ctx->state != NSS_CORE_STATE_INITIALIZED)) {
1169 return NSS_TX_FAILURE_NOT_READY;
1170 }
1171
1172 /*
1173 * Sanity check the message
1174 */
1175 if (ncm->interface != NSS_N2H_INTERFACE) {
1176 nss_warning("%p: tx request for another interface: %d", nss_ctx, ncm->interface);
1177 return NSS_TX_FAILURE;
1178 }
1179
1180 if (ncm->type >= NSS_METADATA_TYPE_N2H_MAX) {
1181 nss_warning("%p: message type out of range: %d", nss_ctx, ncm->type);
1182 return NSS_TX_FAILURE;
1183 }
1184
Suruchi Agarwalef8a8702016-01-08 12:40:08 -08001185 if (nss_cmn_get_msg_len(ncm) > sizeof(struct nss_n2h_msg)) {
1186 nss_warning("%p: tx request for another interface: %d", nss_ctx, nss_cmn_get_msg_len(ncm));
Vijay Dewangan488e5372014-12-29 21:40:11 -08001187 return NSS_TX_FAILURE;
1188 }
1189
1190
1191 nbuf = dev_alloc_skb(NSS_NBUF_PAYLOAD_SIZE);
1192 if (unlikely(!nbuf)) {
Sundarajan Srinivasan62fee7e2015-01-22 11:13:10 -08001193 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 -08001194 return NSS_TX_FAILURE;
1195 }
1196
1197 /*
1198 * Copy the message to our skb.
1199 */
1200 nnm2 = (struct nss_n2h_msg *)skb_put(nbuf, sizeof(struct nss_n2h_msg));
1201 memcpy(nnm2, nnm, sizeof(struct nss_n2h_msg));
1202 status = nss_core_send_buffer(nss_ctx, 0, nbuf, NSS_IF_CMD_QUEUE, H2N_BUFFER_CTRL, 0);
1203 if (status != NSS_CORE_STATUS_SUCCESS) {
1204 dev_kfree_skb_any(nbuf);
1205 nss_info("%p: unable to enqueue 'nss frequency change' - marked as stopped\n", nss_ctx);
1206 return NSS_TX_FAILURE;
1207 }
1208
1209 nss_hal_send_interrupt(nss_ctx->nmap,
1210 nss_ctx->h2n_desc_rings[NSS_IF_CMD_QUEUE].desc_ring.int_bit,
1211 NSS_REGS_H2N_INTR_STATUS_DATA_COMMAND_QUEUE);
1212 NSS_PKT_STATS_INCREMENT(nss_ctx, &nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_TX_CMD_REQ]);
1213 return NSS_TX_SUCCESS;
1214}
1215
Vijay Dewangan488e5372014-12-29 21:40:11 -08001216/*
1217 * nss_n2h_notify_register()
1218 * Register to received N2H events.
1219 *
1220 * NOTE: Do we want to pass an nss_ctx here so that we can register for n2h on any core?
1221 */
1222struct nss_ctx_instance *nss_n2h_notify_register(int core, nss_n2h_msg_callback_t cb, void *app_data)
1223{
1224 if (core >= NSS_MAX_CORES) {
1225 nss_warning("Input core number %d is wrong \n", core);
1226 return NULL;
1227 }
1228 /*
1229 * TODO: We need to have a new array in support of the new API
1230 * TODO: If we use a per-context array, we would move the array into nss_ctx based.
1231 */
1232 nss_n2h_rd[core].n2h_callback = cb;
1233 nss_n2h_rd[core].app_data = app_data;
1234 return &nss_top_main.nss[core];
Abhishek Rastogi84d95d02014-03-26 19:31:31 +05301235}
1236
1237/*
1238 * nss_n2h_register_handler()
1239 */
1240void nss_n2h_register_handler()
1241{
Sundarajan Srinivasanf1e57462014-09-17 15:24:01 -07001242 nss_core_register_handler(NSS_N2H_INTERFACE, nss_n2h_interface_handler, NULL);
1243
Vijay Dewangan634ce592015-01-07 17:21:09 -08001244 /*
1245 * RPS sema init
1246 */
1247 sema_init(&nss_n2h_rcp.sem, 1);
1248 init_completion(&nss_n2h_rcp.complete);
1249
Kalyan Tallapragadab50e8902015-08-06 17:00:54 +05301250 /*
1251 * MITIGATION sema init for core0
1252 */
1253 sema_init(&nss_n2h_mitigationcp[NSS_CORE_0].sem, 1);
1254 init_completion(&nss_n2h_mitigationcp[NSS_CORE_0].complete);
1255
1256 /*
1257 * MITIGATION sema init for core1
1258 */
1259 sema_init(&nss_n2h_mitigationcp[NSS_CORE_1].sem, 1);
1260 init_completion(&nss_n2h_mitigationcp[NSS_CORE_1].complete);
1261
1262 /*
1263 * PBUF addition sema init for core0
1264 */
1265 sema_init(&nss_n2h_bufcp[NSS_CORE_0].sem, 1);
1266 init_completion(&nss_n2h_bufcp[NSS_CORE_0].complete);
1267
1268 /*
1269 * PBUF addition sema init for core1
1270 */
1271 sema_init(&nss_n2h_bufcp[NSS_CORE_1].sem, 1);
1272 init_completion(&nss_n2h_bufcp[NSS_CORE_1].complete);
Vijay Dewangan634ce592015-01-07 17:21:09 -08001273
Vijay Dewangan488e5372014-12-29 21:40:11 -08001274 nss_n2h_notify_register(NSS_CORE_0, NULL, NULL);
1275 nss_n2h_notify_register(NSS_CORE_1, NULL, NULL);
1276
Abhishek Rastogi84d95d02014-03-26 19:31:31 +05301277}
Vijay Dewangan488e5372014-12-29 21:40:11 -08001278
1279EXPORT_SYMBOL(nss_n2h_notify_register);
Vijay Dewanganac7efc42015-02-09 16:04:53 -08001280EXPORT_SYMBOL(nss_n2h_empty_pool_buf_register_sysctl);