int acpi_processor_cst_has_changed(struct acpi_processor *pr) { int ret = 0; if (boot_option_idle_override) return 0; if (!pr) return -EINVAL; if (nocst) { return -ENODEV; } if (!pr->flags.power_setup_done) return -ENODEV; cpuidle_pause_and_lock(); cpuidle_disable_device(&pr->power.dev); acpi_processor_get_power_info(pr); if (pr->flags.power) { acpi_processor_setup_cpuidle(pr); ret = cpuidle_enable_device(&pr->power.dev); } cpuidle_resume_and_unlock(); return ret; }
int acpi_processor_hotplug(struct acpi_processor *pr) { int ret = 0; if (disabled_by_idle_boot_param()) return 0; if (!pr) return -EINVAL; if (nocst) { return -ENODEV; } if (!pr->flags.power_setup_done) return -ENODEV; cpuidle_pause_and_lock(); cpuidle_disable_device(&pr->power.dev); acpi_processor_get_power_info(pr); if (pr->flags.power) { acpi_processor_setup_cpuidle_cx(pr); ret = cpuidle_enable_device(&pr->power.dev); } cpuidle_resume_and_unlock(); return ret; }
static int pseries_cpuidle_add_cpu_notifier(struct notifier_block *n, unsigned long action, void *hcpu) { int hotcpu = (unsigned long)hcpu; struct cpuidle_device *dev = per_cpu(cpuidle_devices, hotcpu); if (dev && cpuidle_get_driver()) { switch (action) { case CPU_ONLINE: case CPU_ONLINE_FROZEN: cpuidle_pause_and_lock(); cpuidle_enable_device(dev); cpuidle_resume_and_unlock(); break; case CPU_DEAD: case CPU_DEAD_FROZEN: cpuidle_pause_and_lock(); cpuidle_disable_device(dev); cpuidle_resume_and_unlock(); break; default: return NOTIFY_DONE; } } return NOTIFY_OK; }
int acpi_processor_hotplug(struct acpi_processor *pr) { int ret = 0; struct cpuidle_device *dev; if (disabled_by_idle_boot_param()) return 0; if (nocst) return -ENODEV; if (!pr->flags.power_setup_done) return -ENODEV; dev = per_cpu(acpi_cpuidle_device, pr->id); cpuidle_pause_and_lock(); cpuidle_disable_device(dev); acpi_processor_get_power_info(pr); if (pr->flags.power) { acpi_processor_setup_cpuidle_cx(pr, dev); ret = cpuidle_enable_device(dev); } cpuidle_resume_and_unlock(); return ret; }
/** * cpuidle_switch_governor - changes the governor * @gov: the new target governor * * NOTE: "gov" can be NULL to specify disabled * Must be called with cpuidle_lock acquired. */ int cpuidle_switch_governor(struct cpuidle_governor *gov) { struct cpuidle_device *dev; if (gov == cpuidle_curr_governor) return 0; cpuidle_uninstall_idle_handler(); if (cpuidle_curr_governor) { list_for_each_entry(dev, &cpuidle_detected_devices, device_list) cpuidle_disable_device(dev); module_put(cpuidle_curr_governor->owner); } cpuidle_curr_governor = gov; if (gov) { if (!try_module_get(cpuidle_curr_governor->owner)) return -EINVAL; list_for_each_entry(dev, &cpuidle_detected_devices, device_list) cpuidle_enable_device(dev); cpuidle_install_idle_handler(); printk(KERN_INFO "cpuidle: using governor %s\n", gov->name); } return 0; }
/** * cpuidle_register_device - registers a CPU's idle PM feature * @dev: the cpu */ int cpuidle_register_device(struct cpuidle_device *dev) { int ret; struct sys_device *sys_dev = get_cpu_sysdev((unsigned long)dev->cpu); if (!sys_dev) return -EINVAL; if (!try_module_get(cpuidle_curr_driver->owner)) return -EINVAL; init_completion(&dev->kobj_unregister); mutex_lock(&cpuidle_lock); poll_idle_init(dev); per_cpu(cpuidle_devices, dev->cpu) = dev; list_add(&dev->device_list, &cpuidle_detected_devices); if ((ret = cpuidle_add_sysfs(sys_dev))) { mutex_unlock(&cpuidle_lock); module_put(cpuidle_curr_driver->owner); return ret; } cpuidle_enable_device(dev); cpuidle_install_idle_handler(); mutex_unlock(&cpuidle_lock); return 0; }
int acpi_processor_cst_has_changed(struct acpi_processor *pr) { int cpu; struct acpi_processor *_pr; struct cpuidle_device *dev; 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; dev = per_cpu(acpi_cpuidle_device, cpu); cpuidle_disable_device(dev); } /* Populate Updated C-state information */ acpi_processor_get_power_info(pr); 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) { dev = per_cpu(acpi_cpuidle_device, cpu); acpi_processor_setup_cpuidle_cx(_pr, dev); cpuidle_enable_device(dev); } } put_online_cpus(); cpuidle_resume_and_unlock(); }
int pseries_notify_cpuidle_add_cpu(int cpu) { struct cpuidle_device *dev = per_cpu_ptr(pseries_cpuidle_devices, cpu); if (dev && cpuidle_get_driver()) { cpuidle_disable_device(dev); cpuidle_enable_device(dev); } return 0; }
int s5p6442_setup_lpaudio(unsigned int mode) { struct cpuidle_device *device; int ret = 0; cpuidle_pause_and_lock(); device = &per_cpu(s5p6442_cpuidle_device, smp_processor_id()); cpuidle_disable_device(device); switch (mode) { case NORMAL_MODE: device->state_count = 1; /* Wait for interrupt state */ device->states[0].enter = s5p6442_enter_idle_normal; device->states[0].exit_latency = 1; /* uS */ device->states[0].target_residency = 10000; device->states[0].flags = CPUIDLE_FLAG_TIME_VALID; strcpy(device->states[0].name, "IDLE"); strcpy(device->states[0].desc, "ARM clock gating - WFI"); break; case LPAUDIO_MODE: device->state_count = 1; /* Wait for interrupt state */ device->states[0].enter = s5p6442_enter_idle_bm; device->states[0].exit_latency = 1; /* uS */ device->states[0].target_residency = 5000; device->states[0].flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_CHECK_BM; strcpy(device->states[0].name, "DEEP IDLE"); strcpy(device->states[0].desc, "S5P6442 idle2"); break; default: printk(KERN_ERR "Can't find cpuidle mode %d\n", mode); device->state_count = 1; /* Wait for interrupt state */ device->states[0].enter = s5p6442_enter_idle_normal; device->states[0].exit_latency = 1; /* uS */ device->states[0].target_residency = 10000; device->states[0].flags = CPUIDLE_FLAG_TIME_VALID; strcpy(device->states[0].name, "IDLE"); strcpy(device->states[0].desc, "ARM clock gating - WFI"); break; } cpuidle_enable_device(device); cpuidle_resume_and_unlock(); return ret; }
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 cpuidle_register_device(struct cpuidle_device *dev) { int ret; mutex_lock(&cpuidle_lock); if ((ret = __cpuidle_register_device(dev))) { mutex_unlock(&cpuidle_lock); return ret; } cpuidle_enable_device(dev); cpuidle_install_idle_handler(); mutex_unlock(&cpuidle_lock); return 0; }
static int mv_cpu_idle_write(struct file *file, const char *buffer, unsigned long count, void *data) { MV_U32 regs[4]; /* Reading / Writing from system controller internal registers */ if (!strncmp (buffer, "enable", strlen("enable"))) { if(device_registered == 0) { device_registered = 1; if (cpuidle_register_device(kirkwood_cpu_idle_device)) { printk(KERN_ERR "mv_cpu_idle_write: Failed registering\n"); return -EIO; } } cpuidle_enable_device(kirkwood_cpu_idle_device); } else if (!strncmp (buffer, "disable", strlen("disable"))) { cpuidle_disable_device(kirkwood_cpu_idle_device); } else if (!strncmp (buffer, "test", strlen("test"))) { /* Store Interrupt mask registers. */ regs[0] = MV_REG_READ(MV_IRQ_MASK_LOW_REG); regs[1] = MV_REG_READ(MV_IRQ_MASK_HIGH_REG); regs[2] = MV_REG_READ(MV_IRQ_MASK_ERROR_REG); /* Disable all interrupts . */ MV_REG_WRITE(MV_IRQ_MASK_LOW_REG, 0x0); MV_REG_WRITE(MV_IRQ_MASK_HIGH_REG, 0x0); MV_REG_WRITE(MV_IRQ_MASK_ERROR_REG, 0x0); /* Enable only the UART interrupt. */ MV_REG_BIT_SET(MV_IRQ_MASK_HIGH_REG, 1 << (UART_IRQ_NUM(0) - 32)); printk(KERN_INFO "Press any key to leave deep idle:"); mv_kw2_cpu_idle_enter(); /* Restore Interrupt mask registers. */ MV_REG_WRITE(MV_IRQ_MASK_LOW_REG, regs[0]); MV_REG_WRITE(MV_IRQ_MASK_HIGH_REG, regs[1]); MV_REG_WRITE(MV_IRQ_MASK_ERROR_REG, regs[2]); } return count; }