Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

cpuidle: remove state_count field from struct cpuidle_device

Thomas Schlichter reports the following issue on his Samsung NC20:

"The C-states C1 and C2 to the OS when connected to AC, and additionally
provides the C3 C-state when disconnected from AC. However, the number
of C-states shown in sysfs is fixed to the number of C-states present
at boot.
If I boot with AC connected, I always only see the C-states up to C2
even if I disconnect AC.

The reason is commit 130a5f692425 (ACPI / cpuidle: remove dev->state_count
setting). It removes the update of dev->state_count, but sysfs uses
exactly this variable to show the C-states.

The fix is to use drv->state_count in sysfs. As this is currently the
last user of dev->state_count, this variable can be completely removed."

Remove dev->state_count as per the above.

Reported-by: Thomas Schlichter <thomas.schlichter@web.de>
Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Acked-by: Daniel Lezcano <daniel.lezcano@linaro.org>
Cc: 3.14+ <stable@vger.kernel.org> # 3.14+
[ rjw: Changelog ]
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

authored by

Bartlomiej Zolnierkiewicz and committed by
Rafael J. Wysocki
d75e4af1 e42391cd

+3 -6
-3
drivers/cpuidle/cpuidle.c
··· 330 330 if (!dev->registered) 331 331 return -EINVAL; 332 332 333 - if (!dev->state_count) 334 - dev->state_count = drv->state_count; 335 - 336 333 ret = cpuidle_add_device_sysfs(dev); 337 334 if (ret) 338 335 return ret;
+3 -2
drivers/cpuidle/sysfs.c
··· 401 401 struct cpuidle_driver *drv = cpuidle_get_cpu_driver(device); 402 402 403 403 /* state statistics */ 404 - for (i = 0; i < device->state_count; i++) { 404 + for (i = 0; i < drv->state_count; i++) { 405 405 kobj = kzalloc(sizeof(struct cpuidle_state_kobj), GFP_KERNEL); 406 406 if (!kobj) 407 407 goto error_state; ··· 433 433 */ 434 434 static void cpuidle_remove_state_sysfs(struct cpuidle_device *device) 435 435 { 436 + struct cpuidle_driver *drv = cpuidle_get_cpu_driver(device); 436 437 int i; 437 438 438 - for (i = 0; i < device->state_count; i++) 439 + for (i = 0; i < drv->state_count; i++) 439 440 cpuidle_free_state_kobj(device, i); 440 441 } 441 442
-1
include/linux/cpuidle.h
··· 77 77 unsigned int cpu; 78 78 79 79 int last_residency; 80 - int state_count; 81 80 struct cpuidle_state_usage states_usage[CPUIDLE_STATE_MAX]; 82 81 struct cpuidle_state_kobj *kobjs[CPUIDLE_STATE_MAX]; 83 82 struct cpuidle_driver_kobj *kobj_driver;