static int acpi_processor_start(struct acpi_device *device) { int result = 0; acpi_status status = AE_OK; struct acpi_processor *pr; ACPI_FUNCTION_TRACE("acpi_processor_start"); pr = acpi_driver_data(device); result = acpi_processor_get_info(pr); if (result) { /* Processor is physically not present */ return_VALUE(0); } BUG_ON((pr->id >= NR_CPUS) || (pr->id < 0)); /* * Buggy BIOS check * ACPI id of processors can be reported wrongly by the BIOS. * Don't trust it blindly */ if (processor_device_array[pr->id] != NULL && processor_device_array[pr->id] != (void *)device) { ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "BIOS reporting wrong ACPI id" "for the processor\n")); return_VALUE(-ENODEV); } processor_device_array[pr->id] = (void *)device; processors[pr->id] = pr; result = acpi_processor_add_fs(device); if (result) goto end; status = acpi_install_notify_handler(pr->handle, ACPI_DEVICE_NOTIFY, acpi_processor_notify, pr); if (ACPI_FAILURE(status)) { ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error installing device notify handler\n")); } acpi_processor_power_init(pr, device); 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_VALUE(result); }
static int __cpuinit acpi_processor_start(struct acpi_device *device) { int result = 0; acpi_status status = AE_OK; struct acpi_processor *pr; pr = acpi_driver_data(device); result = acpi_processor_get_info(pr); if (result) { /* Processor is physically not present */ return 0; } BUG_ON((pr->id >= NR_CPUS) || (pr->id < 0)); /* * Buggy BIOS check * ACPI id of processors can be reported wrongly by the BIOS. * Don't trust it blindly */ if (processor_device_array[pr->id] != NULL && processor_device_array[pr->id] != device) { printk(KERN_WARNING "BIOS reported wrong ACPI id" "for the processor\n"); return -ENODEV; } processor_device_array[pr->id] = device; processors[pr->id] = pr; result = acpi_processor_add_fs(device); if (result) goto end; status = acpi_install_notify_handler(pr->handle, ACPI_DEVICE_NOTIFY, acpi_processor_notify, pr); /* _PDC call should be done before doing anything else (if reqd.). */ arch_acpi_processor_init_pdc(pr); acpi_processor_set_pdc(pr); acpi_processor_power_init(pr, device); 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 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 __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 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; }
static int acpi_processor_start(struct acpi_device *device) { int result = 0; acpi_status status = AE_OK; struct acpi_processor *pr; processor_extcntl_init(); pr = acpi_driver_data(device); result = acpi_processor_get_info(pr); if (result || ((pr->id == -1) && !processor_cntl_external())) { /* Processor is physically not present */ return 0; } BUG_ON(!processor_cntl_external() && ((pr->id >= NR_CPUS) || (pr->id < 0))); /* * Buggy BIOS check * ACPI id of processors can be reported wrongly by the BIOS. * Don't trust it blindly */ #ifdef CONFIG_XEN BUG_ON(pr->acpi_id >= NR_ACPI_CPUS); if (processor_device_array[pr->acpi_id] != NULL && processor_device_array[pr->acpi_id] != (void *)device) { #else if (processor_device_array[pr->id] != NULL && processor_device_array[pr->id] != (void *)device) { #endif /* CONFIG_XEN */ printk(KERN_WARNING "BIOS reported wrong ACPI id" "for the processor\n"); return -ENODEV; } #ifdef CONFIG_XEN processor_device_array[pr->acpi_id] = (void *)device; if (pr->id != -1) processors[pr->id] = pr; #else processor_device_array[pr->id] = (void *)device; processors[pr->id] = pr; #endif /* CONFIG_XEN */ result = acpi_processor_add_fs(device); if (result) goto end; status = acpi_install_notify_handler(pr->handle, ACPI_DEVICE_NOTIFY, acpi_processor_notify, pr); /* _PDC call should be done before doing anything else (if reqd.). */ arch_acpi_processor_init_pdc(pr); acpi_processor_set_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 end; 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 acpi_processor_notify(acpi_handle handle, u32 event, void *data) { struct acpi_processor *pr = (struct acpi_processor *)data; struct acpi_device *device = NULL; if (!pr) return; if (acpi_bus_get_device(pr->handle, &device)) return; switch (event) { case ACPI_PROCESSOR_NOTIFY_PERFORMANCE: acpi_processor_ppc_has_changed(pr); acpi_bus_generate_event(device, event, pr->performance_platform_limit); break; case ACPI_PROCESSOR_NOTIFY_POWER: acpi_processor_cst_has_changed(pr); acpi_bus_generate_event(device, event, 0); break; case ACPI_PROCESSOR_NOTIFY_THROTTLING: acpi_processor_tstate_has_changed(pr); acpi_bus_generate_event(device, event, 0); break; default: ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Unsupported event [0x%x]\n", event)); break; } return; } static int acpi_processor_add(struct acpi_device *device) { struct acpi_processor *pr = NULL; if (!device) return -EINVAL; pr = kmalloc(sizeof(struct acpi_processor), GFP_KERNEL); if (!pr) return -ENOMEM; memset(pr, 0, sizeof(struct acpi_processor)); pr->handle = device->handle; strcpy(acpi_device_name(device), ACPI_PROCESSOR_DEVICE_NAME); strcpy(acpi_device_class(device), ACPI_PROCESSOR_CLASS); acpi_driver_data(device) = pr; return 0; } static int acpi_processor_remove(struct acpi_device *device, int type) { acpi_status status = AE_OK; struct acpi_processor *pr = NULL; if (!device || !acpi_driver_data(device)) return -EINVAL; pr = (struct acpi_processor *)acpi_driver_data(device); if (!processor_cntl_external() && pr->id >= NR_CPUS) { kfree(pr); return 0; } if (type == ACPI_BUS_REMOVAL_EJECT) { if (acpi_processor_handle_eject(pr)) return -EINVAL; } acpi_processor_power_exit(pr, device); status = acpi_remove_notify_handler(pr->handle, ACPI_DEVICE_NOTIFY, acpi_processor_notify); acpi_processor_remove_fs(device); #ifdef CONFIG_XEN if (pr->id != -1) processors[pr->id] = NULL; #else processors[pr->id] = NULL; #endif /* CONFIG_XEN */ kfree(pr); return 0; }