xref: /wlan-dirver/qca-wifi-host-cmn/hif/src/hif_runtime_pm.h (revision 901120c066e139c7f8a2c8e4820561fdd83c67ef)
1 /*
2  * Copyright (c) 2013-2021 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2022 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  * @request_resume_ts: Last request resume done timestamp
52  * @request_resume_ts: Client ID requesting resume
53  */
54 struct hif_rtpm_state_stats {
55 	uint32_t resume_count;
56 	uint32_t suspend_count;
57 	uint32_t suspend_err_count;
58 	uint64_t resume_ts;
59 	uint64_t suspend_ts;
60 	uint64_t suspend_err_ts;
61 	uint64_t last_busy_ts;
62 	uint32_t last_busy_id;
63 	void *last_busy_marker;
64 	uint64_t request_resume_ts;
65 	uint64_t request_resume_id;
66 	uint32_t prevent_suspend;
67 	uint32_t allow_suspend;
68 	uint32_t runtime_get_err;
69 };
70 
71 /**
72  * struct hif_rtpm_client - Runtime PM client structure
73  * @hif_rtpm_cbk: Callback during resume if get called at suspend and failed
74  * @prevent_multiple_get: Client restricted to not calling get and put calls
75  *                        simultaneously
76  * @active_count: current active status of client
77  * @get_count: count of get calls by this client
78  * @put_count: count of put calls by this client
79  * @get_ts: Last get called timestamp
80  * @put_ts: Last put called timestamp
81  * @request_resume_ts: client request resume timestamp
82  */
83 struct hif_rtpm_client {
84 	void (*hif_rtpm_cbk)(void);
85 	qdf_atomic_t active_count;
86 	qdf_atomic_t get_count;
87 	qdf_atomic_t put_count;
88 	uint32_t last_busy_cnt;
89 	uint64_t get_ts;
90 	uint64_t put_ts;
91 	uint64_t last_busy_ts;
92 };
93 
94 /**
95  * struct hif_rtpm_ctx - Runtime power management context
96  * @runtime_lock: Lock to sync state changes with get calls
97  * @runtime_suspend_lock: Suspend lock
98  * @client_count: Number of clients currently registered
99  * @clients: clients registered to use runtime PM module
100  * @pm_state: Current runtime pm state
101  * @pending_job: bitmap to set the client job to be called at resume
102  * @monitor_wake_intr: Monitor waking MSI for runtime PM
103  * @stats: Runtime PM stats
104  * @pm_entry: debug fs entry
105  */
106 struct hif_rtpm_ctx {
107 	bool enable_rpm;
108 	struct device *dev;
109 	qdf_spinlock_t runtime_lock;
110 	qdf_spinlock_t runtime_suspend_lock;
111 	unsigned int client_count;
112 	struct hif_rtpm_client *clients[HIF_RTPM_ID_MAX];
113 	qdf_spinlock_t prevent_list_lock;
114 	struct list_head prevent_list;
115 	uint32_t prevent_cnt;
116 	qdf_atomic_t pm_state;
117 	unsigned long pending_job;
118 	qdf_atomic_t monitor_wake_intr;
119 	struct hif_rtpm_state_stats stats;
120 	struct dentry *pm_dentry;
121 };
122 
123 /**
124  * __hif_rtpm_enabled() - Check if runtime pm is enabled from kernel
125  * @dev: device structure
126  *
127  * Return: true if enabled.
128  */
129 static inline bool __hif_rtpm_enabled(struct device *dev)
130 {
131 	return pm_runtime_enabled(dev);
132 }
133 
134 /**
135  * __hif_rtpm_get() - Increment dev usage count and call resume function
136  * @dev: device structure
137  *
138  * Increments usage count and internally queue resume work
139  *
140  * Return: 1 if state is active. 0 if resume is requested. Error otherwise.
141  */
142 static inline int __hif_rtpm_get(struct device *dev)
143 {
144 	return pm_runtime_get(dev);
145 }
146 
147 /**
148  * __hif_rtpm_get_noresume() - Only increment dev usage count
149  * @dev: device structure
150  *
151  * Return: Void
152  */
153 static inline void __hif_rtpm_get_noresume(struct device *dev)
154 {
155 	pm_runtime_get_noresume(dev);
156 }
157 
158 /**
159  * __hif_rtpm_get_sync() - Increment usage count and set state to active
160  * @dev: device structure
161  *
162  * Return: 1 if state is already active, 0 if state active was done.
163  *         Error otherwise.
164  */
165 static inline int __hif_rtpm_get_sync(struct device *dev)
166 {
167 	return pm_runtime_get_sync(dev);
168 }
169 
170 /**
171  * __hif_rtpm_put_auto() - Decrement usage count and call suspend function
172  * @dev: device structure
173  *
174  * Decrements usage count and queue suspend work if usage count is 0
175  *
176  * Return: 0 if success. Error otherwise.
177  */
178 static inline int __hif_rtpm_put_auto(struct device *dev)
179 {
180 	return pm_runtime_put_autosuspend(dev);
181 }
182 
183 /**
184  * __hif_rtpm_put_noidle() - Decrement usage count
185  * @dev: device structure
186  *
187  * Return: void
188  */
189 static inline void __hif_rtpm_put_noidle(struct device *dev)
190 {
191 	pm_runtime_put_noidle(dev);
192 }
193 
194 /**
195  * __hif_rtpm_put_sync_suspend() - Decrement usage count
196  * @dev: device structure
197  *
198  * Decrement usage_count of device and if 0 synchrounsly call suspend function
199  *
200  * Return: 0 if success. Error otherwise
201  */
202 static inline int __hif_rtpm_put_sync_suspend(struct device *dev)
203 {
204 	return pm_runtime_put_sync_suspend(dev);
205 }
206 
207 /**
208  * __hif_rtpm_mark_last_busy() - Mark last busy timestamp
209  * @dev: device structure
210  *
211  * Return: Void
212  */
213 static inline void __hif_rtpm_mark_last_busy(struct device *dev)
214 {
215 	pm_runtime_mark_last_busy(dev);
216 }
217 
218 /**
219  * __hif_rtpm_resume() - Do Runtime PM Resume of bus
220  * dev: device structure
221  *
222  * Return: 0 if success. Error otherwise
223  */
224 static inline int __hif_rtpm_resume(struct device *dev)
225 {
226 	return pm_runtime_resume(dev);
227 }
228 
229 /**
230  * __hif_rtpm_request_resume() - Queue resume work
231  * dev: device structure
232  *
233  * Return: 1 if already active. 0 if successfully queued. Error otherwise
234  */
235 static inline int __hif_rtpm_request_resume(struct device *dev)
236 {
237 	return pm_request_resume(dev);
238 }
239 
240 /**
241  * hif_rtpm_open() - initialize runtime pm
242  * @scn: hif ctx
243  *
244  * Return: None
245  */
246 void hif_rtpm_open(struct hif_softc *scn);
247 
248 /**
249  * hif_rtpm_close() - close runtime pm
250  * @scn: hif ctx
251  *
252  * ensure runtime_pm is stopped before closing the driver
253  *
254  * Return: None
255  */
256 void hif_rtpm_close(struct hif_softc *scn);
257 
258 /**
259  * hif_rtpm_start() - start the runtime pm
260  * @scn: hif context
261  *
262  * After this call, runtime pm will be active.
263  *
264  * Return: None
265  */
266 void hif_rtpm_start(struct hif_softc *scn);
267 
268 /**
269  * hif_rtpm_stop() - stop runtime pm
270  * @scn: hif context
271  *
272  * Turns off runtime pm and frees corresponding resources
273  * that were acquired by hif_rtpm_start().
274  *
275  * Return: None
276  */
277 void hif_rtpm_stop(struct hif_softc *scn);
278 #else
279 static inline void hif_rtpm_open(struct hif_softc *scn) {}
280 static inline void hif_rtpm_close(struct hif_softc *scn) {}
281 static inline void hif_rtpm_start(struct hif_softc *scn) {}
282 static inline void hif_rtpm_stop(struct hif_softc *scn) {}
283 #endif /* FEATURE_RUNTIME_PM */
284 #endif /* __HIF_RUNTIME_PM_H__ */
285