1 /*
2  * Copyright (c) 2016-2021 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
4  *
5  * Permission to use, copy, modify, and/or distribute this software for
6  * any purpose with or without fee is hereby granted, provided that the
7  * above copyright notice and this permission notice appear in all
8  * copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17  * PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 #if !defined WLAN_HDD_TSF_H
21 #define WLAN_HDD_TSF_H
22 #include "wlan_hdd_cfg.h"
23 #include "wlan_hdd_main.h"
24 #ifdef WLAN_FEATURE_TSF_ACCURACY
25 #include "qdf_hrtimer.h"
26 #endif
27 /**
28  * enum hdd_tsf_get_state - status of get tsf action
29  * @TSF_RETURN:                   get tsf
30  * @TSF_STA_NOT_CONNECTED_NO_TSF: sta not connected to ap
31  * @TSF_NOT_RETURNED_BY_FW:       fw not returned tsf
32  * @TSF_CURRENT_IN_CAP_STATE:     driver in capture state
33  * @TSF_CAPTURE_FAIL:             capture fail
34  * @TSF_GET_FAIL:                 get fail
35  * @TSF_RESET_GPIO_FAIL:          GPIO reset fail
36  * @TSF_SAP_NOT_STARTED_NO_TSF:   SAP not started
37  * @TSF_NOT_READY: TSF module is not initialized or init failed
38  * @TSF_DISABLED_BY_TSFPLUS: cap_tsf/get_tsf are disabled due to TSF_PLUS
39  */
40 enum hdd_tsf_get_state {
41 	TSF_RETURN = 0,
42 	TSF_STA_NOT_CONNECTED_NO_TSF,
43 	TSF_NOT_RETURNED_BY_FW,
44 	TSF_CURRENT_IN_CAP_STATE,
45 	TSF_CAPTURE_FAIL,
46 	TSF_GET_FAIL,
47 	TSF_RESET_GPIO_FAIL,
48 	TSF_SAP_NOT_STARTED_NO_TSF,
49 	TSF_NOT_READY,
50 	TSF_DISABLED_BY_TSFPLUS
51 };
52 
53 /**
54  * enum hdd_tsf_capture_state - status of capture
55  * @TSF_IDLE:      idle
56  * @TSF_CAP_STATE: current is in capture state
57  */
58 enum hdd_tsf_capture_state {
59 	TSF_IDLE = 0,
60 	TSF_CAP_STATE
61 };
62 
63 /**
64  * struct hdd_tsf_op_response - Store TSF sync parameters if TSF sync is active
65  * @status: TSF response status defined by enum hdd_tsf_get_state
66  * @time: TSF sync Target time. Time unit is microseconds.
67  * @soc_time: TSF sync SOC time. Time unit is microseconds.
68  */
69 struct hdd_tsf_op_response {
70 	enum hdd_tsf_get_state status;
71 	uint64_t time;
72 	uint64_t soc_time;
73 };
74 
75 /**
76  * enum hdd_tsf_auto_rpt_source - trigger source of tsf auto report
77  * @HDD_TSF_AUTO_RPT_SOURCE_UPLINK_DELAY: uplink delay feature
78  * @HDD_TSF_AUTO_RPT_SOURCE_TX_LATENCY: transmit latency statistics
79  */
80 enum hdd_tsf_auto_rpt_source {
81 	HDD_TSF_AUTO_RPT_SOURCE_UPLINK_DELAY,
82 	HDD_TSF_AUTO_RPT_SOURCE_TX_LATENCY,
83 };
84 
85 #ifdef WLAN_FEATURE_TSF_AUTO_REPORT
86 /**
87  * hdd_set_tsf_auto_report() - enable or disable tsf auto report
88  * for an adapter
89  * @adapter: pointer to Adapter context
90  * @ena: requesting state (true or false)
91  * @source: source of the request
92  *
93  * Return: 0 for success or non-zero negative failure code
94  */
95 int
96 hdd_set_tsf_auto_report(struct hdd_adapter *adapter, bool ena,
97 			enum hdd_tsf_auto_rpt_source source);
98 
99 /**
100  * hdd_tsf_auto_report_init() - initialize tsf auto report related
101  * structures for an adapter
102  * @adapter: pointer to Adapter context
103  *
104  * Return: None
105  */
106 void hdd_tsf_auto_report_init(struct hdd_adapter *adapter);
107 #else
108 static inline int
hdd_set_tsf_auto_report(struct hdd_adapter * adapter,bool ena,enum hdd_tsf_auto_rpt_source source)109 hdd_set_tsf_auto_report(struct hdd_adapter *adapter, bool ena,
110 			enum hdd_tsf_auto_rpt_source source)
111 {
112 	return -ENOTSUPP;
113 }
114 
hdd_tsf_auto_report_init(struct hdd_adapter * adapter)115 static inline void hdd_tsf_auto_report_init(struct hdd_adapter *adapter)
116 {
117 }
118 #endif
119 
120 /**
121  * struct hdd_vdev_tsf - Adapter level tsf params
122  * @cur_target_time: tsf value received from firmware.
123  * @cur_tsf_sync_soc_time: Current SOC time.
124  * @last_tsf_sync_soc_time: Last SOC time when TSF was synced.
125  * @cur_target_global_tsf_time: Global Fw TSF time.
126  * @last_target_global_tsf_time: Last reported global Fw TSF time.
127  * @host_capture_req_timer: Host timer to capture TSF time.
128  * @tsf_id: TSF id as obtained from FW report.
129  * @tsf_mac_id: mac_id as obtained from FW report.
130  * @tsf_details_valid: flag indicating whether tsf details are valid.
131  * @host_target_sync_lock: spin lock for read/write timestamps.
132  * @host_target_sync_timer: Timer to Sync host target.
133  * @host_trigger_gpio_timer: A hrtimer used for TSF Accuracy Feature to
134  *                           indicate TSF cycle complete.
135  * @enable_dynamic_tsf_sync: Enable/Disable TSF sync through NL interface.
136  * @host_target_sync_force: Force update host to TSF mapping.
137  * @dynamic_tsf_sync_interval: TSF sync interval configure through NL interface.
138  * @cur_host_time: Current Host time.
139  * @last_host_time: Host time when TSF read was done.
140  * @last_target_time: Last Fw reported time when TSF read was done.
141  * @continuous_error_count: Store the count of continuous invalid tstamp-pair.
142  * @continuous_cap_retry_count: to store the count of continuous capture retry.
143  * @tsf_sync_ready_flag: to indicate whether tsf_sync has been initialized.
144  * @gpio_tsf_sync_work: work to sync send TSF CAP WMI command.
145  * @auto_rpt_src: bitmap to record trigger sources of TSF auto report
146  */
147 struct hdd_vdev_tsf {
148 	uint64_t cur_target_time;
149 	uint64_t cur_tsf_sync_soc_time;
150 	uint64_t last_tsf_sync_soc_time;
151 	uint64_t cur_target_global_tsf_time;
152 	uint64_t last_target_global_tsf_time;
153 	qdf_mc_timer_t host_capture_req_timer;
154 #ifdef QCA_GET_TSF_VIA_REG
155 	int tsf_id;
156 	int tsf_mac_id;
157 	qdf_atomic_t tsf_details_valid;
158 #endif
159 #ifdef WLAN_FEATURE_TSF_PLUS
160 	qdf_spinlock_t host_target_sync_lock;
161 	qdf_mc_timer_t host_target_sync_timer;
162 #ifdef WLAN_FEATURE_TSF_ACCURACY
163 	qdf_hrtimer_data_t host_trigger_gpio_timer;
164 #endif
165 	bool enable_dynamic_tsf_sync;
166 	bool host_target_sync_force;
167 	uint32_t dynamic_tsf_sync_interval;
168 	uint64_t cur_host_time;
169 	uint64_t last_host_time;
170 	uint64_t last_target_time;
171 	int continuous_error_count;
172 	int continuous_cap_retry_count;
173 	qdf_atomic_t tsf_sync_ready_flag;
174 #ifdef WLAN_FEATURE_TSF_PLUS_EXT_GPIO_SYNC
175 	qdf_work_t gpio_tsf_sync_work;
176 #endif
177 #endif /* WLAN_FEATURE_TSF_PLUS */
178 #ifdef WLAN_FEATURE_TSF_AUTO_REPORT
179 	unsigned long auto_rpt_src;
180 
181 #endif /* WLAN_FEATURE_TSF_UPLINK_DELAY */
182 };
183 
184 /**
185  * struct hdd_ctx_tsf - Context level tsf params
186  * @tsf_ready_flag: indicate whether tsf has been initialized.
187  * @cap_tsf_flag: indicate whether it's now capturing tsf(updating tstamp-pair).
188  * @cap_tsf_context:  the context that is capturing tsf.
189  * @tsf_accuracy_context: the context that is capturing tsf accuracy.
190  * @ptp_cinfo: TSF PTP clock info.
191  * @ptp_clock: TSF PTP clock.
192  */
193 struct hdd_ctx_tsf {
194 	qdf_atomic_t tsf_ready_flag;
195 	qdf_atomic_t cap_tsf_flag;
196 	struct hdd_adapter *cap_tsf_context;
197 #ifdef WLAN_FEATURE_TSF_ACCURACY
198 	struct hdd_adapter *tsf_accuracy_context;
199 #endif
200 #ifdef WLAN_FEATURE_TSF_PTP
201 	struct ptp_clock_info ptp_cinfo;
202 	struct ptp_clock *ptp_clock;
203 #endif
204 };
205 
206 #ifdef WLAN_FEATURE_TSF_UPLINK_DELAY
207 /**
208  * hdd_get_uplink_delay_len() - get uplink delay length
209  * @adapter: pointer to the adapter
210  *
211  * Return: uplink delay length
212  */
213 uint32_t hdd_get_uplink_delay_len(struct hdd_adapter *adapter);
214 
215 /**
216  * hdd_add_uplink_delay() - add uplink delay
217  * @adapter: pointer to the adapter
218  * @skb: nbuf
219  *
220  * Return: status
221  */
222 QDF_STATUS hdd_add_uplink_delay(struct hdd_adapter *adapter,
223 				struct sk_buff *skb);
224 #else /* !WLAN_FEATURE_TSF_UPLINK_DELAY */
hdd_get_uplink_delay_len(struct hdd_adapter * adapter)225 static inline uint32_t hdd_get_uplink_delay_len(struct hdd_adapter *adapter)
226 {
227 	return 0;
228 }
229 
hdd_add_uplink_delay(struct hdd_adapter * adapter,struct sk_buff * skb)230 static inline QDF_STATUS hdd_add_uplink_delay(struct hdd_adapter *adapter,
231 					      struct sk_buff *skb)
232 {
233 	return QDF_STATUS_SUCCESS;
234 }
235 #endif /* WLAN_FEATURE_TSF_UPLINK_DELAY */
236 #ifdef WLAN_FEATURE_TSF
237 /**
238  * wlan_hdd_tsf_init() - set gpio and callbacks for
239  *     capturing tsf and init tsf_plus
240  * @hdd_ctx: pointer to the struct hdd_context
241  *
242  * This function set the callback to sme module, the callback will be
243  * called when a tsf event is reported by firmware; set gpio number
244  * to FW, FW will toggle this gpio when received a CAP_TSF command;
245  * do tsf_plus init
246  *
247  * Return: nothing
248  */
249 void wlan_hdd_tsf_init(struct hdd_context *hdd_ctx);
250 
251 /**
252  * wlan_hdd_tsf_deinit() - reset callbacks for capturing tsf, deinit tsf_plus
253  * @hdd_ctx: pointer to the struct hdd_context
254  *
255  * This function reset the callback to sme module, and deinit tsf_plus
256  *
257  * Return: nothing
258  */
259 void wlan_hdd_tsf_deinit(struct hdd_context *hdd_ctx);
260 
261 /**
262  * hdd_capture_tsf() - capture tsf
263  * @adapter: pointer to adapter
264  * @buf: pointer to uplayer buf
265  * @len : the length of buf
266  *
267  * This function returns tsf value to uplayer.
268  *
269  * Return: 0 for success or non-zero negative failure code
270  */
271 int hdd_capture_tsf(struct hdd_adapter *adapter, uint32_t *buf, int len);
272 
273 /**
274  * hdd_indicate_tsf() - return tsf to uplayer
275  *
276  * @adapter: pointer to adapter
277  * @tsf_op_resp: pointer to struct hdd_tsf_op_response
278  *
279  * This function returns tsf value to uplayer.
280  *
281  * Return: Describe the execute result of this routine
282  */
283 int hdd_indicate_tsf(struct hdd_adapter *adapter,
284 		     struct hdd_tsf_op_response *tsf_op_resp);
285 
286 /**
287  * wlan_hdd_cfg80211_handle_tsf_cmd(): Setup TSF operations
288  * @wiphy: Pointer to wireless phy
289  * @wdev: Pointer to wireless device
290  * @data: Pointer to data
291  * @data_len: Data length
292  *
293  * Handle TSF SET / GET operation from userspace
294  *
295  * Return: 0 on success, negative errno on failure
296  */
297 int wlan_hdd_cfg80211_handle_tsf_cmd(struct wiphy *wiphy,
298 					struct wireless_dev *wdev,
299 					const void *data,
300 					int data_len);
301 
302 int hdd_get_tsf_cb(void *pcb_cxt, struct stsf *ptsf);
303 
304 extern const struct nla_policy tsf_policy[QCA_WLAN_VENDOR_ATTR_TSF_MAX + 1];
305 
306 #define FEATURE_HANDLE_TSF_VENDOR_COMMANDS \
307 { \
308 	.info.vendor_id = QCA_NL80211_VENDOR_ID, \
309 	.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TSF, \
310 	.flags = WIPHY_VENDOR_CMD_NEED_WDEV | \
311 		WIPHY_VENDOR_CMD_NEED_NETDEV | \
312 		WIPHY_VENDOR_CMD_NEED_RUNNING, \
313 	.doit = wlan_hdd_cfg80211_handle_tsf_cmd, \
314 	vendor_command_policy(tsf_policy, QCA_WLAN_VENDOR_ATTR_TSF_MAX)\
315 },
316 #else
wlan_hdd_tsf_init(struct hdd_context * hdd_ctx)317 static inline void wlan_hdd_tsf_init(struct hdd_context *hdd_ctx)
318 {
319 }
320 
wlan_hdd_tsf_deinit(struct hdd_context * hdd_ctx)321 static inline void wlan_hdd_tsf_deinit(struct hdd_context *hdd_ctx)
322 {
323 }
324 
hdd_indicate_tsf(struct hdd_adapter * adapter,struct hdd_tsf_op_response * tsf_op_resp)325 static inline int hdd_indicate_tsf(struct hdd_adapter *adapter,
326 				   struct hdd_tsf_op_response *tsf_op_resp)
327 {
328 	return -ENOTSUPP;
329 }
330 
331 static inline int
hdd_capture_tsf(struct hdd_adapter * adapter,uint32_t * buf,int len)332 hdd_capture_tsf(struct hdd_adapter *adapter, uint32_t *buf, int len)
333 {
334 	return -ENOTSUPP;
335 }
336 
wlan_hdd_cfg80211_handle_tsf_cmd(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)337 static inline int wlan_hdd_cfg80211_handle_tsf_cmd(struct wiphy *wiphy,
338 					struct wireless_dev *wdev,
339 					const void *data,
340 					int data_len)
341 {
342 	return -ENOTSUPP;
343 }
hdd_get_tsf_cb(void * pcb_cxt,struct stsf * ptsf)344 static inline int hdd_get_tsf_cb(void *pcb_cxt, struct stsf *ptsf)
345 {
346 	return -ENOTSUPP;
347 }
348 
349 #define FEATURE_HANDLE_TSF_VENDOR_COMMANDS
350 #endif
351 
352 #if defined(WLAN_FEATURE_TSF_PLUS) && defined(WLAN_FEATURE_TSF)
353 /**
354  * hdd_tsf_is_tx_set() - check ini configuration
355  * @hdd: pointer to hdd context
356  *
357  * This function checks tsf configuration for ptp on tx
358  *
359  * Return: true on enable, false on disable
360  */
361 
362 bool hdd_tsf_is_tx_set(struct hdd_context *hdd);
363 /**
364  * hdd_tsf_is_rx_set() - check ini configuration
365  * @hdd: pointer to hdd context
366  *
367  * This function checks tsf configuration for ptp on rx
368  *
369  * Return: true on enable, false on disable
370  */
371 bool hdd_tsf_is_rx_set(struct hdd_context *hdd);
372 /**
373  * hdd_tsf_is_raw_set() - check ini configuration
374  * @hdd: pointer to hdd context
375  *
376  * This function checks tsf configuration for ptp on raw
377  *
378  * Return: true on enable, false on disable
379  */
380 bool hdd_tsf_is_raw_set(struct hdd_context *hdd);
381 /**
382  * hdd_tsf_is_dbg_fs_set() - check ini configuration
383  * @hdd: pointer to hdd context
384  *
385  * This function checks tsf configuration for ptp on dbg fs
386  *
387  * Return: true on enable, false on disable
388  */
389 bool hdd_tsf_is_dbg_fs_set(struct hdd_context *hdd);
390 
391 /**
392  * hdd_start_tsf_sync() - start tsf sync
393  * @adapter: pointer to adapter
394  *
395  * This function initialize and start TSF synchronization
396  *
397  * Return: Describe the execute result of this routine
398  */
399 int hdd_start_tsf_sync(struct hdd_adapter *adapter);
400 
401 /**
402  * hdd_restart_tsf_sync_post_wlan_resume() - restart host TSF sync
403  * @adapter: pointer to adapter
404  *
405  * This function restarts host TSF sync immediately after wlan resume
406  *
407  * Return: none
408  */
409 void hdd_restart_tsf_sync_post_wlan_resume(struct hdd_adapter *adapter);
410 
411 /**
412  * hdd_stop_tsf_sync() - stop tsf sync
413  * @adapter: pointer to adapter
414  *
415  * This function stop and de-initialize TSF synchronization
416  *
417  * Return: Describe the execute result of this routine
418  */
419 int hdd_stop_tsf_sync(struct hdd_adapter *adapter);
420 
421 /**
422  * hdd_capture_req_timer_expired_handler() - capture req timer handler
423  * @arg: pointer to a adapter
424  *
425  * This function set a timeout handler for TSF capture timer.
426  *
427  * Return: none
428  */
429 
430 void hdd_capture_req_timer_expired_handler(void *arg);
431 
432 /**
433  * hdd_tsf_is_tsf64_tx_set() - check ini configuration
434  * @hdd: pointer to hdd context
435  *
436  * This function checks tsf configuration for ptp on tsf64 tx
437  *
438  * Return: true on enable, false on disable
439  */
440 bool hdd_tsf_is_tsf64_tx_set(struct hdd_context *hdd);
441 
442 /**
443  * hdd_tsf_is_time_sync_enabled_cfg() - check ini configuration
444  * @hdd_ctx: pointer to hdd context
445  *
446  * This function checks tsf configuration for ptp for tsf
447  * sync period
448  * Return: true on enable, false on disable
449  */
450 bool hdd_tsf_is_time_sync_enabled_cfg(struct hdd_context *hdd_ctx);
451 
452 /**
453  * hdd_update_dynamic_tsf_sync - Configure TSF mode for vdev
454  * @adapter: pointer to hdd adapter
455  *
456  * This function configures TSF mode for vdev with ini parameter
457  */
458 void hdd_update_dynamic_tsf_sync(struct hdd_adapter *adapter);
459 
460 #ifdef WLAN_FEATURE_TSF_PLUS_SOCK_TS
461 /**
462  * hdd_rx_timestamp() - time stamp RX netbuf
463  *
464  * @netbuf: pointer to a RX netbuf
465  * @target_time: RX time for the netbuf
466  *
467  * This function get corresponding host time from target time,
468  * and time stamp the RX netbuf with this time
469  *
470  * Return: Describe the execute result of this routine
471  */
472 int hdd_rx_timestamp(qdf_nbuf_t netbuf, uint64_t target_time);
473 #endif
474 
475 /**
476  * hdd_get_tsf_time() - get tsf time for system time
477  *
478  * @adapter_ctx: adapter context
479  * @input_time: input system time
480  * @tsf_time: tsf time for system time
481  *
482  * Return: qdf status
483  */
484 QDF_STATUS hdd_get_tsf_time(void *adapter_ctx, uint64_t input_time,
485 			    uint64_t *tsf_time);
486 #else
hdd_start_tsf_sync(struct hdd_adapter * adapter)487 static inline int hdd_start_tsf_sync(struct hdd_adapter *adapter)
488 {
489 	return -ENOTSUPP;
490 }
491 
hdd_stop_tsf_sync(struct hdd_adapter * adapter)492 static inline int hdd_stop_tsf_sync(struct hdd_adapter *adapter)
493 {
494 	return -ENOTSUPP;
495 }
496 
497 static inline
hdd_capture_req_timer_expired_handler(void * arg)498 void hdd_capture_req_timer_expired_handler(void *arg)
499 {
500 }
501 
502 static inline
hdd_tsf_is_tsf64_tx_set(struct hdd_context * hdd)503 bool hdd_tsf_is_tsf64_tx_set(struct hdd_context *hdd)
504 {
505 	return FALSE;
506 }
507 
508 static inline
hdd_tsf_is_time_sync_enabled_cfg(struct hdd_context * hdd_ctx)509 bool hdd_tsf_is_time_sync_enabled_cfg(struct hdd_context *hdd_ctx)
510 {
511 	return false;
512 }
513 
514 static inline
hdd_update_dynamic_tsf_sync(struct hdd_adapter * adapter)515 void hdd_update_dynamic_tsf_sync(struct hdd_adapter *adapter)
516 {
517 }
518 
519 static inline
hdd_restart_tsf_sync_post_wlan_resume(struct hdd_adapter * adapter)520 void hdd_restart_tsf_sync_post_wlan_resume(struct hdd_adapter *adapter)
521 {
522 }
523 
524 static inline
hdd_get_tsf_time(void * adapter_ctx,uint64_t input_time,uint64_t * tsf_time)525 QDF_STATUS hdd_get_tsf_time(void *adapter_ctx, uint64_t input_time,
526 			    uint64_t *tsf_time)
527 {
528 	*tsf_time = 0;
529 	return QDF_STATUS_E_NOSUPPORT;
530 }
531 #endif
532 
533 #ifdef WLAN_FEATURE_TSF_PTP
534 /**
535  * wlan_get_ts_info() - return ts info to uplayer
536  * @dev: pointer to net_device
537  * @info: pointer to ethtool_ts_info
538  *
539  * Return: Describe the execute result of this routine
540  */
541 int wlan_get_ts_info(struct net_device *dev, struct ethtool_ts_info *info);
542 
543 #endif
544 #endif
545