hc
2024-12-19 9370bb92b2d16684ee45cf24e879c93c509162da
kernel/drivers/cpuidle/driver.c
....@@ -155,8 +155,6 @@
155155 {
156156 int i;
157157
158
- drv->refcnt = 0;
159
-
160158 /*
161159 * Use all possible CPUs as the default, because if the kernel boots
162160 * with some CPUs offline and then we online one of them, the CPU
....@@ -165,16 +163,27 @@
165163 if (!drv->cpumask)
166164 drv->cpumask = (struct cpumask *)cpu_possible_mask;
167165
168
- /*
169
- * Look for the timer stop flag in the different states, so that we know
170
- * if the broadcast timer has to be set up. The loop is in the reverse
171
- * order, because usually one of the deeper states have this flag set.
172
- */
173
- for (i = drv->state_count - 1; i >= 0 ; i--) {
174
- if (drv->states[i].flags & CPUIDLE_FLAG_TIMER_STOP) {
166
+ for (i = 0; i < drv->state_count; i++) {
167
+ struct cpuidle_state *s = &drv->states[i];
168
+
169
+ /*
170
+ * Look for the timer stop flag in the different states and if
171
+ * it is found, indicate that the broadcast timer has to be set
172
+ * up.
173
+ */
174
+ if (s->flags & CPUIDLE_FLAG_TIMER_STOP)
175175 drv->bctimer = 1;
176
- break;
177
- }
176
+
177
+ /*
178
+ * The core will use the target residency and exit latency
179
+ * values in nanoseconds, but allow drivers to provide them in
180
+ * microseconds too.
181
+ */
182
+ if (s->target_residency > 0)
183
+ s->target_residency_ns = s->target_residency * NSEC_PER_USEC;
184
+
185
+ if (s->exit_latency > 0)
186
+ s->exit_latency_ns = s->exit_latency * NSEC_PER_USEC;
178187 }
179188 }
180189
....@@ -229,9 +238,6 @@
229238 */
230239 static void __cpuidle_unregister_driver(struct cpuidle_driver *drv)
231240 {
232
- if (WARN_ON(drv->refcnt > 0))
233
- return;
234
-
235241 if (drv->bctimer) {
236242 drv->bctimer = 0;
237243 on_each_cpu_mask(drv->cpumask, cpuidle_setup_broadcast_timer,
....@@ -253,11 +259,24 @@
253259 */
254260 int cpuidle_register_driver(struct cpuidle_driver *drv)
255261 {
262
+ struct cpuidle_governor *gov;
256263 int ret;
257264
258265 spin_lock(&cpuidle_driver_lock);
259266 ret = __cpuidle_register_driver(drv);
260267 spin_unlock(&cpuidle_driver_lock);
268
+
269
+ if (!ret && !strlen(param_governor) && drv->governor &&
270
+ (cpuidle_get_driver() == drv)) {
271
+ mutex_lock(&cpuidle_lock);
272
+ gov = cpuidle_find_governor(drv->governor);
273
+ if (gov) {
274
+ cpuidle_prev_governor = cpuidle_curr_governor;
275
+ if (cpuidle_switch_governor(gov) < 0)
276
+ cpuidle_prev_governor = NULL;
277
+ }
278
+ mutex_unlock(&cpuidle_lock);
279
+ }
261280
262281 return ret;
263282 }
....@@ -273,9 +292,21 @@
273292 */
274293 void cpuidle_unregister_driver(struct cpuidle_driver *drv)
275294 {
295
+ bool enabled = (cpuidle_get_driver() == drv);
296
+
276297 spin_lock(&cpuidle_driver_lock);
277298 __cpuidle_unregister_driver(drv);
278299 spin_unlock(&cpuidle_driver_lock);
300
+
301
+ if (!enabled)
302
+ return;
303
+
304
+ mutex_lock(&cpuidle_lock);
305
+ if (cpuidle_prev_governor) {
306
+ if (!cpuidle_switch_governor(cpuidle_prev_governor))
307
+ cpuidle_prev_governor = NULL;
308
+ }
309
+ mutex_unlock(&cpuidle_lock);
279310 }
280311 EXPORT_SYMBOL_GPL(cpuidle_unregister_driver);
281312
....@@ -314,42 +345,40 @@
314345 EXPORT_SYMBOL_GPL(cpuidle_get_cpu_driver);
315346
316347 /**
317
- * cpuidle_driver_ref - get a reference to the driver.
318
- *
319
- * Increment the reference counter of the cpuidle driver associated with
320
- * the current CPU.
321
- *
322
- * Returns a pointer to the driver, or NULL if the current CPU has no driver.
348
+ * cpuidle_driver_state_disabled - Disable or enable an idle state
349
+ * @drv: cpuidle driver owning the state
350
+ * @idx: State index
351
+ * @disable: Whether or not to disable the state
323352 */
324
-struct cpuidle_driver *cpuidle_driver_ref(void)
353
+void cpuidle_driver_state_disabled(struct cpuidle_driver *drv, int idx,
354
+ bool disable)
325355 {
326
- struct cpuidle_driver *drv;
356
+ unsigned int cpu;
357
+
358
+ mutex_lock(&cpuidle_lock);
327359
328360 spin_lock(&cpuidle_driver_lock);
329361
330
- drv = cpuidle_get_driver();
331
- if (drv)
332
- drv->refcnt++;
362
+ if (!drv->cpumask) {
363
+ drv->states[idx].flags |= CPUIDLE_FLAG_UNUSABLE;
364
+ goto unlock;
365
+ }
333366
367
+ for_each_cpu(cpu, drv->cpumask) {
368
+ struct cpuidle_device *dev = per_cpu(cpuidle_devices, cpu);
369
+
370
+ if (!dev)
371
+ continue;
372
+
373
+ if (disable)
374
+ dev->states_usage[idx].disable |= CPUIDLE_STATE_DISABLED_BY_DRIVER;
375
+ else
376
+ dev->states_usage[idx].disable &= ~CPUIDLE_STATE_DISABLED_BY_DRIVER;
377
+ }
378
+
379
+unlock:
334380 spin_unlock(&cpuidle_driver_lock);
335
- return drv;
381
+
382
+ mutex_unlock(&cpuidle_lock);
336383 }
337
-
338
-/**
339
- * cpuidle_driver_unref - puts down the refcount for the driver
340
- *
341
- * Decrement the reference counter of the cpuidle driver associated with
342
- * the current CPU.
343
- */
344
-void cpuidle_driver_unref(void)
345
-{
346
- struct cpuidle_driver *drv;
347
-
348
- spin_lock(&cpuidle_driver_lock);
349
-
350
- drv = cpuidle_get_driver();
351
- if (drv && !WARN_ON(drv->refcnt <= 0))
352
- drv->refcnt--;
353
-
354
- spin_unlock(&cpuidle_driver_lock);
355
-}
384
+EXPORT_SYMBOL_GPL(cpuidle_driver_state_disabled);