1 /******************************************************************************
3 * Copyright (c) 2014 - 2019 Samsung Electronics Co., Ltd. All rights reserved
5 *****************************************************************************/
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>
24 #include "hip4_sampler.h"
27 #include "scsc_wifilogger_rings.h"
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)");
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)");
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");
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)");
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");
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");
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
;
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");
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");
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
;
89 static ktime_t intr_received
;
90 static ktime_t bh_init
;
91 static ktime_t bh_end
;
95 static ktime_t closing
;
102 static u8
hip4_read_index(struct slsi_hip4
*hip
, u32 q
, enum rw r_w
);
104 /* Q mapping V3 - V4 */
105 /*offset of F/W owned indices */
106 #define FW_OWN_OFS (64)
108 * HIP queue indices layout in the scoreboard (SC-505612-DD). v3
111 * +-----------------------------------+
112 * +0 | Q3R | Q2R | Q1W | Q0W | Owned by the host
113 * +-----------------------------------+
114 * +4 | | | Q5W | Q4R | Owned by the host
115 * +-----------------------------------+
117 * +-----------------------------------+
118 * +64 | Q3W | Q2W | Q1R | Q0R | Owned by the F/W
119 * +-----------------------------------+
120 * +68 | | | Q5R | Q4W | Owned by the F/W
121 * +-----------------------------------+
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.
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 */
135 /*offset of F/W owned VIF Status */
136 #define FW_OWN_VIF (96)
138 * HIP Pause state VIF. v4. 2 bits per PEER
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 * +-----------------------------------+
160 /* MAX_STORM. Max Interrupts allowed when platform is in suspend */
163 /* Timeout for Wakelocks in HIP */
164 #define SLSI_HIP_WAKELOCK_TIME_OUT_IN_MS (1000)
166 #ifdef CONFIG_SCSC_WLAN_DEBUG
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
;
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 */
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
;
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 */
196 /* MAX_HISTORY_RECORDS should be power of two */
197 #define MAX_HISTORY_RECORDS 32
202 struct hip4_history
{
207 } hip4_signal_history
[MAX_HISTORY_RECORDS
];
209 static u32 history_record
;
211 /* This function should be called from atomic context */
212 static void hip4_history_record_add(bool dir
, u32 signal_id
)
214 struct hip4_history record
;
216 record
= hip4_signal_history
[history_record
];
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();
222 hip4_signal_history
[history_record
] = record
;
226 history_record
= (history_record
+ 1) & (MAX_HISTORY_RECORDS
- 1);
228 record
= hip4_signal_history
[history_record
];
230 record
.signal
= signal_id
;
232 record
.last_time
= ktime_get();
233 hip4_signal_history
[history_record
] = record
;
236 #define HIP4_HISTORY(in_seq_file, m, fmt, arg ...) \
239 seq_printf(m, fmt, ## arg); \
241 SLSI_ERR_NODEV(fmt, ## arg); \
244 static void hip4_history_record_print(bool in_seq_file
, struct seq_file
*m
)
246 struct hip4_history record
;
250 old
= ktime_set(0, 0);
252 /* Start with the Next record to print history in order */
253 pos
= (history_record
+ 1) & (MAX_HISTORY_RECORDS
- 1);
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
];
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
)));
264 old
= record
.last_time
;
265 pos
= (pos
+ 1) & (MAX_HISTORY_RECORDS
- 1);
269 static int hip4_proc_show_history(struct seq_file
*m
, void *v
)
271 hip4_history_record_print(true, m
);
275 static int hip4_proc_history_open(struct inode
*inode
, struct file
*file
)
277 return single_open(file
, hip4_proc_show_history
, PDE_DATA(inode
));
280 static const struct file_operations hip4_procfs_history_fops
= {
281 .owner
= THIS_MODULE
,
282 .open
= hip4_proc_history_open
,
285 .release
= single_release
,
288 static int hip4_proc_show(struct seq_file
*m
, void *v
)
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
);
295 u32 conf_hip4_ver
= 0;
298 if (!hip
->hip_priv
) {
299 seq_puts(m
, "HIP4 not active\n");
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
);
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
);
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
]);
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()));
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
);
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
));
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
]);
417 static int hip4_proc_open(struct inode
*inode
, struct file
*file
)
419 return single_open(file
, hip4_proc_show
, PDE_DATA(inode
));
422 static const struct file_operations hip4_procfs_stats_fops
= {
423 .owner
= THIS_MODULE
,
424 .open
= hip4_proc_open
,
427 .release
= single_release
,
430 static int hip4_proc_jitter_show(struct seq_file
*m
, void *v
)
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
);
452 static int hip4_proc_jitter_open(struct inode
*inode
, struct file
*file
)
454 return single_open(file
, hip4_proc_jitter_show
, PDE_DATA(inode
));
457 static ssize_t
hip4_proc_jitter_clear(struct file
*file
, const char __user
*user_buf
, size_t count
, loff_t
*ppos
)
459 SLSI_INFO_NODEV("Clear Histogram\n");
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;
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
,
486 .release
= single_release
,
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
)
493 return ktime_add_ns(kt
, msec
* NSEC_PER_MSEC
);
497 #define FB_NO_SPC_NUM_RET 100
498 #define FB_NO_SPC_SLEEP_MS 10
499 #define FB_NO_SPC_DELAY_US 1000
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
)
505 struct hip4_priv
*hip_priv
= hip
->hip_priv
;
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
;
511 SLSI_ERR_NODEV("Incorrect version\n");
515 /* Memory barrier when updating shared mailbox/memory */
517 SCSC_HIP4_SAMPLER_Q(hip_priv
->minor
, q
, r_w
, value
, 0);
519 write_unlock_bh(&hip_priv
->rw_scoreboard
);
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
)
526 struct hip4_priv
*hip_priv
= hip
->hip_priv
;
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
]));
533 SLSI_ERR_NODEV("Incorrect version\n");
537 /* Memory barrier when reading shared mailbox/memory */
540 read_unlock_bh(&hip_priv
->rw_scoreboard
);
544 static void hip4_dump_dbg(struct slsi_hip4
*hip
, struct mbulk
*m
, struct sk_buff
*skb
, struct scsc_service
*service
)
548 #ifdef CONFIG_SCSC_WLAN_RX_NAPI
549 u32 conf_hip4_ver
= 0;
551 conf_hip4_ver
= scsc_wifi_get_hip_config_version(&hip
->hip_control
->init
);
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
]);
558 SLSI_ERR_NODEV("intr_tohost 0x%x\n", hip
->hip_priv
->intr_tohost
);
561 SLSI_ERR_NODEV("intr_tohost 0x%x\n", hip
->hip_priv
->intr_tohost
);
563 SLSI_ERR_NODEV("intr_fromhost 0x%x\n", hip
->hip_priv
->intr_fromhost
);
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
));
572 scsc_mx_service_mif_dump_registers(service
);
575 if (scsc_mx_service_mif_ptr_to_addr(service
, m
, &ref
))
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);
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);
584 print_hex_dump(KERN_ERR
, SCSC_PREFIX
"skb ", DUMP_PREFIX_NONE
, 16, 1, skb
->data
, skb
->len
> 0xff ? 0xff : skb
->len
, 0);
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
));
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
));
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
));
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 */
613 hip4_history_record_print(false, NULL
);
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
)
620 struct mbulk
*m
= NULL
;
621 void *sig
= NULL
, *b_data
= NULL
;
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
633 payload
= skb
->len
- cb
->sig_length
;
635 /* Get headroom/tailroom */
636 headroom
= hip
->unidat_req_headroom
;
637 tailroom
= hip
->unidat_req_tailroom
;
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
);
646 if (!mbulk_reserve_head(m
, headroom
))
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);
655 /* Get signal handler */
656 sig
= mbulk_get_signal(m
);
658 mbulk_free_virt_host(m
);
663 /* 4Bytes offset is required for FW fapi header */
664 memcpy(sig
+ 4, skb
->data
, cb
->sig_length
);
667 /* If the signal has payload memcpy the data */
669 /* Get head pointer */
670 b_data
= mbulk_dat_rw(m
);
672 mbulk_free_virt_host(m
);
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() .
680 linear_data
= skb_headlen(skb
) - cb
->sig_length
;
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
;
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
;
694 unsigned int frag_size
;
696 frag
= &skb_shinfo(skb
)->frags
[i
];
700 frag_va_data
= skb_frag_address_safe(frag
);
701 WARN_ON(!frag_va_data
);
704 frag_size
= skb_frag_size(frag
);
705 /* Copy the fragmented data */
706 memcpy(b_data
+ offset
, frag_va_data
, frag_size
);
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);
718 if (iph
->protocol
== IPPROTO_TCP
) {
719 struct tcphdr
*th
= (struct tcphdr
*)((char *)b_data
+ sizeof(*mach
) +
722 th
->check
= csum_tcpudp_magic(iph
->saddr
, iph
->daddr
, len
,
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
) +
730 uh
->check
= csum_tcpudp_magic(iph
->saddr
, iph
->daddr
, len
,
732 csum_partial((char *)uh
, len
, 0));
733 SLSI_DBG3_NODEV(SLSI_HIP
, "uh->check 0x%x\n", ntohs(uh
->check
));
738 /* Copy payload skipping the signal data */
739 memcpy(b_data
, skb
->data
+ cb
->sig_length
, payload
);
741 mbulk_append_tail(m
, payload
);
743 m
->flag
|= MBULK_F_OBOUND
;
745 #ifdef CONFIG_SCSC_SMAPPER
746 /* Clear smapper field */
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
)
755 struct slsi_skb_cb
*cb
;
756 struct mbulk
*next_mbulk
[MBULK_MAX_CHAIN
];
757 struct sk_buff
*skb
= NULL
;
759 scsc_mifram_ref m_chain_next
;
763 size_t bytes_to_alloc
= 0;
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");
771 /* Track mbulk that should be freed */
772 to_free
[free
++] = ref
;
774 bytes_to_alloc
+= m
->sig_bufsz
- 4;
775 bytes_to_alloc
+= m
->len
;
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
);
781 SLSI_ERR_NODEV("Mbulk is set MBULK_F_CHAIN_HEAD and MBULK_F_CHAIN but m_chain_next is NULL\n");
785 /* increase number mbulks in chain */
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");
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]);
802 if (i
>= MBULK_MAX_CHAIN
) {
803 SLSI_ERR_NODEV("Max number of chained MBULK reached\n");
814 skb
= slsi_alloc_skb(bytes_to_alloc
, GFP_ATOMIC
);
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
);
821 SLSI_ERR_NODEV("Error allocating skb %d bytes\n", bytes_to_alloc
);
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
;
830 p
= mbulk_get_signal(m
);
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);
837 /* Remove 4Bytes offset coming from FW */
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
);
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
);
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
)
855 struct hip4_hip_control
*ctrl
= hip
->hip_control
;
856 struct hip4_priv
*hip_priv
= hip
->hip_priv
;
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);
868 if (idx_r
== ((idx_w
+ 1) & (MAX_NUM
- 1)))
872 ctrl
->q
[conf
].array
[idx_w
] = phy_m
;
873 /* Memory barrier before updating shared mailbox */
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;
882 idx_w
&= (MAX_NUM
- 1);
884 /* Update the scoreboard */
885 hip4_update_index(hip
, conf
, widx
, idx_w
);
888 scsc_service_mifintrbit_bit_set(service
, hip_priv
->intr_fromhost
, SCSC_MIFINTR_TARGET_R4
);
893 #if KERNEL_VERSION(4, 15, 0) <= LINUX_VERSION_CODE
894 static void hip4_watchdog(struct timer_list
*t
)
896 static void hip4_watchdog(unsigned long data
)
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
;
903 struct slsi_hip4
*hip
= (struct slsi_hip4
*)data
;
905 struct slsi_dev
*sdev
= container_of(hip
, struct slsi_dev
, hip4_inst
);
906 struct scsc_service
*service
;
909 #ifdef CONFIG_SCSC_WLAN_RX_NAPI
910 bool retrigger_watchdog
= true;
911 u32 conf_hip4_ver
= 0;
914 if (!hip
|| !sdev
|| !sdev
->service
|| !hip
->hip_priv
)
917 spin_lock_irqsave(&hip
->hip_priv
->watchdog_lock
, flags
);
918 if (!atomic_read(&hip
->hip_priv
->watchdog_timer_active
))
923 #ifdef CONFIG_SCSC_WLAN_RX_NAPI
924 conf_hip4_ver
= scsc_wifi_get_hip_config_version(&hip
->hip_control
->init
);
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;
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;
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;
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);
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);
956 intr_ov
= ktime_add_ms(intr_received
, jiffies_to_msecs(HZ
));
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);
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);
973 intr_ov
= ktime_add_ms(intr_received
, jiffies_to_msecs(HZ
));
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);
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
);
989 service
= sdev
->service
;
991 SLSI_INFO_NODEV("Hip4 watchdog triggered\n");
993 #ifdef CONFIG_SCSC_WLAN_RX_NAPI
994 if (conf_hip4_ver
== 4) {
996 for (i
= 0; i
< MIF_HIP_CFG_Q_NUM
; i
++) {
997 if (hip
->hip_priv
->intr_tohost_mul
[i
] == MIF_NO_IRQ
)
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
]);
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
);
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
);
1020 spin_unlock_irqrestore(&hip
->hip_priv
->watchdog_lock
, flags
);
1023 #ifdef CONFIG_SCSC_WLAN_RX_NAPI
1024 static void hip4_wq_fb(struct work_struct
*data
)
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;
1034 scsc_mifram_ref ref
;
1037 if (!hip_priv
|| !hip_priv
->hip
) {
1038 SLSI_ERR_NODEV("hip_priv or hip_priv->hip is Null\n");
1042 hip
= hip_priv
->hip
;
1043 ctrl
= hip
->hip_control
;
1046 SLSI_ERR_NODEV("hip->hip_control is Null\n");
1049 sdev
= container_of(hip
, struct slsi_dev
, hip4_inst
);
1051 if (!sdev
|| !sdev
->service
) {
1052 SLSI_ERR_NODEV("sdev or sdev->service is Null\n");
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
);
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
);
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);
1071 while (idx_r
!= idx_w
) {
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
);
1080 mem
= scsc_mx_service_mif_addr_to_ptr(service
, ref
);
1081 m
= (struct mbulk
*)mem
;
1084 SLSI_ERR_NODEV("FB: Mbulk is NULL\n");
1085 goto consume_fb_mbulk
;
1087 /* colour is defined as: */
1088 /* u16 register bits:
1091 * [7:4] - peer_index
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 */
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)
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
);
1112 /* Ignore return value */
1113 slsi_hip_tx_done(sdev
, colour
);
1115 mbulk_free_virt_host(m
);
1117 /* Increase index */
1119 idx_r
&= (MAX_NUM
- 1);
1120 hip4_update_index(hip
, HIP4_MIF_Q_FH_RFB
, ridx
, idx_r
);
1124 atomic_inc(&hip
->hip_priv
->stats
.spurious_irqs
);
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
]);
1130 SCSC_HIP4_SAMPLER_INT_OUT_BH(hip
->hip_priv
->minor
, 2);
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
);
1138 bh_end_fb
= ktime_get();
1139 spin_unlock_bh(&hip_priv
->rx_lock
);
1142 static void hip4_irq_handler_fb(int irq
, void *data
)
1144 struct slsi_hip4
*hip
= (struct slsi_hip4
*)data
;
1145 struct slsi_dev
*sdev
= container_of(hip
, struct slsi_dev
, hip4_inst
);
1147 SCSC_HIP4_SAMPLER_INT(hip
->hip_priv
->minor
, 2);
1148 intr_received_fb
= ktime_get();
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
);
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
);
1161 set_bit(HIP4_MIF_Q_FH_RFB
, hip
->hip_priv
->irq_bitmap
);
1163 scsc_service_mifintrbit_bit_mask(sdev
->service
, irq
);
1165 schedule_work(&hip
->hip_priv
->intr_wq_fb
);
1167 queue_work(hip
->hip_priv
->hip4_workq
, &hip
->hip_priv
->intr_wq_fb
);
1169 /* Clear interrupt */
1170 scsc_service_mifintrbit_bit_clear(sdev
->service
, irq
);
1171 SCSC_HIP4_SAMPLER_INT_OUT(hip
->hip_priv
->minor
, 2);
1174 static void hip4_wq_ctrl(struct work_struct
*data
)
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
;
1182 bool no_change
= true;
1185 scsc_mifram_ref ref
;
1188 #if defined(CONFIG_SCSC_WLAN_DEBUG) || defined(CONFIG_SCSC_WLAN_HIP4_PROFILING)
1192 if (!hip_priv
|| !hip_priv
->hip
) {
1193 SLSI_ERR_NODEV("hip_priv or hip_priv->hip is Null\n");
1197 hip
= hip_priv
->hip
;
1198 ctrl
= hip
->hip_control
;
1201 SLSI_ERR_NODEV("hip->hip_control is Null\n");
1204 sdev
= container_of(hip
, struct slsi_dev
, hip4_inst
);
1206 if (!sdev
|| !sdev
->service
) {
1207 SLSI_ERR_NODEV("sdev or sdev->service is Null\n");
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
);
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
);
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);
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
1232 scsc_mifram_ref to_free
[MBULK_MAX_CHAIN
+ 1] = { 0 };
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
);
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);
1246 SLSI_ERR_NODEV("Ctrl: Error parsing or allocating skb\n");
1247 hip4_dump_dbg(hip
, m
, skb
, service
);
1248 goto consume_ctl_mbulk
;
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
);
1257 if (m
->flag
& MBULK_F_WAKEUP
)
1258 SLSI_INFO(sdev
, "WIFI wakeup by MLME frame 0x%x\n", fapi_get_sigid(skb
));
1261 #if defined(CONFIG_SCSC_WLAN_DEBUG) || defined(CONFIG_SCSC_WLAN_HIP4_PROFILING)
1262 id
= fapi_get_sigid(skb
);
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);
1269 #ifdef CONFIG_SCSC_WLAN_DEBUG
1270 hip4_history_record_add(TH
, id
);
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
);
1278 /* Increase index */
1280 idx_r
&= (MAX_NUM
- 1);
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
);
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
);
1298 hip4_update_index(hip
, HIP4_MIF_Q_TH_CTRL
, ridx
, idx_r
);
1302 atomic_inc(&hip
->hip_priv
->stats
.spurious_irqs
);
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
]);
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
);
1315 bh_end_ctrl
= ktime_get();
1316 spin_unlock_bh(&hip_priv
->rx_lock
);
1319 static void hip4_irq_handler_ctrl(int irq
, void *data
)
1321 struct slsi_hip4
*hip
= (struct slsi_hip4
*)data
;
1322 struct slsi_dev
*sdev
= container_of(hip
, struct slsi_dev
, hip4_inst
);
1324 SCSC_HIP4_SAMPLER_INT(hip
->hip_priv
->minor
, 1);
1325 intr_received_ctrl
= ktime_get();
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
);
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
);
1338 set_bit(HIP4_MIF_Q_TH_CTRL
, hip
->hip_priv
->irq_bitmap
);
1340 scsc_service_mifintrbit_bit_mask(sdev
->service
, irq
);
1343 schedule_work(&hip
->hip_priv
->intr_wq_ctrl
);
1345 queue_work(hip
->hip_priv
->hip4_workq
, &hip
->hip_priv
->intr_wq_ctrl
);
1347 /* Clear interrupt */
1348 scsc_service_mifintrbit_bit_clear(sdev
->service
, irq
);
1349 SCSC_HIP4_SAMPLER_INT_OUT(hip
->hip_priv
->minor
, 1);
1352 static int hip4_napi_poll(struct napi_struct
*napi
, int budget
)
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
;
1360 #ifdef CONFIG_SCSC_WLAN_DEBUG
1365 scsc_mifram_ref ref
;
1371 if (!hip_priv
|| !hip_priv
->hip
) {
1372 SLSI_ERR_NODEV("hip_priv or hip_priv->hip is Null\n");
1376 hip
= hip_priv
->hip
;
1377 ctrl
= hip
->hip_control
;
1380 SLSI_ERR_NODEV("hip->hip_control is Null\n");
1383 sdev
= container_of(hip
, struct slsi_dev
, hip4_inst
);
1385 if (!sdev
|| !sdev
->service
) {
1386 SLSI_ERR_NODEV("sdev or sdev->service is Null\n");
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);
1398 clear_bit(HIP4_MIF_Q_TH_DAT
, hip
->hip_priv
->irq_bitmap
);
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
);
1403 service
= sdev
->service
;
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
]);
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
);
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);
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
1435 /* list of mbulks to be freed */
1436 scsc_mifram_ref to_free
[MBULK_MAX_CHAIN
+ 1] = { 0 };
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
);
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);
1448 SLSI_ERR_NODEV("Dat: Error parsing or allocating skb\n");
1449 hip4_dump_dbg(hip
, m
, skb
, service
);
1450 goto consume_dat_mbulk
;
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
);
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
);
1463 #ifdef CONFIG_SCSC_WLAN_DEBUG
1464 id
= fapi_get_sigid(skb
);
1465 hip4_history_record_add(TH
, id
);
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
);
1473 /* Increase index */
1475 idx_r
&= (MAX_NUM
- 1);
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
);
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
);
1494 if (budget
== work_done
) {
1495 /* We have consumed all the bugdet */
1500 hip4_update_index(hip
, HIP4_MIF_Q_TH_DAT
, ridx
, idx_r
);
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
]);
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
);
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
);
1524 static void hip4_napi_schedule(void *data
)
1526 struct slsi_hip4
*hip
= (struct slsi_hip4
*)data
;
1528 napi_schedule(&hip
->hip_priv
->napi
);
1531 static void hip4_irq_data_tasklet(unsigned long data
)
1533 /* TODO: NAPI - formalize the CPU selection code */
1534 struct slsi_hip4
*hip
= (struct slsi_hip4
*)data
;
1537 if (cpu_online(napi_select_cpu
))
1538 err
= smp_call_function_single(napi_select_cpu
, hip4_napi_schedule
, hip
, 0);
1541 napi_schedule(&hip
->hip_priv
->napi
);
1544 static void hip4_irq_handler_dat(int irq
, void *data
)
1546 struct slsi_hip4
*hip
= (struct slsi_hip4
*)data
;
1547 struct slsi_dev
*sdev
= container_of(hip
, struct slsi_dev
, hip4_inst
);
1549 if (!hip
|| !sdev
|| !sdev
->service
|| !hip
->hip_priv
)
1552 SCSC_HIP4_SAMPLER_INT(hip
->hip_priv
->minor
, 0);
1553 intr_received_data
= ktime_get();
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
);
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
);
1565 set_bit(HIP4_MIF_Q_TH_DAT
, hip
->hip_priv
->irq_bitmap
);
1567 if (napi_select_cpu
)
1568 tasklet_schedule(&hip
->hip_priv
->intr_tasklet
);
1570 napi_schedule(&hip
->hip_priv
->napi
);
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
]);
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);
1580 #endif /* #ifdef CONFIG_SCSC_WLAN_RX_NAPI */
1582 static bool slsi_check_rx_flowcontrol(struct slsi_dev
*sdev
)
1584 struct netdev_vif
*ndev_vif
;
1587 ndev_vif
= netdev_priv(sdev
->netdev
[SLSI_NET_INDEX_WLAN
]);
1589 qlen
= skb_queue_len(&ndev_vif
->rx_data
.queue
);
1591 if (!mutex_trylock(&sdev
->netdev_remove_mutex
))
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
]);
1598 qlen
+= skb_queue_len(&ndev_vif
->rx_data
.queue
);
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
]);
1604 qlen
+= skb_queue_len(&ndev_vif
->rx_data
.queue
);
1607 mutex_unlock(&sdev
->netdev_remove_mutex
);
1610 if (qlen
> max_buffered_frames
) {
1611 SLSI_DBG1_NODEV(SLSI_HIP
, "max qlen reached: %d\n", qlen
);
1614 SLSI_DBG3_NODEV(SLSI_HIP
, "qlen %d\n", qlen
);
1619 /* Worqueue: Lower priority, run in process context. Can run simultaneously on
1622 static void hip4_wq(struct work_struct
*data
)
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
;
1632 struct slsi_dev
*sdev
= container_of(hip
, struct slsi_dev
, hip4_inst
);
1633 struct scsc_service
*service
;
1634 bool no_change
= true;
1637 bool rx_flowcontrol
= false;
1639 #if defined(CONFIG_SCSC_WLAN_HIP4_PROFILING) || defined(CONFIG_SCSC_WLAN_DEBUG)
1643 if (!sdev
|| !sdev
->service
) {
1648 service
= sdev
->service
;
1650 atomic_set(&hip
->hip_priv
->in_rx
, 1);
1651 if (slsi_check_rx_flowcontrol(sdev
))
1652 rx_flowcontrol
= true;
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);
1658 bh_init
= ktime_get();
1660 #ifdef CONFIG_SCSC_WLAN_DEBUG
1661 /* Compute jitter */
1665 jitter
= ktime_to_ns(ktime_sub(bh_init
, intr_received
));
1667 if (jitter
<= HISTO_1
)
1669 else if (jitter
> HISTO_1
&& jitter
<= HISTO_2
)
1671 else if (jitter
> HISTO_2
&& jitter
<= HISTO_3
)
1673 else if (jitter
> HISTO_3
&& jitter
<= HISTO_4
)
1675 else if (jitter
> HISTO_4
&& jitter
<= HISTO_5
)
1680 if (jitter
> max_jitter
)
1681 max_jitter
= jitter
;
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
);
1687 if (idx_r
!= idx_w
) {
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);
1693 SCSC_HIP4_SAMPLER_INT_BH(hip_priv
->minor
, 2);
1694 while (idx_r
!= idx_w
) {
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;
1703 mem
= scsc_mx_service_mif_addr_to_ptr(service
, ref
);
1704 m
= (struct mbulk
*)mem
;
1706 SLSI_ERR_NODEV("FB: Mbulk is NULL 0x%x\n", ref
);
1707 goto consume_fb_mbulk
;
1709 /* colour is defined as: */
1710 /* u16 register bits:
1713 * [7:4] - peer_index
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 */
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)
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
);
1734 /* Ignore return value */
1735 slsi_hip_tx_done(sdev
, colour
);
1737 mbulk_free_virt_host(m
);
1739 /* Increase index */
1741 idx_r
&= (MAX_NUM
- 1);
1742 hip4_update_index(hip
, HIP4_MIF_Q_FH_RFB
, ridx
, idx_r
);
1744 SCSC_HIP4_SAMPLER_INT_OUT_BH(hip_priv
->minor
, 2);
1746 atomic_set(&hip
->hip_priv
->in_rx
, 4);
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
);
1751 if (idx_r
!= idx_w
) {
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);
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
1764 scsc_mifram_ref to_free
[MBULK_MAX_CHAIN
+ 1] = { 0 };
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;
1773 mem
= scsc_mx_service_mif_addr_to_ptr(service
, ref
);
1774 m
= (struct mbulk
*)(mem
);
1776 SLSI_ERR_NODEV("Ctrl: Mbulk is NULL 0x%x\n", ref
);
1777 goto consume_ctl_mbulk
;
1779 /* Process Control Signal */
1780 skb
= hip4_mbulk_to_skb(service
, hip_priv
, m
, to_free
, false);
1782 SLSI_ERR_NODEV("Ctrl: Error parsing or allocating skb\n");
1783 hip4_dump_dbg(hip
, m
, skb
, service
);
1784 goto consume_ctl_mbulk
;
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
);
1793 if (m
->flag
& MBULK_F_WAKEUP
)
1794 SLSI_INFO(sdev
, "WIFI wakeup by MLME frame 0x%x\n", fapi_get_sigid(skb
));
1797 #if defined(CONFIG_SCSC_WLAN_HIP4_PROFILING) || defined(CONFIG_SCSC_WLAN_DEBUG)
1798 id
= fapi_get_sigid(skb
);
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);
1805 #ifdef CONFIG_SCSC_WLAN_DEBUG
1806 hip4_history_record_add(TH
, id
);
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
);
1814 /* Increase index */
1816 idx_r
&= (MAX_NUM
- 1);
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
);
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
);
1834 hip4_update_index(hip
, HIP4_MIF_Q_TH_CTRL
, ridx
, idx_r
);
1837 SCSC_HIP4_SAMPLER_INT_OUT_BH(hip_priv
->minor
, 1);
1842 atomic_set(&hip
->hip_priv
->in_rx
, 5);
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
);
1847 if (idx_r
!= idx_w
) {
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 */
1855 u8 num_packets
= (idx_w
- idx_r
) % 256;
1857 if (num_packets
<= HISTO_1_DATA
)
1859 else if (num_packets
> HISTO_1_DATA
&& num_packets
<= HISTO_2_DATA
)
1861 else if (num_packets
> HISTO_2_DATA
&& num_packets
<= HISTO_3_DATA
)
1863 else if (num_packets
> HISTO_3_DATA
&& num_packets
<= HISTO_4_DATA
)
1865 else if (num_packets
> HISTO_4_DATA
&& num_packets
<= HISTO_5_DATA
)
1869 if (num_packets
> max_data
)
1870 max_data
= num_packets
;
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
1881 /* list of mbulks to be freed */
1882 scsc_mifram_ref to_free
[MBULK_MAX_CHAIN
+ 1] = { 0 };
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;
1892 mem
= scsc_mx_service_mif_addr_to_ptr(service
, ref
);
1893 m
= (struct mbulk
*)(mem
);
1895 SLSI_ERR_NODEV("Dat: Mbulk is NULL 0x%x\n", ref
);
1896 goto consume_dat_mbulk
;
1899 skb
= hip4_mbulk_to_skb(service
, hip_priv
, m
, to_free
, false);
1901 SLSI_ERR_NODEV("Dat: Error parsing or allocating skb\n");
1902 hip4_dump_dbg(hip
, m
, skb
, service
);
1903 goto consume_dat_mbulk
;
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
);
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
);
1917 #ifdef CONFIG_SCSC_WLAN_DEBUG
1918 id
= fapi_get_sigid(skb
);
1919 hip4_history_record_add(TH
, id
);
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
);
1927 /* Increase index */
1929 idx_r
&= (MAX_NUM
- 1);
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
);
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
);
1948 hip4_update_index(hip
, HIP4_MIF_Q_TH_DAT
, ridx
, idx_r
);
1950 /* read again the write index */
1951 if ((idx_r
== idx_w
) && (packets_total
< HIP4_POLLING_MAX_PACKETS
)) {
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);
1961 SCSC_HIP4_SAMPLER_INT_OUT_BH(hip_priv
->minor
, 0);
1964 atomic_inc(&hip
->hip_priv
->stats
.spurious_irqs
);
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
);
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
);
1979 bh_end
= ktime_get();
1980 atomic_set(&hip
->hip_priv
->in_rx
, 0);
1981 spin_unlock_bh(&hip_priv
->rx_lock
);
1984 /* IRQ handler for hip4. The function runs in Interrupt context, so all the
1985 * asssumptions related to interrupt should be applied (sleep, fast,...)
1987 static void hip4_irq_handler(int irq
, void *data
)
1989 struct slsi_hip4
*hip
= (struct slsi_hip4
*)data
;
1990 struct slsi_dev
*sdev
= container_of(hip
, struct slsi_dev
, hip4_inst
);
1992 (void)irq
; /* unused */
1994 if (!hip
|| !sdev
|| !sdev
->service
|| !hip
->hip_priv
)
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();
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
);
2008 /* if wd timer is active system might be in trouble as it should be
2009 * cleared in the BH. Ignore updating the timer
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
);
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
));
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
2031 hip
->hip_priv
->storm_count
= 0;
2032 scsc_service_mifintrbit_bit_mask(sdev
->service
, hip
->hip_priv
->intr_tohost
);
2035 atomic_inc(&hip
->hip_priv
->stats
.irqs
);
2038 schedule_work(&hip
->hip_priv
->intr_wq
);
2040 queue_work(hip
->hip_priv
->hip4_workq
, &hip
->hip_priv
->intr_wq
);
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);
2049 #ifdef CONFIG_SCSC_QOS
2050 static void hip4_pm_qos_work(struct work_struct
*data
)
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
);
2057 if (!sdev
|| !sdev
->service
) {
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
);
2069 static void hip4_traffic_monitor_cb(void *client_ctx
, u32 state
, u32 tput_tx
, u32 tput_rx
)
2071 struct slsi_hip4
*hip
= (struct slsi_hip4
*)client_ctx
;
2072 struct slsi_dev
*sdev
= container_of(hip
, struct slsi_dev
, hip4_inst
);
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
;
2084 hip
->hip_priv
->pm_qos_state
= SCSC_QOS_DISABLED
;
2086 spin_unlock_bh(&hip
->hip_priv
->pm_qos_lock
);
2088 schedule_work(&hip
->hip_priv
->pm_qos_work
);
2092 #ifdef CONFIG_SCSC_LOGRING
2093 static void hip4_traffic_monitor_logring_cb(void *client_ctx
, u32 state
, u32 tput_tx
, u32 tput_rx
)
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
);
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);
2107 scsc_logring_enable(true);
2112 int hip4_init(struct slsi_hip4
*hip
)
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
;
2122 u32 mib_file_offset
;
2123 #ifdef CONFIG_SCSC_WLAN_RX_NAPI
2124 struct net_device
*dev
;
2127 if (!sdev
|| !sdev
->service
)
2130 hip
->hip_priv
= kzalloc(sizeof(*hip
->hip_priv
), GFP_ATOMIC
);
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
);
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
;
2160 SLSI_DBG1_NODEV(SLSI_HIP
, "hip4_sampler is not enabled\n");
2164 /* Used in the workqueue */
2165 hip
->hip_priv
->hip
= hip
;
2167 service
= sdev
->service
;
2169 hip
->hip_priv
->host_pool_id_dat
= MBULK_POOL_ID_DATA
;
2170 hip
->hip_priv
->host_pool_id_ctl
= MBULK_POOL_ID_CTRL
;
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
);
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
);
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
);
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);
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);
2208 /* Reset hip_control table */
2209 memset(hip_ptr
, 0, sizeof(struct hip4_hip_control
));
2211 /* Reset Sample q values sending 0xff */
2212 SCSC_HIP4_SAMPLER_RESET(hip
->hip_priv
->minor
);
2214 /***** VERSION 4 *******/
2215 /* TOHOST Handler allocator */
2216 #ifdef CONFIG_SCSC_WLAN_RX_NAPI
2218 hip
->hip_priv
->intr_tohost_mul
[HIP4_MIF_Q_FH_CTRL
] = MIF_NO_IRQ
;
2220 hip
->hip_priv
->intr_tohost_mul
[HIP4_MIF_Q_FH_DAT
] = MIF_NO_IRQ
;
2222 hip
->hip_priv
->intr_tohost_mul
[HIP4_MIF_Q_TH_RFB
] = MIF_NO_IRQ
;
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
]);
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
]);
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
]);
2237 /* one NAPI instance is ok for multiple netdev devices */
2238 dev
= slsi_get_netdev_rcu(sdev
, SLSI_NET_INDEX_WLAN
);
2240 SLSI_ERR(sdev
, "netdev No longer exists\n");
2244 netif_napi_add(dev
, &hip
->hip_priv
->napi
, hip4_napi_poll
, NAPI_POLL_WEIGHT
);
2247 /* TOHOST Handler allocator */
2248 hip
->hip_priv
->intr_tohost
=
2249 scsc_service_mifintrbit_register_tohost(service
, hip4_irq_handler
, hip
);
2251 /* Mask the interrupt to prevent intr been kicked during start */
2252 scsc_service_mifintrbit_bit_mask(service
, hip
->hip_priv
->intr_tohost
);
2254 /* FROMHOST Handler allocator */
2255 hip
->hip_priv
->intr_fromhost
=
2256 scsc_service_mifintrbit_alloc_fromhost(service
, SCSC_MIFINTR_TARGET_R4
);
2258 /* Get hip_control pointer on shared memory */
2259 hip_control
= (struct hip4_hip_control
*)(hip_ptr
+
2260 HIP4_WLAN_CONFIG_OFFSET
);
2262 /* Initialize scoreboard */
2263 if (scsc_mx_service_mif_ptr_to_addr(service
, &hip_control
->scoreboard
, &ref_scoreboard
))
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
;
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
);
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;
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
;
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
;
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
;
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;
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;
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
];
2321 hip_control
->config_v4
.mif_th_int_n
[i
] = hip
->hip_priv
->intr_tohost
;
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
))
2333 hip_control
->config_v4
.q_loc
[i
] = (u32
)ref
;
2335 /***** END VERSION 4 *******/
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 */
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
))
2359 hip_control
->config_v5
.q_loc
[i
] = (u32
)ref
;
2361 /***** END VERSION 5 *******/
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
))
2367 hip_control
->init
.version_a_ref
= ref
;
2369 if (scsc_mx_service_mif_ptr_to_addr(service
, &hip_control
->config_v5
, &ref
))
2371 hip_control
->init
.version_b_ref
= ref
;
2372 /* End hip_init configuration */
2374 hip
->hip_control
= hip_control
;
2375 hip
->hip_priv
->scbrd_base
= &hip_control
->scoreboard
;
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);
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");
2388 wake_lock_init(&hip
->hip_priv
->hip4_wake_lock
, WAKE_LOCK_SUSPEND
, "hip4_wake_lock");
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");
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
);
2401 INIT_WORK(&hip
->hip_priv
->intr_wq
, hip4_wq
);
2403 rwlock_init(&hip
->hip_priv
->rw_scoreboard
);
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);
2411 setup_timer(&hip
->hip_priv
->watchdog
, hip4_watchdog
, (unsigned long)hip
);
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;
2419 #ifdef CONFIG_SCSC_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;
2426 hip4_smapper_is_enabled
= true;
2430 #ifdef CONFIG_SCSC_QOS
2431 /* setup for PM QoS */
2432 spin_lock_init(&hip
->hip_priv
->pm_qos_lock
);
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");
2440 INIT_WORK(&hip
->hip_priv
->pm_qos_work
, hip4_pm_qos_work
);
2442 SLSI_WARN(sdev
, "failed to add PM QoS request\n");
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");
2455 * This function returns the number of free slots available to
2456 * transmit control packet.
2458 int hip4_free_ctrl_slots_count(struct slsi_hip4
*hip
)
2460 return mbulk_pool_get_free_count(MBULK_POOL_ID_CTRL
);
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.
2471 int scsc_wifi_transmit_frame(struct slsi_hip4
*hip
, bool ctrl_packet
, struct sk_buff
*skb
)
2473 struct scsc_service
*service
;
2474 scsc_mifram_ref offset
;
2476 struct slsi_dev
*sdev
= container_of(hip
, struct slsi_dev
, hip4_inst
);
2477 struct fapi_signal_header
*fapi_header
;
2479 #ifdef CONFIG_SCSC_WLAN_HIP4_PROFILING
2480 struct slsi_skb_cb
*cb
= slsi_skb_cb_get(skb
);
2482 #ifdef CONFIG_SCSC_WLAN_RX_NAPI
2483 u32 conf_hip4_ver
= 0;
2486 if (!hip
|| !sdev
|| !sdev
->service
|| !skb
|| !hip
->hip_priv
)
2489 spin_lock_bh(&hip
->hip_priv
->tx_lock
);
2490 atomic_set(&hip
->hip_priv
->in_tx
, 1);
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
);
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
);
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
);
2513 service
= sdev
->service
;
2515 fapi_header
= (struct fapi_signal_header
*)skb
->data
;
2517 m
= hip4_skb_to_mbulk(hip
->hip_priv
, skb
, ctrl_packet
);
2519 SCSC_HIP4_SAMPLER_MFULL(hip
->hip_priv
->minor
);
2521 SLSI_ERR_NODEV("mbulk is NULL\n");
2525 if (scsc_mx_service_mif_ptr_to_addr(service
, m
, &offset
) < 0) {
2526 mbulk_free_virt_host(m
);
2528 SLSI_ERR_NODEV("Incorrect reference memory\n");
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
);
2536 SLSI_ERR_NODEV("No space\n");
2540 #ifdef CONFIG_SCSC_WLAN_HIP4_PROFILING
2541 /* colour is defined as: */
2542 /* u8 register bits:
2545 * [7:3] - peer_index
2548 /* Record control signal */
2549 SCSC_HIP4_SAMPLER_SIGNAL_CTRLTX(hip
->hip_priv
->minor
, (fapi_header
->id
& 0xff00) >> 8, fapi_header
->id
& 0xff);
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);
2555 #ifdef CONFIG_SCSC_WLAN_DEBUG
2556 hip4_history_record_add(FH
, fapi_header
->id
);
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.
2567 SCSC_BIN_TAG_DEBUG(BIN_WIFI_CTRL_TX
, skb
->data
, skb_headlen(skb
));
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
);
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
);
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
);
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
);
2598 atomic_set(&hip
->hip_priv
->in_tx
, 0);
2599 spin_unlock_bh(&hip
->hip_priv
->tx_lock
);
2603 /* HIP4 has been initialize, setup with values
2606 int hip4_setup(struct slsi_hip4
*hip
)
2608 struct slsi_dev
*sdev
= container_of(hip
, struct slsi_dev
, hip4_inst
);
2609 struct scsc_service
*service
;
2610 u32 conf_hip4_ver
= 0;
2612 if (!sdev
|| !sdev
->service
)
2615 if (atomic_read(&sdev
->hip
.hip_state
) != SLSI_HIP_STATE_STARTED
)
2618 service
= sdev
->service
;
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
);
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;
2636 #ifdef CONFIG_SCSC_WLAN_RX_NAPI
2637 napi_enable(&hip
->hip_priv
->napi
);
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;
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);
2652 atomic_set(&hip
->hip_priv
->closing
, 0);
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
]);
2660 scsc_service_mifintrbit_bit_unmask(service
, hip
->hip_priv
->intr_tohost
);
2663 scsc_service_mifintrbit_bit_unmask(service
, hip
->hip_priv
->intr_tohost
);
2668 /* On suspend hip4 needs to ensure that TH interrupts *are* unmasked */
2669 void hip4_suspend(struct slsi_hip4
*hip
)
2671 struct slsi_dev
*sdev
;
2672 struct scsc_service
*service
;
2673 #ifdef CONFIG_SCSC_WLAN_RX_NAPI
2674 u32 conf_hip4_ver
= 0;
2677 if (!hip
|| !hip
->hip_priv
)
2680 sdev
= container_of(hip
, struct slsi_dev
, hip4_inst
);
2681 if (!sdev
|| !sdev
->service
)
2684 if (atomic_read(&sdev
->hip
.hip_state
) != SLSI_HIP_STATE_STARTED
)
2687 service
= sdev
->service
;
2689 slsi_log_client_msg(sdev
, UDI_DRV_SUSPEND_IND
, 0, NULL
);
2690 SCSC_HIP4_SAMPLER_SUSPEND(hip
->hip_priv
->minor
);
2692 atomic_set(&hip
->hip_priv
->in_suspend
, 1);
2694 #ifdef CONFIG_SCSC_WLAN_RX_NAPI
2695 conf_hip4_ver
= scsc_wifi_get_hip_config_version(&hip
->hip_control
->init
);
2697 if (conf_hip4_ver
== 4) {
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
]);
2703 scsc_service_mifintrbit_bit_unmask(service
, hip
->hip_priv
->intr_tohost
);
2706 scsc_service_mifintrbit_bit_unmask(service
, hip
->hip_priv
->intr_tohost
);
2710 void hip4_resume(struct slsi_hip4
*hip
)
2712 struct slsi_dev
*sdev
;
2713 struct scsc_service
*service
;
2714 #ifdef CONFIG_SCSC_WLAN_RX_NAPI
2715 u32 conf_hip4_ver
= 0;
2718 if (!hip
|| !hip
->hip_priv
)
2721 sdev
= container_of(hip
, struct slsi_dev
, hip4_inst
);
2722 if (!sdev
|| !sdev
->service
)
2725 if (atomic_read(&sdev
->hip
.hip_state
) != SLSI_HIP_STATE_STARTED
)
2728 service
= sdev
->service
;
2730 #ifdef CONFIG_SCSC_WLAN_RX_NAPI
2731 conf_hip4_ver
= scsc_wifi_get_hip_config_version(&hip
->hip_control
->init
);
2733 if (conf_hip4_ver
== 4) {
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
]);
2739 scsc_service_mifintrbit_bit_unmask(service
, hip
->hip_priv
->intr_tohost
);
2742 scsc_service_mifintrbit_bit_unmask(service
, hip
->hip_priv
->intr_tohost
);
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);
2750 void hip4_freeze(struct slsi_hip4
*hip
)
2752 struct slsi_dev
*sdev
;
2753 struct scsc_service
*service
;
2754 #ifdef CONFIG_SCSC_WLAN_RX_NAPI
2755 u32 conf_hip4_ver
= 0;
2758 if (!hip
|| !hip
->hip_priv
)
2761 sdev
= container_of(hip
, struct slsi_dev
, hip4_inst
);
2762 if (!sdev
|| !sdev
->service
)
2765 if (atomic_read(&sdev
->hip
.hip_state
) != SLSI_HIP_STATE_STARTED
)
2768 service
= sdev
->service
;
2770 closing
= ktime_get();
2771 atomic_set(&hip
->hip_priv
->closing
, 1);
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
);
2777 if (conf_hip4_ver
== 4) {
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
]);
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
);
2787 scsc_service_mifintrbit_bit_mask(service
, hip
->hip_priv
->intr_tohost
);
2788 cancel_work_sync(&hip
->hip_priv
->intr_wq
);
2791 scsc_service_mifintrbit_bit_mask(service
, hip
->hip_priv
->intr_tohost
);
2792 cancel_work_sync(&hip
->hip_priv
->intr_wq
);
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);
2798 /* Deactive the wd timer prior its expiration */
2799 del_timer_sync(&hip
->hip_priv
->watchdog
);
2802 void hip4_deinit(struct slsi_hip4
*hip
)
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
2809 if (!sdev
|| !sdev
->service
)
2812 service
= sdev
->service
;
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);
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
);
2825 #ifdef CONFIG_SCSC_SMAPPER
2827 if (hip4_smapper_is_enabled
) {
2828 hip4_smapper_is_enabled
= false;
2829 hip4_smapper_deinit(sdev
, hip
);
2833 closing
= ktime_get();
2834 atomic_set(&hip
->hip_priv
->closing
, 1);
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
]);
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
);
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
]);
2849 netif_napi_del(&hip
->hip_priv
->napi
);
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
);
2855 flush_workqueue(hip
->hip_priv
->hip4_workq
);
2856 destroy_workqueue(hip
->hip_priv
->hip4_workq
);
2858 scsc_service_mifintrbit_free_fromhost(service
, hip
->hip_priv
->intr_fromhost
, SCSC_MIFINTR_TARGET_R4
);
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
);
2866 wake_lock_destroy(&hip
->hip_priv
->hip4_wake_lock
);
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
));
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
);
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
);
2885 kfree(hip
->hip_priv
);
2887 hip
->hip_priv
= NULL
;