blob: 463f924acd7c94edde220a65df3dd1f1292ea6d4 [file] [log] [blame]
Abhishek Rastogi84d95d02014-03-26 19:31:31 +05301/*
2 **************************************************************************
Stephen Wang3e2dbd12018-03-14 17:28:17 -07003 * Copyright (c) 2013-2018, 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_core0_mitigation_cfg __read_mostly = 1;
37int nss_n2h_core1_mitigation_cfg __read_mostly = 1;
38int nss_n2h_core0_add_buf_pool_size __read_mostly;
39int nss_n2h_core1_add_buf_pool_size __read_mostly;
Shashank Balashankar4162f572018-08-21 13:32:34 -070040int nss_n2h_queue_limit[NSS_MAX_CORES] __read_mostly = {NSS_DEFAULT_QUEUE_LIMIT, NSS_DEFAULT_QUEUE_LIMIT};
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;
Shashank Balashankar4162f572018-08-21 13:32:34 -070054static struct nss_n2h_cfg_pvt nss_n2h_q_lim_pvt;
Pamidipati, Vijayefcc4692014-05-09 14:47:38 +053055
56/*
Sundarajan Srinivasanf1e57462014-09-17 15:24:01 -070057 * nss_n2h_interface_handler()
Abhishek Rastogi84d95d02014-03-26 19:31:31 +053058 * Handle NSS -> HLOS messages for N2H node
59 */
Vijay Dewangan634ce592015-01-07 17:21:09 -080060static void nss_n2h_interface_handler(struct nss_ctx_instance *nss_ctx,
61 struct nss_cmn_msg *ncm,
Arunkumar Tba9b4a02016-11-07 11:41:14 +053062 void *app_data)
Abhishek Rastogi84d95d02014-03-26 19:31:31 +053063{
64 struct nss_n2h_msg *nnm = (struct nss_n2h_msg *)ncm;
Vijay Dewangan488e5372014-12-29 21:40:11 -080065 nss_n2h_msg_callback_t cb;
Abhishek Rastogi84d95d02014-03-26 19:31:31 +053066
Sundarajan Srinivasanf1e57462014-09-17 15:24:01 -070067 BUG_ON(ncm->interface != NSS_N2H_INTERFACE);
68
Abhishek Rastogi84d95d02014-03-26 19:31:31 +053069 /*
70 * Is this a valid request/response packet?
71 */
72 if (nnm->cm.type >= NSS_METADATA_TYPE_N2H_MAX) {
73 nss_warning("%p: received invalid message %d for Offload stats interface", nss_ctx, nnm->cm.type);
74 return;
75 }
76
77 switch (nnm->cm.type) {
Pamidipati, Vijayefcc4692014-05-09 14:47:38 +053078 case NSS_TX_METADATA_TYPE_N2H_RPS_CFG:
Pamidipati, Vijayefcc4692014-05-09 14:47:38 +053079 nss_info("NSS N2H rps_en %d \n",nnm->msg.rps_cfg.enable);
Vijay Dewangan488e5372014-12-29 21:40:11 -080080 break;
81
Kalyan Tallapragadab50e8902015-08-06 17:00:54 +053082 case NSS_TX_METADATA_TYPE_N2H_MITIGATION_CFG:
83 nss_info("NSS N2H mitigation_dis %d \n",nnm->msg.mitigation_cfg.enable);
84 break;
85
Vijay Dewangan488e5372014-12-29 21:40:11 -080086 case NSS_TX_METADATA_TYPE_N2H_EMPTY_POOL_BUF_CFG:
87 nss_info("%p: empty pool buf cfg response from FW", nss_ctx);
Pamidipati, Vijayefcc4692014-05-09 14:47:38 +053088 break;
89
Radha krishna Simha Jiguru7f424d52015-02-10 19:41:01 +053090 case NSS_TX_METADATA_TYPE_N2H_FLUSH_PAYLOADS:
91 nss_info("%p: flush payloads cmd response from FW", nss_ctx);
92 break;
93
Abhishek Rastogi84d95d02014-03-26 19:31:31 +053094 case NSS_RX_METADATA_TYPE_N2H_STATS_SYNC:
Sundarajan Srinivasanf1e57462014-09-17 15:24:01 -070095 nss_n2h_stats_sync(nss_ctx, &nnm->msg.stats_sync);
Abhishek Rastogi84d95d02014-03-26 19:31:31 +053096 break;
97
98 default:
99 if (ncm->response != NSS_CMN_RESPONSE_ACK) {
100 /*
101 * Check response
102 */
103 nss_info("%p: Received response %d for type %d, interface %d",
104 nss_ctx, ncm->response, ncm->type, ncm->interface);
105 }
106 }
Vijay Dewangan488e5372014-12-29 21:40:11 -0800107
108 /*
Stephen Wang49b474b2016-03-25 10:40:30 -0700109 * Update the callback and app_data for NOTIFY messages, n2h sends all notify messages
Vijay Dewangan488e5372014-12-29 21:40:11 -0800110 * to the same callback/app_data.
111 */
Suruchi Agarwale4ad24a2018-06-11 12:03:46 +0530112 if (nnm->cm.response == NSS_CMN_RESPONSE_NOTIFY) {
Vijay Dewangan488e5372014-12-29 21:40:11 -0800113 /*
114 * Place holder for the user to create right call
Suruchi Agarwale4ad24a2018-06-11 12:03:46 +0530115 * back and app data when response is NSS_CMN_RESPONSE_NOTIFY
Vijay Dewangan488e5372014-12-29 21:40:11 -0800116 */
Stephen Wangaed46332016-12-12 17:29:03 -0800117 ncm->cb = (nss_ptr_t)nss_n2h_rd[nss_ctx->id].n2h_callback;
118 ncm->app_data = (nss_ptr_t)nss_n2h_rd[nss_ctx->id].app_data;
Vijay Dewangan488e5372014-12-29 21:40:11 -0800119 }
120
121 /*
122 * Do we have a callback?
123 */
124 if (!ncm->cb) {
125 return;
126 }
127
128 /*
129 * Callback
130 */
131 cb = (nss_n2h_msg_callback_t)ncm->cb;
132 cb((void *)ncm->app_data, nnm);
133}
134
135/*
Kalyan Tallapragadab50e8902015-08-06 17:00:54 +0530136 * nss_n2h_mitigation_cfg_callback()
137 * call back function for mitigation configuration
138 */
139static void nss_n2h_mitigation_cfg_callback(void *app_data, struct nss_n2h_msg *nnm)
140{
Stephen Wangaed46332016-12-12 17:29:03 -0800141 uint32_t core_num = (uint32_t)(nss_ptr_t)app_data;
Kalyan Tallapragadab50e8902015-08-06 17:00:54 +0530142 struct nss_top_instance *nss_top = &nss_top_main;
143 struct nss_ctx_instance *nss_ctx = &nss_top->nss[core_num];
144
145 if (nnm->cm.response != NSS_CMN_RESPONSE_ACK) {
146
147 /*
148 * Error, hence we are not updating the nss_n2h_mitigate_en
149 */
150 nss_n2h_mitigationcp[core_num].response = NSS_FAILURE;
151 complete(&nss_n2h_mitigationcp[core_num].complete);
152 nss_warning("core%d: MITIGATION configuration failed : %d\n", core_num, nnm->cm.error);
153 return;
154 }
155
156 nss_info("core%d: MITIGATION configuration succeeded: %d\n", core_num, nnm->cm.error);
157
158 nss_ctx->n2h_mitigate_en = nnm->msg.mitigation_cfg.enable;
159 nss_n2h_mitigationcp[core_num].response = NSS_SUCCESS;
160 complete(&nss_n2h_mitigationcp[core_num].complete);
161}
162
163/*
164 * nss_n2h_buf_cfg_callback()
165 * call back function for pbuf configuration
166 */
167static void nss_n2h_bufs_cfg_callback(void *app_data, struct nss_n2h_msg *nnm)
168{
Stephen Wangaed46332016-12-12 17:29:03 -0800169 uint32_t core_num = (uint32_t)(nss_ptr_t)app_data;
Kalyan Tallapragadab50e8902015-08-06 17:00:54 +0530170 unsigned int allocated_sz;
171
172 struct nss_top_instance *nss_top = &nss_top_main;
173 struct nss_ctx_instance *nss_ctx = &nss_top->nss[core_num];
174
175 if (nnm->cm.response != NSS_CMN_RESPONSE_ACK) {
176 nss_n2h_bufcp[core_num].response = NSS_FAILURE;
177 nss_warning("core%d: buf configuration failed : %d\n", core_num, nnm->cm.error);
178 goto done;
179 }
180
181 nss_info("core%d: buf configuration succeeded: %d\n", core_num, nnm->cm.error);
182
183 allocated_sz = nnm->msg.buf_pool.nss_buf_page_size * nnm->msg.buf_pool.nss_buf_num_pages;
184 nss_ctx->buf_sz_allocated += allocated_sz;
185
186 nss_n2h_bufcp[core_num].response = NSS_SUCCESS;
187
188done:
189 complete(&nss_n2h_bufcp[core_num].complete);
190}
191
192/*
Saurabh Misra71034db2015-06-04 16:18:38 -0700193 * nss_n2h_payload_stats_callback()
194 * It gets called response to payload accounting.
Vijay Dewangan488e5372014-12-29 21:40:11 -0800195 */
Saurabh Misra71034db2015-06-04 16:18:38 -0700196static void nss_n2h_payload_stats_callback(void *app_data,
197 struct nss_n2h_msg *nnm)
Vijay Dewangan488e5372014-12-29 21:40:11 -0800198{
Stephen Wangaed46332016-12-12 17:29:03 -0800199 uint32_t core_num = (uint32_t)(nss_ptr_t)app_data;
Saurabh Misra71034db2015-06-04 16:18:38 -0700200
Vijay Dewangan488e5372014-12-29 21:40:11 -0800201 if (nnm->cm.response != NSS_CMN_RESPONSE_ACK) {
202 struct nss_n2h_empty_pool_buf *nnepbcm;
203 nnepbcm = &nnm->msg.empty_pool_buf_cfg;
204
Saurabh Misra71034db2015-06-04 16:18:38 -0700205 nss_warning("%d: core empty pool buf set failure: %d\n",
206 core_num, nnm->cm.error);
Vijay Dewangan488e5372014-12-29 21:40:11 -0800207 nss_n2h_nepbcfgp[core_num].response = NSS_FAILURE;
208 complete(&nss_n2h_nepbcfgp[core_num].complete);
209 return;
210 }
211
Sachin Shashidhar475012b2017-03-13 16:56:07 -0700212 if (nnm->cm.type == NSS_TX_METADATA_TYPE_GET_WATER_MARK) {
213 nss_n2h_nepbcfgp[core_num].empty_buf_pool_info.pool_size =
Saurabh Misra71034db2015-06-04 16:18:38 -0700214 ntohl(nnm->msg.payload_info.pool_size);
Sachin Shashidhar475012b2017-03-13 16:56:07 -0700215 nss_n2h_nepbcfgp[core_num].empty_buf_pool_info.low_water =
Saurabh Misra71034db2015-06-04 16:18:38 -0700216 ntohl(nnm->msg.payload_info.low_water);
Sachin Shashidhar475012b2017-03-13 16:56:07 -0700217 nss_n2h_nepbcfgp[core_num].empty_buf_pool_info.high_water =
Saurabh Misra71034db2015-06-04 16:18:38 -0700218 ntohl(nnm->msg.payload_info.high_water);
219 }
220
Sachin Shashidhar475012b2017-03-13 16:56:07 -0700221 if (nnm->cm.type == NSS_TX_METADATA_TYPE_GET_PAGED_WATER_MARK) {
222 nss_n2h_nepbcfgp[core_num].empty_paged_buf_pool_info.pool_size =
223 ntohl(nnm->msg.paged_payload_info.pool_size);
224 nss_n2h_nepbcfgp[core_num].empty_paged_buf_pool_info.low_water =
225 ntohl(nnm->msg.paged_payload_info.low_water);
226 nss_n2h_nepbcfgp[core_num].empty_paged_buf_pool_info.high_water =
227 ntohl(nnm->msg.paged_payload_info.high_water);
228 }
229
Vijay Dewangan488e5372014-12-29 21:40:11 -0800230 nss_n2h_nepbcfgp[core_num].response = NSS_SUCCESS;
231 complete(&nss_n2h_nepbcfgp[core_num].complete);
232}
233
234/*
Pamidipati, Vijayee9c2972016-01-10 08:13:19 +0530235 * nss_n2h_set_wifi_payloads_callback()
Cemil Coskun9165c762017-12-04 14:35:24 -0800236 * call back function for response to wifi pool configuration
Pamidipati, Vijayee9c2972016-01-10 08:13:19 +0530237 *
238 */
239static void nss_n2h_set_wifi_payloads_callback(void *app_data,
240 struct nss_n2h_msg *nnm)
241{
Arunkumar Tba9b4a02016-11-07 11:41:14 +0530242 struct nss_ctx_instance *nss_ctx __maybe_unused = (struct nss_ctx_instance *)app_data;
Pamidipati, Vijayee9c2972016-01-10 08:13:19 +0530243 if (nnm->cm.response != NSS_CMN_RESPONSE_ACK) {
244
245 nss_n2h_wp.response = NSS_FAILURE;
246 complete(&nss_n2h_wp.complete);
247 nss_warning("%p: wifi pool configuration failed : %d\n", nss_ctx,
248 nnm->cm.error);
249 return;
250 }
251
252 nss_info("%p: wifi payload configuration succeeded: %d\n", nss_ctx,
253 nnm->cm.error);
254 nss_n2h_wp.response = NSS_SUCCESS;
255 complete(&nss_n2h_wp.complete);
256}
257
258/*
Saurabh Misra71034db2015-06-04 16:18:38 -0700259 * nss_n2h_get_payload_info()
Sachin Shashidhar475012b2017-03-13 16:56:07 -0700260 * Gets Payload information.
Vijay Dewangan488e5372014-12-29 21:40:11 -0800261 */
Sachin Shashidhar475012b2017-03-13 16:56:07 -0700262static 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 -0700263{
264 struct nss_top_instance *nss_top = &nss_top_main;
265 struct nss_ctx_instance *nss_ctx = &nss_top->nss[core_num];
Saurabh Misra71034db2015-06-04 16:18:38 -0700266 nss_tx_status_t nss_tx_status;
267 int ret = NSS_FAILURE;
268
269 /*
270 * Note that semaphore should be already held.
271 */
272
Sachin Shashidhar475012b2017-03-13 16:56:07 -0700273 nss_tx_status = nss_n2h_tx_msg(nss_ctx, nnm);
Saurabh Misra71034db2015-06-04 16:18:38 -0700274
275 if (nss_tx_status != NSS_TX_SUCCESS) {
Stephen Wangaed46332016-12-12 17:29:03 -0800276 nss_warning("%p: core %d nss_tx error errorn", nss_ctx, (int)core_num);
Saurabh Misra71034db2015-06-04 16:18:38 -0700277 return NSS_FAILURE;
278 }
279
280 /*
281 * Blocking call, wait till we get ACK for this msg.
282 */
283 ret = wait_for_completion_timeout(&nss_n2h_nepbcfgp[core_num].complete,
284 msecs_to_jiffies(NSS_CONN_CFG_TIMEOUT));
285 if (ret == 0) {
Stephen Wangaed46332016-12-12 17:29:03 -0800286 nss_warning("%p: core %d waiting for ack timed out\n", nss_ctx, (int)core_num);
Saurabh Misra71034db2015-06-04 16:18:38 -0700287 return NSS_FAILURE;
288 }
289
290 if (NSS_FAILURE == nss_n2h_nepbcfgp[core_num].response) {
Stephen Wangaed46332016-12-12 17:29:03 -0800291 nss_warning("%p: core %d response returned failure\n", nss_ctx, (int)core_num);
Saurabh Misra71034db2015-06-04 16:18:38 -0700292 return NSS_FAILURE;
293 }
294
295 return NSS_SUCCESS;
296}
297
298/*
Sachin Shashidhar475012b2017-03-13 16:56:07 -0700299 * nss_n2h_get_default_payload_info()
300 * Gets the default payload information.
301 */
302static int nss_n2h_get_default_payload_info(nss_ptr_t core_num)
303{
304 struct nss_n2h_msg nnm;
305
306 nss_n2h_msg_init(&nnm, NSS_N2H_INTERFACE,
307 NSS_TX_METADATA_TYPE_GET_WATER_MARK,
308 sizeof(struct nss_n2h_payload_info),
309 nss_n2h_payload_stats_callback,
310 (void *)core_num);
311
312 return nss_n2h_get_payload_info(core_num, &nnm,
313 &nnm.msg.payload_info);
314}
315
316/*
317 * nss_n2h_get_paged_payload_info()
318 * Gets the paged payload information.
319 */
320static int nss_n2h_get_paged_payload_info(nss_ptr_t core_num)
321{
322 struct nss_n2h_msg nnm;
323
324 nss_n2h_msg_init(&nnm, NSS_N2H_INTERFACE,
325 NSS_TX_METADATA_TYPE_GET_PAGED_WATER_MARK,
326 sizeof(struct nss_n2h_payload_info),
327 nss_n2h_payload_stats_callback,
328 (void *)core_num);
329
330 return nss_n2h_get_payload_info(core_num, &nnm,
331 &nnm.msg.paged_payload_info);
332}
333
334/*
Saurabh Misra71034db2015-06-04 16:18:38 -0700335 * nss_n2h_set_empty_pool_buf()
336 * Sets empty pool buffer
337 */
Stephen Wang52e6d342016-03-29 15:02:33 -0700338static int nss_n2h_set_empty_pool_buf(struct ctl_table *ctl, int write,
Saurabh Misra71034db2015-06-04 16:18:38 -0700339 void __user *buffer,
340 size_t *lenp, loff_t *ppos,
Stephen Wangaed46332016-12-12 17:29:03 -0800341 nss_ptr_t core_num, int *new_val)
Vijay Dewangan488e5372014-12-29 21:40:11 -0800342{
343 struct nss_top_instance *nss_top = &nss_top_main;
344 struct nss_ctx_instance *nss_ctx = &nss_top->nss[core_num];
345 struct nss_n2h_msg nnm;
346 struct nss_n2h_empty_pool_buf *nnepbcm;
347 nss_tx_status_t nss_tx_status;
348 int ret = NSS_FAILURE;
349
350 /*
351 * Acquiring semaphore
352 */
353 down(&nss_n2h_nepbcfgp[core_num].sem);
354
355 /*
356 * Take snap shot of current value
357 */
Sachin Shashidhar475012b2017-03-13 16:56:07 -0700358 nss_n2h_nepbcfgp[core_num].empty_buf_pool_info.pool_size = *new_val;
Vijay Dewangan488e5372014-12-29 21:40:11 -0800359
Saurabh Misra71034db2015-06-04 16:18:38 -0700360 if (!write) {
Sachin Shashidhar475012b2017-03-13 16:56:07 -0700361 ret = nss_n2h_get_default_payload_info(core_num);
362 *new_val = nss_n2h_nepbcfgp[core_num].empty_buf_pool_info.pool_size;
Saurabh Misra71034db2015-06-04 16:18:38 -0700363 if (ret == NSS_FAILURE) {
364 up(&nss_n2h_nepbcfgp[core_num].sem);
365 return -EBUSY;
366 }
367
368 up(&nss_n2h_nepbcfgp[core_num].sem);
369
370 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
371 return ret;
372 }
373
Vijay Dewangan488e5372014-12-29 21:40:11 -0800374 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
Saurabh Misra71034db2015-06-04 16:18:38 -0700375 if (ret) {
Vijay Dewangan488e5372014-12-29 21:40:11 -0800376 up(&nss_n2h_nepbcfgp[core_num].sem);
377 return ret;
378 }
379
Vijay Dewangan488e5372014-12-29 21:40:11 -0800380 if ((*new_val < NSS_N2H_MIN_EMPTY_POOL_BUF_SZ)) {
Saurabh Misra71034db2015-06-04 16:18:38 -0700381 nss_warning("%p: core %d setting %d < min number of buffer",
Stephen Wangaed46332016-12-12 17:29:03 -0800382 nss_ctx, (int)core_num, *new_val);
Stephen Wang06761022015-03-03 16:38:42 -0800383 goto failure;
Vijay Dewangan488e5372014-12-29 21:40:11 -0800384 }
385
386 nss_info("%p: core %d number of empty pool buffer is : %d\n",
Stephen Wangaed46332016-12-12 17:29:03 -0800387 nss_ctx, (int)core_num, *new_val);
Vijay Dewangan488e5372014-12-29 21:40:11 -0800388
389 nss_n2h_msg_init(&nnm, NSS_N2H_INTERFACE,
390 NSS_TX_METADATA_TYPE_N2H_EMPTY_POOL_BUF_CFG,
391 sizeof(struct nss_n2h_empty_pool_buf),
Saurabh Misra71034db2015-06-04 16:18:38 -0700392 nss_n2h_payload_stats_callback,
Stephen Wangaed46332016-12-12 17:29:03 -0800393 (nss_ptr_t *)core_num);
Vijay Dewangan488e5372014-12-29 21:40:11 -0800394
395 nnepbcm = &nnm.msg.empty_pool_buf_cfg;
396 nnepbcm->pool_size = htonl(*new_val);
397 nss_tx_status = nss_n2h_tx_msg(nss_ctx, &nnm);
398
399 if (nss_tx_status != NSS_TX_SUCCESS) {
Saurabh Misra71034db2015-06-04 16:18:38 -0700400 nss_warning("%p: core %d nss_tx error empty pool buffer: %d\n",
Stephen Wangaed46332016-12-12 17:29:03 -0800401 nss_ctx, (int)core_num, *new_val);
Stephen Wang06761022015-03-03 16:38:42 -0800402 goto failure;
Vijay Dewangan488e5372014-12-29 21:40:11 -0800403 }
404
405 /*
406 * Blocking call, wait till we get ACK for this msg.
407 */
Saurabh Misra71034db2015-06-04 16:18:38 -0700408 ret = wait_for_completion_timeout(&nss_n2h_nepbcfgp[core_num].complete,
409 msecs_to_jiffies(NSS_CONN_CFG_TIMEOUT));
Vijay Dewangan488e5372014-12-29 21:40:11 -0800410 if (ret == 0) {
Stephen Wangaed46332016-12-12 17:29:03 -0800411 nss_warning("%p: core %d Waiting for ack timed out\n", nss_ctx, (int)core_num);
Stephen Wang06761022015-03-03 16:38:42 -0800412 goto failure;
Vijay Dewangan488e5372014-12-29 21:40:11 -0800413 }
414
415 /*
416 * ACK/NACK received from NSS FW
417 * If ACK: Callback function will update nss_n2h_empty_pool_buf with
418 * nss_n2h_nepbcfgp.num_conn_valid, which holds the user input
419 */
420 if (NSS_FAILURE == nss_n2h_nepbcfgp[core_num].response) {
Stephen Wang06761022015-03-03 16:38:42 -0800421 goto failure;
Vijay Dewangan488e5372014-12-29 21:40:11 -0800422 }
423
424 up(&nss_n2h_nepbcfgp[core_num].sem);
Thomas Wu651b3902015-05-12 11:21:09 -0700425 return 0;
Stephen Wang06761022015-03-03 16:38:42 -0800426
427failure:
428 /*
429 * Restore the current_value to its previous state
430 */
Sachin Shashidhar475012b2017-03-13 16:56:07 -0700431 *new_val = nss_n2h_nepbcfgp[core_num].empty_buf_pool_info.pool_size;
432 up(&nss_n2h_nepbcfgp[core_num].sem);
433 return NSS_FAILURE;
434}
435
436/*
437 * nss_n2h_set_empty_paged_pool_buf()
438 * Sets empty paged pool buffer
439 */
440static int nss_n2h_set_empty_paged_pool_buf(struct ctl_table *ctl, int write,
441 void __user *buffer,
442 size_t *lenp, loff_t *ppos,
443 nss_ptr_t core_num, int *new_val)
444{
445 struct nss_top_instance *nss_top = &nss_top_main;
446 struct nss_ctx_instance *nss_ctx = &nss_top->nss[core_num];
447 struct nss_n2h_msg nnm;
448 struct nss_n2h_empty_pool_buf *nneppbcm;
449 nss_tx_status_t nss_tx_status;
450 int ret = NSS_FAILURE;
451
452 /*
453 * Acquiring semaphore
454 */
455 down(&nss_n2h_nepbcfgp[core_num].sem);
456
457 /*
458 * Take snap shot of current value
459 */
460 nss_n2h_nepbcfgp[core_num].empty_paged_buf_pool_info.pool_size = *new_val;
461
462 if (!write) {
463 ret = nss_n2h_get_paged_payload_info(core_num);
464 *new_val = nss_n2h_nepbcfgp[core_num].empty_paged_buf_pool_info.pool_size;
465 if (ret == NSS_FAILURE) {
466 up(&nss_n2h_nepbcfgp[core_num].sem);
467 return -EBUSY;
468 }
469
470 up(&nss_n2h_nepbcfgp[core_num].sem);
471
472 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
473 return ret;
474 }
475
476 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
477 if (ret) {
478 up(&nss_n2h_nepbcfgp[core_num].sem);
479 return ret;
480 }
481
482 if ((*new_val < NSS_N2H_MIN_EMPTY_POOL_BUF_SZ)) {
483 nss_warning("%p: core %d setting %d < min number of buffer",
484 nss_ctx, (int)core_num, *new_val);
485 goto failure;
486 }
487
488 nss_info("%p: core %d number of empty paged pool buffer is : %d\n",
489 nss_ctx, (int)core_num, *new_val);
490
491 nss_n2h_msg_init(&nnm, NSS_N2H_INTERFACE,
492 NSS_TX_METADATA_TYPE_N2H_EMPTY_PAGED_POOL_BUF_CFG,
493 sizeof(struct nss_n2h_empty_pool_buf),
494 nss_n2h_payload_stats_callback,
495 (nss_ptr_t *)core_num);
496
497 nneppbcm = &nnm.msg.empty_pool_buf_cfg;
498 nneppbcm->pool_size = htonl(*new_val);
499 nss_tx_status = nss_n2h_tx_msg(nss_ctx, &nnm);
500
501 if (nss_tx_status != NSS_TX_SUCCESS) {
502 nss_warning("%p: core %d nss_tx error empty paged pool buffer: %d\n",
503 nss_ctx, (int)core_num, *new_val);
504 goto failure;
505 }
506
507 /*
508 * Blocking call, wait till we get ACK for this msg.
509 */
510 ret = wait_for_completion_timeout(&nss_n2h_nepbcfgp[core_num].complete,
511 msecs_to_jiffies(NSS_CONN_CFG_TIMEOUT));
512 if (ret == 0) {
513 nss_warning("%p: core %d Waiting for ack timed out\n", nss_ctx, (int)core_num);
514 goto failure;
515 }
516
517 /*
518 * ACK/NACK received from NSS FW
519 * If ACK: Callback function will update nss_n2h_empty_pool_buf with
520 * nss_n2h_nepbcfgp.num_conn_valid, which holds the user input
521 */
522 if (NSS_FAILURE == nss_n2h_nepbcfgp[core_num].response) {
523 goto failure;
524 }
525
526 up(&nss_n2h_nepbcfgp[core_num].sem);
527 return 0;
528
529failure:
530 /*
531 * Restore the current_value to its previous state
532 */
533 *new_val = nss_n2h_nepbcfgp[core_num].empty_paged_buf_pool_info.pool_size;
Saurabh Misra71034db2015-06-04 16:18:38 -0700534 up(&nss_n2h_nepbcfgp[core_num].sem);
535 return NSS_FAILURE;
536}
537
538/*
539 * nss_n2h_set_water_mark()
540 * Sets water mark for N2H SOS
541 */
Stephen Wang52e6d342016-03-29 15:02:33 -0700542static int nss_n2h_set_water_mark(struct ctl_table *ctl, int write,
Saurabh Misra71034db2015-06-04 16:18:38 -0700543 void __user *buffer,
544 size_t *lenp, loff_t *ppos,
Stephen Wangaed46332016-12-12 17:29:03 -0800545 uint32_t core_num, int *low, int *high)
Saurabh Misra71034db2015-06-04 16:18:38 -0700546{
547 struct nss_top_instance *nss_top = &nss_top_main;
548 struct nss_ctx_instance *nss_ctx = &nss_top->nss[core_num];
549 struct nss_n2h_msg nnm;
550 struct nss_n2h_water_mark *wm;
551 nss_tx_status_t nss_tx_status;
552 int ret = NSS_FAILURE;
553
554 /*
555 * Acquiring semaphore
556 */
557 down(&nss_n2h_nepbcfgp[core_num].sem);
558
559 /*
560 * Take snap shot of current value
561 */
Sachin Shashidhar475012b2017-03-13 16:56:07 -0700562 nss_n2h_nepbcfgp[core_num].empty_buf_pool_info.low_water = *low;
563 nss_n2h_nepbcfgp[core_num].empty_buf_pool_info.high_water = *high;
Saurabh Misra71034db2015-06-04 16:18:38 -0700564
Sachin Shashidhar475012b2017-03-13 16:56:07 -0700565 if (!write || *low == -1 || *high == -1) {
566 ret = nss_n2h_get_default_payload_info(core_num);
Saurabh Misra71034db2015-06-04 16:18:38 -0700567 if (ret == NSS_FAILURE) {
568 up(&nss_n2h_nepbcfgp[core_num].sem);
569 return -EBUSY;
570 }
571
Sachin Shashidhar475012b2017-03-13 16:56:07 -0700572 *low = nss_n2h_nepbcfgp[core_num].empty_buf_pool_info.low_water;
573 *high = nss_n2h_nepbcfgp[core_num].empty_buf_pool_info.high_water;
Saurabh Misra71034db2015-06-04 16:18:38 -0700574 }
575
576 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
Sachin Shashidhar475012b2017-03-13 16:56:07 -0700577 if (!write || ret) {
Saurabh Misra71034db2015-06-04 16:18:38 -0700578 up(&nss_n2h_nepbcfgp[core_num].sem);
579 return ret;
580 }
581
Saurabh Misra71034db2015-06-04 16:18:38 -0700582 if ((*low < NSS_N2H_MIN_EMPTY_POOL_BUF_SZ) ||
583 (*high < NSS_N2H_MIN_EMPTY_POOL_BUF_SZ)) {
584 nss_warning("%p: core %d setting %d, %d < min number of buffer",
585 nss_ctx, core_num, *low, *high);
586 goto failure;
587 }
588
Pamidipati, Vijayee9c2972016-01-10 08:13:19 +0530589 if ((*low > NSS_N2H_MAX_EMPTY_POOL_BUF_SZ) ||
590 (*high > NSS_N2H_MAX_EMPTY_POOL_BUF_SZ)) {
Saurabh Misra71034db2015-06-04 16:18:38 -0700591 nss_warning("%p: core %d setting %d, %d is > upper limit",
592 nss_ctx, core_num, *low, *high);
593 goto failure;
594 }
595
596 if (*low > *high) {
597 nss_warning("%p: core %d setting low %d is more than high %d",
598 nss_ctx, core_num, *low, *high);
599 goto failure;
600 }
601
602 nss_info("%p: core %d number of low : %d and high : %d\n",
603 nss_ctx, core_num, *low, *high);
604
605 nss_n2h_msg_init(&nnm, NSS_N2H_INTERFACE,
606 NSS_TX_METADATA_TYPE_SET_WATER_MARK,
607 sizeof(struct nss_n2h_water_mark),
608 nss_n2h_payload_stats_callback,
Stephen Wangaed46332016-12-12 17:29:03 -0800609 (void *)(nss_ptr_t)core_num);
Saurabh Misra71034db2015-06-04 16:18:38 -0700610
611 wm = &nnm.msg.wm;
612 wm->low_water = htonl(*low);
613 wm->high_water = htonl(*high);
614 nss_tx_status = nss_n2h_tx_msg(nss_ctx, &nnm);
615
616 if (nss_tx_status != NSS_TX_SUCCESS) {
617 nss_warning("%p: core %d nss_tx error setting : %d, %d\n",
618 nss_ctx, core_num, *low, *high);
619 goto failure;
620 }
621
622 /*
623 * Blocking call, wait till we get ACK for this msg.
624 */
625 ret = wait_for_completion_timeout(&nss_n2h_nepbcfgp[core_num].complete,
626 msecs_to_jiffies(NSS_CONN_CFG_TIMEOUT));
627 if (ret == 0) {
628 nss_warning("%p: core %d Waiting for ack timed out\n", nss_ctx,
629 core_num);
630 goto failure;
631 }
632
633 /*
634 * ACK/NACK received from NSS FW
635 */
636 if (NSS_FAILURE == nss_n2h_nepbcfgp[core_num].response)
637 goto failure;
638
639 up(&nss_n2h_nepbcfgp[core_num].sem);
640 return NSS_SUCCESS;
641
642failure:
643 /*
644 * Restore the current_value to its previous state
645 */
Sachin Shashidhar475012b2017-03-13 16:56:07 -0700646 *low = nss_n2h_nepbcfgp[core_num].empty_buf_pool_info.low_water;
647 *high = nss_n2h_nepbcfgp[core_num].empty_buf_pool_info.high_water;
648 up(&nss_n2h_nepbcfgp[core_num].sem);
649 return -EINVAL;
650}
651
652/*
653 * nss_n2h_set_paged_water_mark()
654 * Sets water mark for paged pool N2H SOS
655 */
656static int nss_n2h_set_paged_water_mark(struct ctl_table *ctl, int write,
657 void __user *buffer,
658 size_t *lenp, loff_t *ppos,
659 uint32_t core_num, int *low, int *high)
660{
661 struct nss_top_instance *nss_top = &nss_top_main;
662 struct nss_ctx_instance *nss_ctx = &nss_top->nss[core_num];
663 struct nss_n2h_msg nnm;
664 struct nss_n2h_water_mark *pwm;
665 nss_tx_status_t nss_tx_status;
666 int ret = NSS_FAILURE;
667
668 /*
669 * Acquiring semaphore
670 */
671 down(&nss_n2h_nepbcfgp[core_num].sem);
672
673 /*
674 * Take snap shot of current value
675 */
676 nss_n2h_nepbcfgp[core_num].empty_paged_buf_pool_info.low_water = *low;
677 nss_n2h_nepbcfgp[core_num].empty_paged_buf_pool_info.high_water = *high;
678
679 if (!write || *low == -1 || *high == -1) {
680 ret = nss_n2h_get_paged_payload_info(core_num);
681 if (ret == NSS_FAILURE) {
682 up(&nss_n2h_nepbcfgp[core_num].sem);
683 return -EBUSY;
684 }
685
686 *low = nss_n2h_nepbcfgp[core_num].empty_paged_buf_pool_info.low_water;
687 *high = nss_n2h_nepbcfgp[core_num].empty_paged_buf_pool_info.high_water;
688 }
689
690 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
691 if (!write || ret) {
692 up(&nss_n2h_nepbcfgp[core_num].sem);
693 return ret;
694 }
695
696 if ((*low < NSS_N2H_MIN_EMPTY_POOL_BUF_SZ) ||
697 (*high < NSS_N2H_MIN_EMPTY_POOL_BUF_SZ)) {
698 nss_warning("%p: core %d setting %d, %d < min number of buffer",
699 nss_ctx, core_num, *low, *high);
700 goto failure;
701 }
702
703 if ((*low > NSS_N2H_MAX_EMPTY_POOL_BUF_SZ) ||
704 (*high > NSS_N2H_MAX_EMPTY_POOL_BUF_SZ)) {
705 nss_warning("%p: core %d setting %d, %d is > upper limit",
706 nss_ctx, core_num, *low, *high);
707 goto failure;
708 }
709
710 if (*low > *high) {
711 nss_warning("%p: core %d setting low %d is more than high %d",
712 nss_ctx, core_num, *low, *high);
713 goto failure;
714 }
715
716 nss_info("%p: core %d number of low : %d and high : %d\n",
717 nss_ctx, core_num, *low, *high);
718
719 nss_n2h_msg_init(&nnm, NSS_N2H_INTERFACE,
720 NSS_TX_METADATA_TYPE_SET_PAGED_WATER_MARK,
721 sizeof(struct nss_n2h_water_mark),
722 nss_n2h_payload_stats_callback,
723 (void *)(nss_ptr_t)core_num);
724
725 pwm = &nnm.msg.wm_paged;
726 pwm->low_water = htonl(*low);
727 pwm->high_water = htonl(*high);
728 nss_tx_status = nss_n2h_tx_msg(nss_ctx, &nnm);
729
730 if (nss_tx_status != NSS_TX_SUCCESS) {
731 nss_warning("%p: core %d nss_tx error setting : %d, %d\n",
732 nss_ctx, core_num, *low, *high);
733 goto failure;
734 }
735
736 /*
737 * Blocking call, wait till we get ACK for this msg.
738 */
739 ret = wait_for_completion_timeout(&nss_n2h_nepbcfgp[core_num].complete,
740 msecs_to_jiffies(NSS_CONN_CFG_TIMEOUT));
741 if (ret == 0) {
742 nss_warning("%p: core %d Waiting for ack timed out\n", nss_ctx,
743 core_num);
744 goto failure;
745 }
746
747 /*
748 * ACK/NACK received from NSS FW
749 */
750 if (NSS_FAILURE == nss_n2h_nepbcfgp[core_num].response)
751 goto failure;
752
753 up(&nss_n2h_nepbcfgp[core_num].sem);
754 return NSS_SUCCESS;
755
756failure:
757 /*
758 * Restore the current_value to its previous state
759 */
760 *low = nss_n2h_nepbcfgp[core_num].empty_paged_buf_pool_info.low_water;
761 *high = nss_n2h_nepbcfgp[core_num].empty_paged_buf_pool_info.high_water;
Stephen Wang06761022015-03-03 16:38:42 -0800762 up(&nss_n2h_nepbcfgp[core_num].sem);
Thomas Wu651b3902015-05-12 11:21:09 -0700763 return -EINVAL;
Vijay Dewangan488e5372014-12-29 21:40:11 -0800764}
765
766/*
Pamidipati, Vijayee9c2972016-01-10 08:13:19 +0530767 * nss_n2h_cfg_wifi_pool()
768 * Sets number of wifi payloads to adjust high water mark for N2H SoS
769 */
Stephen Wang52e6d342016-03-29 15:02:33 -0700770static int nss_n2h_cfg_wifi_pool(struct ctl_table *ctl, int write,
Pamidipati, Vijayee9c2972016-01-10 08:13:19 +0530771 void __user *buffer,
772 size_t *lenp, loff_t *ppos,
773 int *payloads)
774{
775 struct nss_top_instance *nss_top = &nss_top_main;
776 struct nss_ctx_instance *nss_ctx = &nss_top->nss[0];
777 struct nss_n2h_msg nnm;
778 struct nss_n2h_wifi_payloads *wp;
779 nss_tx_status_t nss_tx_status;
780 int ret = NSS_FAILURE;
781
782 /*
783 * Acquiring semaphore
784 */
785 down(&nss_n2h_wp.sem);
786
787 if (!write) {
788 *payloads = nss_n2h_wp.wifi_pool;
789
790 up(&nss_n2h_wp.sem);
791 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
792 return ret;
793 }
794
795 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
796 if (ret) {
797 up(&nss_n2h_wp.sem);
798 return ret;
799 }
800
801 /*
802 * If payloads parameter is not set, we do
803 * nothing.
804 */
805 if (*payloads == -1)
806 goto failure;
807
808 if ((*payloads < NSS_N2H_MIN_EMPTY_POOL_BUF_SZ)) {
809 nss_warning("%p: wifi setting %d < min number of buffer",
810 nss_ctx, *payloads);
811 goto failure;
812 }
813
814 if ((*payloads > NSS_N2H_MAX_EMPTY_POOL_BUF_SZ)) {
815 nss_warning("%p: wifi setting %d > max number of buffer",
816 nss_ctx, *payloads);
817 goto failure;
818 }
819
820 nss_info("%p: wifi payloads : %d\n",
821 nss_ctx, *payloads);
822
823 nss_n2h_msg_init(&nnm, NSS_N2H_INTERFACE,
824 NSS_TX_METADATA_TYPE_N2H_WIFI_POOL_BUF_CFG,
825 sizeof(struct nss_n2h_wifi_payloads),
826 nss_n2h_set_wifi_payloads_callback,
827 (void *)nss_ctx);
828
829 wp = &nnm.msg.wp;
830 wp->payloads = htonl(*payloads);
831 nss_tx_status = nss_n2h_tx_msg(nss_ctx, &nnm);
832
833 if (nss_tx_status != NSS_TX_SUCCESS) {
834 nss_warning("%p: wifi setting %d nss_tx error",
835 nss_ctx, *payloads);
836 goto failure;
837 }
838
839 /*
840 * Blocking call, wait till we get ACK for this msg.
841 */
842 ret = wait_for_completion_timeout(&nss_n2h_wp.complete,
843 msecs_to_jiffies(NSS_CONN_CFG_TIMEOUT));
844 if (ret == 0) {
845 nss_warning("%p: Waiting for ack timed out\n", nss_ctx);
846 goto failure;
847 }
848
849 /*
850 * ACK/NACK received from NSS FW
851 */
852 if (NSS_FAILURE == nss_n2h_wp.response)
853 goto failure;
854
855 up(&nss_n2h_wp.sem);
856 return NSS_SUCCESS;
857
858failure:
859 up(&nss_n2h_wp.sem);
860 return -EINVAL;
861}
862
863/*
Vijay Dewangan488e5372014-12-29 21:40:11 -0800864 * nss_n2h_empty_pool_buf_core1_handler()
865 * Sets the number of empty buffer for core 1
866 */
Stephen Wang52e6d342016-03-29 15:02:33 -0700867static int nss_n2h_empty_pool_buf_cfg_core1_handler(struct ctl_table *ctl,
Saurabh Misra71034db2015-06-04 16:18:38 -0700868 int write, void __user *buffer,
869 size_t *lenp, loff_t *ppos)
Vijay Dewangan488e5372014-12-29 21:40:11 -0800870{
871 return nss_n2h_set_empty_pool_buf(ctl, write, buffer, lenp, ppos,
Saurabh Misra71034db2015-06-04 16:18:38 -0700872 NSS_CORE_1, &nss_n2h_empty_pool_buf_cfg[NSS_CORE_1]);
Vijay Dewangan488e5372014-12-29 21:40:11 -0800873}
874
875/*
876 * nss_n2h_empty_pool_buf_core0_handler()
877 * Sets the number of empty buffer for core 0
878 */
Stephen Wang52e6d342016-03-29 15:02:33 -0700879static int nss_n2h_empty_pool_buf_cfg_core0_handler(struct ctl_table *ctl,
Saurabh Misra71034db2015-06-04 16:18:38 -0700880 int write, void __user *buffer,
881 size_t *lenp, loff_t *ppos)
Vijay Dewangan488e5372014-12-29 21:40:11 -0800882{
883 return nss_n2h_set_empty_pool_buf(ctl, write, buffer, lenp, ppos,
Saurabh Misra71034db2015-06-04 16:18:38 -0700884 NSS_CORE_0, &nss_n2h_empty_pool_buf_cfg[NSS_CORE_0]);
885}
886
887/*
Sachin Shashidhar475012b2017-03-13 16:56:07 -0700888 * nss_n2h_empty_paged_pool_buf_cfg_core1_handler()
889 * Sets the number of empty paged buffer for core 1
890 */
891static int nss_n2h_empty_paged_pool_buf_cfg_core1_handler(struct ctl_table *ctl,
892 int write, void __user *buffer,
893 size_t *lenp, loff_t *ppos)
894{
895 return nss_n2h_set_empty_paged_pool_buf(ctl, write, buffer, lenp, ppos,
896 NSS_CORE_1, &nss_n2h_empty_paged_pool_buf_cfg[NSS_CORE_1]);
897}
898
899/*
900 * nss_n2h_empty_paged_pool_buf_cfg_core0_handler()
901 * Sets the number of empty paged buffer for core 0
902 */
903static int nss_n2h_empty_paged_pool_buf_cfg_core0_handler(struct ctl_table *ctl,
904 int write, void __user *buffer,
905 size_t *lenp, loff_t *ppos)
906{
907 return nss_n2h_set_empty_paged_pool_buf(ctl, write, buffer, lenp, ppos,
908 NSS_CORE_0, &nss_n2h_empty_paged_pool_buf_cfg[NSS_CORE_0]);
909}
910
911/*
Saurabh Misra71034db2015-06-04 16:18:38 -0700912 * nss_n2h_water_mark_core1_handler()
913 * Sets water mark for core 1
914 */
Stephen Wang52e6d342016-03-29 15:02:33 -0700915static int nss_n2h_water_mark_core1_handler(struct ctl_table *ctl,
Saurabh Misra71034db2015-06-04 16:18:38 -0700916 int write, void __user *buffer,
917 size_t *lenp, loff_t *ppos)
918{
919 return nss_n2h_set_water_mark(ctl, write, buffer, lenp, ppos,
920 NSS_CORE_1, &nss_n2h_water_mark[NSS_CORE_1][0],
921 &nss_n2h_water_mark[NSS_CORE_1][1]);
922}
923
924/*
925 * nss_n2h_water_mark_core0_handler()
926 * Sets water mark for core 0
927 */
Stephen Wang52e6d342016-03-29 15:02:33 -0700928static int nss_n2h_water_mark_core0_handler(struct ctl_table *ctl,
Saurabh Misra71034db2015-06-04 16:18:38 -0700929 int write, void __user *buffer,
930 size_t *lenp, loff_t *ppos)
931{
932 return nss_n2h_set_water_mark(ctl, write, buffer, lenp, ppos,
933 NSS_CORE_0, &nss_n2h_water_mark[NSS_CORE_0][0],
934 &nss_n2h_water_mark[NSS_CORE_0][1]);
Vijay Dewangan488e5372014-12-29 21:40:11 -0800935}
936
Vijay Dewangan634ce592015-01-07 17:21:09 -0800937/*
Sachin Shashidhar475012b2017-03-13 16:56:07 -0700938 * nss_n2h_paged_water_mark_core1_handler()
939 * Sets paged water mark for core 1
940 */
941static int nss_n2h_paged_water_mark_core1_handler(struct ctl_table *ctl,
942 int write, void __user *buffer,
943 size_t *lenp, loff_t *ppos)
944{
945 return nss_n2h_set_paged_water_mark(ctl, write, buffer, lenp, ppos,
946 NSS_CORE_1, &nss_n2h_paged_water_mark[NSS_CORE_1][0],
947 &nss_n2h_paged_water_mark[NSS_CORE_1][1]);
948}
949
Sachin Shashidhar475012b2017-03-13 16:56:07 -0700950/*
951 * nss_n2h_paged_water_mark_core0_handler()
952 * Sets paged water mark for core 0
953 */
954static int nss_n2h_paged_water_mark_core0_handler(struct ctl_table *ctl,
955 int write, void __user *buffer,
956 size_t *lenp, loff_t *ppos)
957{
958 return nss_n2h_set_paged_water_mark(ctl, write, buffer, lenp, ppos,
959 NSS_CORE_0, &nss_n2h_paged_water_mark[NSS_CORE_0][0],
960 &nss_n2h_paged_water_mark[NSS_CORE_0][1]);
961}
962
963/*
Pamidipati, Vijayee9c2972016-01-10 08:13:19 +0530964 * nss_n2h_wifi_payloads_handler()
965 * Sets number of wifi payloads
966 */
Stephen Wang52e6d342016-03-29 15:02:33 -0700967static int nss_n2h_wifi_payloads_handler(struct ctl_table *ctl,
Pamidipati, Vijayee9c2972016-01-10 08:13:19 +0530968 int write, void __user *buffer,
969 size_t *lenp, loff_t *ppos)
970{
971 return nss_n2h_cfg_wifi_pool(ctl, write, buffer, lenp, ppos,
972 &nss_n2h_wifi_pool_buf_cfg);
973}
974
975/*
ratheesh kannothab436af2017-07-20 08:51:07 +0530976 * nss_n2h_update_queue_config_callback()
977 * Callback to handle the completion of queue config command
ratheesh kannoth024a6e82017-05-18 17:48:10 +0530978 */
ratheesh kannothab436af2017-07-20 08:51:07 +0530979static void nss_n2h_update_queue_config_callback(void *app_data, struct nss_n2h_msg *nim)
ratheesh kannoth024a6e82017-05-18 17:48:10 +0530980{
ratheesh kannothab436af2017-07-20 08:51:07 +0530981 if (nim->cm.response != NSS_CMN_RESPONSE_ACK) {
982 nss_warning("n2h Error response %d\n", nim->cm.response);
983 nss_n2h_q_cfg_pvt.response = NSS_TX_FAILURE;
984 } else {
985 nss_n2h_q_cfg_pvt.response = NSS_TX_SUCCESS;
986 }
987
988 complete(&nss_n2h_q_cfg_pvt.complete);
989}
990
991/*
992 * nss_n2h_update_queue_config_async()
993 * Asynchronous call to send pnode queue configuration.
994 */
995nss_tx_status_t nss_n2h_update_queue_config_async(struct nss_ctx_instance *nss_ctx, bool mq_en, uint16_t *qlimits)
996{
997
ratheesh kannoth024a6e82017-05-18 17:48:10 +0530998 struct nss_n2h_msg nnm;
999 struct nss_n2h_pnode_queue_config *cfg;
1000 nss_tx_status_t status;
ratheesh kannoth024a6e82017-05-18 17:48:10 +05301001 int i;
1002
1003 if (!mq_en) {
1004 return NSS_TX_SUCCESS;
1005 }
1006
ratheesh kannoth93ba95c2017-07-13 15:52:52 +05301007 /*
1008 * MQ mode doesnot make any sense if number of priority queues in NSS
1009 * is 1
1010 */
1011 if (NSS_MAX_NUM_PRI <= 1) {
1012 return NSS_TX_SUCCESS;
1013 }
1014
ratheesh kannothab436af2017-07-20 08:51:07 +05301015 memset(&nnm, 0, sizeof(struct nss_n2h_msg));
ratheesh kannoth024a6e82017-05-18 17:48:10 +05301016
ratheesh kannoth024a6e82017-05-18 17:48:10 +05301017 nss_n2h_msg_init(&nnm, NSS_N2H_INTERFACE,
1018 NSS_TX_METADATA_TYPE_N2H_SET_PNODE_QUEUE_CFG,
1019 sizeof(struct nss_n2h_pnode_queue_config), NULL, 0);
1020
ratheesh kannothab436af2017-07-20 08:51:07 +05301021 cfg = &nnm.msg.pn_q_cfg;
1022
1023 /*
Cemil Coskun9165c762017-12-04 14:35:24 -08001024 * Update limits
1025 */
ratheesh kannothab436af2017-07-20 08:51:07 +05301026 for (i = 0; i < NSS_MAX_NUM_PRI; i++) {
1027 cfg->qlimits[i] = qlimits[i];
1028 }
1029 cfg->mq_en = true;
1030
ratheesh kannoth024a6e82017-05-18 17:48:10 +05301031 status = nss_n2h_tx_msg(nss_ctx, &nnm);
1032 if (status != NSS_TX_SUCCESS) {
1033 nss_warning("%p: nss_tx error to send pnode queue config\n", nss_ctx);
1034 return status;
1035 }
1036
1037 return NSS_TX_SUCCESS;
ratheesh kannoth024a6e82017-05-18 17:48:10 +05301038}
ratheesh kannothab436af2017-07-20 08:51:07 +05301039EXPORT_SYMBOL(nss_n2h_update_queue_config_async);
1040
1041/*
1042 * nss_n2h_update_queue_config_sync()
1043 * Synchronous call to send pnode queue configuration.
1044 */
1045nss_tx_status_t nss_n2h_update_queue_config_sync(struct nss_ctx_instance *nss_ctx, bool mq_en, uint16_t *qlimits)
1046{
1047
1048 struct nss_n2h_msg nnm;
1049 struct nss_n2h_pnode_queue_config *cfg;
1050 nss_tx_status_t status;
1051 int ret, i;
1052
1053 if (!mq_en) {
1054 return NSS_TX_SUCCESS;
1055 }
1056
ratheesh kannoth93ba95c2017-07-13 15:52:52 +05301057 /*
1058 * MQ mode doesnot make any sense if number of priority queues in NSS
1059 * is 1
1060 */
1061 if (NSS_MAX_NUM_PRI <= 1) {
1062 return NSS_TX_SUCCESS;
1063 }
1064
ratheesh kannothab436af2017-07-20 08:51:07 +05301065 memset(&nnm, 0, sizeof(struct nss_n2h_msg));
1066
1067 nss_n2h_msg_init(&nnm, NSS_N2H_INTERFACE,
1068 NSS_TX_METADATA_TYPE_N2H_SET_PNODE_QUEUE_CFG,
1069 sizeof(struct nss_n2h_pnode_queue_config), nss_n2h_update_queue_config_callback, 0);
1070
1071 cfg = &nnm.msg.pn_q_cfg;
1072
1073 /*
Cemil Coskun9165c762017-12-04 14:35:24 -08001074 * Update limits
1075 */
ratheesh kannothab436af2017-07-20 08:51:07 +05301076 for (i = 0; i < NSS_MAX_NUM_PRI; i++) {
1077 cfg->qlimits[i] = qlimits[i];
1078 }
1079 cfg->mq_en = true;
1080
1081 down(&nss_n2h_q_cfg_pvt.sem);
1082
1083 status = nss_n2h_tx_msg(nss_ctx, &nnm);
1084
1085 if (status != NSS_TX_SUCCESS) {
1086 nss_warning("%p: n2h_tx_msg failed\n", nss_ctx);
1087 up(&nss_n2h_q_cfg_pvt.sem);
1088 return status;
1089 }
1090 ret = wait_for_completion_timeout(&nss_n2h_q_cfg_pvt.complete, msecs_to_jiffies(NSS_N2H_TX_TIMEOUT));
1091
1092 if (!ret) {
1093 nss_warning("%p: Timeout expired for pnode queue config sync message\n", nss_ctx);
1094 nss_n2h_q_cfg_pvt.response = NSS_TX_FAILURE;
1095 }
1096
1097 status = nss_n2h_q_cfg_pvt.response;
1098 up(&nss_n2h_q_cfg_pvt.sem);
1099 return status;
1100}
1101EXPORT_SYMBOL(nss_n2h_update_queue_config_sync);
ratheesh kannoth024a6e82017-05-18 17:48:10 +05301102
1103/*
Kalyan Tallapragadab50e8902015-08-06 17:00:54 +05301104 * nss_n2h_mitigation_cfg()
1105 * Send Message to NSS to disable MITIGATION.
1106 */
Stephen Wang49b474b2016-03-25 10:40:30 -07001107static 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 +05301108{
1109 struct nss_n2h_msg nnm;
1110 struct nss_n2h_mitigation *mitigation_cfg;
1111 nss_tx_status_t nss_tx_status;
1112 int ret;
1113
1114 nss_assert(core_num < NSS_CORE_MAX);
1115
1116 down(&nss_n2h_mitigationcp[core_num].sem);
1117 nss_n2h_msg_init(&nnm, NSS_N2H_INTERFACE, NSS_TX_METADATA_TYPE_N2H_MITIGATION_CFG,
1118 sizeof(struct nss_n2h_mitigation),
1119 nss_n2h_mitigation_cfg_callback,
1120 (void *)core_num);
1121
1122 mitigation_cfg = &nnm.msg.mitigation_cfg;
1123 mitigation_cfg->enable = enable_mitigation;
1124
1125 nss_tx_status = nss_n2h_tx_msg(nss_ctx, &nnm);
1126
1127 if (nss_tx_status != NSS_TX_SUCCESS) {
1128 nss_warning("%p: nss_tx error setting mitigation\n", nss_ctx);
1129 goto failure;
1130 }
1131
1132 /*
1133 * Blocking call, wait till we get ACK for this msg.
1134 */
1135 ret = wait_for_completion_timeout(&nss_n2h_mitigationcp[core_num].complete, msecs_to_jiffies(NSS_CONN_CFG_TIMEOUT));
1136 if (ret == 0) {
1137 nss_warning("%p: Waiting for ack timed out\n", nss_ctx);
1138 goto failure;
1139 }
1140
1141 /*
1142 * ACK/NACK received from NSS FW
1143 */
1144 if (NSS_FAILURE == nss_n2h_mitigationcp[core_num].response) {
1145 goto failure;
1146 }
1147
1148 up(&nss_n2h_mitigationcp[core_num].sem);
1149 return NSS_SUCCESS;
1150
1151failure:
1152 up(&nss_n2h_mitigationcp[core_num].sem);
1153 return NSS_FAILURE;
1154}
1155
1156static inline void nss_n2h_buf_pool_free(struct nss_n2h_buf_pool *buf_pool)
1157{
1158 int page_count;
1159 for (page_count = 0; page_count < buf_pool->nss_buf_num_pages; page_count++) {
Stephen Wang7df68832017-08-10 16:54:35 -07001160 kfree((void *)buf_pool->nss_buf_pool_vaddr[page_count]);
Kalyan Tallapragadab50e8902015-08-06 17:00:54 +05301161 }
1162}
1163
1164/*
1165 * nss_n2h_buf_cfg()
1166 * Send Message to NSS to enable pbufs.
1167 */
Stephen Wang49b474b2016-03-25 10:40:30 -07001168static nss_tx_status_t nss_n2h_buf_pool_cfg(struct nss_ctx_instance *nss_ctx,
Tallapragada4b0161b2016-07-07 21:38:34 +05301169 int buf_pool_size, nss_core_id_t core_num)
Kalyan Tallapragadab50e8902015-08-06 17:00:54 +05301170{
1171 static struct nss_n2h_msg nnm;
1172 struct nss_n2h_buf_pool *buf_pool;
1173 nss_tx_status_t nss_tx_status;
1174 int ret;
1175 int page_count;
1176 int num_pages = ALIGN(buf_pool_size, PAGE_SIZE)/PAGE_SIZE;
1177
1178 nss_assert(core_num < NSS_CORE_MAX);
1179
1180 nss_n2h_msg_init(&nnm, NSS_N2H_INTERFACE, NSS_METADATA_TYPE_N2H_ADD_BUF_POOL,
1181 sizeof(struct nss_n2h_buf_pool),
1182 nss_n2h_bufs_cfg_callback,
1183 (void *)core_num);
1184
1185 do {
1186
1187 down(&nss_n2h_bufcp[core_num].sem);
1188
1189 buf_pool = &nnm.msg.buf_pool;
1190 buf_pool->nss_buf_page_size = PAGE_SIZE;
1191
1192 for (page_count = 0; page_count < MAX_PAGES_PER_MSG && num_pages; page_count++, num_pages--) {
Kalyan Tallapragadab50e8902015-08-06 17:00:54 +05301193 void *kern_addr = kzalloc(PAGE_SIZE, GFP_ATOMIC);
1194 if (!kern_addr) {
1195 BUG_ON(!page_count);
1196 break;
1197 }
Kalyan Tallapragadab50e8902015-08-06 17:00:54 +05301198
Radha krishna Simha Jiguru60068fb2017-07-28 17:40:52 +05301199 kmemleak_not_leak(kern_addr);
Stephen Wang7df68832017-08-10 16:54:35 -07001200 buf_pool->nss_buf_pool_vaddr[page_count] = (nss_ptr_t)kern_addr;
Stephen Wangefd38512017-01-24 14:01:02 -08001201 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 +05301202 }
1203
1204 buf_pool->nss_buf_num_pages = page_count;
1205 nss_tx_status = nss_n2h_tx_msg(nss_ctx, &nnm);
1206 if (nss_tx_status != NSS_TX_SUCCESS) {
1207
1208 nss_n2h_buf_pool_free(buf_pool);
1209 nss_warning("%p: nss_tx error setting pbuf\n", nss_ctx);
1210 goto failure;
1211 }
1212
1213 /*
Cemil Coskun9165c762017-12-04 14:35:24 -08001214 * Blocking call, wait till we get ACK for this msg.
1215 */
Kalyan Tallapragadab50e8902015-08-06 17:00:54 +05301216 ret = wait_for_completion_timeout(&nss_n2h_bufcp[core_num].complete, msecs_to_jiffies(NSS_CONN_CFG_TIMEOUT));
1217 if (ret == 0) {
1218 nss_warning("%p: Waiting for ack timed out\n", nss_ctx);
1219 goto failure;
1220 }
1221
1222 /*
1223 * ACK/NACK received from NSS FW
1224 */
1225 if (NSS_FAILURE == nss_n2h_bufcp[core_num].response) {
1226
1227 nss_n2h_buf_pool_free(buf_pool);
1228 goto failure;
1229 }
1230
1231 up(&nss_n2h_bufcp[core_num].sem);
1232 } while(num_pages);
1233
1234 return NSS_SUCCESS;
1235failure:
1236 up(&nss_n2h_bufcp[core_num].sem);
1237 return NSS_FAILURE;
1238}
1239
Stephen Wang49b474b2016-03-25 10:40:30 -07001240
1241/*
1242 * nss_mitigation_handler()
1243 * Enable NSS MITIGATION
1244 */
Stephen Wang52e6d342016-03-29 15:02:33 -07001245static 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 -07001246{
1247 struct nss_top_instance *nss_top = &nss_top_main;
1248 struct nss_ctx_instance *nss_ctx = &nss_top->nss[NSS_CORE_0];
1249 int ret;
1250
1251 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
1252 if (ret) {
1253 return ret;
1254 }
1255
1256 /*
1257 * It's a read operation
1258 */
1259 if (!write) {
1260 return ret;
1261 }
1262
1263 if (!nss_n2h_core0_mitigation_cfg) {
1264 printk(KERN_INFO "Disabling NSS MITIGATION\n");
1265 nss_n2h_mitigation_cfg(nss_ctx, 0, NSS_CORE_0);
1266 return 0;
1267 }
1268 printk(KERN_INFO "Invalid input value.Valid value is 0, Runtime re-enabling not supported\n");
1269 return -EINVAL;
1270}
1271
1272/*
1273 * nss_mitigation_handler()
1274 * Enable NSS MITIGATION
1275 */
Stephen Wang52e6d342016-03-29 15:02:33 -07001276static 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 -07001277{
1278 struct nss_top_instance *nss_top = &nss_top_main;
1279 struct nss_ctx_instance *nss_ctx = &nss_top->nss[NSS_CORE_1];
1280 int ret;
1281
1282 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
1283 if (ret) {
1284 return ret;
1285 }
1286
1287 /*
1288 * It's a read operation
1289 */
1290 if (!write) {
1291 return ret;
1292 }
1293
1294 if (!nss_n2h_core1_mitigation_cfg) {
1295 printk(KERN_INFO "Disabling NSS MITIGATION\n");
1296 nss_n2h_mitigation_cfg(nss_ctx, 0, NSS_CORE_1);
1297 return 0;
1298 }
1299 printk(KERN_INFO "Invalid input value.Valid value is 0, Runtime re-enabling not supported\n");
1300 return -EINVAL;
1301}
1302
1303/*
1304 * nss_buf_handler()
1305 * Add extra NSS bufs from host memory
1306 */
Stephen Wang52e6d342016-03-29 15:02:33 -07001307static 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 -07001308{
1309 struct nss_top_instance *nss_top = &nss_top_main;
1310 struct nss_ctx_instance *nss_ctx = &nss_top->nss[NSS_CORE_0];
1311 int ret;
1312
1313 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
1314 if (ret) {
1315 return ret;
1316 }
1317
1318 /*
1319 * It's a read operation
1320 */
1321 if (!write) {
1322 return ret;
1323 }
1324
1325 if (nss_ctx->buf_sz_allocated) {
1326 nss_n2h_core0_add_buf_pool_size = nss_ctx->buf_sz_allocated;
1327 return -EPERM;
1328 }
1329
1330 if ((nss_n2h_core0_add_buf_pool_size >= 1) && (nss_n2h_core0_add_buf_pool_size <= NSS_N2H_MAX_BUF_POOL_SIZE)) {
1331 printk(KERN_INFO "configuring additional NSS pbufs\n");
1332 ret = nss_n2h_buf_pool_cfg(nss_ctx, nss_n2h_core0_add_buf_pool_size, NSS_CORE_0);
1333 nss_n2h_core0_add_buf_pool_size = nss_ctx->buf_sz_allocated;
1334 printk(KERN_INFO "additional pbufs of size %d got added to NSS\n", nss_ctx->buf_sz_allocated);
1335 return ret;
1336 }
1337
1338 printk(KERN_INFO "Invalid input value. should be greater than 1 and less than %d\n", NSS_N2H_MAX_BUF_POOL_SIZE);
1339 return -EINVAL;
1340}
1341
1342/*
1343 * nss_n2h_buf_handler()
1344 * Add extra NSS bufs from host memory
1345 */
Stephen Wang52e6d342016-03-29 15:02:33 -07001346static 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 -07001347{
1348 struct nss_top_instance *nss_top = &nss_top_main;
1349 struct nss_ctx_instance *nss_ctx = &nss_top->nss[NSS_CORE_1];
1350 int ret;
1351
1352 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
1353 if (ret) {
1354 return ret;
1355 }
1356
1357 /*
1358 * It's a read operation
1359 */
1360 if (!write) {
1361 return ret;
1362 }
1363
1364 if (nss_ctx->buf_sz_allocated) {
1365 nss_n2h_core1_add_buf_pool_size = nss_ctx->buf_sz_allocated;
1366 return -EPERM;
1367 }
1368
1369 if ((nss_n2h_core1_add_buf_pool_size >= 1) && (nss_n2h_core1_add_buf_pool_size <= NSS_N2H_MAX_BUF_POOL_SIZE)) {
1370 printk(KERN_INFO "configuring additional NSS pbufs\n");
1371 ret = nss_n2h_buf_pool_cfg(nss_ctx, nss_n2h_core1_add_buf_pool_size, NSS_CORE_1);
1372 nss_n2h_core1_add_buf_pool_size = nss_ctx->buf_sz_allocated;
1373 printk(KERN_INFO "additional pbufs of size %d got added to NSS\n", nss_ctx->buf_sz_allocated);
1374 return ret;
1375 }
1376
1377 printk(KERN_INFO "Invalid input value. should be greater than 1 and less than %d\n", NSS_N2H_MAX_BUF_POOL_SIZE);
1378 return -EINVAL;
1379}
Kalyan Tallapragadab50e8902015-08-06 17:00:54 +05301380
Shashank Balashankar4162f572018-08-21 13:32:34 -07001381/*
1382 * nss_n2h_queue_limit_callback()
1383 * Callback to handle the completion of queue limit command.
1384 */
1385static void nss_n2h_queue_limit_callback(void *app_data, struct nss_n2h_msg *nim)
1386{
1387 if (nim->cm.response != NSS_CMN_RESPONSE_ACK) {
1388 nss_warning("n2h error response %d\n", nim->cm.response);
1389 }
1390
1391 nss_n2h_q_lim_pvt.response = nim->cm.response;
1392 complete(&nss_n2h_q_lim_pvt.complete);
1393}
1394
1395/*
1396 * nss_n2h_set_queue_limit_sync()
1397 * Sets the n2h queue size limit synchronously.
1398 */
1399static int nss_n2h_set_queue_limit_sync(struct ctl_table *ctl, int write, void __user *buffer,
1400 size_t *lenp, loff_t *ppos, uint32_t core_id)
1401{
1402 struct nss_top_instance *nss_top = &nss_top_main;
1403 struct nss_ctx_instance *nss_ctx = &nss_top->nss[core_id];
1404 struct nss_n2h_msg nim;
1405 struct nss_n2h_queue_limit_config *nnqlc = NULL;
1406 int ret, current_val;
1407 nss_tx_status_t nss_tx_status;
1408
1409 /*
1410 * Take a snap shot of current value
1411 */
1412 current_val = nss_n2h_queue_limit[core_id];
1413
1414 /*
1415 * Write the variable with user input
1416 */
1417 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
1418 if (ret || (!write)) {
1419 return ret;
1420 }
1421
1422 /*
1423 * We dont allow shortening of the queue size at run-time
1424 */
1425 if (nss_n2h_queue_limit[core_id] < current_val) {
1426 nss_warning("%p: New queue limit %d less than previous value %d. Cant allow shortening\n",
1427 nss_ctx, nss_n2h_queue_limit[core_id], current_val);
1428 nss_n2h_queue_limit[core_id] = current_val;
1429 return NSS_TX_FAILURE;
1430 }
1431
1432 memset(&nim, 0, sizeof(struct nss_n2h_msg));
1433 nss_n2h_msg_init(&nim, NSS_N2H_INTERFACE,
1434 NSS_TX_METADATA_TYPE_N2H_QUEUE_LIMIT_CFG,
1435 sizeof(struct nss_n2h_queue_limit_config), nss_n2h_queue_limit_callback, NULL);
1436
1437 nnqlc = &nim.msg.ql_cfg;
1438 nnqlc->qlimit = nss_n2h_queue_limit[core_id];
1439
1440 /*
1441 * Send synchronous message to firmware
1442 */
1443 down(&nss_n2h_q_lim_pvt.sem);
1444
1445 nss_tx_status = nss_n2h_tx_msg(nss_ctx, &nim);
1446 if (nss_tx_status != NSS_TX_SUCCESS) {
1447 nss_warning("%p: n2h queue limit message send failed\n", nss_ctx);
1448 nss_n2h_queue_limit[core_id] = current_val;
1449 up(&nss_n2h_q_lim_pvt.sem);
1450 return nss_tx_status;
1451 }
1452
1453 ret = wait_for_completion_timeout(&nss_n2h_q_lim_pvt.complete, msecs_to_jiffies(NSS_N2H_TX_TIMEOUT));
1454 if (!ret) {
1455 nss_warning("%p: Timeout expired for queue limit sync message\n", nss_ctx);
1456 nss_n2h_queue_limit[core_id] = current_val;
1457 up(&nss_n2h_q_lim_pvt.sem);
1458 return NSS_TX_FAILURE;
1459 }
1460
1461 /*
1462 * If setting the queue limit failed, reset the value to original value
1463 */
1464 if (nss_n2h_q_lim_pvt.response != NSS_CMN_RESPONSE_ACK) {
1465 nss_n2h_queue_limit[core_id] = current_val;
1466 }
1467
1468 up(&nss_n2h_q_lim_pvt.sem);
1469 return NSS_TX_SUCCESS;
1470}
1471
1472/*
1473 * nss_n2h_queue_limit_core0_handler()
1474 * Sets the n2h queue size limit for core0
1475 */
1476static int nss_n2h_queue_limit_core0_handler(struct ctl_table *ctl,
1477 int write, void __user *buffer,
1478 size_t *lenp, loff_t *ppos)
1479{
1480 return nss_n2h_set_queue_limit_sync(ctl, write, buffer, lenp, ppos,
1481 NSS_CORE_0);
1482}
1483
1484/*
1485 * nss_n2h_queue_limit_core1_handler()
1486 * Sets the n2h queue size limit for core1
1487 */
1488static int nss_n2h_queue_limit_core1_handler(struct ctl_table *ctl,
1489 int write, void __user *buffer,
1490 size_t *lenp, loff_t *ppos)
1491{
1492 return nss_n2h_set_queue_limit_sync(ctl, write, buffer, lenp, ppos,
1493 NSS_CORE_1);
1494}
1495
Stephen Wang52e6d342016-03-29 15:02:33 -07001496static struct ctl_table nss_n2h_table[] = {
Vijay Dewangan488e5372014-12-29 21:40:11 -08001497 {
Saurabh Misra71034db2015-06-04 16:18:38 -07001498 .procname = "n2h_empty_pool_buf_core0",
1499 .data = &nss_n2h_empty_pool_buf_cfg[NSS_CORE_0],
1500 .maxlen = sizeof(int),
1501 .mode = 0644,
1502 .proc_handler = &nss_n2h_empty_pool_buf_cfg_core0_handler,
Vijay Dewangan488e5372014-12-29 21:40:11 -08001503 },
1504 {
Saurabh Misra71034db2015-06-04 16:18:38 -07001505 .procname = "n2h_empty_pool_buf_core1",
1506 .data = &nss_n2h_empty_pool_buf_cfg[NSS_CORE_1],
1507 .maxlen = sizeof(int),
1508 .mode = 0644,
1509 .proc_handler = &nss_n2h_empty_pool_buf_cfg_core1_handler,
1510 },
1511 {
Sachin Shashidhar475012b2017-03-13 16:56:07 -07001512 .procname = "n2h_empty_paged_pool_buf_core0",
1513 .data = &nss_n2h_empty_paged_pool_buf_cfg[NSS_CORE_0],
1514 .maxlen = sizeof(int),
1515 .mode = 0644,
1516 .proc_handler = &nss_n2h_empty_paged_pool_buf_cfg_core0_handler,
1517 },
1518 {
1519 .procname = "n2h_empty_paged_pool_buf_core1",
1520 .data = &nss_n2h_empty_paged_pool_buf_cfg[NSS_CORE_1],
1521 .maxlen = sizeof(int),
1522 .mode = 0644,
1523 .proc_handler = &nss_n2h_empty_paged_pool_buf_cfg_core1_handler,
1524 },
1525
1526 {
Saurabh Misra71034db2015-06-04 16:18:38 -07001527 .procname = "n2h_low_water_core0",
1528 .data = &nss_n2h_water_mark[NSS_CORE_0][0],
1529 .maxlen = sizeof(int),
1530 .mode = 0644,
1531 .proc_handler = &nss_n2h_water_mark_core0_handler,
1532 },
1533 {
1534 .procname = "n2h_low_water_core1",
1535 .data = &nss_n2h_water_mark[NSS_CORE_1][0],
1536 .maxlen = sizeof(int),
1537 .mode = 0644,
1538 .proc_handler = &nss_n2h_water_mark_core1_handler,
1539 },
1540 {
1541 .procname = "n2h_high_water_core0",
1542 .data = &nss_n2h_water_mark[NSS_CORE_0][1],
1543 .maxlen = sizeof(int),
1544 .mode = 0644,
1545 .proc_handler = &nss_n2h_water_mark_core0_handler,
1546 },
1547 {
1548 .procname = "n2h_high_water_core1",
1549 .data = &nss_n2h_water_mark[NSS_CORE_1][1],
1550 .maxlen = sizeof(int),
1551 .mode = 0644,
1552 .proc_handler = &nss_n2h_water_mark_core1_handler,
Vijay Dewangan488e5372014-12-29 21:40:11 -08001553 },
Pamidipati, Vijayee9c2972016-01-10 08:13:19 +05301554 {
Sachin Shashidhar475012b2017-03-13 16:56:07 -07001555 .procname = "n2h_paged_low_water_core0",
1556 .data = &nss_n2h_paged_water_mark[NSS_CORE_0][0],
1557 .maxlen = sizeof(int),
1558 .mode = 0644,
1559 .proc_handler = &nss_n2h_paged_water_mark_core0_handler,
1560 },
1561 {
1562 .procname = "n2h_paged_low_water_core1",
1563 .data = &nss_n2h_paged_water_mark[NSS_CORE_1][0],
1564 .maxlen = sizeof(int),
1565 .mode = 0644,
1566 .proc_handler = &nss_n2h_paged_water_mark_core1_handler,
1567 },
1568 {
1569 .procname = "n2h_paged_high_water_core0",
1570 .data = &nss_n2h_paged_water_mark[NSS_CORE_0][1],
1571 .maxlen = sizeof(int),
1572 .mode = 0644,
1573 .proc_handler = &nss_n2h_paged_water_mark_core0_handler,
1574 },
1575 {
1576 .procname = "n2h_paged_high_water_core1",
1577 .data = &nss_n2h_paged_water_mark[NSS_CORE_1][1],
1578 .maxlen = sizeof(int),
1579 .mode = 0644,
1580 .proc_handler = &nss_n2h_paged_water_mark_core1_handler,
1581 },
1582 {
Pamidipati, Vijayee9c2972016-01-10 08:13:19 +05301583 .procname = "n2h_wifi_pool_buf",
1584 .data = &nss_n2h_wifi_pool_buf_cfg,
1585 .maxlen = sizeof(int),
1586 .mode = 0644,
1587 .proc_handler = &nss_n2h_wifi_payloads_handler,
1588 },
Stephen Wang49b474b2016-03-25 10:40:30 -07001589 {
Stephen Wang49b474b2016-03-25 10:40:30 -07001590 .procname = "mitigation_core0",
1591 .data = &nss_n2h_core0_mitigation_cfg,
1592 .maxlen = sizeof(int),
1593 .mode = 0644,
1594 .proc_handler = &nss_n2h_mitigationcfg_core0_handler,
1595 },
1596 {
1597 .procname = "mitigation_core1",
1598 .data = &nss_n2h_core1_mitigation_cfg,
1599 .maxlen = sizeof(int),
1600 .mode = 0644,
1601 .proc_handler = &nss_n2h_mitigationcfg_core1_handler,
1602 },
1603 {
1604 .procname = "extra_pbuf_core0",
1605 .data = &nss_n2h_core0_add_buf_pool_size,
1606 .maxlen = sizeof(int),
1607 .mode = 0644,
1608 .proc_handler = &nss_n2h_buf_cfg_core0_handler,
1609 },
1610 {
1611 .procname = "extra_pbuf_core1",
1612 .data = &nss_n2h_core1_add_buf_pool_size,
1613 .maxlen = sizeof(int),
1614 .mode = 0644,
1615 .proc_handler = &nss_n2h_buf_cfg_core1_handler,
1616 },
Shashank Balashankar4162f572018-08-21 13:32:34 -07001617 {
1618 .procname = "n2h_queue_limit_core0",
1619 .data = &nss_n2h_queue_limit[NSS_CORE_0],
1620 .maxlen = sizeof(int),
1621 .mode = 0644,
1622 .proc_handler = &nss_n2h_queue_limit_core0_handler,
1623 },
1624 {
1625 .procname = "n2h_queue_limit_core1",
1626 .data = &nss_n2h_queue_limit[NSS_CORE_1],
1627 .maxlen = sizeof(int),
1628 .mode = 0644,
1629 .proc_handler = &nss_n2h_queue_limit_core1_handler,
1630 },
Vijay Dewangan488e5372014-12-29 21:40:11 -08001631
1632 { }
1633};
1634
Stephen Wang52e6d342016-03-29 15:02:33 -07001635static struct ctl_table nss_n2h_dir[] = {
Vijay Dewangan488e5372014-12-29 21:40:11 -08001636 {
1637 .procname = "n2hcfg",
1638 .mode = 0555,
1639 .child = nss_n2h_table,
1640 },
1641 { }
1642};
1643
Stephen Wang52e6d342016-03-29 15:02:33 -07001644static struct ctl_table nss_n2h_root_dir[] = {
Vijay Dewangan488e5372014-12-29 21:40:11 -08001645 {
1646 .procname = "nss",
1647 .mode = 0555,
1648 .child = nss_n2h_dir,
1649 },
1650 { }
1651};
1652
Stephen Wang52e6d342016-03-29 15:02:33 -07001653static struct ctl_table nss_n2h_root[] = {
Vijay Dewangan488e5372014-12-29 21:40:11 -08001654 {
1655 .procname = "dev",
1656 .mode = 0555,
1657 .child = nss_n2h_root_dir,
1658 },
1659 { }
1660};
1661
1662static struct ctl_table_header *nss_n2h_header;
1663
1664/*
Stephen Wang49b474b2016-03-25 10:40:30 -07001665 * nss_n2h_flush_payloads()
Cemil Coskun9165c762017-12-04 14:35:24 -08001666 * Sends a command down to NSS for flushing all payloads
Stephen Wang49b474b2016-03-25 10:40:30 -07001667 */
1668nss_tx_status_t nss_n2h_flush_payloads(struct nss_ctx_instance *nss_ctx)
1669{
1670 struct nss_n2h_msg nnm;
1671 struct nss_n2h_flush_payloads *nnflshpl;
1672 nss_tx_status_t nss_tx_status;
1673
1674 nnflshpl = &nnm.msg.flush_payloads;
1675
1676 /*
1677 * TODO: No additional information sent in message
1678 * as of now. Need to initialize message content accordingly
1679 * if needed.
1680 */
1681 nss_n2h_msg_init(&nnm, NSS_N2H_INTERFACE,
1682 NSS_TX_METADATA_TYPE_N2H_FLUSH_PAYLOADS,
1683 sizeof(struct nss_n2h_flush_payloads),
1684 NULL,
1685 NULL);
1686
1687 nss_tx_status = nss_n2h_tx_msg(nss_ctx, &nnm);
1688 if (nss_tx_status != NSS_TX_SUCCESS) {
1689 nss_warning("%p: failed to send flush payloads command to NSS\n",
1690 nss_ctx);
1691
1692 return NSS_TX_FAILURE;
1693 }
1694
1695 return NSS_TX_SUCCESS;
1696}
1697
1698/*
Vijay Dewangan488e5372014-12-29 21:40:11 -08001699 * nss_n2h_msg_init()
Stephen Wang49b474b2016-03-25 10:40:30 -07001700 * Initialize n2h message.
Vijay Dewangan488e5372014-12-29 21:40:11 -08001701 */
1702void nss_n2h_msg_init(struct nss_n2h_msg *nim, uint16_t if_num, uint32_t type,
Vijay Dewangan634ce592015-01-07 17:21:09 -08001703 uint32_t len, nss_n2h_msg_callback_t cb, void *app_data)
Vijay Dewangan488e5372014-12-29 21:40:11 -08001704{
1705 nss_cmn_msg_init(&nim->cm, if_num, type, len, (void *)cb, app_data);
1706}
1707
Vijay Dewangan488e5372014-12-29 21:40:11 -08001708/*
Vijay Dewangan488e5372014-12-29 21:40:11 -08001709 * nss_n2h_tx_msg()
Cemil Coskun9165c762017-12-04 14:35:24 -08001710 * Send messages to NSS n2h package.
Vijay Dewangan488e5372014-12-29 21:40:11 -08001711 */
1712nss_tx_status_t nss_n2h_tx_msg(struct nss_ctx_instance *nss_ctx, struct nss_n2h_msg *nnm)
1713{
Vijay Dewangan488e5372014-12-29 21:40:11 -08001714 struct nss_cmn_msg *ncm = &nnm->cm;
Vijay Dewangan488e5372014-12-29 21:40:11 -08001715
1716 /*
1717 * Sanity check the message
1718 */
1719 if (ncm->interface != NSS_N2H_INTERFACE) {
1720 nss_warning("%p: tx request for another interface: %d", nss_ctx, ncm->interface);
1721 return NSS_TX_FAILURE;
1722 }
1723
1724 if (ncm->type >= NSS_METADATA_TYPE_N2H_MAX) {
1725 nss_warning("%p: message type out of range: %d", nss_ctx, ncm->type);
1726 return NSS_TX_FAILURE;
1727 }
1728
Stephen Wang3e2dbd12018-03-14 17:28:17 -07001729 return nss_core_send_cmd(nss_ctx, nnm, sizeof(*nnm), NSS_NBUF_PAYLOAD_SIZE);
Vijay Dewangan488e5372014-12-29 21:40:11 -08001730}
1731
Vijay Dewangan488e5372014-12-29 21:40:11 -08001732/*
1733 * nss_n2h_notify_register()
1734 * Register to received N2H events.
1735 *
1736 * NOTE: Do we want to pass an nss_ctx here so that we can register for n2h on any core?
1737 */
1738struct nss_ctx_instance *nss_n2h_notify_register(int core, nss_n2h_msg_callback_t cb, void *app_data)
1739{
1740 if (core >= NSS_MAX_CORES) {
1741 nss_warning("Input core number %d is wrong \n", core);
1742 return NULL;
1743 }
1744 /*
1745 * TODO: We need to have a new array in support of the new API
1746 * TODO: If we use a per-context array, we would move the array into nss_ctx based.
1747 */
1748 nss_n2h_rd[core].n2h_callback = cb;
1749 nss_n2h_rd[core].app_data = app_data;
1750 return &nss_top_main.nss[core];
Abhishek Rastogi84d95d02014-03-26 19:31:31 +05301751}
1752
1753/*
1754 * nss_n2h_register_handler()
1755 */
Thomas Wu91f4bdf2017-06-09 12:03:02 -07001756void nss_n2h_register_handler(struct nss_ctx_instance *nss_ctx)
Abhishek Rastogi84d95d02014-03-26 19:31:31 +05301757{
ratheesh kannothab436af2017-07-20 08:51:07 +05301758 sema_init(&nss_n2h_q_cfg_pvt.sem, 1);
1759 init_completion(&nss_n2h_q_cfg_pvt.complete);
1760
Thomas Wu91f4bdf2017-06-09 12:03:02 -07001761 nss_core_register_handler(nss_ctx, NSS_N2H_INTERFACE, nss_n2h_interface_handler, NULL);
Yu Huang8c107082017-07-24 14:58:26 -07001762
1763 nss_n2h_stats_dentry_create();
Stephen Wang49b474b2016-03-25 10:40:30 -07001764}
Sundarajan Srinivasanf1e57462014-09-17 15:24:01 -07001765
Stephen Wang49b474b2016-03-25 10:40:30 -07001766/*
1767 * nss_n2h_register_sysctl()
1768 */
1769void nss_n2h_register_sysctl(void)
1770{
Vijay Dewangan634ce592015-01-07 17:21:09 -08001771 /*
1772 * RPS sema init
1773 */
1774 sema_init(&nss_n2h_rcp.sem, 1);
1775 init_completion(&nss_n2h_rcp.complete);
1776
Kalyan Tallapragadab50e8902015-08-06 17:00:54 +05301777 /*
1778 * MITIGATION sema init for core0
1779 */
1780 sema_init(&nss_n2h_mitigationcp[NSS_CORE_0].sem, 1);
1781 init_completion(&nss_n2h_mitigationcp[NSS_CORE_0].complete);
1782
1783 /*
1784 * MITIGATION sema init for core1
1785 */
1786 sema_init(&nss_n2h_mitigationcp[NSS_CORE_1].sem, 1);
1787 init_completion(&nss_n2h_mitigationcp[NSS_CORE_1].complete);
1788
1789 /*
1790 * PBUF addition sema init for core0
1791 */
1792 sema_init(&nss_n2h_bufcp[NSS_CORE_0].sem, 1);
1793 init_completion(&nss_n2h_bufcp[NSS_CORE_0].complete);
1794
1795 /*
1796 * PBUF addition sema init for core1
1797 */
1798 sema_init(&nss_n2h_bufcp[NSS_CORE_1].sem, 1);
1799 init_completion(&nss_n2h_bufcp[NSS_CORE_1].complete);
Vijay Dewangan634ce592015-01-07 17:21:09 -08001800
Stephen Wang49b474b2016-03-25 10:40:30 -07001801 /*
1802 * Core0
1803 */
1804 sema_init(&nss_n2h_nepbcfgp[NSS_CORE_0].sem, 1);
1805 init_completion(&nss_n2h_nepbcfgp[NSS_CORE_0].complete);
Sachin Shashidhar475012b2017-03-13 16:56:07 -07001806 nss_n2h_nepbcfgp[NSS_CORE_0].empty_buf_pool_info.pool_size =
Stephen Wang49b474b2016-03-25 10:40:30 -07001807 nss_n2h_empty_pool_buf_cfg[NSS_CORE_0];
Sachin Shashidhar475012b2017-03-13 16:56:07 -07001808 nss_n2h_nepbcfgp[NSS_CORE_0].empty_buf_pool_info.low_water =
Stephen Wang49b474b2016-03-25 10:40:30 -07001809 nss_n2h_water_mark[NSS_CORE_0][0];
Sachin Shashidhar475012b2017-03-13 16:56:07 -07001810 nss_n2h_nepbcfgp[NSS_CORE_0].empty_buf_pool_info.high_water =
Stephen Wang49b474b2016-03-25 10:40:30 -07001811 nss_n2h_water_mark[NSS_CORE_0][1];
Sachin Shashidhar475012b2017-03-13 16:56:07 -07001812 nss_n2h_nepbcfgp[NSS_CORE_0].empty_paged_buf_pool_info.pool_size =
1813 nss_n2h_empty_paged_pool_buf_cfg[NSS_CORE_0];
1814 nss_n2h_nepbcfgp[NSS_CORE_0].empty_paged_buf_pool_info.low_water =
1815 nss_n2h_paged_water_mark[NSS_CORE_0][0];
1816 nss_n2h_nepbcfgp[NSS_CORE_0].empty_paged_buf_pool_info.high_water =
1817 nss_n2h_paged_water_mark[NSS_CORE_0][1];
1818
Stephen Wang49b474b2016-03-25 10:40:30 -07001819 /*
1820 * Core1
1821 */
1822 sema_init(&nss_n2h_nepbcfgp[NSS_CORE_1].sem, 1);
1823 init_completion(&nss_n2h_nepbcfgp[NSS_CORE_1].complete);
Sachin Shashidhar475012b2017-03-13 16:56:07 -07001824 nss_n2h_nepbcfgp[NSS_CORE_1].empty_buf_pool_info.pool_size =
Stephen Wang49b474b2016-03-25 10:40:30 -07001825 nss_n2h_empty_pool_buf_cfg[NSS_CORE_1];
Sachin Shashidhar475012b2017-03-13 16:56:07 -07001826 nss_n2h_nepbcfgp[NSS_CORE_1].empty_buf_pool_info.low_water =
Stephen Wang49b474b2016-03-25 10:40:30 -07001827 nss_n2h_water_mark[NSS_CORE_1][0];
Sachin Shashidhar475012b2017-03-13 16:56:07 -07001828 nss_n2h_nepbcfgp[NSS_CORE_1].empty_buf_pool_info.high_water =
Stephen Wang49b474b2016-03-25 10:40:30 -07001829 nss_n2h_water_mark[NSS_CORE_1][1];
Sachin Shashidhar475012b2017-03-13 16:56:07 -07001830 nss_n2h_nepbcfgp[NSS_CORE_1].empty_paged_buf_pool_info.pool_size =
1831 nss_n2h_empty_paged_pool_buf_cfg[NSS_CORE_1];
1832 nss_n2h_nepbcfgp[NSS_CORE_1].empty_paged_buf_pool_info.low_water =
1833 nss_n2h_paged_water_mark[NSS_CORE_1][0];
1834 nss_n2h_nepbcfgp[NSS_CORE_1].empty_paged_buf_pool_info.high_water =
1835 nss_n2h_paged_water_mark[NSS_CORE_1][1];
1836
Stephen Wang49b474b2016-03-25 10:40:30 -07001837 /*
1838 * WiFi pool buf cfg sema init
1839 */
1840 sema_init(&nss_n2h_wp.sem, 1);
1841 init_completion(&nss_n2h_wp.complete);
1842
Shashank Balashankar4162f572018-08-21 13:32:34 -07001843 /*
1844 * N2H queue config sema init
1845 */
1846 sema_init(&nss_n2h_q_lim_pvt.sem, 1);
1847 init_completion(&nss_n2h_q_lim_pvt.complete);
1848
Vijay Dewangan488e5372014-12-29 21:40:11 -08001849 nss_n2h_notify_register(NSS_CORE_0, NULL, NULL);
1850 nss_n2h_notify_register(NSS_CORE_1, NULL, NULL);
1851
Stephen Wang49b474b2016-03-25 10:40:30 -07001852 /*
1853 * Register sysctl table.
1854 */
1855 nss_n2h_header = register_sysctl_table(nss_n2h_root);
1856}
1857
1858/*
1859 * nss_n2h_unregister_sysctl()
1860 * Unregister sysctl specific to n2h
1861 */
1862void nss_n2h_unregister_sysctl(void)
1863{
1864 /*
1865 * Unregister sysctl table.
1866 */
1867 if (nss_n2h_header) {
1868 unregister_sysctl_table(nss_n2h_header);
1869 }
Abhishek Rastogi84d95d02014-03-26 19:31:31 +05301870}
Vijay Dewangan488e5372014-12-29 21:40:11 -08001871
1872EXPORT_SYMBOL(nss_n2h_notify_register);