static ssize_t dlpar_cpu_release(const char *buf, size_t count) { struct device_node *dn; const u32 *drc_index; int rc; dn = of_find_node_by_path(buf); if (!dn) return -EINVAL; drc_index = of_get_property(dn, "ibm,my-drc-index", NULL); if (!drc_index) { of_node_put(dn); return -EINVAL; } cpu_hotplug_driver_lock(); rc = dlpar_offline_cpu(dn); if (rc) { of_node_put(dn); rc = -EINVAL; goto out; } rc = dlpar_release_drc(*drc_index); if (rc) { of_node_put(dn); goto out; } rc = dlpar_detach_node(dn); if (rc) { dlpar_acquire_drc(*drc_index); goto out; } of_node_put(dn); out: cpu_hotplug_driver_unlock(); return rc ? rc : count; }
static void dvfs_hotplug_callback(struct work_struct *unused) { cpu_hotplug_driver_lock(); if (cpu_is_offline(NON_BOOT_CPU)) { ssize_t ret; struct sys_device *cpu_sys_dev; ret = cpu_up(NON_BOOT_CPU); // it takes 60ms if (!ret) { cpu_sys_dev = get_cpu_sysdev(NON_BOOT_CPU); if (cpu_sys_dev) { kobject_uevent(&cpu_sys_dev->kobj, KOBJ_ONLINE); stall_mpdecision = 1; } } } cpu_hotplug_driver_unlock(); }
static ssize_t __ref store_online(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct cpu *cpu = container_of(dev, struct cpu, dev); int cpuid = cpu->dev.id; int from_nid, to_nid; ssize_t ret; cpu_hotplug_driver_lock(); switch (buf[0]) { case '0': ret = cpu_down(cpuid); if (!ret) kobject_uevent(&dev->kobj, KOBJ_OFFLINE); break; case '1': from_nid = cpu_to_node(cpuid); ret = cpu_up(cpuid); /* * When hot adding memory to memoryless node and enabling a cpu * on the node, node number of the cpu may internally change. */ to_nid = cpu_to_node(cpuid); if (from_nid != to_nid) change_cpu_under_node(cpu, from_nid, to_nid); if (!ret) kobject_uevent(&dev->kobj, KOBJ_ONLINE); break; default: ret = -EINVAL; } cpu_hotplug_driver_unlock(); if (ret >= 0) ret = count; return ret; }
static ssize_t store_run_queue_avg(struct kobject *kobj, struct kobj_attribute *attr, char *buf, size_t count) { if (buf[0] == '1') { if (is_dual_locked != 0) return count; cpufreq_set_limit(DVFS_START); #if 1 cpu_hotplug_driver_lock(); if (cpu_is_offline(NON_BOOT_CPU)) { cpu_up(NON_BOOT_CPU); // it takes 60ms } cpu_hotplug_driver_unlock(); #else if (cpu_is_offline(NON_BOOT_CPU)) schedule_work_on(0, &dvfs_hotplug_work); #endif stall_mpdecision = 1; is_dual_locked = 1; } else { if (is_dual_locked == 0) { stall_mpdecision = 0; return count; } cpufreq_set_limit(DVFS_STOP); stall_mpdecision = 0; is_dual_locked = 0; } return count; }
static int __ref cpu_subsys_online(struct device *dev) { struct cpu *cpu = container_of(dev, struct cpu, dev); int cpuid = dev->id; int from_nid, to_nid; int ret; cpu_hotplug_driver_lock(); from_nid = cpu_to_node(cpuid); ret = cpu_up(cpuid); /* * When hot adding memory to memoryless node and enabling a cpu * on the node, node number of the cpu may internally change. */ to_nid = cpu_to_node(cpuid); if (from_nid != to_nid) change_cpu_under_node(cpu, from_nid, to_nid); cpu_hotplug_driver_unlock(); return ret; }