diff options
Diffstat (limited to 'drivers/acpi')
| -rw-r--r-- | drivers/acpi/blacklist.c | 16 | ||||
| -rw-r--r-- | drivers/acpi/glue.c | 40 | ||||
| -rw-r--r-- | drivers/acpi/osl.c | 25 | ||||
| -rw-r--r-- | drivers/acpi/pci_bind.c | 313 | ||||
| -rw-r--r-- | drivers/acpi/pci_irq.c | 17 | ||||
| -rw-r--r-- | drivers/acpi/pci_root.c | 297 | ||||
| -rw-r--r-- | drivers/acpi/power.c | 28 | ||||
| -rw-r--r-- | drivers/acpi/processor_core.c | 45 | ||||
| -rw-r--r-- | drivers/acpi/processor_idle.c | 47 | ||||
| -rw-r--r-- | drivers/acpi/scan.c | 69 | ||||
| -rw-r--r-- | drivers/acpi/video.c | 61 | ||||
| -rw-r--r-- | drivers/acpi/video_detect.c | 9 | 
12 files changed, 382 insertions, 585 deletions
diff --git a/drivers/acpi/blacklist.c b/drivers/acpi/blacklist.c index 09c69806c1f..f6baa77deef 100644 --- a/drivers/acpi/blacklist.c +++ b/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/drivers/acpi/glue.c b/drivers/acpi/glue.c index 8bd2c2a6884..a8a5c29958c 100644 --- a/drivers/acpi/glue.c +++ b/drivers/acpi/glue.c @@ -140,46 +140,6 @@ struct device *acpi_get_physical_device(acpi_handle handle)  EXPORT_SYMBOL(acpi_get_physical_device); -/* ToDo: When a PCI bridge is found, return the PCI device behind the bridge - *       This should work in general, but did not on a Lenovo T61 for the - *	 graphics card. But this must be fixed when the PCI device is - *       bound and the kernel device struct is attached to the acpi device - * Note: A success call will increase reference count by one - *       Do call put_device(dev) on the returned device then - */ -struct device *acpi_get_physical_pci_device(acpi_handle handle) -{ -	struct device *dev; -	long long device_id; -	acpi_status status; - -	status = -		acpi_evaluate_integer(handle, "_ADR", NULL, &device_id); - -	if (ACPI_FAILURE(status)) -		return NULL; - -	/* We need to attempt to determine whether the _ADR refers to a -	   PCI device or not. There's no terribly good way to do this, -	   so the best we can hope for is to assume that there'll never -	   be a device in the host bridge */ -	if (device_id >= 0x10000) { -		/* It looks like a PCI device. Does it exist? */ -		dev = acpi_get_physical_device(handle); -	} else { -		/* It doesn't look like a PCI device. Does its parent -		   exist? */ -		acpi_handle phandle; -		if (acpi_get_parent(handle, &phandle)) -			return NULL; -		dev = acpi_get_physical_device(phandle); -	} -	if (!dev) -		return NULL; -	return dev; -} -EXPORT_SYMBOL(acpi_get_physical_pci_device); -  static int acpi_bind_one(struct device *dev, acpi_handle handle)  {  	struct acpi_device *acpi_dev; diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index d916bea729f..71670719d61 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -79,6 +79,7 @@ static acpi_osd_handler acpi_irq_handler;  static void *acpi_irq_context;  static struct workqueue_struct *kacpid_wq;  static struct workqueue_struct *kacpi_notify_wq; +static struct workqueue_struct *kacpi_hotplug_wq;  struct acpi_res_list {  	resource_size_t start; @@ -192,8 +193,10 @@ acpi_status acpi_os_initialize1(void)  {  	kacpid_wq = create_singlethread_workqueue("kacpid");  	kacpi_notify_wq = create_singlethread_workqueue("kacpi_notify"); +	kacpi_hotplug_wq = create_singlethread_workqueue("kacpi_hotplug");  	BUG_ON(!kacpid_wq);  	BUG_ON(!kacpi_notify_wq); +	BUG_ON(!kacpi_hotplug_wq);  	return AE_OK;  } @@ -206,6 +209,7 @@ acpi_status acpi_os_terminate(void)  	destroy_workqueue(kacpid_wq);  	destroy_workqueue(kacpi_notify_wq); +	destroy_workqueue(kacpi_hotplug_wq);  	return AE_OK;  } @@ -716,6 +720,7 @@ static acpi_status __acpi_os_execute(acpi_execute_type type,  	acpi_status status = AE_OK;  	struct acpi_os_dpc *dpc;  	struct workqueue_struct *queue; +	work_func_t func;  	int ret;  	ACPI_DEBUG_PRINT((ACPI_DB_EXEC,  			  "Scheduling function [%p(%p)] for deferred execution.\n", @@ -740,15 +745,17 @@ static acpi_status __acpi_os_execute(acpi_execute_type type,  	dpc->function = function;  	dpc->context = context; -	if (!hp) { -		INIT_WORK(&dpc->work, acpi_os_execute_deferred); -		queue = (type == OSL_NOTIFY_HANDLER) ? -			kacpi_notify_wq : kacpid_wq; -		ret = queue_work(queue, &dpc->work); -	} else { -		INIT_WORK(&dpc->work, acpi_os_execute_hp_deferred); -		ret = schedule_work(&dpc->work); -	} +	/* +	 * We can't run hotplug code in keventd_wq/kacpid_wq/kacpid_notify_wq +	 * because the hotplug code may call driver .remove() functions, +	 * which invoke flush_scheduled_work/acpi_os_wait_events_complete +	 * to flush these workqueues. +	 */ +	queue = hp ? kacpi_hotplug_wq : +		(type == OSL_NOTIFY_HANDLER ? kacpi_notify_wq : kacpid_wq); +	func = hp ? acpi_os_execute_hp_deferred : acpi_os_execute_deferred; +	INIT_WORK(&dpc->work, func); +	ret = queue_work(queue, &dpc->work);  	if (!ret) {  		printk(KERN_ERR PREFIX diff --git a/drivers/acpi/pci_bind.c b/drivers/acpi/pci_bind.c index bc46de3d967..a5a77b78a72 100644 --- a/drivers/acpi/pci_bind.c +++ b/drivers/acpi/pci_bind.c @@ -24,12 +24,7 @@   */  #include <linux/kernel.h> -#include <linux/module.h> -#include <linux/init.h>  #include <linux/types.h> -#include <linux/proc_fs.h> -#include <linux/spinlock.h> -#include <linux/pm.h>  #include <linux/pci.h>  #include <linux/acpi.h>  #include <acpi/acpi_bus.h> @@ -38,310 +33,76 @@  #define _COMPONENT		ACPI_PCI_COMPONENT  ACPI_MODULE_NAME("pci_bind"); -struct acpi_pci_data { -	struct acpi_pci_id id; -	struct pci_bus *bus; -	struct pci_dev *dev; -}; - -static int acpi_pci_unbind(struct acpi_device *device); - -static void acpi_pci_data_handler(acpi_handle handle, u32 function, -				  void *context) -{ - -	/* TBD: Anything we need to do here? */ - -	return; -} - -/** - * acpi_get_pci_id - * ------------------ - * This function is used by the ACPI Interpreter (a.k.a. Core Subsystem) - * to resolve PCI information for ACPI-PCI devices defined in the namespace. - * This typically occurs when resolving PCI operation region information. - */ -acpi_status acpi_get_pci_id(acpi_handle handle, struct acpi_pci_id *id) +static int acpi_pci_unbind(struct acpi_device *device)  { -	int result = 0; -	acpi_status status = AE_OK; -	struct acpi_device *device = NULL; -	struct acpi_pci_data *data = NULL; - - -	if (!id) -		return AE_BAD_PARAMETER; - -	result = acpi_bus_get_device(handle, &device); -	if (result) { -		printk(KERN_ERR PREFIX -			    "Invalid ACPI Bus context for device %s\n", -			    acpi_device_bid(device)); -		return AE_NOT_EXIST; -	} - -	status = acpi_get_data(handle, acpi_pci_data_handler, (void **)&data); -	if (ACPI_FAILURE(status) || !data) { -		ACPI_EXCEPTION((AE_INFO, status, -				"Invalid ACPI-PCI context for device %s", -				acpi_device_bid(device))); -		return status; -	} +	struct pci_dev *dev; -	*id = data->id; +	dev = acpi_get_pci_dev(device->handle); +	if (!dev || !dev->subordinate) +		goto out; -	/* -	   id->segment = data->id.segment; -	   id->bus = data->id.bus; -	   id->device = data->id.device; -	   id->function = data->id.function; -	 */ +	acpi_pci_irq_del_prt(dev->subordinate); -	ACPI_DEBUG_PRINT((ACPI_DB_INFO, -			  "Device %s has PCI address %04x:%02x:%02x.%d\n", -			  acpi_device_bid(device), id->segment, id->bus, -			  id->device, id->function)); +	device->ops.bind = NULL; +	device->ops.unbind = NULL; -	return AE_OK; +out: +	pci_dev_put(dev); +	return 0;  } -EXPORT_SYMBOL(acpi_get_pci_id); - -int acpi_pci_bind(struct acpi_device *device) +static int acpi_pci_bind(struct acpi_device *device)  { -	int result = 0;  	acpi_status status; -	struct acpi_pci_data *data; -	struct acpi_pci_data *pdata; -	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };  	acpi_handle handle; +	struct pci_bus *bus; +	struct pci_dev *dev; -	if (!device || !device->parent) -		return -EINVAL; - -	data = kzalloc(sizeof(struct acpi_pci_data), GFP_KERNEL); -	if (!data) -		return -ENOMEM; - -	status = acpi_get_name(device->handle, ACPI_FULL_PATHNAME, &buffer); -	if (ACPI_FAILURE(status)) { -		kfree(data); -		return -ENODEV; -	} - -	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Binding PCI device [%s]...\n", -			  (char *)buffer.pointer)); - -	/*  -	 * 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_EXCEPTION((AE_INFO, status, -				"Invalid ACPI-PCI context for parent device %s", -				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 %04x:%02x:%02x.%d\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_get_slot(pdata->bus, -				PCI_DEVFN(data->id.device, data->id.function)); -	if (!data->dev) { -		ACPI_DEBUG_PRINT((ACPI_DB_INFO, -				  "Device %04x:%02x:%02x.%d 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) { -		printk(KERN_ERR PREFIX -			    "Device %04x:%02x:%02x.%d has invalid 'bus' field\n", -			    data->id.segment, data->id.bus, -			    data->id.device, data->id.function); -		result = -ENODEV; -		goto end; -	} +	dev = acpi_get_pci_dev(device->handle); +	if (!dev) +		return 0;  	/* -	 * PCI Bridge? -	 * ----------- -	 * If so, set the 'bus' field and install the 'bind' function to  -	 * facilitate callbacks for all of its children. +	 * Install the 'bind' function to facilitate callbacks for +	 * children of the P2P bridge.  	 */ -	if (data->dev->subordinate) { +	if (dev->subordinate) {  		ACPI_DEBUG_PRINT((ACPI_DB_INFO,  				  "Device %04x:%02x:%02x.%d is a PCI bridge\n", -				  data->id.segment, data->id.bus, -				  data->id.device, data->id.function)); -		data->bus = data->dev->subordinate; +				  pci_domain_nr(dev->bus), dev->bus->number, +				  PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn)));  		device->ops.bind = acpi_pci_bind;  		device->ops.unbind = acpi_pci_unbind;  	}  	/* -	 * 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_EXCEPTION((AE_INFO, status, -				"Unable to attach ACPI-PCI context to device %s", -				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. +	 * Evaluate and parse _PRT, if exists.  This code allows 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: -	kfree(buffer.pointer); -	if (result) { -		pci_dev_put(data->dev); -		kfree(data); -	} -	return result; -} - -static int acpi_pci_unbind(struct acpi_device *device) -{ -	int result = 0; -	acpi_status status; -	struct acpi_pci_data *data; -	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; - - -	if (!device || !device->parent) -		return -EINVAL; - -	status = acpi_get_name(device->handle, ACPI_FULL_PATHNAME, &buffer);  	if (ACPI_FAILURE(status)) -		return -ENODEV; +		goto out; -	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Unbinding PCI device [%s]...\n", -			  (char *) buffer.pointer)); -	kfree(buffer.pointer); +	if (dev->subordinate) +		bus = dev->subordinate; +	else +		bus = dev->bus; -	status = -	    acpi_get_data(device->handle, acpi_pci_data_handler, -			  (void **)&data); -	if (ACPI_FAILURE(status)) { -		result = -ENODEV; -		goto end; -	} +	acpi_pci_irq_add_prt(device->handle, bus); -	status = acpi_detach_data(device->handle, acpi_pci_data_handler); -	if (ACPI_FAILURE(status)) { -		ACPI_EXCEPTION((AE_INFO, status, -				"Unable to detach data from device %s", -				acpi_device_bid(device))); -		result = -ENODEV; -		goto end; -	} -	if (data->dev->subordinate) { -		acpi_pci_irq_del_prt(data->id.segment, data->bus->number); -	} -	pci_dev_put(data->dev); -	kfree(data); - -      end: -	return result; +out: +	pci_dev_put(dev); +	return 0;  } -int -acpi_pci_bind_root(struct acpi_device *device, -		   struct acpi_pci_id *id, struct pci_bus *bus) +int acpi_pci_bind_root(struct acpi_device *device)  { -	int result = 0; -	acpi_status status; -	struct acpi_pci_data *data = NULL; -	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; - -	if (!device || !id || !bus) { -		return -EINVAL; -	} - -	data = kzalloc(sizeof(struct acpi_pci_data), GFP_KERNEL); -	if (!data) -		return -ENOMEM; - -	data->id = *id; -	data->bus = bus;  	device->ops.bind = acpi_pci_bind;  	device->ops.unbind = acpi_pci_unbind; -	status = acpi_get_name(device->handle, ACPI_FULL_PATHNAME, &buffer); -	if (ACPI_FAILURE(status)) { -		kfree (data); -		return -ENODEV; -	} - -	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Binding PCI root bridge [%s] to " -			"%04x:%02x\n", (char *)buffer.pointer, -			id->segment, id->bus)); - -	status = acpi_attach_data(device->handle, acpi_pci_data_handler, data); -	if (ACPI_FAILURE(status)) { -		ACPI_EXCEPTION((AE_INFO, status, -				"Unable to attach ACPI-PCI context to device %s", -				(char *)buffer.pointer)); -		result = -ENODEV; -		goto end; -	} - -      end: -	kfree(buffer.pointer); -	if (result != 0) -		kfree(data); - -	return result; +	return 0;  } diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c index 2faa9e2ac89..b794eb88ab9 100644 --- a/drivers/acpi/pci_irq.c +++ b/drivers/acpi/pci_irq.c @@ -182,7 +182,7 @@ static void do_prt_fixups(struct acpi_prt_entry *entry,  	}  } -static int acpi_pci_irq_add_entry(acpi_handle handle, int segment, int bus, +static int acpi_pci_irq_add_entry(acpi_handle handle, struct pci_bus *bus,  				  struct acpi_pci_routing_table *prt)  {  	struct acpi_prt_entry *entry; @@ -196,8 +196,8 @@ static int acpi_pci_irq_add_entry(acpi_handle handle, int segment, int bus,  	 * 1=INTA, 2=INTB.  We use the PCI encoding throughout, so convert  	 * it here.  	 */ -	entry->id.segment = segment; -	entry->id.bus = bus; +	entry->id.segment = pci_domain_nr(bus); +	entry->id.bus = bus->number;  	entry->id.device = (prt->address >> 16) & 0xFFFF;  	entry->pin = prt->pin + 1; @@ -242,7 +242,7 @@ static int acpi_pci_irq_add_entry(acpi_handle handle, int segment, int bus,  	return 0;  } -int acpi_pci_irq_add_prt(acpi_handle handle, int segment, int bus) +int acpi_pci_irq_add_prt(acpi_handle handle, struct pci_bus *bus)  {  	acpi_status status;  	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; @@ -271,7 +271,7 @@ int acpi_pci_irq_add_prt(acpi_handle handle, int segment, int bus)  	entry = buffer.pointer;  	while (entry && (entry->length > 0)) { -		acpi_pci_irq_add_entry(handle, segment, bus, entry); +		acpi_pci_irq_add_entry(handle, bus, entry);  		entry = (struct acpi_pci_routing_table *)  		    ((unsigned long)entry + entry->length);  	} @@ -280,16 +280,17 @@ int acpi_pci_irq_add_prt(acpi_handle handle, int segment, int bus)  	return 0;  } -void acpi_pci_irq_del_prt(int segment, int bus) +void acpi_pci_irq_del_prt(struct pci_bus *bus)  {  	struct acpi_prt_entry *entry, *tmp;  	printk(KERN_DEBUG  	       "ACPI: Delete PCI Interrupt Routing Table for %04x:%02x\n", -	       segment, bus); +	       pci_domain_nr(bus), bus->number);  	spin_lock(&acpi_prt_lock);  	list_for_each_entry_safe(entry, tmp, &acpi_prt_list, list) { -		if (segment == entry->id.segment && bus == entry->id.bus) { +		if (pci_domain_nr(bus) == entry->id.segment +			&& bus->number == entry->id.bus) {  			list_del(&entry->list);  			kfree(entry);  		} diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index 196f97d0095..8a5bf3b356f 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -63,9 +63,10 @@ static struct acpi_driver acpi_pci_root_driver = {  struct acpi_pci_root {  	struct list_head node; -	struct acpi_device * device; -	struct acpi_pci_id id; +	struct acpi_device *device;  	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 */ @@ -82,7 +83,7 @@ static DEFINE_MUTEX(osc_lock);  int acpi_pci_register_driver(struct acpi_pci_driver *driver)  {  	int n = 0; -	struct list_head *entry; +	struct acpi_pci_root *root;  	struct acpi_pci_driver **pptr = &sub_driver;  	while (*pptr) @@ -92,9 +93,7 @@ int acpi_pci_register_driver(struct acpi_pci_driver *driver)  	if (!driver->add)  		return 0; -	list_for_each(entry, &acpi_pci_roots) { -		struct acpi_pci_root *root; -		root = list_entry(entry, struct acpi_pci_root, node); +	list_for_each_entry(root, &acpi_pci_roots, node) {  		driver->add(root->device->handle);  		n++;  	} @@ -106,7 +105,7 @@ EXPORT_SYMBOL(acpi_pci_register_driver);  void acpi_pci_unregister_driver(struct acpi_pci_driver *driver)  { -	struct list_head *entry; +	struct acpi_pci_root *root;  	struct acpi_pci_driver **pptr = &sub_driver;  	while (*pptr) { @@ -120,28 +119,48 @@ void acpi_pci_unregister_driver(struct acpi_pci_driver *driver)  	if (!driver->remove)  		return; -	list_for_each(entry, &acpi_pci_roots) { -		struct acpi_pci_root *root; -		root = list_entry(entry, struct acpi_pci_root, node); +	list_for_each_entry(root, &acpi_pci_roots, 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 *tmp; +	struct acpi_pci_root *root; -	list_for_each_entry(tmp, &acpi_pci_roots, node) { -		if ((tmp->id.segment == (u16) seg) && (tmp->id.bus == (u16) bus)) -			return tmp->device->handle; -	} +	list_for_each_entry(root, &acpi_pci_roots, node) +		if ((root->segment == (u16) seg) && (root->bus_nr == (u16) bus)) +			return root->device->handle;  	return NULL;		  }  EXPORT_SYMBOL_GPL(acpi_get_pci_rootbridge_handle); +/** + * acpi_is_root_bridge - determine whether an ACPI CA node is a PCI root bridge + * @handle - the ACPI CA node in question. + * + * Note: we could make this API take a struct acpi_device * instead, but + * for now, it's more convenient to operate on an acpi_handle. + */ +int acpi_is_root_bridge(acpi_handle handle) +{ +	int ret; +	struct acpi_device *device; + +	ret = acpi_bus_get_device(handle, &device); +	if (ret) +		return 0; + +	ret = acpi_match_device_ids(device, root_device_ids); +	if (ret) +		return 0; +	else +		return 1; +} +EXPORT_SYMBOL_GPL(acpi_is_root_bridge); +  static acpi_status  get_root_bridge_busnr_callback(struct acpi_resource *resource, void *data)  { @@ -161,19 +180,22 @@ 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, int *busnum) +static acpi_status try_get_root_bridge_busnr(acpi_handle handle, +					     unsigned long long *bus)  {  	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;  } @@ -298,6 +320,7 @@ 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; @@ -305,6 +328,87 @@ static struct acpi_pci_root *acpi_pci_find_root(acpi_handle handle)  	return NULL;  } +struct acpi_handle_node { +	struct list_head node; +	acpi_handle handle; +}; + +/** + * acpi_get_pci_dev - convert ACPI CA handle to struct pci_dev + * @handle: the handle in question + * + * Given an ACPI CA handle, the desired PCI device is located in the + * list of PCI devices. + * + * If the device is found, its reference count is increased and this + * function returns a pointer to its data structure.  The caller must + * decrement the reference count by calling pci_dev_put(). + * If no device is found, %NULL is returned. + */ +struct pci_dev *acpi_get_pci_dev(acpi_handle handle) +{ +	int dev, fn; +	unsigned long long adr; +	acpi_status status; +	acpi_handle phandle; +	struct pci_bus *pbus; +	struct pci_dev *pdev = NULL; +	struct acpi_handle_node *node, *tmp; +	struct acpi_pci_root *root; +	LIST_HEAD(device_list); + +	/* +	 * Walk up the ACPI CA namespace until we reach a PCI root bridge. +	 */ +	phandle = handle; +	while (!acpi_is_root_bridge(phandle)) { +		node = kzalloc(sizeof(struct acpi_handle_node), GFP_KERNEL); +		if (!node) +			goto out; + +		INIT_LIST_HEAD(&node->node); +		node->handle = phandle; +		list_add(&node->node, &device_list); + +		status = acpi_get_parent(phandle, &phandle); +		if (ACPI_FAILURE(status)) +			goto out; +	} + +	root = acpi_pci_find_root(phandle); +	if (!root) +		goto out; + +	pbus = root->bus; + +	/* +	 * Now, walk back down the PCI device tree until we return to our +	 * original handle. Assumes that everything between the PCI root +	 * bridge and the device we're looking for must be a P2P bridge. +	 */ +	list_for_each_entry(node, &device_list, node) { +		acpi_handle hnd = node->handle; +		status = acpi_evaluate_integer(hnd, "_ADR", NULL, &adr); +		if (ACPI_FAILURE(status)) +			goto out; +		dev = (adr >> 16) & 0xffff; +		fn  = adr & 0xffff; + +		pdev = pci_get_slot(pbus, PCI_DEVFN(dev, fn)); +		if (hnd == handle) +			break; + +		pbus = pdev->subordinate; +		pci_dev_put(pdev); +	} +out: +	list_for_each_entry_safe(node, tmp, &device_list, node) +		kfree(node); + +	return pdev; +} +EXPORT_SYMBOL_GPL(acpi_get_pci_dev); +  /**   * acpi_pci_osc_control_set - commit requested control to Firmware   * @handle: acpi_handle for the target ACPI object @@ -363,31 +467,46 @@ EXPORT_SYMBOL(acpi_pci_osc_control_set);  static int __devinit acpi_pci_root_add(struct acpi_device *device)  { -	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; +	unsigned long long segment, bus; +	acpi_status status; +	int result; +	struct acpi_pci_root *root; +	acpi_handle handle;  	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; +	} -	if (!device) -		return -EINVAL; +	/* 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; +		} +	}  	root = kzalloc(sizeof(struct acpi_pci_root), GFP_KERNEL);  	if (!root)  		return -ENOMEM; -	INIT_LIST_HEAD(&root->node); +	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; -	device->ops.bind = acpi_pci_bind; -  	/*  	 * All supported architectures that use ACPI have support for  	 * PCI domains, so we indicate this in _OSC support capabilities. @@ -395,79 +514,6 @@ 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.  	 */ @@ -477,7 +523,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->id.segment, root->id.bus); +	       root->segment, root->bus_nr);  	/*  	 * Scan the Root Bridge @@ -486,11 +532,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, root->id.segment, root->id.bus); +	root->bus = pci_acpi_scan_root(device, segment, bus);  	if (!root->bus) {  		printk(KERN_ERR PREFIX  			    "Bus %04x:%02x not present in PCI namespace\n", -			    root->id.segment, root->id.bus); +			    root->segment, root->bus_nr);  		result = -ENODEV;  		goto end;  	} @@ -500,7 +546,7 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device)  	 * -----------------------  	 * Thus binding the ACPI and PCI devices.  	 */ -	result = acpi_pci_bind_root(device, &root->id, root->bus); +	result = acpi_pci_bind_root(device);  	if (result)  		goto end; @@ -511,8 +557,7 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device)  	 */  	status = acpi_get_handle(device->handle, METHOD_NAME__PRT, &handle);  	if (ACPI_SUCCESS(status)) -		result = acpi_pci_irq_add_prt(device->handle, root->id.segment, -					      root->id.bus); +		result = acpi_pci_irq_add_prt(device->handle, root->bus);  	/*  	 * Scan and bind all _ADR-Based Devices @@ -531,42 +576,28 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device)  	if (flags != base_flags)  		acpi_pci_osc_support(root, flags); -      end: -	if (result) { -		if (!list_empty(&root->node)) -			list_del(&root->node); -		kfree(root); -	} +	return 0; +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; +	struct acpi_pci_root *root = acpi_driver_data(device); - -	list_for_each_entry(root, &acpi_pci_roots, node) { -		if (root->device == device) { -			pci_bus_add_devices(root->bus); -			return 0; -		} -	} -	return -ENODEV; +	pci_bus_add_devices(root->bus); +	return 0;  }  static int acpi_pci_root_remove(struct acpi_device *device, int type)  { -	struct acpi_pci_root *root = NULL; - - -	if (!device || !acpi_driver_data(device)) -		return -EINVAL; - -	root = acpi_driver_data(device); +	struct acpi_pci_root *root = acpi_driver_data(device);  	kfree(root); -  	return 0;  } diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c index 56665a63bf1..d74365d4a6e 100644 --- a/drivers/acpi/power.c +++ b/drivers/acpi/power.c @@ -194,7 +194,7 @@ static int acpi_power_get_list_state(struct acpi_handle_list *list, int *state)  static int acpi_power_on(acpi_handle handle, struct acpi_device *dev)  { -	int result = 0, state; +	int result = 0;  	int found = 0;  	acpi_status status = AE_OK;  	struct acpi_power_resource *resource = NULL; @@ -236,18 +236,6 @@ static int acpi_power_on(acpi_handle handle, struct acpi_device *dev)  	if (ACPI_FAILURE(status))  		return -ENODEV; -	if (!acpi_power_nocheck) { -		/* -		 * If acpi_power_nocheck is set, it is unnecessary to check -		 * the power state after power transition. -		 */ -		result = acpi_power_get_state(resource->device->handle, -				&state); -		if (result) -			return result; -		if (state != ACPI_POWER_RESOURCE_STATE_ON) -			return -ENOEXEC; -	}  	/* Update the power resource's _device_ power state */  	resource->device->power.state = ACPI_STATE_D0; @@ -258,7 +246,7 @@ static int acpi_power_on(acpi_handle handle, struct acpi_device *dev)  static int acpi_power_off_device(acpi_handle handle, struct acpi_device *dev)  { -	int result = 0, state; +	int result = 0;  	acpi_status status = AE_OK;  	struct acpi_power_resource *resource = NULL;  	struct list_head *node, *next; @@ -293,18 +281,6 @@ static int acpi_power_off_device(acpi_handle handle, struct acpi_device *dev)  	if (ACPI_FAILURE(status))  		return -ENODEV; -	if (!acpi_power_nocheck) { -		/* -		 * If acpi_power_nocheck is set, it is unnecessary to check -		 * the power state after power transition. -		 */ -		result = acpi_power_get_state(handle, &state); -		if (result) -			return result; -		if (state != ACPI_POWER_RESOURCE_STATE_OFF) -			return -ENOEXEC; -	} -  	/* Update the power resource's _device_ power state */  	resource->device->power.state = ACPI_STATE_D3; diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index 23f0fb84f1c..84e0f3c0744 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c @@ -89,7 +89,7 @@ static int acpi_processor_handle_eject(struct acpi_processor *pr);  static const struct acpi_device_id processor_device_ids[] = {  	{ACPI_PROCESSOR_OBJECT_HID, 0}, -	{ACPI_PROCESSOR_HID, 0}, +	{"ACPI0007", 0},  	{"", 0},  };  MODULE_DEVICE_TABLE(acpi, processor_device_ids); @@ -596,7 +596,21 @@ static int acpi_processor_get_info(struct acpi_device *device)  		ACPI_DEBUG_PRINT((ACPI_DB_INFO,  				  "No bus mastering arbitration control\n")); -	if (!strcmp(acpi_device_hid(device), ACPI_PROCESSOR_HID)) { +	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. @@ -611,20 +625,6 @@ static int acpi_processor_get_info(struct acpi_device *device)  		}  		device_declaration = 1;  		pr->acpi_id = value; -	} else { -		/* 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;  	}  	cpu_index = get_cpu_id(pr->handle, device_declaration, pr->acpi_id); @@ -649,7 +649,16 @@ static int acpi_processor_get_info(struct acpi_device *device)  			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)); @@ -731,6 +740,8 @@ static int __cpuinit acpi_processor_start(struct acpi_device *device)  	/* _PDC call should be done before doing anything else (if reqd.). */  	arch_acpi_processor_init_pdc(pr);  	acpi_processor_set_pdc(pr); +	arch_acpi_processor_cleanup_pdc(pr); +  #ifdef CONFIG_CPU_FREQ  	acpi_processor_ppc_has_changed(pr);  #endif diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index 10a2d913635..0efa59e7e3a 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -139,7 +139,7 @@ static void acpi_safe_halt(void)   * are affected too. We pick the most conservative approach: we assume   * that the local APIC stops in both C2 and C3.   */ -static void acpi_timer_check_state(int state, struct acpi_processor *pr, +static void lapic_timer_check_state(int state, struct acpi_processor *pr,  				   struct acpi_processor_cx *cx)  {  	struct acpi_processor_power *pwr = &pr->power; @@ -162,7 +162,7 @@ static void acpi_timer_check_state(int state, struct acpi_processor *pr,  		pr->power.timer_broadcast_on_state = state;  } -static void acpi_propagate_timer_broadcast(struct acpi_processor *pr) +static void lapic_timer_propagate_broadcast(struct acpi_processor *pr)  {  	unsigned long reason; @@ -173,7 +173,7 @@ static void acpi_propagate_timer_broadcast(struct acpi_processor *pr)  }  /* Power(C) State timer broadcast control */ -static void acpi_state_timer_broadcast(struct acpi_processor *pr, +static void lapic_timer_state_broadcast(struct acpi_processor *pr,  				       struct acpi_processor_cx *cx,  				       int broadcast)  { @@ -190,10 +190,10 @@ static void acpi_state_timer_broadcast(struct acpi_processor *pr,  #else -static void acpi_timer_check_state(int state, struct acpi_processor *pr, +static void lapic_timer_check_state(int state, struct acpi_processor *pr,  				   struct acpi_processor_cx *cstate) { } -static void acpi_propagate_timer_broadcast(struct acpi_processor *pr) { } -static void acpi_state_timer_broadcast(struct acpi_processor *pr, +static void lapic_timer_propagate_broadcast(struct acpi_processor *pr) { } +static void lapic_timer_state_broadcast(struct acpi_processor *pr,  				       struct acpi_processor_cx *cx,  				       int broadcast)  { @@ -515,7 +515,8 @@ static void acpi_processor_power_verify_c2(struct acpi_processor_cx *cx)  static void acpi_processor_power_verify_c3(struct acpi_processor *pr,  					   struct acpi_processor_cx *cx)  { -	static int bm_check_flag; +	static int bm_check_flag = -1; +	static int bm_control_flag = -1;  	if (!cx->address) @@ -545,12 +546,14 @@ static void acpi_processor_power_verify_c3(struct acpi_processor *pr,  	}  	/* All the logic here assumes flags.bm_check is same across all CPUs */ -	if (!bm_check_flag) { +	if (bm_check_flag == -1) {  		/* Determine whether bm_check is needed based on CPU  */  		acpi_processor_power_init_bm_check(&(pr->flags), pr->id);  		bm_check_flag = pr->flags.bm_check; +		bm_control_flag = pr->flags.bm_control;  	} else {  		pr->flags.bm_check = bm_check_flag; +		pr->flags.bm_control = bm_control_flag;  	}  	if (pr->flags.bm_check) { @@ -614,29 +617,25 @@ static int acpi_processor_power_verify(struct acpi_processor *pr)  		switch (cx->type) {  		case ACPI_STATE_C1:  			cx->valid = 1; -			acpi_timer_check_state(i, pr, cx);  			break;  		case ACPI_STATE_C2:  			acpi_processor_power_verify_c2(cx); -			if (cx->valid) -				acpi_timer_check_state(i, pr, cx);  			break;  		case ACPI_STATE_C3:  			acpi_processor_power_verify_c3(pr, cx); -			if (cx->valid) -				acpi_timer_check_state(i, pr, cx);  			break;  		} -		if (cx->valid) -			tsc_check_state(cx->type); +		if (!cx->valid) +			continue; -		if (cx->valid) -			working++; +		lapic_timer_check_state(i, pr, cx); +		tsc_check_state(cx->type); +		working++;  	} -	acpi_propagate_timer_broadcast(pr); +	lapic_timer_propagate_broadcast(pr);  	return (working);  } @@ -839,7 +838,7 @@ static int acpi_idle_enter_c1(struct cpuidle_device *dev,  		return 0;  	} -	acpi_state_timer_broadcast(pr, cx, 1); +	lapic_timer_state_broadcast(pr, cx, 1);  	kt1 = ktime_get_real();  	acpi_idle_do_entry(cx);  	kt2 = ktime_get_real(); @@ -847,7 +846,7 @@ static int acpi_idle_enter_c1(struct cpuidle_device *dev,  	local_irq_enable();  	cx->usage++; -	acpi_state_timer_broadcast(pr, cx, 0); +	lapic_timer_state_broadcast(pr, cx, 0);  	return idle_time;  } @@ -892,7 +891,7 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev,  	 * Must be done before busmaster disable as we might need to  	 * access HPET !  	 */ -	acpi_state_timer_broadcast(pr, cx, 1); +	lapic_timer_state_broadcast(pr, cx, 1);  	if (cx->type == ACPI_STATE_C3)  		ACPI_FLUSH_CPU_CACHE(); @@ -914,7 +913,7 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev,  	cx->usage++; -	acpi_state_timer_broadcast(pr, cx, 0); +	lapic_timer_state_broadcast(pr, cx, 0);  	cx->time += sleep_ticks;  	return idle_time;  } @@ -981,7 +980,7 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,  	 * Must be done before busmaster disable as we might need to  	 * access HPET !  	 */ -	acpi_state_timer_broadcast(pr, cx, 1); +	lapic_timer_state_broadcast(pr, cx, 1);  	kt1 = ktime_get_real();  	/* @@ -1026,7 +1025,7 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,  	cx->usage++; -	acpi_state_timer_broadcast(pr, cx, 0); +	lapic_timer_state_broadcast(pr, cx, 0);  	cx->time += sleep_ticks;  	return idle_time;  } diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 8ff510b91d8..781435d7e36 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -95,7 +95,7 @@ acpi_device_modalias_show(struct device *dev, struct device_attribute *attr, cha  }  static DEVICE_ATTR(modalias, 0444, acpi_device_modalias_show, NULL); -static int acpi_bus_hot_remove_device(void *context) +static void acpi_bus_hot_remove_device(void *context)  {  	struct acpi_device *device;  	acpi_handle handle = context; @@ -104,10 +104,10 @@ static int acpi_bus_hot_remove_device(void *context)  	acpi_status status = AE_OK;  	if (acpi_bus_get_device(handle, &device)) -		return 0; +		return;  	if (!device) -		return 0; +		return;  	ACPI_DEBUG_PRINT((ACPI_DB_INFO,  		"Hot-removing device %s...\n", dev_name(&device->dev))); @@ -115,7 +115,7 @@ static int acpi_bus_hot_remove_device(void *context)  	if (acpi_bus_trim(device, 1)) {  		printk(KERN_ERR PREFIX  				"Removing device failed\n"); -		return -1; +		return;  	}  	/* power off device */ @@ -142,9 +142,10 @@ static int acpi_bus_hot_remove_device(void *context)  	 */  	status = acpi_evaluate_object(handle, "_EJ0", &arg_list, NULL);  	if (ACPI_FAILURE(status)) -		return -ENODEV; +		printk(KERN_WARNING PREFIX +				"Eject device failed\n"); -	return 0; +	return;  }  static ssize_t @@ -155,7 +156,6 @@ acpi_eject_store(struct device *d, struct device_attribute *attr,  	acpi_status status;  	acpi_object_type type = 0;  	struct acpi_device *acpi_device = to_acpi_device(d); -	struct task_struct *task;  	if ((!count) || (buf[0] != '1')) {  		return -EINVAL; @@ -172,11 +172,7 @@ acpi_eject_store(struct device *d, struct device_attribute *attr,  		goto err;  	} -	/* remove the device in another thread to fix the deadlock issue */ -	task = kthread_run(acpi_bus_hot_remove_device, -				acpi_device->handle, "acpi_hot_remove_device"); -	if (IS_ERR(task)) -		ret = PTR_ERR(task); +	acpi_os_hotplug_execute(acpi_bus_hot_remove_device, acpi_device->handle);  err:  	return ret;  } @@ -198,12 +194,12 @@ acpi_device_path_show(struct device *dev, struct device_attribute *attr, char *b  	int result;  	result = acpi_get_name(acpi_dev->handle, ACPI_FULL_PATHNAME, &path); -	if(result) +	if (result)  		goto end;  	result = sprintf(buf, "%s\n", (char*)path.pointer);  	kfree(path.pointer); -  end: +end:  	return result;  }  static DEVICE_ATTR(path, 0444, acpi_device_path_show, NULL); @@ -217,21 +213,21 @@ static int acpi_device_setup_files(struct acpi_device *dev)  	/*  	 * Devices gotten from FADT don't have a "path" attribute  	 */ -	if(dev->handle) { +	if (dev->handle) {  		result = device_create_file(&dev->dev, &dev_attr_path); -		if(result) +		if (result)  			goto end;  	} -	if(dev->flags.hardware_id) { +	if (dev->flags.hardware_id) {  		result = device_create_file(&dev->dev, &dev_attr_hid); -		if(result) +		if (result)  			goto end;  	} -	if (dev->flags.hardware_id || dev->flags.compatible_ids){ +	if (dev->flags.hardware_id || dev->flags.compatible_ids) {  		result = device_create_file(&dev->dev, &dev_attr_modalias); -		if(result) +		if (result)  			goto end;  	} @@ -242,7 +238,7 @@ static int acpi_device_setup_files(struct acpi_device *dev)  	status = acpi_get_handle(dev->handle, "_EJ0", &temp);  	if (ACPI_SUCCESS(status))  		result = device_create_file(&dev->dev, &dev_attr_eject); -  end: +end:  	return result;  } @@ -262,9 +258,9 @@ static void acpi_device_remove_files(struct acpi_device *dev)  	if (dev->flags.hardware_id || dev->flags.compatible_ids)  		device_remove_file(&dev->dev, &dev_attr_modalias); -	if(dev->flags.hardware_id) +	if (dev->flags.hardware_id)  		device_remove_file(&dev->dev, &dev_attr_hid); -	if(dev->handle) +	if (dev->handle)  		device_remove_file(&dev->dev, &dev_attr_path);  }  /* -------------------------------------------------------------------------- @@ -512,7 +508,7 @@ static int acpi_device_register(struct acpi_device *device,  			break;  		}  	} -	if(!found) { +	if (!found) {  		acpi_device_bus_id = new_bus_id;  		strcpy(acpi_device_bus_id->bus_id, device->flags.hardware_id ? device->pnp.hardware_id : "device");  		acpi_device_bus_id->instance_no = 0; @@ -530,22 +526,21 @@ static int acpi_device_register(struct acpi_device *device,  	if (device->parent)  		device->dev.parent = &parent->dev;  	device->dev.bus = &acpi_bus_type; -	device_initialize(&device->dev);  	device->dev.release = &acpi_device_release; -	result = device_add(&device->dev); -	if(result) { -		dev_err(&device->dev, "Error adding device\n"); +	result = device_register(&device->dev); +	if (result) { +		dev_err(&device->dev, "Error registering device\n");  		goto end;  	}  	result = acpi_device_setup_files(device); -	if(result) +	if (result)  		printk(KERN_ERR PREFIX "Error creating sysfs interface for device %s\n",  		       dev_name(&device->dev));  	device->removal_type = ACPI_BUS_REMOVAL_NORMAL;  	return 0; -  end: +end:  	mutex_lock(&acpi_device_lock);  	if (device->parent)  		list_del(&device->node); @@ -577,7 +572,7 @@ static void acpi_device_unregister(struct acpi_device *device, int type)   * @device: the device to add and initialize   * @driver: driver for the device   * - * Used to initialize a device via its device driver.  Called whenever a  + * Used to initialize a device via its device driver.  Called whenever a   * driver is bound to a device.  Invokes the driver's add() ops.   */  static int @@ -585,7 +580,6 @@ acpi_bus_driver_init(struct acpi_device *device, struct acpi_driver *driver)  {  	int result = 0; -  	if (!device || !driver)  		return -EINVAL; @@ -802,7 +796,7 @@ static int acpi_bus_get_wakeup_device_flags(struct acpi_device *device)  	if (!acpi_match_device_ids(device, button_device_ids))  		device->wakeup.flags.run_wake = 1; -      end: +end:  	if (ACPI_FAILURE(status))  		device->flags.wake_capable = 0;  	return 0; @@ -1070,7 +1064,7 @@ static void acpi_device_set_id(struct acpi_device *device,  		break;  	} -	/*  +	/*  	 * \_SB  	 * ----  	 * Fix for the system root bus device -- the only root-level device. @@ -1320,7 +1314,7 @@ acpi_add_single_object(struct acpi_device **child,  			device->parent->ops.bind(device);  	} -      end: +end:  	if (!result)  		*child = device;  	else { @@ -1464,7 +1458,6 @@ acpi_bus_add(struct acpi_device **child,  	return result;  } -  EXPORT_SYMBOL(acpi_bus_add);  int acpi_bus_start(struct acpi_device *device) @@ -1484,7 +1477,6 @@ int acpi_bus_start(struct acpi_device *device)  	}  	return result;  } -  EXPORT_SYMBOL(acpi_bus_start);  int acpi_bus_trim(struct acpi_device *start, int rmdevice) @@ -1542,7 +1534,6 @@ int acpi_bus_trim(struct acpi_device *start, int rmdevice)  }  EXPORT_SYMBOL_GPL(acpi_bus_trim); -  static int acpi_bus_scan_fixed(struct acpi_device *root)  {  	int result = 0; @@ -1610,6 +1601,6 @@ int __init acpi_scan_init(void)  	if (result)  		acpi_device_unregister(acpi_root, ACPI_BUS_REMOVAL_NORMAL); -      Done: +Done:  	return result;  } diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index 1bdfb37377e..8851315ce85 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -76,6 +76,7 @@ MODULE_LICENSE("GPL");  static int brightness_switch_enabled = 1;  module_param(brightness_switch_enabled, bool, 0644); +static int register_count = 0;  static int acpi_video_bus_add(struct acpi_device *device);  static int acpi_video_bus_remove(struct acpi_device *device, int type);  static int acpi_video_resume(struct acpi_device *device); @@ -586,6 +587,14 @@ static struct dmi_system_id video_dmi_table[] __initdata = {  		DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5315"),  		},  	}, +	{ +	 .callback = video_set_bqc_offset, +	 .ident = "Acer Aspire 7720", +	 .matches = { +		DMI_MATCH(DMI_BOARD_VENDOR, "Acer"), +		DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 7720"), +		}, +	},  	{}  }; @@ -976,6 +985,11 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device)  		device->backlight->props.max_brightness = device->brightness->count-3;  		kfree(name); +		result = sysfs_create_link(&device->backlight->dev.kobj, +					   &device->dev->dev.kobj, "device"); +		if (result) +			printk(KERN_ERR PREFIX "Create sysfs link\n"); +  		device->cdev = thermal_cooling_device_register("LCD",  					device->dev, &video_cooling_ops);  		if (IS_ERR(device->cdev)) @@ -1054,15 +1068,15 @@ static void acpi_video_bus_find_cap(struct acpi_video_bus *video)  static int acpi_video_bus_check(struct acpi_video_bus *video)  {  	acpi_status status = -ENOENT; -	struct device *dev; +	struct pci_dev *dev;  	if (!video)  		return -EINVAL; -	dev = acpi_get_physical_pci_device(video->device->handle); +	dev = acpi_get_pci_dev(video->device->handle);  	if (!dev)  		return -ENODEV; -	put_device(dev); +	pci_dev_put(dev);  	/* Since there is no HID, CID and so on for VGA driver, we have  	 * to check well known required nodes. @@ -1990,6 +2004,7 @@ static int acpi_video_bus_put_one_device(struct acpi_video_device *device)  	status = acpi_remove_notify_handler(device->dev->handle,  					    ACPI_DEVICE_NOTIFY,  					    acpi_video_device_notify); +	sysfs_remove_link(&device->backlight->dev.kobj, "device");  	backlight_device_unregister(device->backlight);  	if (device->cdev) {  		sysfs_remove_link(&device->dev->dev.kobj, @@ -2318,6 +2333,13 @@ static int __init intel_opregion_present(void)  int acpi_video_register(void)  {  	int result = 0; +	if (register_count) { +		/* +		 * if the function of acpi_video_register is already called, +		 * don't register the acpi_vide_bus again and return no error. +		 */ +		return 0; +	}  	acpi_video_dir = proc_mkdir(ACPI_VIDEO_CLASS, acpi_root_dir);  	if (!acpi_video_dir) @@ -2329,10 +2351,35 @@ int acpi_video_register(void)  		return -ENODEV;  	} +	/* +	 * When the acpi_video_bus is loaded successfully, increase +	 * the counter reference. +	 */ +	register_count = 1; +  	return 0;  }  EXPORT_SYMBOL(acpi_video_register); +void acpi_video_unregister(void) +{ +	if (!register_count) { +		/* +		 * If the acpi video bus is already unloaded, don't +		 * unload it again and return directly. +		 */ +		return; +	} +	acpi_bus_unregister_driver(&acpi_video_bus); + +	remove_proc_entry(ACPI_VIDEO_CLASS, acpi_root_dir); + +	register_count = 0; + +	return; +} +EXPORT_SYMBOL(acpi_video_unregister); +  /*   * This is kind of nasty. Hardware using Intel chipsets may require   * the video opregion code to be run first in order to initialise @@ -2350,16 +2397,12 @@ static int __init acpi_video_init(void)  	return acpi_video_register();  } -void acpi_video_exit(void) +static void __exit acpi_video_exit(void)  { - -	acpi_bus_unregister_driver(&acpi_video_bus); - -	remove_proc_entry(ACPI_VIDEO_CLASS, acpi_root_dir); +	acpi_video_unregister();  	return;  } -EXPORT_SYMBOL(acpi_video_exit);  module_init(acpi_video_init);  module_exit(acpi_video_exit); diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c index 09737275e25..7cd2b63435e 100644 --- a/drivers/acpi/video_detect.c +++ b/drivers/acpi/video_detect.c @@ -10,7 +10,7 @@   * assinged   *   * After PCI devices are glued with ACPI devices - * acpi_get_physical_pci_device() can be called to identify ACPI graphics + * acpi_get_pci_dev() can be called to identify ACPI graphics   * devices for which a real graphics card is plugged in   *   * Now acpi_video_get_capabilities() can be called to check which @@ -36,6 +36,7 @@  #include <linux/acpi.h>  #include <linux/dmi.h> +#include <linux/pci.h>  ACPI_MODULE_NAME("video");  #define _COMPONENT		ACPI_VIDEO_COMPONENT @@ -109,7 +110,7 @@ static acpi_status  find_video(acpi_handle handle, u32 lvl, void *context, void **rv)  {  	long *cap = context; -	struct device *dev; +	struct pci_dev *dev;  	struct acpi_device *acpi_dev;  	const struct acpi_device_id video_ids[] = { @@ -120,10 +121,10 @@ find_video(acpi_handle handle, u32 lvl, void *context, void **rv)  		return AE_OK;  	if (!acpi_match_device_ids(acpi_dev, video_ids)) { -		dev = acpi_get_physical_pci_device(handle); +		dev = acpi_get_pci_dev(handle);  		if (!dev)  			return AE_OK; -		put_device(dev); +		pci_dev_put(dev);  		*cap |= acpi_is_video_device(acpi_dev);  	}  	return AE_OK;  |