From 646b20e60dcbc6c5b6d167b2f7c944e9150f8375 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Mon, 22 Jun 2009 11:31:17 +0800 Subject: [PATCH] --- yaml --- r: 154159 b: refs/heads/master c: 35a7c64fbc77bab4ca8ae477e8ab278ccd679ce2 h: refs/heads/master i: 154157: 4665aedf14922c6f5bdb9ddb2688b330f0118ed3 154155: ec246ffb61eae4019f00ebfa4be7d6116d40632d 154151: 30fc84312592fdf0adee5f1bcb34b152a6370ee9 154143: 2e259b49cfa3b7a07e19d8f8df03bf0370d1a066 v: v3 --- [refs] | 2 +- trunk/drivers/acpi/blacklist.c | 16 +++ trunk/drivers/acpi/pci_root.c | 185 +++++++++++++++++++++++---------- 3 files changed, 145 insertions(+), 58 deletions(-) diff --git a/[refs] b/[refs] index 0c2e0900adb5..73a5ba8bda8a 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 0705495d9010048e293013d9d129cf723363a0a8 +refs/heads/master: 35a7c64fbc77bab4ca8ae477e8ab278ccd679ce2 diff --git a/trunk/drivers/acpi/blacklist.c b/trunk/drivers/acpi/blacklist.c index 09c69806c1fc..f6baa77deefb 100644 --- a/trunk/drivers/acpi/blacklist.c +++ b/trunk/drivers/acpi/blacklist.c @@ -192,6 +192,22 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = { DMI_MATCH(DMI_PRODUCT_NAME, "ESPRIMO Mobile V5505"), }, }, + { + .callback = dmi_disable_osi_vista, + .ident = "Sony VGN-NS10J_S", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), + DMI_MATCH(DMI_PRODUCT_NAME, "VGN-NS10J_S"), + }, + }, + { + .callback = dmi_disable_osi_vista, + .ident = "Sony VGN-SR290J", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), + DMI_MATCH(DMI_PRODUCT_NAME, "Sony VGN-SR290J"), + }, + }, /* * BIOS invocation of _OSI(Linux) is almost always a BIOS bug. diff --git a/trunk/drivers/acpi/pci_root.c b/trunk/drivers/acpi/pci_root.c index e95b5ac2e609..196f97d00956 100644 --- a/trunk/drivers/acpi/pci_root.c +++ b/trunk/drivers/acpi/pci_root.c @@ -63,10 +63,9 @@ static struct acpi_driver acpi_pci_root_driver = { struct acpi_pci_root { struct list_head node; - struct acpi_device *device; + struct acpi_device * device; + struct acpi_pci_id id; struct pci_bus *bus; - u16 segment; - u8 bus_nr; u32 osc_support_set; /* _OSC state of support bits */ u32 osc_control_set; /* _OSC state of control bits */ @@ -83,7 +82,7 @@ static DEFINE_MUTEX(osc_lock); int acpi_pci_register_driver(struct acpi_pci_driver *driver) { int n = 0; - struct acpi_pci_root *root; + struct list_head *entry; struct acpi_pci_driver **pptr = &sub_driver; while (*pptr) @@ -93,7 +92,9 @@ int acpi_pci_register_driver(struct acpi_pci_driver *driver) if (!driver->add) return 0; - list_for_each_entry(root, &acpi_pci_roots, node) { + list_for_each(entry, &acpi_pci_roots) { + struct acpi_pci_root *root; + root = list_entry(entry, struct acpi_pci_root, node); driver->add(root->device->handle); n++; } @@ -105,7 +106,7 @@ EXPORT_SYMBOL(acpi_pci_register_driver); void acpi_pci_unregister_driver(struct acpi_pci_driver *driver) { - struct acpi_pci_root *root; + struct list_head *entry; struct acpi_pci_driver **pptr = &sub_driver; while (*pptr) { @@ -119,19 +120,23 @@ void acpi_pci_unregister_driver(struct acpi_pci_driver *driver) if (!driver->remove) return; - list_for_each_entry(root, &acpi_pci_roots, node) + list_for_each(entry, &acpi_pci_roots) { + struct acpi_pci_root *root; + root = list_entry(entry, struct acpi_pci_root, node); driver->remove(root->device->handle); + } } EXPORT_SYMBOL(acpi_pci_unregister_driver); acpi_handle acpi_get_pci_rootbridge_handle(unsigned int seg, unsigned int bus) { - struct acpi_pci_root *root; + struct acpi_pci_root *tmp; - list_for_each_entry(root, &acpi_pci_roots, node) - if ((root->segment == (u16) seg) && (root->bus_nr == (u16) bus)) - return root->device->handle; + list_for_each_entry(tmp, &acpi_pci_roots, node) { + if ((tmp->id.segment == (u16) seg) && (tmp->id.bus == (u16) bus)) + return tmp->device->handle; + } return NULL; } @@ -156,22 +161,19 @@ get_root_bridge_busnr_callback(struct acpi_resource *resource, void *data) return AE_OK; } -static acpi_status try_get_root_bridge_busnr(acpi_handle handle, - unsigned long long *bus) +static acpi_status try_get_root_bridge_busnr(acpi_handle handle, int *busnum) { acpi_status status; - int busnum; - busnum = -1; + *busnum = -1; status = acpi_walk_resources(handle, METHOD_NAME__CRS, - get_root_bridge_busnr_callback, &busnum); + get_root_bridge_busnr_callback, busnum); if (ACPI_FAILURE(status)) return status; /* Check if we really get a bus number from _CRS */ - if (busnum == -1) + if (*busnum == -1) return AE_ERROR; - *bus = busnum; return AE_OK; } @@ -296,7 +298,6 @@ static acpi_status acpi_pci_osc_support(struct acpi_pci_root *root, u32 flags) static struct acpi_pci_root *acpi_pci_find_root(acpi_handle handle) { struct acpi_pci_root *root; - list_for_each_entry(root, &acpi_pci_roots, node) { if (root->device->handle == handle) return root; @@ -362,42 +363,25 @@ EXPORT_SYMBOL(acpi_pci_osc_control_set); static int __devinit acpi_pci_root_add(struct acpi_device *device) { - unsigned long long segment, bus; - acpi_status status; - int result; - struct acpi_pci_root *root; - acpi_handle handle; + int result = 0; + struct acpi_pci_root *root = NULL; + struct acpi_pci_root *tmp; + acpi_status status = AE_OK; + unsigned long long value = 0; + acpi_handle handle = NULL; struct acpi_device *child; u32 flags, base_flags; - segment = 0; - status = acpi_evaluate_integer(device->handle, METHOD_NAME__SEG, NULL, - &segment); - if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { - printk(KERN_ERR PREFIX "can't evaluate _SEG\n"); - return -ENODEV; - } - /* Check _CRS first, then _BBN. If no _BBN, default to zero. */ - bus = 0; - status = try_get_root_bridge_busnr(device->handle, &bus); - if (ACPI_FAILURE(status)) { - status = acpi_evaluate_integer(device->handle, METHOD_NAME__BBN, NULL, &bus); - if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { - printk(KERN_ERR PREFIX - "no bus number in _CRS and can't evaluate _BBN\n"); - return -ENODEV; - } - } + if (!device) + return -EINVAL; root = kzalloc(sizeof(struct acpi_pci_root), GFP_KERNEL); if (!root) return -ENOMEM; - INIT_LIST_HEAD(&root->node); + root->device = device; - root->segment = segment & 0xFFFF; - root->bus_nr = bus & 0xFF; strcpy(acpi_device_name(device), ACPI_PCI_ROOT_DEVICE_NAME); strcpy(acpi_device_class(device), ACPI_PCI_ROOT_CLASS); device->driver_data = root; @@ -411,6 +395,79 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device) flags = base_flags = OSC_PCI_SEGMENT_GROUPS_SUPPORT; acpi_pci_osc_support(root, flags); + /* + * Segment + * ------- + * Obtained via _SEG, if exists, otherwise assumed to be zero (0). + */ + status = acpi_evaluate_integer(device->handle, METHOD_NAME__SEG, NULL, + &value); + switch (status) { + case AE_OK: + root->id.segment = (u16) value; + break; + case AE_NOT_FOUND: + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Assuming segment 0 (no _SEG)\n")); + root->id.segment = 0; + break; + default: + ACPI_EXCEPTION((AE_INFO, status, "Evaluating _SEG")); + result = -ENODEV; + goto end; + } + + /* + * Bus + * --- + * Obtained via _BBN, if exists, otherwise assumed to be zero (0). + */ + status = acpi_evaluate_integer(device->handle, METHOD_NAME__BBN, NULL, + &value); + switch (status) { + case AE_OK: + root->id.bus = (u16) value; + break; + case AE_NOT_FOUND: + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Assuming bus 0 (no _BBN)\n")); + root->id.bus = 0; + break; + default: + ACPI_EXCEPTION((AE_INFO, status, "Evaluating _BBN")); + result = -ENODEV; + goto end; + } + + /* Some systems have wrong _BBN */ + list_for_each_entry(tmp, &acpi_pci_roots, node) { + if ((tmp->id.segment == root->id.segment) + && (tmp->id.bus == root->id.bus)) { + int bus = 0; + acpi_status status; + + printk(KERN_ERR PREFIX + "Wrong _BBN value, reboot" + " and use option 'pci=noacpi'\n"); + + status = try_get_root_bridge_busnr(device->handle, &bus); + if (ACPI_FAILURE(status)) + break; + if (bus != root->id.bus) { + printk(KERN_INFO PREFIX + "PCI _CRS %d overrides _BBN 0\n", bus); + root->id.bus = bus; + } + break; + } + } + /* + * Device & Function + * ----------------- + * Obtained from _ADR (which has already been evaluated for us). + */ + root->id.device = device->pnp.bus_address >> 16; + root->id.function = device->pnp.bus_address & 0xFFFF; + /* * TBD: Need PCI interface for enumeration/configuration of roots. */ @@ -420,7 +477,7 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device) printk(KERN_INFO PREFIX "%s [%s] (%04x:%02x)\n", acpi_device_name(device), acpi_device_bid(device), - root->segment, root->bus_nr); + root->id.segment, root->id.bus); /* * Scan the Root Bridge @@ -429,11 +486,11 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device) * PCI namespace does not get created until this call is made (and * thus the root bridge's pci_dev does not exist). */ - root->bus = pci_acpi_scan_root(device, segment, bus); + root->bus = pci_acpi_scan_root(device, root->id.segment, root->id.bus); if (!root->bus) { printk(KERN_ERR PREFIX "Bus %04x:%02x not present in PCI namespace\n", - root->segment, root->bus_nr); + root->id.segment, root->id.bus); result = -ENODEV; goto end; } @@ -474,28 +531,42 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device) if (flags != base_flags) acpi_pci_osc_support(root, flags); - return 0; + end: + if (result) { + if (!list_empty(&root->node)) + list_del(&root->node); + kfree(root); + } -end: - if (!list_empty(&root->node)) - list_del(&root->node); - kfree(root); return result; } static int acpi_pci_root_start(struct acpi_device *device) { - struct acpi_pci_root *root = acpi_driver_data(device); + struct acpi_pci_root *root; - pci_bus_add_devices(root->bus); - return 0; + + list_for_each_entry(root, &acpi_pci_roots, node) { + if (root->device == device) { + pci_bus_add_devices(root->bus); + return 0; + } + } + return -ENODEV; } static int acpi_pci_root_remove(struct acpi_device *device, int type) { - struct acpi_pci_root *root = acpi_driver_data(device); + struct acpi_pci_root *root = NULL; + + + if (!device || !acpi_driver_data(device)) + return -EINVAL; + + root = acpi_driver_data(device); kfree(root); + return 0; }