/** * __cpuidle_register_device - internal register function called before register * and enable routines * @dev: the cpu * * cpuidle_lock mutex must be held before this is called */ static int __cpuidle_register_device(struct cpuidle_device *dev) { int ret; struct device *cpu_dev = get_cpu_device((unsigned long)dev->cpu); struct cpuidle_driver *cpuidle_driver = cpuidle_get_driver(); if (!dev) return -EINVAL; if (!try_module_get(cpuidle_driver->owner)) return -EINVAL; init_completion(&dev->kobj_unregister); per_cpu(cpuidle_devices, dev->cpu) = dev; list_add(&dev->device_list, &cpuidle_detected_devices); ret = cpuidle_add_sysfs(cpu_dev); if (ret) goto err_sysfs; ret = cpuidle_coupled_register_device(dev); if (ret) goto err_coupled; dev->registered = 1; return 0; err_coupled: cpuidle_remove_sysfs(cpu_dev); wait_for_completion(&dev->kobj_unregister); err_sysfs: list_del(&dev->device_list); per_cpu(cpuidle_devices, dev->cpu) = NULL; module_put(cpuidle_driver->owner); return ret; }
/** * __cpuidle_register_device - internal register function called before register * and enable routines * @dev: the cpu * * cpuidle_lock mutex must be held before this is called */ static int __cpuidle_register_device(struct cpuidle_device *dev) { int ret; struct cpuidle_driver *drv = cpuidle_get_cpu_driver(dev); if (!try_module_get(drv->owner)) return -EINVAL; per_cpu(cpuidle_devices, dev->cpu) = dev; list_add(&dev->device_list, &cpuidle_detected_devices); ret = cpuidle_add_sysfs(dev); if (ret) goto err_sysfs; ret = cpuidle_coupled_register_device(dev); if (ret) goto err_coupled; dev->registered = 1; return 0; err_coupled: cpuidle_remove_sysfs(dev); err_sysfs: list_del(&dev->device_list); per_cpu(cpuidle_devices, dev->cpu) = NULL; module_put(drv->owner); return ret; }
/** * cpuidle_unregister_device - unregisters a CPU's idle PM feature * @dev: the cpu */ void cpuidle_unregister_device(struct cpuidle_device *dev) { struct sys_device *sys_dev = get_cpu_sysdev((unsigned long)dev->cpu); if (!sys_dev) { pr_err(" ERR get_cpu_sysdev returned NULL\n"); return; } if (dev->registered == 0) return; if (!sys_dev) return; cpuidle_pause_and_lock(); cpuidle_disable_device(dev); cpuidle_remove_sysfs(sys_dev); list_del(&dev->device_list); wait_for_completion(&dev->kobj_unregister); per_cpu(cpuidle_devices, dev->cpu) = NULL; cpuidle_resume_and_unlock(); module_put(cpuidle_curr_driver->owner); }
/** * cpuidle_unregister_device - unregisters a CPU's idle PM feature * @dev: the cpu */ void cpuidle_unregister_device(struct cpuidle_device *dev) { struct device *cpu_dev; struct cpuidle_driver *cpuidle_driver = cpuidle_get_driver(); if (!dev) return; cpu_dev = get_cpu_device((unsigned long)dev->cpu); if (!cpu_dev) return; if (dev->registered == 0) return; cpuidle_pause_and_lock(); cpuidle_disable_device(dev); cpuidle_remove_sysfs(cpu_dev); list_del(&dev->device_list); wait_for_completion(&dev->kobj_unregister); per_cpu(cpuidle_devices, dev->cpu) = NULL; cpuidle_coupled_unregister_device(dev); cpuidle_resume_and_unlock(); module_put(cpuidle_driver->owner); }
/** * __cpuidle_register_device - internal register function called before register * and enable routines * @dev: the cpu * * cpuidle_lock mutex must be held before this is called */ static int __cpuidle_register_device(struct cpuidle_device *dev) { int ret; struct sys_device *sys_dev = get_cpu_sysdev((unsigned long)dev->cpu); struct cpuidle_driver *cpuidle_driver = cpuidle_get_driver(); if (!sys_dev) return -EINVAL; if (!try_module_get(cpuidle_driver->owner)) return -EINVAL; init_completion(&dev->kobj_unregister); /* * cpuidle driver should set the dev->power_specified bit * before registering the device if the driver provides * power_usage numbers. * * For those devices whose ->power_specified is not set, * we fill in power_usage with decreasing values as the * cpuidle code has an implicit assumption that state Cn * uses less power than C(n-1). * * With CONFIG_ARCH_HAS_CPU_RELAX, C0 is already assigned * an power value of -1. So we use -2, -3, etc, for other * c-states. */ if (!dev->power_specified) { int i; for (i = CPUIDLE_DRIVER_STATE_START; i < dev->state_count; i++) dev->states[i].power_usage = -1 - i; } per_cpu(cpuidle_devices, dev->cpu) = dev; list_add(&dev->device_list, &cpuidle_detected_devices); ret = cpuidle_add_sysfs(sys_dev); if (ret) goto err_sysfs; ret = cpuidle_coupled_register_device(dev); if (ret) goto err_coupled; dev->registered = 1; return 0; err_coupled: cpuidle_remove_sysfs(sys_dev); wait_for_completion(&dev->kobj_unregister); err_sysfs: list_del(&dev->device_list); per_cpu(cpuidle_devices, dev->cpu) = NULL; module_put(cpuidle_driver->owner); return ret; }
/** * cpuidle_unregister_device - unregisters a CPU's idle PM feature * @dev: the cpu */ void cpuidle_unregister_device(struct cpuidle_device *dev) { struct cpuidle_driver *drv = cpuidle_get_cpu_driver(dev); if (dev->registered == 0) return; cpuidle_pause_and_lock(); cpuidle_disable_device(dev); cpuidle_remove_sysfs(dev); list_del(&dev->device_list); per_cpu(cpuidle_devices, dev->cpu) = NULL; cpuidle_coupled_unregister_device(dev); cpuidle_resume_and_unlock(); module_put(drv->owner); }