Commit 018ba0a6 authored by Bjorn Helgaas's avatar Bjorn Helgaas

Merge branch 'pci/yinghai-root-bus-hotplug' into next

* pci/yinghai-root-bus-hotplug:
  PCI/ACPI: Don't cache _PRT, and don't associate them with bus numbers
parents fd5e20bc 181380b7
...@@ -53,9 +53,6 @@ struct acpi_prt_entry { ...@@ -53,9 +53,6 @@ struct acpi_prt_entry {
u32 index; /* GSI, or link _CRS index */ 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) static inline char pin_name(int pin)
{ {
return 'A' + pin - 1; return 'A' + pin - 1;
...@@ -65,28 +62,6 @@ static inline char pin_name(int pin) ...@@ -65,28 +62,6 @@ static inline char pin_name(int pin)
PCI IRQ Routing Table (PRT) Support 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 */ /* http://bugzilla.kernel.org/show_bug.cgi?id=4773 */
static const struct dmi_system_id medion_md9580[] = { static const struct dmi_system_id medion_md9580[] = {
{ {
...@@ -184,11 +159,19 @@ static void do_prt_fixups(struct acpi_prt_entry *entry, ...@@ -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, static int acpi_pci_irq_check_entry(acpi_handle handle, struct pci_dev *dev,
struct acpi_pci_routing_table *prt) 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; 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); entry = kzalloc(sizeof(struct acpi_prt_entry), GFP_KERNEL);
if (!entry) if (!entry)
return -ENOMEM; return -ENOMEM;
...@@ -237,43 +220,37 @@ static int acpi_pci_irq_add_entry(acpi_handle handle, int segment, int bus, ...@@ -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), entry->id.device, pin_name(entry->pin),
prt->source, entry->index)); prt->source, entry->index));
spin_lock(&acpi_prt_lock); *entry_ptr = entry;
list_add_tail(&entry->list, &acpi_prt_list);
spin_unlock(&acpi_prt_lock);
return 0; 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; acpi_status status;
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
struct acpi_pci_routing_table *entry; struct acpi_pci_routing_table *entry;
acpi_handle handle = NULL;
/* 'handle' is the _PRT's parent (root bridge or PCI-PCI bridge) */ if (dev->bus->bridge)
status = acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer); handle = ACPI_HANDLE(dev->bus->bridge);
if (ACPI_FAILURE(status))
return -ENODEV;
printk(KERN_DEBUG "ACPI: PCI Interrupt Routing Table [%s._PRT]\n",
(char *) buffer.pointer);
kfree(buffer.pointer);
buffer.length = ACPI_ALLOCATE_BUFFER; if (!handle)
buffer.pointer = NULL; return -ENODEV;
/* 'handle' is the _PRT's parent (root bridge or PCI-PCI bridge) */
status = acpi_get_irq_routing_table(handle, &buffer); status = acpi_get_irq_routing_table(handle, &buffer);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PRT [%s]",
acpi_format_exception(status)));
kfree(buffer.pointer); kfree(buffer.pointer);
return -ENODEV; return -ENODEV;
} }
entry = buffer.pointer; entry = buffer.pointer;
while (entry && (entry->length > 0)) { 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 *) entry = (struct acpi_pci_routing_table *)
((unsigned long)entry + entry->length); ((unsigned long)entry + entry->length);
} }
...@@ -282,23 +259,6 @@ int acpi_pci_irq_add_prt(acpi_handle handle, int segment, int bus) ...@@ -282,23 +259,6 @@ int acpi_pci_irq_add_prt(acpi_handle handle, int segment, int bus)
return 0; 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 PCI Interrupt Routing Support
-------------------------------------------------------------------------- */ -------------------------------------------------------------------------- */
...@@ -359,12 +319,13 @@ static int acpi_reroute_boot_interrupt(struct pci_dev *dev, ...@@ -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) 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; struct pci_dev *bridge;
u8 bridge_pin, orig_pin = pin; u8 bridge_pin, orig_pin = pin;
int ret;
entry = acpi_pci_irq_find_prt_entry(dev, pin); ret = acpi_pci_irq_find_prt_entry(dev, pin, &entry);
if (entry) { if (!ret && entry) {
#ifdef CONFIG_X86_IO_APIC #ifdef CONFIG_X86_IO_APIC
acpi_reroute_boot_interrupt(dev, entry); acpi_reroute_boot_interrupt(dev, entry);
#endif /* CONFIG_X86_IO_APIC */ #endif /* CONFIG_X86_IO_APIC */
...@@ -373,7 +334,7 @@ static struct acpi_prt_entry *acpi_pci_irq_lookup(struct pci_dev *dev, int pin) ...@@ -373,7 +334,7 @@ static struct acpi_prt_entry *acpi_pci_irq_lookup(struct pci_dev *dev, int pin)
return entry; return entry;
} }
/* /*
* Attempt to derive an IRQ for this device from a parent bridge's * 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). * 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) ...@@ -393,8 +354,8 @@ static struct acpi_prt_entry *acpi_pci_irq_lookup(struct pci_dev *dev, int pin)
pin = bridge_pin; pin = bridge_pin;
} }
entry = acpi_pci_irq_find_prt_entry(bridge, pin); ret = acpi_pci_irq_find_prt_entry(bridge, pin, &entry);
if (entry) { if (!ret && entry) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO, ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"Derived GSI for %s INT %c from %s\n", "Derived GSI for %s INT %c from %s\n",
pci_name(dev), pin_name(orig_pin), pci_name(dev), pin_name(orig_pin),
...@@ -470,6 +431,7 @@ int acpi_pci_irq_enable(struct pci_dev *dev) ...@@ -470,6 +431,7 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
dev_warn(&dev->dev, "PCI INT %c: no GSI\n", dev_warn(&dev->dev, "PCI INT %c: no GSI\n",
pin_name(pin)); pin_name(pin));
} }
return 0; return 0;
} }
...@@ -477,6 +439,7 @@ int acpi_pci_irq_enable(struct pci_dev *dev) ...@@ -477,6 +439,7 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
if (rc < 0) { if (rc < 0) {
dev_warn(&dev->dev, "PCI INT %c: failed to register GSI\n", dev_warn(&dev->dev, "PCI INT %c: failed to register GSI\n",
pin_name(pin)); pin_name(pin));
kfree(entry);
return rc; return rc;
} }
dev->irq = rc; dev->irq = rc;
...@@ -491,6 +454,7 @@ int acpi_pci_irq_enable(struct pci_dev *dev) ...@@ -491,6 +454,7 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
(triggering == ACPI_LEVEL_SENSITIVE) ? "level" : "edge", (triggering == ACPI_LEVEL_SENSITIVE) ? "level" : "edge",
(polarity == ACPI_ACTIVE_LOW) ? "low" : "high", dev->irq); (polarity == ACPI_ACTIVE_LOW) ? "low" : "high", dev->irq);
kfree(entry);
return 0; return 0;
} }
...@@ -513,6 +477,8 @@ void acpi_pci_irq_disable(struct pci_dev *dev) ...@@ -513,6 +477,8 @@ void acpi_pci_irq_disable(struct pci_dev *dev)
else else
gsi = entry->index; gsi = entry->index;
kfree(entry);
/* /*
* TBD: It might be worth clearing dev->irq by magic constant * TBD: It might be worth clearing dev->irq by magic constant
* (e.g. PCI_UNDEFINED_IRQ). * (e.g. PCI_UNDEFINED_IRQ).
......
...@@ -416,7 +416,6 @@ static int acpi_pci_root_add(struct acpi_device *device) ...@@ -416,7 +416,6 @@ static int acpi_pci_root_add(struct acpi_device *device)
acpi_status status; acpi_status status;
int result; int result;
struct acpi_pci_root *root; struct acpi_pci_root *root;
acpi_handle handle;
struct acpi_pci_driver *driver; struct acpi_pci_driver *driver;
u32 flags, base_flags; u32 flags, base_flags;
bool is_osc_granted = false; bool is_osc_granted = false;
...@@ -471,16 +470,6 @@ static int acpi_pci_root_add(struct acpi_device *device) ...@@ -471,16 +470,6 @@ static int acpi_pci_root_add(struct acpi_device *device)
acpi_device_name(device), acpi_device_bid(device), acpi_device_name(device), acpi_device_bid(device),
root->segment, &root->secondary); 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); root->mcfg_addr = acpi_pci_root_get_mcfg_addr(device->handle);
/* /*
...@@ -605,7 +594,6 @@ static int acpi_pci_root_add(struct acpi_device *device) ...@@ -605,7 +594,6 @@ static int acpi_pci_root_add(struct acpi_device *device)
list_del(&root->node); list_del(&root->node);
mutex_unlock(&acpi_pci_root_lock); mutex_unlock(&acpi_pci_root_lock);
acpi_pci_irq_del_prt(root->segment, root->secondary.start);
end: end:
kfree(root); kfree(root);
return result; return result;
...@@ -613,8 +601,6 @@ static int acpi_pci_root_add(struct acpi_device *device) ...@@ -613,8 +601,6 @@ static int acpi_pci_root_add(struct acpi_device *device)
static int acpi_pci_root_remove(struct acpi_device *device, int type) 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_root *root = acpi_driver_data(device);
struct acpi_pci_driver *driver; struct acpi_pci_driver *driver;
...@@ -629,10 +615,6 @@ static int acpi_pci_root_remove(struct acpi_device *device, int type) ...@@ -629,10 +615,6 @@ static int acpi_pci_root_remove(struct acpi_device *device, int type)
device_set_run_wake(root->bus->bridge, false); device_set_run_wake(root->bus->bridge, false);
pci_acpi_remove_bus_pm_notifier(device); 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); pci_remove_root_bus(root->bus);
mutex_lock(&acpi_pci_root_lock); mutex_lock(&acpi_pci_root_lock);
......
...@@ -307,25 +307,6 @@ static void pci_acpi_setup(struct device *dev) ...@@ -307,25 +307,6 @@ static void pci_acpi_setup(struct device *dev)
struct pci_dev *pci_dev = to_pci_dev(dev); struct pci_dev *pci_dev = to_pci_dev(dev);
acpi_handle handle = ACPI_HANDLE(dev); acpi_handle handle = ACPI_HANDLE(dev);
struct acpi_device *adev; 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); acpi_power_resource_register_device(dev, handle);
if (acpi_bus_get_device(handle, &adev) || !adev->wakeup.flags.valid) if (acpi_bus_get_device(handle, &adev) || !adev->wakeup.flags.valid)
...@@ -341,7 +322,6 @@ static void pci_acpi_setup(struct device *dev) ...@@ -341,7 +322,6 @@ static void pci_acpi_setup(struct device *dev)
static void pci_acpi_cleanup(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); acpi_handle handle = ACPI_HANDLE(dev);
struct acpi_device *adev; struct acpi_device *adev;
...@@ -351,10 +331,6 @@ static void pci_acpi_cleanup(struct device *dev) ...@@ -351,10 +331,6 @@ static void pci_acpi_cleanup(struct device *dev)
pci_acpi_remove_pm_notifier(adev); pci_acpi_remove_pm_notifier(adev);
} }
acpi_power_resource_unregister_device(dev, handle); 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 = { static struct acpi_bus_type acpi_pci_bus = {
......
...@@ -90,11 +90,6 @@ int acpi_pci_link_allocate_irq(acpi_handle handle, int index, int *triggering, ...@@ -90,11 +90,6 @@ int acpi_pci_link_allocate_irq(acpi_handle handle, int index, int *triggering,
int *polarity, char **name); int *polarity, char **name);
int acpi_pci_link_free_irq(acpi_handle handle); 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) */ /* ACPI PCI Device Binding (pci_bind.c) */
struct pci_bus; struct pci_bus;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment