[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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.