diff options
| -rw-r--r-- | drivers/acpi/pci_irq.c | 102 | ||||
| -rw-r--r-- | drivers/acpi/pci_root.c | 18 | ||||
| -rw-r--r-- | drivers/pci/pci-acpi.c | 24 | ||||
| -rw-r--r-- | include/acpi/acpi_drivers.h | 5 | 
4 files changed, 34 insertions, 115 deletions
diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c index 68a921d0324..41c5e1b799e 100644 --- a/drivers/acpi/pci_irq.c +++ b/drivers/acpi/pci_irq.c @@ -53,9 +53,6 @@ struct acpi_prt_entry {  	u32			index;		/* GSI, or link _CRS index */  }; -static LIST_HEAD(acpi_prt_list); -static DEFINE_SPINLOCK(acpi_prt_lock); -  static inline char pin_name(int pin)  {  	return 'A' + pin - 1; @@ -65,28 +62,6 @@ static inline char pin_name(int pin)                           PCI IRQ Routing Table (PRT) Support     -------------------------------------------------------------------------- */ -static struct acpi_prt_entry *acpi_pci_irq_find_prt_entry(struct pci_dev *dev, -							  int pin) -{ -	struct acpi_prt_entry *entry; -	int segment = pci_domain_nr(dev->bus); -	int bus = dev->bus->number; -	int device = PCI_SLOT(dev->devfn); - -	spin_lock(&acpi_prt_lock); -	list_for_each_entry(entry, &acpi_prt_list, list) { -		if ((segment == entry->id.segment) -		    && (bus == entry->id.bus) -		    && (device == entry->id.device) -		    && (pin == entry->pin)) { -			spin_unlock(&acpi_prt_lock); -			return entry; -		} -	} -	spin_unlock(&acpi_prt_lock); -	return NULL; -} -  /* http://bugzilla.kernel.org/show_bug.cgi?id=4773 */  static const struct dmi_system_id medion_md9580[] = {  	{ @@ -184,11 +159,19 @@ static void do_prt_fixups(struct acpi_prt_entry *entry,  	}  } -static int acpi_pci_irq_add_entry(acpi_handle handle, int segment, int bus, -				  struct acpi_pci_routing_table *prt) +static int acpi_pci_irq_check_entry(acpi_handle handle, struct pci_dev *dev, +				  int pin, struct acpi_pci_routing_table *prt, +				  struct acpi_prt_entry **entry_ptr)  { +	int segment = pci_domain_nr(dev->bus); +	int bus = dev->bus->number; +	int device = PCI_SLOT(dev->devfn);  	struct acpi_prt_entry *entry; +	if (((prt->address >> 16) & 0xffff) != device || +	    prt->pin + 1 != pin) +		return -ENODEV; +  	entry = kzalloc(sizeof(struct acpi_prt_entry), GFP_KERNEL);  	if (!entry)  		return -ENOMEM; @@ -237,43 +220,37 @@ static int acpi_pci_irq_add_entry(acpi_handle handle, int segment, int bus,  			      entry->id.device, pin_name(entry->pin),  			      prt->source, entry->index)); -	spin_lock(&acpi_prt_lock); -	list_add_tail(&entry->list, &acpi_prt_list); -	spin_unlock(&acpi_prt_lock); +	*entry_ptr = entry;  	return 0;  } -int acpi_pci_irq_add_prt(acpi_handle handle, int segment, int bus) +static int acpi_pci_irq_find_prt_entry(struct pci_dev *dev, +			  int pin, struct acpi_prt_entry **entry_ptr)  {  	acpi_status status;  	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };  	struct acpi_pci_routing_table *entry; +	acpi_handle handle = NULL; -	/* 'handle' is the _PRT's parent (root bridge or PCI-PCI bridge) */ -	status = acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer); -	if (ACPI_FAILURE(status)) -		return -ENODEV; - -	printk(KERN_DEBUG "ACPI: PCI Interrupt Routing Table [%s._PRT]\n", -	       (char *) buffer.pointer); - -	kfree(buffer.pointer); +	if (dev->bus->bridge) +		handle = ACPI_HANDLE(dev->bus->bridge); -	buffer.length = ACPI_ALLOCATE_BUFFER; -	buffer.pointer = NULL; +	if (!handle) +		return -ENODEV; +	/* 'handle' is the _PRT's parent (root bridge or PCI-PCI bridge) */  	status = acpi_get_irq_routing_table(handle, &buffer);  	if (ACPI_FAILURE(status)) { -		ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PRT [%s]", -				acpi_format_exception(status)));  		kfree(buffer.pointer);  		return -ENODEV;  	}  	entry = buffer.pointer;  	while (entry && (entry->length > 0)) { -		acpi_pci_irq_add_entry(handle, segment, bus, entry); +		if (!acpi_pci_irq_check_entry(handle, dev, pin, +						 entry, entry_ptr)) +			break;  		entry = (struct acpi_pci_routing_table *)  		    ((unsigned long)entry + entry->length);  	} @@ -282,23 +259,6 @@ 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) -{ -	struct acpi_prt_entry *entry, *tmp; - -	printk(KERN_DEBUG -	       "ACPI: Delete PCI Interrupt Routing Table for %04x:%02x\n", -	       segment, bus); -	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) { -			list_del(&entry->list); -			kfree(entry); -		} -	} -	spin_unlock(&acpi_prt_lock); -} -  /* --------------------------------------------------------------------------                            PCI Interrupt Routing Support     -------------------------------------------------------------------------- */ @@ -359,12 +319,13 @@ static int acpi_reroute_boot_interrupt(struct pci_dev *dev,  static struct acpi_prt_entry *acpi_pci_irq_lookup(struct pci_dev *dev, int pin)  { -	struct acpi_prt_entry *entry; +	struct acpi_prt_entry *entry = NULL;  	struct pci_dev *bridge;  	u8 bridge_pin, orig_pin = pin; +	int ret; -	entry = acpi_pci_irq_find_prt_entry(dev, pin); -	if (entry) { +	ret = acpi_pci_irq_find_prt_entry(dev, pin, &entry); +	if (!ret && entry) {  #ifdef CONFIG_X86_IO_APIC  		acpi_reroute_boot_interrupt(dev, entry);  #endif /* CONFIG_X86_IO_APIC */ @@ -373,7 +334,7 @@ static struct acpi_prt_entry *acpi_pci_irq_lookup(struct pci_dev *dev, int pin)  		return entry;  	} -	/*  +	/*  	 * Attempt to derive an IRQ for this device from a parent bridge's  	 * PCI interrupt routing entry (eg. yenta bridge and add-in card bridge).  	 */ @@ -393,8 +354,8 @@ static struct acpi_prt_entry *acpi_pci_irq_lookup(struct pci_dev *dev, int pin)  			pin = bridge_pin;  		} -		entry = acpi_pci_irq_find_prt_entry(bridge, pin); -		if (entry) { +		ret = acpi_pci_irq_find_prt_entry(bridge, pin, &entry); +		if (!ret && entry) {  			ACPI_DEBUG_PRINT((ACPI_DB_INFO,  					 "Derived GSI for %s INT %c from %s\n",  					 pci_name(dev), pin_name(orig_pin), @@ -470,6 +431,7 @@ int acpi_pci_irq_enable(struct pci_dev *dev)  			dev_warn(&dev->dev, "PCI INT %c: no GSI\n",  				 pin_name(pin));  		} +  		return 0;  	} @@ -477,6 +439,7 @@ int acpi_pci_irq_enable(struct pci_dev *dev)  	if (rc < 0) {  		dev_warn(&dev->dev, "PCI INT %c: failed to register GSI\n",  			 pin_name(pin)); +		kfree(entry);  		return rc;  	}  	dev->irq = rc; @@ -491,6 +454,7 @@ int acpi_pci_irq_enable(struct pci_dev *dev)  		(triggering == ACPI_LEVEL_SENSITIVE) ? "level" : "edge",  		(polarity == ACPI_ACTIVE_LOW) ? "low" : "high", dev->irq); +	kfree(entry);  	return 0;  } @@ -513,6 +477,8 @@ void acpi_pci_irq_disable(struct pci_dev *dev)  	else  		gsi = entry->index; +	kfree(entry); +  	/*  	 * TBD: It might be worth clearing dev->irq by magic constant  	 * (e.g. PCI_UNDEFINED_IRQ). diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index 417487a201f..8b5a73b7620 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -416,7 +416,6 @@ static int acpi_pci_root_add(struct acpi_device *device)  	acpi_status status;  	int result;  	struct acpi_pci_root *root; -	acpi_handle handle;  	struct acpi_pci_driver *driver;  	u32 flags, base_flags;  	bool is_osc_granted = false; @@ -471,16 +470,6 @@ static int acpi_pci_root_add(struct acpi_device *device)  	       acpi_device_name(device), acpi_device_bid(device),  	       root->segment, &root->secondary); -	/* -	 * PCI Routing Table -	 * ----------------- -	 * Evaluate and parse _PRT, if exists. -	 */ -	status = acpi_get_handle(device->handle, METHOD_NAME__PRT, &handle); -	if (ACPI_SUCCESS(status)) -		result = acpi_pci_irq_add_prt(device->handle, root->segment, -					      root->secondary.start); -  	root->mcfg_addr = acpi_pci_root_get_mcfg_addr(device->handle);  	/* @@ -605,7 +594,6 @@ out_del_root:  	list_del(&root->node);  	mutex_unlock(&acpi_pci_root_lock); -	acpi_pci_irq_del_prt(root->segment, root->secondary.start);  end:  	kfree(root);  	return result; @@ -613,8 +601,6 @@ end:  static int acpi_pci_root_remove(struct acpi_device *device, int type)  { -	acpi_status status; -	acpi_handle handle;  	struct acpi_pci_root *root = acpi_driver_data(device);  	struct acpi_pci_driver *driver; @@ -629,10 +615,6 @@ static int acpi_pci_root_remove(struct acpi_device *device, int type)  	device_set_run_wake(root->bus->bridge, false);  	pci_acpi_remove_bus_pm_notifier(device); -	status = acpi_get_handle(device->handle, METHOD_NAME__PRT, &handle); -	if (ACPI_SUCCESS(status)) -		acpi_pci_irq_del_prt(root->segment, root->secondary.start); -  	pci_remove_root_bus(root->bus);  	mutex_lock(&acpi_pci_root_lock); diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c index 1c2587c4029..c685ff5e12d 100644 --- a/drivers/pci/pci-acpi.c +++ b/drivers/pci/pci-acpi.c @@ -307,25 +307,6 @@ static void pci_acpi_setup(struct device *dev)  	struct pci_dev *pci_dev = to_pci_dev(dev);  	acpi_handle handle = ACPI_HANDLE(dev);  	struct acpi_device *adev; -	acpi_status status; -	acpi_handle dummy; - -	/* -	 * 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(handle, METHOD_NAME__PRT, &dummy); -	if (ACPI_SUCCESS(status)) { -		unsigned char bus; - -		bus = pci_dev->subordinate ? -			pci_dev->subordinate->number : pci_dev->bus->number; -		acpi_pci_irq_add_prt(handle, pci_domain_nr(pci_dev->bus), bus); -	}  	acpi_power_resource_register_device(dev, handle);  	if (acpi_bus_get_device(handle, &adev) || !adev->wakeup.flags.valid) @@ -341,7 +322,6 @@ static void pci_acpi_setup(struct device *dev)  static void pci_acpi_cleanup(struct device *dev)  { -	struct pci_dev *pci_dev = to_pci_dev(dev);  	acpi_handle handle = ACPI_HANDLE(dev);  	struct acpi_device *adev; @@ -351,10 +331,6 @@ static void pci_acpi_cleanup(struct device *dev)  		pci_acpi_remove_pm_notifier(adev);  	}  	acpi_power_resource_unregister_device(dev, handle); - -	if (pci_dev->subordinate) -		acpi_pci_irq_del_prt(pci_domain_nr(pci_dev->bus), -				     pci_dev->subordinate->number);  }  static struct acpi_bus_type acpi_pci_bus = { diff --git a/include/acpi/acpi_drivers.h b/include/acpi/acpi_drivers.h index 8b1d7a6a969..627749af0ba 100644 --- a/include/acpi/acpi_drivers.h +++ b/include/acpi/acpi_drivers.h @@ -90,11 +90,6 @@ int acpi_pci_link_allocate_irq(acpi_handle handle, int index, int *triggering,  			       int *polarity, char **name);  int acpi_pci_link_free_irq(acpi_handle handle); -/* ACPI PCI Interrupt Routing (pci_irq.c) */ - -int acpi_pci_irq_add_prt(acpi_handle handle, int segment, int bus); -void acpi_pci_irq_del_prt(int segment, int bus); -  /* ACPI PCI Device Binding (pci_bind.c) */  struct pci_bus;  |