From 7461b60afa62b26943e97861d87b9f9a32d7fd9c Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 29 Nov 2006 21:18:04 +0000 Subject: PCI: use /sys/bus/pci/drivers//new_id first Unfortunately, the .../new_id feature does not work with the 8250_pci driver. The reason for this comes down to the way .../new_id is implemented. When PCI tries to match a driver to a device, it checks the modules static device ID tables _before_ checking the dynamic new_id tables. When a driver is capable of matching by ID, and falls back to matching by class (as 8250_pci does), this makes it absolutely impossible to specify a board by ID, and as such the correct driver_data value to use with it. Let's say you have a serial board with vendor 0x1234 and device 0x5678. It's class is set to PCI_CLASS_COMMUNICATION_SERIAL. On boot, this card is matched to the 8250_pci driver, which tries to probe it because it matched using the class entry. The driver finds that it is unable to automatically detect the correct settings to use, so it returns -ENODEV. You know that the information the driver needs is to match this card using a device_data value of '7'. So you echo 1234 5678 0 0 0 0 7 into new_id. The kernel attempts to re-bind 8250_pci to this device. However, because it scans the PCI driver tables, it _again_ matches the class entry which has the wrong device_data. It fails. End of story. You can't support the card without rebuilding the kernel (or writing a specific PCI probe module to support it.) So, can we make new_id override the driver-internal PCI ID tables? IOW, like this: From: Russell King Signed-off-by: Greg Kroah-Hartman --- drivers/pci/pci-driver.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index e5ae3a0..de5b901 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c @@ -162,14 +162,9 @@ const struct pci_device_id *pci_match_id(const struct pci_device_id *ids, const struct pci_device_id *pci_match_device(struct pci_driver *drv, struct pci_dev *dev) { - const struct pci_device_id *id; struct pci_dynid *dynid; - id = pci_match_id(drv->id_table, dev); - if (id) - return id; - - /* static ids didn't match, lets look at the dynamic ones */ + /* Look at the dynamic ids first, before the static ones */ spin_lock(&drv->dynids.lock); list_for_each_entry(dynid, &drv->dynids.list, node) { if (pci_match_one_device(&dynid->id, dev)) { @@ -178,7 +173,8 @@ const struct pci_device_id *pci_match_device(struct pci_driver *drv, } } spin_unlock(&drv->dynids.lock); - return NULL; + + return pci_match_id(drv->id_table, dev); } static int pci_call_probe(struct pci_driver *drv, struct pci_dev *dev, -- cgit v1.1 From 0c875c28649eac0adb8d2e2efac2186c3089e100 Mon Sep 17 00:00:00 2001 From: David Rientjes Date: Sun, 3 Dec 2006 11:55:34 -0800 Subject: PCI quirks: remove redundant check Removes redundant check for dev->subordinate; if it is NULL, the function returns before the patch-affected code region. Signed-off-by: David Rientjes Acked-by: Brice Goglin Signed-off-by: Greg Kroah-Hartman --- drivers/pci/quirks.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 9ca9b9b..7571863 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -1688,8 +1688,7 @@ static void __devinit quirk_nvidia_ck804_msi_ht_cap(struct pci_dev *dev) * a single one having MSI is enough to be sure that MSI are supported. */ pdev = pci_get_slot(dev->bus, 0); - if (dev->subordinate && !msi_ht_cap_enabled(dev) - && !msi_ht_cap_enabled(pdev)) { + if (!msi_ht_cap_enabled(dev) && !msi_ht_cap_enabled(pdev)) { printk(KERN_WARNING "PCI: MSI quirk detected. " "MSI disabled on chipset %s.\n", pci_name(dev)); -- cgit v1.1 From f1e79092d9a59e2b1c8eae3b0f4ef3827dda08a0 Mon Sep 17 00:00:00 2001 From: Linas Vepstas Date: Fri, 1 Dec 2006 16:31:27 -0800 Subject: rpaphp: compiler warning cleanup This janitorial patch removes the following annoying compile-time message: drivers/pci/hotplug/rpaphp_slot.c:57: warning: ignoring return value of sfs_create_file declared with attribute warn_unused_result It also fixes a typo, removes some misc crud. Signed-off-by: Linas Vepstas Cc: John Rose Signed-off-by: Kristen Carlson Accardi Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/rpaphp_slot.c | 47 +++++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/hotplug/rpaphp_slot.c b/drivers/pci/hotplug/rpaphp_slot.c index b771196..3009193 100644 --- a/drivers/pci/hotplug/rpaphp_slot.c +++ b/drivers/pci/hotplug/rpaphp_slot.c @@ -47,21 +47,11 @@ static ssize_t location_read_file (struct hotplug_slot *php_slot, char *buf) return retval; } -static struct hotplug_slot_attribute hotplug_slot_attr_location = { +static struct hotplug_slot_attribute php_attr_location = { .attr = {.name = "phy_location", .mode = S_IFREG | S_IRUGO}, .show = location_read_file, }; -static void rpaphp_sysfs_add_attr_location (struct hotplug_slot *slot) -{ - sysfs_create_file(&slot->kobj, &hotplug_slot_attr_location.attr); -} - -static void rpaphp_sysfs_remove_attr_location (struct hotplug_slot *slot) -{ - sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_location.attr); -} - /* free up the memory used by a slot */ static void rpaphp_release_slot(struct hotplug_slot *hotplug_slot) { @@ -145,7 +135,7 @@ int rpaphp_deregister_slot(struct slot *slot) list_del(&slot->rpaphp_slot_list); /* remove "phy_location" file */ - rpaphp_sysfs_remove_attr_location(php_slot); + sysfs_remove_file(&php_slot->kobj, &php_attr_location.attr); retval = pci_hp_deregister(php_slot); if (retval) @@ -160,36 +150,45 @@ EXPORT_SYMBOL_GPL(rpaphp_deregister_slot); int rpaphp_register_slot(struct slot *slot) { + struct hotplug_slot *php_slot = slot->hotplug_slot; int retval; dbg("%s registering slot:path[%s] index[%x], name[%s] pdomain[%x] type[%d]\n", __FUNCTION__, slot->dn->full_name, slot->index, slot->name, slot->power_domain, slot->type); + /* should not try to register the same slot twice */ - if (is_registered(slot)) { /* should't be here */ + if (is_registered(slot)) { err("rpaphp_register_slot: slot[%s] is already registered\n", slot->name); - rpaphp_release_slot(slot->hotplug_slot); - return -EAGAIN; + retval = -EAGAIN; + goto register_fail; } - retval = pci_hp_register(slot->hotplug_slot); + + retval = pci_hp_register(php_slot); if (retval) { err("pci_hp_register failed with error %d\n", retval); - rpaphp_release_slot(slot->hotplug_slot); - return retval; + goto register_fail; } - - /* create "phy_locatoin" file */ - rpaphp_sysfs_add_attr_location(slot->hotplug_slot); - /* add slot to our internal list */ - dbg("%s adding slot[%s] to rpaphp_slot_list\n", - __FUNCTION__, slot->name); + /* create "phy_location" file */ + retval = sysfs_create_file(&php_slot->kobj, &php_attr_location.attr); + if (retval) { + err("sysfs_create_file failed with error %d\n", retval); + goto sysfs_fail; + } + /* add slot to our internal list */ list_add(&slot->rpaphp_slot_list, &rpaphp_slot_head); info("Slot [%s](PCI location=%s) registered\n", slot->name, slot->location); num_slots++; return 0; + +sysfs_fail: + pci_hp_deregister(php_slot); +register_fail: + rpaphp_release_slot(php_slot); + return retval; } int rpaphp_get_power_status(struct slot *slot, u8 * value) -- cgit v1.1 From 83e42bcdd3be31a0df8b1a8d2d3fa1a65e43815c Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Wed, 6 Dec 2006 22:07:30 +0900 Subject: PCI: pcieport-driver: remove invalid warning message The following warning message should not be displayed for devices which don't use an interrupt pin. pcie_portdrv_probe->Dev[XXXX:XXXX] has invalid IRQ. Check vendor BIOS Signed-off-by: Kenji Kaneshige Signed-off-by: Greg Kroah-Hartman --- drivers/pci/pcie/portdrv_pci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c index b4da795..f17e7ed 100644 --- a/drivers/pci/pcie/portdrv_pci.c +++ b/drivers/pci/pcie/portdrv_pci.c @@ -90,7 +90,7 @@ static int __devinit pcie_portdrv_probe (struct pci_dev *dev, return -ENODEV; pci_set_master(dev); - if (!dev->irq) { + if (!dev->irq && dev->pin) { printk(KERN_WARNING "%s->Dev[%04x:%04x] has invalid IRQ. Check vendor BIOS\n", __FUNCTION__, dev->device, dev->vendor); -- cgit v1.1 From d86f90f9913d27bb968132bf63499c56bca56db6 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Mon, 4 Dec 2006 15:14:44 -0800 Subject: pci: Introduce pci_find_present This works like pci_dev_present but instead of returning boolean returns the matching pci_device_id entry. This makes it much more useful. Code bloat is basically nil as the old boolean function is rewritten in terms of the new one. This will be used by the updated VIA PCI quirks for one Signed-off-by: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/pci/search.c | 39 ++++++++++++++++++++++----------------- 1 file changed, 22 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/search.c b/drivers/pci/search.c index 2f13eba..2bbafe0 100644 --- a/drivers/pci/search.c +++ b/drivers/pci/search.c @@ -413,6 +413,24 @@ exit: return dev; } +const struct pci_device_id *pci_find_present(const struct pci_device_id *ids) +{ + struct pci_dev *dev; + struct pci_device_id * found = NULL; + + WARN_ON(in_interrupt()); + down_read(&pci_bus_sem); + while (ids->vendor || ids->subvendor || ids->class_mask) { + list_for_each_entry(dev, &pci_devices, global_list) { + if ((found = pci_match_one_device(ids, dev)) != NULL) + break; + } + ids++; + } + up_read(&pci_bus_sem); + return found; +} + /** * pci_dev_present - Returns 1 if device matching the device list is present, 0 if not. * @ids: A pointer to a null terminated list of struct pci_device_id structures @@ -424,27 +442,14 @@ exit: * find devices that are usually built into a system, or for a general hint as * to if another device happens to be present at this specific moment in time. */ + int pci_dev_present(const struct pci_device_id *ids) { - struct pci_dev *dev; - int found = 0; - - WARN_ON(in_interrupt()); - down_read(&pci_bus_sem); - while (ids->vendor || ids->subvendor || ids->class_mask) { - list_for_each_entry(dev, &pci_devices, global_list) { - if (pci_match_one_device(ids, dev)) { - found = 1; - goto exit; - } - } - ids++; - } -exit: - up_read(&pci_bus_sem); - return found; + return pci_find_present(ids) == NULL ? 0 : 1; } + EXPORT_SYMBOL(pci_dev_present); +EXPORT_SYMBOL(pci_find_present); EXPORT_SYMBOL(pci_find_device); EXPORT_SYMBOL(pci_find_device_reverse); -- cgit v1.1 From d3bac118fb27a365d5e9f54f4a078eb9b42f968f Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Wed, 22 Nov 2006 18:26:16 +1100 Subject: PCI: Create __pci_bus_find_cap_start() from __pci_bus_find_cap() The current implementation of __pci_bus_find_cap() does two things, first it determines the start of the capability chain for the device, and then it trys to find the requested capability. Split these out, so that we can use the two parts independantly in a subsequent patch. Externally visible behaviour should be unchanged. Signed-off-by: Michael Ellerman Signed-off-by: Greg Kroah-Hartman --- drivers/pci/pci.c | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 5a14b73..4627a51 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -96,10 +96,10 @@ int pci_find_next_capability(struct pci_dev *dev, u8 pos, int cap) } EXPORT_SYMBOL_GPL(pci_find_next_capability); -static int __pci_bus_find_cap(struct pci_bus *bus, unsigned int devfn, u8 hdr_type, int cap) +static int __pci_bus_find_cap_start(struct pci_bus *bus, + unsigned int devfn, u8 hdr_type) { u16 status; - u8 pos; pci_bus_read_config_word(bus, devfn, PCI_STATUS, &status); if (!(status & PCI_STATUS_CAP_LIST)) @@ -108,15 +108,14 @@ static int __pci_bus_find_cap(struct pci_bus *bus, unsigned int devfn, u8 hdr_ty switch (hdr_type) { case PCI_HEADER_TYPE_NORMAL: case PCI_HEADER_TYPE_BRIDGE: - pos = PCI_CAPABILITY_LIST; - break; + return PCI_CAPABILITY_LIST; case PCI_HEADER_TYPE_CARDBUS: - pos = PCI_CB_CAPABILITY_LIST; - break; + return PCI_CB_CAPABILITY_LIST; default: return 0; } - return __pci_find_next_cap(bus, devfn, pos, cap); + + return 0; } /** @@ -140,7 +139,13 @@ static int __pci_bus_find_cap(struct pci_bus *bus, unsigned int devfn, u8 hdr_ty */ int pci_find_capability(struct pci_dev *dev, int cap) { - return __pci_bus_find_cap(dev->bus, dev->devfn, dev->hdr_type, cap); + int pos; + + pos = __pci_bus_find_cap_start(dev->bus, dev->devfn, dev->hdr_type); + if (pos) + pos = __pci_find_next_cap(dev->bus, dev->devfn, pos, cap); + + return pos; } /** @@ -158,11 +163,16 @@ int pci_find_capability(struct pci_dev *dev, int cap) */ int pci_bus_find_capability(struct pci_bus *bus, unsigned int devfn, int cap) { + int pos; u8 hdr_type; pci_bus_read_config_byte(bus, devfn, PCI_HEADER_TYPE, &hdr_type); - return __pci_bus_find_cap(bus, devfn, hdr_type & 0x7f, cap); + pos = __pci_bus_find_cap_start(bus, devfn, hdr_type & 0x7f); + if (pos) + pos = __pci_find_next_cap(bus, devfn, pos, cap); + + return pos; } /** -- cgit v1.1 From 687d5fe3dc33794efb500f42164a0588e2647914 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Wed, 22 Nov 2006 18:26:18 +1100 Subject: PCI: Add pci_find_ht_capability() for finding Hypertransport capabilities There are already several places in the kernel that want to search a PCI device for a given Hypertransport capability. Although this is possible using pci_find_capability() etc., it makes sense to encapsulate that logic in a helper - pci_find_ht_capability(). To cater for searching exhaustively for a capability, we also provide pci_find_next_ht_capability(). We also need to cater for the fact that the HT capability fields may be either 3 or 5 bits wide. pci_find_ht_capability() deals with this for you, but callers using the #defines directly must handle that themselves. Signed-off-by: Michael Ellerman Signed-off-by: Greg Kroah-Hartman --- drivers/pci/pci.c | 84 +++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 81 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 4627a51..6bfb942 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -68,12 +68,14 @@ pci_max_busnr(void) #endif /* 0 */ -static int __pci_find_next_cap(struct pci_bus *bus, unsigned int devfn, u8 pos, int cap) +#define PCI_FIND_CAP_TTL 48 + +static int __pci_find_next_cap_ttl(struct pci_bus *bus, unsigned int devfn, + u8 pos, int cap, int *ttl) { u8 id; - int ttl = 48; - while (ttl--) { + while ((*ttl)--) { pci_bus_read_config_byte(bus, devfn, pos, &pos); if (pos < 0x40) break; @@ -89,6 +91,14 @@ static int __pci_find_next_cap(struct pci_bus *bus, unsigned int devfn, u8 pos, return 0; } +static int __pci_find_next_cap(struct pci_bus *bus, unsigned int devfn, + u8 pos, int cap) +{ + int ttl = PCI_FIND_CAP_TTL; + + return __pci_find_next_cap_ttl(bus, devfn, pos, cap, &ttl); +} + int pci_find_next_capability(struct pci_dev *dev, u8 pos, int cap) { return __pci_find_next_cap(dev->bus, dev->devfn, @@ -224,6 +234,74 @@ int pci_find_ext_capability(struct pci_dev *dev, int cap) } EXPORT_SYMBOL_GPL(pci_find_ext_capability); +static int __pci_find_next_ht_cap(struct pci_dev *dev, int pos, int ht_cap) +{ + int rc, ttl = PCI_FIND_CAP_TTL; + u8 cap, mask; + + if (ht_cap == HT_CAPTYPE_SLAVE || ht_cap == HT_CAPTYPE_HOST) + mask = HT_3BIT_CAP_MASK; + else + mask = HT_5BIT_CAP_MASK; + + pos = __pci_find_next_cap_ttl(dev->bus, dev->devfn, pos, + PCI_CAP_ID_HT, &ttl); + while (pos) { + rc = pci_read_config_byte(dev, pos + 3, &cap); + if (rc != PCIBIOS_SUCCESSFUL) + return 0; + + if ((cap & mask) == ht_cap) + return pos; + + pos = __pci_find_next_cap_ttl(dev->bus, dev->devfn, pos, + PCI_CAP_ID_HT, &ttl); + } + + return 0; +} +/** + * pci_find_next_ht_capability - query a device's Hypertransport capabilities + * @dev: PCI device to query + * @pos: Position from which to continue searching + * @ht_cap: Hypertransport capability code + * + * To be used in conjunction with pci_find_ht_capability() to search for + * all capabilities matching @ht_cap. @pos should always be a value returned + * from pci_find_ht_capability(). + * + * NB. To be 100% safe against broken PCI devices, the caller should take + * steps to avoid an infinite loop. + */ +int pci_find_next_ht_capability(struct pci_dev *dev, int pos, int ht_cap) +{ + return __pci_find_next_ht_cap(dev, pos + PCI_CAP_LIST_NEXT, ht_cap); +} +EXPORT_SYMBOL_GPL(pci_find_next_ht_capability); + +/** + * pci_find_ht_capability - query a device's Hypertransport capabilities + * @dev: PCI device to query + * @ht_cap: Hypertransport capability code + * + * Tell if a device supports a given Hypertransport capability. + * Returns an address within the device's PCI configuration space + * or 0 in case the device does not support the request capability. + * The address points to the PCI capability, of type PCI_CAP_ID_HT, + * which has a Hypertransport capability matching @ht_cap. + */ +int pci_find_ht_capability(struct pci_dev *dev, int ht_cap) +{ + int pos; + + pos = __pci_bus_find_cap_start(dev->bus, dev->devfn, dev->hdr_type); + if (pos) + pos = __pci_find_next_ht_cap(dev, pos, ht_cap); + + return pos; +} +EXPORT_SYMBOL_GPL(pci_find_ht_capability); + /** * pci_find_parent_resource - return resource region of parent bus of given region * @dev: PCI device structure contains resources to be searched -- cgit v1.1 From 120a50df4536da69d2e85633a60bc40a85088dd1 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Wed, 22 Nov 2006 18:26:19 +1100 Subject: PCI: Use pci_find_ht_capability() in drivers/pci/htirq.c Use pci_find_ht_capability() in drivers/pci/htirq.c Signed-off-by: Michael Ellerman Signed-off-by: Greg Kroah-Hartman --- drivers/pci/htirq.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/htirq.c b/drivers/pci/htirq.c index 0a8d1cc..279c940 100644 --- a/drivers/pci/htirq.c +++ b/drivers/pci/htirq.c @@ -99,14 +99,7 @@ int __ht_create_irq(struct pci_dev *dev, int idx, ht_irq_update_t *update) int pos; int irq; - pos = pci_find_capability(dev, PCI_CAP_ID_HT); - while (pos) { - u8 subtype; - pci_read_config_byte(dev, pos + 3, &subtype); - if (subtype == HT_CAPTYPE_IRQ) - break; - pos = pci_find_next_capability(dev, pos, PCI_CAP_ID_HT); - } + pos = pci_find_ht_capability(dev, HT_CAPTYPE_IRQ); if (!pos) return -EINVAL; -- cgit v1.1 From 7a380507c48f7894bae7d367375313df9d51b2e5 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Wed, 22 Nov 2006 18:26:21 +1100 Subject: PCI: Use pci_find_ht_capability() in drivers/pci/quirks.c Use pci_find_ht_capability() in drivers/pci/quirks.c. I'm pretty sure the logic is unchanged here, but someone please eye-ball it for me. I've changed the message to be a little shorter, it's now: PCI: Found (enabled|disabled) HT MSI mapping on xxxx:xx:xx.x Signed-off-by: Michael Ellerman Signed-off-by: Greg Kroah-Hartman --- drivers/pci/quirks.c | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 7571863..cf3e7c0 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -1644,19 +1644,23 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_BRIDGE, quirk_ * return 1 if a HT MSI capability is found and enabled */ static int __devinit msi_ht_cap_enabled(struct pci_dev *dev) { - u8 pos; - int ttl; - for (pos = pci_find_capability(dev, PCI_CAP_ID_HT), ttl = 48; - pos && ttl; - pos = pci_find_next_capability(dev, pos, PCI_CAP_ID_HT), ttl--) { - u32 cap_hdr; - /* MSI mapping section according to Hypertransport spec */ - if (pci_read_config_dword(dev, pos, &cap_hdr) == 0 - && (cap_hdr & 0xf8000000) == 0xa8000000 /* MSI mapping */) { - printk(KERN_INFO "PCI: Found HT MSI mapping on %s with capability %s\n", - pci_name(dev), cap_hdr & 0x10000 ? "enabled" : "disabled"); - return (cap_hdr & 0x10000) != 0; /* MSI mapping cap enabled */ + int pos, ttl = 48; + + pos = pci_find_ht_capability(dev, HT_CAPTYPE_MSI_MAPPING); + while (pos && ttl--) { + u8 flags; + + if (pci_read_config_byte(dev, pos + HT_MSI_FLAGS, + &flags) == 0) + { + printk(KERN_INFO "PCI: Found %s HT MSI Mapping on %s\n", + flags & HT_MSI_FLAGS_ENABLE ? + "enabled" : "disabled", pci_name(dev)); + return (flags & HT_MSI_FLAGS_ENABLE) != 0; } + + pos = pci_find_next_ht_capability(dev, pos, + HT_CAPTYPE_MSI_MAPPING); } return 0; } -- cgit v1.1 From 1597cacbe39802d86656d1f2e6329895bd2ef531 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Mon, 4 Dec 2006 15:14:45 -0800 Subject: PCI: Fix multiple problems with VIA hardware This patch is designed to fix: - Disk eating corruptor on KT7 after resume from RAM - VIA IRQ handling - VIA fixups for bus lockups after resume from RAM The core of this is to add a table of resume fixups run at resume time. We need to do this for a variety of boards and features, but particularly we need to do this to get various critical VIA fixups done on resume. The second part of the problem is to handle VIA IRQ number rules which are a bit odd and need special handling for PIC interrupts. Various patches broke various boxes and while this one may not be perfect (hopefully it is) it ensures the workaround is applied to the right devices only. From: Jean Delvare Now that PCI quirks are replayed on software resume, we can safely re-enable the Asus SMBus unhiding quirk even when software suspend support is enabled. [akpm@osdl.org: fix const warning] Signed-off-by: Alan Cox Cc: Jean Delvare Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/pci/pci-driver.c | 2 + drivers/pci/quirks.c | 167 +++++++++++++++++++++++++++++++---------------- drivers/pci/search.c | 3 +- 3 files changed, 112 insertions(+), 60 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index de5b901..b8d2385 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c @@ -353,6 +353,8 @@ static int pci_device_resume_early(struct device * dev) struct pci_dev * pci_dev = to_pci_dev(dev); struct pci_driver * drv = pci_dev->driver; + pci_fixup_device(pci_fixup_resume, pci_dev); + if (drv && drv->resume_early) error = drv->resume_early(pci_dev); return error; diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index cf3e7c0..30c41fc 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -36,7 +36,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_MELLANOX,PCI_DEVICE_ID_MELLANOX_TAVOR_BRID /* Deal with broken BIOS'es that neglect to enable passive release, which can cause problems in combination with the 82441FX/PPro MTRRs */ -static void __devinit quirk_passive_release(struct pci_dev *dev) +static void quirk_passive_release(struct pci_dev *dev) { struct pci_dev *d = NULL; unsigned char dlc; @@ -53,6 +53,7 @@ static void __devinit quirk_passive_release(struct pci_dev *dev) } } DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82441, quirk_passive_release ); +DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82441, quirk_passive_release ); /* The VIA VP2/VP3/MVP3 seem to have some 'features'. There may be a workaround but VIA don't answer queries. If you happen to have good contacts at VIA @@ -134,7 +135,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82439TX, quir * Updated based on further information from the site and also on * information provided by VIA */ -static void __devinit quirk_vialatency(struct pci_dev *dev) +static void quirk_vialatency(struct pci_dev *dev) { struct pci_dev *p; u8 rev; @@ -185,6 +186,10 @@ exit: DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8363_0, quirk_vialatency ); DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8371_1, quirk_vialatency ); DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8361, quirk_vialatency ); +/* Must restore this on a resume from RAM */ +DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8363_0, quirk_vialatency ); +DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8371_1, quirk_vialatency ); +DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8361, quirk_vialatency ); /* * VIA Apollo VP3 needs ETBF on BT848/878 @@ -532,7 +537,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8235, quirk_vt8235 * TODO: When we have device-specific interrupt routers, * this code will go away from quirks. */ -static void __devinit quirk_via_ioapic(struct pci_dev *dev) +static void quirk_via_ioapic(struct pci_dev *dev) { u8 tmp; @@ -548,6 +553,7 @@ static void __devinit quirk_via_ioapic(struct pci_dev *dev) pci_write_config_byte (dev, 0x58, tmp); } DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686, quirk_via_ioapic ); +DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686, quirk_via_ioapic ); /* * VIA 8237: Some BIOSs don't set the 'Bypass APIC De-Assert Message' Bit. @@ -555,7 +561,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686, quirk_via_i * Set this bit to get rid of cycle wastage. * Otherwise uncritical. */ -static void __devinit quirk_via_vt8237_bypass_apic_deassert(struct pci_dev *dev) +static void quirk_via_vt8237_bypass_apic_deassert(struct pci_dev *dev) { u8 misc_control2; #define BYPASS_APIC_DEASSERT 8 @@ -567,6 +573,7 @@ static void __devinit quirk_via_vt8237_bypass_apic_deassert(struct pci_dev *dev) } } DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237, quirk_via_vt8237_bypass_apic_deassert); +DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237, quirk_via_vt8237_bypass_apic_deassert); /* * The AMD io apic can hang the box when an apic irq is masked. @@ -600,7 +607,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SI, PCI_ANY_ID, quirk_ioapic_rmw ); #define AMD8131_revB0 0x11 #define AMD8131_MISC 0x40 #define AMD8131_NIOAMODE_BIT 0 -static void __init quirk_amd_8131_ioapic(struct pci_dev *dev) +static void quirk_amd_8131_ioapic(struct pci_dev *dev) { unsigned char revid, tmp; @@ -616,6 +623,7 @@ static void __init quirk_amd_8131_ioapic(struct pci_dev *dev) } } DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_BRIDGE, quirk_amd_8131_ioapic); +DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_BRIDGE, quirk_amd_8131_ioapic); #endif /* CONFIG_X86_IO_APIC */ @@ -641,65 +649,84 @@ static void __devinit quirk_via_acpi(struct pci_dev *d) DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_3, quirk_via_acpi ); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4, quirk_via_acpi ); -/* - * Via 686A/B: The PCI_INTERRUPT_LINE register for the on-chip - * devices, USB0/1, AC97, MC97, and ACPI, has an unusual feature: - * when written, it makes an internal connection to the PIC. - * For these devices, this register is defined to be 4 bits wide. - * Normally this is fine. However for IO-APIC motherboards, or - * non-x86 architectures (yes Via exists on PPC among other places), - * we must mask the PCI_INTERRUPT_LINE value versus 0xf to get - * interrupts delivered properly. - * - * Some of the on-chip devices are actually '586 devices' so they are - * listed here. - */ - -static int via_irq_fixup_needed = -1; /* - * As some VIA hardware is available in PCI-card form, we need to restrict - * this quirk to VIA PCI hardware built onto VIA-based motherboards only. - * We try to locate a VIA southbridge before deciding whether the quirk - * should be applied. + * VIA bridges which have VLink */ -static const struct pci_device_id via_irq_fixup_tbl[] = { - { - .vendor = PCI_VENDOR_ID_VIA, - .device = PCI_ANY_ID, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .class = PCI_CLASS_BRIDGE_ISA << 8, - .class_mask = 0xffff00, - }, + +static const struct pci_device_id via_vlink_fixup_tbl[] = { + /* Internal devices need IRQ line routing, pre VLink */ + { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_82C686), 0 }, + { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_8231), 17 }, + /* Devices with VLink */ + { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_8233_0), 17}, + { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_8233A), 17 }, + { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_8233C_0), 17 }, + { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_8235), 16 }, + { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_8237), 15 }, + { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_8237A), 15 }, { 0, }, }; -static void quirk_via_irq(struct pci_dev *dev) +/** + * quirk_via_vlink - VIA VLink IRQ number update + * @dev: PCI device + * + * If the device we are dealing with is on a PIC IRQ we need to + * ensure that the IRQ line register which usually is not relevant + * for PCI cards, is actually written so that interrupts get sent + * to the right place + */ + +static void quirk_via_vlink(struct pci_dev *dev) { + const struct pci_device_id *via_vlink_fixup; + static int dev_lo = -1, dev_hi = 18; u8 irq, new_irq; - if (via_irq_fixup_needed == -1) - via_irq_fixup_needed = pci_dev_present(via_irq_fixup_tbl); + /* Check if we have VLink and cache the result */ - if (!via_irq_fixup_needed) + /* Checked already - no */ + if (dev_lo == -2) return; + /* Not checked - see what bridge we have and find the device + ranges */ + + if (dev_lo == -1) { + via_vlink_fixup = pci_find_present(via_vlink_fixup_tbl); + if (via_vlink_fixup == NULL) { + dev_lo = -2; + return; + } + dev_lo = via_vlink_fixup->driver_data; + /* 82C686 is special - 0/0 */ + if (dev_lo == 0) + dev_hi = 0; + } new_irq = dev->irq; /* Don't quirk interrupts outside the legacy IRQ range */ if (!new_irq || new_irq > 15) return; + /* Internal device ? */ + if (dev->bus->number != 0 || PCI_SLOT(dev->devfn) > dev_hi || + PCI_SLOT(dev->devfn) < dev_lo) + return; + + /* This is an internal VLink device on a PIC interrupt. The BIOS + ought to have set this but may not have, so we redo it */ + pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq); if (new_irq != irq) { - printk(KERN_INFO "PCI: VIA IRQ fixup for %s, from %d to %d\n", + printk(KERN_INFO "PCI: VIA VLink IRQ fixup for %s, from %d to %d\n", pci_name(dev), irq, new_irq); udelay(15); /* unknown if delay really needed */ pci_write_config_byte(dev, PCI_INTERRUPT_LINE, new_irq); } } -DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_ANY_ID, quirk_via_irq); +DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_ANY_ID, quirk_via_vlink); /* * VIA VT82C598 has its device ID settable and many BIOSes @@ -720,13 +747,14 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C597_0, quirk_vt * do this even if the Linux CardBus driver is not loaded, because * the Linux i82365 driver does not (and should not) handle CardBus. */ -static void __devinit quirk_cardbus_legacy(struct pci_dev *dev) +static void quirk_cardbus_legacy(struct pci_dev *dev) { if ((PCI_CLASS_BRIDGE_CARDBUS << 8) ^ dev->class) return; pci_write_config_dword(dev, PCI_CB_LEGACY_MODE_BASE, 0); } DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, quirk_cardbus_legacy); +DECLARE_PCI_FIXUP_RESUME(PCI_ANY_ID, PCI_ANY_ID, quirk_cardbus_legacy); /* * Following the PCI ordering rules is optional on the AMD762. I'm not @@ -735,7 +763,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, quirk_cardbus_legacy); * To be fair to AMD, it follows the spec by default, its BIOS people * who turn it off! */ -static void __devinit quirk_amd_ordering(struct pci_dev *dev) +static void quirk_amd_ordering(struct pci_dev *dev) { u32 pcic; pci_read_config_dword(dev, 0x4C, &pcic); @@ -749,6 +777,7 @@ static void __devinit quirk_amd_ordering(struct pci_dev *dev) } } DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_FE_GATE_700C, quirk_amd_ordering ); +DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_FE_GATE_700C, quirk_amd_ordering ); /* * DreamWorks provided workaround for Dunord I-3000 problem @@ -784,7 +813,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TOSHIBA, 0x605, quirk_transparent_bridge * datasheets found at http://www.national.com/ds/GX for info on what * these bits do. */ -static void __init quirk_mediagx_master(struct pci_dev *dev) +static void quirk_mediagx_master(struct pci_dev *dev) { u8 reg; pci_read_config_byte(dev, 0x41, ®); @@ -795,13 +824,14 @@ static void __init quirk_mediagx_master(struct pci_dev *dev) } } DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_PCI_MASTER, quirk_mediagx_master ); +DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_PCI_MASTER, quirk_mediagx_master ); /* * Ensure C0 rev restreaming is off. This is normally done by * the BIOS but in the odd case it is not the results are corruption * hence the presence of a Linux check */ -static void __init quirk_disable_pxb(struct pci_dev *pdev) +static void quirk_disable_pxb(struct pci_dev *pdev) { u16 config; u8 rev; @@ -817,6 +847,7 @@ static void __init quirk_disable_pxb(struct pci_dev *pdev) } } DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82454NX, quirk_disable_pxb ); +DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82454NX, quirk_disable_pxb ); /* @@ -874,7 +905,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82375, quirk_e * runs everywhere at present we suppress the printk output in most * irrelevant cases. */ -static void __init k8t_sound_hostbridge(struct pci_dev *dev) +static void k8t_sound_hostbridge(struct pci_dev *dev) { unsigned char val; @@ -893,8 +924,8 @@ static void __init k8t_sound_hostbridge(struct pci_dev *dev) } } DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237, k8t_sound_hostbridge); +DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237, k8t_sound_hostbridge); -#ifndef CONFIG_ACPI_SLEEP /* * On ASUS P4B boards, the SMBus PCI Device within the ICH2/4 southbridge * is not activated. The myth is that Asus said that they do not want the @@ -906,10 +937,6 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237, k8t_sound_ho * bridge. Unfortunately, this device has no subvendor/subdevice ID. So it * becomes necessary to do this tweak in two steps -- I've chosen the Host * bridge as trigger. - * - * Actually, leaving it unhidden and not redoing the quirk over suspend2ram - * will cause thermal management to break down, and causing machine to - * overheat. */ static int __initdata asus_hides_smbus; @@ -1019,7 +1046,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82855PM_HB, as DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82855GM_HB, asus_hides_smbus_hostbridge ); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82915GM_HB, asus_hides_smbus_hostbridge ); -static void __init asus_hides_smbus_lpc(struct pci_dev *dev) +static void asus_hides_smbus_lpc(struct pci_dev *dev) { u16 val; @@ -1042,8 +1069,14 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_0, asu DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_12, asus_hides_smbus_lpc ); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12, asus_hides_smbus_lpc ); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0, asus_hides_smbus_lpc ); +DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0, asus_hides_smbus_lpc ); +DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0, asus_hides_smbus_lpc ); +DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_0, asus_hides_smbus_lpc ); +DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_12, asus_hides_smbus_lpc ); +DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12, asus_hides_smbus_lpc ); +DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0, asus_hides_smbus_lpc ); -static void __init asus_hides_smbus_lpc_ich6(struct pci_dev *dev) +static void asus_hides_smbus_lpc_ich6(struct pci_dev *dev) { u32 val, rcba; void __iomem *base; @@ -1059,13 +1092,12 @@ static void __init asus_hides_smbus_lpc_ich6(struct pci_dev *dev) printk(KERN_INFO "PCI: Enabled ICH6/i801 SMBus device\n"); } DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_1, asus_hides_smbus_lpc_ich6 ); - -#endif +DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_1, asus_hides_smbus_lpc_ich6 ); /* * SiS 96x south bridge: BIOS typically hides SMBus device... */ -static void __init quirk_sis_96x_smbus(struct pci_dev *dev) +static void quirk_sis_96x_smbus(struct pci_dev *dev) { u8 val = 0; printk(KERN_INFO "Enabling SiS 96x SMBus.\n"); @@ -1086,7 +1118,7 @@ static int __devinitdata sis_96x_compatible = 0; #define SIS_DETECT_REGISTER 0x40 -static void __init quirk_sis_503(struct pci_dev *dev) +static void quirk_sis_503(struct pci_dev *dev) { u8 reg; u16 devid; @@ -1122,13 +1154,14 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_651, quirk_sis_96x_ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_735, quirk_sis_96x_compatible ); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503, quirk_sis_503 ); +DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503, quirk_sis_503 ); /* * On ASUS A8V and A8V Deluxe boards, the onboard AC97 audio controller * and MC97 modem controller are disabled when a second PCI soundcard is * present. This patch, tweaking the VT8237 ISA bridge, enables them. * -- bjd */ -static void __init asus_hides_ac97_lpc(struct pci_dev *dev) +static void asus_hides_ac97_lpc(struct pci_dev *dev) { u8 val; int asus_hides_ac97 = 0; @@ -1159,6 +1192,14 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_962, quirk_sis_96x_ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_963, quirk_sis_96x_smbus ); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_LPC, quirk_sis_96x_smbus ); +DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237, asus_hides_ac97_lpc ); + + +DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_961, quirk_sis_96x_smbus ); +DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_962, quirk_sis_96x_smbus ); +DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_963, quirk_sis_96x_smbus ); +DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_LPC, quirk_sis_96x_smbus ); + #if defined(CONFIG_ATA) || defined(CONFIG_ATA_MODULE) /* @@ -1167,7 +1208,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_LPC, quirk_sis_96x_ * the PCI scanning. */ -static void __devinit quirk_jmicron_dualfn(struct pci_dev *pdev) +static void quirk_jmicron_dualfn(struct pci_dev *pdev) { u32 conf; u8 hdr; @@ -1205,6 +1246,7 @@ static void __devinit quirk_jmicron_dualfn(struct pci_dev *pdev) } DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, quirk_jmicron_dualfn); +DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, quirk_jmicron_dualfn); #endif @@ -1532,6 +1574,8 @@ extern struct pci_fixup __start_pci_fixups_final[]; extern struct pci_fixup __end_pci_fixups_final[]; extern struct pci_fixup __start_pci_fixups_enable[]; extern struct pci_fixup __end_pci_fixups_enable[]; +extern struct pci_fixup __start_pci_fixups_resume[]; +extern struct pci_fixup __end_pci_fixups_resume[]; void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev) @@ -1559,6 +1603,11 @@ void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev) end = __end_pci_fixups_enable; break; + case pci_fixup_resume: + start = __start_pci_fixups_resume; + end = __end_pci_fixups_resume; + break; + default: /* stupid compiler warning, you would think with an enum... */ return; @@ -1596,7 +1645,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x1460, quirk_p64h2_1k_io); * Force it to be linked by setting the corresponding control bit in the * config space. */ -static void __devinit quirk_nvidia_ck804_pcie_aer_ext_cap(struct pci_dev *dev) +static void quirk_nvidia_ck804_pcie_aer_ext_cap(struct pci_dev *dev) { uint8_t b; if (pci_read_config_byte(dev, 0xf41, &b) == 0) { @@ -1610,6 +1659,8 @@ static void __devinit quirk_nvidia_ck804_pcie_aer_ext_cap(struct pci_dev *dev) } DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_CK804_PCIE, quirk_nvidia_ck804_pcie_aer_ext_cap); +DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_CK804_PCIE, + quirk_nvidia_ck804_pcie_aer_ext_cap); #ifdef CONFIG_PCI_MSI /* To disable MSI globally */ diff --git a/drivers/pci/search.c b/drivers/pci/search.c index 2bbafe0..45f2b20 100644 --- a/drivers/pci/search.c +++ b/drivers/pci/search.c @@ -416,7 +416,7 @@ exit: const struct pci_device_id *pci_find_present(const struct pci_device_id *ids) { struct pci_dev *dev; - struct pci_device_id * found = NULL; + const struct pci_device_id *found = NULL; WARN_ON(in_interrupt()); down_read(&pci_bus_sem); @@ -442,7 +442,6 @@ const struct pci_device_id *pci_find_present(const struct pci_device_id *ids) * find devices that are usually built into a system, or for a general hint as * to if another device happens to be present at this specific moment in time. */ - int pci_dev_present(const struct pci_device_id *ids) { return pci_find_present(ids) == NULL ? 0 : 1; -- cgit v1.1 From 9ac0ce8596b17093739d42721cc8a616cedf734b Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Mon, 4 Dec 2006 15:14:48 -0800 Subject: PCI: Be a bit defensive in quirk_nvidia_ck804() so we don't risk dereferencing a NULL pdev. pci_get_slot() may return NULL if nothing was found. quirk_nvidia_ck804() does not check the value returned from pci_get_slot(), so it may end up causing a NULL pointer deref. Signed-off-by: Jesper Juhl Acked-by: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/pci/quirks.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 30c41fc..8a2db01 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -1743,6 +1743,8 @@ static void __devinit quirk_nvidia_ck804_msi_ht_cap(struct pci_dev *dev) * a single one having MSI is enough to be sure that MSI are supported. */ pdev = pci_get_slot(dev->bus, 0); + if (!pdev) + return; if (!msi_ht_cap_enabled(dev) && !msi_ht_cap_enabled(pdev)) { printk(KERN_WARNING "PCI: MSI quirk detected. " "MSI disabled on chipset %s.\n", -- cgit v1.1 From fb0f2b40faff41f03acaa2ee6e6231fc96ca497c Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Tue, 19 Dec 2006 13:12:08 -0800 Subject: PCI legacy resource fix Since commit 368c73d4f689dae0807d0a2aa74c61fd2b9b075f the kernel will try to update the non-writeable BAR registers 0..3 of PIIX4 IDE adapters if pci_assign_unassigned_resources() is used to do full resource assignment of the bus. This fails because in the PIIX4 these BAR registers have implicitly assumed values and read back as zero; it used to work because the kernel used to just write zero to that register the read back value did match what was written. The fix is a new resource flag IORESOURCE_PCI_FIXED used to mark a resource as non-movable. This will also be useful to keep other import system resources from being moved around - for example system consoles on PCI busses. [akpm@osdl.org: cleanup] Signed-off-by: Ralf Baechle Acked-by: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/pci/probe.c | 11 +++++++---- drivers/pci/setup-res.c | 19 +++++++++++++++++-- 2 files changed, 24 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 6a3c1e7..1ae9c3f 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -649,6 +649,9 @@ static void pci_read_irq(struct pci_dev *dev) * Returns 0 on success and -1 if unknown type of device (not normal, bridge * or CardBus). */ + +#define LEGACY_IO_RESOURCE (IORESOURCE_IO | IORESOURCE_PCI_FIXED) + static int pci_setup_device(struct pci_dev * dev) { u32 class; @@ -692,18 +695,18 @@ static int pci_setup_device(struct pci_dev * dev) if ((progif & 1) == 0) { dev->resource[0].start = 0x1F0; dev->resource[0].end = 0x1F7; - dev->resource[0].flags = IORESOURCE_IO; + dev->resource[0].flags = LEGACY_IO_RESOURCE; dev->resource[1].start = 0x3F6; dev->resource[1].end = 0x3F6; - dev->resource[1].flags = IORESOURCE_IO; + dev->resource[1].flags = LEGACY_IO_RESOURCE; } if ((progif & 4) == 0) { dev->resource[2].start = 0x170; dev->resource[2].end = 0x177; - dev->resource[2].flags = IORESOURCE_IO; + dev->resource[2].flags = LEGACY_IO_RESOURCE; dev->resource[3].start = 0x376; dev->resource[3].end = 0x376; - dev->resource[3].flags = IORESOURCE_IO; + dev->resource[3].flags = LEGACY_IO_RESOURCE; } } break; diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c index ab78e4b..cb4ced3 100644 --- a/drivers/pci/setup-res.c +++ b/drivers/pci/setup-res.c @@ -33,11 +33,22 @@ pci_update_resource(struct pci_dev *dev, struct resource *res, int resno) u32 new, check, mask; int reg; - /* Ignore resources for unimplemented BARs and unused resource slots - for 64 bit BARs. */ + /* + * Ignore resources for unimplemented BARs and unused resource slots + * for 64 bit BARs. + */ if (!res->flags) return; + /* + * Ignore non-moveable resources. This might be legacy resources for + * which no functional BAR register exists or another important + * system resource we should better not move around in system address + * space. + */ + if (res->flags & IORESOURCE_PCI_FIXED) + return; + pcibios_resource_to_bus(dev, ®ion, res); pr_debug(" got res [%llx:%llx] bus [%lx:%lx] flags %lx for " @@ -212,6 +223,10 @@ pdev_sort_resources(struct pci_dev *dev, struct resource_list *head) resource_size_t r_align; r = &dev->resource[i]; + + if (r->flags & IORESOURCE_PCI_FIXED) + continue; + r_align = r->end - r->start; if (!(r->flags) || r->parent) -- cgit v1.1 From ab17443a3df35abe4b7529e83511a591aa7384f3 Mon Sep 17 00:00:00 2001 From: Conke Hu Date: Tue, 19 Dec 2006 13:11:37 -0800 Subject: PCI: ATI sb600 sata quirk Acked-by: Jeff Garzik Cc: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/ide/pci/atiixp.c | 1 - drivers/pci/quirks.c | 17 +++++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/ide/pci/atiixp.c b/drivers/ide/pci/atiixp.c index d55b938..ffdffb6 100644 --- a/drivers/ide/pci/atiixp.c +++ b/drivers/ide/pci/atiixp.c @@ -368,7 +368,6 @@ static struct pci_device_id atiixp_pci_tbl[] = { { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP300_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP400_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP600_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP600_SATA, PCI_ANY_ID, PCI_ANY_ID, (PCI_CLASS_STORAGE_IDE<<8)|0x8a, 0xffff05, 1}, { 0, }, }; MODULE_DEVICE_TABLE(pci, atiixp_pci_tbl); diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 8a2db01..8f0322d 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -850,6 +850,23 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82454NX, quirk_ DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82454NX, quirk_disable_pxb ); +static void __devinit quirk_sb600_sata(struct pci_dev *pdev) +{ + /* set sb600 sata to ahci mode */ + if ((pdev->class >> 8) == PCI_CLASS_STORAGE_IDE) { + u8 tmp; + + pci_read_config_byte(pdev, 0x40, &tmp); + pci_write_config_byte(pdev, 0x40, tmp|1); + pci_write_config_byte(pdev, 0x9, 1); + pci_write_config_byte(pdev, 0xa, 6); + pci_write_config_byte(pdev, 0x40, tmp); + + pdev->class = 0x010601; + } +} +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP600_SATA, quirk_sb600_sata); + /* * Serverworks CSB5 IDE does not fully support native mode */ -- cgit v1.1 From 0abe68ce24973a23fcc6cbce80343f68656de7b6 Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Sat, 16 Dec 2006 15:25:34 -0800 Subject: shpchp: remove unnecessary struct php_ctlr The struct php_ctlr seems to be only for complicating codes. This patch removes struct php_ctlr and related codes. Signed-off-by: Kenji Kaneshige Signed-off-by: Kristen Carlson Accardi Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/shpchp.h | 42 +------ drivers/pci/hotplug/shpchp_core.c | 45 +------- drivers/pci/hotplug/shpchp_ctrl.c | 12 +- drivers/pci/hotplug/shpchp_hpc.c | 223 +++++++++++--------------------------- 4 files changed, 73 insertions(+), 249 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h index 5075769..f036485 100644 --- a/drivers/pci/hotplug/shpchp.h +++ b/drivers/pci/hotplug/shpchp.h @@ -83,7 +83,6 @@ struct event_info { struct controller { struct mutex crit_sect; /* critical section mutex */ struct mutex cmd_lock; /* command lock */ - struct php_ctlr_state_s *hpc_ctlr_handle; /* HPC controller handle */ int num_slots; /* Number of slots on ctlr */ int slot_num_inc; /* 1 or -1 */ struct pci_dev *pci_dev; @@ -102,6 +101,8 @@ struct controller { u32 cap_offset; unsigned long mmio_base; unsigned long mmio_size; + void __iomem *creg; + struct timer_list poll_timer; }; @@ -176,10 +177,10 @@ extern int __must_check shpchp_create_ctrl_files(struct controller *ctrl); extern int shpchp_sysfs_enable_slot(struct slot *slot); extern int shpchp_sysfs_disable_slot(struct slot *slot); -extern u8 shpchp_handle_attention_button(u8 hp_slot, void *inst_id); -extern u8 shpchp_handle_switch_change(u8 hp_slot, void *inst_id); -extern u8 shpchp_handle_presence_change(u8 hp_slot, void *inst_id); -extern u8 shpchp_handle_power_fault(u8 hp_slot, void *inst_id); +extern u8 shpchp_handle_attention_button(u8 hp_slot, struct controller *ctrl); +extern u8 shpchp_handle_switch_change(u8 hp_slot, struct controller *ctrl); +extern u8 shpchp_handle_presence_change(u8 hp_slot, struct controller *ctrl); +extern u8 shpchp_handle_power_fault(u8 hp_slot, struct controller *ctrl); /* pci functions */ extern int shpchp_save_config(struct controller *ctrl, int busnumber, int num_ctlr_slots, int first_device_num); @@ -262,24 +263,6 @@ enum ctrl_offsets { SLOT11 = offsetof(struct ctrl_reg, slot11), SLOT12 = offsetof(struct ctrl_reg, slot12), }; -typedef u8(*php_intr_callback_t) (u8 hp_slot, void *instance_id); -struct php_ctlr_state_s { - struct php_ctlr_state_s *pnext; - struct pci_dev *pci_dev; - unsigned int irq; - unsigned long flags; /* spinlock's */ - u32 slot_device_offset; - u32 num_slots; - struct timer_list int_poll_timer; /* Added for poll event */ - php_intr_callback_t attention_button_callback; - php_intr_callback_t switch_change_callback; - php_intr_callback_t presence_change_callback; - php_intr_callback_t power_fault_callback; - void *callback_instance_id; - void __iomem *creg; /* Ptr to controller register space */ -}; -/* Inline functions */ - /* Inline functions to check the sanity of a pointer that is passed to us */ static inline int slot_paranoia_check (struct slot *slot, const char *function) @@ -400,21 +383,8 @@ static inline void amd_pogo_errata_restore_misc_reg(struct slot *p_slot) pci_write_config_dword(p_slot->ctrl->pci_dev, PCIX_MISCII_OFFSET, pcix_misc2_temp); } -enum php_ctlr_type { - PCI, - ISA, - ACPI -}; - int shpc_init( struct controller *ctrl, struct pci_dev *pdev); -int shpc_get_ctlr_slot_config( struct controller *ctrl, - int *num_ctlr_slots, - int *first_device_num, - int *physical_slot_num, - int *updown, - int *flags); - struct hpc_ops { int (*power_on_slot ) (struct slot *slot); int (*slot_enable ) (struct slot *slot); diff --git a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c index 4eac85b..68471dd 100644 --- a/drivers/pci/hotplug/shpchp_core.c +++ b/drivers/pci/hotplug/shpchp_core.c @@ -211,36 +211,6 @@ void cleanup_slots(struct controller *ctrl) } } -static int get_ctlr_slot_config(struct controller *ctrl) -{ - int num_ctlr_slots; - int first_device_num; - int physical_slot_num; - int updown; - int rc; - int flags; - - rc = shpc_get_ctlr_slot_config(ctrl, &num_ctlr_slots, - &first_device_num, &physical_slot_num, - &updown, &flags); - if (rc) { - err("%s: get_ctlr_slot_config fail for b:d (%x:%x)\n", - __FUNCTION__, ctrl->bus, ctrl->device); - return -1; - } - - ctrl->num_slots = num_ctlr_slots; - ctrl->slot_device_offset = first_device_num; - ctrl->first_slot = physical_slot_num; - ctrl->slot_num_inc = updown; /* either -1 or 1 */ - - dbg("%s: num_slot(0x%x) 1st_dev(0x%x) psn(0x%x) updown(%d) for b:d " - "(%x:%x)\n", __FUNCTION__, num_ctlr_slots, first_device_num, - physical_slot_num, updown, ctrl->bus, ctrl->device); - - return 0; -} - /* * set_attention_status - Turns the Amber LED for a slot on, off or blink */ @@ -386,8 +356,6 @@ static int shpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) int rc; struct controller *ctrl; struct slot *t_slot; - int first_device_num; /* first PCI device number */ - int num_ctlr_slots; /* number of slots implemented */ if (!is_shpc_capable(pdev)) return -ENODEV; @@ -416,17 +384,6 @@ static int shpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) dbg("ctrl bus=0x%x, device=%x, function=%x, irq=%x\n", ctrl->bus, ctrl->device, ctrl->function, pdev->irq); - /* - * Save configuration headers for this and subordinate PCI buses - */ - rc = get_ctlr_slot_config(ctrl); - if (rc) { - err(msg_initialization_err, rc); - goto err_out_release_ctlr; - } - first_device_num = ctrl->slot_device_offset; - num_ctlr_slots = ctrl->num_slots; - ctrl->add_support = 1; /* Setup the slot information structures */ @@ -437,7 +394,7 @@ static int shpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) } /* Now hpc_functions (slot->hpc_ops->functions) are ready */ - t_slot = shpchp_find_slot(ctrl, first_device_num); + t_slot = shpchp_find_slot(ctrl, ctrl->slot_device_offset); /* Check for operation bus speed */ rc = t_slot->hpc_ops->get_cur_bus_speed(t_slot, &ctrl->speed); diff --git a/drivers/pci/hotplug/shpchp_ctrl.c b/drivers/pci/hotplug/shpchp_ctrl.c index 158ac78..39893c7 100644 --- a/drivers/pci/hotplug/shpchp_ctrl.c +++ b/drivers/pci/hotplug/shpchp_ctrl.c @@ -57,9 +57,8 @@ static int queue_interrupt_event(struct slot *p_slot, u32 event_type) return 0; } -u8 shpchp_handle_attention_button(u8 hp_slot, void *inst_id) +u8 shpchp_handle_attention_button(u8 hp_slot, struct controller *ctrl) { - struct controller *ctrl = (struct controller *) inst_id; struct slot *p_slot; u32 event_type; @@ -81,9 +80,8 @@ u8 shpchp_handle_attention_button(u8 hp_slot, void *inst_id) } -u8 shpchp_handle_switch_change(u8 hp_slot, void *inst_id) +u8 shpchp_handle_switch_change(u8 hp_slot, struct controller *ctrl) { - struct controller *ctrl = (struct controller *) inst_id; struct slot *p_slot; u8 getstatus; u32 event_type; @@ -120,9 +118,8 @@ u8 shpchp_handle_switch_change(u8 hp_slot, void *inst_id) return 1; } -u8 shpchp_handle_presence_change(u8 hp_slot, void *inst_id) +u8 shpchp_handle_presence_change(u8 hp_slot, struct controller *ctrl) { - struct controller *ctrl = (struct controller *) inst_id; struct slot *p_slot; u32 event_type; @@ -154,9 +151,8 @@ u8 shpchp_handle_presence_change(u8 hp_slot, void *inst_id) return 1; } -u8 shpchp_handle_power_fault(u8 hp_slot, void *inst_id) +u8 shpchp_handle_power_fault(u8 hp_slot, struct controller *ctrl) { - struct controller *ctrl = (struct controller *) inst_id; struct slot *p_slot; u32 event_type; diff --git a/drivers/pci/hotplug/shpchp_hpc.c b/drivers/pci/hotplug/shpchp_hpc.c index 83a5226..b7bede4 100644 --- a/drivers/pci/hotplug/shpchp_hpc.c +++ b/drivers/pci/hotplug/shpchp_hpc.c @@ -212,44 +212,40 @@ #define SLOT_SERR_INT_MASK 0x3 DEFINE_DBG_BUFFER /* Debug string buffer for entire HPC defined here */ -static struct php_ctlr_state_s *php_ctlr_list_head; /* HPC state linked list */ -static int ctlr_seq_num = 0; /* Controller sequenc # */ -static spinlock_t list_lock; - static atomic_t shpchp_num_controllers = ATOMIC_INIT(0); static irqreturn_t shpc_isr(int irq, void *dev_id); -static void start_int_poll_timer(struct php_ctlr_state_s *php_ctlr, int sec); +static void start_int_poll_timer(struct controller *ctrl, int sec); static int hpc_check_cmd_status(struct controller *ctrl); static inline u8 shpc_readb(struct controller *ctrl, int reg) { - return readb(ctrl->hpc_ctlr_handle->creg + reg); + return readb(ctrl->creg + reg); } static inline void shpc_writeb(struct controller *ctrl, int reg, u8 val) { - writeb(val, ctrl->hpc_ctlr_handle->creg + reg); + writeb(val, ctrl->creg + reg); } static inline u16 shpc_readw(struct controller *ctrl, int reg) { - return readw(ctrl->hpc_ctlr_handle->creg + reg); + return readw(ctrl->creg + reg); } static inline void shpc_writew(struct controller *ctrl, int reg, u16 val) { - writew(val, ctrl->hpc_ctlr_handle->creg + reg); + writew(val, ctrl->creg + reg); } static inline u32 shpc_readl(struct controller *ctrl, int reg) { - return readl(ctrl->hpc_ctlr_handle->creg + reg); + return readl(ctrl->creg + reg); } static inline void shpc_writel(struct controller *ctrl, int reg, u32 val) { - writel(val, ctrl->hpc_ctlr_handle->creg + reg); + writel(val, ctrl->creg + reg); } static inline int shpc_indirect_read(struct controller *ctrl, int index, @@ -268,21 +264,20 @@ static inline int shpc_indirect_read(struct controller *ctrl, int index, /* * This is the interrupt polling timeout function. */ -static void int_poll_timeout(unsigned long lphp_ctlr) +static void int_poll_timeout(unsigned long data) { - struct php_ctlr_state_s *php_ctlr = - (struct php_ctlr_state_s *)lphp_ctlr; + struct controller *ctrl = (struct controller *)data; DBG_ENTER_ROUTINE /* Poll for interrupt events. regs == NULL => polling */ - shpc_isr(0, php_ctlr->callback_instance_id); + shpc_isr(0, ctrl); - init_timer(&php_ctlr->int_poll_timer); + init_timer(&ctrl->poll_timer); if (!shpchp_poll_time) shpchp_poll_time = 2; /* default polling interval is 2 sec */ - start_int_poll_timer(php_ctlr, shpchp_poll_time); + start_int_poll_timer(ctrl, shpchp_poll_time); DBG_LEAVE_ROUTINE } @@ -290,16 +285,16 @@ static void int_poll_timeout(unsigned long lphp_ctlr) /* * This function starts the interrupt polling timer. */ -static void start_int_poll_timer(struct php_ctlr_state_s *php_ctlr, int sec) +static void start_int_poll_timer(struct controller *ctrl, int sec) { /* Clamp to sane value */ if ((sec <= 0) || (sec > 60)) sec = 2; - php_ctlr->int_poll_timer.function = &int_poll_timeout; - php_ctlr->int_poll_timer.data = (unsigned long)php_ctlr; - php_ctlr->int_poll_timer.expires = jiffies + sec * HZ; - add_timer(&php_ctlr->int_poll_timer); + ctrl->poll_timer.function = &int_poll_timeout; + ctrl->poll_timer.data = (unsigned long)ctrl; + ctrl->poll_timer.expires = jiffies + sec * HZ; + add_timer(&ctrl->poll_timer); } static inline int is_ctrl_busy(struct controller *ctrl) @@ -666,33 +661,8 @@ static void hpc_set_green_led_blink(struct slot *slot) shpc_write_cmd(slot, slot->hp_slot, SET_PWR_BLINK); } -int shpc_get_ctlr_slot_config(struct controller *ctrl, - int *num_ctlr_slots, /* number of slots in this HPC */ - int *first_device_num, /* PCI dev num of the first slot in this SHPC */ - int *physical_slot_num, /* phy slot num of the first slot in this SHPC */ - int *updown, /* physical_slot_num increament: 1 or -1 */ - int *flags) -{ - u32 slot_config; - - DBG_ENTER_ROUTINE - - slot_config = shpc_readl(ctrl, SLOT_CONFIG); - *first_device_num = (slot_config & FIRST_DEV_NUM) >> 8; - *num_ctlr_slots = slot_config & SLOT_NUM; - *physical_slot_num = (slot_config & PSN) >> 16; - *updown = ((slot_config & UPDOWN) >> 29) ? 1 : -1; - - dbg("%s: physical_slot_num = %x\n", __FUNCTION__, *physical_slot_num); - - DBG_LEAVE_ROUTINE - return 0; -} - static void hpc_release_ctlr(struct controller *ctrl) { - struct php_ctlr_state_s *php_ctlr = ctrl->hpc_ctlr_handle; - struct php_ctlr_state_s *p, *p_prev; int i; u32 slot_reg, serr_int; @@ -722,40 +692,15 @@ static void hpc_release_ctlr(struct controller *ctrl) serr_int &= ~SERR_INTR_RSVDZ_MASK; shpc_writel(ctrl, SERR_INTR_ENABLE, serr_int); - if (shpchp_poll_mode) { - del_timer(&php_ctlr->int_poll_timer); - } else { - if (php_ctlr->irq) { - free_irq(php_ctlr->irq, ctrl); - php_ctlr->irq = 0; - pci_disable_msi(php_ctlr->pci_dev); - } - } - - if (php_ctlr->pci_dev) { - iounmap(php_ctlr->creg); - release_mem_region(ctrl->mmio_base, ctrl->mmio_size); - php_ctlr->pci_dev = NULL; - } - - spin_lock(&list_lock); - p = php_ctlr_list_head; - p_prev = NULL; - while (p) { - if (p == php_ctlr) { - if (p_prev) - p_prev->pnext = p->pnext; - else - php_ctlr_list_head = p->pnext; - break; - } else { - p_prev = p; - p = p->pnext; - } + if (shpchp_poll_mode) + del_timer(&ctrl->poll_timer); + else { + free_irq(ctrl->pci_dev->irq, ctrl); + pci_disable_msi(ctrl->pci_dev); } - spin_unlock(&list_lock); - kfree(php_ctlr); + iounmap(ctrl->creg); + release_mem_region(ctrl->mmio_base, ctrl->mmio_size); /* * If this is the last controller to be released, destroy the @@ -764,8 +709,7 @@ static void hpc_release_ctlr(struct controller *ctrl) if (atomic_dec_and_test(&shpchp_num_controllers)) destroy_workqueue(shpchp_wq); -DBG_LEAVE_ROUTINE - + DBG_LEAVE_ROUTINE } static int hpc_power_on_slot(struct slot * slot) @@ -891,7 +835,6 @@ static int hpc_set_bus_speed_mode(struct slot * slot, enum pci_bus_speed value) static irqreturn_t shpc_isr(int irq, void *dev_id) { struct controller *ctrl = (struct controller *)dev_id; - struct php_ctlr_state_s *php_ctlr = ctrl->hpc_ctlr_handle; u32 serr_int, slot_reg, intr_loc, intr_loc2; int hp_slot; @@ -942,20 +885,16 @@ static irqreturn_t shpc_isr(int irq, void *dev_id) __FUNCTION__, hp_slot, slot_reg); if (slot_reg & MRL_CHANGE_DETECTED) - php_ctlr->switch_change_callback( - hp_slot, php_ctlr->callback_instance_id); + shpchp_handle_switch_change(hp_slot, ctrl); if (slot_reg & BUTTON_PRESS_DETECTED) - php_ctlr->attention_button_callback( - hp_slot, php_ctlr->callback_instance_id); + shpchp_handle_attention_button(hp_slot, ctrl); if (slot_reg & PRSNT_CHANGE_DETECTED) - php_ctlr->presence_change_callback( - hp_slot , php_ctlr->callback_instance_id); + shpchp_handle_presence_change(hp_slot, ctrl); if (slot_reg & (ISO_PFAULT_DETECTED | CON_PFAULT_DETECTED)) - php_ctlr->power_fault_callback( - hp_slot, php_ctlr->callback_instance_id); + shpchp_handle_power_fault(hp_slot, ctrl); /* Clear all slot events */ slot_reg &= ~SLOT_REG_RSVDZ_MASK; @@ -1114,10 +1053,8 @@ static struct hpc_ops shpchp_hpc_ops = { .release_ctlr = hpc_release_ctlr, }; -int shpc_init(struct controller * ctrl, struct pci_dev * pdev) +int shpc_init(struct controller *ctrl, struct pci_dev *pdev) { - struct php_ctlr_state_s *php_ctlr, *p; - void *instance_id = ctrl; int rc = -1, num_slots = 0; u8 hp_slot; u32 shpc_base_offset; @@ -1128,16 +1065,6 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev) ctrl->pci_dev = pdev; /* pci_dev of the P2P bridge */ - spin_lock_init(&list_lock); - php_ctlr = kzalloc(sizeof(*php_ctlr), GFP_KERNEL); - - if (!php_ctlr) { /* allocate controller state data */ - err("%s: HPC controller memory allocation error!\n", __FUNCTION__); - goto abort; - } - - php_ctlr->pci_dev = pdev; /* save pci_dev in context */ - if ((pdev->vendor == PCI_VENDOR_ID_AMD) || (pdev->device == PCI_DEVICE_ID_AMD_GOLAM_7450)) { /* amd shpc driver doesn't use Base Offset; assume 0 */ @@ -1147,20 +1074,20 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev) ctrl->cap_offset = pci_find_capability(pdev, PCI_CAP_ID_SHPC); if (!ctrl->cap_offset) { err("%s : cap_offset == 0\n", __FUNCTION__); - goto abort_free_ctlr; + goto abort; } dbg("%s: cap_offset = %x\n", __FUNCTION__, ctrl->cap_offset); rc = shpc_indirect_read(ctrl, 0, &shpc_base_offset); if (rc) { err("%s: cannot read base_offset\n", __FUNCTION__); - goto abort_free_ctlr; + goto abort; } rc = shpc_indirect_read(ctrl, 3, &tempdword); if (rc) { err("%s: cannot read slot config\n", __FUNCTION__); - goto abort_free_ctlr; + goto abort; } num_slots = tempdword & SLOT_NUM; dbg("%s: num_slots (indirect) %x\n", __FUNCTION__, num_slots); @@ -1170,7 +1097,7 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev) if (rc) { err("%s: cannot read creg (index = %d)\n", __FUNCTION__, i); - goto abort_free_ctlr; + goto abort; } dbg("%s: offset %d: value %x\n", __FUNCTION__,i, tempdword); @@ -1187,24 +1114,24 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev) rc = pci_enable_device(pdev); if (rc) { err("%s: pci_enable_device failed\n", __FUNCTION__); - goto abort_free_ctlr; + goto abort; } if (!request_mem_region(ctrl->mmio_base, ctrl->mmio_size, MY_NAME)) { err("%s: cannot reserve MMIO region\n", __FUNCTION__); rc = -1; - goto abort_free_ctlr; + goto abort; } - php_ctlr->creg = ioremap(ctrl->mmio_base, ctrl->mmio_size); - if (!php_ctlr->creg) { + ctrl->creg = ioremap(ctrl->mmio_base, ctrl->mmio_size); + if (!ctrl->creg) { err("%s: cannot remap MMIO region %lx @ %lx\n", __FUNCTION__, ctrl->mmio_size, ctrl->mmio_base); release_mem_region(ctrl->mmio_base, ctrl->mmio_size); rc = -1; - goto abort_free_ctlr; + goto abort; } - dbg("%s: php_ctlr->creg %p\n", __FUNCTION__, php_ctlr->creg); + dbg("%s: ctrl->creg %p\n", __FUNCTION__, ctrl->creg); mutex_init(&ctrl->crit_sect); mutex_init(&ctrl->cmd_lock); @@ -1212,23 +1139,14 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev) /* Setup wait queue */ init_waitqueue_head(&ctrl->queue); - /* Find the IRQ */ - php_ctlr->irq = pdev->irq; - php_ctlr->attention_button_callback = shpchp_handle_attention_button, - php_ctlr->switch_change_callback = shpchp_handle_switch_change; - php_ctlr->presence_change_callback = shpchp_handle_presence_change; - php_ctlr->power_fault_callback = shpchp_handle_power_fault; - php_ctlr->callback_instance_id = instance_id; - - ctrl->hpc_ctlr_handle = php_ctlr; ctrl->hpc_ops = &shpchp_hpc_ops; /* Return PCI Controller Info */ slot_config = shpc_readl(ctrl, SLOT_CONFIG); - php_ctlr->slot_device_offset = (slot_config & FIRST_DEV_NUM) >> 8; - php_ctlr->num_slots = slot_config & SLOT_NUM; - dbg("%s: slot_device_offset %x\n", __FUNCTION__, php_ctlr->slot_device_offset); - dbg("%s: num_slots %x\n", __FUNCTION__, php_ctlr->num_slots); + ctrl->slot_device_offset = (slot_config & FIRST_DEV_NUM) >> 8; + ctrl->num_slots = slot_config & SLOT_NUM; + ctrl->first_slot = (slot_config & PSN) >> 16; + ctrl->slot_num_inc = ((slot_config & UPDOWN) >> 29) ? 1 : -1; /* Mask Global Interrupt Mask & Command Complete Interrupt Mask */ tempdword = shpc_readl(ctrl, SERR_INTR_ENABLE); @@ -1243,7 +1161,7 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev) /* Mask the MRL sensor SERR Mask of individual slot in * Slot SERR-INT Mask & clear all the existing event if any */ - for (hp_slot = 0; hp_slot < php_ctlr->num_slots; hp_slot++) { + for (hp_slot = 0; hp_slot < ctrl->num_slots; hp_slot++) { slot_reg = shpc_readl(ctrl, SLOT_REG(hp_slot)); dbg("%s: Default Logical Slot Register %d value %x\n", __FUNCTION__, hp_slot, slot_reg); @@ -1255,24 +1173,27 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev) shpc_writel(ctrl, SLOT_REG(hp_slot), slot_reg); } - if (shpchp_poll_mode) {/* Install interrupt polling code */ - /* Install and start the interrupt polling timer */ - init_timer(&php_ctlr->int_poll_timer); - start_int_poll_timer( php_ctlr, 10 ); /* start with 10 second delay */ + if (shpchp_poll_mode) { + /* Install interrupt polling timer. Start with 10 sec delay */ + init_timer(&ctrl->poll_timer); + start_int_poll_timer(ctrl, 10); } else { /* Installs the interrupt handler */ rc = pci_enable_msi(pdev); if (rc) { info("Can't get msi for the hotplug controller\n"); info("Use INTx for the hotplug controller\n"); - } else - php_ctlr->irq = pdev->irq; + } - rc = request_irq(php_ctlr->irq, shpc_isr, IRQF_SHARED, MY_NAME, (void *) ctrl); - dbg("%s: request_irq %d for hpc%d (returns %d)\n", __FUNCTION__, php_ctlr->irq, ctlr_seq_num, rc); + rc = request_irq(ctrl->pci_dev->irq, shpc_isr, IRQF_SHARED, + MY_NAME, (void *)ctrl); + dbg("%s: request_irq %d for hpc%d (returns %d)\n", + __FUNCTION__, ctrl->pci_dev->irq, + atomic_read(&shpchp_num_controllers), rc); if (rc) { - err("Can't get irq %d for the hotplug controller\n", php_ctlr->irq); - goto abort_free_ctlr; + err("Can't get irq %d for the hotplug controller\n", + ctrl->pci_dev->irq); + goto abort_iounmap; } } dbg("%s: HPC at b:d:f:irq=0x%x:%x:%x:%x\n", __FUNCTION__, @@ -1280,24 +1201,6 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev) PCI_FUNC(pdev->devfn), pdev->irq); get_hp_hw_control_from_firmware(pdev); - /* Add this HPC instance into the HPC list */ - spin_lock(&list_lock); - if (php_ctlr_list_head == 0) { - php_ctlr_list_head = php_ctlr; - p = php_ctlr_list_head; - p->pnext = NULL; - } else { - p = php_ctlr_list_head; - - while (p->pnext) - p = p->pnext; - - p->pnext = php_ctlr; - } - spin_unlock(&list_lock); - - ctlr_seq_num++; - /* * If this is the first controller to be initialized, * initialize the shpchpd work queue @@ -1306,14 +1209,14 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev) shpchp_wq = create_singlethread_workqueue("shpchpd"); if (!shpchp_wq) { rc = -ENOMEM; - goto abort_free_ctlr; + goto abort_iounmap; } } /* * Unmask all event interrupts of all slots */ - for (hp_slot = 0; hp_slot < php_ctlr->num_slots; hp_slot++) { + for (hp_slot = 0; hp_slot < ctrl->num_slots; hp_slot++) { slot_reg = shpc_readl(ctrl, SLOT_REG(hp_slot)); dbg("%s: Default Logical Slot Register %d value %x\n", __FUNCTION__, hp_slot, slot_reg); @@ -1336,10 +1239,8 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev) return 0; /* We end up here for the many possible ways to fail this API. */ -abort_free_ctlr: - if (php_ctlr->creg) - iounmap(php_ctlr->creg); - kfree(php_ctlr); +abort_iounmap: + iounmap(ctrl->creg); abort: DBG_LEAVE_ROUTINE return rc; -- cgit v1.1 From 227b84c77f5fb3a3b01e5dee1a2928cafc5fd216 Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Sat, 16 Dec 2006 15:25:42 -0800 Subject: shpchp: cleanup struct controller This patch removes unused/unnecessary members from struct controller. Signed-off-by: Kenji Kaneshige Signed-off-by: Kristen Carlson Accardi Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/shpchp.h | 6 ------ drivers/pci/hotplug/shpchp_core.c | 26 +------------------------- 2 files changed, 1 insertion(+), 31 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h index f036485..e217149 100644 --- a/drivers/pci/hotplug/shpchp.h +++ b/drivers/pci/hotplug/shpchp.h @@ -89,15 +89,9 @@ struct controller { struct list_head slot_list; struct hpc_ops *hpc_ops; wait_queue_head_t queue; /* sleep & wake process */ - u8 bus; - u8 device; - u8 function; u8 slot_device_offset; - u8 add_support; u32 pcix_misc2_reg; /* for amd pogo errata */ - enum pci_bus_speed speed; u32 first_slot; /* First physical slot number */ - u8 slot_bus; /* Bus where the slots handled by this controller sit */ u32 cap_offset; unsigned long mmio_base; unsigned long mmio_size; diff --git a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c index 68471dd..b64999d 100644 --- a/drivers/pci/hotplug/shpchp_core.c +++ b/drivers/pci/hotplug/shpchp_core.c @@ -149,7 +149,7 @@ static int init_slots(struct controller *ctrl) slot->hp_slot = i; slot->ctrl = ctrl; - slot->bus = ctrl->slot_bus; + slot->bus = ctrl->pci_dev->subordinate->number; slot->device = ctrl->slot_device_offset + i; slot->hpc_ops = ctrl->hpc_ops; mutex_init(&slot->lock); @@ -355,7 +355,6 @@ static int shpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { int rc; struct controller *ctrl; - struct slot *t_slot; if (!is_shpc_capable(pdev)) return -ENODEV; @@ -376,16 +375,6 @@ static int shpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) pci_set_drvdata(pdev, ctrl); - ctrl->bus = pdev->bus->number; - ctrl->slot_bus = pdev->subordinate->number; - ctrl->device = PCI_SLOT(pdev->devfn); - ctrl->function = PCI_FUNC(pdev->devfn); - - dbg("ctrl bus=0x%x, device=%x, function=%x, irq=%x\n", - ctrl->bus, ctrl->device, ctrl->function, pdev->irq); - - ctrl->add_support = 1; - /* Setup the slot information structures */ rc = init_slots(ctrl); if (rc) { @@ -393,19 +382,6 @@ static int shpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) goto err_out_release_ctlr; } - /* Now hpc_functions (slot->hpc_ops->functions) are ready */ - t_slot = shpchp_find_slot(ctrl, ctrl->slot_device_offset); - - /* Check for operation bus speed */ - rc = t_slot->hpc_ops->get_cur_bus_speed(t_slot, &ctrl->speed); - dbg("%s: t_slot->hp_slot %x\n", __FUNCTION__,t_slot->hp_slot); - - if (rc || ctrl->speed == PCI_SPEED_UNKNOWN) { - err(SHPC_MODULE_NAME ": Can't get current bus speed. " - "Set to 33MHz PCI.\n"); - ctrl->speed = PCI_SPEED_33MHz; - } - rc = shpchp_create_ctrl_files(ctrl); if (rc) goto err_cleanup_slots; -- cgit v1.1 From 6f39be2e05cc6e66481f1395264297f06bef1e21 Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Sat, 16 Dec 2006 15:25:49 -0800 Subject: shpchp: remove shpchprm_get_physical_slot_number This patch removes unnecessary shpchprm_get_physical_slot_number() function. Signed-off-by: Kenji Kaneshige Signed-off-by: Kristen Carlson Accardi Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/shpchp_core.c | 25 +------------------------ 1 file changed, 1 insertion(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c index b64999d..24d1afa 100644 --- a/drivers/pci/hotplug/shpchp_core.c +++ b/drivers/pci/hotplug/shpchp_core.c @@ -104,23 +104,6 @@ static void make_slot_name(struct slot *slot) slot->bus, slot->number); } - - - -static int -shpchprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, - u8 busnum, u8 devnum) -{ - int offset = devnum - ctrl->slot_device_offset; - - dbg("%s: ctrl->slot_num_inc %d, offset %d\n", __FUNCTION__, - ctrl->slot_num_inc, offset); - *sun = (u8) (ctrl->first_slot + ctrl->slot_num_inc *offset); - return 0; -} - - - static int init_slots(struct controller *ctrl) { struct slot *slot; @@ -128,7 +111,6 @@ static int init_slots(struct controller *ctrl) struct hotplug_slot_info *info; int retval = -ENOMEM; int i; - u32 sun; for (i = 0; i < ctrl->num_slots; i++) { slot = kzalloc(sizeof(*slot), GFP_KERNEL); @@ -152,13 +134,8 @@ static int init_slots(struct controller *ctrl) slot->bus = ctrl->pci_dev->subordinate->number; slot->device = ctrl->slot_device_offset + i; slot->hpc_ops = ctrl->hpc_ops; + slot->number = ctrl->first_slot + (ctrl->slot_num_inc * i); mutex_init(&slot->lock); - - if (shpchprm_get_physical_slot_number(ctrl, &sun, - slot->bus, slot->device)) - goto error_info; - - slot->number = sun; INIT_DELAYED_WORK(&slot->work, queue_pushbutton_work); /* register this slot with the hotplug pci core */ -- cgit v1.1 From 8352e04eb427db0ca8ebb9a8547971d433627cad Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Sat, 16 Dec 2006 15:25:57 -0800 Subject: shpchp: cleanup shpchp.h This patch cleans up shpchp.h. Signed-off-by: Kenji Kaneshige Signed-off-by: Kristen Carlson Accardi Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/shpchp.h | 190 ++++++++++++-------------------------- drivers/pci/hotplug/shpchp_core.c | 22 ++--- drivers/pci/hotplug/shpchp_ctrl.c | 9 +- 3 files changed, 77 insertions(+), 144 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h index e217149..3ca6a4f 100644 --- a/drivers/pci/hotplug/shpchp.h +++ b/drivers/pci/hotplug/shpchp.h @@ -47,11 +47,17 @@ extern int shpchp_poll_time; extern int shpchp_debug; extern struct workqueue_struct *shpchp_wq; -/*#define dbg(format, arg...) do { if (shpchp_debug) printk(KERN_DEBUG "%s: " format, MY_NAME , ## arg); } while (0)*/ -#define dbg(format, arg...) do { if (shpchp_debug) printk("%s: " format, MY_NAME , ## arg); } while (0) -#define err(format, arg...) printk(KERN_ERR "%s: " format, MY_NAME , ## arg) -#define info(format, arg...) printk(KERN_INFO "%s: " format, MY_NAME , ## arg) -#define warn(format, arg...) printk(KERN_WARNING "%s: " format, MY_NAME , ## arg) +#define dbg(format, arg...) \ + do { \ + if (shpchp_debug) \ + printk("%s: " format, MY_NAME , ## arg); \ + } while (0) +#define err(format, arg...) \ + printk(KERN_ERR "%s: " format, MY_NAME , ## arg) +#define info(format, arg...) \ + printk(KERN_INFO "%s: " format, MY_NAME , ## arg) +#define warn(format, arg...) \ + printk(KERN_WARNING "%s: " format, MY_NAME , ## arg) #define SLOT_NAME_SIZE 10 struct slot { @@ -99,13 +105,11 @@ struct controller { struct timer_list poll_timer; }; - /* Define AMD SHPC ID */ #define PCI_DEVICE_ID_AMD_GOLAM_7450 0x7450 #define PCI_DEVICE_ID_AMD_POGO_7458 0x7458 /* AMD PCIX bridge registers */ - #define PCIX_MEM_BASE_LIMIT_OFFSET 0x1C #define PCIX_MISCII_OFFSET 0x48 #define PCIX_MISC_BRIDGE_ERRORS_OFFSET 0x80 @@ -140,8 +144,6 @@ struct controller { #define POWERON_STATE 3 #define POWEROFF_STATE 4 -#define PCI_TO_PCI_BRIDGE_CLASS 0x00060400 - /* Error messages */ #define INTERLOCK_OPEN 0x00000002 #define ADD_NOT_SUPPORTED 0x00000003 @@ -153,50 +155,32 @@ struct controller { #define WRONG_BUS_FREQUENCY 0x0000000D #define POWER_FAILURE 0x0000000E -#define REMOVE_NOT_SUPPORTED 0x00000003 - -#define DISABLE_CARD 1 - -/* - * error Messages - */ -#define msg_initialization_err "Initialization failure, error=%d\n" -#define msg_button_on "PCI slot #%s - powering on due to button press.\n" -#define msg_button_off "PCI slot #%s - powering off due to button press.\n" -#define msg_button_cancel "PCI slot #%s - action canceled due to button press.\n" - -/* sysfs functions for the hotplug controller info */ extern int __must_check shpchp_create_ctrl_files(struct controller *ctrl); - -extern int shpchp_sysfs_enable_slot(struct slot *slot); -extern int shpchp_sysfs_disable_slot(struct slot *slot); - +extern void shpchp_remove_ctrl_files(struct controller *ctrl); +extern int shpchp_sysfs_enable_slot(struct slot *slot); +extern int shpchp_sysfs_disable_slot(struct slot *slot); extern u8 shpchp_handle_attention_button(u8 hp_slot, struct controller *ctrl); extern u8 shpchp_handle_switch_change(u8 hp_slot, struct controller *ctrl); extern u8 shpchp_handle_presence_change(u8 hp_slot, struct controller *ctrl); extern u8 shpchp_handle_power_fault(u8 hp_slot, struct controller *ctrl); - -/* pci functions */ -extern int shpchp_save_config(struct controller *ctrl, int busnumber, int num_ctlr_slots, int first_device_num); -extern int shpchp_configure_device(struct slot *p_slot); -extern int shpchp_unconfigure_device(struct slot *p_slot); -extern void shpchp_remove_ctrl_files(struct controller *ctrl); -extern void cleanup_slots(struct controller *ctrl); -extern void queue_pushbutton_work(struct work_struct *work); - +extern int shpchp_configure_device(struct slot *p_slot); +extern int shpchp_unconfigure_device(struct slot *p_slot); +extern void cleanup_slots(struct controller *ctrl); +extern void queue_pushbutton_work(struct work_struct *work); +extern int shpc_init( struct controller *ctrl, struct pci_dev *pdev); #ifdef CONFIG_ACPI static inline int get_hp_params_from_firmware(struct pci_dev *dev, - struct hotplug_params *hpp) + struct hotplug_params *hpp) { if (ACPI_FAILURE(acpi_get_hp_params_from_firmware(dev->bus, hpp))) return -ENODEV; return 0; } -#define get_hp_hw_control_from_firmware(pdev) \ - do { \ - if (DEVICE_ACPI_HANDLE(&(pdev->dev))) \ - acpi_run_oshp(DEVICE_ACPI_HANDLE(&(pdev->dev))); \ +#define get_hp_hw_control_from_firmware(pdev) \ + do { \ + if (DEVICE_ACPI_HANDLE(&(pdev->dev))) \ + acpi_run_oshp(DEVICE_ACPI_HANDLE(&(pdev->dev)));\ } while (0) #else #define get_hp_params_from_firmware(dev, hpp) (-ENODEV) @@ -217,90 +201,40 @@ struct ctrl_reg { volatile u32 serr_loc; volatile u32 serr_intr_enable; volatile u32 slot1; - volatile u32 slot2; - volatile u32 slot3; - volatile u32 slot4; - volatile u32 slot5; - volatile u32 slot6; - volatile u32 slot7; - volatile u32 slot8; - volatile u32 slot9; - volatile u32 slot10; - volatile u32 slot11; - volatile u32 slot12; } __attribute__ ((packed)); /* offsets to the controller registers based on the above structure layout */ enum ctrl_offsets { - BASE_OFFSET = offsetof(struct ctrl_reg, base_offset), - SLOT_AVAIL1 = offsetof(struct ctrl_reg, slot_avail1), - SLOT_AVAIL2 = offsetof(struct ctrl_reg, slot_avail2), - SLOT_CONFIG = offsetof(struct ctrl_reg, slot_config), - SEC_BUS_CONFIG = offsetof(struct ctrl_reg, sec_bus_config), - MSI_CTRL = offsetof(struct ctrl_reg, msi_ctrl), - PROG_INTERFACE = offsetof(struct ctrl_reg, prog_interface), - CMD = offsetof(struct ctrl_reg, cmd), - CMD_STATUS = offsetof(struct ctrl_reg, cmd_status), - INTR_LOC = offsetof(struct ctrl_reg, intr_loc), - SERR_LOC = offsetof(struct ctrl_reg, serr_loc), - SERR_INTR_ENABLE = offsetof(struct ctrl_reg, serr_intr_enable), - SLOT1 = offsetof(struct ctrl_reg, slot1), - SLOT2 = offsetof(struct ctrl_reg, slot2), - SLOT3 = offsetof(struct ctrl_reg, slot3), - SLOT4 = offsetof(struct ctrl_reg, slot4), - SLOT5 = offsetof(struct ctrl_reg, slot5), - SLOT6 = offsetof(struct ctrl_reg, slot6), - SLOT7 = offsetof(struct ctrl_reg, slot7), - SLOT8 = offsetof(struct ctrl_reg, slot8), - SLOT9 = offsetof(struct ctrl_reg, slot9), - SLOT10 = offsetof(struct ctrl_reg, slot10), - SLOT11 = offsetof(struct ctrl_reg, slot11), - SLOT12 = offsetof(struct ctrl_reg, slot12), + BASE_OFFSET = offsetof(struct ctrl_reg, base_offset), + SLOT_AVAIL1 = offsetof(struct ctrl_reg, slot_avail1), + SLOT_AVAIL2 = offsetof(struct ctrl_reg, slot_avail2), + SLOT_CONFIG = offsetof(struct ctrl_reg, slot_config), + SEC_BUS_CONFIG = offsetof(struct ctrl_reg, sec_bus_config), + MSI_CTRL = offsetof(struct ctrl_reg, msi_ctrl), + PROG_INTERFACE = offsetof(struct ctrl_reg, prog_interface), + CMD = offsetof(struct ctrl_reg, cmd), + CMD_STATUS = offsetof(struct ctrl_reg, cmd_status), + INTR_LOC = offsetof(struct ctrl_reg, intr_loc), + SERR_LOC = offsetof(struct ctrl_reg, serr_loc), + SERR_INTR_ENABLE = offsetof(struct ctrl_reg, serr_intr_enable), + SLOT1 = offsetof(struct ctrl_reg, slot1), }; -/* Inline functions to check the sanity of a pointer that is passed to us */ -static inline int slot_paranoia_check (struct slot *slot, const char *function) -{ - if (!slot) { - dbg("%s - slot == NULL", function); - return -1; - } - if (!slot->hotplug_slot) { - dbg("%s - slot->hotplug_slot == NULL!", function); - return -1; - } - return 0; -} - -static inline struct slot *get_slot (struct hotplug_slot *hotplug_slot, const char *function) +static inline struct slot *get_slot(struct hotplug_slot *hotplug_slot) { - struct slot *slot; - - if (!hotplug_slot) { - dbg("%s - hotplug_slot == NULL\n", function); - return NULL; - } - - slot = (struct slot *)hotplug_slot->private; - if (slot_paranoia_check (slot, function)) - return NULL; - return slot; + return hotplug_slot->private; } -static inline struct slot *shpchp_find_slot (struct controller *ctrl, u8 device) +static inline struct slot *shpchp_find_slot(struct controller *ctrl, u8 device) { struct slot *slot; - if (!ctrl) - return NULL; - list_for_each_entry(slot, &ctrl->slot_list, slot_list) { if (slot->device == device) return slot; } err("%s: slot (device=0x%x) not found\n", __FUNCTION__, device); - return NULL; } @@ -377,31 +311,27 @@ static inline void amd_pogo_errata_restore_misc_reg(struct slot *p_slot) pci_write_config_dword(p_slot->ctrl->pci_dev, PCIX_MISCII_OFFSET, pcix_misc2_temp); } -int shpc_init( struct controller *ctrl, struct pci_dev *pdev); - struct hpc_ops { - int (*power_on_slot ) (struct slot *slot); - int (*slot_enable ) (struct slot *slot); - int (*slot_disable ) (struct slot *slot); - int (*set_bus_speed_mode) (struct slot *slot, enum pci_bus_speed speed); - int (*get_power_status) (struct slot *slot, u8 *status); - int (*get_attention_status) (struct slot *slot, u8 *status); - int (*set_attention_status) (struct slot *slot, u8 status); - int (*get_latch_status) (struct slot *slot, u8 *status); - int (*get_adapter_status) (struct slot *slot, u8 *status); - - int (*get_max_bus_speed) (struct slot *slot, enum pci_bus_speed *speed); - int (*get_cur_bus_speed) (struct slot *slot, enum pci_bus_speed *speed); - int (*get_adapter_speed) (struct slot *slot, enum pci_bus_speed *speed); - int (*get_mode1_ECC_cap) (struct slot *slot, u8 *mode); - int (*get_prog_int) (struct slot *slot, u8 *prog_int); - - int (*query_power_fault) (struct slot *slot); - void (*green_led_on) (struct slot *slot); - void (*green_led_off) (struct slot *slot); - void (*green_led_blink) (struct slot *slot); - void (*release_ctlr) (struct controller *ctrl); - int (*check_cmd_status) (struct controller *ctrl); + int (*power_on_slot)(struct slot *slot); + int (*slot_enable)(struct slot *slot); + int (*slot_disable)(struct slot *slot); + int (*set_bus_speed_mode)(struct slot *slot, enum pci_bus_speed speed); + int (*get_power_status)(struct slot *slot, u8 *status); + int (*get_attention_status)(struct slot *slot, u8 *status); + int (*set_attention_status)(struct slot *slot, u8 status); + int (*get_latch_status)(struct slot *slot, u8 *status); + int (*get_adapter_status)(struct slot *slot, u8 *status); + int (*get_max_bus_speed)(struct slot *slot, enum pci_bus_speed *speed); + int (*get_cur_bus_speed)(struct slot *slot, enum pci_bus_speed *speed); + int (*get_adapter_speed)(struct slot *slot, enum pci_bus_speed *speed); + int (*get_mode1_ECC_cap)(struct slot *slot, u8 *mode); + int (*get_prog_int)(struct slot *slot, u8 *prog_int); + int (*query_power_fault)(struct slot *slot); + void (*green_led_on)(struct slot *slot); + void (*green_led_off)(struct slot *slot); + void (*green_led_blink)(struct slot *slot); + void (*release_ctlr)(struct controller *ctrl); + int (*check_cmd_status)(struct controller *ctrl); }; #endif /* _SHPCHP_H */ diff --git a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c index 24d1afa..590cd3c 100644 --- a/drivers/pci/hotplug/shpchp_core.c +++ b/drivers/pci/hotplug/shpchp_core.c @@ -193,7 +193,7 @@ void cleanup_slots(struct controller *ctrl) */ static int set_attention_status (struct hotplug_slot *hotplug_slot, u8 status) { - struct slot *slot = get_slot(hotplug_slot, __FUNCTION__); + struct slot *slot = get_slot(hotplug_slot); dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); @@ -205,7 +205,7 @@ static int set_attention_status (struct hotplug_slot *hotplug_slot, u8 status) static int enable_slot (struct hotplug_slot *hotplug_slot) { - struct slot *slot = get_slot(hotplug_slot, __FUNCTION__); + struct slot *slot = get_slot(hotplug_slot); dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); @@ -214,7 +214,7 @@ static int enable_slot (struct hotplug_slot *hotplug_slot) static int disable_slot (struct hotplug_slot *hotplug_slot) { - struct slot *slot = get_slot(hotplug_slot, __FUNCTION__); + struct slot *slot = get_slot(hotplug_slot); dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); @@ -223,7 +223,7 @@ static int disable_slot (struct hotplug_slot *hotplug_slot) static int get_power_status (struct hotplug_slot *hotplug_slot, u8 *value) { - struct slot *slot = get_slot(hotplug_slot, __FUNCTION__); + struct slot *slot = get_slot(hotplug_slot); int retval; dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); @@ -237,7 +237,7 @@ static int get_power_status (struct hotplug_slot *hotplug_slot, u8 *value) static int get_attention_status (struct hotplug_slot *hotplug_slot, u8 *value) { - struct slot *slot = get_slot(hotplug_slot, __FUNCTION__); + struct slot *slot = get_slot(hotplug_slot); int retval; dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); @@ -251,7 +251,7 @@ static int get_attention_status (struct hotplug_slot *hotplug_slot, u8 *value) static int get_latch_status (struct hotplug_slot *hotplug_slot, u8 *value) { - struct slot *slot = get_slot(hotplug_slot, __FUNCTION__); + struct slot *slot = get_slot(hotplug_slot); int retval; dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); @@ -265,7 +265,7 @@ static int get_latch_status (struct hotplug_slot *hotplug_slot, u8 *value) static int get_adapter_status (struct hotplug_slot *hotplug_slot, u8 *value) { - struct slot *slot = get_slot(hotplug_slot, __FUNCTION__); + struct slot *slot = get_slot(hotplug_slot); int retval; dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); @@ -279,7 +279,7 @@ static int get_adapter_status (struct hotplug_slot *hotplug_slot, u8 *value) static int get_address (struct hotplug_slot *hotplug_slot, u32 *value) { - struct slot *slot = get_slot(hotplug_slot, __FUNCTION__); + struct slot *slot = get_slot(hotplug_slot); struct pci_bus *bus = slot->ctrl->pci_dev->subordinate; dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); @@ -291,7 +291,7 @@ static int get_address (struct hotplug_slot *hotplug_slot, u32 *value) static int get_max_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value) { - struct slot *slot = get_slot(hotplug_slot, __FUNCTION__); + struct slot *slot = get_slot(hotplug_slot); int retval; dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); @@ -305,7 +305,7 @@ static int get_max_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_sp static int get_cur_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value) { - struct slot *slot = get_slot(hotplug_slot, __FUNCTION__); + struct slot *slot = get_slot(hotplug_slot); int retval; dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); @@ -355,7 +355,7 @@ static int shpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) /* Setup the slot information structures */ rc = init_slots(ctrl); if (rc) { - err(msg_initialization_err, 6); + err("%s: slot initialization failed\n", SHPC_MODULE_NAME); goto err_out_release_ctlr; } diff --git a/drivers/pci/hotplug/shpchp_ctrl.c b/drivers/pci/hotplug/shpchp_ctrl.c index 39893c7..6bb8473 100644 --- a/drivers/pci/hotplug/shpchp_ctrl.c +++ b/drivers/pci/hotplug/shpchp_ctrl.c @@ -493,10 +493,12 @@ static void handle_button_press_event(struct slot *p_slot) p_slot->hpc_ops->get_power_status(p_slot, &getstatus); if (getstatus) { p_slot->state = BLINKINGOFF_STATE; - info(msg_button_off, p_slot->name); + info("PCI slot #%s - powering off due to button " + "press.\n", p_slot->name); } else { p_slot->state = BLINKINGON_STATE; - info(msg_button_on, p_slot->name); + info("PCI slot #%s - powering on due to button " + "press.\n", p_slot->name); } /* blink green LED and turn off amber */ p_slot->hpc_ops->green_led_blink(p_slot); @@ -519,7 +521,8 @@ static void handle_button_press_event(struct slot *p_slot) else p_slot->hpc_ops->green_led_off(p_slot); p_slot->hpc_ops->set_attention_status(p_slot, 0); - info(msg_button_cancel, p_slot->name); + info("PCI slot #%s - action canceled due to button press\n", + p_slot->name); p_slot->state = STATIC_STATE; break; case POWEROFF_STATE: -- cgit v1.1 From 031f30d2bc69f78cf542c0e5874a9d67c03d0ffe Mon Sep 17 00:00:00 2001 From: Kristen Carlson Accardi Date: Sat, 16 Dec 2006 15:26:04 -0800 Subject: acpiphp: Link-time error for PCI Hotplug I'm seeing: `acpiphp_glue_exit' referenced in section `.init.text' of drivers/built-in.o: defined in discarded section `.exit.text' of drivers/built-in.o when trying to compile an IA64 kernel with PCI hotplug enabled. I suggest this patch: Signed-off-by: Peter Chubb Signed-off-by: Kristen Carlson Accardi Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/acpiphp_glue.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index 0b9d0db..bd1faeb 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -1682,7 +1682,7 @@ int __init acpiphp_glue_init(void) * * This function frees all data allocated in acpiphp_glue_init() */ -void __exit acpiphp_glue_exit(void) +void acpiphp_glue_exit(void) { acpi_pci_unregister_driver(&acpi_pci_hp_driver); } -- cgit v1.1