xref: /wlan-driver/qca-wifi-host-cmn/hif/src/hif_runtime_pm.h (revision 5113495b16420b49004c444715d2daae2066e7dc)
1 /*
2  * Copyright (c) 2013-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 any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8 
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  */
17 
18 #ifndef __HIF_RUNTIME_PM_H__
19 #define __HIF_RUNTIME_PM_H__
20 
21 /**
22  * enum hif_rtpm_fill_type - Caller type for Runtime PM stats fill
23  * @HIF_RTPM_FILL_TYPE_SYSFS: Sysfs is caller for Runtime PM stats
24  * @HIF_RTPM_FILL_TYPE_DEBUGFS: Debugfs is caller for Runtime PM stats
25  * @HIF_RTPM_FILL_TYPE_MAX: max value
26  */
27 enum hif_rtpm_fill_type {
28 	HIF_RTPM_FILL_TYPE_SYSFS,
29 	HIF_RTPM_FILL_TYPE_DEBUGFS,
30 	HIF_RTPM_FILL_TYPE_MAX,
31 };
32 
33 #ifdef FEATURE_RUNTIME_PM
34 #include <linux/pm_runtime.h>
35 
36 /**
37  * enum hif_rtpm_state - Driver States for Runtime Power Management
38  * @HIF_RTPM_STATE_NONE: runtime pm is off
39  * @HIF_RTPM_STATE_ON: runtime pm is active and link is active
40  * @HIF_RTPM_STATE_RESUMING: a runtime resume is in progress
41  * @HIF_RTPM_STATE_RESUMING_LINKUP: Link is up during resume
42  * @HIF_RTPM_STATE_SUSPENDING: a runtime suspend is in progress
43  * @HIF_RTPM_STATE_SUSPENDED: the driver is runtime suspended
44  */
45 enum hif_rtpm_state {
46 	HIF_RTPM_STATE_NONE,
47 	HIF_RTPM_STATE_ON,
48 	HIF_RTPM_STATE_RESUMING_LINKUP,
49 	HIF_RTPM_STATE_RESUMING,
50 	HIF_RTPM_STATE_SUSPENDING,
51 	HIF_RTPM_STATE_SUSPENDED,
52 };
53 
54 /**
55  * struct hif_rtpm_state_stats - Runtime PM stats
56  * @resume_count: count of resume calls done
57  * @suspend_count: count of suspend calls done
58  * @suspend_err_count: count of suspend calls failed
59  * @resume_ts: Last resume call timestamp
60  * @suspend_ts: Last suspend call timestamp
61  * @suspend_err_ts: Last suspend call fail timestamp
62  * @last_busy_ts: Last busy timestamp marked
63  * @last_busy_id:
64  * @last_busy_marker:
65  * @request_resume_ts: Last request resume done timestamp
66  * @request_resume_id: Client ID requesting resume
67  * @prevent_suspend:
68  * @allow_suspend:
69  * @runtime_get_err:
70  */
71 struct hif_rtpm_state_stats {
72 	uint32_t resume_count;
73 	uint32_t suspend_count;
74 	uint32_t suspend_err_count;
75 	uint64_t resume_ts;
76 	uint64_t suspend_ts;
77 	uint64_t suspend_err_ts;
78 	uint64_t last_busy_ts;
79 	uint32_t last_busy_id;
80 	void *last_busy_marker;
81 	uint64_t request_resume_ts;
82 	uint64_t request_resume_id;
83 	uint32_t prevent_suspend;
84 	uint32_t allow_suspend;
85 	uint32_t runtime_get_err;
86 };
87 
88 #define HIF_RTPM_BUSY_HIST_MAX  16
89 #define HIF_RTPM_BUSY_HIST_MASK (HIF_RTPM_BUSY_HIST_MAX - 1)
90 
91 /**
92  * struct hif_rtpm_last_busy_hist - Runtime last busy hist
93  * @last_busy_cnt: count of last busy mark
94  * @last_busy_idx: last busy history index
95  * @last_busy_ts: last busy marked timestamp
96  */
97 struct hif_rtpm_last_busy_hist {
98 	unsigned long last_busy_cnt;
99 	unsigned long last_busy_idx;
100 	uint64_t last_busy_ts[HIF_RTPM_BUSY_HIST_MAX];
101 };
102 
103 /**
104  * struct hif_rtpm_client - Runtime PM client structure
105  * @hif_rtpm_cbk: Callback during resume if get called at suspend and failed
106  * @active_count: current active status of client
107  * @get_count: count of get calls by this client
108  * @put_count: count of put calls by this client
109  * @last_busy_cnt:
110  * @get_ts: Last get called timestamp
111  * @put_ts: Last put called timestamp
112  * @last_busy_ts:
113  */
114 struct hif_rtpm_client {
115 	void (*hif_rtpm_cbk)(void);
116 	qdf_atomic_t active_count;
117 	qdf_atomic_t get_count;
118 	qdf_atomic_t put_count;
119 	uint32_t last_busy_cnt;
120 	uint64_t get_ts;
121 	uint64_t put_ts;
122 	uint64_t last_busy_ts;
123 };
124 
125 /**
126  * struct hif_rtpm_ctx - Runtime power management context
127  * @enable_rpm:
128  * @dev:
129  * @runtime_lock: Lock to sync state changes with get calls
130  * @runtime_suspend_lock: Suspend lock
131  * @client_count: Number of clients currently registered
132  * @clients: clients registered to use runtime PM module
133  * @prevent_list_lock:
134  * @prevent_list:
135  * @prevent_cnt:
136  * @pm_state: Current runtime pm state
137  * @pending_job: bitmap to set the client job to be called at resume
138  * @monitor_wake_intr: Monitor waking MSI for runtime PM
139  * @stats: Runtime PM stats
140  * @pm_dentry: debug fs entry
141  * @cfg_delay:
142  * @delay:
143  * @busy_hist: busy histogram
144  */
145 struct hif_rtpm_ctx {
146 	bool enable_rpm;
147 	struct device *dev;
148 	qdf_spinlock_t runtime_lock;
149 	qdf_spinlock_t runtime_suspend_lock;
150 	unsigned int client_count;
151 	struct hif_rtpm_client *clients[HIF_RTPM_ID_MAX];
152 	qdf_spinlock_t prevent_list_lock;
153 	struct list_head prevent_list;
154 	uint32_t prevent_cnt;
155 	qdf_atomic_t pm_state;
156 	unsigned long pending_job;
157 	qdf_atomic_t monitor_wake_intr;
158 	struct hif_rtpm_state_stats stats;
159 	struct dentry *pm_dentry;
160 	int cfg_delay;
161 	int delay;
162 	struct hif_rtpm_last_busy_hist *busy_hist[CE_COUNT_MAX];
163 };
164 
165 #define HIF_RTPM_DELAY_MIN 100
166 #define HIF_RTPM_DELAY_MAX 10000
167 
168 /**
169  * __hif_rtpm_enabled() - Check if runtime pm is enabled from kernel
170  * @dev: device structure
171  *
172  * Return: true if enabled.
173  */
__hif_rtpm_enabled(struct device * dev)174 static inline bool __hif_rtpm_enabled(struct device *dev)
175 {
176 	return pm_runtime_enabled(dev);
177 }
178 
179 /**
180  * __hif_rtpm_get() - Increment dev usage count and call resume function
181  * @dev: device structure
182  *
183  * Increments usage count and internally queue resume work
184  *
185  * Return: 1 if state is active. 0 if resume is requested. Error otherwise.
186  */
__hif_rtpm_get(struct device * dev)187 static inline int __hif_rtpm_get(struct device *dev)
188 {
189 	return pm_runtime_get(dev);
190 }
191 
192 /**
193  * __hif_rtpm_get_noresume() - Only increment dev usage count
194  * @dev: device structure
195  *
196  * Return: Void
197  */
__hif_rtpm_get_noresume(struct device * dev)198 static inline void __hif_rtpm_get_noresume(struct device *dev)
199 {
200 	pm_runtime_get_noresume(dev);
201 }
202 
203 /**
204  * __hif_rtpm_get_sync() - Increment usage count and set state to active
205  * @dev: device structure
206  *
207  * Return: 1 if state is already active, 0 if state active was done.
208  *         Error otherwise.
209  */
__hif_rtpm_get_sync(struct device * dev)210 static inline int __hif_rtpm_get_sync(struct device *dev)
211 {
212 	return pm_runtime_get_sync(dev);
213 }
214 
215 /**
216  * __hif_rtpm_put_auto() - Decrement usage count and call suspend function
217  * @dev: device structure
218  *
219  * Decrements usage count and queue suspend work if usage count is 0
220  *
221  * Return: 0 if success. Error otherwise.
222  */
__hif_rtpm_put_auto(struct device * dev)223 static inline int __hif_rtpm_put_auto(struct device *dev)
224 {
225 	return pm_runtime_put_autosuspend(dev);
226 }
227 
228 /**
229  * __hif_rtpm_put_noidle() - Decrement usage count
230  * @dev: device structure
231  *
232  * Return: void
233  */
__hif_rtpm_put_noidle(struct device * dev)234 static inline void __hif_rtpm_put_noidle(struct device *dev)
235 {
236 	pm_runtime_put_noidle(dev);
237 }
238 
239 /**
240  * __hif_rtpm_put_sync_suspend() - Decrement usage count
241  * @dev: device structure
242  *
243  * Decrement usage_count of device and if 0 synchrounsly call suspend function
244  *
245  * Return: 0 if success. Error otherwise
246  */
__hif_rtpm_put_sync_suspend(struct device * dev)247 static inline int __hif_rtpm_put_sync_suspend(struct device *dev)
248 {
249 	return pm_runtime_put_sync_suspend(dev);
250 }
251 
252 /**
253  * __hif_rtpm_set_autosuspend_delay() - Set delay to trigger RTPM suspend
254  * @dev: device structure
255  * @delay: delay in ms to be set
256  *
257  * Return: None
258  */
259 static inline
__hif_rtpm_set_autosuspend_delay(struct device * dev,int delay)260 void __hif_rtpm_set_autosuspend_delay(struct device *dev, int delay)
261 {
262 	pm_runtime_set_autosuspend_delay(dev, delay);
263 }
264 
265 /**
266  * __hif_rtpm_mark_last_busy() - Mark last busy timestamp
267  * @dev: device structure
268  *
269  * Return: Void
270  */
__hif_rtpm_mark_last_busy(struct device * dev)271 static inline void __hif_rtpm_mark_last_busy(struct device *dev)
272 {
273 	pm_runtime_mark_last_busy(dev);
274 }
275 
276 /**
277  * __hif_rtpm_resume() - Do Runtime PM Resume of bus
278  * @dev: device structure
279  *
280  * Return: 0 if success. Error otherwise
281  */
__hif_rtpm_resume(struct device * dev)282 static inline int __hif_rtpm_resume(struct device *dev)
283 {
284 	return pm_runtime_resume(dev);
285 }
286 
287 /**
288  * __hif_rtpm_request_resume() - Queue resume work
289  * @dev: device structure
290  *
291  * Return: 1 if already active. 0 if successfully queued. Error otherwise
292  */
__hif_rtpm_request_resume(struct device * dev)293 static inline int __hif_rtpm_request_resume(struct device *dev)
294 {
295 	return pm_request_resume(dev);
296 }
297 
298 /**
299  * hif_rtpm_open() - initialize runtime pm
300  * @scn: hif ctx
301  *
302  * Return: None
303  */
304 void hif_rtpm_open(struct hif_softc *scn);
305 
306 /**
307  * hif_rtpm_close() - close runtime pm
308  * @scn: hif ctx
309  *
310  * ensure runtime_pm is stopped before closing the driver
311  *
312  * Return: None
313  */
314 void hif_rtpm_close(struct hif_softc *scn);
315 
316 /**
317  * hif_rtpm_start() - start the runtime pm
318  * @scn: hif context
319  *
320  * After this call, runtime pm will be active.
321  *
322  * Return: None
323  */
324 void hif_rtpm_start(struct hif_softc *scn);
325 
326 /**
327  * hif_rtpm_stop() - stop runtime pm
328  * @scn: hif context
329  *
330  * Turns off runtime pm and frees corresponding resources
331  * that were acquired by hif_rtpm_start().
332  *
333  * Return: None
334  */
335 void hif_rtpm_stop(struct hif_softc *scn);
336 
337 /**
338  * hif_rtpm_log_debug_stats() - fill buffer with runtime pm stats
339  * @s: pointer to buffer to fill status
340  * @type: type of caller
341  *
342  * Fills input buffer with runtime pm stats depending on caller type.
343  *
344  * Return: Num of bytes filled if caller type requires, else 0.
345  */
346 int hif_rtpm_log_debug_stats(void *s, enum hif_rtpm_fill_type type);
347 
348 #else
hif_rtpm_open(struct hif_softc * scn)349 static inline void hif_rtpm_open(struct hif_softc *scn) {}
hif_rtpm_close(struct hif_softc * scn)350 static inline void hif_rtpm_close(struct hif_softc *scn) {}
hif_rtpm_start(struct hif_softc * scn)351 static inline void hif_rtpm_start(struct hif_softc *scn) {}
hif_rtpm_stop(struct hif_softc * scn)352 static inline void hif_rtpm_stop(struct hif_softc *scn) {}
hif_rtpm_log_debug_stats(void * s,enum hif_rtpm_fill_type type)353 static inline int hif_rtpm_log_debug_stats(void *s,
354 					   enum hif_rtpm_fill_type type)
355 {
356 	return 0;
357 }
358 #endif /* FEATURE_RUNTIME_PM */
359 #endif /* __HIF_RUNTIME_PM_H__ */
360