static int 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 = get_cpu_id(pr->handle, device_declaration, 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; /* * 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 (acpi_processor_hotadd_init(pr->handle, &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 acpi_thermal_add_fs ( struct acpi_device *device) { struct proc_dir_entry *entry = NULL; ACPI_FUNCTION_TRACE("acpi_thermal_add_fs"); if (!acpi_device_dir(device)) { acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), acpi_thermal_dir); if (!acpi_device_dir(device)) return_VALUE(-ENODEV); } /* 'state' [R] */ entry = create_proc_entry(ACPI_THERMAL_FILE_STATE, S_IRUGO, acpi_device_dir(device)); if (!entry) ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unable to create '%s' fs entry\n", ACPI_THERMAL_FILE_STATE)); else { entry->read_proc = acpi_thermal_read_state; entry->data = acpi_driver_data(device); } /* 'temperature' [R] */ entry = create_proc_entry(ACPI_THERMAL_FILE_TEMPERATURE, S_IRUGO, acpi_device_dir(device)); if (!entry) ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unable to create '%s' fs entry\n", ACPI_THERMAL_FILE_TEMPERATURE)); else { entry->read_proc = acpi_thermal_read_temperature; entry->data = acpi_driver_data(device); } /* 'trip_points' [R/W] */ entry = create_proc_entry(ACPI_THERMAL_FILE_TRIP_POINTS, 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_THERMAL_FILE_POLLING_FREQ)); else { entry->read_proc = acpi_thermal_read_trip_points; entry->write_proc = acpi_thermal_write_trip_points; entry->data = acpi_driver_data(device); } /* 'cooling_mode' [R/W] */ entry = create_proc_entry(ACPI_THERMAL_FILE_COOLING_MODE, 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_THERMAL_FILE_COOLING_MODE)); else { entry->read_proc = acpi_thermal_read_cooling_mode; entry->write_proc = acpi_thermal_write_cooling_mode; entry->data = acpi_driver_data(device); } /* 'polling_frequency' [R/W] */ entry = create_proc_entry(ACPI_THERMAL_FILE_POLLING_FREQ, 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_THERMAL_FILE_POLLING_FREQ)); else { entry->read_proc = acpi_thermal_read_polling; entry->write_proc = acpi_thermal_write_polling; entry->data = acpi_driver_data(device); } return_VALUE(0); }
static int acpi_system_add ( struct acpi_device *device) { int result = 0; acpi_status status = AE_OK; struct acpi_system *system = NULL; u8 i = 0; ACPI_FUNCTION_TRACE("acpi_system_add"); if (!device) return_VALUE(-EINVAL); system = kmalloc(sizeof(struct acpi_system), GFP_KERNEL); if (!system) return_VALUE(-ENOMEM); memset(system, 0, sizeof(struct acpi_system)); system->handle = device->handle; sprintf(acpi_device_name(device), "%s", ACPI_SYSTEM_DEVICE_NAME); sprintf(acpi_device_class(device), "%s", ACPI_SYSTEM_CLASS); acpi_driver_data(device) = system; result = acpi_system_add_fs(device); if (result) goto end; printk(KERN_INFO PREFIX "%s [%s] (supports", acpi_device_name(device), acpi_device_bid(device)); for (i=0; i<ACPI_S_STATE_COUNT; i++) { u8 type_a, type_b; status = acpi_get_sleep_type_data(i, &type_a, &type_b); switch (i) { case ACPI_STATE_S4: if (acpi_gbl_FACS->S4bios_f && 0 != acpi_gbl_FADT->smi_cmd) { printk(" S4bios"); system->states[i] = 1; } /* no break */ default: if (ACPI_SUCCESS(status)) { system->states[i] = 1; printk(" S%d", i); } } } printk(")\n"); #ifdef CONFIG_PM /* Install the soft-off (S5) handler. */ if (system->states[ACPI_STATE_S5]) { pm_power_off = acpi_power_off; register_sysrq_key('o', &sysrq_acpi_poweroff_op); } #endif end: if (result) kfree(system); return_VALUE(result); }
static int acpi_processor_get_info(struct acpi_device *device) { union acpi_object object = { 0 }; struct acpi_buffer buffer = { sizeof(union acpi_object), &object }; struct acpi_processor *pr = acpi_driver_data(device); int device_declaration = 0; acpi_status status = AE_OK; static int cpu0_initialized; unsigned long long value; acpi_processor_errata(); /* * 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)) { dev_err(&device->dev, "Failed to evaluate processor object (0x%x)\n", status); return -ENODEV; } pr->acpi_id = object.processor.proc_id; } else { /* * Declared with "Device" statement; match _UID. * Note that we don't handle string _UIDs yet. */ status = acpi_evaluate_integer(pr->handle, METHOD_NAME__UID, NULL, &value); if (ACPI_FAILURE(status)) { dev_err(&device->dev, "Failed to evaluate processor _UID (0x%x)\n", status); return -ENODEV; } device_declaration = 1; pr->acpi_id = value; } if (acpi_duplicate_processor_id(pr->acpi_id)) { dev_err(&device->dev, "Failed to get unique processor _UID (0x%x)\n", pr->acpi_id); return -ENODEV; } pr->phys_id = acpi_get_phys_id(pr->handle, device_declaration, pr->acpi_id); if (invalid_phys_cpuid(pr->phys_id)) acpi_handle_debug(pr->handle, "failed to get CPU physical ID.\n"); pr->id = acpi_map_cpuid(pr->phys_id, pr->acpi_id); if (!cpu0_initialized && !acpi_has_cpu_in_madt()) { cpu0_initialized = 1; /* * Handle UP system running SMP kernel, with no CPU * entry in MADT */ if (invalid_logical_cpuid(pr->id) && (num_online_cpus() == 1)) pr->id = 0; } /* * 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. * * NOTE: Even if the processor has a cpuid, it may not be present * because cpuid <-> apicid mapping is persistent now. */ if (invalid_logical_cpuid(pr->id) || !cpu_present(pr->id)) { int ret = acpi_processor_hotadd_init(pr); if (ret) return ret; } /* * 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) dev_err(&device->dev, "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; } /* * If ACPI describes a slot number for this CPU, we can use it to * ensure we get the right value in the "physical id" field * of /proc/cpuinfo */ status = acpi_evaluate_integer(pr->handle, "_SUN", NULL, &value); if (ACPI_SUCCESS(status)) arch_fix_phys_package_id(pr->id, value); return 0; }
static int __devinit snd_card_mpu401_probe(int dev, struct acpi_device *device) { snd_card_t *card; int err; #ifdef USE_ACPI_PNP if (!device) { #endif if (port[dev] == SNDRV_AUTO_PORT) { snd_printk(KERN_ERR "specify port\n"); return -EINVAL; } if (irq[dev] == SNDRV_AUTO_IRQ) { snd_printk(KERN_ERR "specify or disable IRQ port\n"); return -EINVAL; } #ifdef USE_ACPI_PNP } #endif #ifdef USE_ACPI_PNP if (device && (err = snd_mpu401_acpi_pnp(dev, device)) < 0) return err; #endif card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); if (card == NULL) return -ENOMEM; strcpy(card->driver, "MPU-401 UART"); strcpy(card->shortname, card->driver); sprintf(card->longname, "%s at 0x%lx, ", card->shortname, port[dev]); if (irq[dev] >= 0) { sprintf(card->longname + strlen(card->longname), "IRQ %d", irq[dev]); } else { strcat(card->longname, "polled"); } #ifdef USE_ACPI_PNP if (device) { strcat(card->longname, ", bus id "); strlcat(card->longname, acpi_device_bid(device), sizeof(card->longname)); } #endif if (snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401, port[dev], 0, irq[dev], irq[dev] >= 0 ? SA_INTERRUPT : 0, NULL) < 0) { printk(KERN_ERR "MPU401 not detected at 0x%lx\n", port[dev]); snd_card_free(card); return -ENODEV; } if ((err = snd_card_register(card)) < 0) { snd_card_free(card); return err; } #ifdef USE_ACPI_PNP if (device) acpi_driver_data(device) = card; else #endif snd_mpu401_legacy_cards[dev] = card; ++cards; return 0; }
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")); } /* _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_VALUE(result); }
static void acpi_processor_hotplug_notify(acpi_handle handle, u32 event, void *data) { 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"); if (!is_processor_present(handle)) break; 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")); break; } pr = acpi_driver_data(device); if (!pr) { ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Driver data is NULL\n")); break; } if (pr->id >= 0 && (pr->id < NR_CPUS)) { kobject_uevent(&device->kobj, KOBJ_OFFLINE); break; } result = acpi_processor_start(device); if ((!result) && ((pr->id >= 0) && (pr->id < NR_CPUS))) { kobject_uevent(&device->kobj, KOBJ_ONLINE); } else { ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Device [%s] failed to start\n", acpi_device_bid(device))); } break; case ACPI_NOTIFY_EJECT_REQUEST: 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")); break; } pr = acpi_driver_data(device); if (!pr) { ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Driver data is NULL, dropping EJECT\n")); return_VOID; } if ((pr->id < NR_CPUS) && (cpu_present(pr->id))) kobject_uevent(&device->kobj, KOBJ_OFFLINE); break; default: ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Unsupported event [0x%x]\n", event)); break; } return_VOID; }
static int __init pnpacpi_add_device(struct acpi_device *device) { acpi_handle temp = NULL; acpi_status status; struct pnp_id *dev_id; struct pnp_dev *dev; status = acpi_get_handle(device->handle, "_CRS", &temp); if (ACPI_FAILURE(status) || !ispnpidacpi(acpi_device_hid(device)) || is_exclusive_device(device)) return 0; dev = kzalloc(sizeof(struct pnp_dev), GFP_KERNEL); if (!dev) { pnp_err("Out of memory"); return -ENOMEM; } dev->data = device->handle; /* .enabled means the device can decode the resources */ dev->active = device->status.enabled; status = acpi_get_handle(device->handle, "_SRS", &temp); if (ACPI_SUCCESS(status)) dev->capabilities |= PNP_CONFIGURABLE; dev->capabilities |= PNP_READ; if (device->flags.dynamic_status) dev->capabilities |= PNP_WRITE; if (device->flags.removable) dev->capabilities |= PNP_REMOVABLE; status = acpi_get_handle(device->handle, "_DIS", &temp); if (ACPI_SUCCESS(status)) dev->capabilities |= PNP_DISABLE; dev->protocol = &pnpacpi_protocol; if (strlen(acpi_device_name(device))) strncpy(dev->name, acpi_device_name(device), sizeof(dev->name)); else strncpy(dev->name, acpi_device_bid(device), sizeof(dev->name)); dev->number = num; /* set the initial values for the PnP device */ dev_id = kzalloc(sizeof(struct pnp_id), GFP_KERNEL); if (!dev_id) goto err; pnpidacpi_to_pnpid(acpi_device_hid(device), dev_id->id); pnp_add_id(dev_id, dev); if (dev->active) { /* parse allocated resource */ status = pnpacpi_parse_allocated_resource(device->handle, &dev->res); if (ACPI_FAILURE(status) && (status != AE_NOT_FOUND)) { pnp_err("PnPACPI: METHOD_NAME__CRS failure for %s", dev_id->id); goto err1; } } if (dev->capabilities & PNP_CONFIGURABLE) { status = pnpacpi_parse_resource_option_data(device->handle, dev); if (ACPI_FAILURE(status) && (status != AE_NOT_FOUND)) { pnp_err("PnPACPI: METHOD_NAME__PRS failure for %s", dev_id->id); goto err1; } } /* parse compatible ids */ if (device->flags.compatible_ids) { struct acpi_compatible_id_list *cid_list = device->pnp.cid_list; int i; for (i = 0; i < cid_list->count; i++) { if (!ispnpidacpi(cid_list->id[i].value)) continue; dev_id = kzalloc(sizeof(struct pnp_id), GFP_KERNEL); if (!dev_id) continue; pnpidacpi_to_pnpid(cid_list->id[i].value, dev_id->id); pnp_add_id(dev_id, dev); } } /* clear out the damaged flags */ if (!dev->active) pnp_init_resource_table(&dev->res); pnp_add_device(dev); num++; return AE_OK; err1: kfree(dev_id); err: kfree(dev); return -EINVAL; }
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 acpi_button_add_fs ( struct acpi_device *device) { struct proc_dir_entry *entry = NULL; struct acpi_button *button = NULL; ACPI_FUNCTION_TRACE("acpi_button_add_fs"); if (!device || !acpi_driver_data(device)) return_VALUE(-EINVAL); button = acpi_driver_data(device); switch (button->type) { case ACPI_BUTTON_TYPE_POWER: case ACPI_BUTTON_TYPE_POWERF: entry = proc_mkdir(ACPI_BUTTON_SUBCLASS_POWER, acpi_button_dir); break; case ACPI_BUTTON_TYPE_SLEEP: case ACPI_BUTTON_TYPE_SLEEPF: entry = proc_mkdir(ACPI_BUTTON_SUBCLASS_SLEEP, acpi_button_dir); break; case ACPI_BUTTON_TYPE_LID: entry = proc_mkdir(ACPI_BUTTON_SUBCLASS_LID, acpi_button_dir); break; } acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), entry); if (!acpi_device_dir(device)) return_VALUE(-ENODEV); /* 'info' [R] */ entry = create_proc_entry(ACPI_BUTTON_FILE_INFO, S_IRUGO, acpi_device_dir(device)); if (!entry) ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unable to create '%s' fs entry\n", ACPI_BUTTON_FILE_INFO)); else { entry->read_proc = acpi_button_read_info; entry->data = acpi_driver_data(device); } if (button->type==ACPI_BUTTON_TYPE_LID){ /* 'state' [R] */ entry = create_proc_entry(ACPI_BUTTON_FILE_STATE, S_IRUGO, acpi_device_dir(device)); if (!entry) ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unable to create '%s' fs entry\n", ACPI_BUTTON_FILE_STATE)); else { entry->read_proc = acpi_button_lid_read_state; entry->data = acpi_driver_data(device); } } return_VALUE(0); }
static int acpi_button_add ( struct acpi_device *device) { int result = 0; acpi_status status = AE_OK; struct acpi_button *button = NULL; static struct acpi_device *power_button; static struct acpi_device *sleep_button; static struct acpi_device *lid_button; ACPI_FUNCTION_TRACE("acpi_button_add"); if (!device) return_VALUE(-EINVAL); button = kmalloc(sizeof(struct acpi_button), GFP_KERNEL); if (!button) return_VALUE(-ENOMEM); memset(button, 0, sizeof(struct acpi_button)); button->device = device; button->handle = device->handle; acpi_driver_data(device) = button; /* * Determine the button type (via hid), as fixed-feature buttons * need to be handled a bit differently than generic-space. */ if (!strcmp(acpi_device_hid(device), ACPI_BUTTON_HID_POWER)) { button->type = ACPI_BUTTON_TYPE_POWER; sprintf(acpi_device_name(device), "%s", ACPI_BUTTON_DEVICE_NAME_POWER); sprintf(acpi_device_class(device), "%s/%s", ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_POWER); } else if (!strcmp(acpi_device_hid(device), ACPI_BUTTON_HID_POWERF)) { button->type = ACPI_BUTTON_TYPE_POWERF; sprintf(acpi_device_name(device), "%s", ACPI_BUTTON_DEVICE_NAME_POWERF); sprintf(acpi_device_class(device), "%s/%s", ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_POWER); } else if (!strcmp(acpi_device_hid(device), ACPI_BUTTON_HID_SLEEP)) { button->type = ACPI_BUTTON_TYPE_SLEEP; sprintf(acpi_device_name(device), "%s", ACPI_BUTTON_DEVICE_NAME_SLEEP); sprintf(acpi_device_class(device), "%s/%s", ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_SLEEP); } else if (!strcmp(acpi_device_hid(device), ACPI_BUTTON_HID_SLEEPF)) { button->type = ACPI_BUTTON_TYPE_SLEEPF; sprintf(acpi_device_name(device), "%s", ACPI_BUTTON_DEVICE_NAME_SLEEPF); sprintf(acpi_device_class(device), "%s/%s", ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_SLEEP); } else if (!strcmp(acpi_device_hid(device), ACPI_BUTTON_HID_LID)) { button->type = ACPI_BUTTON_TYPE_LID; sprintf(acpi_device_name(device), "%s", ACPI_BUTTON_DEVICE_NAME_LID); sprintf(acpi_device_class(device), "%s/%s", ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_LID); } else { ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unsupported hid [%s]\n", acpi_device_hid(device))); result = -ENODEV; goto end; } /* * Ensure only one button of each type is used. */ switch (button->type) { case ACPI_BUTTON_TYPE_POWER: case ACPI_BUTTON_TYPE_POWERF: if (!power_button) power_button = device; else { kfree(button); return_VALUE(-ENODEV); } break; case ACPI_BUTTON_TYPE_SLEEP: case ACPI_BUTTON_TYPE_SLEEPF: if (!sleep_button) sleep_button = device; else { kfree(button); return_VALUE(-ENODEV); } break; case ACPI_BUTTON_TYPE_LID: if (!lid_button) lid_button = device; else { kfree(button); return_VALUE(-ENODEV); } break; } result = acpi_button_add_fs(device); if (result) goto end; switch (button->type) { case ACPI_BUTTON_TYPE_POWERF: status = acpi_install_fixed_event_handler ( ACPI_EVENT_POWER_BUTTON, acpi_button_notify_fixed, button); break; case ACPI_BUTTON_TYPE_SLEEPF: status = acpi_install_fixed_event_handler ( ACPI_EVENT_SLEEP_BUTTON, acpi_button_notify_fixed, button); break; default: status = acpi_install_notify_handler ( button->handle, ACPI_DEVICE_NOTIFY, acpi_button_notify, button); break; } if (ACPI_FAILURE(status)) { ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error installing notify handler\n")); result = -ENODEV; goto end; } printk(KERN_INFO PREFIX "%s [%s]\n", acpi_device_name(device), acpi_device_bid(device)); end: if (result) { acpi_button_remove_fs(device); kfree(button); } return_VALUE(result); }
static int __init pnpacpi_add_device(struct acpi_device *device) { acpi_handle temp = NULL; acpi_status status; struct pnp_dev *dev; /* * If a PnPacpi device is not present , the device * driver should not be loaded. */ status = acpi_get_handle(device->handle, "_CRS", &temp); if (ACPI_FAILURE(status) || !ispnpidacpi(acpi_device_hid(device)) || is_exclusive_device(device) || (!device->status.present)) return 0; dev = pnp_alloc_dev(&pnpacpi_protocol, num, acpi_device_hid(device)); if (!dev) return -ENOMEM; dev->data = device->handle; /* .enabled means the device can decode the resources */ dev->active = device->status.enabled; status = acpi_get_handle(device->handle, "_SRS", &temp); if (ACPI_SUCCESS(status)) dev->capabilities |= PNP_CONFIGURABLE; dev->capabilities |= PNP_READ; if (device->flags.dynamic_status && (dev->capabilities & PNP_CONFIGURABLE)) dev->capabilities |= PNP_WRITE; if (device->flags.removable) dev->capabilities |= PNP_REMOVABLE; status = acpi_get_handle(device->handle, "_DIS", &temp); if (ACPI_SUCCESS(status)) dev->capabilities |= PNP_DISABLE; if (strlen(acpi_device_name(device))) strncpy(dev->name, acpi_device_name(device), sizeof(dev->name)); else strncpy(dev->name, acpi_device_bid(device), sizeof(dev->name)); if (dev->active) pnpacpi_parse_allocated_resource(dev); if (dev->capabilities & PNP_CONFIGURABLE) pnpacpi_parse_resource_option_data(dev); if (device->flags.compatible_ids) { struct acpi_compatible_id_list *cid_list = device->pnp.cid_list; int i; for (i = 0; i < cid_list->count; i++) { if (!ispnpidacpi(cid_list->id[i].value)) continue; pnp_add_id(dev, cid_list->id[i].value); } } /* clear out the damaged flags */ if (!dev->active) pnp_init_resources(dev); pnp_add_device(dev); num++; return AE_OK; }
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, device->flags.unique_id); 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 (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); #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); 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 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); 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)) { status = acpi_evaluate_object(pr->handle, NULL, NULL, &buffer); if (ACPI_FAILURE(status)) { printk(KERN_ERR PREFIX "Evaluating processor object\n"); return -ENODEV; } pr->acpi_id = object.processor.proc_id; } else { 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 = acpi_get_cpuid(pr->handle, device_declaration, pr->acpi_id); if (!cpu0_initialized && (cpu_index == -1) && (num_online_cpus() == 1)) { cpu_index = 0; } cpu0_initialized = 1; pr->id = cpu_index; if (pr->id == -1) { if (ACPI_FAILURE(acpi_processor_hotadd_init(pr))) return -ENODEV; } 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; request_region(pr->throttling.address, 6, "ACPI CPU throttle"); } 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; }
int acpi_pci_bind ( struct acpi_device *device) { int result = 0; acpi_status status = AE_OK; struct acpi_pci_data *data = NULL; struct acpi_pci_data *pdata = NULL; char pathname[ACPI_PATHNAME_MAX] = {0}; struct acpi_buffer buffer = {ACPI_PATHNAME_MAX, pathname}; acpi_handle handle = NULL; ACPI_FUNCTION_TRACE("acpi_pci_bind"); if (!device || !device->parent) return_VALUE(-EINVAL); data = kmalloc(sizeof(struct acpi_pci_data), GFP_KERNEL); if (!data) return_VALUE(-ENOMEM); memset(data, 0, sizeof(struct acpi_pci_data)); acpi_get_name(device->handle, ACPI_FULL_PATHNAME, &buffer); ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Binding PCI device [%s]...\n", pathname)); /* * Segment & Bus * ------------- * These are obtained via the parent device's ACPI-PCI context. */ status = acpi_get_data(device->parent->handle, acpi_pci_data_handler, (void**) &pdata); if (ACPI_FAILURE(status) || !pdata || !pdata->bus) { ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid ACPI-PCI context for parent device %s\n", acpi_device_bid(device->parent))); result = -ENODEV; goto end; } data->id.segment = pdata->id.segment; data->id.bus = pdata->bus->number; /* * Device & Function * ----------------- * These are simply obtained from the device's _ADR method. Note * that a value of zero is valid. */ data->id.device = device->pnp.bus_address >> 16; data->id.function = device->pnp.bus_address & 0xFFFF; ACPI_DEBUG_PRINT((ACPI_DB_INFO, "...to %02x:%02x:%02x.%02x\n", data->id.segment, data->id.bus, data->id.device, data->id.function)); /* * TBD: Support slot devices (e.g. function=0xFFFF). */ /* * Locate PCI Device * ----------------- * Locate matching device in PCI namespace. If it doesn't exist * this typically means that the device isn't currently inserted * (e.g. docking station, port replicator, etc.). */ data->dev = pci_find_slot(data->id.bus, PCI_DEVFN(data->id.device, data->id.function)); if (!data->dev) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device %02x:%02x:%02x.%02x not present in PCI namespace\n", data->id.segment, data->id.bus, data->id.device, data->id.function)); result = -ENODEV; goto end; } if (!data->dev->bus) { ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Device %02x:%02x:%02x.%02x has invalid 'bus' field\n", data->id.segment, data->id.bus, data->id.device, data->id.function)); result = -ENODEV; goto end; } /* * PCI Bridge? * ----------- * If so, set the 'bus' field and install the 'bind' function to * facilitate callbacks for all of its children. */ if (data->dev->subordinate) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device %02x:%02x:%02x.%02x is a PCI bridge\n", data->id.segment, data->id.bus, data->id.device, data->id.function)); data->bus = data->dev->subordinate; device->ops.bind = acpi_pci_bind; } /* * Attach ACPI-PCI Context * ----------------------- * Thus binding the ACPI and PCI devices. */ status = acpi_attach_data(device->handle, acpi_pci_data_handler, data); if (ACPI_FAILURE(status)) { ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unable to attach ACPI-PCI context to device %s\n", acpi_device_bid(device))); result = -ENODEV; goto end; } /* * PCI Routing Table * ----------------- * Evaluate and parse _PRT, if exists. This code is independent of * PCI bridges (above) to allow parsing of _PRT objects within the * scope of non-bridge devices. Note that _PRTs within the scope of * a PCI bridge assume the bridge's subordinate bus number. * * TBD: Can _PRTs exist within the scope of non-bridge PCI devices? */ status = acpi_get_handle(device->handle, METHOD_NAME__PRT, &handle); if (ACPI_SUCCESS(status)) { if (data->bus) /* PCI-PCI bridge */ acpi_pci_irq_add_prt(device->handle, data->id.segment, data->bus->number); else /* non-bridge PCI device */ acpi_pci_irq_add_prt(device->handle, data->id.segment, data->id.bus); } end: if (result) kfree(data); return_VALUE(result); }
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; }