blob: a41f4632b102df193aa427ead50227c13e7f16fc [file] [log] [blame]
Radhakrishna Jiguru1c9b2252013-08-27 23:57:48 +05301/*
2 **************************************************************************
Vijay Dewangan488e5372014-12-29 21:40:11 -08003 * Copyright (c) 2013 - 2015, The Linux Foundation. All rights reserved.
Radhakrishna Jiguru1c9b2252013-08-27 23:57:48 +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 */
Abhishek Rastogibc74e432013-04-02 10:28:22 +053016
17/*
18 * nss_init.c
19 * NSS init APIs
20 *
21 */
Abhishek Rastogibc74e432013-04-02 10:28:22 +053022#include "nss_core.h"
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -080023#if (NSS_PM_SUPPORT == 1)
Pamidipati, Vijay7f413b52013-09-24 19:07:12 +053024#include "nss_pm.h"
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -080025#endif
Abhishek Rastogi9da47472014-03-18 19:46:15 +053026#include "nss_tx_rx_common.h"
Stephen Wang38e89bc2014-11-06 11:34:45 -080027#include "nss_data_plane.h"
Pamidipati, Vijay7f413b52013-09-24 19:07:12 +053028
Abhishek Rastogibc74e432013-04-02 10:28:22 +053029#include <nss_hal.h>
30
31#include <linux/module.h>
32#include <linux/platform_device.h>
wthomas442c7972013-08-05 14:28:17 -070033#include <linux/proc_fs.h>
34#include <linux/device.h>
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -080035
36#if (NSS_DT_SUPPORT == 1)
37#include <linux/of.h>
38#include <linux/of_net.h>
39#include <linux/of_irq.h>
40#include <linux/of_address.h>
41#include <linux/reset.h>
42#else
Abhishek Rastogibc74e432013-04-02 10:28:22 +053043#include <mach/msm_nss.h>
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -080044#endif
Abhishek Rastogibc74e432013-04-02 10:28:22 +053045
wthomas442c7972013-08-05 14:28:17 -070046#include <linux/sysctl.h>
47#include <linux/regulator/consumer.h>
Thomas Wufb6a6842013-10-23 13:14:27 -070048#include <linux/clk.h>
wthomas442c7972013-08-05 14:28:17 -070049
Kalyan Tallapragadab50e8902015-08-06 17:00:54 +053050#define NSS_N2H_MAX_BUF_POOL_SIZE (1024 * 1024 * 4) /* 4MB */
51
Abhishek Rastogibc74e432013-04-02 10:28:22 +053052/*
53 * Global declarations
54 */
Abhishek Rastogi5cd2e4c2013-11-13 18:09:08 +053055int nss_ctl_redirect __read_mostly = 0;
Sakthi Vignesh Radhakrishnanaf39aad2014-03-31 11:31:03 -070056int nss_ctl_debug __read_mostly = 0;
Pamidipati, Vijayefcc4692014-05-09 14:47:38 +053057int nss_rps_cfg __read_mostly = 0;
Kalyan Tallapragadab50e8902015-08-06 17:00:54 +053058int nss_core0_mitigation_cfg __read_mostly = 1;
59int nss_core1_mitigation_cfg __read_mostly = 1;
60int nss_core0_add_buf_pool_size __read_mostly = 0;
61int nss_core1_add_buf_pool_size __read_mostly = 0;
Saurabh Misra96998db2014-07-10 12:15:48 -070062int nss_ctl_logbuf __read_mostly = 0;
Sundarajan Srinivasanf9c4a232014-11-18 13:25:40 -080063int nss_jumbo_mru __read_mostly = 0;
64int nss_paged_mode __read_mostly = 0;
Abhishek Rastogibc74e432013-04-02 10:28:22 +053065
66/*
Pamidipati, Vijay5d27d812013-11-22 16:48:11 +053067 * PM client handle
68 */
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -080069#if (NSS_PM_SUPPORT == 1)
Pamidipati, Vijay5d27d812013-11-22 16:48:11 +053070static void *pm_client;
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -080071#endif
Pamidipati, Vijay5d27d812013-11-22 16:48:11 +053072
73/*
wthomas626147f2013-09-18 13:12:40 -070074 * Handler to send NSS messages
75 */
Thomas Wufb6a6842013-10-23 13:14:27 -070076struct clk *nss_core0_clk;
wthomas626147f2013-09-18 13:12:40 -070077
78/*
Thomas Wucd6b35a2015-07-14 10:17:48 -070079 * Handle fabric requests - only on new kernel
80 */
81#if (NSS_DT_SUPPORT == 1)
82struct clk *nss_fab0_clk;
83struct clk *nss_fab1_clk;
84#endif
85
86/*
Abhishek Rastogibc74e432013-04-02 10:28:22 +053087 * Top level nss context structure
88 */
89struct nss_top_instance nss_top_main;
wthomas442c7972013-08-05 14:28:17 -070090struct nss_cmd_buffer nss_cmd_buf;
wthomas626147f2013-09-18 13:12:40 -070091struct nss_runtime_sampling nss_runtime_samples;
92struct workqueue_struct *nss_wq;
93
94/*
95 * Work Queue to handle messages to Kernel
96 */
97nss_work_t *nss_work;
Abhishek Rastogibc74e432013-04-02 10:28:22 +053098
Arunkumar T79990cb2015-06-05 10:53:16 +053099extern struct of_device_id nss_dt_ids[];
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530100
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530101/*
102 * nss_probe()
Arunkumar T79990cb2015-06-05 10:53:16 +0530103 * HLOS device probe callback
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530104 */
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800105#if (LINUX_VERSION_CODE <= KERNEL_VERSION(3,7,0))
Arunkumar T79990cb2015-06-05 10:53:16 +0530106inline int __devinit nss_probe(struct platform_device *nss_dev)
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800107#else
Arunkumar T79990cb2015-06-05 10:53:16 +0530108inline int nss_probe(struct platform_device *nss_dev)
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800109#endif
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530110{
Arunkumar T79990cb2015-06-05 10:53:16 +0530111 return nss_hal_probe(nss_dev);
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530112}
113
114/*
115 * nss_remove()
Arunkumar T79990cb2015-06-05 10:53:16 +0530116 * HLOS device remove callback
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530117 */
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800118#if (LINUX_VERSION_CODE <= KERNEL_VERSION(3,7,0))
Arunkumar T79990cb2015-06-05 10:53:16 +0530119inline int __devexit nss_remove(struct platform_device *nss_dev)
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800120#else
Arunkumar T79990cb2015-06-05 10:53:16 +0530121inline int nss_remove(struct platform_device *nss_dev)
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800122#endif
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530123{
Arunkumar T79990cb2015-06-05 10:53:16 +0530124 return nss_hal_remove(nss_dev);
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530125}
126
127/*
128 * nss_driver
129 * Platform driver structure for NSS
130 */
131struct platform_driver nss_driver = {
132 .probe = nss_probe,
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800133#if (LINUX_VERSION_CODE <= KERNEL_VERSION(3,7,0))
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530134 .remove = __devexit_p(nss_remove),
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800135#else
136 .remove = nss_remove,
137#endif
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530138 .driver = {
139 .name = "qca-nss",
140 .owner = THIS_MODULE,
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800141#if (NSS_DT_SUPPORT == 1)
142 .of_match_table = of_match_ptr(nss_dt_ids),
143#endif
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530144 },
145};
146
Arunkumar T28b2d742015-06-16 22:15:58 +0530147#if (NSS_FREQ_SCALE_SUPPORT == 1)
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530148/*
Kiran Kumar C.S.K69fd5992014-01-06 20:58:14 +0530149 * nss_reset_frequency_stats_samples()
150 * Reset all frequency sampling state when auto scaling is turned off.
151 */
152static void nss_reset_frequency_stats_samples (void)
153{
154 nss_runtime_samples.buffer_index = 0;
155 nss_runtime_samples.sum = 0;
156 nss_runtime_samples.average = 0;
157 nss_runtime_samples.sample_count = 0;
158 nss_runtime_samples.message_rate_limit = 0;
Kiran Kumar C.S.K69fd5992014-01-06 20:58:14 +0530159 nss_runtime_samples.freq_scale_rate_limit_down = 0;
160}
161
162/*
wthomas626147f2013-09-18 13:12:40 -0700163 ***************************************************************************************************
Thomas Wufb6a6842013-10-23 13:14:27 -0700164 * nss_wq_function() is used to queue up requests to change NSS frequencies.
165 * The function will take care of NSS notices and also control clock.
166 * The auto rate algorithmn will queue up requests or the procfs may also queue up these requests.
wthomas626147f2013-09-18 13:12:40 -0700167 ***************************************************************************************************
168 */
169
170/*
171 * nss_wq_function()
172 * Added to Handle BH requests to kernel
173 */
174void nss_wq_function (struct work_struct *work)
175{
176 nss_work_t *my_work = (nss_work_t *)work;
177
Guojun Jin32a3c6d2015-05-06 12:27:52 -0700178 nss_freq_change(&nss_top_main.nss[NSS_CORE_0], my_work->frequency, my_work->stats_enable, 0);
Guojun Jin9d782812015-05-12 14:01:25 -0700179 if (nss_top_main.nss[NSS_CORE_1].state == NSS_CORE_STATE_INITIALIZED) {
180 nss_freq_change(&nss_top_main.nss[NSS_CORE_1], my_work->frequency, my_work->stats_enable, 0);
181 }
Thomas Wufb6a6842013-10-23 13:14:27 -0700182 clk_set_rate(nss_core0_clk, my_work->frequency);
Guojun Jin32a3c6d2015-05-06 12:27:52 -0700183 nss_freq_change(&nss_top_main.nss[NSS_CORE_0], my_work->frequency, my_work->stats_enable, 1);
Guojun Jin9d782812015-05-12 14:01:25 -0700184 if (nss_top_main.nss[NSS_CORE_1].state == NSS_CORE_STATE_INITIALIZED) {
185 nss_freq_change(&nss_top_main.nss[NSS_CORE_1], my_work->frequency, my_work->stats_enable, 1);
186 }
wthomas626147f2013-09-18 13:12:40 -0700187
Thomas Wucd6b35a2015-07-14 10:17:48 -0700188/*
189 * If we are running NSS_PM_SUPPORT, we are on banana
190 * otherwise, we check if we are are on new kernel by checking if the
191 * fabric lookups are not NULL (success in init()))
192 */
Thomas Wu0d112192015-04-13 11:37:22 -0700193#if (NSS_PM_SUPPORT == 1)
Thomas Wucd6b35a2015-07-14 10:17:48 -0700194 if (!pm_client) {
Pamidipati, Vijay5d27d812013-11-22 16:48:11 +0530195 goto out;
196 }
197
Thomas Wu0e2fc4f2015-03-04 15:39:14 -0800198 if (my_work->frequency >= NSS_FREQ_733) {
Pamidipati, Vijay5d27d812013-11-22 16:48:11 +0530199 nss_pm_set_perf_level(pm_client, NSS_PM_PERF_LEVEL_TURBO);
Thomas Wu0e2fc4f2015-03-04 15:39:14 -0800200 } else if (my_work->frequency > NSS_FREQ_110) {
Pamidipati, Vijay5d27d812013-11-22 16:48:11 +0530201 nss_pm_set_perf_level(pm_client, NSS_PM_PERF_LEVEL_NOMINAL);
202 } else {
203 nss_pm_set_perf_level(pm_client, NSS_PM_PERF_LEVEL_IDLE);
204 }
Thomas Wu0d112192015-04-13 11:37:22 -0700205
Pamidipati, Vijay5d27d812013-11-22 16:48:11 +0530206out:
Thomas Wucd6b35a2015-07-14 10:17:48 -0700207#else
208#if (NSS_DT_SUPPORT == 1)
209 if ((nss_fab0_clk != NULL) && (nss_fab0_clk != NULL)) {
210 if (my_work->frequency >= NSS_FREQ_733) {
211 clk_set_rate(nss_fab0_clk, NSS_FABRIC0_TURBO);
212 clk_set_rate(nss_fab1_clk, NSS_FABRIC1_TURBO);
213 } else if (my_work->frequency > NSS_FREQ_110) {
214 clk_set_rate(nss_fab0_clk, NSS_FABRIC0_NOMINAL);
215 clk_set_rate(nss_fab1_clk, NSS_FABRIC1_NOMINAL);
216 } else {
217 clk_set_rate(nss_fab0_clk, NSS_FABRIC0_IDLE);
218 clk_set_rate(nss_fab1_clk, NSS_FABRIC1_IDLE);
219 }
220 }
221#endif
Thomas Wu0d112192015-04-13 11:37:22 -0700222#endif
wthomas626147f2013-09-18 13:12:40 -0700223 kfree((void *)work);
224}
225
226/*
wthomas442c7972013-08-05 14:28:17 -0700227 * nss_current_freq_handler()
228 * Handle Userspace Frequency Change Requests
229 */
230static int nss_current_freq_handler (ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos)
231{
Thomas Wu0e2fc4f2015-03-04 15:39:14 -0800232 int ret, i;
wthomas626147f2013-09-18 13:12:40 -0700233
234 BUG_ON(!nss_wq);
wthomas442c7972013-08-05 14:28:17 -0700235
236 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
237
wthomasd39fa822013-08-22 16:44:23 -0700238 if (!write) {
wthomas626147f2013-09-18 13:12:40 -0700239 printk("Frequency Set to %d\n", nss_cmd_buf.current_freq);
wthomasd39fa822013-08-22 16:44:23 -0700240 return ret;
wthomas442c7972013-08-05 14:28:17 -0700241 }
wthomasd39fa822013-08-22 16:44:23 -0700242
Thomas Wu0e2fc4f2015-03-04 15:39:14 -0800243 /*
244 * Check if frequency exists in frequency Table
245 */
246 i = 0;
Thomas Wu7132bd32015-05-07 15:03:06 -0700247 while (i < NSS_FREQ_MAX_SCALE) {
Thomas Wu0e2fc4f2015-03-04 15:39:14 -0800248 if (nss_runtime_samples.freq_scale[i].frequency == nss_cmd_buf.current_freq) {
249 break;
250 }
251 i++;
252 }
Thomas Wu7132bd32015-05-07 15:03:06 -0700253 if (i == NSS_FREQ_MAX_SCALE) {
Thomas Wufb6a6842013-10-23 13:14:27 -0700254 printk("Frequency not found. Please check Frequency Table\n");
wthomas626147f2013-09-18 13:12:40 -0700255 return ret;
wthomasd39fa822013-08-22 16:44:23 -0700256 }
257
Thomas Wu0e2fc4f2015-03-04 15:39:14 -0800258 /* Turn off Auto Scale */
259 nss_cmd_buf.auto_scale = 0;
260 nss_runtime_samples.freq_scale_ready = 0;
261
Thomas Wu7409bce2014-05-21 10:56:07 -0700262 nss_work = (nss_work_t *)kmalloc(sizeof(nss_work_t), GFP_ATOMIC);
wthomas626147f2013-09-18 13:12:40 -0700263 if (!nss_work) {
264 nss_info("NSS Freq WQ kmalloc fail");
265 return ret;
266 }
267 INIT_WORK((struct work_struct *)nss_work, nss_wq_function);
268 nss_work->frequency = nss_cmd_buf.current_freq;
Kiran Kumar C.S.K69fd5992014-01-06 20:58:14 +0530269 nss_work->stats_enable = 0;
270
271 /* Ensure we start with a fresh set of samples later */
272 nss_reset_frequency_stats_samples();
273
wthomas626147f2013-09-18 13:12:40 -0700274 queue_work(nss_wq, (struct work_struct *)nss_work);
275
wthomas442c7972013-08-05 14:28:17 -0700276 return ret;
277}
278
279/*
280 * nss_auto_scale_handler()
281 * Enables or Disable Auto Scaling
282 */
283static int nss_auto_scale_handler (ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos)
284{
285 int ret;
286
287 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
288
wthomas626147f2013-09-18 13:12:40 -0700289 if (!write) {
290 return ret;
291 }
292
Thomas Wufb6a6842013-10-23 13:14:27 -0700293 if (nss_cmd_buf.auto_scale != 1) {
wthomas626147f2013-09-18 13:12:40 -0700294 /*
Kiran Kumar C.S.K69fd5992014-01-06 20:58:14 +0530295 * Is auto scaling currently enabled? If so, send the command to
296 * disable stats reporting to NSS
wthomas626147f2013-09-18 13:12:40 -0700297 */
Kiran Kumar C.S.K69fd5992014-01-06 20:58:14 +0530298 if (nss_runtime_samples.freq_scale_ready != 0) {
299 nss_cmd_buf.current_freq = nss_runtime_samples.freq_scale[nss_runtime_samples.freq_scale_index].frequency;
Thomas Wu7409bce2014-05-21 10:56:07 -0700300 nss_work = (nss_work_t *)kmalloc(sizeof(nss_work_t), GFP_ATOMIC);
Kiran Kumar C.S.K69fd5992014-01-06 20:58:14 +0530301 if (!nss_work) {
302 nss_info("NSS Freq WQ kmalloc fail");
303 return ret;
304 }
305 INIT_WORK((struct work_struct *)nss_work, nss_wq_function);
306 nss_work->frequency = nss_cmd_buf.current_freq;
307 nss_work->stats_enable = 0;
308 queue_work(nss_wq, (struct work_struct *)nss_work);
309 nss_runtime_samples.freq_scale_ready = 0;
310
311 /*
312 * The current samples would be stale later when scaling is
313 * enabled again, hence reset them
314 */
315 nss_reset_frequency_stats_samples();
316 }
Thomas Wufb6a6842013-10-23 13:14:27 -0700317 return ret;
wthomas626147f2013-09-18 13:12:40 -0700318 }
wthomas442c7972013-08-05 14:28:17 -0700319
Thomas Wufb6a6842013-10-23 13:14:27 -0700320 /*
321 * Auto Scaling is already being done
322 */
323 if (nss_runtime_samples.freq_scale_ready == 1) {
324 return ret;
325 }
326
327 /*
328 * Setup default values - Middle of Freq Scale Band
329 */
330 nss_runtime_samples.freq_scale_index = 1;
331 nss_cmd_buf.current_freq = nss_runtime_samples.freq_scale[nss_runtime_samples.freq_scale_index].frequency;
332
Thomas Wu7409bce2014-05-21 10:56:07 -0700333 nss_work = (nss_work_t *)kmalloc(sizeof(nss_work_t), GFP_ATOMIC);
Thomas Wufb6a6842013-10-23 13:14:27 -0700334 if (!nss_work) {
335 nss_info("NSS Freq WQ kmalloc fail");
336 return ret;
337 }
338 INIT_WORK((struct work_struct *)nss_work, nss_wq_function);
339 nss_work->frequency = nss_cmd_buf.current_freq;
Kiran Kumar C.S.K69fd5992014-01-06 20:58:14 +0530340 nss_work->stats_enable = 1;
Thomas Wufb6a6842013-10-23 13:14:27 -0700341 queue_work(nss_wq, (struct work_struct *)nss_work);
342
Thomas Wu0e2fc4f2015-03-04 15:39:14 -0800343 nss_cmd_buf.auto_scale = 0;
Thomas Wufb6a6842013-10-23 13:14:27 -0700344 nss_runtime_samples.freq_scale_ready = 1;
345
wthomas442c7972013-08-05 14:28:17 -0700346 return ret;
347}
348
349/*
350 * nss_get_freq_table_handler()
351 * Display Support Freq and Ex how to Change.
352 */
Thomas Wu05495be2013-12-19 14:24:24 -0800353static int nss_get_freq_table_handler(ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos)
wthomas442c7972013-08-05 14:28:17 -0700354{
Thomas Wu0e2fc4f2015-03-04 15:39:14 -0800355 int ret, i;
wthomas442c7972013-08-05 14:28:17 -0700356
357 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
358
Thomas Wu0e2fc4f2015-03-04 15:39:14 -0800359 printk("Frequency Supported - ");
360 i = 0;
Thomas Wu7132bd32015-05-07 15:03:06 -0700361 while (i < NSS_FREQ_MAX_SCALE) {
Thomas Wu0e2fc4f2015-03-04 15:39:14 -0800362 printk("%dMhz ", nss_runtime_samples.freq_scale[i].frequency/1000000);
363 i++;
Thomas Wu0a0a9c92013-11-21 15:28:19 -0800364 }
Thomas Wu0e2fc4f2015-03-04 15:39:14 -0800365 printk("\n");
wthomas442c7972013-08-05 14:28:17 -0700366
367 return ret;
368}
369
370/*
Thomas Wu05495be2013-12-19 14:24:24 -0800371 * nss_get_average_inst_handler()
372 * Display AVG Inst Per Ms.
373 */
374static int nss_get_average_inst_handler(ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos)
375{
376 int ret;
377
378 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
379
380 if (!ret && !write) {
381 printk("Current Inst Per Ms %x\n", nss_runtime_samples.average);
382 }
383
384 return ret;
385}
Arunkumar T28b2d742015-06-16 22:15:58 +0530386#endif
Thomas Wu05495be2013-12-19 14:24:24 -0800387
Sundarajan Srinivasan758e8f42014-12-08 14:56:24 -0800388#if (NSS_FW_DBG_SUPPORT == 1)
Thomas Wu05495be2013-12-19 14:24:24 -0800389/*
Abhishek Rastogi1626a902013-11-21 17:09:49 +0530390 * nss_debug_handler()
391 * Enable NSS debug output
392 */
393static int nss_debug_handler(ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos)
394{
395 int ret;
396
397 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
398 if (!ret) {
399 if ((write) && (nss_ctl_debug != 0)) {
400 printk("Enabling NSS SPI Debug\n");
401 nss_hal_debug_enable();
402 }
403 }
404
405 return ret;
406}
Sundarajan Srinivasan758e8f42014-12-08 14:56:24 -0800407#endif
Abhishek Rastogi1626a902013-11-21 17:09:49 +0530408
409/*
Pamidipati, Vijayefcc4692014-05-09 14:47:38 +0530410 * nss_rps_handler()
411 * Enable NSS RPS
412 */
413static int nss_rpscfg_handler(ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos)
414{
415 struct nss_top_instance *nss_top = &nss_top_main;
416 struct nss_ctx_instance *nss_ctx = &nss_top->nss[0];
417 int ret;
418
419 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
420 if (!ret) {
421 if ((write) && (nss_rps_cfg == 1)) {
422 printk("Enabling NSS RPS\n");
Vijay Dewangan634ce592015-01-07 17:21:09 -0800423
424 return nss_n2h_rps_cfg(nss_ctx, 1);
Pamidipati, Vijayefcc4692014-05-09 14:47:38 +0530425 }
426
427 if ((write) && (nss_rps_cfg == 0)) {
428 printk("Runtime disabling of NSS RPS not supported \n");
429 return ret;
430 }
431
432 if (write) {
433 printk("Invalid input value.Valid values are 0 and 1 \n");
434 }
435
436 }
437
438 return ret;
439}
440
441/*
Kalyan Tallapragadab50e8902015-08-06 17:00:54 +0530442 * nss_mitigation_handler()
443 * Enable NSS MITIGATION
444 */
445static int nss_mitigationcfg_core0_handler(ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos)
446{
447 struct nss_top_instance *nss_top = &nss_top_main;
448 struct nss_ctx_instance *nss_ctx = &nss_top->nss[NSS_CORE_0];
449 int ret;
450
451 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
452 if (ret) {
453 return ret;
454 }
455
456 /*
457 * It's a read operation
458 */
459 if (!write) {
460 return ret;
461 }
462
463 if (!nss_core0_mitigation_cfg ) {
464 printk("Disabling NSS MITIGATION\n");
465 nss_n2h_mitigation_cfg(nss_ctx, 0, NSS_CORE_0);
466 return 0;
467 }
468 printk("Invalid input value.Valid value is 0, Runtime re-enabling not supported\n");
469 return -EINVAL;
470}
471
472/*
473 * nss_mitigation_handler()
474 * Enable NSS MITIGATION
475 */
476static int nss_mitigationcfg_core1_handler(ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos)
477{
478 struct nss_top_instance *nss_top = &nss_top_main;
479 struct nss_ctx_instance *nss_ctx = &nss_top->nss[NSS_CORE_1];
480 int ret;
481
482 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
483 if (ret) {
484 return ret;;
485 }
486
487 /*
488 * It's a read operation
489 */
490 if (!write) {
491 return ret;
492 }
493
494 if (!nss_core1_mitigation_cfg ) {
495 printk("Disabling NSS MITIGATION\n");
496 nss_n2h_mitigation_cfg(nss_ctx, 0, NSS_CORE_1);
497 return 0;
498 }
499 printk("Invalid input value.Valid value is 0, Runtime re-enabling not supported\n");
500 return -EINVAL;
501}
502
503/*
504 * nss_buf_handler()
505 * Add extra NSS bufs from host memory
506 */
507static int nss_buf_cfg_core0_handler(ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos)
508{
509 struct nss_top_instance *nss_top = &nss_top_main;
510 struct nss_ctx_instance *nss_ctx = &nss_top->nss[NSS_CORE_0];
511 int ret;
512
513 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
514 if (ret) {
515 return ret;
516 }
517
518 /*
519 * It's a read operation
520 */
521 if (!write) {
522 return ret;
523 }
524
525 if (nss_ctx->buf_sz_allocated) {
526 nss_core0_add_buf_pool_size = nss_ctx->buf_sz_allocated;
527 return -EPERM;
528 }
529
530 if ((nss_core0_add_buf_pool_size >= 1) && (nss_core0_add_buf_pool_size <= NSS_N2H_MAX_BUF_POOL_SIZE)) {
531 printk("configuring additional NSS pbufs\n");
532 ret = nss_n2h_buf_pool_cfg(nss_ctx, nss_core0_add_buf_pool_size, NSS_CORE_0);
533 nss_core0_add_buf_pool_size = nss_ctx->buf_sz_allocated;
534 printk("additional pbufs of size %d got added to NSS\n", nss_ctx->buf_sz_allocated);
535 return ret;;
536 }
537
538 printk("Invalid input value. should be greater than 1 and less than %d\n", NSS_N2H_MAX_BUF_POOL_SIZE);
539 return -EINVAL;
540}
541
542/*
543 * nss_buf_handler()
544 * Add extra NSS bufs from host memory
545 */
546static int nss_buf_cfg_core1_handler(ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos)
547{
548 struct nss_top_instance *nss_top = &nss_top_main;
549 struct nss_ctx_instance *nss_ctx = &nss_top->nss[NSS_CORE_1];
550 int ret;
551
552 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
553 if (ret) {
554 return ret;
555 }
556
557 /*
558 * It's a read operation
559 */
560 if (!write) {
561 return ret;
562 }
563
564 if (nss_ctx->buf_sz_allocated) {
565 nss_core1_add_buf_pool_size = nss_ctx->buf_sz_allocated;
566 return -EPERM;
567 }
568
569 if ((nss_core1_add_buf_pool_size >= 1) && (nss_core1_add_buf_pool_size <= NSS_N2H_MAX_BUF_POOL_SIZE)) {
570 printk("configuring additional NSS pbufs\n");
571 ret = nss_n2h_buf_pool_cfg(nss_ctx, nss_core1_add_buf_pool_size, NSS_CORE_1);
572 nss_core1_add_buf_pool_size = nss_ctx->buf_sz_allocated;
573 printk("additional pbufs of size %d got added to NSS\n", nss_ctx->buf_sz_allocated);
574 return ret;
575 }
576
577 printk("Invalid input value. should be greater than 1 and less than %d\n", NSS_N2H_MAX_BUF_POOL_SIZE);
578 return -EINVAL;
579}
580
581/*
Thomas Wu52075f42014-02-06 16:32:42 -0800582 * nss_coredump_handler()
583 * Send Signal To Coredump NSS Cores
584 */
585static int nss_coredump_handler(ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos)
586{
Guojun Jin32a3c6d2015-05-06 12:27:52 -0700587 struct nss_ctx_instance *nss_ctx = &nss_top_main.nss[NSS_CORE_0];
Thomas Wu52075f42014-02-06 16:32:42 -0800588 int ret;
589
590 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
591 if (!ret) {
592 if ((write) && (nss_ctl_debug != 0)) {
593 printk("Coredumping to DDR\n");
Stephen Wangf26af762015-07-15 12:00:30 -0700594 nss_hal_send_interrupt(nss_ctx->nmap, nss_ctx->h2n_desc_rings[NSS_IF_CMD_QUEUE].desc_ring.int_bit, NSS_REGS_H2N_INTR_STATUS_TRIGGER_COREDUMP);
Thomas Wu52075f42014-02-06 16:32:42 -0800595 }
596 }
597
598 return ret;
599}
600
601/*
Sundarajan Srinivasanf9c4a232014-11-18 13:25:40 -0800602 * nss_jumbo_mru_handler()
603 * Sysctl to modify nss_jumbo_mru
604 */
605static int nss_jumbo_mru_handler(ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos)
606{
607 int ret;
608
609 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
610 if (ret) {
611 return ret;
612 }
613
614 if (write) {
615 nss_core_set_jumbo_mru(nss_jumbo_mru);
616 nss_info("jumbo_mru set to %d\n", nss_jumbo_mru);
617 }
618
619 return ret;
620}
621
622/* nss_paged_mode_handler()
623 * Sysctl to modify nss_paged_mode.
624 */
625
626static int nss_paged_mode_handler(ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos)
627{
628 int ret;
629
630 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
631 if (ret) {
632 return ret;
633 }
634
635 if (write) {
636 nss_core_set_paged_mode(nss_paged_mode);
637 nss_info("paged_mode set to %d\n", nss_paged_mode);
638 }
639
640 return ret;
641}
642
Arunkumar T28b2d742015-06-16 22:15:58 +0530643#if (NSS_FREQ_SCALE_SUPPORT == 1)
Sundarajan Srinivasanf9c4a232014-11-18 13:25:40 -0800644/*
wthomas442c7972013-08-05 14:28:17 -0700645 * sysctl-tuning infrastructure.
646 */
647static ctl_table nss_freq_table[] = {
648 {
649 .procname = "current_freq",
650 .data = &nss_cmd_buf.current_freq,
651 .maxlen = sizeof(int),
652 .mode = 0644,
653 .proc_handler = &nss_current_freq_handler,
654 },
655 {
656 .procname = "freq_table",
657 .data = &nss_cmd_buf.max_freq,
658 .maxlen = sizeof(int),
659 .mode = 0644,
660 .proc_handler = &nss_get_freq_table_handler,
661 },
662 {
663 .procname = "auto_scale",
664 .data = &nss_cmd_buf.auto_scale,
665 .maxlen = sizeof(int),
666 .mode = 0644,
667 .proc_handler = &nss_auto_scale_handler,
668 },
Thomas Wu05495be2013-12-19 14:24:24 -0800669 {
670 .procname = "inst_per_sec",
671 .data = &nss_cmd_buf.average_inst,
672 .maxlen = sizeof(int),
673 .mode = 0644,
674 .proc_handler = &nss_get_average_inst_handler,
675 },
wthomas442c7972013-08-05 14:28:17 -0700676 { }
677};
Arunkumar T28b2d742015-06-16 22:15:58 +0530678#endif
wthomas442c7972013-08-05 14:28:17 -0700679
Abhishek Rastogi5cd2e4c2013-11-13 18:09:08 +0530680static ctl_table nss_general_table[] = {
681 {
682 .procname = "redirect",
683 .data = &nss_ctl_redirect,
684 .maxlen = sizeof(int),
685 .mode = 0644,
Vijay Dewangan9db18752014-09-15 16:25:01 -0700686 .proc_handler = proc_dointvec,
Abhishek Rastogi5cd2e4c2013-11-13 18:09:08 +0530687 },
Sundarajan Srinivasan758e8f42014-12-08 14:56:24 -0800688#if (NSS_FW_DBG_SUPPORT == 1)
Abhishek Rastogi1626a902013-11-21 17:09:49 +0530689 {
690 .procname = "debug",
691 .data = &nss_ctl_debug,
692 .maxlen = sizeof(int),
693 .mode = 0644,
Vijay Dewangan9db18752014-09-15 16:25:01 -0700694 .proc_handler = &nss_debug_handler,
Abhishek Rastogi1626a902013-11-21 17:09:49 +0530695 },
Sundarajan Srinivasan758e8f42014-12-08 14:56:24 -0800696#endif
Thomas Wu52075f42014-02-06 16:32:42 -0800697 {
698 .procname = "coredump",
699 .data = &nss_cmd_buf.coredump,
700 .maxlen = sizeof(int),
701 .mode = 0644,
Vijay Dewangan9db18752014-09-15 16:25:01 -0700702 .proc_handler = &nss_coredump_handler,
Thomas Wu52075f42014-02-06 16:32:42 -0800703 },
Pamidipati, Vijayefcc4692014-05-09 14:47:38 +0530704 {
705 .procname = "rps",
706 .data = &nss_rps_cfg,
707 .maxlen = sizeof(int),
708 .mode = 0644,
Vijay Dewangan9db18752014-09-15 16:25:01 -0700709 .proc_handler = &nss_rpscfg_handler,
Pamidipati, Vijayefcc4692014-05-09 14:47:38 +0530710 },
Saurabh Misra96998db2014-07-10 12:15:48 -0700711 {
Kalyan Tallapragadab50e8902015-08-06 17:00:54 +0530712 .procname = "mitigation_core0",
713 .data = &nss_core0_mitigation_cfg,
714 .maxlen = sizeof(int),
715 .mode = 0644,
716 .proc_handler = &nss_mitigationcfg_core0_handler,
717 },
718 {
719 .procname = "mitigation_core1",
720 .data = &nss_core1_mitigation_cfg,
721 .maxlen = sizeof(int),
722 .mode = 0644,
723 .proc_handler = &nss_mitigationcfg_core1_handler,
724 },
725 {
726 .procname = "extra_pbuf_core0",
727 .data = &nss_core0_add_buf_pool_size,
728 .maxlen = sizeof(int),
729 .mode = 0644,
730 .proc_handler = &nss_buf_cfg_core0_handler,
731 },
732 {
733 .procname = "extra_pbuf_core1",
734 .data = &nss_core1_add_buf_pool_size,
735 .maxlen = sizeof(int),
736 .mode = 0644,
737 .proc_handler = &nss_buf_cfg_core1_handler,
738 },
739 {
Saurabh Misra96998db2014-07-10 12:15:48 -0700740 .procname = "logbuf",
741 .data = &nss_ctl_logbuf,
742 .maxlen = sizeof(int),
743 .mode = 0644,
744 .proc_handler = &nss_logbuffer_handler,
745 },
Sundarajan Srinivasanf9c4a232014-11-18 13:25:40 -0800746 {
747 .procname = "jumbo_mru",
748 .data = &nss_jumbo_mru,
749 .maxlen = sizeof(int),
750 .mode = 0644,
751 .proc_handler = &nss_jumbo_mru_handler,
752 },
753 {
754 .procname = "paged_mode",
755 .data = &nss_paged_mode,
756 .maxlen = sizeof(int),
757 .mode = 0644,
758 .proc_handler = &nss_paged_mode_handler,
759 },
Abhishek Rastogi5cd2e4c2013-11-13 18:09:08 +0530760 { }
761};
762
wthomas442c7972013-08-05 14:28:17 -0700763static ctl_table nss_clock_dir[] = {
Arunkumar T28b2d742015-06-16 22:15:58 +0530764#if (NSS_FREQ_SCALE_SUPPORT == 1)
wthomas442c7972013-08-05 14:28:17 -0700765 {
Abhishek Rastogi5cd2e4c2013-11-13 18:09:08 +0530766 .procname = "clock",
767 .mode = 0555,
768 .child = nss_freq_table,
769 },
Arunkumar T28b2d742015-06-16 22:15:58 +0530770#endif
Abhishek Rastogi5cd2e4c2013-11-13 18:09:08 +0530771 {
772 .procname = "general",
773 .mode = 0555,
774 .child = nss_general_table,
wthomas442c7972013-08-05 14:28:17 -0700775 },
776 { }
777};
778
779static ctl_table nss_root_dir[] = {
780 {
781 .procname = "nss",
782 .mode = 0555,
783 .child = nss_clock_dir,
784 },
785 { }
786};
787
788static ctl_table nss_root[] = {
789 {
790 .procname = "dev",
791 .mode = 0555,
792 .child = nss_root_dir,
793 },
794 { }
795};
796
797static struct ctl_table_header *nss_dev_header;
798
799/*
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530800 * nss_init()
801 * Registers nss driver
802 */
803static int __init nss_init(void)
804{
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800805#if (NSS_DT_SUPPORT == 1)
806 struct device_node *cmn = NULL;
807 struct resource res_nss_fpb_base;
808#endif
809
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530810 nss_info("Init NSS driver");
811
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800812#if (NSS_DT_SUPPORT == 1)
813 /*
814 * Get reference to NSS common device node
815 */
816 cmn = of_find_node_by_name(NULL, "nss-common");
817 if (!cmn) {
Xiaoping Fan921869a2015-08-12 17:19:43 -0700818 nss_info_always("qca-nss-drv.ko is loaded for symbol link\n");
819 return 0;
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800820 }
821
822 if (of_address_to_resource(cmn, 0, &res_nss_fpb_base) != 0) {
823 nss_info("of_address_to_resource() return error for nss_fpb_base\n");
824 of_node_put(cmn);
825 return -EFAULT;
826 }
827
828 nss_top_main.nss_fpb_base = ioremap_nocache(res_nss_fpb_base.start,
829 resource_size(&res_nss_fpb_base));
830 if (!nss_top_main.nss_fpb_base) {
831 nss_info("ioremap fail for nss_fpb_base\n");
832 of_node_put(cmn);
833 return -EFAULT;
834 }
835
836 nss_top_main.nss_hal_common_init_done = false;
837
838 /*
839 * Release reference to NSS common device node
840 */
841 of_node_put(cmn);
842 cmn = NULL;
843#else
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530844 /*
845 * Perform clock init common to all NSS cores
846 */
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530847 nss_hal_common_reset(&(nss_top_main.clk_src));
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530848
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800849#endif /* NSS_DT_SUPPORT */
850
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530851 /*
852 * Enable spin locks
853 */
854 spin_lock_init(&(nss_top_main.lock));
855 spin_lock_init(&(nss_top_main.stats_lock));
856
857 /*
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530858 * Enable NSS statistics
859 */
860 nss_stats_init();
861
862 /*
wthomas442c7972013-08-05 14:28:17 -0700863 * Register sysctl table.
864 */
865 nss_dev_header = register_sysctl_table(nss_root);
866
867 /*
Vijay Dewangan9db18752014-09-15 16:25:01 -0700868 * Registering sysctl for ipv4/6 specific config.
869 */
870 nss_ipv4_register_sysctl();
871 nss_ipv6_register_sysctl();
872
Vijay Dewanganac7efc42015-02-09 16:04:53 -0800873 /*
874 * Registering sysctl for n2h empty pool buffer.
875 */
876 nss_n2h_empty_pool_buf_register_sysctl();
877
Vijay Dewangan9db18752014-09-15 16:25:01 -0700878 /*
wthomas626147f2013-09-18 13:12:40 -0700879 * Setup Runtime Sample values
880 */
wthomas626147f2013-09-18 13:12:40 -0700881 nss_runtime_samples.freq_scale_index = 1;
882 nss_runtime_samples.freq_scale_ready = 0;
Thomas Wu9681f7e2013-11-06 13:12:57 -0800883 nss_runtime_samples.freq_scale_rate_limit_down = 0;
wthomas626147f2013-09-18 13:12:40 -0700884 nss_runtime_samples.buffer_index = 0;
885 nss_runtime_samples.sum = 0;
886 nss_runtime_samples.sample_count = 0;
887 nss_runtime_samples.average = 0;
888 nss_runtime_samples.message_rate_limit = 0;
Kiran Kumar C.S.K69fd5992014-01-06 20:58:14 +0530889 nss_runtime_samples.initialized = 0;
wthomas626147f2013-09-18 13:12:40 -0700890
Thomas Wu05495be2013-12-19 14:24:24 -0800891 nss_cmd_buf.current_freq = nss_runtime_samples.freq_scale[nss_runtime_samples.freq_scale_index].frequency;
892
wthomas626147f2013-09-18 13:12:40 -0700893 /*
894 * Initial Workqueue
895 */
896 nss_wq = create_workqueue("nss_freq_queue");
897
Thomas Wu0d112192015-04-13 11:37:22 -0700898#if (NSS_PM_SUPPORT == 1)
wthomas626147f2013-09-18 13:12:40 -0700899 /*
Pamidipati, Vijay7f413b52013-09-24 19:07:12 +0530900 * Initialize NSS Bus PM module
901 */
902 nss_pm_init();
903
904 /*
Pamidipati, Vijay5d27d812013-11-22 16:48:11 +0530905 * Register with Bus driver
906 */
907 pm_client = nss_pm_client_register(NSS_PM_CLIENT_NETAP);
908 if (!pm_client) {
909 nss_warning("Error registering with PM driver");
910 }
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800911#endif
Pamidipati, Vijay5d27d812013-11-22 16:48:11 +0530912
913 /*
Radha krishna Simha Jiguru7f424d52015-02-10 19:41:01 +0530914 * Initialize mtu size needed as start
915 */
916 nss_top_main.prev_mtu_sz = NSS_GMAC_NORMAL_FRAME_MTU;
917
918 /*
Guojun Jin1cb79522015-06-22 22:34:22 -0700919 * register panic handler and timeout control
920 */
921 nss_coredump_notify_register();
922 nss_coredump_init_delay_work();
923
924 /*
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530925 * Register platform_driver
926 */
927 return platform_driver_register(&nss_driver);
928}
929
930/*
931 * nss_cleanup()
932 * Unregisters nss driver
933 */
934static void __exit nss_cleanup(void)
935{
Xiaoping Fan921869a2015-08-12 17:19:43 -0700936#if (NSS_DT_SUPPORT == 1)
937 struct device_node *cmn = NULL;
938
939 /*
940 * Get reference to NSS common device node
941 */
942 cmn = of_find_node_by_name(NULL, "nss-common");
943 if (!cmn) {
944 nss_info_always("cannot find nss-common node, maybe just for symbol link\n");
945 return;
946 }
947#endif
948
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530949 nss_info("Exit NSS driver");
wthomas442c7972013-08-05 14:28:17 -0700950
951 if (nss_dev_header)
952 unregister_sysctl_table(nss_dev_header);
953
Vijay Dewangan9db18752014-09-15 16:25:01 -0700954 /*
Vijay Dewangan488e5372014-12-29 21:40:11 -0800955 * Unregister n2h specific sysctl
956 */
957 nss_n2h_empty_pool_buf_unregister_sysctl();
958
959 /*
Vijay Dewangan9db18752014-09-15 16:25:01 -0700960 * Unregister ipv4/6 specific sysctl
961 */
962 nss_ipv4_unregister_sysctl();
963 nss_ipv6_unregister_sysctl();
964
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800965#if (NSS_DT_SUPPORT == 1)
966 if(nss_top_main.nss_fpb_base) {
967 iounmap(nss_top_main.nss_fpb_base);
968 nss_top_main.nss_fpb_base = 0;
969 }
970#endif
971
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530972 platform_driver_unregister(&nss_driver);
973}
974
975module_init(nss_init);
976module_exit(nss_cleanup);
977
978MODULE_DESCRIPTION("QCA NSS Driver");
979MODULE_AUTHOR("Qualcomm Atheros Inc");
980MODULE_LICENSE("Dual BSD/GPL");