/* * register cpu under node */ int register_cpu_under_node(unsigned int cpu, unsigned int nid) { int ret; struct sys_device *obj; if (!node_online(nid)) return 0; obj = get_cpu_sysdev(cpu); if (!obj) return 0; ret = sysfs_create_link(&node_devices[nid].sysdev.kobj, &obj->kobj, kobject_name(&obj->kobj)); if (ret) return ret; return sysfs_create_link(&obj->kobj, &node_devices[nid].sysdev.kobj, kobject_name(&node_devices[nid].sysdev.kobj)); }
/** * __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); per_cpu(cpuidle_devices, dev->cpu) = dev; list_add(&dev->device_list, &cpuidle_detected_devices); if ((ret = cpuidle_add_sysfs(sys_dev))) { module_put(cpuidle_driver->owner); return ret; } dev->registered = 1; return 0; }
/** * 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); struct cpuidle_driver *cpuidle_driver = cpuidle_get_driver(); if (dev->registered == 0) 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_coupled_unregister_device(dev); cpuidle_resume_and_unlock(); module_put(cpuidle_driver->owner); }
static __init int thermal_throttle_init_device(void) { unsigned int cpu = 0; int err; if (!atomic_read(&therm_throt_en)) return 0; register_hotcpu_notifier(&thermal_throttle_cpu_notifier); #ifdef CONFIG_HOTPLUG_CPU mutex_lock(&therm_cpu_lock); #endif /* connect live CPUs to sysfs */ for_each_online_cpu(cpu) { err = thermal_throttle_add_dev(get_cpu_sysdev(cpu)); WARN_ON(err); } #ifdef CONFIG_HOTPLUG_CPU mutex_unlock(&therm_cpu_lock); #endif return 0; }
/* Get notified when a cpu comes on/off. Be hotplug friendly. */ static __cpuinit int thermal_throttle_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) { unsigned int cpu = (unsigned long)hcpu; struct sys_device *sys_dev; int err; sys_dev = get_cpu_sysdev(cpu); mutex_lock(&therm_cpu_lock); switch (action) { case CPU_ONLINE: case CPU_ONLINE_FROZEN: err = thermal_throttle_add_dev(sys_dev); WARN_ON(err); break; case CPU_DEAD: case CPU_DEAD_FROZEN: thermal_throttle_remove_dev(sys_dev); break; } mutex_unlock(&therm_cpu_lock); return NOTIFY_OK; }
static int __cpuinit acpi_processor_add(struct acpi_device *device) { struct acpi_processor *pr = NULL; int result = 0; struct sys_device *sysdev; pr = kzalloc(sizeof(struct acpi_processor), GFP_KERNEL); if (!pr) return -ENOMEM; if (!zalloc_cpumask_var(&pr->throttling.shared_cpu_map, GFP_KERNEL)) { kfree(pr); return -ENOMEM; } pr->handle = device->handle; strcpy(acpi_device_name(device), ACPI_PROCESSOR_DEVICE_NAME); strcpy(acpi_device_class(device), ACPI_PROCESSOR_CLASS); device->driver_data = pr; result = acpi_processor_get_info(device); if (result) { /* Processor is physically not present */ return 0; } BUG_ON((pr->id >= nr_cpu_ids) || (pr->id < 0)); /* * Buggy BIOS check * ACPI id of processors can be reported wrongly by the BIOS. * Don't trust it blindly */ if (per_cpu(processor_device_array, pr->id) != NULL && per_cpu(processor_device_array, pr->id) != device) { printk(KERN_WARNING "BIOS reported wrong ACPI id " "for the processor\n"); result = -ENODEV; goto err_free_cpumask; } per_cpu(processor_device_array, pr->id) = device; per_cpu(processors, pr->id) = pr; result = acpi_processor_add_fs(device); if (result) goto err_free_cpumask; sysdev = get_cpu_sysdev(pr->id); if (sysfs_create_link(&device->dev.kobj, &sysdev->kobj, "sysdev")) { result = -EFAULT; goto err_remove_fs; } /* _PDC call should be done before doing anything else (if reqd.). */ arch_acpi_processor_init_pdc(pr); acpi_processor_set_pdc(pr); arch_acpi_processor_cleanup_pdc(pr); #ifdef CONFIG_CPU_FREQ acpi_processor_ppc_has_changed(pr); #endif acpi_processor_get_throttling_info(pr); acpi_processor_get_limit_info(pr); acpi_processor_power_init(pr, device); pr->cdev = thermal_cooling_device_register("Processor", device, &processor_cooling_ops); if (IS_ERR(pr->cdev)) { result = PTR_ERR(pr->cdev); goto err_power_exit; } dev_info(&device->dev, "registered as cooling_device%d\n", pr->cdev->id); result = sysfs_create_link(&device->dev.kobj, &pr->cdev->device.kobj, "thermal_cooling"); if (result) { printk(KERN_ERR PREFIX "Create sysfs link\n"); goto err_thermal_unregister; } result = sysfs_create_link(&pr->cdev->device.kobj, &device->dev.kobj, "device"); if (result) { printk(KERN_ERR PREFIX "Create sysfs link\n"); goto err_remove_sysfs; } return 0; err_remove_sysfs: sysfs_remove_link(&device->dev.kobj, "thermal_cooling"); err_thermal_unregister: thermal_cooling_device_unregister(pr->cdev); err_power_exit: acpi_processor_power_exit(pr, device); err_remove_fs: acpi_processor_remove_fs(device); err_free_cpumask: free_cpumask_var(pr->throttling.shared_cpu_map); return result; }
static int init_rq_attribs(void) { int i; int err = 0; const int attr_count = 4; struct attribute **attribs = kzalloc(sizeof(struct attribute *) * attr_count, GFP_KERNEL); if (!attribs) { pr_err("%s: Allocate attribs failed!\n", __func__); goto rel; } rq_info.rq_avg = 0; attribs[0] = MSM_RQ_STATS_RW_ATTRIB(def_timer_ms); attribs[1] = MSM_RQ_STATS_RO_ATTRIB(run_queue_avg); attribs[2] = MSM_RQ_STATS_RW_ATTRIB(run_queue_poll_ms); attribs[3] = NULL; for (i = 0; i < attr_count - 1 ; i++) { if (!attribs[i]) { pr_err("%s: Allocate attribs[%d] failed!\n", __func__, i); goto rel2; } } rq_info.attr_group = kzalloc(sizeof(struct attribute_group), GFP_KERNEL); if (!rq_info.attr_group) { pr_err("%s: Allocate rq_info.attr_group failed!\n", __func__); goto rel3; } rq_info.attr_group->attrs = attribs; /* Create /sys/devices/system/cpu/cpu0/rq-stats/... */ rq_info.kobj = kobject_create_and_add("rq-stats", &get_cpu_sysdev(0)->kobj); if (!rq_info.kobj) { pr_err("%s: Create rq_info.kobj failed!\n", __func__); goto rel3; } err = sysfs_create_group(rq_info.kobj, rq_info.attr_group); if (err) kobject_put(rq_info.kobj); else kobject_uevent(rq_info.kobj, KOBJ_ADD); if (!err) { pr_info("%s: Initialize done.\n", __func__); init_done = 1; return err; } rel3: kfree(rq_info.attr_group); kfree(rq_info.kobj); rel2: for (i = 0; i < attr_count - 1; i++) kfree(attribs[i]); rel: kfree(attribs); return -ENOMEM; }
static int __cpuinit acpi_processor_start(struct acpi_device *device) { int result = 0; struct acpi_processor *pr; struct sys_device *sysdev; pr = acpi_driver_data(device); result = acpi_processor_get_info(device); if (result) { /* Processor is physically not present */ return 0; } BUG_ON((pr->id >= nr_cpu_ids) || (pr->id < 0)); /* * Buggy BIOS check * ACPI id of processors can be reported wrongly by the BIOS. * Don't trust it blindly */ if (per_cpu(processor_device_array, pr->id) != NULL && per_cpu(processor_device_array, pr->id) != device) { printk(KERN_WARNING "BIOS reported wrong ACPI id " "for the processor\n"); return -ENODEV; } per_cpu(processor_device_array, pr->id) = device; per_cpu(processors, pr->id) = pr; result = acpi_processor_add_fs(device); if (result) goto end; sysdev = get_cpu_sysdev(pr->id); if (sysfs_create_link(&device->dev.kobj, &sysdev->kobj, "sysdev")) return -EFAULT; /* _PDC call should be done before doing anything else (if reqd.). */ arch_acpi_processor_init_pdc(pr); acpi_processor_set_pdc(pr); #ifdef CONFIG_CPU_FREQ acpi_processor_ppc_has_changed(pr); #endif acpi_processor_get_throttling_info(pr); acpi_processor_get_limit_info(pr); acpi_processor_power_init(pr, device); pr->cdev = thermal_cooling_device_register("Processor", device, &processor_cooling_ops); if (IS_ERR(pr->cdev)) { result = PTR_ERR(pr->cdev); goto end; } dev_info(&device->dev, "registered as cooling_device%d\n", pr->cdev->id); result = sysfs_create_link(&device->dev.kobj, &pr->cdev->device.kobj, "thermal_cooling"); if (result) printk(KERN_ERR PREFIX "Create sysfs link\n"); result = sysfs_create_link(&pr->cdev->device.kobj, &device->dev.kobj, "device"); if (result) printk(KERN_ERR PREFIX "Create sysfs link\n"); if (pr->flags.throttling) { printk(KERN_INFO PREFIX "%s [%s] (supports", acpi_device_name(device), acpi_device_bid(device)); printk(" %d throttling states", pr->throttling.state_count); printk(")\n"); } end: return result; }
static void __cpuinit topology_remove_dev(unsigned int cpu) { struct sys_device *sys_dev = get_cpu_sysdev(cpu); sysfs_remove_group(&sys_dev->kobj, &topology_attr_group); }
/* Add/Remove cpu_topology interface for CPU device */ static int __cpuinit topology_add_dev(unsigned int cpu) { struct sys_device *sys_dev = get_cpu_sysdev(cpu); return sysfs_create_group(&sys_dev->kobj, &topology_attr_group); }
/** * __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; } /* * 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); if ((ret = cpuidle_add_sysfs(sys_dev))) { module_put(cpuidle_driver->owner); return ret; } dev->registered = 1; return 0; }
static int __cpuinit acpi_processor_add(struct acpi_device *device) { struct acpi_processor *pr = NULL; int result = 0; struct sys_device *sysdev; pr = kzalloc(sizeof(struct acpi_processor), GFP_KERNEL); if (!pr) return -ENOMEM; if (!zalloc_cpumask_var(&pr->throttling.shared_cpu_map, GFP_KERNEL)) { kfree(pr); return -ENOMEM; } pr->handle = device->handle; strcpy(acpi_device_name(device), ACPI_PROCESSOR_DEVICE_NAME); strcpy(acpi_device_class(device), ACPI_PROCESSOR_CLASS); device->driver_data = pr; processor_extcntl_init(); result = acpi_processor_get_info(device); if (result || ((pr->id == -1) && !processor_cntl_external())) { /* Processor is physically not present */ return 0; } BUG_ON(!processor_cntl_external() && ((pr->id >= nr_cpu_ids) || (pr->id < 0))); /* * Buggy BIOS check * ACPI id of processors can be reported wrongly by the BIOS. * Don't trust it blindly */ #ifndef CONFIG_XEN if (per_cpu(processor_device_array, pr->id) != NULL && per_cpu(processor_device_array, pr->id) != device) { #else BUG_ON(pr->acpi_id >= NR_ACPI_CPUS); if (processor_device_array[pr->acpi_id] != NULL && processor_device_array[pr->acpi_id] != device) { #endif printk(KERN_WARNING "BIOS reported wrong ACPI id " "for the processor\n"); result = -ENODEV; goto err_free_cpumask; } #ifndef CONFIG_XEN per_cpu(processor_device_array, pr->id) = device; per_cpu(processors, pr->id) = pr; #else processor_device_array[pr->acpi_id] = device; if (pr->id != -1) per_cpu(processors, pr->id) = pr; #endif result = acpi_processor_add_fs(device); if (result) goto err_free_cpumask; if (pr->id != -1) { sysdev = get_cpu_sysdev(pr->id); if (sysfs_create_link(&device->dev.kobj, &sysdev->kobj, "sysdev")) { result = -EFAULT; goto err_remove_fs; } } /* _PDC call should be done before doing anything else (if reqd.). */ arch_acpi_processor_init_pdc(pr); acpi_processor_set_pdc(pr); arch_acpi_processor_cleanup_pdc(pr); #if defined(CONFIG_CPU_FREQ) || defined(CONFIG_PROCESSOR_EXTERNAL_CONTROL) acpi_processor_ppc_has_changed(pr); #endif /* * pr->id may equal to -1 while processor_cntl_external enabled. * throttle and thermal module don't support this case. * Tx only works when dom0 vcpu == pcpu num by far, as we give * control to dom0. */ if (pr->id != -1) { acpi_processor_get_throttling_info(pr); acpi_processor_get_limit_info(pr); } acpi_processor_power_init(pr, device); result = processor_extcntl_prepare(pr); if (result) goto err_power_exit; pr->cdev = thermal_cooling_device_register("Processor", device, &processor_cooling_ops); if (IS_ERR(pr->cdev)) { result = PTR_ERR(pr->cdev); goto err_power_exit; } dev_info(&device->dev, "registered as cooling_device%d\n", pr->cdev->id); result = sysfs_create_link(&device->dev.kobj, &pr->cdev->device.kobj, "thermal_cooling"); if (result) { printk(KERN_ERR PREFIX "Create sysfs link\n"); goto err_thermal_unregister; } result = sysfs_create_link(&pr->cdev->device.kobj, &device->dev.kobj, "device"); if (result) { printk(KERN_ERR PREFIX "Create sysfs link\n"); goto err_remove_sysfs; } return 0; err_remove_sysfs: sysfs_remove_link(&device->dev.kobj, "thermal_cooling"); err_thermal_unregister: thermal_cooling_device_unregister(pr->cdev); err_power_exit: acpi_processor_power_exit(pr, device); err_remove_fs: acpi_processor_remove_fs(device); err_free_cpumask: free_cpumask_var(pr->throttling.shared_cpu_map); return result; } static int acpi_processor_remove(struct acpi_device *device, int type) { struct acpi_processor *pr = NULL; if (!device || !acpi_driver_data(device)) return -EINVAL; pr = acpi_driver_data(device); if (!processor_cntl_external() && pr->id >= nr_cpu_ids) goto free; if (type == ACPI_BUS_REMOVAL_EJECT) { if (acpi_processor_handle_eject(pr)) return -EINVAL; } acpi_processor_power_exit(pr, device); if (pr->id != -1) sysfs_remove_link(&device->dev.kobj, "sysdev"); acpi_processor_remove_fs(device); if (pr->cdev) { sysfs_remove_link(&device->dev.kobj, "thermal_cooling"); sysfs_remove_link(&pr->cdev->device.kobj, "device"); thermal_cooling_device_unregister(pr->cdev); pr->cdev = NULL; } #ifndef CONFIG_XEN per_cpu(processors, pr->id) = NULL; per_cpu(processor_device_array, pr->id) = NULL; #else if (pr->id != -1) per_cpu(processors, pr->id) = NULL; processor_device_array[pr->acpi_id] = NULL; #endif free: free_cpumask_var(pr->throttling.shared_cpu_map); kfree(pr); return 0; } #ifdef CONFIG_ACPI_HOTPLUG_CPU /**************************************************************************** * Acpi processor hotplug support * ****************************************************************************/ static int is_processor_present(acpi_handle handle) { acpi_status status; unsigned long long sta = 0; status = acpi_evaluate_integer(handle, "_STA", NULL, &sta); if (ACPI_SUCCESS(status) && (sta & ACPI_STA_DEVICE_PRESENT)) return 1; /* * _STA is mandatory for a processor that supports hot plug */ if (status == AE_NOT_FOUND) ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Processor does not support hot plug\n")); else ACPI_EXCEPTION((AE_INFO, status, "Processor Device is not present")); return 0; }