X-Git-Url: http://ftp.safe.ca/?a=blobdiff_plain;f=drivers%2Facpi%2Fprocessor_core.c;h=f7de02a6f497a5d61752dff2a413a7c7b4c9f43a;hb=7b1d5c0b604df6cee31b2c0160ede3f1311fbb66;hp=d56a439ac614f4931c6b86fab438396bf72dc4c9;hpb=5028770a42e7bc4d15791a44c28f0ad539323807;p=safe%2Fjmp%2Flinux-2.6 diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index d56a439..f7de02a 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c @@ -58,10 +58,8 @@ #include #include - #define ACPI_PROCESSOR_COMPONENT 0x01000000 #define ACPI_PROCESSOR_CLASS "processor" -#define ACPI_PROCESSOR_DRIVER_NAME "ACPI Processor Driver" #define ACPI_PROCESSOR_DEVICE_NAME "Processor" #define ACPI_PROCESSOR_FILE_INFO "info" #define ACPI_PROCESSOR_FILE_THROTTLING "throttling" @@ -72,67 +70,58 @@ #define ACPI_PROCESSOR_LIMIT_USER 0 #define ACPI_PROCESSOR_LIMIT_THERMAL 1 -#define ACPI_STA_PRESENT 0x00000001 - #define _COMPONENT ACPI_PROCESSOR_COMPONENT -ACPI_MODULE_NAME ("acpi_processor") +ACPI_MODULE_NAME("processor_core"); MODULE_AUTHOR("Paul Diefenbaugh"); -MODULE_DESCRIPTION(ACPI_PROCESSOR_DRIVER_NAME); +MODULE_DESCRIPTION("ACPI Processor Driver"); MODULE_LICENSE("GPL"); - -static int acpi_processor_add (struct acpi_device *device); -static int acpi_processor_start (struct acpi_device *device); -static int acpi_processor_remove (struct acpi_device *device, int type); +static int acpi_processor_add(struct acpi_device *device); +static int acpi_processor_start(struct acpi_device *device); +static int acpi_processor_remove(struct acpi_device *device, int type); static int acpi_processor_info_open_fs(struct inode *inode, struct file *file); -static void acpi_processor_notify ( acpi_handle handle, u32 event, void *data); +static void acpi_processor_notify(acpi_handle handle, u32 event, void *data); static acpi_status acpi_processor_hotadd_init(acpi_handle handle, int *p_cpu); static int acpi_processor_handle_eject(struct acpi_processor *pr); static struct acpi_driver acpi_processor_driver = { - .name = ACPI_PROCESSOR_DRIVER_NAME, - .class = ACPI_PROCESSOR_CLASS, - .ids = ACPI_PROCESSOR_HID, - .ops = { - .add = acpi_processor_add, - .remove = acpi_processor_remove, - .start = acpi_processor_start, - }, + .name = "processor", + .class = ACPI_PROCESSOR_CLASS, + .ids = ACPI_PROCESSOR_HID, + .ops = { + .add = acpi_processor_add, + .remove = acpi_processor_remove, + .start = acpi_processor_start, + }, }; #define INSTALL_NOTIFY_HANDLER 1 #define UNINSTALL_NOTIFY_HANDLER 2 - -static struct file_operations acpi_processor_info_fops = { - .open = acpi_processor_info_open_fs, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, +static const struct file_operations acpi_processor_info_fops = { + .open = acpi_processor_info_open_fs, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, }; - -struct acpi_processor *processors[NR_CPUS]; -struct acpi_processor_errata errata; - +struct acpi_processor *processors[NR_CPUS]; +struct acpi_processor_errata errata __read_mostly; /* -------------------------------------------------------------------------- Errata Handling -------------------------------------------------------------------------- */ -static int -acpi_processor_errata_piix4 ( - struct pci_dev *dev) +static int acpi_processor_errata_piix4(struct pci_dev *dev) { - u8 rev = 0; - u8 value1 = 0; - u8 value2 = 0; + u8 rev = 0; + u8 value1 = 0; + u8 value2 = 0; - ACPI_FUNCTION_TRACE("acpi_processor_errata_piix4"); if (!dev) - return_VALUE(-EINVAL); + return -EINVAL; /* * Note that 'dev' references the PIIX4 ACPI Controller. @@ -188,8 +177,8 @@ acpi_processor_errata_piix4 ( * DMA activity. */ dev = pci_get_subsys(PCI_VENDOR_ID_INTEL, - PCI_DEVICE_ID_INTEL_82371AB, - PCI_ANY_ID, PCI_ANY_ID, NULL); + PCI_DEVICE_ID_INTEL_82371AB, + PCI_ANY_ID, PCI_ANY_ID, NULL); if (dev) { errata.piix4.bmisx = pci_resource_start(dev, 4); pci_dev_put(dev); @@ -205,8 +194,8 @@ acpi_processor_errata_piix4 ( * devices won't operate well if fast DMA is disabled. */ dev = pci_get_subsys(PCI_VENDOR_ID_INTEL, - PCI_DEVICE_ID_INTEL_82371AB_0, - PCI_ANY_ID, PCI_ANY_ID, NULL); + PCI_DEVICE_ID_INTEL_82371AB_0, + PCI_ANY_ID, PCI_ANY_ID, NULL); if (dev) { pci_read_config_byte(dev, 0x76, &value1); pci_read_config_byte(dev, 0x77, &value2); @@ -220,140 +209,118 @@ acpi_processor_errata_piix4 ( if (errata.piix4.bmisx) ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Bus master activity detection (BM-IDE) erratum enabled\n")); + "Bus master activity detection (BM-IDE) erratum enabled\n")); if (errata.piix4.fdma) ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Type-F DMA livelock erratum (C3 disabled)\n")); + "Type-F DMA livelock erratum (C3 disabled)\n")); - return_VALUE(0); + return 0; } - -int -acpi_processor_errata ( - struct acpi_processor *pr) +static int acpi_processor_errata(struct acpi_processor *pr) { - int result = 0; - struct pci_dev *dev = NULL; + int result = 0; + struct pci_dev *dev = NULL; - ACPI_FUNCTION_TRACE("acpi_processor_errata"); if (!pr) - return_VALUE(-EINVAL); + return -EINVAL; /* * PIIX4 */ dev = pci_get_subsys(PCI_VENDOR_ID_INTEL, - PCI_DEVICE_ID_INTEL_82371AB_3, PCI_ANY_ID, PCI_ANY_ID, NULL); + PCI_DEVICE_ID_INTEL_82371AB_3, PCI_ANY_ID, + PCI_ANY_ID, NULL); if (dev) { result = acpi_processor_errata_piix4(dev); pci_dev_put(dev); } - return_VALUE(result); + return result; } - /* -------------------------------------------------------------------------- - Common ACPI processor fucntions + Common ACPI processor functions -------------------------------------------------------------------------- */ /* * _PDC is required for a BIOS-OS handshake for most of the newer * ACPI processor features. */ - -int acpi_processor_set_pdc(struct acpi_processor *pr, - struct acpi_object_list *pdc_in) +static int acpi_processor_set_pdc(struct acpi_processor *pr) { - acpi_status status = AE_OK; - u32 arg0_buf[3]; - union acpi_object arg0 = {ACPI_TYPE_BUFFER}; - struct acpi_object_list no_object = {1, &arg0}; - struct acpi_object_list *pdc; + struct acpi_object_list *pdc_in = pr->pdc; + acpi_status status = AE_OK; - ACPI_FUNCTION_TRACE("acpi_processor_set_pdc"); - arg0.buffer.length = 12; - arg0.buffer.pointer = (u8 *) arg0_buf; - arg0_buf[0] = ACPI_PDC_REVISION_ID; - arg0_buf[1] = 0; - arg0_buf[2] = 0; + if (!pdc_in) + return status; - pdc = (pdc_in) ? pdc_in : &no_object; + status = acpi_evaluate_object(pr->handle, "_PDC", pdc_in, NULL); - status = acpi_evaluate_object(pr->handle, "_PDC", pdc, NULL); - - if ((ACPI_FAILURE(status)) && (pdc_in)) - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Error evaluating _PDC, using legacy perf. control...\n")); + if (ACPI_FAILURE(status)) + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Could not evaluate _PDC, using legacy perf. control...\n")); - return_VALUE(status); + return status; } - /* -------------------------------------------------------------------------- FS Interface (/proc) -------------------------------------------------------------------------- */ -static struct proc_dir_entry *acpi_processor_dir = NULL; +static struct proc_dir_entry *acpi_processor_dir = NULL; static int acpi_processor_info_seq_show(struct seq_file *seq, void *offset) { - struct acpi_processor *pr = (struct acpi_processor *)seq->private; + struct acpi_processor *pr = seq->private; - ACPI_FUNCTION_TRACE("acpi_processor_info_seq_show"); if (!pr) goto end; seq_printf(seq, "processor id: %d\n" - "acpi id: %d\n" - "bus mastering control: %s\n" - "power management: %s\n" - "throttling control: %s\n" - "limit interface: %s\n", - pr->id, - pr->acpi_id, - pr->flags.bm_control ? "yes" : "no", - pr->flags.power ? "yes" : "no", - pr->flags.throttling ? "yes" : "no", - pr->flags.limit ? "yes" : "no"); - -end: - return_VALUE(0); + "acpi id: %d\n" + "bus mastering control: %s\n" + "power management: %s\n" + "throttling control: %s\n" + "limit interface: %s\n", + pr->id, + pr->acpi_id, + pr->flags.bm_control ? "yes" : "no", + pr->flags.power ? "yes" : "no", + pr->flags.throttling ? "yes" : "no", + pr->flags.limit ? "yes" : "no"); + + end: + return 0; } static int acpi_processor_info_open_fs(struct inode *inode, struct file *file) { return single_open(file, acpi_processor_info_seq_show, - PDE(inode)->data); + PDE(inode)->data); } - -static int -acpi_processor_add_fs ( - struct acpi_device *device) +static int acpi_processor_add_fs(struct acpi_device *device) { - struct proc_dir_entry *entry = NULL; + struct proc_dir_entry *entry = NULL; - ACPI_FUNCTION_TRACE("acpi_processor_add_fs"); if (!acpi_device_dir(device)) { acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), - acpi_processor_dir); + acpi_processor_dir); if (!acpi_device_dir(device)) - return_VALUE(-ENODEV); + return -ENODEV; } acpi_device_dir(device)->owner = THIS_MODULE; /* 'info' [R] */ entry = create_proc_entry(ACPI_PROCESSOR_FILE_INFO, - S_IRUGO, acpi_device_dir(device)); + S_IRUGO, acpi_device_dir(device)); if (!entry) - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Unable to create '%s' fs entry\n", - ACPI_PROCESSOR_FILE_INFO)); + return -EIO; else { entry->proc_fops = &acpi_processor_info_fops; entry->data = acpi_driver_data(device); @@ -362,79 +329,169 @@ acpi_processor_add_fs ( /* 'throttling' [R/W] */ entry = create_proc_entry(ACPI_PROCESSOR_FILE_THROTTLING, - S_IFREG|S_IRUGO|S_IWUSR, acpi_device_dir(device)); + S_IFREG | S_IRUGO | S_IWUSR, + acpi_device_dir(device)); if (!entry) - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Unable to create '%s' fs entry\n", - ACPI_PROCESSOR_FILE_THROTTLING)); + return -EIO; else { entry->proc_fops = &acpi_processor_throttling_fops; - entry->proc_fops->write = acpi_processor_write_throttling; entry->data = acpi_driver_data(device); entry->owner = THIS_MODULE; } /* 'limit' [R/W] */ entry = create_proc_entry(ACPI_PROCESSOR_FILE_LIMIT, - S_IFREG|S_IRUGO|S_IWUSR, acpi_device_dir(device)); + S_IFREG | S_IRUGO | S_IWUSR, + acpi_device_dir(device)); if (!entry) - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Unable to create '%s' fs entry\n", - ACPI_PROCESSOR_FILE_LIMIT)); + return -EIO; else { entry->proc_fops = &acpi_processor_limit_fops; - entry->proc_fops->write = acpi_processor_write_limit; entry->data = acpi_driver_data(device); entry->owner = THIS_MODULE; } - return_VALUE(0); + return 0; } - -static int -acpi_processor_remove_fs ( - struct acpi_device *device) +static int acpi_processor_remove_fs(struct acpi_device *device) { - ACPI_FUNCTION_TRACE("acpi_processor_remove_fs"); if (acpi_device_dir(device)) { - remove_proc_entry(ACPI_PROCESSOR_FILE_INFO,acpi_device_dir(device)); + remove_proc_entry(ACPI_PROCESSOR_FILE_INFO, + acpi_device_dir(device)); remove_proc_entry(ACPI_PROCESSOR_FILE_THROTTLING, - acpi_device_dir(device)); - remove_proc_entry(ACPI_PROCESSOR_FILE_LIMIT,acpi_device_dir(device)); + acpi_device_dir(device)); + remove_proc_entry(ACPI_PROCESSOR_FILE_LIMIT, + acpi_device_dir(device)); remove_proc_entry(acpi_device_bid(device), acpi_processor_dir); acpi_device_dir(device) = NULL; } - return_VALUE(0); + return 0; } /* Use the acpiid in MADT to map cpus in case of SMP */ + #ifndef CONFIG_SMP -#define convert_acpiid_to_cpu(acpi_id) (0xff) +static int get_cpu_id(acpi_handle handle, u32 acpi_id) {return -1;} #else +static struct acpi_table_madt *madt; + +static int map_lapic_id(struct acpi_subtable_header *entry, + u32 acpi_id, int *apic_id) +{ + struct acpi_madt_local_apic *lapic = + (struct acpi_madt_local_apic *)entry; + if ((lapic->lapic_flags & ACPI_MADT_ENABLED) && + lapic->processor_id == acpi_id) { + *apic_id = lapic->id; + return 1; + } + return 0; +} + +static int map_lsapic_id(struct acpi_subtable_header *entry, + u32 acpi_id, int *apic_id) +{ + struct acpi_madt_local_sapic *lsapic = + (struct acpi_madt_local_sapic *)entry; + /* Only check enabled APICs*/ + if (lsapic->lapic_flags & ACPI_MADT_ENABLED) { + /* First check against id */ + if (lsapic->processor_id == acpi_id) { + *apic_id = (lsapic->id << 8) | lsapic->eid; + return 1; + /* Check against optional uid */ + } else if (entry->length >= 16 && + lsapic->uid == acpi_id) { + *apic_id = lsapic->uid; + return 1; + } + } + return 0; +} + #ifdef CONFIG_IA64 -#define arch_acpiid_to_apicid ia64_acpiid_to_sapicid #define arch_cpu_to_apicid ia64_cpu_to_sapicid -#define ARCH_BAD_APICID (0xffff) #else -#define arch_acpiid_to_apicid x86_acpiid_to_apicid #define arch_cpu_to_apicid x86_cpu_to_apicid -#define ARCH_BAD_APICID (0xff) #endif -static u8 convert_acpiid_to_cpu(u8 acpi_id) +static int map_madt_entry(u32 acpi_id) +{ + unsigned long madt_end, entry; + int apic_id = -1; + + if (!madt) + return apic_id; + + entry = (unsigned long)madt; + madt_end = entry + madt->header.length; + + /* Parse all entries looking for a match. */ + + entry += sizeof(struct acpi_table_madt); + while (entry + sizeof(struct acpi_subtable_header) < madt_end) { + struct acpi_subtable_header *header = + (struct acpi_subtable_header *)entry; + if (header->type == ACPI_MADT_TYPE_LOCAL_APIC) { + if (map_lapic_id(header, acpi_id, &apic_id)) + break; + } else if (header->type == ACPI_MADT_TYPE_LOCAL_SAPIC) { + if (map_lsapic_id(header, acpi_id, &apic_id)) + break; + } + entry += header->length; + } + return apic_id; +} + +static int map_mat_entry(acpi_handle handle, u32 acpi_id) +{ + struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; + union acpi_object *obj; + struct acpi_subtable_header *header; + int apic_id = -1; + + if (ACPI_FAILURE(acpi_evaluate_object(handle, "_MAT", NULL, &buffer))) + goto exit; + + if (!buffer.length || !buffer.pointer) + goto exit; + + obj = buffer.pointer; + if (obj->type != ACPI_TYPE_BUFFER || + obj->buffer.length < sizeof(struct acpi_subtable_header)) { + goto exit; + } + + header = (struct acpi_subtable_header *)obj->buffer.pointer; + if (header->type == ACPI_MADT_TYPE_LOCAL_APIC) { + map_lapic_id(header, acpi_id, &apic_id); + } else if (header->type == ACPI_MADT_TYPE_LOCAL_SAPIC) { + map_lsapic_id(header, acpi_id, &apic_id); + } + +exit: + if (buffer.pointer) + kfree(buffer.pointer); + return apic_id; +} + +static int get_cpu_id(acpi_handle handle, u32 acpi_id) { - u16 apic_id; int i; + int apic_id = -1; - apic_id = arch_acpiid_to_apicid[acpi_id]; - if (apic_id == ARCH_BAD_APICID) - return -1; + apic_id = map_mat_entry(handle, acpi_id); + if (apic_id == -1) + apic_id = map_madt_entry(acpi_id); + if (apic_id == -1) + return apic_id; - for (i = 0; i < NR_CPUS; i++) { + for (i = 0; i < NR_CPUS; ++i) { if (arch_cpu_to_apicid[i] == apic_id) return i; } @@ -446,20 +503,17 @@ static u8 convert_acpiid_to_cpu(u8 acpi_id) Driver Interface -------------------------------------------------------------------------- */ -static int -acpi_processor_get_info ( - struct acpi_processor *pr) +static int acpi_processor_get_info(struct acpi_processor *pr, unsigned has_uid) { - acpi_status status = 0; - union acpi_object object = {0}; - struct acpi_buffer buffer = {sizeof(union acpi_object), &object}; - u8 cpu_index; - static int cpu0_initialized; + acpi_status status = 0; + union acpi_object object = { 0 }; + struct acpi_buffer buffer = { sizeof(union acpi_object), &object }; + int cpu_index; + static int cpu0_initialized; - ACPI_FUNCTION_TRACE("acpi_processor_get_info"); if (!pr) - return_VALUE(-EINVAL); + return -EINVAL; if (num_online_cpus() > 1) errata.smp = TRUE; @@ -470,71 +524,78 @@ acpi_processor_get_info ( * Check to see if we have bus mastering arbitration control. This * is required for proper C3 usage (to maintain cache coherency). */ - if (acpi_fadt.V1_pm2_cnt_blk && acpi_fadt.pm2_cnt_len) { + 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 + "Bus mastering arbitration control present\n")); + } else ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "No bus mastering arbitration control\n")); + "No bus mastering arbitration control\n")); + + /* Check if it is a Device with HID and UID */ + if (has_uid) { + unsigned long value; + status = acpi_evaluate_integer(pr->handle, METHOD_NAME__UID, + NULL, &value); + if (ACPI_FAILURE(status)) { + printk(KERN_ERR PREFIX "Evaluating processor _UID\n"); + return -ENODEV; + } + pr->acpi_id = value; + } else { + /* + * Evalute the processor object. Note that it is common on SMP to + * have the first (boot) processor with a valid PBLK address while + * all others have a NULL address. + */ + status = acpi_evaluate_object(pr->handle, NULL, NULL, &buffer); + if (ACPI_FAILURE(status)) { + printk(KERN_ERR PREFIX "Evaluating processor object\n"); + return -ENODEV; + } - /* - * Evalute the processor object. Note that it is common on SMP to - * have the first (boot) processor with a valid PBLK address while - * all others have a NULL address. - */ - status = acpi_evaluate_object(pr->handle, NULL, NULL, &buffer); - if (ACPI_FAILURE(status)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Error evaluating processor object\n")); - return_VALUE(-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; + } + cpu_index = get_cpu_id(pr->handle, pr->acpi_id); + + /* 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; + /* - * TBD: Synch processor ID (via LAPIC/LSAPIC structures) on SMP. - * >>> 'acpi_get_processor_id(acpi_id, &id)' in arch/xxx/acpi.c + * 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. */ - pr->acpi_id = object.processor.proc_id; - - cpu_index = convert_acpiid_to_cpu(pr->acpi_id); - - /* Handle UP system running SMP kernel, with no LAPIC in MADT */ - if ( !cpu0_initialized && (cpu_index == 0xff) && - (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 (cpu_index >= NR_CPUS) { - if (ACPI_FAILURE(acpi_processor_hotadd_init(pr->handle, &pr->id))) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Error getting cpuindex for acpiid 0x%x\n", - pr->acpi_id)); - return_VALUE(-ENODEV); - } - } + if (pr->id == -1) { + if (ACPI_FAILURE + (acpi_processor_hotadd_init(pr->handle, &pr->id))) { + return -ENODEV; + } + } ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Processor [%d:%d]\n", pr->id, - pr->acpi_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) - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid PBLK length [%d]\n", - object.processor.pblk_length)); + 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_fadt.duty_offset; - pr->throttling.duty_width = acpi_fadt.duty_width; + pr->throttling.duty_offset = acpi_gbl_FADT.duty_offset; + pr->throttling.duty_width = acpi_gbl_FADT.duty_width; pr->pblk = object.processor.pblk_address; @@ -554,29 +615,41 @@ acpi_processor_get_info ( acpi_processor_get_throttling_info(pr); acpi_processor_get_limit_info(pr); - return_VALUE(0); + return 0; } -static int -acpi_processor_start( - struct acpi_device *device) +static void *processor_device_array[NR_CPUS]; + +static int __cpuinit acpi_processor_start(struct acpi_device *device) { - int result = 0; - acpi_status status = AE_OK; - struct acpi_processor *pr; + 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); + result = acpi_processor_get_info(pr, device->flags.unique_id); if (result) { /* Processor is physically not present */ - return_VALUE(0); + 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); @@ -584,50 +657,43 @@ acpi_processor_start( 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_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)); + acpi_device_name(device), acpi_device_bid(device)); printk(" %d throttling states", pr->throttling.state_count); printk(")\n"); } -end: + end: - return_VALUE(result); + return result; } - - -static void -acpi_processor_notify ( - acpi_handle handle, - u32 event, - void *data) +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; + struct acpi_processor *pr = data; + struct acpi_device *device = NULL; - ACPI_FUNCTION_TRACE("acpi_processor_notify"); if (!pr) - return_VOID; + return; if (acpi_bus_get_device(pr->handle, &device)) - return_VOID; + return; switch (event) { case ACPI_PROCESSOR_NOTIFY_PERFORMANCE: acpi_processor_ppc_has_changed(pr); acpi_bus_generate_event(device, event, - pr->performance_platform_limit); + pr->performance_platform_limit); break; case ACPI_PROCESSOR_NOTIFY_POWER: acpi_processor_cst_has_changed(pr); @@ -635,72 +701,58 @@ acpi_processor_notify ( break; default: ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Unsupported event [0x%x]\n", event)); + "Unsupported event [0x%x]\n", event)); break; } - return_VOID; + return; } - -static int -acpi_processor_add ( - struct acpi_device *device) +static int acpi_processor_add(struct acpi_device *device) { - struct acpi_processor *pr = NULL; + struct acpi_processor *pr = NULL; - ACPI_FUNCTION_TRACE("acpi_processor_add"); if (!device) - return_VALUE(-EINVAL); + return -EINVAL; - pr = kmalloc(sizeof(struct acpi_processor), GFP_KERNEL); + pr = kzalloc(sizeof(struct acpi_processor), GFP_KERNEL); if (!pr) - return_VALUE(-ENOMEM); - memset(pr, 0, sizeof(struct acpi_processor)); + return -ENOMEM; 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_VALUE(0); + return 0; } - -static int -acpi_processor_remove ( - struct acpi_device *device, - int type) +static int acpi_processor_remove(struct acpi_device *device, int type) { - acpi_status status = AE_OK; - struct acpi_processor *pr = NULL; + acpi_status status = AE_OK; + struct acpi_processor *pr = NULL; - ACPI_FUNCTION_TRACE("acpi_processor_remove"); if (!device || !acpi_driver_data(device)) - return_VALUE(-EINVAL); + return -EINVAL; - pr = (struct acpi_processor *) acpi_driver_data(device); + pr = acpi_driver_data(device); if (pr->id >= NR_CPUS) { kfree(pr); - return_VALUE(0); + return 0; } if (type == ACPI_BUS_REMOVAL_EJECT) { if (acpi_processor_handle_eject(pr)) - return_VALUE(-EINVAL); + return -EINVAL; } acpi_processor_power_exit(pr, device); status = acpi_remove_notify_handler(pr->handle, ACPI_DEVICE_NOTIFY, - acpi_processor_notify); - if (ACPI_FAILURE(status)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Error removing notify handler\n")); - } + acpi_processor_notify); acpi_processor_remove_fs(device); @@ -708,7 +760,7 @@ acpi_processor_remove ( kfree(pr); - return_VALUE(0); + return 0; } #ifdef CONFIG_ACPI_HOTPLUG_CPU @@ -718,79 +770,66 @@ acpi_processor_remove ( static int is_processor_present(acpi_handle handle); -static int -is_processor_present( - acpi_handle handle) +static int is_processor_present(acpi_handle handle) { - acpi_status status; - unsigned long sta = 0; + acpi_status status; + unsigned long sta = 0; - ACPI_FUNCTION_TRACE("is_processor_present"); status = acpi_evaluate_integer(handle, "_STA", NULL, &sta); - if (ACPI_FAILURE(status) || !(sta & ACPI_STA_PRESENT)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Processor Device is not present\n")); - return_VALUE(0); + if (ACPI_FAILURE(status) || !(sta & ACPI_STA_DEVICE_PRESENT)) { + ACPI_EXCEPTION((AE_INFO, status, "Processor Device is not present")); + return 0; } - return_VALUE(1); + return 1; } - static -int acpi_processor_device_add( - acpi_handle handle, - struct acpi_device **device) +int acpi_processor_device_add(acpi_handle handle, struct acpi_device **device) { - acpi_handle phandle; - struct acpi_device *pdev; - struct acpi_processor *pr; + acpi_handle phandle; + struct acpi_device *pdev; + struct acpi_processor *pr; - ACPI_FUNCTION_TRACE("acpi_processor_device_add"); if (acpi_get_parent(handle, &phandle)) { - return_VALUE(-ENODEV); + return -ENODEV; } if (acpi_bus_get_device(phandle, &pdev)) { - return_VALUE(-ENODEV); + return -ENODEV; } if (acpi_bus_add(device, pdev, handle, ACPI_BUS_TYPE_PROCESSOR)) { - return_VALUE(-ENODEV); + return -ENODEV; } acpi_bus_start(*device); pr = acpi_driver_data(*device); if (!pr) - return_VALUE(-ENODEV); + return -ENODEV; - if ((pr->id >=0) && (pr->id < NR_CPUS)) { - kobject_hotplug(&(*device)->kobj, KOBJ_ONLINE); + if ((pr->id >= 0) && (pr->id < NR_CPUS)) { + kobject_uevent(&(*device)->dev.kobj, KOBJ_ONLINE); } - return_VALUE(0); + return 0; } - static void -acpi_processor_hotplug_notify ( - acpi_handle handle, - u32 event, - void *data) +acpi_processor_hotplug_notify(acpi_handle handle, u32 event, void *data) { - struct acpi_processor *pr; - struct acpi_device *device = NULL; + struct acpi_processor *pr; + struct acpi_device *device = NULL; int result; - ACPI_FUNCTION_TRACE("acpi_processor_hotplug_notify"); switch (event) { case ACPI_NOTIFY_BUS_CHECK: case ACPI_NOTIFY_DEVICE_CHECK: printk("Processor driver received %s event\n", - (event==ACPI_NOTIFY_BUS_CHECK)? - "ACPI_NOTIFY_BUS_CHECK":"ACPI_NOTIFY_DEVICE_CHECK"); + (event == ACPI_NOTIFY_BUS_CHECK) ? + "ACPI_NOTIFY_BUS_CHECK" : "ACPI_NOTIFY_DEVICE_CHECK"); if (!is_processor_present(handle)) break; @@ -798,167 +837,151 @@ acpi_processor_hotplug_notify ( if (acpi_bus_get_device(handle, &device)) { result = acpi_processor_device_add(handle, &device); if (result) - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Unable to add the device\n")); + printk(KERN_ERR PREFIX + "Unable to add the device\n"); break; } pr = acpi_driver_data(device); if (!pr) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Driver data is NULL\n")); + printk(KERN_ERR PREFIX "Driver data is NULL\n"); break; } if (pr->id >= 0 && (pr->id < NR_CPUS)) { - kobject_hotplug(&device->kobj, KOBJ_OFFLINE); + kobject_uevent(&device->dev.kobj, KOBJ_OFFLINE); break; } result = acpi_processor_start(device); - if ((!result) && ((pr->id >=0) && (pr->id < NR_CPUS))) { - kobject_hotplug(&device->kobj, KOBJ_ONLINE); + if ((!result) && ((pr->id >= 0) && (pr->id < NR_CPUS))) { + kobject_uevent(&device->dev.kobj, KOBJ_ONLINE); } else { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Device [%s] failed to start\n", - acpi_device_bid(device))); + printk(KERN_ERR PREFIX "Device [%s] failed to start\n", + acpi_device_bid(device)); } - break; + break; case ACPI_NOTIFY_EJECT_REQUEST: - ACPI_DEBUG_PRINT((ACPI_DB_INFO,"received ACPI_NOTIFY_EJECT_REQUEST\n")); + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "received ACPI_NOTIFY_EJECT_REQUEST\n")); if (acpi_bus_get_device(handle, &device)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR,"Device don't exist, dropping EJECT\n")); + printk(KERN_ERR PREFIX + "Device don't exist, dropping EJECT\n"); break; } pr = acpi_driver_data(device); if (!pr) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR,"Driver data is NULL, dropping EJECT\n")); - return_VOID; + printk(KERN_ERR PREFIX + "Driver data is NULL, dropping EJECT\n"); + return; } if ((pr->id < NR_CPUS) && (cpu_present(pr->id))) - kobject_hotplug(&device->kobj, KOBJ_OFFLINE); + kobject_uevent(&device->dev.kobj, KOBJ_OFFLINE); break; default: ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Unsupported event [0x%x]\n", event)); + "Unsupported event [0x%x]\n", event)); break; } - return_VOID; + return; } static acpi_status processor_walk_namespace_cb(acpi_handle handle, - u32 lvl, - void *context, - void **rv) + u32 lvl, void *context, void **rv) { - acpi_status status; + acpi_status status; int *action = context; - acpi_object_type type = 0; + acpi_object_type type = 0; status = acpi_get_type(handle, &type); if (ACPI_FAILURE(status)) - return(AE_OK); + return (AE_OK); if (type != ACPI_TYPE_PROCESSOR) - return(AE_OK); + return (AE_OK); - switch(*action) { + switch (*action) { case INSTALL_NOTIFY_HANDLER: acpi_install_notify_handler(handle, - ACPI_SYSTEM_NOTIFY, - acpi_processor_hotplug_notify, - NULL); + ACPI_SYSTEM_NOTIFY, + acpi_processor_hotplug_notify, + NULL); break; case UNINSTALL_NOTIFY_HANDLER: acpi_remove_notify_handler(handle, - ACPI_SYSTEM_NOTIFY, - acpi_processor_hotplug_notify); + ACPI_SYSTEM_NOTIFY, + acpi_processor_hotplug_notify); break; default: break; } - return(AE_OK); + return (AE_OK); } - -static acpi_status -acpi_processor_hotadd_init( - acpi_handle handle, - int *p_cpu) +static acpi_status acpi_processor_hotadd_init(acpi_handle handle, int *p_cpu) { - ACPI_FUNCTION_TRACE("acpi_processor_hotadd_init"); if (!is_processor_present(handle)) { - return_VALUE(AE_ERROR); + return AE_ERROR; } if (acpi_map_lsapic(handle, p_cpu)) - return_VALUE(AE_ERROR); + return AE_ERROR; if (arch_register_cpu(*p_cpu)) { acpi_unmap_lsapic(*p_cpu); - return_VALUE(AE_ERROR); + return AE_ERROR; } - return_VALUE(AE_OK); + return AE_OK; } - -static int -acpi_processor_handle_eject(struct acpi_processor *pr) +static int acpi_processor_handle_eject(struct acpi_processor *pr) { if (cpu_online(pr->id)) { - return(-EINVAL); + return (-EINVAL); } arch_unregister_cpu(pr->id); acpi_unmap_lsapic(pr->id); - return(0); + return (0); } #else -static acpi_status -acpi_processor_hotadd_init( - acpi_handle handle, - int *p_cpu) +static acpi_status acpi_processor_hotadd_init(acpi_handle handle, int *p_cpu) { return AE_ERROR; } -static int -acpi_processor_handle_eject(struct acpi_processor *pr) +static int acpi_processor_handle_eject(struct acpi_processor *pr) { - return(-EINVAL); + return (-EINVAL); } #endif - static void acpi_processor_install_hotplug_notify(void) { #ifdef CONFIG_ACPI_HOTPLUG_CPU int action = INSTALL_NOTIFY_HANDLER; acpi_walk_namespace(ACPI_TYPE_PROCESSOR, - ACPI_ROOT_OBJECT, - ACPI_UINT32_MAX, - processor_walk_namespace_cb, - &action, NULL); + ACPI_ROOT_OBJECT, + ACPI_UINT32_MAX, + processor_walk_namespace_cb, &action, NULL); #endif } - static void acpi_processor_uninstall_hotplug_notify(void) { #ifdef CONFIG_ACPI_HOTPLUG_CPU int action = UNINSTALL_NOTIFY_HANDLER; acpi_walk_namespace(ACPI_TYPE_PROCESSOR, - ACPI_ROOT_OBJECT, - ACPI_UINT32_MAX, - processor_walk_namespace_cb, - &action, NULL); + ACPI_ROOT_OBJECT, + ACPI_UINT32_MAX, + processor_walk_namespace_cb, &action, NULL); #endif } @@ -968,25 +991,29 @@ void acpi_processor_uninstall_hotplug_notify(void) * ACPI, but needs symbols from this driver */ -static int __init -acpi_processor_init (void) +static int __init acpi_processor_init(void) { - int result = 0; + int result = 0; - ACPI_FUNCTION_TRACE("acpi_processor_init"); memset(&processors, 0, sizeof(processors)); memset(&errata, 0, sizeof(errata)); +#ifdef CONFIG_SMP + if (ACPI_FAILURE(acpi_get_table(ACPI_SIG_MADT, 0, + (struct acpi_table_header **)&madt))) + madt = NULL; +#endif + acpi_processor_dir = proc_mkdir(ACPI_PROCESSOR_CLASS, acpi_root_dir); if (!acpi_processor_dir) - return_VALUE(0); + return -ENOMEM; acpi_processor_dir->owner = THIS_MODULE; result = acpi_bus_register_driver(&acpi_processor_driver); if (result < 0) { remove_proc_entry(ACPI_PROCESSOR_CLASS, acpi_root_dir); - return_VALUE(0); + return result; } acpi_processor_install_hotplug_notify(); @@ -995,14 +1022,11 @@ acpi_processor_init (void) acpi_processor_ppc_init(); - return_VALUE(0); + return 0; } - -static void __exit -acpi_processor_exit (void) +static void __exit acpi_processor_exit(void) { - ACPI_FUNCTION_TRACE("acpi_processor_exit"); acpi_processor_ppc_exit(); @@ -1014,10 +1038,9 @@ acpi_processor_exit (void) remove_proc_entry(ACPI_PROCESSOR_CLASS, acpi_root_dir); - return_VOID; + return; } - module_init(acpi_processor_init); module_exit(acpi_processor_exit);