int acpi_processor_cst_has_changed(struct acpi_processor *pr) { int cpu; struct acpi_processor *_pr; if (disabled_by_idle_boot_param()) return 0; if (!pr) return -EINVAL; if (nocst) return -ENODEV; if (!pr->flags.power_setup_done) return -ENODEV; /* * FIXME: Design the ACPI notification to make it once per * system instead of once per-cpu. This condition is a hack * to make the code that updates C-States be called once. */ if (pr->id == 0 && cpuidle_get_driver() == &acpi_idle_driver) { cpuidle_pause_and_lock(); /* Protect against cpu-hotplug */ get_online_cpus(); /* Disable all cpuidle devices */ for_each_online_cpu(cpu) { _pr = per_cpu(processors, cpu); if (!_pr || !_pr->flags.power_setup_done) continue; cpuidle_disable_device(&_pr->power.dev); } /* Populate Updated C-state information */ acpi_processor_setup_cpuidle_states(pr); /* Enable all cpuidle devices */ for_each_online_cpu(cpu) { _pr = per_cpu(processors, cpu); if (!_pr || !_pr->flags.power_setup_done) continue; acpi_processor_get_power_info(_pr); if (_pr->flags.power) { acpi_processor_setup_cpuidle_cx(_pr); cpuidle_enable_device(&_pr->power.dev); } } put_online_cpus(); cpuidle_resume_and_unlock(); }
int acpi_processor_cst_has_changed(struct acpi_processor *pr) { int cpu; struct acpi_processor *_pr; if (disabled_by_idle_boot_param()) return 0; if (!pr) return -EINVAL; if (nocst) return -ENODEV; if (!pr->flags.power_setup_done) return -ENODEV; if (pr->id == 0 && cpuidle_get_driver() == &acpi_idle_driver) { cpuidle_pause_and_lock(); get_online_cpus(); for_each_online_cpu(cpu) { _pr = per_cpu(processors, cpu); if (!_pr || !_pr->flags.power_setup_done) continue; cpuidle_disable_device(&_pr->power.dev); } acpi_processor_setup_cpuidle_states(pr); for_each_online_cpu(cpu) { _pr = per_cpu(processors, cpu); if (!_pr || !_pr->flags.power_setup_done) continue; acpi_processor_get_power_info(_pr); if (_pr->flags.power) { acpi_processor_setup_cpuidle_cx(_pr); cpuidle_enable_device(&_pr->power.dev); } } put_online_cpus(); cpuidle_resume_and_unlock(); }
int __cpuinit acpi_processor_power_init(struct acpi_processor *pr, struct acpi_device *device) { acpi_status status = 0; static int first_run; if (disabled_by_idle_boot_param()) return 0; if (!first_run) { dmi_check_system(processor_power_dmi_table); max_cstate = acpi_processor_cstate_check(max_cstate); if (max_cstate < ACPI_C_STATES_MAX) printk(KERN_NOTICE "ACPI: processor limited to max C-state %d\n", max_cstate); first_run++; } if (!pr) return -EINVAL; if (acpi_gbl_FADT.cst_control && !nocst) { status = acpi_os_write_port(acpi_gbl_FADT.smi_command, acpi_gbl_FADT.cst_control, 8); if (ACPI_FAILURE(status)) { ACPI_EXCEPTION((AE_INFO, status, "Notifying BIOS of _CST ability failed")); } } acpi_processor_get_power_info(pr); pr->flags.power_setup_done = 1; /* * Install the idle handler if processor power management is supported. * Note that we use previously set idle handler will be used on * platforms that only support C1. */ if (pr->flags.power) { acpi_processor_setup_cpuidle(pr); if (cpuidle_register_device(&pr->power.dev)) return -EIO; } return 0; }
int acpi_processor_hotplug(struct acpi_processor *pr) { int ret = 0; struct cpuidle_device *dev; if (disabled_by_idle_boot_param()) return 0; if (!pr->flags.power_setup_done) return -ENODEV; dev = per_cpu(acpi_cpuidle_device, pr->id); cpuidle_pause_and_lock(); cpuidle_disable_device(dev); ret = acpi_processor_get_power_info(pr); if (!ret && pr->flags.power) { acpi_processor_setup_cpuidle_dev(pr, dev); ret = cpuidle_enable_device(dev); } cpuidle_resume_and_unlock(); return ret; }