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