blob: e09834a50944833f1849123f003d440c4a4936f9 [file] [log] [blame]
Abhishek Rastogi84d95d02014-03-26 19:31:31 +05301/*
2 **************************************************************************
Stephen Wangefd38512017-01-24 14:01:02 -08003 * Copyright (c) 2013-2017, 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"
Yu Huang8c107082017-07-24 14:58:26 -070023#include "nss_n2h_stats.h"
Abhishek Rastogi84d95d02014-03-26 19:31:31 +053024
Stephen Wang49b474b2016-03-25 10:40:30 -070025#define NSS_N2H_MAX_BUF_POOL_SIZE (1024 * 1024 * 8) /* 8MB */
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
ratheesh kannothab436af2017-07-20 08:51:07 +053029#define NSS_N2H_TX_TIMEOUT 3000 /* 3 Seconds */
Pamidipati, Vijayefcc4692014-05-09 14:47:38 +053030
Saurabh Misra71034db2015-06-04 16:18:38 -070031int nss_n2h_empty_pool_buf_cfg[NSS_MAX_CORES] __read_mostly = {-1, -1};
Sachin Shashidhar475012b2017-03-13 16:56:07 -070032int nss_n2h_empty_paged_pool_buf_cfg[NSS_MAX_CORES] __read_mostly = {-1, -1};
Saurabh Misra71034db2015-06-04 16:18:38 -070033int nss_n2h_water_mark[NSS_MAX_CORES][2] __read_mostly = {{-1, -1}, {-1, -1} };
Sachin Shashidhar475012b2017-03-13 16:56:07 -070034int nss_n2h_paged_water_mark[NSS_MAX_CORES][2] __read_mostly = {{-1, -1}, {-1, -1} };
Pamidipati, Vijayee9c2972016-01-10 08:13:19 +053035int nss_n2h_wifi_pool_buf_cfg __read_mostly = -1;
Stephen Wang49b474b2016-03-25 10:40:30 -070036int nss_n2h_rps_config __read_mostly;
37int nss_n2h_core0_mitigation_cfg __read_mostly = 1;
38int nss_n2h_core1_mitigation_cfg __read_mostly = 1;
39int nss_n2h_core0_add_buf_pool_size __read_mostly;
40int nss_n2h_core1_add_buf_pool_size __read_mostly;
Pamidipati, Vijayefcc4692014-05-09 14:47:38 +053041
Vijay Dewangan488e5372014-12-29 21:40:11 -080042struct nss_n2h_registered_data {
43 nss_n2h_msg_callback_t n2h_callback;
44 void *app_data;
45};
Pamidipati, Vijayefcc4692014-05-09 14:47:38 +053046
Vijay Dewangan488e5372014-12-29 21:40:11 -080047static struct nss_n2h_cfg_pvt nss_n2h_nepbcfgp[NSS_MAX_CORES];
48static struct nss_n2h_registered_data nss_n2h_rd[NSS_MAX_CORES];
Vijay Dewangan634ce592015-01-07 17:21:09 -080049static struct nss_n2h_cfg_pvt nss_n2h_rcp;
Kalyan Tallapragadab50e8902015-08-06 17:00:54 +053050static struct nss_n2h_cfg_pvt nss_n2h_mitigationcp[NSS_CORE_MAX];
51static struct nss_n2h_cfg_pvt nss_n2h_bufcp[NSS_CORE_MAX];
Pamidipati, Vijayee9c2972016-01-10 08:13:19 +053052static struct nss_n2h_cfg_pvt nss_n2h_wp;
ratheesh kannothab436af2017-07-20 08:51:07 +053053static struct nss_n2h_cfg_pvt nss_n2h_q_cfg_pvt;
Pamidipati, Vijayefcc4692014-05-09 14:47:38 +053054
55/*
Sundarajan Srinivasanf1e57462014-09-17 15:24:01 -070056 * nss_n2h_interface_handler()
Abhishek Rastogi84d95d02014-03-26 19:31:31 +053057 * Handle NSS -> HLOS messages for N2H node
58 */
Vijay Dewangan634ce592015-01-07 17:21:09 -080059static void nss_n2h_interface_handler(struct nss_ctx_instance *nss_ctx,
60 struct nss_cmn_msg *ncm,
Arunkumar Tba9b4a02016-11-07 11:41:14 +053061 void *app_data)
Abhishek Rastogi84d95d02014-03-26 19:31:31 +053062{
63 struct nss_n2h_msg *nnm = (struct nss_n2h_msg *)ncm;
Vijay Dewangan488e5372014-12-29 21:40:11 -080064 nss_n2h_msg_callback_t cb;
Abhishek Rastogi84d95d02014-03-26 19:31:31 +053065
Sundarajan Srinivasanf1e57462014-09-17 15:24:01 -070066 BUG_ON(ncm->interface != NSS_N2H_INTERFACE);
67
Abhishek Rastogi84d95d02014-03-26 19:31:31 +053068 /*
69 * Is this a valid request/response packet?
70 */
71 if (nnm->cm.type >= NSS_METADATA_TYPE_N2H_MAX) {
72 nss_warning("%p: received invalid message %d for Offload stats interface", nss_ctx, nnm->cm.type);
73 return;
74 }
75
76 switch (nnm->cm.type) {
Pamidipati, Vijayefcc4692014-05-09 14:47:38 +053077 case NSS_TX_METADATA_TYPE_N2H_RPS_CFG:
Pamidipati, Vijayefcc4692014-05-09 14:47:38 +053078 nss_info("NSS N2H rps_en %d \n",nnm->msg.rps_cfg.enable);
Vijay Dewangan488e5372014-12-29 21:40:11 -080079 break;
80
Kalyan Tallapragadab50e8902015-08-06 17:00:54 +053081 case NSS_TX_METADATA_TYPE_N2H_MITIGATION_CFG:
82 nss_info("NSS N2H mitigation_dis %d \n",nnm->msg.mitigation_cfg.enable);
83 break;
84
Vijay Dewangan488e5372014-12-29 21:40:11 -080085 case NSS_TX_METADATA_TYPE_N2H_EMPTY_POOL_BUF_CFG:
86 nss_info("%p: empty pool buf cfg response from FW", nss_ctx);
Pamidipati, Vijayefcc4692014-05-09 14:47:38 +053087 break;
88
Radha krishna Simha Jiguru7f424d52015-02-10 19:41:01 +053089 case NSS_TX_METADATA_TYPE_N2H_FLUSH_PAYLOADS:
90 nss_info("%p: flush payloads cmd response from FW", nss_ctx);
91 break;
92
Abhishek Rastogi84d95d02014-03-26 19:31:31 +053093 case NSS_RX_METADATA_TYPE_N2H_STATS_SYNC:
Sundarajan Srinivasanf1e57462014-09-17 15:24:01 -070094 nss_n2h_stats_sync(nss_ctx, &nnm->msg.stats_sync);
Abhishek Rastogi84d95d02014-03-26 19:31:31 +053095 break;
96
97 default:
98 if (ncm->response != NSS_CMN_RESPONSE_ACK) {
99 /*
100 * Check response
101 */
102 nss_info("%p: Received response %d for type %d, interface %d",
103 nss_ctx, ncm->response, ncm->type, ncm->interface);
104 }
105 }
Vijay Dewangan488e5372014-12-29 21:40:11 -0800106
107 /*
Stephen Wang49b474b2016-03-25 10:40:30 -0700108 * Update the callback and app_data for NOTIFY messages, n2h sends all notify messages
Vijay Dewangan488e5372014-12-29 21:40:11 -0800109 * to the same callback/app_data.
110 */
111 if (nnm->cm.response == NSS_CMM_RESPONSE_NOTIFY) {
112 /*
113 * Place holder for the user to create right call
114 * back and app data when response is NSS_CMM_RESPONSE_NOTIFY
115 */
Stephen Wangaed46332016-12-12 17:29:03 -0800116 ncm->cb = (nss_ptr_t)nss_n2h_rd[nss_ctx->id].n2h_callback;
117 ncm->app_data = (nss_ptr_t)nss_n2h_rd[nss_ctx->id].app_data;
Vijay Dewangan488e5372014-12-29 21:40:11 -0800118 }
119
120 /*
121 * Do we have a callback?
122 */
123 if (!ncm->cb) {
124 return;
125 }
126
127 /*
128 * Callback
129 */
130 cb = (nss_n2h_msg_callback_t)ncm->cb;
131 cb((void *)ncm->app_data, nnm);
132}
133
134/*
Vijay Dewangan634ce592015-01-07 17:21:09 -0800135 * nss_n2h_rps_cfg_callback()
136 * call back function for rps configuration
137 */
138static void nss_n2h_rps_cfg_callback(void *app_data, struct nss_n2h_msg *nnm)
139{
140 struct nss_ctx_instance *nss_ctx = (struct nss_ctx_instance *)app_data;
141 if (nnm->cm.response != NSS_CMN_RESPONSE_ACK) {
142
143 /*
144 * Error, hence we are not updating the nss_n2h_empty_pool_buf
145 * Restore the current_value to its previous state
146 */
147 nss_n2h_rcp.response = NSS_FAILURE;
148 complete(&nss_n2h_rcp.complete);
149 nss_warning("%p: RPS configuration failed : %d\n", nss_ctx,
150 nnm->cm.error);
151 return;
152 }
153
154 nss_info("%p: RPS configuration succeeded: %d\n", nss_ctx,
155 nnm->cm.error);
156 nss_ctx->n2h_rps_en = nnm->msg.rps_cfg.enable;
157 nss_n2h_rcp.response = NSS_SUCCESS;
158 complete(&nss_n2h_rcp.complete);
159}
160
161/*
Kalyan Tallapragadab50e8902015-08-06 17:00:54 +0530162 * nss_n2h_mitigation_cfg_callback()
163 * call back function for mitigation configuration
164 */
165static void nss_n2h_mitigation_cfg_callback(void *app_data, struct nss_n2h_msg *nnm)
166{
Stephen Wangaed46332016-12-12 17:29:03 -0800167 uint32_t core_num = (uint32_t)(nss_ptr_t)app_data;
Kalyan Tallapragadab50e8902015-08-06 17:00:54 +0530168 struct nss_top_instance *nss_top = &nss_top_main;
169 struct nss_ctx_instance *nss_ctx = &nss_top->nss[core_num];
170
171 if (nnm->cm.response != NSS_CMN_RESPONSE_ACK) {
172
173 /*
174 * Error, hence we are not updating the nss_n2h_mitigate_en
175 */
176 nss_n2h_mitigationcp[core_num].response = NSS_FAILURE;
177 complete(&nss_n2h_mitigationcp[core_num].complete);
178 nss_warning("core%d: MITIGATION configuration failed : %d\n", core_num, nnm->cm.error);
179 return;
180 }
181
182 nss_info("core%d: MITIGATION configuration succeeded: %d\n", core_num, nnm->cm.error);
183
184 nss_ctx->n2h_mitigate_en = nnm->msg.mitigation_cfg.enable;
185 nss_n2h_mitigationcp[core_num].response = NSS_SUCCESS;
186 complete(&nss_n2h_mitigationcp[core_num].complete);
187}
188
189/*
190 * nss_n2h_buf_cfg_callback()
191 * call back function for pbuf configuration
192 */
193static void nss_n2h_bufs_cfg_callback(void *app_data, struct nss_n2h_msg *nnm)
194{
Stephen Wangaed46332016-12-12 17:29:03 -0800195 uint32_t core_num = (uint32_t)(nss_ptr_t)app_data;
Kalyan Tallapragadab50e8902015-08-06 17:00:54 +0530196 unsigned int allocated_sz;
197
198 struct nss_top_instance *nss_top = &nss_top_main;
199 struct nss_ctx_instance *nss_ctx = &nss_top->nss[core_num];
200
201 if (nnm->cm.response != NSS_CMN_RESPONSE_ACK) {
202 nss_n2h_bufcp[core_num].response = NSS_FAILURE;
203 nss_warning("core%d: buf configuration failed : %d\n", core_num, nnm->cm.error);
204 goto done;
205 }
206
207 nss_info("core%d: buf configuration succeeded: %d\n", core_num, nnm->cm.error);
208
209 allocated_sz = nnm->msg.buf_pool.nss_buf_page_size * nnm->msg.buf_pool.nss_buf_num_pages;
210 nss_ctx->buf_sz_allocated += allocated_sz;
211
212 nss_n2h_bufcp[core_num].response = NSS_SUCCESS;
213
214done:
215 complete(&nss_n2h_bufcp[core_num].complete);
216}
217
218/*
Saurabh Misra71034db2015-06-04 16:18:38 -0700219 * nss_n2h_payload_stats_callback()
220 * It gets called response to payload accounting.
Vijay Dewangan488e5372014-12-29 21:40:11 -0800221 */
Saurabh Misra71034db2015-06-04 16:18:38 -0700222static void nss_n2h_payload_stats_callback(void *app_data,
223 struct nss_n2h_msg *nnm)
Vijay Dewangan488e5372014-12-29 21:40:11 -0800224{
Stephen Wangaed46332016-12-12 17:29:03 -0800225 uint32_t core_num = (uint32_t)(nss_ptr_t)app_data;
Saurabh Misra71034db2015-06-04 16:18:38 -0700226
Vijay Dewangan488e5372014-12-29 21:40:11 -0800227 if (nnm->cm.response != NSS_CMN_RESPONSE_ACK) {
228 struct nss_n2h_empty_pool_buf *nnepbcm;
229 nnepbcm = &nnm->msg.empty_pool_buf_cfg;
230
Saurabh Misra71034db2015-06-04 16:18:38 -0700231 nss_warning("%d: core empty pool buf set failure: %d\n",
232 core_num, nnm->cm.error);
Vijay Dewangan488e5372014-12-29 21:40:11 -0800233 nss_n2h_nepbcfgp[core_num].response = NSS_FAILURE;
234 complete(&nss_n2h_nepbcfgp[core_num].complete);
235 return;
236 }
237
Sachin Shashidhar475012b2017-03-13 16:56:07 -0700238 if (nnm->cm.type == NSS_TX_METADATA_TYPE_GET_WATER_MARK) {
239 nss_n2h_nepbcfgp[core_num].empty_buf_pool_info.pool_size =
Saurabh Misra71034db2015-06-04 16:18:38 -0700240 ntohl(nnm->msg.payload_info.pool_size);
Sachin Shashidhar475012b2017-03-13 16:56:07 -0700241 nss_n2h_nepbcfgp[core_num].empty_buf_pool_info.low_water =
Saurabh Misra71034db2015-06-04 16:18:38 -0700242 ntohl(nnm->msg.payload_info.low_water);
Sachin Shashidhar475012b2017-03-13 16:56:07 -0700243 nss_n2h_nepbcfgp[core_num].empty_buf_pool_info.high_water =
Saurabh Misra71034db2015-06-04 16:18:38 -0700244 ntohl(nnm->msg.payload_info.high_water);
245 }
246
Sachin Shashidhar475012b2017-03-13 16:56:07 -0700247 if (nnm->cm.type == NSS_TX_METADATA_TYPE_GET_PAGED_WATER_MARK) {
248 nss_n2h_nepbcfgp[core_num].empty_paged_buf_pool_info.pool_size =
249 ntohl(nnm->msg.paged_payload_info.pool_size);
250 nss_n2h_nepbcfgp[core_num].empty_paged_buf_pool_info.low_water =
251 ntohl(nnm->msg.paged_payload_info.low_water);
252 nss_n2h_nepbcfgp[core_num].empty_paged_buf_pool_info.high_water =
253 ntohl(nnm->msg.paged_payload_info.high_water);
254 }
255
Vijay Dewangan488e5372014-12-29 21:40:11 -0800256 nss_n2h_nepbcfgp[core_num].response = NSS_SUCCESS;
257 complete(&nss_n2h_nepbcfgp[core_num].complete);
258}
259
260/*
Pamidipati, Vijayee9c2972016-01-10 08:13:19 +0530261 * nss_n2h_set_wifi_payloads_callback()
262 * call back function for response to wifi pool configuration
263 *
264 */
265static void nss_n2h_set_wifi_payloads_callback(void *app_data,
266 struct nss_n2h_msg *nnm)
267{
Arunkumar Tba9b4a02016-11-07 11:41:14 +0530268 struct nss_ctx_instance *nss_ctx __maybe_unused = (struct nss_ctx_instance *)app_data;
Pamidipati, Vijayee9c2972016-01-10 08:13:19 +0530269 if (nnm->cm.response != NSS_CMN_RESPONSE_ACK) {
270
271 nss_n2h_wp.response = NSS_FAILURE;
272 complete(&nss_n2h_wp.complete);
273 nss_warning("%p: wifi pool configuration failed : %d\n", nss_ctx,
274 nnm->cm.error);
275 return;
276 }
277
278 nss_info("%p: wifi payload configuration succeeded: %d\n", nss_ctx,
279 nnm->cm.error);
280 nss_n2h_wp.response = NSS_SUCCESS;
281 complete(&nss_n2h_wp.complete);
282}
283
284/*
Saurabh Misra71034db2015-06-04 16:18:38 -0700285 * nss_n2h_get_payload_info()
Sachin Shashidhar475012b2017-03-13 16:56:07 -0700286 * Gets Payload information.
Vijay Dewangan488e5372014-12-29 21:40:11 -0800287 */
Sachin Shashidhar475012b2017-03-13 16:56:07 -0700288static int nss_n2h_get_payload_info(nss_ptr_t core_num, struct nss_n2h_msg *nnm, struct nss_n2h_payload_info *nnepbcm)
Saurabh Misra71034db2015-06-04 16:18:38 -0700289{
290 struct nss_top_instance *nss_top = &nss_top_main;
291 struct nss_ctx_instance *nss_ctx = &nss_top->nss[core_num];
Saurabh Misra71034db2015-06-04 16:18:38 -0700292 nss_tx_status_t nss_tx_status;
293 int ret = NSS_FAILURE;
294
295 /*
296 * Note that semaphore should be already held.
297 */
298
Sachin Shashidhar475012b2017-03-13 16:56:07 -0700299 nss_tx_status = nss_n2h_tx_msg(nss_ctx, nnm);
Saurabh Misra71034db2015-06-04 16:18:38 -0700300
301 if (nss_tx_status != NSS_TX_SUCCESS) {
Stephen Wangaed46332016-12-12 17:29:03 -0800302 nss_warning("%p: core %d nss_tx error errorn", nss_ctx, (int)core_num);
Saurabh Misra71034db2015-06-04 16:18:38 -0700303 return NSS_FAILURE;
304 }
305
306 /*
307 * Blocking call, wait till we get ACK for this msg.
308 */
309 ret = wait_for_completion_timeout(&nss_n2h_nepbcfgp[core_num].complete,
310 msecs_to_jiffies(NSS_CONN_CFG_TIMEOUT));
311 if (ret == 0) {
Stephen Wangaed46332016-12-12 17:29:03 -0800312 nss_warning("%p: core %d waiting for ack timed out\n", nss_ctx, (int)core_num);
Saurabh Misra71034db2015-06-04 16:18:38 -0700313 return NSS_FAILURE;
314 }
315
316 if (NSS_FAILURE == nss_n2h_nepbcfgp[core_num].response) {
Stephen Wangaed46332016-12-12 17:29:03 -0800317 nss_warning("%p: core %d response returned failure\n", nss_ctx, (int)core_num);
Saurabh Misra71034db2015-06-04 16:18:38 -0700318 return NSS_FAILURE;
319 }
320
321 return NSS_SUCCESS;
322}
323
324/*
Sachin Shashidhar475012b2017-03-13 16:56:07 -0700325 * nss_n2h_get_default_payload_info()
326 * Gets the default payload information.
327 */
328static int nss_n2h_get_default_payload_info(nss_ptr_t core_num)
329{
330 struct nss_n2h_msg nnm;
331
332 nss_n2h_msg_init(&nnm, NSS_N2H_INTERFACE,
333 NSS_TX_METADATA_TYPE_GET_WATER_MARK,
334 sizeof(struct nss_n2h_payload_info),
335 nss_n2h_payload_stats_callback,
336 (void *)core_num);
337
338 return nss_n2h_get_payload_info(core_num, &nnm,
339 &nnm.msg.payload_info);
340}
341
342/*
343 * nss_n2h_get_paged_payload_info()
344 * Gets the paged payload information.
345 */
346static int nss_n2h_get_paged_payload_info(nss_ptr_t core_num)
347{
348 struct nss_n2h_msg nnm;
349
350 nss_n2h_msg_init(&nnm, NSS_N2H_INTERFACE,
351 NSS_TX_METADATA_TYPE_GET_PAGED_WATER_MARK,
352 sizeof(struct nss_n2h_payload_info),
353 nss_n2h_payload_stats_callback,
354 (void *)core_num);
355
356 return nss_n2h_get_payload_info(core_num, &nnm,
357 &nnm.msg.paged_payload_info);
358}
359
360/*
Saurabh Misra71034db2015-06-04 16:18:38 -0700361 * nss_n2h_set_empty_pool_buf()
362 * Sets empty pool buffer
363 */
Stephen Wang52e6d342016-03-29 15:02:33 -0700364static int nss_n2h_set_empty_pool_buf(struct ctl_table *ctl, int write,
Saurabh Misra71034db2015-06-04 16:18:38 -0700365 void __user *buffer,
366 size_t *lenp, loff_t *ppos,
Stephen Wangaed46332016-12-12 17:29:03 -0800367 nss_ptr_t core_num, int *new_val)
Vijay Dewangan488e5372014-12-29 21:40:11 -0800368{
369 struct nss_top_instance *nss_top = &nss_top_main;
370 struct nss_ctx_instance *nss_ctx = &nss_top->nss[core_num];
371 struct nss_n2h_msg nnm;
372 struct nss_n2h_empty_pool_buf *nnepbcm;
373 nss_tx_status_t nss_tx_status;
374 int ret = NSS_FAILURE;
375
376 /*
377 * Acquiring semaphore
378 */
379 down(&nss_n2h_nepbcfgp[core_num].sem);
380
381 /*
382 * Take snap shot of current value
383 */
Sachin Shashidhar475012b2017-03-13 16:56:07 -0700384 nss_n2h_nepbcfgp[core_num].empty_buf_pool_info.pool_size = *new_val;
Vijay Dewangan488e5372014-12-29 21:40:11 -0800385
Saurabh Misra71034db2015-06-04 16:18:38 -0700386 if (!write) {
Sachin Shashidhar475012b2017-03-13 16:56:07 -0700387 ret = nss_n2h_get_default_payload_info(core_num);
388 *new_val = nss_n2h_nepbcfgp[core_num].empty_buf_pool_info.pool_size;
Saurabh Misra71034db2015-06-04 16:18:38 -0700389 if (ret == NSS_FAILURE) {
390 up(&nss_n2h_nepbcfgp[core_num].sem);
391 return -EBUSY;
392 }
393
394 up(&nss_n2h_nepbcfgp[core_num].sem);
395
396 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
397 return ret;
398 }
399
Vijay Dewangan488e5372014-12-29 21:40:11 -0800400 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
Saurabh Misra71034db2015-06-04 16:18:38 -0700401 if (ret) {
Vijay Dewangan488e5372014-12-29 21:40:11 -0800402 up(&nss_n2h_nepbcfgp[core_num].sem);
403 return ret;
404 }
405
Vijay Dewangan488e5372014-12-29 21:40:11 -0800406 if ((*new_val < NSS_N2H_MIN_EMPTY_POOL_BUF_SZ)) {
Saurabh Misra71034db2015-06-04 16:18:38 -0700407 nss_warning("%p: core %d setting %d < min number of buffer",
Stephen Wangaed46332016-12-12 17:29:03 -0800408 nss_ctx, (int)core_num, *new_val);
Stephen Wang06761022015-03-03 16:38:42 -0800409 goto failure;
Vijay Dewangan488e5372014-12-29 21:40:11 -0800410 }
411
412 nss_info("%p: core %d number of empty pool buffer is : %d\n",
Stephen Wangaed46332016-12-12 17:29:03 -0800413 nss_ctx, (int)core_num, *new_val);
Vijay Dewangan488e5372014-12-29 21:40:11 -0800414
415 nss_n2h_msg_init(&nnm, NSS_N2H_INTERFACE,
416 NSS_TX_METADATA_TYPE_N2H_EMPTY_POOL_BUF_CFG,
417 sizeof(struct nss_n2h_empty_pool_buf),
Saurabh Misra71034db2015-06-04 16:18:38 -0700418 nss_n2h_payload_stats_callback,
Stephen Wangaed46332016-12-12 17:29:03 -0800419 (nss_ptr_t *)core_num);
Vijay Dewangan488e5372014-12-29 21:40:11 -0800420
421 nnepbcm = &nnm.msg.empty_pool_buf_cfg;
422 nnepbcm->pool_size = htonl(*new_val);
423 nss_tx_status = nss_n2h_tx_msg(nss_ctx, &nnm);
424
425 if (nss_tx_status != NSS_TX_SUCCESS) {
Saurabh Misra71034db2015-06-04 16:18:38 -0700426 nss_warning("%p: core %d nss_tx error empty pool buffer: %d\n",
Stephen Wangaed46332016-12-12 17:29:03 -0800427 nss_ctx, (int)core_num, *new_val);
Stephen Wang06761022015-03-03 16:38:42 -0800428 goto failure;
Vijay Dewangan488e5372014-12-29 21:40:11 -0800429 }
430
431 /*
432 * Blocking call, wait till we get ACK for this msg.
433 */
Saurabh Misra71034db2015-06-04 16:18:38 -0700434 ret = wait_for_completion_timeout(&nss_n2h_nepbcfgp[core_num].complete,
435 msecs_to_jiffies(NSS_CONN_CFG_TIMEOUT));
Vijay Dewangan488e5372014-12-29 21:40:11 -0800436 if (ret == 0) {
Stephen Wangaed46332016-12-12 17:29:03 -0800437 nss_warning("%p: core %d Waiting for ack timed out\n", nss_ctx, (int)core_num);
Stephen Wang06761022015-03-03 16:38:42 -0800438 goto failure;
Vijay Dewangan488e5372014-12-29 21:40:11 -0800439 }
440
441 /*
442 * ACK/NACK received from NSS FW
443 * If ACK: Callback function will update nss_n2h_empty_pool_buf with
444 * nss_n2h_nepbcfgp.num_conn_valid, which holds the user input
445 */
446 if (NSS_FAILURE == nss_n2h_nepbcfgp[core_num].response) {
Stephen Wang06761022015-03-03 16:38:42 -0800447 goto failure;
Vijay Dewangan488e5372014-12-29 21:40:11 -0800448 }
449
450 up(&nss_n2h_nepbcfgp[core_num].sem);
Thomas Wu651b3902015-05-12 11:21:09 -0700451 return 0;
Stephen Wang06761022015-03-03 16:38:42 -0800452
453failure:
454 /*
455 * Restore the current_value to its previous state
456 */
Sachin Shashidhar475012b2017-03-13 16:56:07 -0700457 *new_val = nss_n2h_nepbcfgp[core_num].empty_buf_pool_info.pool_size;
458 up(&nss_n2h_nepbcfgp[core_num].sem);
459 return NSS_FAILURE;
460}
461
462/*
463 * nss_n2h_set_empty_paged_pool_buf()
464 * Sets empty paged pool buffer
465 */
466static int nss_n2h_set_empty_paged_pool_buf(struct ctl_table *ctl, int write,
467 void __user *buffer,
468 size_t *lenp, loff_t *ppos,
469 nss_ptr_t core_num, int *new_val)
470{
471 struct nss_top_instance *nss_top = &nss_top_main;
472 struct nss_ctx_instance *nss_ctx = &nss_top->nss[core_num];
473 struct nss_n2h_msg nnm;
474 struct nss_n2h_empty_pool_buf *nneppbcm;
475 nss_tx_status_t nss_tx_status;
476 int ret = NSS_FAILURE;
477
478 /*
479 * Acquiring semaphore
480 */
481 down(&nss_n2h_nepbcfgp[core_num].sem);
482
483 /*
484 * Take snap shot of current value
485 */
486 nss_n2h_nepbcfgp[core_num].empty_paged_buf_pool_info.pool_size = *new_val;
487
488 if (!write) {
489 ret = nss_n2h_get_paged_payload_info(core_num);
490 *new_val = nss_n2h_nepbcfgp[core_num].empty_paged_buf_pool_info.pool_size;
491 if (ret == NSS_FAILURE) {
492 up(&nss_n2h_nepbcfgp[core_num].sem);
493 return -EBUSY;
494 }
495
496 up(&nss_n2h_nepbcfgp[core_num].sem);
497
498 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
499 return ret;
500 }
501
502 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
503 if (ret) {
504 up(&nss_n2h_nepbcfgp[core_num].sem);
505 return ret;
506 }
507
508 if ((*new_val < NSS_N2H_MIN_EMPTY_POOL_BUF_SZ)) {
509 nss_warning("%p: core %d setting %d < min number of buffer",
510 nss_ctx, (int)core_num, *new_val);
511 goto failure;
512 }
513
514 nss_info("%p: core %d number of empty paged pool buffer is : %d\n",
515 nss_ctx, (int)core_num, *new_val);
516
517 nss_n2h_msg_init(&nnm, NSS_N2H_INTERFACE,
518 NSS_TX_METADATA_TYPE_N2H_EMPTY_PAGED_POOL_BUF_CFG,
519 sizeof(struct nss_n2h_empty_pool_buf),
520 nss_n2h_payload_stats_callback,
521 (nss_ptr_t *)core_num);
522
523 nneppbcm = &nnm.msg.empty_pool_buf_cfg;
524 nneppbcm->pool_size = htonl(*new_val);
525 nss_tx_status = nss_n2h_tx_msg(nss_ctx, &nnm);
526
527 if (nss_tx_status != NSS_TX_SUCCESS) {
528 nss_warning("%p: core %d nss_tx error empty paged pool buffer: %d\n",
529 nss_ctx, (int)core_num, *new_val);
530 goto failure;
531 }
532
533 /*
534 * Blocking call, wait till we get ACK for this msg.
535 */
536 ret = wait_for_completion_timeout(&nss_n2h_nepbcfgp[core_num].complete,
537 msecs_to_jiffies(NSS_CONN_CFG_TIMEOUT));
538 if (ret == 0) {
539 nss_warning("%p: core %d Waiting for ack timed out\n", nss_ctx, (int)core_num);
540 goto failure;
541 }
542
543 /*
544 * ACK/NACK received from NSS FW
545 * If ACK: Callback function will update nss_n2h_empty_pool_buf with
546 * nss_n2h_nepbcfgp.num_conn_valid, which holds the user input
547 */
548 if (NSS_FAILURE == nss_n2h_nepbcfgp[core_num].response) {
549 goto failure;
550 }
551
552 up(&nss_n2h_nepbcfgp[core_num].sem);
553 return 0;
554
555failure:
556 /*
557 * Restore the current_value to its previous state
558 */
559 *new_val = nss_n2h_nepbcfgp[core_num].empty_paged_buf_pool_info.pool_size;
Saurabh Misra71034db2015-06-04 16:18:38 -0700560 up(&nss_n2h_nepbcfgp[core_num].sem);
561 return NSS_FAILURE;
562}
563
564/*
565 * nss_n2h_set_water_mark()
566 * Sets water mark for N2H SOS
567 */
Stephen Wang52e6d342016-03-29 15:02:33 -0700568static int nss_n2h_set_water_mark(struct ctl_table *ctl, int write,
Saurabh Misra71034db2015-06-04 16:18:38 -0700569 void __user *buffer,
570 size_t *lenp, loff_t *ppos,
Stephen Wangaed46332016-12-12 17:29:03 -0800571 uint32_t core_num, int *low, int *high)
Saurabh Misra71034db2015-06-04 16:18:38 -0700572{
573 struct nss_top_instance *nss_top = &nss_top_main;
574 struct nss_ctx_instance *nss_ctx = &nss_top->nss[core_num];
575 struct nss_n2h_msg nnm;
576 struct nss_n2h_water_mark *wm;
577 nss_tx_status_t nss_tx_status;
578 int ret = NSS_FAILURE;
579
580 /*
581 * Acquiring semaphore
582 */
583 down(&nss_n2h_nepbcfgp[core_num].sem);
584
585 /*
586 * Take snap shot of current value
587 */
Sachin Shashidhar475012b2017-03-13 16:56:07 -0700588 nss_n2h_nepbcfgp[core_num].empty_buf_pool_info.low_water = *low;
589 nss_n2h_nepbcfgp[core_num].empty_buf_pool_info.high_water = *high;
Saurabh Misra71034db2015-06-04 16:18:38 -0700590
Sachin Shashidhar475012b2017-03-13 16:56:07 -0700591 if (!write || *low == -1 || *high == -1) {
592 ret = nss_n2h_get_default_payload_info(core_num);
Saurabh Misra71034db2015-06-04 16:18:38 -0700593 if (ret == NSS_FAILURE) {
594 up(&nss_n2h_nepbcfgp[core_num].sem);
595 return -EBUSY;
596 }
597
Sachin Shashidhar475012b2017-03-13 16:56:07 -0700598 *low = nss_n2h_nepbcfgp[core_num].empty_buf_pool_info.low_water;
599 *high = nss_n2h_nepbcfgp[core_num].empty_buf_pool_info.high_water;
Saurabh Misra71034db2015-06-04 16:18:38 -0700600 }
601
602 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
Sachin Shashidhar475012b2017-03-13 16:56:07 -0700603 if (!write || ret) {
Saurabh Misra71034db2015-06-04 16:18:38 -0700604 up(&nss_n2h_nepbcfgp[core_num].sem);
605 return ret;
606 }
607
Saurabh Misra71034db2015-06-04 16:18:38 -0700608 if ((*low < NSS_N2H_MIN_EMPTY_POOL_BUF_SZ) ||
609 (*high < NSS_N2H_MIN_EMPTY_POOL_BUF_SZ)) {
610 nss_warning("%p: core %d setting %d, %d < min number of buffer",
611 nss_ctx, core_num, *low, *high);
612 goto failure;
613 }
614
Pamidipati, Vijayee9c2972016-01-10 08:13:19 +0530615 if ((*low > NSS_N2H_MAX_EMPTY_POOL_BUF_SZ) ||
616 (*high > NSS_N2H_MAX_EMPTY_POOL_BUF_SZ)) {
Saurabh Misra71034db2015-06-04 16:18:38 -0700617 nss_warning("%p: core %d setting %d, %d is > upper limit",
618 nss_ctx, core_num, *low, *high);
619 goto failure;
620 }
621
622 if (*low > *high) {
623 nss_warning("%p: core %d setting low %d is more than high %d",
624 nss_ctx, core_num, *low, *high);
625 goto failure;
626 }
627
628 nss_info("%p: core %d number of low : %d and high : %d\n",
629 nss_ctx, core_num, *low, *high);
630
631 nss_n2h_msg_init(&nnm, NSS_N2H_INTERFACE,
632 NSS_TX_METADATA_TYPE_SET_WATER_MARK,
633 sizeof(struct nss_n2h_water_mark),
634 nss_n2h_payload_stats_callback,
Stephen Wangaed46332016-12-12 17:29:03 -0800635 (void *)(nss_ptr_t)core_num);
Saurabh Misra71034db2015-06-04 16:18:38 -0700636
637 wm = &nnm.msg.wm;
638 wm->low_water = htonl(*low);
639 wm->high_water = htonl(*high);
640 nss_tx_status = nss_n2h_tx_msg(nss_ctx, &nnm);
641
642 if (nss_tx_status != NSS_TX_SUCCESS) {
643 nss_warning("%p: core %d nss_tx error setting : %d, %d\n",
644 nss_ctx, core_num, *low, *high);
645 goto failure;
646 }
647
648 /*
649 * Blocking call, wait till we get ACK for this msg.
650 */
651 ret = wait_for_completion_timeout(&nss_n2h_nepbcfgp[core_num].complete,
652 msecs_to_jiffies(NSS_CONN_CFG_TIMEOUT));
653 if (ret == 0) {
654 nss_warning("%p: core %d Waiting for ack timed out\n", nss_ctx,
655 core_num);
656 goto failure;
657 }
658
659 /*
660 * ACK/NACK received from NSS FW
661 */
662 if (NSS_FAILURE == nss_n2h_nepbcfgp[core_num].response)
663 goto failure;
664
665 up(&nss_n2h_nepbcfgp[core_num].sem);
666 return NSS_SUCCESS;
667
668failure:
669 /*
670 * Restore the current_value to its previous state
671 */
Sachin Shashidhar475012b2017-03-13 16:56:07 -0700672 *low = nss_n2h_nepbcfgp[core_num].empty_buf_pool_info.low_water;
673 *high = nss_n2h_nepbcfgp[core_num].empty_buf_pool_info.high_water;
674 up(&nss_n2h_nepbcfgp[core_num].sem);
675 return -EINVAL;
676}
677
678/*
679 * nss_n2h_set_paged_water_mark()
680 * Sets water mark for paged pool N2H SOS
681 */
682static int nss_n2h_set_paged_water_mark(struct ctl_table *ctl, int write,
683 void __user *buffer,
684 size_t *lenp, loff_t *ppos,
685 uint32_t core_num, int *low, int *high)
686{
687 struct nss_top_instance *nss_top = &nss_top_main;
688 struct nss_ctx_instance *nss_ctx = &nss_top->nss[core_num];
689 struct nss_n2h_msg nnm;
690 struct nss_n2h_water_mark *pwm;
691 nss_tx_status_t nss_tx_status;
692 int ret = NSS_FAILURE;
693
694 /*
695 * Acquiring semaphore
696 */
697 down(&nss_n2h_nepbcfgp[core_num].sem);
698
699 /*
700 * Take snap shot of current value
701 */
702 nss_n2h_nepbcfgp[core_num].empty_paged_buf_pool_info.low_water = *low;
703 nss_n2h_nepbcfgp[core_num].empty_paged_buf_pool_info.high_water = *high;
704
705 if (!write || *low == -1 || *high == -1) {
706 ret = nss_n2h_get_paged_payload_info(core_num);
707 if (ret == NSS_FAILURE) {
708 up(&nss_n2h_nepbcfgp[core_num].sem);
709 return -EBUSY;
710 }
711
712 *low = nss_n2h_nepbcfgp[core_num].empty_paged_buf_pool_info.low_water;
713 *high = nss_n2h_nepbcfgp[core_num].empty_paged_buf_pool_info.high_water;
714 }
715
716 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
717 if (!write || ret) {
718 up(&nss_n2h_nepbcfgp[core_num].sem);
719 return ret;
720 }
721
722 if ((*low < NSS_N2H_MIN_EMPTY_POOL_BUF_SZ) ||
723 (*high < NSS_N2H_MIN_EMPTY_POOL_BUF_SZ)) {
724 nss_warning("%p: core %d setting %d, %d < min number of buffer",
725 nss_ctx, core_num, *low, *high);
726 goto failure;
727 }
728
729 if ((*low > NSS_N2H_MAX_EMPTY_POOL_BUF_SZ) ||
730 (*high > NSS_N2H_MAX_EMPTY_POOL_BUF_SZ)) {
731 nss_warning("%p: core %d setting %d, %d is > upper limit",
732 nss_ctx, core_num, *low, *high);
733 goto failure;
734 }
735
736 if (*low > *high) {
737 nss_warning("%p: core %d setting low %d is more than high %d",
738 nss_ctx, core_num, *low, *high);
739 goto failure;
740 }
741
742 nss_info("%p: core %d number of low : %d and high : %d\n",
743 nss_ctx, core_num, *low, *high);
744
745 nss_n2h_msg_init(&nnm, NSS_N2H_INTERFACE,
746 NSS_TX_METADATA_TYPE_SET_PAGED_WATER_MARK,
747 sizeof(struct nss_n2h_water_mark),
748 nss_n2h_payload_stats_callback,
749 (void *)(nss_ptr_t)core_num);
750
751 pwm = &nnm.msg.wm_paged;
752 pwm->low_water = htonl(*low);
753 pwm->high_water = htonl(*high);
754 nss_tx_status = nss_n2h_tx_msg(nss_ctx, &nnm);
755
756 if (nss_tx_status != NSS_TX_SUCCESS) {
757 nss_warning("%p: core %d nss_tx error setting : %d, %d\n",
758 nss_ctx, core_num, *low, *high);
759 goto failure;
760 }
761
762 /*
763 * Blocking call, wait till we get ACK for this msg.
764 */
765 ret = wait_for_completion_timeout(&nss_n2h_nepbcfgp[core_num].complete,
766 msecs_to_jiffies(NSS_CONN_CFG_TIMEOUT));
767 if (ret == 0) {
768 nss_warning("%p: core %d Waiting for ack timed out\n", nss_ctx,
769 core_num);
770 goto failure;
771 }
772
773 /*
774 * ACK/NACK received from NSS FW
775 */
776 if (NSS_FAILURE == nss_n2h_nepbcfgp[core_num].response)
777 goto failure;
778
779 up(&nss_n2h_nepbcfgp[core_num].sem);
780 return NSS_SUCCESS;
781
782failure:
783 /*
784 * Restore the current_value to its previous state
785 */
786 *low = nss_n2h_nepbcfgp[core_num].empty_paged_buf_pool_info.low_water;
787 *high = nss_n2h_nepbcfgp[core_num].empty_paged_buf_pool_info.high_water;
Stephen Wang06761022015-03-03 16:38:42 -0800788 up(&nss_n2h_nepbcfgp[core_num].sem);
Thomas Wu651b3902015-05-12 11:21:09 -0700789 return -EINVAL;
Vijay Dewangan488e5372014-12-29 21:40:11 -0800790}
791
792/*
Pamidipati, Vijayee9c2972016-01-10 08:13:19 +0530793 * nss_n2h_cfg_wifi_pool()
794 * Sets number of wifi payloads to adjust high water mark for N2H SoS
795 */
Stephen Wang52e6d342016-03-29 15:02:33 -0700796static int nss_n2h_cfg_wifi_pool(struct ctl_table *ctl, int write,
Pamidipati, Vijayee9c2972016-01-10 08:13:19 +0530797 void __user *buffer,
798 size_t *lenp, loff_t *ppos,
799 int *payloads)
800{
801 struct nss_top_instance *nss_top = &nss_top_main;
802 struct nss_ctx_instance *nss_ctx = &nss_top->nss[0];
803 struct nss_n2h_msg nnm;
804 struct nss_n2h_wifi_payloads *wp;
805 nss_tx_status_t nss_tx_status;
806 int ret = NSS_FAILURE;
807
808 /*
809 * Acquiring semaphore
810 */
811 down(&nss_n2h_wp.sem);
812
813 if (!write) {
814 *payloads = nss_n2h_wp.wifi_pool;
815
816 up(&nss_n2h_wp.sem);
817 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
818 return ret;
819 }
820
821 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
822 if (ret) {
823 up(&nss_n2h_wp.sem);
824 return ret;
825 }
826
827 /*
828 * If payloads parameter is not set, we do
829 * nothing.
830 */
831 if (*payloads == -1)
832 goto failure;
833
834 if ((*payloads < NSS_N2H_MIN_EMPTY_POOL_BUF_SZ)) {
835 nss_warning("%p: wifi setting %d < min number of buffer",
836 nss_ctx, *payloads);
837 goto failure;
838 }
839
840 if ((*payloads > NSS_N2H_MAX_EMPTY_POOL_BUF_SZ)) {
841 nss_warning("%p: wifi setting %d > max number of buffer",
842 nss_ctx, *payloads);
843 goto failure;
844 }
845
846 nss_info("%p: wifi payloads : %d\n",
847 nss_ctx, *payloads);
848
849 nss_n2h_msg_init(&nnm, NSS_N2H_INTERFACE,
850 NSS_TX_METADATA_TYPE_N2H_WIFI_POOL_BUF_CFG,
851 sizeof(struct nss_n2h_wifi_payloads),
852 nss_n2h_set_wifi_payloads_callback,
853 (void *)nss_ctx);
854
855 wp = &nnm.msg.wp;
856 wp->payloads = htonl(*payloads);
857 nss_tx_status = nss_n2h_tx_msg(nss_ctx, &nnm);
858
859 if (nss_tx_status != NSS_TX_SUCCESS) {
860 nss_warning("%p: wifi setting %d nss_tx error",
861 nss_ctx, *payloads);
862 goto failure;
863 }
864
865 /*
866 * Blocking call, wait till we get ACK for this msg.
867 */
868 ret = wait_for_completion_timeout(&nss_n2h_wp.complete,
869 msecs_to_jiffies(NSS_CONN_CFG_TIMEOUT));
870 if (ret == 0) {
871 nss_warning("%p: Waiting for ack timed out\n", nss_ctx);
872 goto failure;
873 }
874
875 /*
876 * ACK/NACK received from NSS FW
877 */
878 if (NSS_FAILURE == nss_n2h_wp.response)
879 goto failure;
880
881 up(&nss_n2h_wp.sem);
882 return NSS_SUCCESS;
883
884failure:
885 up(&nss_n2h_wp.sem);
886 return -EINVAL;
887}
888
889/*
Vijay Dewangan488e5372014-12-29 21:40:11 -0800890 * nss_n2h_empty_pool_buf_core1_handler()
891 * Sets the number of empty buffer for core 1
892 */
Stephen Wang52e6d342016-03-29 15:02:33 -0700893static int nss_n2h_empty_pool_buf_cfg_core1_handler(struct ctl_table *ctl,
Saurabh Misra71034db2015-06-04 16:18:38 -0700894 int write, void __user *buffer,
895 size_t *lenp, loff_t *ppos)
Vijay Dewangan488e5372014-12-29 21:40:11 -0800896{
897 return nss_n2h_set_empty_pool_buf(ctl, write, buffer, lenp, ppos,
Saurabh Misra71034db2015-06-04 16:18:38 -0700898 NSS_CORE_1, &nss_n2h_empty_pool_buf_cfg[NSS_CORE_1]);
Vijay Dewangan488e5372014-12-29 21:40:11 -0800899}
900
901/*
902 * nss_n2h_empty_pool_buf_core0_handler()
903 * Sets the number of empty buffer for core 0
904 */
Stephen Wang52e6d342016-03-29 15:02:33 -0700905static int nss_n2h_empty_pool_buf_cfg_core0_handler(struct ctl_table *ctl,
Saurabh Misra71034db2015-06-04 16:18:38 -0700906 int write, void __user *buffer,
907 size_t *lenp, loff_t *ppos)
Vijay Dewangan488e5372014-12-29 21:40:11 -0800908{
909 return nss_n2h_set_empty_pool_buf(ctl, write, buffer, lenp, ppos,
Saurabh Misra71034db2015-06-04 16:18:38 -0700910 NSS_CORE_0, &nss_n2h_empty_pool_buf_cfg[NSS_CORE_0]);
911}
912
913/*
Sachin Shashidhar475012b2017-03-13 16:56:07 -0700914 * nss_n2h_empty_paged_pool_buf_cfg_core1_handler()
915 * Sets the number of empty paged buffer for core 1
916 */
917static int nss_n2h_empty_paged_pool_buf_cfg_core1_handler(struct ctl_table *ctl,
918 int write, void __user *buffer,
919 size_t *lenp, loff_t *ppos)
920{
921 return nss_n2h_set_empty_paged_pool_buf(ctl, write, buffer, lenp, ppos,
922 NSS_CORE_1, &nss_n2h_empty_paged_pool_buf_cfg[NSS_CORE_1]);
923}
924
925/*
926 * nss_n2h_empty_paged_pool_buf_cfg_core0_handler()
927 * Sets the number of empty paged buffer for core 0
928 */
929static int nss_n2h_empty_paged_pool_buf_cfg_core0_handler(struct ctl_table *ctl,
930 int write, void __user *buffer,
931 size_t *lenp, loff_t *ppos)
932{
933 return nss_n2h_set_empty_paged_pool_buf(ctl, write, buffer, lenp, ppos,
934 NSS_CORE_0, &nss_n2h_empty_paged_pool_buf_cfg[NSS_CORE_0]);
935}
936
937/*
Saurabh Misra71034db2015-06-04 16:18:38 -0700938 * nss_n2h_water_mark_core1_handler()
939 * Sets water mark for core 1
940 */
Stephen Wang52e6d342016-03-29 15:02:33 -0700941static int nss_n2h_water_mark_core1_handler(struct ctl_table *ctl,
Saurabh Misra71034db2015-06-04 16:18:38 -0700942 int write, void __user *buffer,
943 size_t *lenp, loff_t *ppos)
944{
945 return nss_n2h_set_water_mark(ctl, write, buffer, lenp, ppos,
946 NSS_CORE_1, &nss_n2h_water_mark[NSS_CORE_1][0],
947 &nss_n2h_water_mark[NSS_CORE_1][1]);
948}
949
950/*
951 * nss_n2h_water_mark_core0_handler()
952 * Sets water mark for core 0
953 */
Stephen Wang52e6d342016-03-29 15:02:33 -0700954static int nss_n2h_water_mark_core0_handler(struct ctl_table *ctl,
Saurabh Misra71034db2015-06-04 16:18:38 -0700955 int write, void __user *buffer,
956 size_t *lenp, loff_t *ppos)
957{
958 return nss_n2h_set_water_mark(ctl, write, buffer, lenp, ppos,
959 NSS_CORE_0, &nss_n2h_water_mark[NSS_CORE_0][0],
960 &nss_n2h_water_mark[NSS_CORE_0][1]);
Vijay Dewangan488e5372014-12-29 21:40:11 -0800961}
962
Vijay Dewangan634ce592015-01-07 17:21:09 -0800963/*
Sachin Shashidhar475012b2017-03-13 16:56:07 -0700964 * nss_n2h_paged_water_mark_core1_handler()
965 * Sets paged water mark for core 1
966 */
967static int nss_n2h_paged_water_mark_core1_handler(struct ctl_table *ctl,
968 int write, void __user *buffer,
969 size_t *lenp, loff_t *ppos)
970{
971 return nss_n2h_set_paged_water_mark(ctl, write, buffer, lenp, ppos,
972 NSS_CORE_1, &nss_n2h_paged_water_mark[NSS_CORE_1][0],
973 &nss_n2h_paged_water_mark[NSS_CORE_1][1]);
974}
975
Sachin Shashidhar475012b2017-03-13 16:56:07 -0700976/*
977 * nss_n2h_paged_water_mark_core0_handler()
978 * Sets paged water mark for core 0
979 */
980static int nss_n2h_paged_water_mark_core0_handler(struct ctl_table *ctl,
981 int write, void __user *buffer,
982 size_t *lenp, loff_t *ppos)
983{
984 return nss_n2h_set_paged_water_mark(ctl, write, buffer, lenp, ppos,
985 NSS_CORE_0, &nss_n2h_paged_water_mark[NSS_CORE_0][0],
986 &nss_n2h_paged_water_mark[NSS_CORE_0][1]);
987}
988
989/*
Pamidipati, Vijayee9c2972016-01-10 08:13:19 +0530990 * nss_n2h_wifi_payloads_handler()
991 * Sets number of wifi payloads
992 */
Stephen Wang52e6d342016-03-29 15:02:33 -0700993static int nss_n2h_wifi_payloads_handler(struct ctl_table *ctl,
Pamidipati, Vijayee9c2972016-01-10 08:13:19 +0530994 int write, void __user *buffer,
995 size_t *lenp, loff_t *ppos)
996{
997 return nss_n2h_cfg_wifi_pool(ctl, write, buffer, lenp, ppos,
998 &nss_n2h_wifi_pool_buf_cfg);
999}
1000
1001/*
ratheesh kannothab436af2017-07-20 08:51:07 +05301002 * nss_n2h_update_queue_config_callback()
1003 * Callback to handle the completion of queue config command
ratheesh kannoth024a6e82017-05-18 17:48:10 +05301004 */
ratheesh kannothab436af2017-07-20 08:51:07 +05301005static void nss_n2h_update_queue_config_callback(void *app_data, struct nss_n2h_msg *nim)
ratheesh kannoth024a6e82017-05-18 17:48:10 +05301006{
ratheesh kannothab436af2017-07-20 08:51:07 +05301007 if (nim->cm.response != NSS_CMN_RESPONSE_ACK) {
1008 nss_warning("n2h Error response %d\n", nim->cm.response);
1009 nss_n2h_q_cfg_pvt.response = NSS_TX_FAILURE;
1010 } else {
1011 nss_n2h_q_cfg_pvt.response = NSS_TX_SUCCESS;
1012 }
1013
1014 complete(&nss_n2h_q_cfg_pvt.complete);
1015}
1016
1017/*
1018 * nss_n2h_update_queue_config_async()
1019 * Asynchronous call to send pnode queue configuration.
1020 */
1021nss_tx_status_t nss_n2h_update_queue_config_async(struct nss_ctx_instance *nss_ctx, bool mq_en, uint16_t *qlimits)
1022{
1023
ratheesh kannoth024a6e82017-05-18 17:48:10 +05301024 struct nss_n2h_msg nnm;
1025 struct nss_n2h_pnode_queue_config *cfg;
1026 nss_tx_status_t status;
ratheesh kannoth024a6e82017-05-18 17:48:10 +05301027 int i;
1028
1029 if (!mq_en) {
1030 return NSS_TX_SUCCESS;
1031 }
1032
ratheesh kannoth93ba95c2017-07-13 15:52:52 +05301033 /*
1034 * MQ mode doesnot make any sense if number of priority queues in NSS
1035 * is 1
1036 */
1037 if (NSS_MAX_NUM_PRI <= 1) {
1038 return NSS_TX_SUCCESS;
1039 }
1040
ratheesh kannothab436af2017-07-20 08:51:07 +05301041 memset(&nnm, 0, sizeof(struct nss_n2h_msg));
ratheesh kannoth024a6e82017-05-18 17:48:10 +05301042
ratheesh kannoth024a6e82017-05-18 17:48:10 +05301043 nss_n2h_msg_init(&nnm, NSS_N2H_INTERFACE,
1044 NSS_TX_METADATA_TYPE_N2H_SET_PNODE_QUEUE_CFG,
1045 sizeof(struct nss_n2h_pnode_queue_config), NULL, 0);
1046
ratheesh kannothab436af2017-07-20 08:51:07 +05301047 cfg = &nnm.msg.pn_q_cfg;
1048
1049 /*
1050 * Update limits
1051 */
1052 for (i = 0; i < NSS_MAX_NUM_PRI; i++) {
1053 cfg->qlimits[i] = qlimits[i];
1054 }
1055 cfg->mq_en = true;
1056
ratheesh kannoth024a6e82017-05-18 17:48:10 +05301057 status = nss_n2h_tx_msg(nss_ctx, &nnm);
1058 if (status != NSS_TX_SUCCESS) {
1059 nss_warning("%p: nss_tx error to send pnode queue config\n", nss_ctx);
1060 return status;
1061 }
1062
1063 return NSS_TX_SUCCESS;
ratheesh kannoth024a6e82017-05-18 17:48:10 +05301064}
ratheesh kannothab436af2017-07-20 08:51:07 +05301065EXPORT_SYMBOL(nss_n2h_update_queue_config_async);
1066
1067/*
1068 * nss_n2h_update_queue_config_sync()
1069 * Synchronous call to send pnode queue configuration.
1070 */
1071nss_tx_status_t nss_n2h_update_queue_config_sync(struct nss_ctx_instance *nss_ctx, bool mq_en, uint16_t *qlimits)
1072{
1073
1074 struct nss_n2h_msg nnm;
1075 struct nss_n2h_pnode_queue_config *cfg;
1076 nss_tx_status_t status;
1077 int ret, i;
1078
1079 if (!mq_en) {
1080 return NSS_TX_SUCCESS;
1081 }
1082
ratheesh kannoth93ba95c2017-07-13 15:52:52 +05301083 /*
1084 * MQ mode doesnot make any sense if number of priority queues in NSS
1085 * is 1
1086 */
1087 if (NSS_MAX_NUM_PRI <= 1) {
1088 return NSS_TX_SUCCESS;
1089 }
1090
ratheesh kannothab436af2017-07-20 08:51:07 +05301091 memset(&nnm, 0, sizeof(struct nss_n2h_msg));
1092
1093 nss_n2h_msg_init(&nnm, NSS_N2H_INTERFACE,
1094 NSS_TX_METADATA_TYPE_N2H_SET_PNODE_QUEUE_CFG,
1095 sizeof(struct nss_n2h_pnode_queue_config), nss_n2h_update_queue_config_callback, 0);
1096
1097 cfg = &nnm.msg.pn_q_cfg;
1098
1099 /*
1100 * Update limits
1101 */
1102 for (i = 0; i < NSS_MAX_NUM_PRI; i++) {
1103 cfg->qlimits[i] = qlimits[i];
1104 }
1105 cfg->mq_en = true;
1106
1107 down(&nss_n2h_q_cfg_pvt.sem);
1108
1109 status = nss_n2h_tx_msg(nss_ctx, &nnm);
1110
1111 if (status != NSS_TX_SUCCESS) {
1112 nss_warning("%p: n2h_tx_msg failed\n", nss_ctx);
1113 up(&nss_n2h_q_cfg_pvt.sem);
1114 return status;
1115 }
1116 ret = wait_for_completion_timeout(&nss_n2h_q_cfg_pvt.complete, msecs_to_jiffies(NSS_N2H_TX_TIMEOUT));
1117
1118 if (!ret) {
1119 nss_warning("%p: Timeout expired for pnode queue config sync message\n", nss_ctx);
1120 nss_n2h_q_cfg_pvt.response = NSS_TX_FAILURE;
1121 }
1122
1123 status = nss_n2h_q_cfg_pvt.response;
1124 up(&nss_n2h_q_cfg_pvt.sem);
1125 return status;
1126}
1127EXPORT_SYMBOL(nss_n2h_update_queue_config_sync);
ratheesh kannoth024a6e82017-05-18 17:48:10 +05301128
1129/*
Vijay Dewangan634ce592015-01-07 17:21:09 -08001130 * nss_n2h_rps_cfg()
1131 * Send Message to NSS to enable RPS.
1132 */
Stephen Wang49b474b2016-03-25 10:40:30 -07001133static nss_tx_status_t nss_n2h_rps_cfg(struct nss_ctx_instance *nss_ctx, int enable_rps)
Vijay Dewangan634ce592015-01-07 17:21:09 -08001134{
1135 struct nss_n2h_msg nnm;
1136 struct nss_n2h_rps *rps_cfg;
1137 nss_tx_status_t nss_tx_status;
1138 int ret;
1139
1140 down(&nss_n2h_rcp.sem);
1141 nss_n2h_msg_init(&nnm, NSS_N2H_INTERFACE, NSS_TX_METADATA_TYPE_N2H_RPS_CFG,
1142 sizeof(struct nss_n2h_rps),
1143 nss_n2h_rps_cfg_callback,
1144 (void *)nss_ctx);
1145
1146 rps_cfg = &nnm.msg.rps_cfg;
1147 rps_cfg->enable = enable_rps;
1148
1149 nss_tx_status = nss_n2h_tx_msg(nss_ctx, &nnm);
1150
1151 if (nss_tx_status != NSS_TX_SUCCESS) {
1152 nss_warning("%p: nss_tx error setting rps\n", nss_ctx);
1153
1154 up(&nss_n2h_rcp.sem);
1155 return NSS_FAILURE;
1156 }
1157
1158 /*
1159 * Blocking call, wait till we get ACK for this msg.
1160 */
1161 ret = wait_for_completion_timeout(&nss_n2h_rcp.complete, msecs_to_jiffies(NSS_CONN_CFG_TIMEOUT));
1162 if (ret == 0) {
1163 nss_warning("%p: Waiting for ack timed out\n", nss_ctx);
1164 up(&nss_n2h_rcp.sem);
1165 return NSS_FAILURE;
1166 }
1167
1168 /*
1169 * ACK/NACK received from NSS FW
1170 * If ACK: Callback function will update nss_n2h_empty_pool_buf with
1171 * nss_n2h_nepbcfgp.num_conn_valid, which holds the user input
1172 */
1173 if (NSS_FAILURE == nss_n2h_rcp.response) {
1174 up(&nss_n2h_rcp.sem);
1175 return NSS_FAILURE;
1176 }
1177
1178 up(&nss_n2h_rcp.sem);
1179 return NSS_SUCCESS;
1180}
1181
Kalyan Tallapragadab50e8902015-08-06 17:00:54 +05301182/*
1183 * nss_n2h_mitigation_cfg()
1184 * Send Message to NSS to disable MITIGATION.
1185 */
Stephen Wang49b474b2016-03-25 10:40:30 -07001186static nss_tx_status_t nss_n2h_mitigation_cfg(struct nss_ctx_instance *nss_ctx, int enable_mitigation, nss_core_id_t core_num)
Kalyan Tallapragadab50e8902015-08-06 17:00:54 +05301187{
1188 struct nss_n2h_msg nnm;
1189 struct nss_n2h_mitigation *mitigation_cfg;
1190 nss_tx_status_t nss_tx_status;
1191 int ret;
1192
1193 nss_assert(core_num < NSS_CORE_MAX);
1194
1195 down(&nss_n2h_mitigationcp[core_num].sem);
1196 nss_n2h_msg_init(&nnm, NSS_N2H_INTERFACE, NSS_TX_METADATA_TYPE_N2H_MITIGATION_CFG,
1197 sizeof(struct nss_n2h_mitigation),
1198 nss_n2h_mitigation_cfg_callback,
1199 (void *)core_num);
1200
1201 mitigation_cfg = &nnm.msg.mitigation_cfg;
1202 mitigation_cfg->enable = enable_mitigation;
1203
1204 nss_tx_status = nss_n2h_tx_msg(nss_ctx, &nnm);
1205
1206 if (nss_tx_status != NSS_TX_SUCCESS) {
1207 nss_warning("%p: nss_tx error setting mitigation\n", nss_ctx);
1208 goto failure;
1209 }
1210
1211 /*
1212 * Blocking call, wait till we get ACK for this msg.
1213 */
1214 ret = wait_for_completion_timeout(&nss_n2h_mitigationcp[core_num].complete, msecs_to_jiffies(NSS_CONN_CFG_TIMEOUT));
1215 if (ret == 0) {
1216 nss_warning("%p: Waiting for ack timed out\n", nss_ctx);
1217 goto failure;
1218 }
1219
1220 /*
1221 * ACK/NACK received from NSS FW
1222 */
1223 if (NSS_FAILURE == nss_n2h_mitigationcp[core_num].response) {
1224 goto failure;
1225 }
1226
1227 up(&nss_n2h_mitigationcp[core_num].sem);
1228 return NSS_SUCCESS;
1229
1230failure:
1231 up(&nss_n2h_mitigationcp[core_num].sem);
1232 return NSS_FAILURE;
1233}
1234
1235static inline void nss_n2h_buf_pool_free(struct nss_n2h_buf_pool *buf_pool)
1236{
1237 int page_count;
1238 for (page_count = 0; page_count < buf_pool->nss_buf_num_pages; page_count++) {
Stephen Wang7df68832017-08-10 16:54:35 -07001239 kfree((void *)buf_pool->nss_buf_pool_vaddr[page_count]);
Kalyan Tallapragadab50e8902015-08-06 17:00:54 +05301240 }
1241}
1242
1243/*
1244 * nss_n2h_buf_cfg()
1245 * Send Message to NSS to enable pbufs.
1246 */
Stephen Wang49b474b2016-03-25 10:40:30 -07001247static nss_tx_status_t nss_n2h_buf_pool_cfg(struct nss_ctx_instance *nss_ctx,
Tallapragada4b0161b2016-07-07 21:38:34 +05301248 int buf_pool_size, nss_core_id_t core_num)
Kalyan Tallapragadab50e8902015-08-06 17:00:54 +05301249{
1250 static struct nss_n2h_msg nnm;
1251 struct nss_n2h_buf_pool *buf_pool;
1252 nss_tx_status_t nss_tx_status;
1253 int ret;
1254 int page_count;
1255 int num_pages = ALIGN(buf_pool_size, PAGE_SIZE)/PAGE_SIZE;
1256
1257 nss_assert(core_num < NSS_CORE_MAX);
1258
1259 nss_n2h_msg_init(&nnm, NSS_N2H_INTERFACE, NSS_METADATA_TYPE_N2H_ADD_BUF_POOL,
1260 sizeof(struct nss_n2h_buf_pool),
1261 nss_n2h_bufs_cfg_callback,
1262 (void *)core_num);
1263
1264 do {
1265
1266 down(&nss_n2h_bufcp[core_num].sem);
1267
1268 buf_pool = &nnm.msg.buf_pool;
1269 buf_pool->nss_buf_page_size = PAGE_SIZE;
1270
1271 for (page_count = 0; page_count < MAX_PAGES_PER_MSG && num_pages; page_count++, num_pages--) {
Kalyan Tallapragadab50e8902015-08-06 17:00:54 +05301272 void *kern_addr = kzalloc(PAGE_SIZE, GFP_ATOMIC);
1273 if (!kern_addr) {
1274 BUG_ON(!page_count);
1275 break;
1276 }
Kalyan Tallapragadab50e8902015-08-06 17:00:54 +05301277
Radha krishna Simha Jiguru60068fb2017-07-28 17:40:52 +05301278 kmemleak_not_leak(kern_addr);
Stephen Wang7df68832017-08-10 16:54:35 -07001279 buf_pool->nss_buf_pool_vaddr[page_count] = (nss_ptr_t)kern_addr;
Stephen Wangefd38512017-01-24 14:01:02 -08001280 buf_pool->nss_buf_pool_addr[page_count] = dma_map_single(nss_ctx->dev, kern_addr, PAGE_SIZE, DMA_TO_DEVICE);
Kalyan Tallapragadab50e8902015-08-06 17:00:54 +05301281 }
1282
1283 buf_pool->nss_buf_num_pages = page_count;
1284 nss_tx_status = nss_n2h_tx_msg(nss_ctx, &nnm);
1285 if (nss_tx_status != NSS_TX_SUCCESS) {
1286
1287 nss_n2h_buf_pool_free(buf_pool);
1288 nss_warning("%p: nss_tx error setting pbuf\n", nss_ctx);
1289 goto failure;
1290 }
1291
1292 /*
1293 * Blocking call, wait till we get ACK for this msg.
1294 */
1295 ret = wait_for_completion_timeout(&nss_n2h_bufcp[core_num].complete, msecs_to_jiffies(NSS_CONN_CFG_TIMEOUT));
1296 if (ret == 0) {
1297 nss_warning("%p: Waiting for ack timed out\n", nss_ctx);
1298 goto failure;
1299 }
1300
1301 /*
1302 * ACK/NACK received from NSS FW
1303 */
1304 if (NSS_FAILURE == nss_n2h_bufcp[core_num].response) {
1305
1306 nss_n2h_buf_pool_free(buf_pool);
1307 goto failure;
1308 }
1309
1310 up(&nss_n2h_bufcp[core_num].sem);
1311 } while(num_pages);
1312
1313 return NSS_SUCCESS;
1314failure:
1315 up(&nss_n2h_bufcp[core_num].sem);
1316 return NSS_FAILURE;
1317}
1318
Stephen Wang49b474b2016-03-25 10:40:30 -07001319/*
1320 * nss_rps_handler()
1321 * Enable NSS RPS
1322 */
Stephen Wang52e6d342016-03-29 15:02:33 -07001323static int nss_n2h_rpscfg_handler(struct ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos)
Stephen Wang49b474b2016-03-25 10:40:30 -07001324{
1325 struct nss_top_instance *nss_top = &nss_top_main;
1326 struct nss_ctx_instance *nss_ctx = &nss_top->nss[0];
1327 int ret;
Kalyan Tallapragadab50e8902015-08-06 17:00:54 +05301328
Stephen Wang49b474b2016-03-25 10:40:30 -07001329 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
1330 if (!ret) {
1331 if ((write) && (nss_n2h_rps_config == 1)) {
1332 printk(KERN_INFO "Enabling NSS RPS\n");
1333
1334 return nss_n2h_rps_cfg(nss_ctx, 1);
1335 }
1336
1337 if ((write) && (nss_n2h_rps_config == 0)) {
1338 printk(KERN_INFO "Runtime disabling of NSS RPS not supported\n");
1339 return ret;
1340 }
1341
1342 if (write) {
1343 printk(KERN_INFO "Invalid input value.Valid values are 0 and 1\n");
1344 }
1345
1346 }
1347
1348 return ret;
1349}
1350
1351/*
1352 * nss_mitigation_handler()
1353 * Enable NSS MITIGATION
1354 */
Stephen Wang52e6d342016-03-29 15:02:33 -07001355static int nss_n2h_mitigationcfg_core0_handler(struct ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos)
Stephen Wang49b474b2016-03-25 10:40:30 -07001356{
1357 struct nss_top_instance *nss_top = &nss_top_main;
1358 struct nss_ctx_instance *nss_ctx = &nss_top->nss[NSS_CORE_0];
1359 int ret;
1360
1361 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
1362 if (ret) {
1363 return ret;
1364 }
1365
1366 /*
1367 * It's a read operation
1368 */
1369 if (!write) {
1370 return ret;
1371 }
1372
1373 if (!nss_n2h_core0_mitigation_cfg) {
1374 printk(KERN_INFO "Disabling NSS MITIGATION\n");
1375 nss_n2h_mitigation_cfg(nss_ctx, 0, NSS_CORE_0);
1376 return 0;
1377 }
1378 printk(KERN_INFO "Invalid input value.Valid value is 0, Runtime re-enabling not supported\n");
1379 return -EINVAL;
1380}
1381
1382/*
1383 * nss_mitigation_handler()
1384 * Enable NSS MITIGATION
1385 */
Stephen Wang52e6d342016-03-29 15:02:33 -07001386static int nss_n2h_mitigationcfg_core1_handler(struct ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos)
Stephen Wang49b474b2016-03-25 10:40:30 -07001387{
1388 struct nss_top_instance *nss_top = &nss_top_main;
1389 struct nss_ctx_instance *nss_ctx = &nss_top->nss[NSS_CORE_1];
1390 int ret;
1391
1392 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
1393 if (ret) {
1394 return ret;
1395 }
1396
1397 /*
1398 * It's a read operation
1399 */
1400 if (!write) {
1401 return ret;
1402 }
1403
1404 if (!nss_n2h_core1_mitigation_cfg) {
1405 printk(KERN_INFO "Disabling NSS MITIGATION\n");
1406 nss_n2h_mitigation_cfg(nss_ctx, 0, NSS_CORE_1);
1407 return 0;
1408 }
1409 printk(KERN_INFO "Invalid input value.Valid value is 0, Runtime re-enabling not supported\n");
1410 return -EINVAL;
1411}
1412
1413/*
1414 * nss_buf_handler()
1415 * Add extra NSS bufs from host memory
1416 */
Stephen Wang52e6d342016-03-29 15:02:33 -07001417static int nss_n2h_buf_cfg_core0_handler(struct ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos)
Stephen Wang49b474b2016-03-25 10:40:30 -07001418{
1419 struct nss_top_instance *nss_top = &nss_top_main;
1420 struct nss_ctx_instance *nss_ctx = &nss_top->nss[NSS_CORE_0];
1421 int ret;
1422
1423 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
1424 if (ret) {
1425 return ret;
1426 }
1427
1428 /*
1429 * It's a read operation
1430 */
1431 if (!write) {
1432 return ret;
1433 }
1434
1435 if (nss_ctx->buf_sz_allocated) {
1436 nss_n2h_core0_add_buf_pool_size = nss_ctx->buf_sz_allocated;
1437 return -EPERM;
1438 }
1439
1440 if ((nss_n2h_core0_add_buf_pool_size >= 1) && (nss_n2h_core0_add_buf_pool_size <= NSS_N2H_MAX_BUF_POOL_SIZE)) {
1441 printk(KERN_INFO "configuring additional NSS pbufs\n");
1442 ret = nss_n2h_buf_pool_cfg(nss_ctx, nss_n2h_core0_add_buf_pool_size, NSS_CORE_0);
1443 nss_n2h_core0_add_buf_pool_size = nss_ctx->buf_sz_allocated;
1444 printk(KERN_INFO "additional pbufs of size %d got added to NSS\n", nss_ctx->buf_sz_allocated);
1445 return ret;
1446 }
1447
1448 printk(KERN_INFO "Invalid input value. should be greater than 1 and less than %d\n", NSS_N2H_MAX_BUF_POOL_SIZE);
1449 return -EINVAL;
1450}
1451
1452/*
1453 * nss_n2h_buf_handler()
1454 * Add extra NSS bufs from host memory
1455 */
Stephen Wang52e6d342016-03-29 15:02:33 -07001456static int nss_n2h_buf_cfg_core1_handler(struct ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos)
Stephen Wang49b474b2016-03-25 10:40:30 -07001457{
1458 struct nss_top_instance *nss_top = &nss_top_main;
1459 struct nss_ctx_instance *nss_ctx = &nss_top->nss[NSS_CORE_1];
1460 int ret;
1461
1462 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
1463 if (ret) {
1464 return ret;
1465 }
1466
1467 /*
1468 * It's a read operation
1469 */
1470 if (!write) {
1471 return ret;
1472 }
1473
1474 if (nss_ctx->buf_sz_allocated) {
1475 nss_n2h_core1_add_buf_pool_size = nss_ctx->buf_sz_allocated;
1476 return -EPERM;
1477 }
1478
1479 if ((nss_n2h_core1_add_buf_pool_size >= 1) && (nss_n2h_core1_add_buf_pool_size <= NSS_N2H_MAX_BUF_POOL_SIZE)) {
1480 printk(KERN_INFO "configuring additional NSS pbufs\n");
1481 ret = nss_n2h_buf_pool_cfg(nss_ctx, nss_n2h_core1_add_buf_pool_size, NSS_CORE_1);
1482 nss_n2h_core1_add_buf_pool_size = nss_ctx->buf_sz_allocated;
1483 printk(KERN_INFO "additional pbufs of size %d got added to NSS\n", nss_ctx->buf_sz_allocated);
1484 return ret;
1485 }
1486
1487 printk(KERN_INFO "Invalid input value. should be greater than 1 and less than %d\n", NSS_N2H_MAX_BUF_POOL_SIZE);
1488 return -EINVAL;
1489}
Kalyan Tallapragadab50e8902015-08-06 17:00:54 +05301490
Stephen Wang52e6d342016-03-29 15:02:33 -07001491static struct ctl_table nss_n2h_table[] = {
Vijay Dewangan488e5372014-12-29 21:40:11 -08001492 {
Saurabh Misra71034db2015-06-04 16:18:38 -07001493 .procname = "n2h_empty_pool_buf_core0",
1494 .data = &nss_n2h_empty_pool_buf_cfg[NSS_CORE_0],
1495 .maxlen = sizeof(int),
1496 .mode = 0644,
1497 .proc_handler = &nss_n2h_empty_pool_buf_cfg_core0_handler,
Vijay Dewangan488e5372014-12-29 21:40:11 -08001498 },
1499 {
Saurabh Misra71034db2015-06-04 16:18:38 -07001500 .procname = "n2h_empty_pool_buf_core1",
1501 .data = &nss_n2h_empty_pool_buf_cfg[NSS_CORE_1],
1502 .maxlen = sizeof(int),
1503 .mode = 0644,
1504 .proc_handler = &nss_n2h_empty_pool_buf_cfg_core1_handler,
1505 },
1506 {
Sachin Shashidhar475012b2017-03-13 16:56:07 -07001507 .procname = "n2h_empty_paged_pool_buf_core0",
1508 .data = &nss_n2h_empty_paged_pool_buf_cfg[NSS_CORE_0],
1509 .maxlen = sizeof(int),
1510 .mode = 0644,
1511 .proc_handler = &nss_n2h_empty_paged_pool_buf_cfg_core0_handler,
1512 },
1513 {
1514 .procname = "n2h_empty_paged_pool_buf_core1",
1515 .data = &nss_n2h_empty_paged_pool_buf_cfg[NSS_CORE_1],
1516 .maxlen = sizeof(int),
1517 .mode = 0644,
1518 .proc_handler = &nss_n2h_empty_paged_pool_buf_cfg_core1_handler,
1519 },
1520
1521 {
Saurabh Misra71034db2015-06-04 16:18:38 -07001522 .procname = "n2h_low_water_core0",
1523 .data = &nss_n2h_water_mark[NSS_CORE_0][0],
1524 .maxlen = sizeof(int),
1525 .mode = 0644,
1526 .proc_handler = &nss_n2h_water_mark_core0_handler,
1527 },
1528 {
1529 .procname = "n2h_low_water_core1",
1530 .data = &nss_n2h_water_mark[NSS_CORE_1][0],
1531 .maxlen = sizeof(int),
1532 .mode = 0644,
1533 .proc_handler = &nss_n2h_water_mark_core1_handler,
1534 },
1535 {
1536 .procname = "n2h_high_water_core0",
1537 .data = &nss_n2h_water_mark[NSS_CORE_0][1],
1538 .maxlen = sizeof(int),
1539 .mode = 0644,
1540 .proc_handler = &nss_n2h_water_mark_core0_handler,
1541 },
1542 {
1543 .procname = "n2h_high_water_core1",
1544 .data = &nss_n2h_water_mark[NSS_CORE_1][1],
1545 .maxlen = sizeof(int),
1546 .mode = 0644,
1547 .proc_handler = &nss_n2h_water_mark_core1_handler,
Vijay Dewangan488e5372014-12-29 21:40:11 -08001548 },
Pamidipati, Vijayee9c2972016-01-10 08:13:19 +05301549 {
Sachin Shashidhar475012b2017-03-13 16:56:07 -07001550 .procname = "n2h_paged_low_water_core0",
1551 .data = &nss_n2h_paged_water_mark[NSS_CORE_0][0],
1552 .maxlen = sizeof(int),
1553 .mode = 0644,
1554 .proc_handler = &nss_n2h_paged_water_mark_core0_handler,
1555 },
1556 {
1557 .procname = "n2h_paged_low_water_core1",
1558 .data = &nss_n2h_paged_water_mark[NSS_CORE_1][0],
1559 .maxlen = sizeof(int),
1560 .mode = 0644,
1561 .proc_handler = &nss_n2h_paged_water_mark_core1_handler,
1562 },
1563 {
1564 .procname = "n2h_paged_high_water_core0",
1565 .data = &nss_n2h_paged_water_mark[NSS_CORE_0][1],
1566 .maxlen = sizeof(int),
1567 .mode = 0644,
1568 .proc_handler = &nss_n2h_paged_water_mark_core0_handler,
1569 },
1570 {
1571 .procname = "n2h_paged_high_water_core1",
1572 .data = &nss_n2h_paged_water_mark[NSS_CORE_1][1],
1573 .maxlen = sizeof(int),
1574 .mode = 0644,
1575 .proc_handler = &nss_n2h_paged_water_mark_core1_handler,
1576 },
1577 {
Pamidipati, Vijayee9c2972016-01-10 08:13:19 +05301578 .procname = "n2h_wifi_pool_buf",
1579 .data = &nss_n2h_wifi_pool_buf_cfg,
1580 .maxlen = sizeof(int),
1581 .mode = 0644,
1582 .proc_handler = &nss_n2h_wifi_payloads_handler,
1583 },
Stephen Wang49b474b2016-03-25 10:40:30 -07001584 {
1585 .procname = "rps",
1586 .data = &nss_n2h_rps_config,
1587 .maxlen = sizeof(int),
1588 .mode = 0644,
1589 .proc_handler = &nss_n2h_rpscfg_handler,
1590 },
1591 {
1592 .procname = "mitigation_core0",
1593 .data = &nss_n2h_core0_mitigation_cfg,
1594 .maxlen = sizeof(int),
1595 .mode = 0644,
1596 .proc_handler = &nss_n2h_mitigationcfg_core0_handler,
1597 },
1598 {
1599 .procname = "mitigation_core1",
1600 .data = &nss_n2h_core1_mitigation_cfg,
1601 .maxlen = sizeof(int),
1602 .mode = 0644,
1603 .proc_handler = &nss_n2h_mitigationcfg_core1_handler,
1604 },
1605 {
1606 .procname = "extra_pbuf_core0",
1607 .data = &nss_n2h_core0_add_buf_pool_size,
1608 .maxlen = sizeof(int),
1609 .mode = 0644,
1610 .proc_handler = &nss_n2h_buf_cfg_core0_handler,
1611 },
1612 {
1613 .procname = "extra_pbuf_core1",
1614 .data = &nss_n2h_core1_add_buf_pool_size,
1615 .maxlen = sizeof(int),
1616 .mode = 0644,
1617 .proc_handler = &nss_n2h_buf_cfg_core1_handler,
1618 },
Vijay Dewangan488e5372014-12-29 21:40:11 -08001619
1620 { }
1621};
1622
Stephen Wang52e6d342016-03-29 15:02:33 -07001623static struct ctl_table nss_n2h_dir[] = {
Vijay Dewangan488e5372014-12-29 21:40:11 -08001624 {
1625 .procname = "n2hcfg",
1626 .mode = 0555,
1627 .child = nss_n2h_table,
1628 },
1629 { }
1630};
1631
Stephen Wang52e6d342016-03-29 15:02:33 -07001632static struct ctl_table nss_n2h_root_dir[] = {
Vijay Dewangan488e5372014-12-29 21:40:11 -08001633 {
1634 .procname = "nss",
1635 .mode = 0555,
1636 .child = nss_n2h_dir,
1637 },
1638 { }
1639};
1640
Stephen Wang52e6d342016-03-29 15:02:33 -07001641static struct ctl_table nss_n2h_root[] = {
Vijay Dewangan488e5372014-12-29 21:40:11 -08001642 {
1643 .procname = "dev",
1644 .mode = 0555,
1645 .child = nss_n2h_root_dir,
1646 },
1647 { }
1648};
1649
1650static struct ctl_table_header *nss_n2h_header;
1651
1652/*
Stephen Wang49b474b2016-03-25 10:40:30 -07001653 * nss_n2h_flush_payloads()
1654 * Sends a command down to NSS for flushing all payloads
1655 */
1656nss_tx_status_t nss_n2h_flush_payloads(struct nss_ctx_instance *nss_ctx)
1657{
1658 struct nss_n2h_msg nnm;
1659 struct nss_n2h_flush_payloads *nnflshpl;
1660 nss_tx_status_t nss_tx_status;
1661
1662 nnflshpl = &nnm.msg.flush_payloads;
1663
1664 /*
1665 * TODO: No additional information sent in message
1666 * as of now. Need to initialize message content accordingly
1667 * if needed.
1668 */
1669 nss_n2h_msg_init(&nnm, NSS_N2H_INTERFACE,
1670 NSS_TX_METADATA_TYPE_N2H_FLUSH_PAYLOADS,
1671 sizeof(struct nss_n2h_flush_payloads),
1672 NULL,
1673 NULL);
1674
1675 nss_tx_status = nss_n2h_tx_msg(nss_ctx, &nnm);
1676 if (nss_tx_status != NSS_TX_SUCCESS) {
1677 nss_warning("%p: failed to send flush payloads command to NSS\n",
1678 nss_ctx);
1679
1680 return NSS_TX_FAILURE;
1681 }
1682
1683 return NSS_TX_SUCCESS;
1684}
1685
1686/*
Vijay Dewangan488e5372014-12-29 21:40:11 -08001687 * nss_n2h_msg_init()
Stephen Wang49b474b2016-03-25 10:40:30 -07001688 * Initialize n2h message.
Vijay Dewangan488e5372014-12-29 21:40:11 -08001689 */
1690void nss_n2h_msg_init(struct nss_n2h_msg *nim, uint16_t if_num, uint32_t type,
Vijay Dewangan634ce592015-01-07 17:21:09 -08001691 uint32_t len, nss_n2h_msg_callback_t cb, void *app_data)
Vijay Dewangan488e5372014-12-29 21:40:11 -08001692{
1693 nss_cmn_msg_init(&nim->cm, if_num, type, len, (void *)cb, app_data);
1694}
1695
Vijay Dewangan488e5372014-12-29 21:40:11 -08001696/*
Vijay Dewangan488e5372014-12-29 21:40:11 -08001697 * nss_n2h_tx_msg()
1698 * Send messages to NSS n2h pacakge
1699 */
1700nss_tx_status_t nss_n2h_tx_msg(struct nss_ctx_instance *nss_ctx, struct nss_n2h_msg *nnm)
1701{
1702 struct nss_n2h_msg *nnm2;
1703 struct nss_cmn_msg *ncm = &nnm->cm;
1704 struct sk_buff *nbuf;
1705 nss_tx_status_t status;
1706
1707 NSS_VERIFY_CTX_MAGIC(nss_ctx);
1708 if (unlikely(nss_ctx->state != NSS_CORE_STATE_INITIALIZED)) {
1709 return NSS_TX_FAILURE_NOT_READY;
1710 }
1711
1712 /*
1713 * Sanity check the message
1714 */
1715 if (ncm->interface != NSS_N2H_INTERFACE) {
1716 nss_warning("%p: tx request for another interface: %d", nss_ctx, ncm->interface);
1717 return NSS_TX_FAILURE;
1718 }
1719
1720 if (ncm->type >= NSS_METADATA_TYPE_N2H_MAX) {
1721 nss_warning("%p: message type out of range: %d", nss_ctx, ncm->type);
1722 return NSS_TX_FAILURE;
1723 }
1724
Suruchi Agarwalef8a8702016-01-08 12:40:08 -08001725 if (nss_cmn_get_msg_len(ncm) > sizeof(struct nss_n2h_msg)) {
1726 nss_warning("%p: tx request for another interface: %d", nss_ctx, nss_cmn_get_msg_len(ncm));
Vijay Dewangan488e5372014-12-29 21:40:11 -08001727 return NSS_TX_FAILURE;
1728 }
1729
Vijay Dewangan488e5372014-12-29 21:40:11 -08001730 nbuf = dev_alloc_skb(NSS_NBUF_PAYLOAD_SIZE);
1731 if (unlikely(!nbuf)) {
Sundarajan Srinivasan62fee7e2015-01-22 11:13:10 -08001732 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 -08001733 return NSS_TX_FAILURE;
1734 }
1735
1736 /*
1737 * Copy the message to our skb.
1738 */
1739 nnm2 = (struct nss_n2h_msg *)skb_put(nbuf, sizeof(struct nss_n2h_msg));
1740 memcpy(nnm2, nnm, sizeof(struct nss_n2h_msg));
1741 status = nss_core_send_buffer(nss_ctx, 0, nbuf, NSS_IF_CMD_QUEUE, H2N_BUFFER_CTRL, 0);
1742 if (status != NSS_CORE_STATUS_SUCCESS) {
1743 dev_kfree_skb_any(nbuf);
1744 nss_info("%p: unable to enqueue 'nss frequency change' - marked as stopped\n", nss_ctx);
1745 return NSS_TX_FAILURE;
1746 }
1747
Stephen Wang90c67de2016-04-26 15:15:59 -07001748 nss_hal_send_interrupt(nss_ctx, NSS_H2N_INTR_DATA_COMMAND_QUEUE);
Vijay Dewangan488e5372014-12-29 21:40:11 -08001749 NSS_PKT_STATS_INCREMENT(nss_ctx, &nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_TX_CMD_REQ]);
1750 return NSS_TX_SUCCESS;
1751}
1752
Vijay Dewangan488e5372014-12-29 21:40:11 -08001753/*
1754 * nss_n2h_notify_register()
1755 * Register to received N2H events.
1756 *
1757 * NOTE: Do we want to pass an nss_ctx here so that we can register for n2h on any core?
1758 */
1759struct nss_ctx_instance *nss_n2h_notify_register(int core, nss_n2h_msg_callback_t cb, void *app_data)
1760{
1761 if (core >= NSS_MAX_CORES) {
1762 nss_warning("Input core number %d is wrong \n", core);
1763 return NULL;
1764 }
1765 /*
1766 * TODO: We need to have a new array in support of the new API
1767 * TODO: If we use a per-context array, we would move the array into nss_ctx based.
1768 */
1769 nss_n2h_rd[core].n2h_callback = cb;
1770 nss_n2h_rd[core].app_data = app_data;
1771 return &nss_top_main.nss[core];
Abhishek Rastogi84d95d02014-03-26 19:31:31 +05301772}
1773
1774/*
1775 * nss_n2h_register_handler()
1776 */
Thomas Wu91f4bdf2017-06-09 12:03:02 -07001777void nss_n2h_register_handler(struct nss_ctx_instance *nss_ctx)
Abhishek Rastogi84d95d02014-03-26 19:31:31 +05301778{
ratheesh kannothab436af2017-07-20 08:51:07 +05301779 sema_init(&nss_n2h_q_cfg_pvt.sem, 1);
1780 init_completion(&nss_n2h_q_cfg_pvt.complete);
1781
Thomas Wu91f4bdf2017-06-09 12:03:02 -07001782 nss_core_register_handler(nss_ctx, NSS_N2H_INTERFACE, nss_n2h_interface_handler, NULL);
Yu Huang8c107082017-07-24 14:58:26 -07001783
1784 nss_n2h_stats_dentry_create();
Stephen Wang49b474b2016-03-25 10:40:30 -07001785}
Sundarajan Srinivasanf1e57462014-09-17 15:24:01 -07001786
Stephen Wang49b474b2016-03-25 10:40:30 -07001787/*
1788 * nss_n2h_register_sysctl()
1789 */
1790void nss_n2h_register_sysctl(void)
1791{
Vijay Dewangan634ce592015-01-07 17:21:09 -08001792 /*
1793 * RPS sema init
1794 */
1795 sema_init(&nss_n2h_rcp.sem, 1);
1796 init_completion(&nss_n2h_rcp.complete);
1797
Kalyan Tallapragadab50e8902015-08-06 17:00:54 +05301798 /*
1799 * MITIGATION sema init for core0
1800 */
1801 sema_init(&nss_n2h_mitigationcp[NSS_CORE_0].sem, 1);
1802 init_completion(&nss_n2h_mitigationcp[NSS_CORE_0].complete);
1803
1804 /*
1805 * MITIGATION sema init for core1
1806 */
1807 sema_init(&nss_n2h_mitigationcp[NSS_CORE_1].sem, 1);
1808 init_completion(&nss_n2h_mitigationcp[NSS_CORE_1].complete);
1809
1810 /*
1811 * PBUF addition sema init for core0
1812 */
1813 sema_init(&nss_n2h_bufcp[NSS_CORE_0].sem, 1);
1814 init_completion(&nss_n2h_bufcp[NSS_CORE_0].complete);
1815
1816 /*
1817 * PBUF addition sema init for core1
1818 */
1819 sema_init(&nss_n2h_bufcp[NSS_CORE_1].sem, 1);
1820 init_completion(&nss_n2h_bufcp[NSS_CORE_1].complete);
Vijay Dewangan634ce592015-01-07 17:21:09 -08001821
Stephen Wang49b474b2016-03-25 10:40:30 -07001822 /*
1823 * Core0
1824 */
1825 sema_init(&nss_n2h_nepbcfgp[NSS_CORE_0].sem, 1);
1826 init_completion(&nss_n2h_nepbcfgp[NSS_CORE_0].complete);
Sachin Shashidhar475012b2017-03-13 16:56:07 -07001827 nss_n2h_nepbcfgp[NSS_CORE_0].empty_buf_pool_info.pool_size =
Stephen Wang49b474b2016-03-25 10:40:30 -07001828 nss_n2h_empty_pool_buf_cfg[NSS_CORE_0];
Sachin Shashidhar475012b2017-03-13 16:56:07 -07001829 nss_n2h_nepbcfgp[NSS_CORE_0].empty_buf_pool_info.low_water =
Stephen Wang49b474b2016-03-25 10:40:30 -07001830 nss_n2h_water_mark[NSS_CORE_0][0];
Sachin Shashidhar475012b2017-03-13 16:56:07 -07001831 nss_n2h_nepbcfgp[NSS_CORE_0].empty_buf_pool_info.high_water =
Stephen Wang49b474b2016-03-25 10:40:30 -07001832 nss_n2h_water_mark[NSS_CORE_0][1];
Sachin Shashidhar475012b2017-03-13 16:56:07 -07001833 nss_n2h_nepbcfgp[NSS_CORE_0].empty_paged_buf_pool_info.pool_size =
1834 nss_n2h_empty_paged_pool_buf_cfg[NSS_CORE_0];
1835 nss_n2h_nepbcfgp[NSS_CORE_0].empty_paged_buf_pool_info.low_water =
1836 nss_n2h_paged_water_mark[NSS_CORE_0][0];
1837 nss_n2h_nepbcfgp[NSS_CORE_0].empty_paged_buf_pool_info.high_water =
1838 nss_n2h_paged_water_mark[NSS_CORE_0][1];
1839
Stephen Wang49b474b2016-03-25 10:40:30 -07001840 /*
1841 * Core1
1842 */
1843 sema_init(&nss_n2h_nepbcfgp[NSS_CORE_1].sem, 1);
1844 init_completion(&nss_n2h_nepbcfgp[NSS_CORE_1].complete);
Sachin Shashidhar475012b2017-03-13 16:56:07 -07001845 nss_n2h_nepbcfgp[NSS_CORE_1].empty_buf_pool_info.pool_size =
Stephen Wang49b474b2016-03-25 10:40:30 -07001846 nss_n2h_empty_pool_buf_cfg[NSS_CORE_1];
Sachin Shashidhar475012b2017-03-13 16:56:07 -07001847 nss_n2h_nepbcfgp[NSS_CORE_1].empty_buf_pool_info.low_water =
Stephen Wang49b474b2016-03-25 10:40:30 -07001848 nss_n2h_water_mark[NSS_CORE_1][0];
Sachin Shashidhar475012b2017-03-13 16:56:07 -07001849 nss_n2h_nepbcfgp[NSS_CORE_1].empty_buf_pool_info.high_water =
Stephen Wang49b474b2016-03-25 10:40:30 -07001850 nss_n2h_water_mark[NSS_CORE_1][1];
Sachin Shashidhar475012b2017-03-13 16:56:07 -07001851 nss_n2h_nepbcfgp[NSS_CORE_1].empty_paged_buf_pool_info.pool_size =
1852 nss_n2h_empty_paged_pool_buf_cfg[NSS_CORE_1];
1853 nss_n2h_nepbcfgp[NSS_CORE_1].empty_paged_buf_pool_info.low_water =
1854 nss_n2h_paged_water_mark[NSS_CORE_1][0];
1855 nss_n2h_nepbcfgp[NSS_CORE_1].empty_paged_buf_pool_info.high_water =
1856 nss_n2h_paged_water_mark[NSS_CORE_1][1];
1857
Stephen Wang49b474b2016-03-25 10:40:30 -07001858 /*
1859 * WiFi pool buf cfg sema init
1860 */
1861 sema_init(&nss_n2h_wp.sem, 1);
1862 init_completion(&nss_n2h_wp.complete);
1863
Vijay Dewangan488e5372014-12-29 21:40:11 -08001864 nss_n2h_notify_register(NSS_CORE_0, NULL, NULL);
1865 nss_n2h_notify_register(NSS_CORE_1, NULL, NULL);
1866
Stephen Wang49b474b2016-03-25 10:40:30 -07001867 /*
1868 * Register sysctl table.
1869 */
1870 nss_n2h_header = register_sysctl_table(nss_n2h_root);
1871}
1872
1873/*
1874 * nss_n2h_unregister_sysctl()
1875 * Unregister sysctl specific to n2h
1876 */
1877void nss_n2h_unregister_sysctl(void)
1878{
1879 /*
1880 * Unregister sysctl table.
1881 */
1882 if (nss_n2h_header) {
1883 unregister_sysctl_table(nss_n2h_header);
1884 }
Abhishek Rastogi84d95d02014-03-26 19:31:31 +05301885}
Vijay Dewangan488e5372014-12-29 21:40:11 -08001886
1887EXPORT_SYMBOL(nss_n2h_notify_register);