[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH 08/10] xen/acpi: add cpu hotadd support
On Thu, Dec 22, 2011 at 10:08:34AM +0000, Liu, Jinsong wrote: > >From 282958be3a33b2f2b888e1ed3ac022bf8a199ec9 Mon Sep 17 00:00:00 2001 > From: Liu Jinsong <jinsong.liu@xxxxxxxxx> > Date: Wed, 14 Dec 2011 11:38:11 +0800 > Subject: [PATCH 08/10] xen/acpi: add cpu hotadd support > > This patch add cpu hotadd support. > It keep similar cpu hotadd logic as native, w/ some changes according > to xen requirement, hypercalling hypervisor related logic to hotadd cpu. Is this needed anymore? Or is the existing code in the upstream kernel sufficient enough for this? Or do we need a hotplug CPU notifier in the xen-acpi-processor? > > Signed-off-by: Liu, Jinsong <jinsong.liu@xxxxxxxxx> > Signed-off-by: Jiang, Yunhong <yunhong.jiang@xxxxxxxxx> > --- > drivers/acpi/processor_driver.c | 4 +- > drivers/acpi/processor_xen.c | 242 > ++++++++++++++++++++++++++++++++++++++- > include/acpi/processor.h | 2 + > include/xen/pcpu.h | 2 + > 4 files changed, 246 insertions(+), 4 deletions(-) > > diff --git a/drivers/acpi/processor_driver.c b/drivers/acpi/processor_driver.c > index 8a367d7..d473fd5 100644 > --- a/drivers/acpi/processor_driver.c > +++ b/drivers/acpi/processor_driver.c > @@ -221,7 +221,7 @@ static int acpi_processor_errata_piix4(struct pci_dev > *dev) > return 0; > } > > -static int acpi_processor_errata(struct acpi_processor *pr) > +int acpi_processor_errata(struct acpi_processor *pr) > { > int result = 0; > struct pci_dev *dev = NULL; > @@ -378,7 +378,7 @@ static int acpi_processor_get_info(struct acpi_device > *device) > return 0; > } > > -static DEFINE_PER_CPU(void *, processor_device_array); > +DEFINE_PER_CPU(void *, processor_device_array); > > void acpi_processor_notify(struct acpi_device *device, u32 event) > { > diff --git a/drivers/acpi/processor_xen.c b/drivers/acpi/processor_xen.c > index 38a1c05..3af1f73 100644 > --- a/drivers/acpi/processor_xen.c > +++ b/drivers/acpi/processor_xen.c > @@ -24,6 +24,7 @@ > #define PREFIX "ACPI: " > > #define ACPI_PROCESSOR_CLASS "processor" > +#define ACPI_PROCESSOR_DEVICE_NAME "Processor" > #define ACPI_PROCESSOR_NOTIFY_PERFORMANCE 0x80 > #define ACPI_PROCESSOR_NOTIFY_POWER 0x81 > #define ACPI_PROCESSOR_NOTIFY_THROTTLING 0x82 > @@ -88,6 +89,8 @@ xen_acpi_processor_hotadd_init(struct acpi_processor *pr, > int *p_cpu) > PROCESSOR_HOTPLUG, HOTPLUG_TYPE_ADD)) > return AE_ERROR; > > + *p_cpu = xen_pcpu_index(pr->acpi_id, 1); > + > return AE_OK; > } > > @@ -149,13 +152,248 @@ err_out: > } > #endif /* CONFIG_CPU_FREQ */ > > +static int xen_acpi_processor_get_info(struct acpi_device *device) > +{ > + acpi_status status = 0; > + union acpi_object object = { 0 }; > + struct acpi_buffer buffer = { sizeof(union acpi_object), &object }; > + struct acpi_processor *pr; > + int cpu_index, device_declaration = 0; > + static int cpu0_initialized; > + > + pr = acpi_driver_data(device); > + if (!pr) > + return -EINVAL; > + > + if (num_online_cpus() > 1) > + errata.smp = TRUE; > + > + acpi_processor_errata(pr); > + > + /* > + * Check to see if we have bus mastering arbitration control. This > + * is required for proper C3 usage (to maintain cache coherency). > + */ > + if (acpi_gbl_FADT.pm2_control_block && > acpi_gbl_FADT.pm2_control_length) { > + pr->flags.bm_control = 1; > + ACPI_DEBUG_PRINT((ACPI_DB_INFO, > + "Bus mastering arbitration control > present\n")); > + } else > + ACPI_DEBUG_PRINT((ACPI_DB_INFO, > + "No bus mastering arbitration control\n")); > + > + if (!strcmp(acpi_device_hid(device), ACPI_PROCESSOR_OBJECT_HID)) { > + /* Declared with "Processor" statement; match ProcessorID */ > + status = acpi_evaluate_object(pr->handle, NULL, NULL, &buffer); > + if (ACPI_FAILURE(status)) { > + printk(KERN_ERR PREFIX "Evaluating processor object\n"); > + return -ENODEV; > + } > + > + /* > + * TBD: Synch processor ID (via LAPIC/LSAPIC structures) on SMP. > + * >>> 'acpi_get_processor_id(acpi_id, &id)' in > + * arch/xxx/acpi.c > + */ > + pr->acpi_id = object.processor.proc_id; > + } else { > + /* > + * Declared with "Device" statement; match _UID. > + * Note that we don't handle string _UIDs yet. > + */ > + unsigned long long value; > + status = acpi_evaluate_integer(pr->handle, METHOD_NAME__UID, > + NULL, &value); > + if (ACPI_FAILURE(status)) { > + printk(KERN_ERR PREFIX > + "Evaluating processor _UID [%#x]\n", status); > + return -ENODEV; > + } > + device_declaration = 1; > + pr->acpi_id = value; > + } > + > + cpu_index = xen_pcpu_index(pr->acpi_id, 1); > + > + /* Handle UP system running SMP kernel, with no LAPIC in MADT */ > + if (!cpu0_initialized && (cpu_index == -1) && > + (num_online_cpus() == 1)) { > + cpu_index = 0; > + } > + > + cpu0_initialized = 1; > + > + pr->id = cpu_index; > + > + /* > + * Extra Processor objects may be enumerated on MP systems with > + * less than the max # of CPUs. They should be ignored _iff > + * they are physically not present. > + */ > + if (pr->id == -1) { > + if (ACPI_FAILURE > + (xen_acpi_processor_hotadd_init(pr, &pr->id))) { > + return -ENODEV; > + } > + } > + /* > + * On some boxes several processors use the same processor bus id. > + * But they are located in different scope. For example: > + * \_SB.SCK0.CPU0 > + * \_SB.SCK1.CPU0 > + * Rename the processor device bus id. And the new bus id will be > + * generated as the following format: > + * CPU+CPU ID. > + */ > + sprintf(acpi_device_bid(device), "CPU%X", pr->id); > + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Processor [%d:%d]\n", pr->id, > + pr->acpi_id)); > + > + if (!object.processor.pblk_address) > + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No PBLK (NULL address)\n")); > + else if (object.processor.pblk_length != 6) > + printk(KERN_ERR PREFIX "Invalid PBLK length [%d]\n", > + object.processor.pblk_length); > + else { > + pr->throttling.address = object.processor.pblk_address; > + pr->throttling.duty_offset = acpi_gbl_FADT.duty_offset; > + pr->throttling.duty_width = acpi_gbl_FADT.duty_width; > + > + pr->pblk = object.processor.pblk_address; > + > + /* > + * We don't care about error returns - we just try to mark > + * these reserved so that nobody else is confused into thinking > + * that this region might be unused.. > + * > + * (In particular, allocating the IO range for Cardbus) > + */ > + request_region(pr->throttling.address, 6, "ACPI CPU throttle"); > + } > + > + /* > + * If ACPI describes a slot number for this CPU, we can use it > + * ensure we get the right value in the "physical id" field > + * of /proc/cpuinfo > + */ > + status = acpi_evaluate_object(pr->handle, "_SUN", NULL, &buffer); > + if (ACPI_SUCCESS(status)) > + arch_fix_phys_package_id(pr->id, object.integer.value); > + > + return 0; > +} > + > +static int __cpuinit __xen_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 = xen_acpi_processor_get_info(device); > + if (result) { > + /* Processor is physically not present */ > + return 0; > + } > + > +#ifdef CONFIG_SMP > + if (pr->id >= setup_max_cpus && pr->id != 0) > + return 0; > +#endif > + > + 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; > + > + sysdev = get_cpu_sysdev(pr->id); > + if (sysfs_create_link(&device->dev.kobj, &sysdev->kobj, "sysdev")) { > + result = -EFAULT; > + goto err_free_cpumask; > + } > + > +#ifdef CONFIG_CPU_FREQ > + acpi_processor_ppc_has_changed(pr, 0); > +#endif > + acpi_processor_get_throttling_info(pr); > + acpi_processor_get_limit_info(pr); > + > + > + if (cpuidle_get_driver() == &acpi_idle_driver) > + 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_dbg(&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_free_cpumask: > + free_cpumask_var(pr->throttling.shared_cpu_map); > + > + return result; > +} > + > static int __cpuinit xen_acpi_processor_add(struct acpi_device *device) > { > struct acpi_processor *pr = NULL; > int result = 0; > > - result = acpi_processor_add(device); > - if (result < 0) > + result = __xen_acpi_processor_add(device); > + if (result) > return result; > > pr = acpi_driver_data(device); > diff --git a/include/acpi/processor.h b/include/acpi/processor.h > index c48e2f9..3a1ee01 100644 > --- a/include/acpi/processor.h > +++ b/include/acpi/processor.h > @@ -225,6 +225,8 @@ struct acpi_processor_errata { > } piix4; > }; > > +extern int acpi_processor_errata(struct acpi_processor *pr); > + > extern int acpi_processor_preregister_performance(struct > acpi_processor_performance > __percpu *performance); > diff --git a/include/xen/pcpu.h b/include/xen/pcpu.h > index 7e8f9d1..3e99db9 100644 > --- a/include/xen/pcpu.h > +++ b/include/xen/pcpu.h > @@ -4,6 +4,8 @@ > #include <xen/interface/platform.h> > #include <linux/sysdev.h> > > +extern DEFINE_PER_CPU(void *, processor_device_array); > + > extern int xen_pcpu_hotplug(int type, uint32_t apic_id); > #define XEN_PCPU_ONLINE 0x01 > #define XEN_PCPU_OFFLINE 0x02 > -- > 1.6.5.6 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |