[9610] wlbt: SCSC Driver version 10.9.1.0
[GitHub/MotorolaMobilityLLC/kernel-slsi.git] / drivers / net / wireless / scsc / hip4.c
1 /******************************************************************************
2 *
3 * Copyright (c) 2014 - 2019 Samsung Electronics Co., Ltd. All rights reserved
4 *
5 *****************************************************************************/
6
7 #include <linux/slab.h>
8 #include <linux/interrupt.h>
9 #include <linux/delay.h>
10 #include <linux/workqueue.h>
11 #include <scsc/scsc_mx.h>
12 #include <scsc/scsc_mifram.h>
13 #include <linux/ktime.h>
14 #include <linux/kthread.h>
15 #include <scsc/scsc_logring.h>
16 #ifdef CONFIG_SCSC_WLAN_RX_NAPI
17 #include <linux/cpu.h>
18 #include <linux/bitmap.h>
19 #endif
20
21 #include "hip4.h"
22 #include "mbulk.h"
23 #include "dev.h"
24 #include "hip4_sampler.h"
25
26 #ifdef CONFIG_ANDROID
27 #include "scsc_wifilogger_rings.h"
28 #endif
29
30 #include "debug.h"
31
32 static bool hip4_system_wq;
33 module_param(hip4_system_wq, bool, S_IRUGO | S_IWUSR);
34 MODULE_PARM_DESC(hip4_system_wq, "Use system wq instead of named workqueue. (default: N)");
35
36 #ifdef CONFIG_SCSC_LOGRING
37 static bool hip4_dynamic_logging = true;
38 module_param(hip4_dynamic_logging, bool, S_IRUGO | S_IWUSR);
39 MODULE_PARM_DESC(hip4_dynamic_logging, "Dynamic logging, logring is disabled if tput > hip4_qos_med_tput_in_mbps. (default: Y)");
40
41 static int hip4_dynamic_logging_tput_in_mbps = 150;
42 module_param(hip4_dynamic_logging_tput_in_mbps, int, S_IRUGO | S_IWUSR);
43 MODULE_PARM_DESC(hip4_dynamic_logging_tput_in_mbps, "throughput (in Mbps) to apply dynamic logring logging");
44 #endif
45
46 #ifdef CONFIG_SCSC_QOS
47 static bool hip4_qos_enable = true;
48 module_param(hip4_qos_enable, bool, S_IRUGO | S_IWUSR);
49 MODULE_PARM_DESC(hip4_qos_enable, "enable HIP4 PM QoS. (default: Y)");
50
51 static int hip4_qos_max_tput_in_mbps = 300;
52 module_param(hip4_qos_max_tput_in_mbps, int, S_IRUGO | S_IWUSR);
53 MODULE_PARM_DESC(hip4_qos_max_tput_in_mbps, "throughput (in Mbps) to apply Max PM QoS");
54
55 static int hip4_qos_med_tput_in_mbps = 150;
56 module_param(hip4_qos_med_tput_in_mbps, int, S_IRUGO | S_IWUSR);
57 MODULE_PARM_DESC(hip4_qos_med_tput_in_mbps, "throughput (in Mbps) to apply Median PM QoS");
58 #endif
59
60 #ifdef CONFIG_SCSC_SMAPPER
61 static bool hip4_smapper_enable;
62 module_param(hip4_smapper_enable, bool, S_IRUGO | S_IWUSR);
63 MODULE_PARM_DESC(hip4_smapper_enable, "enable HIP4 SMAPPER. (default: N)");
64 static bool hip4_smapper_is_enabled;
65 #endif
66
67 #ifdef CONFIG_SCSC_WLAN_RX_NAPI
68 /* run NAPI poll on a specific CPU (preferably a big CPU if online) */
69 static int napi_select_cpu; /* CPU number */
70 module_param(napi_select_cpu, int, 0644);
71 MODULE_PARM_DESC(napi_select_cpu, "select a specific CPU to execute NAPI poll");
72 #endif
73
74 static int max_buffered_frames = 10000;
75 module_param(max_buffered_frames, int, S_IRUGO | S_IWUSR);
76 MODULE_PARM_DESC(max_buffered_frames, "Maximum number of frames to buffer in the driver");
77
78 #ifdef CONFIG_SCSC_WLAN_RX_NAPI
79 static ktime_t intr_received_fb;
80 static ktime_t bh_init_fb;
81 static ktime_t bh_end_fb;
82 static ktime_t intr_received_ctrl;
83 static ktime_t bh_init_ctrl;
84 static ktime_t bh_end_ctrl;
85 static ktime_t intr_received_data;
86 static ktime_t bh_init_data;
87 static ktime_t bh_end_data;
88 #endif
89 static ktime_t intr_received;
90 static ktime_t bh_init;
91 static ktime_t bh_end;
92
93 static ktime_t wdt;
94 static ktime_t send;
95 static ktime_t closing;
96
97 enum rw {
98 widx,
99 ridx,
100 };
101
102 static u8 hip4_read_index(struct slsi_hip4 *hip, u32 q, enum rw r_w);
103
104 /* Q mapping V3 - V4 */
105 /*offset of F/W owned indices */
106 #define FW_OWN_OFS (64)
107 /**
108 * HIP queue indices layout in the scoreboard (SC-505612-DD). v3
109 *
110 * 3 2 1 0
111 * +-----------------------------------+
112 * +0 | Q3R | Q2R | Q1W | Q0W | Owned by the host
113 * +-----------------------------------+
114 * +4 | | | Q5W | Q4R | Owned by the host
115 * +-----------------------------------+
116 *
117 * +-----------------------------------+
118 * +64 | Q3W | Q2W | Q1R | Q0R | Owned by the F/W
119 * +-----------------------------------+
120 * +68 | | | Q5R | Q4W | Owned by the F/W
121 * +-----------------------------------+
122 *
123 * The queue indcies which owned by the host are only writable by the host.
124 * F/W can only read them. And vice versa.
125 */
126 static int q_idx_layout[6][2] = {
127 { 0, FW_OWN_OFS + 0}, /* mif_q_fh_ctl : 0 */
128 { 1, FW_OWN_OFS + 1}, /* mif_q_fh_dat : 1 */
129 { FW_OWN_OFS + 2, 2}, /* mif_q_fh_rfb : 2 */
130 { FW_OWN_OFS + 3, 3}, /* mif_q_th_ctl : 3 */
131 { FW_OWN_OFS + 4, 4}, /* mif_q_th_dat : 4 */
132 { 5, FW_OWN_OFS + 5} /* mif_q_th_rfb : 5 */
133 };
134
135 /*offset of F/W owned VIF Status */
136 #define FW_OWN_VIF (96)
137 /**
138 * HIP Pause state VIF. v4. 2 bits per PEER
139 *
140 * +-----------------------------------+
141 * +96 | VIF[0] Peers [15-1] | Owned by the F/W
142 * +-----------------------------------+
143 * +100 | VIF[0] Peers [31-16] | Owned by the F/W
144 * +-----------------------------------+
145 * +104 | VIF[1] Peers [15-1] | Owned by the F/W
146 * +-----------------------------------+
147 * +108 | VIF[1] Peers [31-16] | Owned by the F/W
148 * +-----------------------------------+
149 * +112 | VIF[2] Peers [15-1] | Owned by the F/W
150 * +-----------------------------------+
151 * +116 | VIF[2] Peers [31-16] | Owned by the F/W
152 * +-----------------------------------+
153 * +120 | VIF[3] Peers [15-1] | Owned by the F/W
154 * +-----------------------------------+
155 * +124 | VIF[3] Peers [31-16] | Owned by the F/W
156 * +-----------------------------------+
157 *
158 */
159
160 /* MAX_STORM. Max Interrupts allowed when platform is in suspend */
161 #define MAX_STORM 5
162
163 /* Timeout for Wakelocks in HIP */
164 #define SLSI_HIP_WAKELOCK_TIME_OUT_IN_MS (1000)
165
166 #ifdef CONFIG_SCSC_WLAN_DEBUG
167
168 static u64 histogram_1;
169 static u64 histogram_2;
170 static u64 histogram_3;
171 static u64 histogram_4;
172 static u64 histogram_5;
173 static u64 histogram_6;
174 static u64 max_jitter;
175
176 #define HISTO_1 1000 /* 1 us */
177 #define HISTO_2 10000 /* 10 us */
178 #define HISTO_3 100000 /* 100 us */
179 #define HISTO_4 1000000 /* 1ms */
180 #define HISTO_5 10000000 /* 10ms */
181
182 static u64 histogram_1_data;
183 static u64 histogram_2_data;
184 static u64 histogram_3_data;
185 static u64 histogram_4_data;
186 static u64 histogram_5_data;
187 static u64 histogram_6_data;
188 static u64 max_data;
189
190 #define HISTO_1_DATA 50 /* 50 th data packets */
191 #define HISTO_2_DATA 100/* 100 th data packets */
192 #define HISTO_3_DATA 150/* 150 th data packets */
193 #define HISTO_4_DATA 200/* 200 th data packets */
194 #define HISTO_5_DATA 250/* 250 th data packets */
195
196 /* MAX_HISTORY_RECORDS should be power of two */
197 #define MAX_HISTORY_RECORDS 32
198
199 #define FH 0
200 #define TH 1
201
202 struct hip4_history {
203 bool dir;
204 u32 signal;
205 u32 cnt;
206 ktime_t last_time;
207 } hip4_signal_history[MAX_HISTORY_RECORDS];
208
209 static u32 history_record;
210
211 /* This function should be called from atomic context */
212 static void hip4_history_record_add(bool dir, u32 signal_id)
213 {
214 struct hip4_history record;
215
216 record = hip4_signal_history[history_record];
217
218 if (record.signal == signal_id && record.dir == dir) {
219 /* If last signal and direction is the same, increment counter */
220 record.last_time = ktime_get();
221 record.cnt += 1;
222 hip4_signal_history[history_record] = record;
223 return;
224 }
225
226 history_record = (history_record + 1) & (MAX_HISTORY_RECORDS - 1);
227
228 record = hip4_signal_history[history_record];
229 record.dir = dir;
230 record.signal = signal_id;
231 record.cnt = 1;
232 record.last_time = ktime_get();
233 hip4_signal_history[history_record] = record;
234 }
235
236 #define HIP4_HISTORY(in_seq_file, m, fmt, arg ...) \
237 do { \
238 if (in_seq_file) \
239 seq_printf(m, fmt, ## arg); \
240 else \
241 SLSI_ERR_NODEV(fmt, ## arg); \
242 } while (0)
243
244 static void hip4_history_record_print(bool in_seq_file, struct seq_file *m)
245 {
246 struct hip4_history record;
247 u32 i, pos;
248 ktime_t old;
249
250 old = ktime_set(0, 0);
251
252 /* Start with the Next record to print history in order */
253 pos = (history_record + 1) & (MAX_HISTORY_RECORDS - 1);
254
255 HIP4_HISTORY(in_seq_file, m, "dir\t signal\t cnt\t last_time(ns) \t\t gap(ns)\n");
256 HIP4_HISTORY(in_seq_file, m, "-----------------------------------------------------------------------------\n");
257 for (i = 0; i < MAX_HISTORY_RECORDS; i++) {
258 record = hip4_signal_history[pos];
259 /*next pos*/
260 if (record.cnt) {
261 HIP4_HISTORY(in_seq_file, m, "%s\t 0x%04x\t %d\t %lld \t%lld\n", record.dir ? "<--TH" : "FH-->",
262 record.signal, record.cnt, ktime_to_ns(record.last_time), ktime_to_ns(ktime_sub(record.last_time, old)));
263 }
264 old = record.last_time;
265 pos = (pos + 1) & (MAX_HISTORY_RECORDS - 1);
266 }
267 }
268
269 static int hip4_proc_show_history(struct seq_file *m, void *v)
270 {
271 hip4_history_record_print(true, m);
272 return 0;
273 }
274
275 static int hip4_proc_history_open(struct inode *inode, struct file *file)
276 {
277 return single_open(file, hip4_proc_show_history, PDE_DATA(inode));
278 }
279
280 static const struct file_operations hip4_procfs_history_fops = {
281 .owner = THIS_MODULE,
282 .open = hip4_proc_history_open,
283 .read = seq_read,
284 .llseek = seq_lseek,
285 .release = single_release,
286 };
287
288 static int hip4_proc_show(struct seq_file *m, void *v)
289 {
290 struct slsi_hip4 *hip = m->private;
291 struct hip4_hip_control *hip_control;
292 struct slsi_dev *sdev = container_of(hip, struct slsi_dev, hip4_inst);
293 u8 i;
294
295 u32 conf_hip4_ver = 0;
296 void *hip_ptr;
297
298 if (!hip->hip_priv) {
299 seq_puts(m, "HIP4 not active\n");
300 return 0;
301 }
302
303 conf_hip4_ver = scsc_wifi_get_hip_config_version(&hip->hip_control->init);
304 /* Check if the version is supported. And get the index */
305 /* This is hardcoded and may change in future versions */
306 if (conf_hip4_ver != 4 && conf_hip4_ver != 3) {
307 SLSI_ERR_NODEV("FW Version %d not supported or Hip has not been set up\n", conf_hip4_ver);
308 return 0;
309 }
310
311 /* hip_ref contains the reference of the start of shared memory allocated for WLAN */
312 /* hip_ptr is the kernel address of hip_ref*/
313 hip_ptr = scsc_mx_service_mif_addr_to_ptr(sdev->service, hip->hip_ref);
314 /* Get hip_control pointer on shared memory */
315 hip_control = (struct hip4_hip_control *)(hip_ptr +
316 HIP4_WLAN_CONFIG_OFFSET);
317
318 seq_puts(m, "-----------------------------------------\n");
319 seq_puts(m, "HIP4 CONFIG:\n");
320 seq_puts(m, "-----------------------------------------\n");
321 seq_printf(m, "config kernel addr = %p\n", hip_control);
322 if (conf_hip4_ver == 4) {
323 seq_printf(m, "hip4_version_4 addr = 0x%p\n", &hip_control->config_v4);
324 seq_printf(m, "magic_number = 0x%x\n", hip_control->config_v4.magic_number);
325 seq_printf(m, "hip_config_ver = 0x%x\n", hip_control->config_v4.hip_config_ver);
326 seq_printf(m, "config_len = 0x%x\n", hip_control->config_v4.config_len);
327 seq_printf(m, "compat_flag = 0x%x\n", hip_control->config_v4.compat_flag);
328 seq_printf(m, "sap_mlme_ver = 0x%x\n", hip_control->config_v4.sap_mlme_ver);
329 seq_printf(m, "sap_ma_ver = 0x%x\n", hip_control->config_v4.sap_ma_ver);
330 seq_printf(m, "sap_debug_ver = 0x%x\n", hip_control->config_v4.sap_debug_ver);
331 seq_printf(m, "sap_test_ver = 0x%x\n", hip_control->config_v4.sap_test_ver);
332 seq_printf(m, "fw_build_id = 0x%x\n", hip_control->config_v4.fw_build_id);
333 seq_printf(m, "fw_patch_id = 0x%x\n", hip_control->config_v4.fw_patch_id);
334 seq_printf(m, "unidat_req_headroom = 0x%x\n", hip_control->config_v4.unidat_req_headroom);
335 seq_printf(m, "unidat_req_tailroom = 0x%x\n", hip_control->config_v4.unidat_req_tailroom);
336 seq_printf(m, "bulk_buffer_align = 0x%x\n", hip_control->config_v4.bulk_buffer_align);
337 seq_printf(m, "host_cache_line = 0x%x\n", hip_control->config_v4.host_cache_line);
338 seq_printf(m, "host_buf_loc = 0x%x\n", hip_control->config_v4.host_buf_loc);
339 seq_printf(m, "host_buf_sz = 0x%x\n", hip_control->config_v4.host_buf_sz);
340 seq_printf(m, "fw_buf_loc = 0x%x\n", hip_control->config_v4.fw_buf_loc);
341 seq_printf(m, "fw_buf_sz = 0x%x\n", hip_control->config_v4.fw_buf_sz);
342 seq_printf(m, "mib_buf_loc = 0x%x\n", hip_control->config_v4.mib_loc);
343 seq_printf(m, "mib_buf_sz = 0x%x\n", hip_control->config_v4.mib_sz);
344 seq_printf(m, "log_config_loc = 0x%x\n", hip_control->config_v4.log_config_loc);
345 seq_printf(m, "log_config_sz = 0x%x\n", hip_control->config_v4.log_config_sz);
346 seq_printf(m, "mif_fh_int_n = 0x%x\n", hip_control->config_v4.mif_fh_int_n);
347 seq_printf(m, "mif_th_int_n[FH_CTRL] = 0x%x\n", hip_control->config_v4.mif_th_int_n[HIP4_MIF_Q_FH_CTRL]);
348 seq_printf(m, "mif_th_int_n[FH_DAT] = 0x%x\n", hip_control->config_v4.mif_th_int_n[HIP4_MIF_Q_FH_DAT]);
349 seq_printf(m, "mif_th_int_n[FH_RFB] = 0x%x\n", hip_control->config_v4.mif_th_int_n[HIP4_MIF_Q_FH_RFB]);
350 seq_printf(m, "mif_th_int_n[TH_CTRL] = 0x%x\n", hip_control->config_v4.mif_th_int_n[HIP4_MIF_Q_TH_CTRL]);
351 seq_printf(m, "mif_th_int_n[TH_DAT] = 0x%x\n", hip_control->config_v4.mif_th_int_n[HIP4_MIF_Q_TH_DAT]);
352 seq_printf(m, "mif_th_int_n[TH_RFB] = 0x%x\n", hip_control->config_v4.mif_th_int_n[HIP4_MIF_Q_TH_RFB]);
353 seq_printf(m, "scbrd_loc = 0x%x\n", hip_control->config_v4.scbrd_loc);
354 seq_printf(m, "q_num = 0x%x\n", hip_control->config_v4.q_num);
355 seq_printf(m, "q_len = 0x%x\n", hip_control->config_v4.q_len);
356 seq_printf(m, "q_idx_sz = 0x%x\n", hip_control->config_v4.q_idx_sz);
357 for (i = 0; i < MIF_HIP_CFG_Q_NUM; i++)
358 seq_printf(m, "q_loc[%d] = 0x%x\n", i, hip_control->config_v4.q_loc[i]);
359 } else if (conf_hip4_ver == 5) {
360 seq_printf(m, "hip4_version_5 addr = 0x%p\n", &hip_control->config_v5);
361 seq_printf(m, "magic_number = 0x%x\n", hip_control->config_v5.magic_number);
362 seq_printf(m, "hip_config_ver = 0x%x\n", hip_control->config_v5.hip_config_ver);
363 seq_printf(m, "config_len = 0x%x\n", hip_control->config_v5.config_len);
364 seq_printf(m, "compat_flag = 0x%x\n", hip_control->config_v5.compat_flag);
365 seq_printf(m, "sap_mlme_ver = 0x%x\n", hip_control->config_v5.sap_mlme_ver);
366 seq_printf(m, "sap_ma_ver = 0x%x\n", hip_control->config_v5.sap_ma_ver);
367 seq_printf(m, "sap_debug_ver = 0x%x\n", hip_control->config_v5.sap_debug_ver);
368 seq_printf(m, "sap_test_ver = 0x%x\n", hip_control->config_v5.sap_test_ver);
369 seq_printf(m, "fw_build_id = 0x%x\n", hip_control->config_v5.fw_build_id);
370 seq_printf(m, "fw_patch_id = 0x%x\n", hip_control->config_v5.fw_patch_id);
371 seq_printf(m, "unidat_req_headroom = 0x%x\n", hip_control->config_v5.unidat_req_headroom);
372 seq_printf(m, "unidat_req_tailroom = 0x%x\n", hip_control->config_v5.unidat_req_tailroom);
373 seq_printf(m, "bulk_buffer_align = 0x%x\n", hip_control->config_v5.bulk_buffer_align);
374 seq_printf(m, "host_cache_line = 0x%x\n", hip_control->config_v5.host_cache_line);
375 seq_printf(m, "host_buf_loc = 0x%x\n", hip_control->config_v5.host_buf_loc);
376 seq_printf(m, "host_buf_sz = 0x%x\n", hip_control->config_v5.host_buf_sz);
377 seq_printf(m, "fw_buf_loc = 0x%x\n", hip_control->config_v5.fw_buf_loc);
378 seq_printf(m, "fw_buf_sz = 0x%x\n", hip_control->config_v5.fw_buf_sz);
379 seq_printf(m, "mib_buf_loc = 0x%x\n", hip_control->config_v5.mib_loc);
380 seq_printf(m, "mib_buf_sz = 0x%x\n", hip_control->config_v5.mib_sz);
381 seq_printf(m, "log_config_loc = 0x%x\n", hip_control->config_v5.log_config_loc);
382 seq_printf(m, "log_config_sz = 0x%x\n", hip_control->config_v5.log_config_sz);
383 seq_printf(m, "mif_fh_int_n = 0x%x\n", hip_control->config_v5.mif_fh_int_n);
384 seq_printf(m, "mif_th_int_n = 0x%x\n", hip_control->config_v5.mif_th_int_n);
385 seq_printf(m, "scbrd_loc = 0x%x\n", hip_control->config_v5.scbrd_loc);
386 seq_printf(m, "q_num = 0x%x\n", hip_control->config_v5.q_num);
387 seq_printf(m, "q_len = 0x%x\n", hip_control->config_v5.q_len);
388 seq_printf(m, "q_idx_sz = 0x%x\n", hip_control->config_v5.q_idx_sz);
389 for (i = 0; i < MIF_HIP_CFG_Q_NUM; i++)
390 seq_printf(m, "q_loc[%d] = 0x%x\n", i, hip_control->config_v5.q_loc[i]);
391 }
392 seq_puts(m, "\n-----------------------------------------\n");
393 seq_puts(m, "HIP4 SCOREBOARD INDEXES:\n");
394 seq_puts(m, "-----------------------------------------\n");
395 seq_printf(m, "ktime start %lld (ns)\n", ktime_to_ns(hip->hip_priv->stats.start));
396 seq_printf(m, "ktime now %lld (ns)\n\n", ktime_to_ns(ktime_get()));
397
398 seq_printf(m, "rx_intr_tohost 0x%x\n", hip->hip_priv->intr_tohost);
399 seq_printf(m, "rx_intr_fromhost 0x%x\n\n", hip->hip_priv->intr_fromhost);
400
401 /* HIP statistics */
402 seq_printf(m, "HIP IRQs: %u\n", atomic_read(&hip->hip_priv->stats.irqs));
403 seq_printf(m, "HIP IRQs spurious: %u\n", atomic_read(&hip->hip_priv->stats.spurious_irqs));
404 seq_printf(m, "FW debug-inds: %u\n\n", atomic_read(&sdev->debug_inds));
405
406 seq_puts(m, "Queue\tIndex\tFrames\n");
407 seq_puts(m, "-----\t-----\t------\n");
408 /* Print scoreboard */
409 for (i = 0; i < MIF_HIP_CFG_Q_NUM; i++) {
410 seq_printf(m, "Q%dW\t0x%x\t\n", i, hip4_read_index(hip, i, widx));
411 seq_printf(m, "Q%dR\t0x%x\t%d\n", i, hip4_read_index(hip, i, ridx), hip->hip_priv->stats.q_num_frames[i]);
412 }
413 seq_puts(m, "\n");
414 return 0;
415 }
416
417 static int hip4_proc_open(struct inode *inode, struct file *file)
418 {
419 return single_open(file, hip4_proc_show, PDE_DATA(inode));
420 }
421
422 static const struct file_operations hip4_procfs_stats_fops = {
423 .owner = THIS_MODULE,
424 .open = hip4_proc_open,
425 .read = seq_read,
426 .llseek = seq_lseek,
427 .release = single_release,
428 };
429
430 static int hip4_proc_jitter_show(struct seq_file *m, void *v)
431 {
432 seq_puts(m, "Values in ns\n");
433 seq_printf(m, "<%d(ns)\t\t\t\t %lld\n", HISTO_1, histogram_1);
434 seq_printf(m, "%d(ns)-%d(ns)\t\t\t %lld\n", HISTO_1, HISTO_2, histogram_2);
435 seq_printf(m, "%d(ns)-%d(ns)\t\t\t %lld\n", HISTO_2, HISTO_3, histogram_3);
436 seq_printf(m, "%d(ns)-%d(ns)\t\t\t %lld\n", HISTO_3, HISTO_4, histogram_4);
437 seq_printf(m, "%d(ns)-%d(ns)\t\t %lld\n", HISTO_4, HISTO_5, histogram_5);
438 seq_printf(m, ">%d(ns)\t\t\t\t %lld\n", HISTO_5, histogram_6);
439 seq_printf(m, "max jitter(ns)\t\t\t\t %lld\n", max_jitter);
440 seq_puts(m, "--------------------------\n");
441 seq_puts(m, "Packets in TH DATA Q\n");
442 seq_printf(m, "<%d\t\t%lld\n", HISTO_1_DATA, histogram_1_data);
443 seq_printf(m, "%d-%d\t\t%lld\n", HISTO_1_DATA, HISTO_2_DATA, histogram_2_data);
444 seq_printf(m, "%d-%d\t\t%lld\n", HISTO_2_DATA, HISTO_3_DATA, histogram_3_data);
445 seq_printf(m, "%d-%d\t\t%lld\n", HISTO_3_DATA, HISTO_4_DATA, histogram_4_data);
446 seq_printf(m, "%d-%d\t\t%lld\n", HISTO_4_DATA, HISTO_5_DATA, histogram_5_data);
447 seq_printf(m, ">%d\t\t%lld\n", HISTO_5_DATA, histogram_6_data);
448 seq_printf(m, "max data\t%lld\n", max_data);
449 return 0;
450 }
451
452 static int hip4_proc_jitter_open(struct inode *inode, struct file *file)
453 {
454 return single_open(file, hip4_proc_jitter_show, PDE_DATA(inode));
455 }
456
457 static ssize_t hip4_proc_jitter_clear(struct file *file, const char __user *user_buf, size_t count, loff_t *ppos)
458 {
459 SLSI_INFO_NODEV("Clear Histogram\n");
460
461 histogram_1 = 0;
462 histogram_2 = 0;
463 histogram_3 = 0;
464 histogram_4 = 0;
465 histogram_5 = 0;
466 histogram_6 = 0;
467 max_jitter = 0;
468
469 histogram_1_data = 0;
470 histogram_2_data = 0;
471 histogram_3_data = 0;
472 histogram_4_data = 0;
473 histogram_5_data = 0;
474 histogram_6_data = 0;
475 max_data = 0;
476
477 return count;
478 }
479
480 static const struct file_operations hip4_procfs_jitter_fops = {
481 .owner = THIS_MODULE,
482 .open = hip4_proc_jitter_open,
483 .write = hip4_proc_jitter_clear,
484 .read = seq_read,
485 .llseek = seq_lseek,
486 .release = single_release,
487 };
488 #endif
489
490 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 11, 0))
491 static inline ktime_t ktime_add_ms(const ktime_t kt, const u64 msec)
492 {
493 return ktime_add_ns(kt, msec * NSEC_PER_MSEC);
494 }
495 #endif
496
497 #define FB_NO_SPC_NUM_RET 100
498 #define FB_NO_SPC_SLEEP_MS 10
499 #define FB_NO_SPC_DELAY_US 1000
500
501 /* Update scoreboard index */
502 /* Function can be called from BH context */
503 static void hip4_update_index(struct slsi_hip4 *hip, u32 q, enum rw r_w, u8 value)
504 {
505 struct hip4_priv *hip_priv = hip->hip_priv;
506
507 write_lock_bh(&hip_priv->rw_scoreboard);
508 if (hip->hip_priv->version == 5 || hip->hip_priv->version == 4) {
509 *((u8 *)(hip->hip_priv->scbrd_base + q_idx_layout[q][r_w])) = value;
510 } else {
511 SLSI_ERR_NODEV("Incorrect version\n");
512 goto error;
513 }
514
515 /* Memory barrier when updating shared mailbox/memory */
516 smp_wmb();
517 SCSC_HIP4_SAMPLER_Q(hip_priv->minor, q, r_w, value, 0);
518 error:
519 write_unlock_bh(&hip_priv->rw_scoreboard);
520 }
521
522 /* Read scoreboard index */
523 /* Function can be called from BH context */
524 static u8 hip4_read_index(struct slsi_hip4 *hip, u32 q, enum rw r_w)
525 {
526 struct hip4_priv *hip_priv = hip->hip_priv;
527 u32 value = 0;
528
529 read_lock_bh(&hip_priv->rw_scoreboard);
530 if (hip->hip_priv->version == 5 || hip->hip_priv->version == 4) {
531 value = *((u8 *)(hip->hip_priv->scbrd_base + q_idx_layout[q][r_w]));
532 } else {
533 SLSI_ERR_NODEV("Incorrect version\n");
534 goto error;
535 }
536
537 /* Memory barrier when reading shared mailbox/memory */
538 smp_rmb();
539 error:
540 read_unlock_bh(&hip_priv->rw_scoreboard);
541 return value;
542 }
543
544 static void hip4_dump_dbg(struct slsi_hip4 *hip, struct mbulk *m, struct sk_buff *skb, struct scsc_service *service)
545 {
546 unsigned int i = 0;
547 scsc_mifram_ref ref;
548 #ifdef CONFIG_SCSC_WLAN_RX_NAPI
549 u32 conf_hip4_ver = 0;
550
551 conf_hip4_ver = scsc_wifi_get_hip_config_version(&hip->hip_control->init);
552
553 if (conf_hip4_ver == 4) {
554 SLSI_ERR_NODEV("intr_tohost_fb 0x%x\n", hip->hip_priv->intr_tohost_mul[HIP4_MIF_Q_FH_RFB]);
555 SLSI_ERR_NODEV("intr_tohost_ctrl 0x%x\n", hip->hip_priv->intr_tohost_mul[HIP4_MIF_Q_TH_CTRL]);
556 SLSI_ERR_NODEV("intr_tohost_dat 0x%x\n", hip->hip_priv->intr_tohost_mul[HIP4_MIF_Q_TH_DAT]);
557 } else {
558 SLSI_ERR_NODEV("intr_tohost 0x%x\n", hip->hip_priv->intr_tohost);
559 }
560 #else
561 SLSI_ERR_NODEV("intr_tohost 0x%x\n", hip->hip_priv->intr_tohost);
562 #endif
563 SLSI_ERR_NODEV("intr_fromhost 0x%x\n", hip->hip_priv->intr_fromhost);
564
565 /* Print scoreboard */
566 for (i = 0; i < 6; i++) {
567 SLSI_ERR_NODEV("Q%dW 0x%x\n", i, hip4_read_index(hip, i, widx));
568 SLSI_ERR_NODEV("Q%dR 0x%x\n", i, hip4_read_index(hip, i, ridx));
569 }
570
571 if (service)
572 scsc_mx_service_mif_dump_registers(service);
573
574 if (m && service) {
575 if (scsc_mx_service_mif_ptr_to_addr(service, m, &ref))
576 return;
577 SLSI_ERR_NODEV("m: %p 0x%x\n", m, ref);
578 print_hex_dump(KERN_ERR, SCSC_PREFIX "mbulk ", DUMP_PREFIX_NONE, 16, 1, m, sizeof(struct mbulk), 0);
579 }
580 if (m && mbulk_has_signal(m))
581 print_hex_dump(KERN_ERR, SCSC_PREFIX "sig ", DUMP_PREFIX_NONE, 16, 1, mbulk_get_signal(m),
582 MBULK_SEG_SIG_BUFSIZE(m), 0);
583 if (skb)
584 print_hex_dump(KERN_ERR, SCSC_PREFIX "skb ", DUMP_PREFIX_NONE, 16, 1, skb->data, skb->len > 0xff ? 0xff : skb->len, 0);
585
586 SLSI_ERR_NODEV("time: wdt %lld\n", ktime_to_ns(wdt));
587 SLSI_ERR_NODEV("time: send %lld\n", ktime_to_ns(send));
588 #ifdef CONFIG_SCSC_WLAN_RX_NAPI
589 if (conf_hip4_ver == 4) {
590 SLSI_ERR_NODEV("time: intr_fb %lld\n", ktime_to_ns(intr_received_fb));
591 SLSI_ERR_NODEV("time: bh_init_fb %lld\n", ktime_to_ns(bh_init_fb));
592 SLSI_ERR_NODEV("time: bh_end_fb %lld\n", ktime_to_ns(bh_end_fb));
593 SLSI_ERR_NODEV("time: intr_ctrl %lld\n", ktime_to_ns(intr_received_ctrl));
594 SLSI_ERR_NODEV("time: bh_init_ctrl %lld\n", ktime_to_ns(bh_init_ctrl));
595 SLSI_ERR_NODEV("time: bh_end_ctrl %lld\n", ktime_to_ns(bh_end_ctrl));
596 SLSI_ERR_NODEV("time: intr_data %lld\n", ktime_to_ns(intr_received_data));
597 SLSI_ERR_NODEV("time: bh_init_data %lld\n", ktime_to_ns(bh_init_data));
598 SLSI_ERR_NODEV("time: bh_end_data %lld\n", ktime_to_ns(bh_end_data));
599 } else {
600 SLSI_ERR_NODEV("time: intr %lld\n", ktime_to_ns(intr_received));
601 SLSI_ERR_NODEV("time: bh_init %lld\n", ktime_to_ns(bh_init));
602 SLSI_ERR_NODEV("time: bh_end %lld\n", ktime_to_ns(bh_end));
603 }
604 #else
605 SLSI_ERR_NODEV("time: intr %lld\n", ktime_to_ns(intr_received));
606 SLSI_ERR_NODEV("time: bh_init %lld\n", ktime_to_ns(bh_init));
607 SLSI_ERR_NODEV("time: bh_end %lld\n", ktime_to_ns(bh_end));
608 #endif
609 SLSI_ERR_NODEV("time: closing %lld\n", ktime_to_ns(closing));
610 #ifdef CONFIG_SCSC_WLAN_DEBUG
611 /* Discard noise if it is a mbulk/skb issue */
612 if (!skb && !m)
613 hip4_history_record_print(false, NULL);
614 #endif
615 }
616
617 /* Transform skb to mbulk (fapi_signal + payload) */
618 static struct mbulk *hip4_skb_to_mbulk(struct hip4_priv *hip, struct sk_buff *skb, bool ctrl_packet)
619 {
620 struct mbulk *m = NULL;
621 void *sig = NULL, *b_data = NULL;
622 size_t payload = 0;
623 u8 pool_id = ctrl_packet ? MBULK_POOL_ID_CTRL : MBULK_POOL_ID_DATA;
624 u8 headroom = 0, tailroom = 0;
625 enum mbulk_class clas = ctrl_packet ? MBULK_CLASS_FROM_HOST_CTL : MBULK_CLASS_FROM_HOST_DAT;
626 struct slsi_skb_cb *cb = slsi_skb_cb_get(skb);
627 #ifdef CONFIG_SCSC_WLAN_SG
628 u32 linear_data;
629 u32 offset;
630 u8 i;
631 #endif
632
633 payload = skb->len - cb->sig_length;
634
635 /* Get headroom/tailroom */
636 headroom = hip->unidat_req_headroom;
637 tailroom = hip->unidat_req_tailroom;
638
639 /* Allocate mbulk */
640 if (payload > 0) {
641 /* If signal include payload, add headroom and tailroom */
642 m = mbulk_with_signal_alloc_by_pool(pool_id, cb->colour, clas, cb->sig_length + 4,
643 payload + headroom + tailroom);
644 if (!m)
645 return NULL;
646 if (!mbulk_reserve_head(m, headroom))
647 return NULL;
648 } else {
649 /* If it is only a signal do not add headroom */
650 m = mbulk_with_signal_alloc_by_pool(pool_id, cb->colour, clas, cb->sig_length + 4, 0);
651 if (!m)
652 return NULL;
653 }
654
655 /* Get signal handler */
656 sig = mbulk_get_signal(m);
657 if (!sig) {
658 mbulk_free_virt_host(m);
659 return NULL;
660 }
661
662 /* Copy signal */
663 /* 4Bytes offset is required for FW fapi header */
664 memcpy(sig + 4, skb->data, cb->sig_length);
665
666 /* Copy payload */
667 /* If the signal has payload memcpy the data */
668 if (payload > 0) {
669 /* Get head pointer */
670 b_data = mbulk_dat_rw(m);
671 if (!b_data) {
672 mbulk_free_virt_host(m);
673 return NULL;
674 }
675
676 #ifdef CONFIG_SCSC_WLAN_SG
677 /* The amount of non-paged data at skb->data can be calculated as skb->len - skb->data_len.
678 * Helper routine: skb_headlen() .
679 */
680 linear_data = skb_headlen(skb) - cb->sig_length;
681
682 offset = 0;
683 /* Copy the linear data */
684 if (linear_data > 0) {
685 /* Copy the linear payload skipping the signal data */
686 memcpy(b_data, skb->data + cb->sig_length, linear_data);
687 offset = linear_data;
688 }
689
690 /* Traverse fragments and copy in to linear DRAM memory */
691 for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
692 skb_frag_t *frag = NULL;
693 void *frag_va_data;
694 unsigned int frag_size;
695
696 frag = &skb_shinfo(skb)->frags[i];
697 WARN_ON(!frag);
698 if (!frag)
699 continue;
700 frag_va_data = skb_frag_address_safe(frag);
701 WARN_ON(!frag_va_data);
702 if (!frag_va_data)
703 continue;
704 frag_size = skb_frag_size(frag);
705 /* Copy the fragmented data */
706 memcpy(b_data + offset, frag_va_data, frag_size);
707 offset += frag_size;
708 }
709
710 /* Check whether the driver should perform the checksum */
711 if (skb->ip_summed == CHECKSUM_PARTIAL) {
712 SLSI_DBG3_NODEV(SLSI_HIP, "CHECKSUM_PARTIAL. Driver performing checksum\n");
713 if (skb->protocol == htons(ETH_P_IP)) {
714 struct ethhdr *mach = (struct ethhdr *)b_data;
715 struct iphdr *iph = (struct iphdr *)((char *)b_data + sizeof(*mach));
716 unsigned int len = payload - sizeof(*mach) - (iph->ihl << 2);
717
718 if (iph->protocol == IPPROTO_TCP) {
719 struct tcphdr *th = (struct tcphdr *)((char *)b_data + sizeof(*mach) +
720 (iph->ihl << 2));
721 th->check = 0;
722 th->check = csum_tcpudp_magic(iph->saddr, iph->daddr, len,
723 IPPROTO_TCP,
724 csum_partial((char *)th, len, 0));
725 SLSI_DBG3_NODEV(SLSI_HIP, "th->check 0x%x\n", ntohs(th->check));
726 } else if (iph->protocol == IPPROTO_UDP) {
727 struct udphdr *uh = (struct udphdr *)((char *)b_data + sizeof(*mach) +
728 (iph->ihl << 2));
729 uh->check = 0;
730 uh->check = csum_tcpudp_magic(iph->saddr, iph->daddr, len,
731 IPPROTO_UDP,
732 csum_partial((char *)uh, len, 0));
733 SLSI_DBG3_NODEV(SLSI_HIP, "uh->check 0x%x\n", ntohs(uh->check));
734 }
735 }
736 }
737 #else
738 /* Copy payload skipping the signal data */
739 memcpy(b_data, skb->data + cb->sig_length, payload);
740 #endif
741 mbulk_append_tail(m, payload);
742 }
743 m->flag |= MBULK_F_OBOUND;
744
745 #ifdef CONFIG_SCSC_SMAPPER
746 /* Clear smapper field */
747 cb->skb_addr = NULL;
748 #endif
749 return m;
750 }
751
752 /* Transform mbulk to skb (fapi_signal + payload) */
753 static struct sk_buff *hip4_mbulk_to_skb(struct scsc_service *service, struct hip4_priv *hip_priv, struct mbulk *m, scsc_mifram_ref *to_free, bool atomic)
754 {
755 struct slsi_skb_cb *cb;
756 struct mbulk *next_mbulk[MBULK_MAX_CHAIN];
757 struct sk_buff *skb = NULL;
758 scsc_mifram_ref ref;
759 scsc_mifram_ref m_chain_next;
760 u8 free = 0;
761 u8 i = 0, j = 0;
762 u8 *p;
763 size_t bytes_to_alloc = 0;
764
765 /* Get the mif ref pointer, check for incorrect mbulk */
766 if (scsc_mx_service_mif_ptr_to_addr(service, m, &ref)) {
767 SLSI_ERR_NODEV("mbulk address conversion failed\n");
768 return NULL;
769 }
770
771 /* Track mbulk that should be freed */
772 to_free[free++] = ref;
773
774 bytes_to_alloc += m->sig_bufsz - 4;
775 bytes_to_alloc += m->len;
776
777 /* Detect Chained mbulk to start building the chain */
778 if ((MBULK_SEG_IS_CHAIN_HEAD(m)) && (MBULK_SEG_IS_CHAINED(m))) {
779 m_chain_next = mbulk_chain_next(m);
780 if (!m_chain_next) {
781 SLSI_ERR_NODEV("Mbulk is set MBULK_F_CHAIN_HEAD and MBULK_F_CHAIN but m_chain_next is NULL\n");
782 goto cont;
783 }
784 while (1) {
785 /* increase number mbulks in chain */
786 i++;
787 /* Get next_mbulk kernel address space pointer */
788 next_mbulk[i - 1] = scsc_mx_service_mif_addr_to_ptr(service, m_chain_next);
789 if (!next_mbulk[i - 1]) {
790 SLSI_ERR_NODEV("First Mbulk is set as MBULK_F_CHAIN but next_mbulk is NULL\n");
791 return NULL;
792 }
793 /* Track mbulk to be freed */
794 to_free[free++] = m_chain_next;
795 bytes_to_alloc += next_mbulk[i - 1]->len;
796 if (MBULK_SEG_IS_CHAINED(next_mbulk[i - 1])) {
797 /* continue traversing the chain */
798 m_chain_next = mbulk_chain_next(next_mbulk[i - 1]);
799 if (!m_chain_next)
800 break;
801
802 if (i >= MBULK_MAX_CHAIN) {
803 SLSI_ERR_NODEV("Max number of chained MBULK reached\n");
804 return NULL;
805 }
806 } else {
807 break;
808 }
809 }
810 }
811
812 cont:
813 if (atomic)
814 skb = slsi_alloc_skb(bytes_to_alloc, GFP_ATOMIC);
815 else {
816 spin_unlock_bh(&hip_priv->rx_lock);
817 skb = slsi_alloc_skb(bytes_to_alloc, GFP_KERNEL);
818 spin_lock_bh(&hip_priv->rx_lock);
819 }
820 if (!skb) {
821 SLSI_ERR_NODEV("Error allocating skb %d bytes\n", bytes_to_alloc);
822 return NULL;
823 }
824
825 cb = slsi_skb_cb_init(skb);
826 cb->sig_length = m->sig_bufsz - 4;
827 /* fapi_data_append adds to the data_length */
828 cb->data_length = cb->sig_length;
829
830 p = mbulk_get_signal(m);
831 if (!p) {
832 SLSI_ERR_NODEV("No signal in Mbulk\n");
833 print_hex_dump(KERN_ERR, SCSC_PREFIX "mbulk ", DUMP_PREFIX_NONE, 16, 1, m, sizeof(struct mbulk), 0);
834 slsi_kfree_skb(skb);
835 return NULL;
836 }
837 /* Remove 4Bytes offset coming from FW */
838 p += 4;
839
840 /* Don't need to copy the 4Bytes header coming from the FW */
841 memcpy(skb_put(skb, cb->sig_length), p, cb->sig_length);
842
843 if (m->len)
844 fapi_append_data(skb, mbulk_dat_r(m), m->len);
845 for (j = 0; j < i; j++)
846 fapi_append_data(skb, mbulk_dat_r(next_mbulk[j]), next_mbulk[j]->len);
847
848 return skb;
849 }
850
851 /* Add signal reference (offset in shared memory) in the selected queue */
852 /* This function should be called in atomic context. Callers should supply proper locking mechanism */
853 static int hip4_q_add_signal(struct slsi_hip4 *hip, enum hip4_hip_q_conf conf, scsc_mifram_ref phy_m, struct scsc_service *service)
854 {
855 struct hip4_hip_control *ctrl = hip->hip_control;
856 struct hip4_priv *hip_priv = hip->hip_priv;
857 u8 idx_w;
858 u8 idx_r;
859
860 /* Read the current q write pointer */
861 idx_w = hip4_read_index(hip, conf, widx);
862 /* Read the current q read pointer */
863 idx_r = hip4_read_index(hip, conf, ridx);
864 SCSC_HIP4_SAMPLER_Q(hip_priv->minor, conf, widx, idx_w, 1);
865 SCSC_HIP4_SAMPLER_Q(hip_priv->minor, conf, ridx, idx_r, 1);
866
867 /* Queueu is full */
868 if (idx_r == ((idx_w + 1) & (MAX_NUM - 1)))
869 return -ENOSPC;
870
871 /* Update array */
872 ctrl->q[conf].array[idx_w] = phy_m;
873 /* Memory barrier before updating shared mailbox */
874 smp_wmb();
875 SCSC_HIP4_SAMPLER_QREF(hip_priv->minor, phy_m, conf);
876 #ifdef CONFIG_SCSC_WLAN_DEBUG
877 hip->hip_priv->stats.q_num_frames[conf] = hip->hip_priv->stats.q_num_frames[conf] + 1;
878 #endif
879
880 /* Increase index */
881 idx_w++;
882 idx_w &= (MAX_NUM - 1);
883
884 /* Update the scoreboard */
885 hip4_update_index(hip, conf, widx, idx_w);
886
887 send = ktime_get();
888 scsc_service_mifintrbit_bit_set(service, hip_priv->intr_fromhost, SCSC_MIFINTR_TARGET_R4);
889
890 return 0;
891 }
892
893 #if KERNEL_VERSION(4, 15, 0) <= LINUX_VERSION_CODE
894 static void hip4_watchdog(struct timer_list *t)
895 #else
896 static void hip4_watchdog(unsigned long data)
897 #endif
898 {
899 #if KERNEL_VERSION(4, 15, 0) <= LINUX_VERSION_CODE
900 struct hip4_priv *priv = from_timer(priv, t, watchdog);
901 struct slsi_hip4 *hip = priv->hip;
902 #else
903 struct slsi_hip4 *hip = (struct slsi_hip4 *)data;
904 #endif
905 struct slsi_dev *sdev = container_of(hip, struct slsi_dev, hip4_inst);
906 struct scsc_service *service;
907 ktime_t intr_ov;
908 unsigned long flags;
909 #ifdef CONFIG_SCSC_WLAN_RX_NAPI
910 bool retrigger_watchdog = true;
911 u32 conf_hip4_ver = 0;
912 #endif
913
914 if (!hip || !sdev || !sdev->service || !hip->hip_priv)
915 return;
916
917 spin_lock_irqsave(&hip->hip_priv->watchdog_lock, flags);
918 if (!atomic_read(&hip->hip_priv->watchdog_timer_active))
919 goto exit;
920
921 wdt = ktime_get();
922
923 #ifdef CONFIG_SCSC_WLAN_RX_NAPI
924 conf_hip4_ver = scsc_wifi_get_hip_config_version(&hip->hip_control->init);
925
926 if (conf_hip4_ver == 4) {
927 /* if intr_received > wdt skip as intr has been unblocked */
928 if (test_and_clear_bit(HIP4_MIF_Q_FH_RFB, hip->hip_priv->irq_bitmap)) {
929 intr_ov = ktime_add_ms(intr_received_fb, jiffies_to_msecs(HZ));
930 if ((ktime_compare(intr_ov, wdt) < 0))
931 retrigger_watchdog = false;
932 }
933 if (test_and_clear_bit(HIP4_MIF_Q_TH_CTRL, hip->hip_priv->irq_bitmap)) {
934 intr_ov = ktime_add_ms(intr_received_ctrl, jiffies_to_msecs(HZ));
935 if ((ktime_compare(intr_ov, wdt) < 0))
936 retrigger_watchdog = false;
937 }
938 if (test_and_clear_bit(HIP4_MIF_Q_TH_DAT, hip->hip_priv->irq_bitmap)) {
939 intr_ov = ktime_add_ms(intr_received_data, jiffies_to_msecs(HZ));
940 if ((ktime_compare(intr_ov, wdt) < 0))
941 retrigger_watchdog = false;
942 }
943 if (retrigger_watchdog) {
944 wdt = ktime_set(0, 0);
945 /* Retrigger WDT to check flags again in the future */
946 mod_timer(&hip->hip_priv->watchdog, jiffies + HZ / 2);
947 goto exit;
948 }
949 } else {
950 /* if intr_received > wdt skip as intr has been unblocked */
951 if (ktime_compare(intr_received, wdt) > 0) {
952 wdt = ktime_set(0, 0);
953 goto exit;
954 }
955
956 intr_ov = ktime_add_ms(intr_received, jiffies_to_msecs(HZ));
957
958 /* Check that wdt is > 1 HZ intr */
959 if (!(ktime_compare(intr_ov, wdt) < 0)) {
960 wdt = ktime_set(0, 0);
961 /* Retrigger WDT to check flags again in the future */
962 mod_timer(&hip->hip_priv->watchdog, jiffies + HZ / 2);
963 goto exit;
964 }
965 }
966 #else
967 /* if intr_received > wdt skip as intr has been unblocked */
968 if (ktime_compare(intr_received, wdt) > 0) {
969 wdt = ktime_set(0, 0);
970 goto exit;
971 }
972
973 intr_ov = ktime_add_ms(intr_received, jiffies_to_msecs(HZ));
974
975 /* Check that wdt is > 1 HZ intr */
976 if (!(ktime_compare(intr_ov, wdt) < 0)) {
977 wdt = ktime_set(0, 0);
978 /* Retrigger WDT to check flags again in the future */
979 mod_timer(&hip->hip_priv->watchdog, jiffies + HZ / 2);
980 goto exit;
981 }
982 #endif
983
984 /* Unlock irq to avoid __local_bh_enable_ip warning */
985 spin_unlock_irqrestore(&hip->hip_priv->watchdog_lock, flags);
986 hip4_dump_dbg(hip, NULL, NULL, sdev->service);
987 spin_lock_irqsave(&hip->hip_priv->watchdog_lock, flags);
988
989 service = sdev->service;
990
991 SLSI_INFO_NODEV("Hip4 watchdog triggered\n");
992
993 #ifdef CONFIG_SCSC_WLAN_RX_NAPI
994 if (conf_hip4_ver == 4) {
995 u8 i;
996 for (i = 0; i < MIF_HIP_CFG_Q_NUM; i++) {
997 if (hip->hip_priv->intr_tohost_mul[i] == MIF_NO_IRQ)
998 continue;
999 if (scsc_service_mifintrbit_bit_mask_status_get(service) & (1 << hip->hip_priv->intr_tohost_mul[i])) {
1000 /* Interrupt might be pending! */
1001 SLSI_INFO_NODEV("%d: Interrupt Masked. Unmask to restart Interrupt processing\n", i);
1002 scsc_service_mifintrbit_bit_unmask(service, hip->hip_priv->intr_tohost_mul[i]);
1003 }
1004 }
1005 } else {
1006 if (scsc_service_mifintrbit_bit_mask_status_get(service) & (1 << hip->hip_priv->intr_tohost)) {
1007 /* Interrupt might be pending! */
1008 SLSI_INFO_NODEV("Interrupt Masked. Unmask to restart Interrupt processing\n");
1009 scsc_service_mifintrbit_bit_unmask(service, hip->hip_priv->intr_tohost);
1010 }
1011 }
1012 #else
1013 if (scsc_service_mifintrbit_bit_mask_status_get(service) & (1 << hip->hip_priv->intr_tohost)) {
1014 /* Interrupt might be pending! */
1015 SLSI_INFO_NODEV("Interrupt Masked. Unmask to restart Interrupt processing\n");
1016 scsc_service_mifintrbit_bit_unmask(service, hip->hip_priv->intr_tohost);
1017 }
1018 #endif
1019 exit:
1020 spin_unlock_irqrestore(&hip->hip_priv->watchdog_lock, flags);
1021 }
1022
1023 #ifdef CONFIG_SCSC_WLAN_RX_NAPI
1024 static void hip4_wq_fb(struct work_struct *data)
1025 {
1026 struct hip4_priv *hip_priv = container_of(data, struct hip4_priv, intr_wq_fb);
1027 struct slsi_hip4 *hip;
1028 struct hip4_hip_control *ctrl;
1029 struct scsc_service *service;
1030 struct slsi_dev *sdev;
1031 bool no_change = true;
1032 u8 idx_r;
1033 u8 idx_w;
1034 scsc_mifram_ref ref;
1035 void *mem;
1036
1037 if (!hip_priv || !hip_priv->hip) {
1038 SLSI_ERR_NODEV("hip_priv or hip_priv->hip is Null\n");
1039 return;
1040 }
1041
1042 hip = hip_priv->hip;
1043 ctrl = hip->hip_control;
1044
1045 if (!ctrl) {
1046 SLSI_ERR_NODEV("hip->hip_control is Null\n");
1047 return;
1048 }
1049 sdev = container_of(hip, struct slsi_dev, hip4_inst);
1050
1051 if (!sdev || !sdev->service) {
1052 SLSI_ERR_NODEV("sdev or sdev->service is Null\n");
1053 return;
1054 }
1055
1056 spin_lock_bh(&hip_priv->rx_lock);
1057 service = sdev->service;
1058 SCSC_HIP4_SAMPLER_INT_BH(hip->hip_priv->minor, 2);
1059 bh_init_fb = ktime_get();
1060 clear_bit(HIP4_MIF_Q_FH_RFB, hip->hip_priv->irq_bitmap);
1061
1062 idx_r = hip4_read_index(hip, HIP4_MIF_Q_FH_RFB, ridx);
1063 idx_w = hip4_read_index(hip, HIP4_MIF_Q_FH_RFB, widx);
1064
1065 #ifdef CONFIG_SCSC_WLAN_HIP4_PROFILING
1066 if (idx_r != idx_w) {
1067 SCSC_HIP4_SAMPLER_Q(hip_priv->minor, HIP4_MIF_Q_FH_RFB, ridx, idx_r, 1);
1068 SCSC_HIP4_SAMPLER_Q(hip_priv->minor, HIP4_MIF_Q_FH_RFB, widx, idx_w, 1);
1069 }
1070 #endif
1071 while (idx_r != idx_w) {
1072 struct mbulk *m;
1073 u16 colour;
1074
1075 no_change = false;
1076 ref = ctrl->q[HIP4_MIF_Q_FH_RFB].array[idx_r];
1077 #ifdef CONFIG_SCSC_WLAN_HIP4_PROFILING
1078 SCSC_HIP4_SAMPLER_QREF(hip_priv->minor, ref, HIP4_MIF_Q_FH_RFB);
1079 #endif
1080 mem = scsc_mx_service_mif_addr_to_ptr(service, ref);
1081 m = (struct mbulk *)mem;
1082
1083 if (!m) {
1084 SLSI_ERR_NODEV("FB: Mbulk is NULL\n");
1085 goto consume_fb_mbulk;
1086 }
1087 /* colour is defined as: */
1088 /* u16 register bits:
1089 * 0 - do not use
1090 * [3:1] - vif
1091 * [7:4] - peer_index
1092 * [10:8] - ac queue
1093 */
1094 colour = ((m->clas & 0xc0) << 2) | (m->pid & 0xfe);
1095 /* Account ONLY for data RFB */
1096 if ((m->pid & 0x1) == MBULK_POOL_ID_DATA) {
1097 #ifdef CONFIG_SCSC_WLAN_HIP4_PROFILING
1098 SCSC_HIP4_SAMPLER_VIF_PEER(hip->hip_priv->minor, 0, (colour & 0xE) >> 1, (colour & 0xF0) >> 4);
1099 /* to profile round-trip */
1100 {
1101 u16 host_tag;
1102 u8 *get_host_tag;
1103 /* This is a nasty way of getting the host_tag without involving mbulk processing
1104 * This hostag value should also be include in the cb descriptor which goes to
1105 * mbulk descriptor (no room left at the moment)
1106 */
1107 get_host_tag = (u8 *)m;
1108 host_tag = get_host_tag[37] << 8 | get_host_tag[36];
1109 SCSC_HIP4_SAMPLER_PKT_TX_FB(hip->hip_priv->minor, host_tag);
1110 }
1111 #endif
1112 /* Ignore return value */
1113 slsi_hip_tx_done(sdev, colour);
1114 }
1115 mbulk_free_virt_host(m);
1116 consume_fb_mbulk:
1117 /* Increase index */
1118 idx_r++;
1119 idx_r &= (MAX_NUM - 1);
1120 hip4_update_index(hip, HIP4_MIF_Q_FH_RFB, ridx, idx_r);
1121 }
1122
1123 if (no_change)
1124 atomic_inc(&hip->hip_priv->stats.spurious_irqs);
1125
1126 if (!atomic_read(&hip->hip_priv->closing)) {
1127 atomic_set(&hip->hip_priv->watchdog_timer_active, 0);
1128 scsc_service_mifintrbit_bit_unmask(sdev->service, hip->hip_priv->intr_tohost_mul[HIP4_MIF_Q_FH_RFB]);
1129 }
1130 SCSC_HIP4_SAMPLER_INT_OUT_BH(hip->hip_priv->minor, 2);
1131
1132 #ifdef CONFIG_ANDROID
1133 if (wake_lock_active(&hip->hip_priv->hip4_wake_lock_tx)) {
1134 wake_unlock(&hip->hip_priv->hip4_wake_lock_tx);
1135 SCSC_WLOG_WAKELOCK(WLOG_LAZY, WL_RELEASED, "hip4_wake_lock_tx", WL_REASON_RX);
1136 }
1137 #endif
1138 bh_end_fb = ktime_get();
1139 spin_unlock_bh(&hip_priv->rx_lock);
1140 }
1141
1142 static void hip4_irq_handler_fb(int irq, void *data)
1143 {
1144 struct slsi_hip4 *hip = (struct slsi_hip4 *)data;
1145 struct slsi_dev *sdev = container_of(hip, struct slsi_dev, hip4_inst);
1146
1147 SCSC_HIP4_SAMPLER_INT(hip->hip_priv->minor, 2);
1148 intr_received_fb = ktime_get();
1149
1150 #ifdef CONFIG_ANDROID
1151 if (!wake_lock_active(&hip->hip_priv->hip4_wake_lock_tx)) {
1152 wake_lock_timeout(&hip->hip_priv->hip4_wake_lock_tx, msecs_to_jiffies(SLSI_HIP_WAKELOCK_TIME_OUT_IN_MS));
1153 SCSC_WLOG_WAKELOCK(WLOG_LAZY, WL_TAKEN, "hip4_wake_lock_tx", WL_REASON_RX);
1154 }
1155 #endif
1156
1157 if (!atomic_read(&hip->hip_priv->watchdog_timer_active)) {
1158 atomic_set(&hip->hip_priv->watchdog_timer_active, 1);
1159 mod_timer(&hip->hip_priv->watchdog, jiffies + HZ);
1160 }
1161 set_bit(HIP4_MIF_Q_FH_RFB, hip->hip_priv->irq_bitmap);
1162
1163 scsc_service_mifintrbit_bit_mask(sdev->service, irq);
1164 if (hip4_system_wq)
1165 schedule_work(&hip->hip_priv->intr_wq_fb);
1166 else
1167 queue_work(hip->hip_priv->hip4_workq, &hip->hip_priv->intr_wq_fb);
1168
1169 /* Clear interrupt */
1170 scsc_service_mifintrbit_bit_clear(sdev->service, irq);
1171 SCSC_HIP4_SAMPLER_INT_OUT(hip->hip_priv->minor, 2);
1172 }
1173
1174 static void hip4_wq_ctrl(struct work_struct *data)
1175 {
1176 struct hip4_priv *hip_priv = container_of(data, struct hip4_priv, intr_wq_ctrl);
1177 struct slsi_hip4 *hip;
1178 struct hip4_hip_control *ctrl;
1179 struct scsc_service *service;
1180 struct slsi_dev *sdev;
1181 u8 retry;
1182 bool no_change = true;
1183 u8 idx_r;
1184 u8 idx_w;
1185 scsc_mifram_ref ref;
1186 void *mem;
1187 struct mbulk *m;
1188 #if defined(CONFIG_SCSC_WLAN_DEBUG) || defined(CONFIG_SCSC_WLAN_HIP4_PROFILING)
1189 int id;
1190 #endif
1191
1192 if (!hip_priv || !hip_priv->hip) {
1193 SLSI_ERR_NODEV("hip_priv or hip_priv->hip is Null\n");
1194 return;
1195 }
1196
1197 hip = hip_priv->hip;
1198 ctrl = hip->hip_control;
1199
1200 if (!ctrl) {
1201 SLSI_ERR_NODEV("hip->hip_control is Null\n");
1202 return;
1203 }
1204 sdev = container_of(hip, struct slsi_dev, hip4_inst);
1205
1206 if (!sdev || !sdev->service) {
1207 SLSI_ERR_NODEV("sdev or sdev->service is Null\n");
1208 return;
1209 }
1210
1211 spin_lock_bh(&hip_priv->rx_lock);
1212 service = sdev->service;
1213 SCSC_HIP4_SAMPLER_INT_BH(hip->hip_priv->minor, 1);
1214 bh_init_ctrl = ktime_get();
1215 clear_bit(HIP4_MIF_Q_TH_CTRL, hip->hip_priv->irq_bitmap);
1216
1217 idx_r = hip4_read_index(hip, HIP4_MIF_Q_TH_CTRL, ridx);
1218 idx_w = hip4_read_index(hip, HIP4_MIF_Q_TH_CTRL, widx);
1219
1220 #ifdef CONFIG_SCSC_WLAN_HIP4_PROFILING
1221 if (idx_r != idx_w) {
1222 SCSC_HIP4_SAMPLER_Q(hip_priv->minor, HIP4_MIF_Q_TH_CTRL, ridx, idx_r, 1);
1223 SCSC_HIP4_SAMPLER_Q(hip_priv->minor, HIP4_MIF_Q_TH_CTRL, widx, idx_w, 1);
1224 }
1225 #endif
1226 while (idx_r != idx_w) {
1227 struct sk_buff *skb;
1228 /* TODO: currently the max number to be freed is 2. In future
1229 * implementations (i.e. AMPDU) this number may be bigger
1230 * list of mbulks to be freedi
1231 */
1232 scsc_mifram_ref to_free[MBULK_MAX_CHAIN + 1] = { 0 };
1233 u8 i = 0;
1234
1235 no_change = false;
1236 /* Catch-up with idx_w */
1237 ref = ctrl->q[HIP4_MIF_Q_TH_CTRL].array[idx_r];
1238 #ifdef CONFIG_SCSC_WLAN_HIP4_PROFILING
1239 SCSC_HIP4_SAMPLER_QREF(hip_priv->minor, ref, HIP4_MIF_Q_TH_CTRL);
1240 #endif
1241 mem = scsc_mx_service_mif_addr_to_ptr(service, ref);
1242 m = (struct mbulk *)(mem);
1243 /* Process Control Signal */
1244 skb = hip4_mbulk_to_skb(service, hip_priv, m, to_free, false);
1245 if (!skb) {
1246 SLSI_ERR_NODEV("Ctrl: Error parsing or allocating skb\n");
1247 hip4_dump_dbg(hip, m, skb, service);
1248 goto consume_ctl_mbulk;
1249 }
1250
1251 #ifdef CONFIG_SCSC_WLAN_DEBUG
1252 if (m->flag & MBULK_F_WAKEUP) {
1253 SLSI_INFO(sdev, "WIFI wakeup by MLME frame 0x%x:\n", fapi_get_sigid(skb));
1254 SCSC_BIN_TAG_INFO(BINARY, skb->data, skb->len > 128 ? 128 : skb->len);
1255 }
1256 #else
1257 if (m->flag & MBULK_F_WAKEUP)
1258 SLSI_INFO(sdev, "WIFI wakeup by MLME frame 0x%x\n", fapi_get_sigid(skb));
1259 #endif
1260
1261 #if defined(CONFIG_SCSC_WLAN_DEBUG) || defined(CONFIG_SCSC_WLAN_HIP4_PROFILING)
1262 id = fapi_get_sigid(skb);
1263 #endif
1264 #ifdef CONFIG_SCSC_WLAN_HIP4_PROFILING
1265 /* log control signal, not unidata not debug */
1266 if (fapi_is_mlme(skb))
1267 SCSC_HIP4_SAMPLER_SIGNAL_CTRLRX(hip_priv->minor, (id & 0xff00) >> 8, id & 0xff);
1268 #endif
1269 #ifdef CONFIG_SCSC_WLAN_DEBUG
1270 hip4_history_record_add(TH, id);
1271 #endif
1272 if (slsi_hip_rx(sdev, skb) < 0) {
1273 SLSI_ERR_NODEV("Ctrl: Error detected slsi_hip_rx\n");
1274 hip4_dump_dbg(hip, m, skb, service);
1275 slsi_kfree_skb(skb);
1276 }
1277 consume_ctl_mbulk:
1278 /* Increase index */
1279 idx_r++;
1280 idx_r &= (MAX_NUM - 1);
1281
1282 /* Go through the list of references to free */
1283 while ((ref = to_free[i++])) {
1284 /* Set the number of retries */
1285 retry = FB_NO_SPC_NUM_RET;
1286 /* return to the firmware */
1287 while (hip4_q_add_signal(hip, HIP4_MIF_Q_TH_RFB, ref, service) && retry > 0) {
1288 SLSI_WARN_NODEV("Ctrl: Not enough space in FB, retry: %d/%d\n", retry, FB_NO_SPC_NUM_RET);
1289 spin_unlock_bh(&hip_priv->rx_lock);
1290 msleep(FB_NO_SPC_SLEEP_MS);
1291 spin_lock_bh(&hip_priv->rx_lock);
1292 retry--;
1293 if (retry == 0)
1294 SLSI_ERR_NODEV("Ctrl: FB has not been freed for %d ms\n", FB_NO_SPC_NUM_RET * FB_NO_SPC_SLEEP_MS);
1295 SCSC_HIP4_SAMPLER_QFULL(hip_priv->minor, HIP4_MIF_Q_TH_RFB);
1296 }
1297 }
1298 hip4_update_index(hip, HIP4_MIF_Q_TH_CTRL, ridx, idx_r);
1299 }
1300
1301 if (no_change)
1302 atomic_inc(&hip->hip_priv->stats.spurious_irqs);
1303
1304 if (!atomic_read(&hip->hip_priv->closing)) {
1305 atomic_set(&hip->hip_priv->watchdog_timer_active, 0);
1306 scsc_service_mifintrbit_bit_unmask(sdev->service, hip->hip_priv->intr_tohost_mul[HIP4_MIF_Q_TH_CTRL]);
1307 }
1308 SCSC_HIP4_SAMPLER_INT_OUT_BH(hip->hip_priv->minor, 1);
1309 #ifdef CONFIG_ANDROID
1310 if (wake_lock_active(&hip->hip_priv->hip4_wake_lock_ctrl)) {
1311 wake_unlock(&hip->hip_priv->hip4_wake_lock_ctrl);
1312 SCSC_WLOG_WAKELOCK(WLOG_LAZY, WL_RELEASED, "hip4_wake_lock_ctrl", WL_REASON_RX);
1313 }
1314 #endif
1315 bh_end_ctrl = ktime_get();
1316 spin_unlock_bh(&hip_priv->rx_lock);
1317 }
1318
1319 static void hip4_irq_handler_ctrl(int irq, void *data)
1320 {
1321 struct slsi_hip4 *hip = (struct slsi_hip4 *)data;
1322 struct slsi_dev *sdev = container_of(hip, struct slsi_dev, hip4_inst);
1323
1324 SCSC_HIP4_SAMPLER_INT(hip->hip_priv->minor, 1);
1325 intr_received_ctrl = ktime_get();
1326
1327 #ifdef CONFIG_ANDROID
1328 if (!wake_lock_active(&hip->hip_priv->hip4_wake_lock_ctrl)) {
1329 wake_lock_timeout(&hip->hip_priv->hip4_wake_lock_ctrl, msecs_to_jiffies(SLSI_HIP_WAKELOCK_TIME_OUT_IN_MS));
1330 SCSC_WLOG_WAKELOCK(WLOG_LAZY, WL_TAKEN, "hip4_wake_lock_ctrl", WL_REASON_RX);
1331 }
1332 #endif
1333
1334 if (!atomic_read(&hip->hip_priv->watchdog_timer_active)) {
1335 atomic_set(&hip->hip_priv->watchdog_timer_active, 1);
1336 mod_timer(&hip->hip_priv->watchdog, jiffies + HZ);
1337 }
1338 set_bit(HIP4_MIF_Q_TH_CTRL, hip->hip_priv->irq_bitmap);
1339
1340 scsc_service_mifintrbit_bit_mask(sdev->service, irq);
1341
1342 if (hip4_system_wq)
1343 schedule_work(&hip->hip_priv->intr_wq_ctrl);
1344 else
1345 queue_work(hip->hip_priv->hip4_workq, &hip->hip_priv->intr_wq_ctrl);
1346
1347 /* Clear interrupt */
1348 scsc_service_mifintrbit_bit_clear(sdev->service, irq);
1349 SCSC_HIP4_SAMPLER_INT_OUT(hip->hip_priv->minor, 1);
1350 }
1351
1352 static int hip4_napi_poll(struct napi_struct *napi, int budget)
1353 {
1354 struct hip4_priv *hip_priv = container_of(napi, struct hip4_priv, napi);
1355 struct slsi_hip4 *hip;
1356 struct hip4_hip_control *ctrl;
1357 struct scsc_service *service;
1358 struct slsi_dev *sdev;
1359
1360 #ifdef CONFIG_SCSC_WLAN_DEBUG
1361 int id;
1362 #endif
1363 u8 idx_r;
1364 u8 idx_w;
1365 scsc_mifram_ref ref;
1366 void *mem;
1367 struct mbulk *m;
1368 u8 retry;
1369 int work_done = 0;
1370
1371 if (!hip_priv || !hip_priv->hip) {
1372 SLSI_ERR_NODEV("hip_priv or hip_priv->hip is Null\n");
1373 return 0;
1374 }
1375
1376 hip = hip_priv->hip;
1377 ctrl = hip->hip_control;
1378
1379 if (!ctrl) {
1380 SLSI_ERR_NODEV("hip->hip_control is Null\n");
1381 return 0;
1382 }
1383 sdev = container_of(hip, struct slsi_dev, hip4_inst);
1384
1385 if (!sdev || !sdev->service) {
1386 SLSI_ERR_NODEV("sdev or sdev->service is Null\n");
1387 return 0;
1388 }
1389
1390 spin_lock_bh(&hip_priv->rx_lock);
1391 SCSC_HIP4_SAMPLER_INT_BH(hip->hip_priv->minor, 0);
1392 if (ktime_compare(bh_init_data, bh_end_data) <= 0) {
1393 bh_init_data = ktime_get();
1394 if (!atomic_read(&hip->hip_priv->closing)) {
1395 atomic_set(&hip->hip_priv->watchdog_timer_active, 0);
1396 }
1397 }
1398 clear_bit(HIP4_MIF_Q_TH_DAT, hip->hip_priv->irq_bitmap);
1399
1400 idx_r = hip4_read_index(hip, HIP4_MIF_Q_TH_DAT, ridx);
1401 idx_w = hip4_read_index(hip, HIP4_MIF_Q_TH_DAT, widx);
1402
1403 service = sdev->service;
1404
1405 SLSI_DBG4(sdev, SLSI_RX, "todo:%d\n", (idx_w - idx_r) & 0xff);
1406 if (idx_r == idx_w) {
1407 SLSI_DBG4(sdev, SLSI_RX, "nothing to do, NAPI Complete\n");
1408 bh_end_data = ktime_get();
1409 napi_complete(napi);
1410 if (!atomic_read(&hip->hip_priv->closing)) {
1411 /* Nothing more to drain, unmask interrupt */
1412 scsc_service_mifintrbit_bit_unmask(sdev->service, hip->hip_priv->intr_tohost_mul[HIP4_MIF_Q_TH_DAT]);
1413 }
1414 #ifdef CONFIG_ANDROID
1415 if (wake_lock_active(&hip->hip_priv->hip4_wake_lock_data)) {
1416 wake_unlock(&hip->hip_priv->hip4_wake_lock_data);
1417 SCSC_WLOG_WAKELOCK(WLOG_LAZY, WL_RELEASED, "hip4_wake_lock_data", WL_REASON_RX);
1418 }
1419 #endif
1420 goto end;
1421 }
1422
1423 #ifdef CONFIG_SCSC_WLAN_HIP4_PROFILING
1424 if (idx_r != idx_w) {
1425 SCSC_HIP4_SAMPLER_Q(hip_priv->minor, HIP4_MIF_Q_TH_DAT, ridx, idx_r, 1);
1426 SCSC_HIP4_SAMPLER_Q(hip_priv->minor, HIP4_MIF_Q_TH_DAT, widx, idx_w, 1);
1427 }
1428 #endif
1429
1430 while (idx_r != idx_w) {
1431 struct sk_buff *skb;
1432 /* TODO: currently the max number to be freed is 2. In future
1433 * implementations (i.e. AMPDU) this number may be bigger
1434 */
1435 /* list of mbulks to be freed */
1436 scsc_mifram_ref to_free[MBULK_MAX_CHAIN + 1] = { 0 };
1437 u8 i = 0;
1438
1439 /* Catch-up with idx_w */
1440 ref = ctrl->q[HIP4_MIF_Q_TH_DAT].array[idx_r];
1441 #ifdef CONFIG_SCSC_WLAN_HIP4_PROFILING
1442 SCSC_HIP4_SAMPLER_QREF(hip_priv->minor, ref, HIP4_MIF_Q_TH_DAT);
1443 #endif
1444 mem = scsc_mx_service_mif_addr_to_ptr(service, ref);
1445 m = (struct mbulk *)(mem);
1446 skb = hip4_mbulk_to_skb(service, hip_priv, m, to_free, true);
1447 if (!skb) {
1448 SLSI_ERR_NODEV("Dat: Error parsing or allocating skb\n");
1449 hip4_dump_dbg(hip, m, skb, service);
1450 goto consume_dat_mbulk;
1451 }
1452 #ifdef CONFIG_SCSC_WLAN_DEBUG
1453 if (m->flag & MBULK_F_WAKEUP) {
1454 SLSI_INFO(sdev, "WIFI wakeup by DATA frame:\n");
1455 SCSC_BIN_TAG_INFO(BINARY, skb->data, skb->len > 128 ? 128 : skb->len);
1456 }
1457 #else
1458 if (m->flag & MBULK_F_WAKEUP) {
1459 SLSI_INFO(sdev, "WIFI wakeup by DATA frame:\n");
1460 SCSC_BIN_TAG_INFO(BINARY, skb->data, fapi_get_siglen(skb) + ETH_HLEN);
1461 }
1462 #endif
1463 #ifdef CONFIG_SCSC_WLAN_DEBUG
1464 id = fapi_get_sigid(skb);
1465 hip4_history_record_add(TH, id);
1466 #endif
1467 if (slsi_hip_rx(sdev, skb) < 0) {
1468 SLSI_ERR_NODEV("Dat: Error detected slsi_hip_rx\n");
1469 hip4_dump_dbg(hip, m, skb, service);
1470 slsi_kfree_skb(skb);
1471 }
1472 consume_dat_mbulk:
1473 /* Increase index */
1474 idx_r++;
1475 idx_r &= (MAX_NUM - 1);
1476
1477 while ((ref = to_free[i++])) {
1478 /* Set the number of retries */
1479 retry = FB_NO_SPC_NUM_RET;
1480 while (hip4_q_add_signal(hip, HIP4_MIF_Q_TH_RFB, ref, service) && retry > 0) {
1481 SLSI_WARN_NODEV("Dat: Not enough space in FB, retry: %d/%d\n", retry, FB_NO_SPC_NUM_RET);
1482 udelay(FB_NO_SPC_DELAY_US);
1483 retry--;
1484
1485 if (retry == 0)
1486 SLSI_ERR_NODEV("Dat: FB has not been freed for %d us\n", FB_NO_SPC_NUM_RET * FB_NO_SPC_DELAY_US);
1487 #ifdef CONFIG_SCSC_WLAN_HIP4_PROFILING
1488 SCSC_HIP4_SAMPLER_QFULL(hip_priv->minor, HIP4_MIF_Q_TH_RFB);
1489 #endif
1490 }
1491 }
1492
1493 work_done++;
1494 if (budget == work_done) {
1495 /* We have consumed all the bugdet */
1496 break;
1497 }
1498 }
1499
1500 hip4_update_index(hip, HIP4_MIF_Q_TH_DAT, ridx, idx_r);
1501
1502 if (work_done < budget) {
1503 SLSI_DBG4(sdev, SLSI_RX, "NAPI Complete\n");
1504 bh_end_data = ktime_get();
1505 napi_complete(napi);
1506 if (!atomic_read(&hip->hip_priv->closing)) {
1507 /* Nothing more to drain, unmask interrupt */
1508 scsc_service_mifintrbit_bit_unmask(sdev->service, hip->hip_priv->intr_tohost_mul[HIP4_MIF_Q_TH_DAT]);
1509 }
1510 #ifdef CONFIG_ANDROID
1511 if (wake_lock_active(&hip->hip_priv->hip4_wake_lock_data)) {
1512 wake_unlock(&hip->hip_priv->hip4_wake_lock_data);
1513 SCSC_WLOG_WAKELOCK(WLOG_LAZY, WL_RELEASED, "hip4_wake_lock_data", WL_REASON_RX);
1514 }
1515 #endif
1516 }
1517 end:
1518 SLSI_DBG4(sdev, SLSI_RX, "work done:%d\n", work_done);
1519 SCSC_HIP4_SAMPLER_INT_OUT_BH(hip->hip_priv->minor, 0);
1520 spin_unlock_bh(&hip_priv->rx_lock);
1521 return work_done;
1522 }
1523
1524 static void hip4_napi_schedule(void *data)
1525 {
1526 struct slsi_hip4 *hip = (struct slsi_hip4 *)data;
1527
1528 napi_schedule(&hip->hip_priv->napi);
1529 }
1530
1531 static void hip4_irq_data_tasklet(unsigned long data)
1532 {
1533 /* TODO: NAPI - formalize the CPU selection code */
1534 struct slsi_hip4 *hip = (struct slsi_hip4 *)data;
1535 int err = -EINVAL;
1536
1537 if (cpu_online(napi_select_cpu))
1538 err = smp_call_function_single(napi_select_cpu, hip4_napi_schedule, hip, 0);
1539
1540 if (err)
1541 napi_schedule(&hip->hip_priv->napi);
1542 }
1543
1544 static void hip4_irq_handler_dat(int irq, void *data)
1545 {
1546 struct slsi_hip4 *hip = (struct slsi_hip4 *)data;
1547 struct slsi_dev *sdev = container_of(hip, struct slsi_dev, hip4_inst);
1548
1549 if (!hip || !sdev || !sdev->service || !hip->hip_priv)
1550 return;
1551
1552 SCSC_HIP4_SAMPLER_INT(hip->hip_priv->minor, 0);
1553 intr_received_data = ktime_get();
1554
1555 #ifdef CONFIG_ANDROID
1556 if (!wake_lock_active(&hip->hip_priv->hip4_wake_lock_data)) {
1557 wake_lock_timeout(&hip->hip_priv->hip4_wake_lock_data, msecs_to_jiffies(SLSI_HIP_WAKELOCK_TIME_OUT_IN_MS));
1558 SCSC_WLOG_WAKELOCK(WLOG_LAZY, WL_TAKEN, "hip4_wake_lock_data", WL_REASON_RX);
1559 }
1560 #endif
1561 if (!atomic_read(&hip->hip_priv->watchdog_timer_active)) {
1562 atomic_set(&hip->hip_priv->watchdog_timer_active, 1);
1563 mod_timer(&hip->hip_priv->watchdog, jiffies + HZ);
1564 }
1565 set_bit(HIP4_MIF_Q_TH_DAT, hip->hip_priv->irq_bitmap);
1566
1567 if (napi_select_cpu)
1568 tasklet_schedule(&hip->hip_priv->intr_tasklet);
1569 else
1570 napi_schedule(&hip->hip_priv->napi);
1571
1572 /* Mask interrupt to avoid interrupt storm and let BH run */
1573 scsc_service_mifintrbit_bit_mask(sdev->service, hip->hip_priv->intr_tohost_mul[HIP4_MIF_Q_TH_DAT]);
1574
1575 /* Clear interrupt */
1576 scsc_service_mifintrbit_bit_clear(sdev->service, hip->hip_priv->intr_tohost_mul[HIP4_MIF_Q_TH_DAT]);
1577 SCSC_HIP4_SAMPLER_INT_OUT(hip->hip_priv->minor, 0);
1578 }
1579
1580 #endif /* #ifdef CONFIG_SCSC_WLAN_RX_NAPI */
1581
1582 static bool slsi_check_rx_flowcontrol(struct slsi_dev *sdev)
1583 {
1584 struct netdev_vif *ndev_vif;
1585 int qlen = 0;
1586
1587 ndev_vif = netdev_priv(sdev->netdev[SLSI_NET_INDEX_WLAN]);
1588 if (ndev_vif)
1589 qlen = skb_queue_len(&ndev_vif->rx_data.queue);
1590
1591 if (!mutex_trylock(&sdev->netdev_remove_mutex))
1592 goto evaluate;
1593
1594 #if defined(SLSI_NET_INDEX_P2PX_SWLAN)
1595 if (sdev->netdev[SLSI_NET_INDEX_P2PX_SWLAN]) {
1596 ndev_vif = netdev_priv(sdev->netdev[SLSI_NET_INDEX_P2PX_SWLAN]);
1597 if (ndev_vif)
1598 qlen += skb_queue_len(&ndev_vif->rx_data.queue);
1599 }
1600 #elif defined(SLSI_NET_INDEX_P2PX)
1601 if (sdev->netdev[SLSI_NET_INDEX_P2PX]) {
1602 ndev_vif = netdev_priv(sdev->netdev[SLSI_NET_INDEX_P2PX]);
1603 if (ndev_vif)
1604 qlen += skb_queue_len(&ndev_vif->rx_data.queue);
1605 }
1606 #endif
1607 mutex_unlock(&sdev->netdev_remove_mutex);
1608
1609 evaluate:
1610 if (qlen > max_buffered_frames) {
1611 SLSI_DBG1_NODEV(SLSI_HIP, "max qlen reached: %d\n", qlen);
1612 return true;
1613 }
1614 SLSI_DBG3_NODEV(SLSI_HIP, "qlen %d\n", qlen);
1615
1616 return false;
1617 }
1618
1619 /* Worqueue: Lower priority, run in process context. Can run simultaneously on
1620 * different CPUs
1621 */
1622 static void hip4_wq(struct work_struct *data)
1623 {
1624 struct hip4_priv *hip_priv = container_of(data, struct hip4_priv, intr_wq);
1625 struct slsi_hip4 *hip = hip_priv->hip;
1626 struct hip4_hip_control *ctrl = hip->hip_control;
1627 scsc_mifram_ref ref;
1628 void *mem;
1629 struct mbulk *m;
1630 u8 idx_r;
1631 u8 idx_w;
1632 struct slsi_dev *sdev = container_of(hip, struct slsi_dev, hip4_inst);
1633 struct scsc_service *service;
1634 bool no_change = true;
1635 u8 retry;
1636 u32 packets_total;
1637 bool rx_flowcontrol = false;
1638
1639 #if defined(CONFIG_SCSC_WLAN_HIP4_PROFILING) || defined(CONFIG_SCSC_WLAN_DEBUG)
1640 int id;
1641 #endif
1642
1643 if (!sdev || !sdev->service) {
1644 WARN_ON(1);
1645 return;
1646 }
1647
1648 service = sdev->service;
1649
1650 atomic_set(&hip->hip_priv->in_rx, 1);
1651 if (slsi_check_rx_flowcontrol(sdev))
1652 rx_flowcontrol = true;
1653
1654 atomic_set(&hip->hip_priv->in_rx, 2);
1655 spin_lock_bh(&hip_priv->rx_lock);
1656 atomic_set(&hip->hip_priv->in_rx, 3);
1657
1658 bh_init = ktime_get();
1659
1660 #ifdef CONFIG_SCSC_WLAN_DEBUG
1661 /* Compute jitter */
1662 {
1663 u64 jitter;
1664
1665 jitter = ktime_to_ns(ktime_sub(bh_init, intr_received));
1666
1667 if (jitter <= HISTO_1)
1668 histogram_1++;
1669 else if (jitter > HISTO_1 && jitter <= HISTO_2)
1670 histogram_2++;
1671 else if (jitter > HISTO_2 && jitter <= HISTO_3)
1672 histogram_3++;
1673 else if (jitter > HISTO_3 && jitter <= HISTO_4)
1674 histogram_4++;
1675 else if (jitter > HISTO_4 && jitter <= HISTO_5)
1676 histogram_5++;
1677 else
1678 histogram_6++;
1679
1680 if (jitter > max_jitter)
1681 max_jitter = jitter;
1682 }
1683 #endif
1684 idx_r = hip4_read_index(hip, HIP4_MIF_Q_FH_RFB, ridx);
1685 idx_w = hip4_read_index(hip, HIP4_MIF_Q_FH_RFB, widx);
1686
1687 if (idx_r != idx_w) {
1688 no_change = false;
1689 SCSC_HIP4_SAMPLER_Q(hip_priv->minor, HIP4_MIF_Q_FH_RFB, ridx, idx_r, 1);
1690 SCSC_HIP4_SAMPLER_Q(hip_priv->minor, HIP4_MIF_Q_FH_RFB, widx, idx_w, 1);
1691 }
1692
1693 SCSC_HIP4_SAMPLER_INT_BH(hip_priv->minor, 2);
1694 while (idx_r != idx_w) {
1695 struct mbulk *m;
1696 u16 colour;
1697
1698 ref = ctrl->q[HIP4_MIF_Q_FH_RFB].array[idx_r];
1699 SCSC_HIP4_SAMPLER_QREF(hip_priv->minor, ref, HIP4_MIF_Q_FH_RFB);
1700 #ifdef CONFIG_SCSC_WLAN_DEBUG
1701 hip->hip_priv->stats.q_num_frames[HIP4_MIF_Q_FH_RFB] = hip->hip_priv->stats.q_num_frames[HIP4_MIF_Q_FH_RFB] + 1;
1702 #endif
1703 mem = scsc_mx_service_mif_addr_to_ptr(service, ref);
1704 m = (struct mbulk *)mem;
1705 if (!m) {
1706 SLSI_ERR_NODEV("FB: Mbulk is NULL 0x%x\n", ref);
1707 goto consume_fb_mbulk;
1708 }
1709 /* colour is defined as: */
1710 /* u16 register bits:
1711 * 0 - do not use
1712 * [3:1] - vif
1713 * [7:4] - peer_index
1714 * [10:8] - ac queue
1715 */
1716 colour = ((m->clas & 0xc0) << 2) | (m->pid & 0xfe);
1717 /* Account ONLY for data RFB */
1718 if ((m->pid & 0x1) == MBULK_POOL_ID_DATA) {
1719 #ifdef CONFIG_SCSC_WLAN_HIP4_PROFILING
1720 SCSC_HIP4_SAMPLER_VIF_PEER(hip->hip_priv->minor, 0, (colour & 0xE) >> 1, (colour & 0xF0) >> 4);
1721 /* to profile round-trip */
1722 {
1723 u16 host_tag;
1724 u8 *get_host_tag;
1725 /* This is a nasty way of getting the host_tag without involving mbulk processing
1726 * This hostag value should also be include in the cb descriptor which goes to
1727 * mbulk descriptor (no room left at the moment)
1728 */
1729 get_host_tag = (u8 *)m;
1730 host_tag = get_host_tag[37] << 8 | get_host_tag[36];
1731 SCSC_HIP4_SAMPLER_PKT_TX_FB(hip->hip_priv->minor, host_tag);
1732 }
1733 #endif
1734 /* Ignore return value */
1735 slsi_hip_tx_done(sdev, colour);
1736 }
1737 mbulk_free_virt_host(m);
1738 consume_fb_mbulk:
1739 /* Increase index */
1740 idx_r++;
1741 idx_r &= (MAX_NUM - 1);
1742 hip4_update_index(hip, HIP4_MIF_Q_FH_RFB, ridx, idx_r);
1743 }
1744 SCSC_HIP4_SAMPLER_INT_OUT_BH(hip_priv->minor, 2);
1745
1746 atomic_set(&hip->hip_priv->in_rx, 4);
1747
1748 idx_r = hip4_read_index(hip, HIP4_MIF_Q_TH_CTRL, ridx);
1749 idx_w = hip4_read_index(hip, HIP4_MIF_Q_TH_CTRL, widx);
1750
1751 if (idx_r != idx_w) {
1752 no_change = false;
1753 SCSC_HIP4_SAMPLER_Q(hip_priv->minor, HIP4_MIF_Q_TH_CTRL, ridx, idx_r, 1);
1754 SCSC_HIP4_SAMPLER_Q(hip_priv->minor, HIP4_MIF_Q_TH_CTRL, widx, idx_w, 1);
1755 }
1756
1757 SCSC_HIP4_SAMPLER_INT_BH(hip_priv->minor, 1);
1758 while (idx_r != idx_w) {
1759 struct sk_buff *skb;
1760 /* TODO: currently the max number to be freed is 2. In future
1761 * implementations (i.e. AMPDU) this number may be bigger
1762 * list of mbulks to be freedi
1763 */
1764 scsc_mifram_ref to_free[MBULK_MAX_CHAIN + 1] = { 0 };
1765 u8 i = 0;
1766
1767 /* Catch-up with idx_w */
1768 ref = ctrl->q[HIP4_MIF_Q_TH_CTRL].array[idx_r];
1769 SCSC_HIP4_SAMPLER_QREF(hip_priv->minor, ref, HIP4_MIF_Q_TH_CTRL);
1770 #ifdef CONFIG_SCSC_WLAN_DEBUG
1771 hip->hip_priv->stats.q_num_frames[HIP4_MIF_Q_TH_CTRL] = hip->hip_priv->stats.q_num_frames[HIP4_MIF_Q_TH_CTRL] + 1;
1772 #endif
1773 mem = scsc_mx_service_mif_addr_to_ptr(service, ref);
1774 m = (struct mbulk *)(mem);
1775 if (!m) {
1776 SLSI_ERR_NODEV("Ctrl: Mbulk is NULL 0x%x\n", ref);
1777 goto consume_ctl_mbulk;
1778 }
1779 /* Process Control Signal */
1780 skb = hip4_mbulk_to_skb(service, hip_priv, m, to_free, false);
1781 if (!skb) {
1782 SLSI_ERR_NODEV("Ctrl: Error parsing or allocating skb\n");
1783 hip4_dump_dbg(hip, m, skb, service);
1784 goto consume_ctl_mbulk;
1785 }
1786
1787 #ifdef CONFIG_SCSC_WLAN_DEBUG
1788 if (m->flag & MBULK_F_WAKEUP) {
1789 SLSI_INFO(sdev, "WIFI wakeup by MLME frame 0x%x:\n", fapi_get_sigid(skb));
1790 SCSC_BIN_TAG_INFO(BINARY, skb->data, skb->len > 128 ? 128 : skb->len);
1791 }
1792 #else
1793 if (m->flag & MBULK_F_WAKEUP)
1794 SLSI_INFO(sdev, "WIFI wakeup by MLME frame 0x%x\n", fapi_get_sigid(skb));
1795 #endif
1796
1797 #if defined(CONFIG_SCSC_WLAN_HIP4_PROFILING) || defined(CONFIG_SCSC_WLAN_DEBUG)
1798 id = fapi_get_sigid(skb);
1799 #endif
1800 #ifdef CONFIG_SCSC_WLAN_HIP4_PROFILING
1801 /* log control signal, not unidata not debug */
1802 if (fapi_is_mlme(skb))
1803 SCSC_HIP4_SAMPLER_SIGNAL_CTRLRX(hip_priv->minor, (id & 0xff00) >> 8, id & 0xff);
1804 #endif
1805 #ifdef CONFIG_SCSC_WLAN_DEBUG
1806 hip4_history_record_add(TH, id);
1807 #endif
1808 if (slsi_hip_rx(sdev, skb) < 0) {
1809 SLSI_ERR_NODEV("Ctrl: Error detected slsi_hip_rx\n");
1810 hip4_dump_dbg(hip, m, skb, service);
1811 slsi_kfree_skb(skb);
1812 }
1813 consume_ctl_mbulk:
1814 /* Increase index */
1815 idx_r++;
1816 idx_r &= (MAX_NUM - 1);
1817
1818 /* Go through the list of references to free */
1819 while ((ref = to_free[i++])) {
1820 /* Set the number of retries */
1821 retry = FB_NO_SPC_NUM_RET;
1822 /* return to the firmware */
1823 while (hip4_q_add_signal(hip, HIP4_MIF_Q_TH_RFB, ref, service) && retry > 0) {
1824 SLSI_WARN_NODEV("Ctrl: Not enough space in FB, retry: %d/%d\n", retry, FB_NO_SPC_NUM_RET);
1825 spin_unlock_bh(&hip_priv->rx_lock);
1826 msleep(FB_NO_SPC_SLEEP_MS);
1827 spin_lock_bh(&hip_priv->rx_lock);
1828 retry--;
1829 if (retry == 0)
1830 SLSI_ERR_NODEV("Ctrl: FB has not been freed for %d ms\n", FB_NO_SPC_NUM_RET * FB_NO_SPC_SLEEP_MS);
1831 SCSC_HIP4_SAMPLER_QFULL(hip_priv->minor, HIP4_MIF_Q_TH_RFB);
1832 }
1833 }
1834 hip4_update_index(hip, HIP4_MIF_Q_TH_CTRL, ridx, idx_r);
1835 }
1836
1837 SCSC_HIP4_SAMPLER_INT_OUT_BH(hip_priv->minor, 1);
1838
1839 if (rx_flowcontrol)
1840 goto skip_data_q;
1841
1842 atomic_set(&hip->hip_priv->in_rx, 5);
1843
1844 idx_r = hip4_read_index(hip, HIP4_MIF_Q_TH_DAT, ridx);
1845 idx_w = hip4_read_index(hip, HIP4_MIF_Q_TH_DAT, widx);
1846
1847 if (idx_r != idx_w) {
1848 packets_total = 0;
1849 no_change = false;
1850 SCSC_HIP4_SAMPLER_Q(hip_priv->minor, HIP4_MIF_Q_TH_DAT, ridx, idx_r, 1);
1851 SCSC_HIP4_SAMPLER_Q(hip_priv->minor, HIP4_MIF_Q_TH_DAT, widx, idx_w, 1);
1852 #ifdef CONFIG_SCSC_WLAN_DEBUG
1853 /* Compute DAT histogram */
1854 {
1855 u8 num_packets = (idx_w - idx_r) % 256;
1856
1857 if (num_packets <= HISTO_1_DATA)
1858 histogram_1_data++;
1859 else if (num_packets > HISTO_1_DATA && num_packets <= HISTO_2_DATA)
1860 histogram_2_data++;
1861 else if (num_packets > HISTO_2_DATA && num_packets <= HISTO_3_DATA)
1862 histogram_3_data++;
1863 else if (num_packets > HISTO_3_DATA && num_packets <= HISTO_4_DATA)
1864 histogram_4_data++;
1865 else if (num_packets > HISTO_4_DATA && num_packets <= HISTO_5_DATA)
1866 histogram_5_data++;
1867 else
1868 histogram_6_data++;
1869 if (num_packets > max_data)
1870 max_data = num_packets;
1871 }
1872 #endif
1873 }
1874
1875 SCSC_HIP4_SAMPLER_INT_BH(hip_priv->minor, 0);
1876 while (idx_r != idx_w) {
1877 struct sk_buff *skb;
1878 /* TODO: currently the max number to be freed is 2. In future
1879 * implementations (i.e. AMPDU) this number may be bigger
1880 */
1881 /* list of mbulks to be freed */
1882 scsc_mifram_ref to_free[MBULK_MAX_CHAIN + 1] = { 0 };
1883 u8 i = 0;
1884
1885 packets_total++;
1886 /* Catch-up with idx_w */
1887 ref = ctrl->q[HIP4_MIF_Q_TH_DAT].array[idx_r];
1888 SCSC_HIP4_SAMPLER_QREF(hip_priv->minor, ref, HIP4_MIF_Q_TH_DAT);
1889 #ifdef CONFIG_SCSC_WLAN_DEBUG
1890 hip->hip_priv->stats.q_num_frames[HIP4_MIF_Q_TH_DAT] = hip->hip_priv->stats.q_num_frames[HIP4_MIF_Q_TH_DAT] + 1;
1891 #endif
1892 mem = scsc_mx_service_mif_addr_to_ptr(service, ref);
1893 m = (struct mbulk *)(mem);
1894 if (!m) {
1895 SLSI_ERR_NODEV("Dat: Mbulk is NULL 0x%x\n", ref);
1896 goto consume_dat_mbulk;
1897 }
1898
1899 skb = hip4_mbulk_to_skb(service, hip_priv, m, to_free, false);
1900 if (!skb) {
1901 SLSI_ERR_NODEV("Dat: Error parsing or allocating skb\n");
1902 hip4_dump_dbg(hip, m, skb, service);
1903 goto consume_dat_mbulk;
1904 }
1905
1906 #ifdef CONFIG_SCSC_WLAN_DEBUG
1907 if (m->flag & MBULK_F_WAKEUP) {
1908 SLSI_INFO(sdev, "WIFI wakeup by DATA frame:\n");
1909 SCSC_BIN_TAG_INFO(BINARY, skb->data, skb->len > 128 ? 128 : skb->len);
1910 }
1911 #else
1912 if (m->flag & MBULK_F_WAKEUP) {
1913 SLSI_INFO(sdev, "WIFI wakeup by DATA frame:\n");
1914 SCSC_BIN_TAG_INFO(BINARY, skb->data, fapi_get_siglen(skb) + ETH_HLEN);
1915 }
1916 #endif
1917 #ifdef CONFIG_SCSC_WLAN_DEBUG
1918 id = fapi_get_sigid(skb);
1919 hip4_history_record_add(TH, id);
1920 #endif
1921 if (slsi_hip_rx(sdev, skb) < 0) {
1922 SLSI_ERR_NODEV("Dat: Error detected slsi_hip_rx\n");
1923 hip4_dump_dbg(hip, m, skb, service);
1924 slsi_kfree_skb(skb);
1925 }
1926 consume_dat_mbulk:
1927 /* Increase index */
1928 idx_r++;
1929 idx_r &= (MAX_NUM - 1);
1930
1931 /* Go through the list of references to free */
1932 while ((ref = to_free[i++])) {
1933 /* Set the number of retries */
1934 retry = FB_NO_SPC_NUM_RET;
1935 /* return to the firmware */
1936 while (hip4_q_add_signal(hip, HIP4_MIF_Q_TH_RFB, ref, service) && retry > 0) {
1937 SLSI_WARN_NODEV("Dat: Not enough space in FB, retry: %d/%d\n", retry, FB_NO_SPC_NUM_RET);
1938 spin_unlock_bh(&hip_priv->rx_lock);
1939 msleep(FB_NO_SPC_SLEEP_MS);
1940 spin_lock_bh(&hip_priv->rx_lock);
1941 retry--;
1942 if (retry == 0)
1943 SLSI_ERR_NODEV("Dat: FB has not been freed for %d ms\n", FB_NO_SPC_NUM_RET * FB_NO_SPC_SLEEP_MS);
1944 SCSC_HIP4_SAMPLER_QFULL(hip_priv->minor, HIP4_MIF_Q_TH_RFB);
1945 }
1946 }
1947
1948 hip4_update_index(hip, HIP4_MIF_Q_TH_DAT, ridx, idx_r);
1949
1950 /* read again the write index */
1951 if ((idx_r == idx_w) && (packets_total < HIP4_POLLING_MAX_PACKETS)) {
1952 u8 old_idx = idx_w;
1953
1954 idx_w = hip4_read_index(hip, HIP4_MIF_Q_TH_DAT, widx);
1955 if (idx_w != old_idx) {
1956 SCSC_HIP4_SAMPLER_Q(hip_priv->minor, HIP4_MIF_Q_TH_DAT, ridx, idx_r, 1);
1957 SCSC_HIP4_SAMPLER_Q(hip_priv->minor, HIP4_MIF_Q_TH_DAT, widx, idx_w, 1);
1958 }
1959 }
1960 }
1961 SCSC_HIP4_SAMPLER_INT_OUT_BH(hip_priv->minor, 0);
1962
1963 if (no_change)
1964 atomic_inc(&hip->hip_priv->stats.spurious_irqs);
1965
1966 skip_data_q:
1967 if (!atomic_read(&hip->hip_priv->closing)) {
1968 /* Reset status variable. DO THIS BEFORE UNMASKING!!!*/
1969 atomic_set(&hip->hip_priv->watchdog_timer_active, 0);
1970 scsc_service_mifintrbit_bit_unmask(service, hip->hip_priv->intr_tohost);
1971 }
1972
1973 #ifdef CONFIG_ANDROID
1974 if (wake_lock_active(&hip->hip_priv->hip4_wake_lock)) {
1975 wake_unlock(&hip->hip_priv->hip4_wake_lock);
1976 SCSC_WLOG_WAKELOCK(WLOG_LAZY, WL_RELEASED, "hip4_wake_lock", WL_REASON_RX);
1977 }
1978 #endif
1979 bh_end = ktime_get();
1980 atomic_set(&hip->hip_priv->in_rx, 0);
1981 spin_unlock_bh(&hip_priv->rx_lock);
1982 }
1983
1984 /* IRQ handler for hip4. The function runs in Interrupt context, so all the
1985 * asssumptions related to interrupt should be applied (sleep, fast,...)
1986 */
1987 static void hip4_irq_handler(int irq, void *data)
1988 {
1989 struct slsi_hip4 *hip = (struct slsi_hip4 *)data;
1990 struct slsi_dev *sdev = container_of(hip, struct slsi_dev, hip4_inst);
1991
1992 (void)irq; /* unused */
1993
1994 if (!hip || !sdev || !sdev->service || !hip->hip_priv)
1995 return;
1996
1997 SCSC_HIP4_SAMPLER_INT(hip->hip_priv->minor, 0);
1998 SCSC_HIP4_SAMPLER_INT(hip->hip_priv->minor, 1);
1999 SCSC_HIP4_SAMPLER_INT(hip->hip_priv->minor, 2);
2000 intr_received = ktime_get();
2001
2002 #ifdef CONFIG_ANDROID
2003 if (!wake_lock_active(&hip->hip_priv->hip4_wake_lock)) {
2004 wake_lock_timeout(&hip->hip_priv->hip4_wake_lock, msecs_to_jiffies(SLSI_HIP_WAKELOCK_TIME_OUT_IN_MS));
2005 SCSC_WLOG_WAKELOCK(WLOG_LAZY, WL_TAKEN, "hip4_wake_lock", WL_REASON_RX);
2006 }
2007 #endif
2008 /* if wd timer is active system might be in trouble as it should be
2009 * cleared in the BH. Ignore updating the timer
2010 */
2011 if (!atomic_read(&hip->hip_priv->watchdog_timer_active)) {
2012 atomic_set(&hip->hip_priv->watchdog_timer_active, 1);
2013 mod_timer(&hip->hip_priv->watchdog, jiffies + HZ);
2014 } else {
2015 SLSI_ERR_NODEV("INT triggered while WDT is active\n");
2016 SLSI_ERR_NODEV("bh_init %lld\n", ktime_to_ns(bh_init));
2017 SLSI_ERR_NODEV("bh_end %lld\n", ktime_to_ns(bh_end));
2018 SLSI_ERR_NODEV("hip4_wq work_busy %d\n", work_busy(&hip->hip_priv->intr_wq));
2019 SLSI_ERR_NODEV("hip4_priv->in_rx %d\n", atomic_read(&hip->hip_priv->in_rx));
2020 }
2021 /* If system is not in suspend, mask interrupt to avoid interrupt storm and let BH run */
2022 if (!atomic_read(&hip->hip_priv->in_suspend)) {
2023 scsc_service_mifintrbit_bit_mask(sdev->service, hip->hip_priv->intr_tohost);
2024 hip->hip_priv->storm_count = 0;
2025 } else if (++hip->hip_priv->storm_count >= MAX_STORM) {
2026 /* A MAX_STORM number of interrupts has been received
2027 * when platform was in suspend. This indicates FW interrupt activity
2028 * that should resume the hip4, so it is safe to mask to avoid
2029 * interrupt storm.
2030 */
2031 hip->hip_priv->storm_count = 0;
2032 scsc_service_mifintrbit_bit_mask(sdev->service, hip->hip_priv->intr_tohost);
2033 }
2034
2035 atomic_inc(&hip->hip_priv->stats.irqs);
2036
2037 if (hip4_system_wq)
2038 schedule_work(&hip->hip_priv->intr_wq);
2039 else
2040 queue_work(hip->hip_priv->hip4_workq, &hip->hip_priv->intr_wq);
2041
2042 /* Clear interrupt */
2043 scsc_service_mifintrbit_bit_clear(sdev->service, hip->hip_priv->intr_tohost);
2044 SCSC_HIP4_SAMPLER_INT_OUT(hip->hip_priv->minor, 0);
2045 SCSC_HIP4_SAMPLER_INT_OUT(hip->hip_priv->minor, 1);
2046 SCSC_HIP4_SAMPLER_INT_OUT(hip->hip_priv->minor, 2);
2047 }
2048
2049 #ifdef CONFIG_SCSC_QOS
2050 static void hip4_pm_qos_work(struct work_struct *data)
2051 {
2052 struct hip4_priv *hip_priv = container_of(data, struct hip4_priv, pm_qos_work);
2053 struct slsi_hip4 *hip = hip_priv->hip;
2054 struct slsi_dev *sdev = container_of(hip, struct slsi_dev, hip4_inst);
2055 u8 state;
2056
2057 if (!sdev || !sdev->service) {
2058 WARN_ON(1);
2059 return;
2060 }
2061
2062 SLSI_DBG1(sdev, SLSI_HIP, "update to state %d\n", hip_priv->pm_qos_state);
2063 spin_lock_bh(&hip_priv->pm_qos_lock);
2064 state = hip_priv->pm_qos_state;
2065 spin_unlock_bh(&hip_priv->pm_qos_lock);
2066 scsc_service_pm_qos_update_request(sdev->service, state);
2067 }
2068
2069 static void hip4_traffic_monitor_cb(void *client_ctx, u32 state, u32 tput_tx, u32 tput_rx)
2070 {
2071 struct slsi_hip4 *hip = (struct slsi_hip4 *)client_ctx;
2072 struct slsi_dev *sdev = container_of(hip, struct slsi_dev, hip4_inst);
2073
2074 if (!sdev)
2075 return;
2076
2077 spin_lock_bh(&hip->hip_priv->pm_qos_lock);
2078 SLSI_DBG1(sdev, SLSI_HIP, "event (state:%u, tput_tx:%u bps, tput_rx:%u bps)\n", state, tput_tx, tput_rx);
2079 if (state == TRAFFIC_MON_CLIENT_STATE_HIGH)
2080 hip->hip_priv->pm_qos_state = SCSC_QOS_MAX;
2081 else if (state == TRAFFIC_MON_CLIENT_STATE_MID)
2082 hip->hip_priv->pm_qos_state = SCSC_QOS_MED;
2083 else
2084 hip->hip_priv->pm_qos_state = SCSC_QOS_DISABLED;
2085
2086 spin_unlock_bh(&hip->hip_priv->pm_qos_lock);
2087
2088 schedule_work(&hip->hip_priv->pm_qos_work);
2089 }
2090 #endif
2091
2092 #ifdef CONFIG_SCSC_LOGRING
2093 static void hip4_traffic_monitor_logring_cb(void *client_ctx, u32 state, u32 tput_tx, u32 tput_rx)
2094 {
2095 struct hip4_priv *hip_priv = (struct hip4_priv *)client_ctx;
2096 struct slsi_hip4 *hip = hip_priv->hip;
2097 struct slsi_dev *sdev = container_of(hip, struct slsi_dev, hip4_inst);
2098
2099 if (!sdev)
2100 return;
2101
2102 SLSI_DBG1(sdev, SLSI_HIP, "event (state:%u, tput_tx:%u bps, tput_rx:%u bps)\n", state, tput_tx, tput_rx);
2103 if (state == TRAFFIC_MON_CLIENT_STATE_HIGH || state == TRAFFIC_MON_CLIENT_STATE_MID) {
2104 if (hip4_dynamic_logging)
2105 scsc_logring_enable(false);
2106 } else {
2107 scsc_logring_enable(true);
2108 }
2109 }
2110 #endif
2111
2112 int hip4_init(struct slsi_hip4 *hip)
2113 {
2114 void *hip_ptr;
2115 struct hip4_hip_control *hip_control;
2116 struct scsc_service *service;
2117 struct slsi_dev *sdev = container_of(hip, struct slsi_dev, hip4_inst);
2118 scsc_mifram_ref ref, ref_scoreboard;
2119 int i;
2120 int ret;
2121 u32 total_mib_len;
2122 u32 mib_file_offset;
2123 #ifdef CONFIG_SCSC_WLAN_RX_NAPI
2124 struct net_device *dev;
2125 #endif
2126
2127 if (!sdev || !sdev->service)
2128 return -EINVAL;
2129
2130 hip->hip_priv = kzalloc(sizeof(*hip->hip_priv), GFP_ATOMIC);
2131 if (!hip->hip_priv)
2132 return -ENOMEM;
2133
2134 SLSI_INFO_NODEV("HIP4_WLAN_CONFIG_SIZE (%d)\n", HIP4_WLAN_CONFIG_SIZE);
2135 SLSI_INFO_NODEV("HIP4_WLAN_MIB_SIZE (%d)\n", HIP4_WLAN_MIB_SIZE);
2136 SLSI_INFO_NODEV("HIP4_WLAN_TX_DAT_SIZE (%d)\n", HIP4_WLAN_TX_DAT_SIZE);
2137 SLSI_INFO_NODEV("HIP4_WLAN_TX_CTL_SIZE (%d)\n", HIP4_WLAN_TX_CTL_SIZE);
2138 SLSI_INFO_NODEV("HIP4_WLAN_RX_SIZE (%d)\n", HIP4_WLAN_RX_SIZE);
2139 SLSI_INFO_NODEV("HIP4_WLAN_TOTAL_MEM (%d)\n", HIP4_WLAN_TOTAL_MEM);
2140 SLSI_INFO_NODEV("HIP4_DAT_SLOTS (%d)\n", HIP4_DAT_SLOTS);
2141 SLSI_INFO_NODEV("HIP4_CTL_SLOTS (%d)\n", HIP4_CTL_SLOTS);
2142 #ifdef CONFIG_SCSC_WLAN_DEBUG
2143 memset(&hip->hip_priv->stats, 0, sizeof(hip->hip_priv->stats));
2144 hip->hip_priv->stats.start = ktime_get();
2145 hip->hip_priv->stats.procfs_dir = proc_mkdir("driver/hip4", NULL);
2146 if (hip->hip_priv->stats.procfs_dir) {
2147 proc_create_data("info", S_IRUSR | S_IRGRP,
2148 hip->hip_priv->stats.procfs_dir, &hip4_procfs_stats_fops, hip);
2149 proc_create_data("history", S_IRUSR | S_IRGRP,
2150 hip->hip_priv->stats.procfs_dir, &hip4_procfs_history_fops, hip);
2151 proc_create_data("jitter", S_IRUSR | S_IRGRP,
2152 hip->hip_priv->stats.procfs_dir, &hip4_procfs_jitter_fops, hip);
2153 }
2154
2155 hip->hip_priv->minor = hip4_sampler_register_hip(sdev->maxwell_core);
2156 if (hip->hip_priv->minor < SCSC_HIP4_INTERFACES) {
2157 SLSI_DBG1_NODEV(SLSI_HIP, "registered with minor %d\n", hip->hip_priv->minor);
2158 sdev->minor_prof = hip->hip_priv->minor;
2159 } else {
2160 SLSI_DBG1_NODEV(SLSI_HIP, "hip4_sampler is not enabled\n");
2161 }
2162 #endif
2163
2164 /* Used in the workqueue */
2165 hip->hip_priv->hip = hip;
2166
2167 service = sdev->service;
2168
2169 hip->hip_priv->host_pool_id_dat = MBULK_POOL_ID_DATA;
2170 hip->hip_priv->host_pool_id_ctl = MBULK_POOL_ID_CTRL;
2171
2172 /* hip_ref contains the reference of the start of shared memory allocated for WLAN */
2173 /* hip_ptr is the kernel address of hip_ref*/
2174 hip_ptr = scsc_mx_service_mif_addr_to_ptr(service, hip->hip_ref);
2175
2176 #ifdef CONFIG_SCSC_WLAN_DEBUG
2177 /* Configure mbulk allocator - Data QUEUES */
2178 ret = mbulk_pool_add(MBULK_POOL_ID_DATA, hip_ptr + HIP4_WLAN_TX_DAT_OFFSET,
2179 hip_ptr + HIP4_WLAN_TX_DAT_OFFSET + HIP4_WLAN_TX_DAT_SIZE,
2180 (HIP4_WLAN_TX_DAT_SIZE / HIP4_DAT_SLOTS) - sizeof(struct mbulk), 5,
2181 hip->hip_priv->minor);
2182 if (ret)
2183 return ret;
2184
2185 /* Configure mbulk allocator - Control QUEUES */
2186 ret = mbulk_pool_add(MBULK_POOL_ID_CTRL, hip_ptr + HIP4_WLAN_TX_CTL_OFFSET,
2187 hip_ptr + HIP4_WLAN_TX_CTL_OFFSET + HIP4_WLAN_TX_CTL_SIZE,
2188 (HIP4_WLAN_TX_CTL_SIZE / HIP4_CTL_SLOTS) - sizeof(struct mbulk), 0,
2189 hip->hip_priv->minor);
2190 if (ret)
2191 return ret;
2192 #else
2193 /* Configure mbulk allocator - Data QUEUES */
2194 ret = mbulk_pool_add(MBULK_POOL_ID_DATA, hip_ptr + HIP4_WLAN_TX_DAT_OFFSET,
2195 hip_ptr + HIP4_WLAN_TX_DAT_OFFSET + HIP4_WLAN_TX_DAT_SIZE,
2196 (HIP4_WLAN_TX_DAT_SIZE / HIP4_DAT_SLOTS) - sizeof(struct mbulk), 5);
2197 if (ret)
2198 return ret;
2199
2200 /* Configure mbulk allocator - Control QUEUES */
2201 ret = mbulk_pool_add(MBULK_POOL_ID_CTRL, hip_ptr + HIP4_WLAN_TX_CTL_OFFSET,
2202 hip_ptr + HIP4_WLAN_TX_CTL_OFFSET + HIP4_WLAN_TX_CTL_SIZE,
2203 (HIP4_WLAN_TX_CTL_SIZE / HIP4_CTL_SLOTS) - sizeof(struct mbulk), 0);
2204 if (ret)
2205 return ret;
2206 #endif
2207
2208 /* Reset hip_control table */
2209 memset(hip_ptr, 0, sizeof(struct hip4_hip_control));
2210
2211 /* Reset Sample q values sending 0xff */
2212 SCSC_HIP4_SAMPLER_RESET(hip->hip_priv->minor);
2213
2214 /***** VERSION 4 *******/
2215 /* TOHOST Handler allocator */
2216 #ifdef CONFIG_SCSC_WLAN_RX_NAPI
2217 /* Q0 FH CTRL */
2218 hip->hip_priv->intr_tohost_mul[HIP4_MIF_Q_FH_CTRL] = MIF_NO_IRQ;
2219 /* Q1 FH DATA */
2220 hip->hip_priv->intr_tohost_mul[HIP4_MIF_Q_FH_DAT] = MIF_NO_IRQ;
2221 /* Q5 TH RFB */
2222 hip->hip_priv->intr_tohost_mul[HIP4_MIF_Q_TH_RFB] = MIF_NO_IRQ;
2223 /* Q2 FH FB */
2224 hip->hip_priv->intr_tohost_mul[HIP4_MIF_Q_FH_RFB] =
2225 scsc_service_mifintrbit_register_tohost(service, hip4_irq_handler_fb, hip);
2226 scsc_service_mifintrbit_bit_mask(service, hip->hip_priv->intr_tohost_mul[HIP4_MIF_Q_FH_RFB]);
2227 /* Q3 TH CTRL */
2228 hip->hip_priv->intr_tohost_mul[HIP4_MIF_Q_TH_CTRL] =
2229 scsc_service_mifintrbit_register_tohost(service, hip4_irq_handler_ctrl, hip);
2230 scsc_service_mifintrbit_bit_mask(service, hip->hip_priv->intr_tohost_mul[HIP4_MIF_Q_TH_CTRL]);
2231 /* Q4 TH DAT */
2232 hip->hip_priv->intr_tohost_mul[HIP4_MIF_Q_TH_DAT] =
2233 scsc_service_mifintrbit_register_tohost(service, hip4_irq_handler_dat, hip);
2234 scsc_service_mifintrbit_bit_mask(service, hip->hip_priv->intr_tohost_mul[HIP4_MIF_Q_TH_DAT]);
2235
2236 rcu_read_lock();
2237 /* one NAPI instance is ok for multiple netdev devices */
2238 dev = slsi_get_netdev_rcu(sdev, SLSI_NET_INDEX_WLAN);
2239 if (!dev) {
2240 SLSI_ERR(sdev, "netdev No longer exists\n");
2241 rcu_read_unlock();
2242 return -EINVAL;
2243 }
2244 netif_napi_add(dev, &hip->hip_priv->napi, hip4_napi_poll, NAPI_POLL_WEIGHT);
2245 rcu_read_unlock();
2246 #endif
2247 /* TOHOST Handler allocator */
2248 hip->hip_priv->intr_tohost =
2249 scsc_service_mifintrbit_register_tohost(service, hip4_irq_handler, hip);
2250
2251 /* Mask the interrupt to prevent intr been kicked during start */
2252 scsc_service_mifintrbit_bit_mask(service, hip->hip_priv->intr_tohost);
2253
2254 /* FROMHOST Handler allocator */
2255 hip->hip_priv->intr_fromhost =
2256 scsc_service_mifintrbit_alloc_fromhost(service, SCSC_MIFINTR_TARGET_R4);
2257
2258 /* Get hip_control pointer on shared memory */
2259 hip_control = (struct hip4_hip_control *)(hip_ptr +
2260 HIP4_WLAN_CONFIG_OFFSET);
2261
2262 /* Initialize scoreboard */
2263 if (scsc_mx_service_mif_ptr_to_addr(service, &hip_control->scoreboard, &ref_scoreboard))
2264 return -EFAULT;
2265
2266 /* Calculate total space used by wlan*.hcf files */
2267 for (i = 0, total_mib_len = 0; i < SLSI_WLAN_MAX_MIB_FILE; i++)
2268 total_mib_len += sdev->mib[i].mib_len;
2269
2270 /* Copy MIB content in shared memory if any */
2271 /* Clear the area to avoid picking up old values */
2272 memset(hip_ptr + HIP4_WLAN_MIB_OFFSET, 0, HIP4_WLAN_MIB_SIZE);
2273
2274 if (total_mib_len > HIP4_WLAN_MIB_SIZE) {
2275 SLSI_ERR_NODEV("MIB size (%d), is bigger than the MIB AREA (%d). Aborting memcpy\n", total_mib_len, HIP4_WLAN_MIB_SIZE);
2276 hip_control->config_v4.mib_loc = 0;
2277 hip_control->config_v4.mib_sz = 0;
2278 hip_control->config_v5.mib_loc = 0;
2279 hip_control->config_v5.mib_sz = 0;
2280 total_mib_len = 0;
2281 } else if (total_mib_len) {
2282 SLSI_INFO_NODEV("Loading MIB into shared memory, size (%d)\n", total_mib_len);
2283 /* Load each MIB file into shared DRAM region */
2284 for (i = 0, mib_file_offset = 0;
2285 i < SLSI_WLAN_MAX_MIB_FILE;
2286 i++) {
2287 SLSI_INFO_NODEV("Loading MIB %d into shared memory, offset (%d), size (%d), total (%d)\n", i, mib_file_offset, sdev->mib[i].mib_len, total_mib_len);
2288 if (sdev->mib[i].mib_len) {
2289 memcpy((u8 *)hip_ptr + HIP4_WLAN_MIB_OFFSET + mib_file_offset, sdev->mib[i].mib_data, sdev->mib[i].mib_len);
2290 mib_file_offset += sdev->mib[i].mib_len;
2291 }
2292 }
2293 hip_control->config_v4.mib_loc = hip->hip_ref + HIP4_WLAN_MIB_OFFSET;
2294 hip_control->config_v4.mib_sz = total_mib_len;
2295 hip_control->config_v5.mib_loc = hip->hip_ref + HIP4_WLAN_MIB_OFFSET;
2296 hip_control->config_v5.mib_sz = total_mib_len;
2297 } else {
2298 hip_control->config_v4.mib_loc = 0;
2299 hip_control->config_v4.mib_sz = 0;
2300 hip_control->config_v5.mib_loc = 0;
2301 hip_control->config_v5.mib_sz = 0;
2302 }
2303
2304 /* Initialize hip_control table for version 4 */
2305 /***** VERSION 4 *******/
2306 hip_control->config_v4.magic_number = 0xcaba0401;
2307 hip_control->config_v4.hip_config_ver = 4;
2308 hip_control->config_v4.config_len = sizeof(struct hip4_hip_config_version_4);
2309 hip_control->config_v4.host_cache_line = 64;
2310 hip_control->config_v4.host_buf_loc = hip->hip_ref + HIP4_WLAN_TX_OFFSET;
2311 hip_control->config_v4.host_buf_sz = HIP4_WLAN_TX_SIZE;
2312 hip_control->config_v4.fw_buf_loc = hip->hip_ref + HIP4_WLAN_RX_OFFSET;
2313 hip_control->config_v4.fw_buf_sz = HIP4_WLAN_RX_SIZE;
2314 hip_control->config_v4.log_config_loc = 0;
2315
2316 hip_control->config_v4.mif_fh_int_n = hip->hip_priv->intr_fromhost;
2317 for (i = 0; i < MIF_HIP_CFG_Q_NUM; i++) {
2318 #ifdef CONFIG_SCSC_WLAN_RX_NAPI
2319 hip_control->config_v4.mif_th_int_n[i] = hip->hip_priv->intr_tohost_mul[i];
2320 #else
2321 hip_control->config_v4.mif_th_int_n[i] = hip->hip_priv->intr_tohost;
2322 #endif
2323 }
2324
2325 hip_control->config_v4.scbrd_loc = (u32)ref_scoreboard;
2326 hip_control->config_v4.q_num = 6;
2327 hip_control->config_v4.q_len = 256;
2328 hip_control->config_v4.q_idx_sz = 1;
2329 /* Initialize q relative positions */
2330 for (i = 0; i < MIF_HIP_CFG_Q_NUM; i++) {
2331 if (scsc_mx_service_mif_ptr_to_addr(service, &hip_control->q[i].array, &ref))
2332 return -EFAULT;
2333 hip_control->config_v4.q_loc[i] = (u32)ref;
2334 }
2335 /***** END VERSION 4 *******/
2336
2337 /* Initialize hip_control table for version 5 */
2338 /***** VERSION 5 *******/
2339 hip_control->config_v5.magic_number = 0xcaba0401;
2340 hip_control->config_v5.hip_config_ver = 5;
2341 hip_control->config_v5.config_len = sizeof(struct hip4_hip_config_version_5);
2342 hip_control->config_v5.host_cache_line = 64;
2343 hip_control->config_v5.host_buf_loc = hip->hip_ref + HIP4_WLAN_TX_OFFSET;
2344 hip_control->config_v5.host_buf_sz = HIP4_WLAN_TX_SIZE;
2345 hip_control->config_v5.fw_buf_loc = hip->hip_ref + HIP4_WLAN_RX_OFFSET;
2346 hip_control->config_v5.fw_buf_sz = HIP4_WLAN_RX_SIZE;
2347 hip_control->config_v5.log_config_loc = 0;
2348 hip_control->config_v5.mif_fh_int_n = hip->hip_priv->intr_fromhost;
2349 hip_control->config_v5.mif_th_int_n = hip->hip_priv->intr_tohost;
2350 hip_control->config_v5.q_num = 6;
2351 hip_control->config_v5.q_len = 256;
2352 hip_control->config_v5.q_idx_sz = 1;
2353 hip_control->config_v5.scbrd_loc = (u32)ref_scoreboard; /* scoreborad location */
2354
2355 /* Initialize q relative positions */
2356 for (i = 0; i < MIF_HIP_CFG_Q_NUM; i++) {
2357 if (scsc_mx_service_mif_ptr_to_addr(service, &hip_control->q[i].array, &ref))
2358 return -EFAULT;
2359 hip_control->config_v5.q_loc[i] = (u32)ref;
2360 }
2361 /***** END VERSION 5 *******/
2362
2363 /* Initialzie hip_init configuration */
2364 hip_control->init.magic_number = 0xcaaa0400;
2365 if (scsc_mx_service_mif_ptr_to_addr(service, &hip_control->config_v4, &ref))
2366 return -EFAULT;
2367 hip_control->init.version_a_ref = ref;
2368
2369 if (scsc_mx_service_mif_ptr_to_addr(service, &hip_control->config_v5, &ref))
2370 return -EFAULT;
2371 hip_control->init.version_b_ref = ref;
2372 /* End hip_init configuration */
2373
2374 hip->hip_control = hip_control;
2375 hip->hip_priv->scbrd_base = &hip_control->scoreboard;
2376
2377 spin_lock_init(&hip->hip_priv->rx_lock);
2378 atomic_set(&hip->hip_priv->in_rx, 0);
2379 spin_lock_init(&hip->hip_priv->tx_lock);
2380 atomic_set(&hip->hip_priv->in_tx, 0);
2381
2382 #ifdef CONFIG_ANDROID
2383 #ifdef CONFIG_SCSC_WLAN_RX_NAPI
2384 wake_lock_init(&hip->hip_priv->hip4_wake_lock_tx, WAKE_LOCK_SUSPEND, "hip4_wake_lock_tx");
2385 wake_lock_init(&hip->hip_priv->hip4_wake_lock_ctrl, WAKE_LOCK_SUSPEND, "hip4_wake_lock_ctrl");
2386 wake_lock_init(&hip->hip_priv->hip4_wake_lock_data, WAKE_LOCK_SUSPEND, "hip4_wake_lock_data");
2387 #endif
2388 wake_lock_init(&hip->hip_priv->hip4_wake_lock, WAKE_LOCK_SUSPEND, "hip4_wake_lock");
2389 #endif
2390 /* Init work structs */
2391 hip->hip_priv->hip4_workq = create_singlethread_workqueue("hip4_work");
2392 if (!hip->hip_priv->hip4_workq) {
2393 SLSI_ERR_NODEV("Error creating singlethread_workqueue\n");
2394 return -ENOMEM;
2395 }
2396 #ifdef CONFIG_SCSC_WLAN_RX_NAPI
2397 tasklet_init(&hip->hip_priv->intr_tasklet, hip4_irq_data_tasklet, (unsigned long)hip);
2398 INIT_WORK(&hip->hip_priv->intr_wq_ctrl, hip4_wq_ctrl);
2399 INIT_WORK(&hip->hip_priv->intr_wq_fb, hip4_wq_fb);
2400 #endif
2401 INIT_WORK(&hip->hip_priv->intr_wq, hip4_wq);
2402
2403 rwlock_init(&hip->hip_priv->rw_scoreboard);
2404
2405 /* Setup watchdog timer */
2406 atomic_set(&hip->hip_priv->watchdog_timer_active, 0);
2407 spin_lock_init(&hip->hip_priv->watchdog_lock);
2408 #if KERNEL_VERSION(4, 15, 0) <= LINUX_VERSION_CODE
2409 timer_setup(&hip->hip_priv->watchdog, hip4_watchdog, 0);
2410 #else
2411 setup_timer(&hip->hip_priv->watchdog, hip4_watchdog, (unsigned long)hip);
2412 #endif
2413
2414 atomic_set(&hip->hip_priv->gmod, HIP4_DAT_SLOTS);
2415 atomic_set(&hip->hip_priv->gactive, 1);
2416 spin_lock_init(&hip->hip_priv->gbot_lock);
2417 hip->hip_priv->saturated = 0;
2418
2419 #ifdef CONFIG_SCSC_SMAPPER
2420 /* Init SMAPPER */
2421 if (hip4_smapper_enable) {
2422 if (hip4_smapper_init(sdev, hip)) {
2423 SLSI_ERR_NODEV("Error on hip4_smapper init\n");
2424 hip4_smapper_is_enabled = false;
2425 } else {
2426 hip4_smapper_is_enabled = true;
2427 }
2428 }
2429 #endif
2430 #ifdef CONFIG_SCSC_QOS
2431 /* setup for PM QoS */
2432 spin_lock_init(&hip->hip_priv->pm_qos_lock);
2433
2434 if (hip4_qos_enable) {
2435 if (!scsc_service_pm_qos_add_request(service, SCSC_QOS_DISABLED)) {
2436 /* register to traffic monitor for throughput events */
2437 if (slsi_traffic_mon_client_register(sdev, hip, TRAFFIC_MON_CLIENT_MODE_EVENTS, (hip4_qos_med_tput_in_mbps * 1000 * 1000), (hip4_qos_max_tput_in_mbps * 1000 * 1000), hip4_traffic_monitor_cb))
2438 SLSI_WARN(sdev, "failed to add PM QoS client to traffic monitor\n");
2439 else
2440 INIT_WORK(&hip->hip_priv->pm_qos_work, hip4_pm_qos_work);
2441 } else {
2442 SLSI_WARN(sdev, "failed to add PM QoS request\n");
2443 }
2444 }
2445 #endif
2446 #ifdef CONFIG_SCSC_LOGRING
2447 /* register to traffic monitor for dynamic logring logging */
2448 if (slsi_traffic_mon_client_register(sdev, hip->hip_priv, TRAFFIC_MON_CLIENT_MODE_EVENTS, 0, (hip4_dynamic_logging_tput_in_mbps * 1000 * 1000), hip4_traffic_monitor_logring_cb))
2449 SLSI_WARN(sdev, "failed to add Logring client to traffic monitor\n");
2450 #endif
2451 return 0;
2452 }
2453
2454 /**
2455 * This function returns the number of free slots available to
2456 * transmit control packet.
2457 */
2458 int hip4_free_ctrl_slots_count(struct slsi_hip4 *hip)
2459 {
2460 return mbulk_pool_get_free_count(MBULK_POOL_ID_CTRL);
2461 }
2462
2463 /**
2464 * This function is in charge to transmit a frame through the HIP.
2465 * It does NOT take ownership of the SKB unless it successfully transmit it;
2466 * as a consequence skb is NOT freed on error.
2467 * We return ENOSPC on queue related troubles in order to trigger upper
2468 * layers of kernel to requeue/retry.
2469 * We free ONLY locally-allocated stuff.
2470 */
2471 int scsc_wifi_transmit_frame(struct slsi_hip4 *hip, bool ctrl_packet, struct sk_buff *skb)
2472 {
2473 struct scsc_service *service;
2474 scsc_mifram_ref offset;
2475 struct mbulk *m;
2476 struct slsi_dev *sdev = container_of(hip, struct slsi_dev, hip4_inst);
2477 struct fapi_signal_header *fapi_header;
2478 int ret = 0;
2479 #ifdef CONFIG_SCSC_WLAN_HIP4_PROFILING
2480 struct slsi_skb_cb *cb = slsi_skb_cb_get(skb);
2481 #endif
2482 #ifdef CONFIG_SCSC_WLAN_RX_NAPI
2483 u32 conf_hip4_ver = 0;
2484 #endif
2485
2486 if (!hip || !sdev || !sdev->service || !skb || !hip->hip_priv)
2487 return -EINVAL;
2488
2489 spin_lock_bh(&hip->hip_priv->tx_lock);
2490 atomic_set(&hip->hip_priv->in_tx, 1);
2491
2492 #ifdef CONFIG_ANDROID
2493 #ifdef CONFIG_SCSC_WLAN_RX_NAPI
2494 conf_hip4_ver = scsc_wifi_get_hip_config_version(&sdev->hip4_inst.hip_control->init);
2495 if (conf_hip4_ver == 4) {
2496 if (!wake_lock_active(&hip->hip_priv->hip4_wake_lock_tx)) {
2497 wake_lock_timeout(&hip->hip_priv->hip4_wake_lock_tx, msecs_to_jiffies(SLSI_HIP_WAKELOCK_TIME_OUT_IN_MS));
2498 SCSC_WLOG_WAKELOCK(WLOG_LAZY, WL_TAKEN, "hip4_wake_lock_tx", WL_REASON_TX);
2499 }
2500 } else {
2501 if (!wake_lock_active(&hip->hip_priv->hip4_wake_lock)) {
2502 wake_lock_timeout(&hip->hip_priv->hip4_wake_lock, msecs_to_jiffies(SLSI_HIP_WAKELOCK_TIME_OUT_IN_MS));
2503 SCSC_WLOG_WAKELOCK(WLOG_LAZY, WL_TAKEN, "hip4_wake_lock", WL_REASON_TX);
2504 }
2505 }
2506 #else
2507 if (!wake_lock_active(&hip->hip_priv->hip4_wake_lock)) {
2508 wake_lock_timeout(&hip->hip_priv->hip4_wake_lock, msecs_to_jiffies(SLSI_HIP_WAKELOCK_TIME_OUT_IN_MS));
2509 SCSC_WLOG_WAKELOCK(WLOG_LAZY, WL_TAKEN, "hip4_wake_lock", WL_REASON_TX);
2510 }
2511 #endif
2512 #endif
2513 service = sdev->service;
2514
2515 fapi_header = (struct fapi_signal_header *)skb->data;
2516
2517 m = hip4_skb_to_mbulk(hip->hip_priv, skb, ctrl_packet);
2518 if (!m) {
2519 SCSC_HIP4_SAMPLER_MFULL(hip->hip_priv->minor);
2520 ret = -ENOSPC;
2521 SLSI_ERR_NODEV("mbulk is NULL\n");
2522 goto error;
2523 }
2524
2525 if (scsc_mx_service_mif_ptr_to_addr(service, m, &offset) < 0) {
2526 mbulk_free_virt_host(m);
2527 ret = -EFAULT;
2528 SLSI_ERR_NODEV("Incorrect reference memory\n");
2529 goto error;
2530 }
2531
2532 if (hip4_q_add_signal(hip, ctrl_packet ? HIP4_MIF_Q_FH_CTRL : HIP4_MIF_Q_FH_DAT, offset, service)) {
2533 SCSC_HIP4_SAMPLER_QFULL(hip->hip_priv->minor, ctrl_packet ? HIP4_MIF_Q_FH_CTRL : HIP4_MIF_Q_FH_DAT);
2534 mbulk_free_virt_host(m);
2535 ret = -ENOSPC;
2536 SLSI_ERR_NODEV("No space\n");
2537 goto error;
2538 }
2539
2540 #ifdef CONFIG_SCSC_WLAN_HIP4_PROFILING
2541 /* colour is defined as: */
2542 /* u8 register bits:
2543 * 0 - do not use
2544 * [2:1] - vif
2545 * [7:3] - peer_index
2546 */
2547 if (ctrl_packet) {
2548 /* Record control signal */
2549 SCSC_HIP4_SAMPLER_SIGNAL_CTRLTX(hip->hip_priv->minor, (fapi_header->id & 0xff00) >> 8, fapi_header->id & 0xff);
2550 } else {
2551 SCSC_HIP4_SAMPLER_PKT_TX_HIP4(hip->hip_priv->minor, fapi_get_u16(skb, u.ma_unitdata_req.host_tag));
2552 SCSC_HIP4_SAMPLER_VIF_PEER(hip->hip_priv->minor, 1, (cb->colour & 0x6) >> 1, (cb->colour & 0xf8) >> 3);
2553 }
2554 #endif
2555 #ifdef CONFIG_SCSC_WLAN_DEBUG
2556 hip4_history_record_add(FH, fapi_header->id);
2557 #endif
2558
2559 /* Here we push a copy of the bare skb TRANSMITTED data also to the logring
2560 * as a binary record. Note that bypassing UDI subsystem as a whole
2561 * means we are losing:
2562 * UDI filtering / UDI Header INFO / UDI QueuesFrames Throttling /
2563 * UDI Skb Asynchronous processing
2564 * We keep separated DATA/CTRL paths.
2565 */
2566 if (ctrl_packet)
2567 SCSC_BIN_TAG_DEBUG(BIN_WIFI_CTRL_TX, skb->data, skb_headlen(skb));
2568 else
2569 SCSC_BIN_TAG_DEBUG(BIN_WIFI_DATA_TX, skb->data, skb_headlen(skb));
2570 /* slsi_log_clients_log_signal_fast: skb is copied to all the log clients */
2571 slsi_log_clients_log_signal_fast(sdev, &sdev->log_clients, skb, SLSI_LOG_DIRECTION_FROM_HOST);
2572 slsi_kfree_skb(skb);
2573 atomic_set(&hip->hip_priv->in_tx, 0);
2574 spin_unlock_bh(&hip->hip_priv->tx_lock);
2575 return 0;
2576
2577 error:
2578 #ifdef CONFIG_ANDROID
2579 #ifdef CONFIG_SCSC_WLAN_RX_NAPI
2580 if (conf_hip4_ver == 4) {
2581 if (wake_lock_active(&hip->hip_priv->hip4_wake_lock_tx)) {
2582 wake_unlock(&hip->hip_priv->hip4_wake_lock_tx);
2583 SCSC_WLOG_WAKELOCK(WLOG_LAZY, WL_RELEASED, "hip4_wake_lock_tx", WL_REASON_TX);
2584 }
2585 } else {
2586 if (wake_lock_active(&hip->hip_priv->hip4_wake_lock)) {
2587 wake_unlock(&hip->hip_priv->hip4_wake_lock);
2588 SCSC_WLOG_WAKELOCK(WLOG_LAZY, WL_RELEASED, "hip4_wake_lock", WL_REASON_TX);
2589 }
2590 }
2591 #else
2592 if (wake_lock_active(&hip->hip_priv->hip4_wake_lock)) {
2593 wake_unlock(&hip->hip_priv->hip4_wake_lock);
2594 SCSC_WLOG_WAKELOCK(WLOG_LAZY, WL_RELEASED, "hip4_wake_lock", WL_REASON_TX);
2595 }
2596 #endif
2597 #endif
2598 atomic_set(&hip->hip_priv->in_tx, 0);
2599 spin_unlock_bh(&hip->hip_priv->tx_lock);
2600 return ret;
2601 }
2602
2603 /* HIP4 has been initialize, setup with values
2604 * provided by FW
2605 */
2606 int hip4_setup(struct slsi_hip4 *hip)
2607 {
2608 struct slsi_dev *sdev = container_of(hip, struct slsi_dev, hip4_inst);
2609 struct scsc_service *service;
2610 u32 conf_hip4_ver = 0;
2611
2612 if (!sdev || !sdev->service)
2613 return -EIO;
2614
2615 if (atomic_read(&sdev->hip.hip_state) != SLSI_HIP_STATE_STARTED)
2616 return -EIO;
2617
2618 service = sdev->service;
2619
2620 /* Get the Version reported by the FW */
2621 conf_hip4_ver = scsc_wifi_get_hip_config_version(&hip->hip_control->init);
2622 /* Check if the version is supported. And get the index */
2623 /* This is hardcoded and may change in future versions */
2624 if (conf_hip4_ver != 4 && conf_hip4_ver != 3) {
2625 SLSI_ERR_NODEV("FW Version %d not supported\n", conf_hip4_ver);
2626 return -EIO;
2627 }
2628
2629 if (conf_hip4_ver == 4) {
2630 hip->hip_priv->unidat_req_headroom =
2631 scsc_wifi_get_hip_config_u8(&hip->hip_control, unidat_req_headroom, 4);
2632 hip->hip_priv->unidat_req_tailroom =
2633 scsc_wifi_get_hip_config_u8(&hip->hip_control, unidat_req_tailroom, 4);
2634 hip->hip_priv->version = 4;
2635
2636 #ifdef CONFIG_SCSC_WLAN_RX_NAPI
2637 napi_enable(&hip->hip_priv->napi);
2638 #endif
2639 } else {
2640 /* version 5 */
2641 hip->hip_priv->unidat_req_headroom =
2642 scsc_wifi_get_hip_config_u8(&hip->hip_control, unidat_req_headroom, 5);
2643 hip->hip_priv->unidat_req_tailroom =
2644 scsc_wifi_get_hip_config_u8(&hip->hip_control, unidat_req_tailroom, 5);
2645 hip->hip_priv->version = 5;
2646 }
2647 /* Unmask interrupts - now host should handle them */
2648 atomic_set(&hip->hip_priv->stats.irqs, 0);
2649 atomic_set(&hip->hip_priv->stats.spurious_irqs, 0);
2650 atomic_set(&sdev->debug_inds, 0);
2651
2652 atomic_set(&hip->hip_priv->closing, 0);
2653
2654 #ifdef CONFIG_SCSC_WLAN_RX_NAPI
2655 if (conf_hip4_ver == 4) {
2656 scsc_service_mifintrbit_bit_unmask(service, hip->hip_priv->intr_tohost_mul[HIP4_MIF_Q_FH_RFB]);
2657 scsc_service_mifintrbit_bit_unmask(service, hip->hip_priv->intr_tohost_mul[HIP4_MIF_Q_TH_CTRL]);
2658 scsc_service_mifintrbit_bit_unmask(service, hip->hip_priv->intr_tohost_mul[HIP4_MIF_Q_TH_DAT]);
2659 } else {
2660 scsc_service_mifintrbit_bit_unmask(service, hip->hip_priv->intr_tohost);
2661 }
2662 #else
2663 scsc_service_mifintrbit_bit_unmask(service, hip->hip_priv->intr_tohost);
2664 #endif
2665 return 0;
2666 }
2667
2668 /* On suspend hip4 needs to ensure that TH interrupts *are* unmasked */
2669 void hip4_suspend(struct slsi_hip4 *hip)
2670 {
2671 struct slsi_dev *sdev;
2672 struct scsc_service *service;
2673 #ifdef CONFIG_SCSC_WLAN_RX_NAPI
2674 u32 conf_hip4_ver = 0;
2675 #endif
2676
2677 if (!hip || !hip->hip_priv)
2678 return;
2679
2680 sdev = container_of(hip, struct slsi_dev, hip4_inst);
2681 if (!sdev || !sdev->service)
2682 return;
2683
2684 if (atomic_read(&sdev->hip.hip_state) != SLSI_HIP_STATE_STARTED)
2685 return;
2686
2687 service = sdev->service;
2688
2689 slsi_log_client_msg(sdev, UDI_DRV_SUSPEND_IND, 0, NULL);
2690 SCSC_HIP4_SAMPLER_SUSPEND(hip->hip_priv->minor);
2691
2692 atomic_set(&hip->hip_priv->in_suspend, 1);
2693
2694 #ifdef CONFIG_SCSC_WLAN_RX_NAPI
2695 conf_hip4_ver = scsc_wifi_get_hip_config_version(&hip->hip_control->init);
2696
2697 if (conf_hip4_ver == 4) {
2698 u8 i;
2699 for (i = 0; i < MIF_HIP_CFG_Q_NUM; i++)
2700 if (hip->hip_priv->intr_tohost_mul[i] != MIF_NO_IRQ)
2701 scsc_service_mifintrbit_bit_unmask(service, hip->hip_priv->intr_tohost_mul[i]);
2702 } else {
2703 scsc_service_mifintrbit_bit_unmask(service, hip->hip_priv->intr_tohost);
2704 }
2705 #else
2706 scsc_service_mifintrbit_bit_unmask(service, hip->hip_priv->intr_tohost);
2707 #endif
2708 }
2709
2710 void hip4_resume(struct slsi_hip4 *hip)
2711 {
2712 struct slsi_dev *sdev;
2713 struct scsc_service *service;
2714 #ifdef CONFIG_SCSC_WLAN_RX_NAPI
2715 u32 conf_hip4_ver = 0;
2716 #endif
2717
2718 if (!hip || !hip->hip_priv)
2719 return;
2720
2721 sdev = container_of(hip, struct slsi_dev, hip4_inst);
2722 if (!sdev || !sdev->service)
2723 return;
2724
2725 if (atomic_read(&sdev->hip.hip_state) != SLSI_HIP_STATE_STARTED)
2726 return;
2727
2728 service = sdev->service;
2729
2730 #ifdef CONFIG_SCSC_WLAN_RX_NAPI
2731 conf_hip4_ver = scsc_wifi_get_hip_config_version(&hip->hip_control->init);
2732
2733 if (conf_hip4_ver == 4) {
2734 u8 i;
2735 for (i = 0; i < MIF_HIP_CFG_Q_NUM; i++)
2736 if (hip->hip_priv->intr_tohost_mul[i] != MIF_NO_IRQ)
2737 scsc_service_mifintrbit_bit_unmask(service, hip->hip_priv->intr_tohost_mul[i]);
2738 } else {
2739 scsc_service_mifintrbit_bit_unmask(service, hip->hip_priv->intr_tohost);
2740 }
2741 #else
2742 scsc_service_mifintrbit_bit_unmask(service, hip->hip_priv->intr_tohost);
2743 #endif
2744
2745 slsi_log_client_msg(sdev, UDI_DRV_RESUME_IND, 0, NULL);
2746 SCSC_HIP4_SAMPLER_RESUME(hip->hip_priv->minor);
2747 atomic_set(&hip->hip_priv->in_suspend, 0);
2748 }
2749
2750 void hip4_freeze(struct slsi_hip4 *hip)
2751 {
2752 struct slsi_dev *sdev;
2753 struct scsc_service *service;
2754 #ifdef CONFIG_SCSC_WLAN_RX_NAPI
2755 u32 conf_hip4_ver = 0;
2756 #endif
2757
2758 if (!hip || !hip->hip_priv)
2759 return;
2760
2761 sdev = container_of(hip, struct slsi_dev, hip4_inst);
2762 if (!sdev || !sdev->service)
2763 return;
2764
2765 if (atomic_read(&sdev->hip.hip_state) != SLSI_HIP_STATE_STARTED)
2766 return;
2767
2768 service = sdev->service;
2769
2770 closing = ktime_get();
2771 atomic_set(&hip->hip_priv->closing, 1);
2772
2773 hip4_dump_dbg(hip, NULL, NULL, service);
2774 #ifdef CONFIG_SCSC_WLAN_RX_NAPI
2775 conf_hip4_ver = scsc_wifi_get_hip_config_version(&hip->hip_control->init);
2776
2777 if (conf_hip4_ver == 4) {
2778 u8 i;
2779 for (i = 0; i < MIF_HIP_CFG_Q_NUM; i++)
2780 if (hip->hip_priv->intr_tohost_mul[i] != MIF_NO_IRQ)
2781 scsc_service_mifintrbit_bit_mask(service, hip->hip_priv->intr_tohost_mul[i]);
2782
2783 tasklet_kill(&hip->hip_priv->intr_tasklet);
2784 cancel_work_sync(&hip->hip_priv->intr_wq_ctrl);
2785 cancel_work_sync(&hip->hip_priv->intr_wq_fb);
2786 } else {
2787 scsc_service_mifintrbit_bit_mask(service, hip->hip_priv->intr_tohost);
2788 cancel_work_sync(&hip->hip_priv->intr_wq);
2789 }
2790 #else
2791 scsc_service_mifintrbit_bit_mask(service, hip->hip_priv->intr_tohost);
2792 cancel_work_sync(&hip->hip_priv->intr_wq);
2793 #endif
2794 flush_workqueue(hip->hip_priv->hip4_workq);
2795 destroy_workqueue(hip->hip_priv->hip4_workq);
2796 atomic_set(&hip->hip_priv->watchdog_timer_active, 0);
2797
2798 /* Deactive the wd timer prior its expiration */
2799 del_timer_sync(&hip->hip_priv->watchdog);
2800 }
2801
2802 void hip4_deinit(struct slsi_hip4 *hip)
2803 {
2804 struct slsi_dev *sdev = container_of(hip, struct slsi_dev, hip4_inst);
2805 struct scsc_service *service;
2806 #ifdef CONFIG_SCSC_WLAN_RX_NAPI
2807 u8 i;
2808 #endif
2809 if (!sdev || !sdev->service)
2810 return;
2811
2812 service = sdev->service;
2813
2814 #ifdef CONFIG_SCSC_LOGRING
2815 slsi_traffic_mon_client_unregister(sdev, hip->hip_priv);
2816 /* Reenable logring in case was disabled */
2817 scsc_logring_enable(true);
2818 #endif
2819 #ifdef CONFIG_SCSC_QOS
2820 /* de-register with traffic monitor */
2821 slsi_traffic_mon_client_unregister(sdev, hip);
2822 scsc_service_pm_qos_remove_request(service);
2823 #endif
2824
2825 #ifdef CONFIG_SCSC_SMAPPER
2826 /* Init SMAPPER */
2827 if (hip4_smapper_is_enabled) {
2828 hip4_smapper_is_enabled = false;
2829 hip4_smapper_deinit(sdev, hip);
2830 }
2831 #endif
2832
2833 closing = ktime_get();
2834 atomic_set(&hip->hip_priv->closing, 1);
2835
2836 #ifdef CONFIG_SCSC_WLAN_RX_NAPI
2837 for (i = 0; i < MIF_HIP_CFG_Q_NUM; i++)
2838 if (hip->hip_priv->intr_tohost_mul[i] != MIF_NO_IRQ)
2839 scsc_service_mifintrbit_bit_mask(service, hip->hip_priv->intr_tohost_mul[i]);
2840
2841 tasklet_kill(&hip->hip_priv->intr_tasklet);
2842 cancel_work_sync(&hip->hip_priv->intr_wq_ctrl);
2843 cancel_work_sync(&hip->hip_priv->intr_wq_fb);
2844
2845 for (i = 0; i < MIF_HIP_CFG_Q_NUM; i++)
2846 if (hip->hip_priv->intr_tohost_mul[i] != MIF_NO_IRQ)
2847 scsc_service_mifintrbit_unregister_tohost(service, hip->hip_priv->intr_tohost_mul[i]);
2848
2849 netif_napi_del(&hip->hip_priv->napi);
2850 #endif
2851 scsc_service_mifintrbit_bit_mask(service, hip->hip_priv->intr_tohost);
2852 cancel_work_sync(&hip->hip_priv->intr_wq);
2853 scsc_service_mifintrbit_unregister_tohost(service, hip->hip_priv->intr_tohost);
2854
2855 flush_workqueue(hip->hip_priv->hip4_workq);
2856 destroy_workqueue(hip->hip_priv->hip4_workq);
2857
2858 scsc_service_mifintrbit_free_fromhost(service, hip->hip_priv->intr_fromhost, SCSC_MIFINTR_TARGET_R4);
2859
2860 #ifdef CONFIG_ANDROID
2861 #ifdef CONFIG_SCSC_WLAN_RX_NAPI
2862 wake_lock_destroy(&hip->hip_priv->hip4_wake_lock_tx);
2863 wake_lock_destroy(&hip->hip_priv->hip4_wake_lock_ctrl);
2864 wake_lock_destroy(&hip->hip_priv->hip4_wake_lock_data);
2865 #endif
2866 wake_lock_destroy(&hip->hip_priv->hip4_wake_lock);
2867 #endif
2868
2869 /* If we get to that point with rx_lock/tx_lock claimed, trigger BUG() */
2870 WARN_ON(atomic_read(&hip->hip_priv->in_tx));
2871 WARN_ON(atomic_read(&hip->hip_priv->in_rx));
2872
2873 atomic_set(&hip->hip_priv->watchdog_timer_active, 0);
2874 /* Deactive the wd timer prior its expiration */
2875 del_timer_sync(&hip->hip_priv->watchdog);
2876
2877 #ifdef CONFIG_SCSC_WLAN_DEBUG
2878 if (hip->hip_priv->stats.procfs_dir) {
2879 remove_proc_entry("driver/hip4/jitter", NULL);
2880 remove_proc_entry("driver/hip4/info", NULL);
2881 remove_proc_entry("driver/hip4/history", NULL);
2882 remove_proc_entry("driver/hip4", NULL);
2883 }
2884 #endif
2885 kfree(hip->hip_priv);
2886
2887 hip->hip_priv = NULL;
2888 }