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