From efe6d7272b1bdb3989322a6f3f9ed063a40c6beb Mon Sep 17 00:00:00 2001 From: Thomas Renninger Date: Fri, 27 May 2011 10:23:00 +0200 Subject: PCI hotplug: Rename is_ejectable which also exists in dock.c While it's declared static, etags points you to the wrong function in drivers/acpi/dock.c and acpiphp_glue.c for example also makes use of some (exported..) functions from this file. If you trust etags and oversee the static declaration (what happened to me) one gets totally confused... Signed-off-by: Thomas Renninger Signed-off-by: Jesse Barnes --- drivers/pci/hotplug/acpi_pcihp.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/pci') diff --git a/drivers/pci/hotplug/acpi_pcihp.c b/drivers/pci/hotplug/acpi_pcihp.c index 8f3faf343f7..095f29e1373 100644 --- a/drivers/pci/hotplug/acpi_pcihp.c +++ b/drivers/pci/hotplug/acpi_pcihp.c @@ -408,7 +408,7 @@ got_one: } EXPORT_SYMBOL(acpi_get_hp_hw_control_from_firmware); -static int is_ejectable(acpi_handle handle) +static int pcihp_is_ejectable(acpi_handle handle) { acpi_status status; acpi_handle tmp; @@ -442,7 +442,7 @@ int acpi_pci_check_ejectable(struct pci_bus *pbus, acpi_handle handle) return 0; if (bridge_handle != parent_handle) return 0; - return is_ejectable(handle); + return pcihp_is_ejectable(handle); } EXPORT_SYMBOL_GPL(acpi_pci_check_ejectable); @@ -450,7 +450,7 @@ static acpi_status check_hotplug(acpi_handle handle, u32 lvl, void *context, void **rv) { int *found = (int *)context; - if (is_ejectable(handle)) { + if (pcihp_is_ejectable(handle)) { *found = 1; return AE_CTRL_TERMINATE; } -- cgit v1.2.3 From 0918472ceeffad234df5589e45b646a94476f835 Mon Sep 17 00:00:00 2001 From: Huang Ying Date: Tue, 17 May 2011 16:08:37 +0800 Subject: PCI: PCIe AER: add aer_recover_queue In addition to native PCIe AER, now APEI (ACPI Platform Error Interface) GHES (Generic Hardware Error Source) can be used to report PCIe AER errors too. To add support to APEI GHES PCIe AER recovery, aer_recover_queue is added to export the recovery function in native PCIe AER driver. Recoverable PCIe AER errors are reported via NMI in APEI GHES. Then APEI GHES uses irq_work to delay the error processing into an IRQ handler. But PCIe AER recovery can be very time-consuming, so aer_recover_queue, which can be used in IRQ handler, delays the real recovery action into the process context, that is, work queue. Signed-off-by: Huang Ying Signed-off-by: Jesse Barnes --- drivers/pci/pcie/aer/aerdrv_core.c | 76 ++++++++++++++++++++++++++++++---- drivers/pci/pcie/aer/aerdrv_errprint.c | 3 +- 2 files changed, 71 insertions(+), 8 deletions(-) (limited to 'drivers/pci') diff --git a/drivers/pci/pcie/aer/aerdrv_core.c b/drivers/pci/pcie/aer/aerdrv_core.c index 43421fbe080..9674e9f30d4 100644 --- a/drivers/pci/pcie/aer/aerdrv_core.c +++ b/drivers/pci/pcie/aer/aerdrv_core.c @@ -24,6 +24,7 @@ #include #include #include +#include #include "aerdrv.h" static int forceload; @@ -445,8 +446,7 @@ static struct pcie_port_service_driver *find_aer_service(struct pci_dev *dev) return drv; } -static pci_ers_result_t reset_link(struct pcie_device *aerdev, - struct pci_dev *dev) +static pci_ers_result_t reset_link(struct pci_dev *dev) { struct pci_dev *udev; pci_ers_result_t status; @@ -486,7 +486,6 @@ static pci_ers_result_t reset_link(struct pcie_device *aerdev, /** * do_recovery - handle nonfatal/fatal error recovery process - * @aerdev: pointer to a pcie_device data structure of root port * @dev: pointer to a pci_dev data structure of agent detecting an error * @severity: error severity type * @@ -494,8 +493,7 @@ static pci_ers_result_t reset_link(struct pcie_device *aerdev, * error detected message to all downstream drivers within a hierarchy in * question and return the returned code. */ -static void do_recovery(struct pcie_device *aerdev, struct pci_dev *dev, - int severity) +static void do_recovery(struct pci_dev *dev, int severity) { pci_ers_result_t status, result = PCI_ERS_RESULT_RECOVERED; enum pci_channel_state state; @@ -511,7 +509,7 @@ static void do_recovery(struct pcie_device *aerdev, struct pci_dev *dev, report_error_detected); if (severity == AER_FATAL) { - result = reset_link(aerdev, dev); + result = reset_link(dev); if (result != PCI_ERS_RESULT_RECOVERED) goto failed; } @@ -576,9 +574,73 @@ static void handle_error_source(struct pcie_device *aerdev, pci_write_config_dword(dev, pos + PCI_ERR_COR_STATUS, info->status); } else - do_recovery(aerdev, dev, info->severity); + do_recovery(dev, info->severity); } +#ifdef CONFIG_ACPI_APEI_PCIEAER +static void aer_recover_work_func(struct work_struct *work); + +#define AER_RECOVER_RING_ORDER 4 +#define AER_RECOVER_RING_SIZE (1 << AER_RECOVER_RING_ORDER) + +struct aer_recover_entry +{ + u8 bus; + u8 devfn; + u16 domain; + int severity; +}; + +static DEFINE_KFIFO(aer_recover_ring, struct aer_recover_entry, + AER_RECOVER_RING_SIZE); +/* + * Mutual exclusion for writers of aer_recover_ring, reader side don't + * need lock, because there is only one reader and lock is not needed + * between reader and writer. + */ +static DEFINE_SPINLOCK(aer_recover_ring_lock); +static DECLARE_WORK(aer_recover_work, aer_recover_work_func); + +void aer_recover_queue(int domain, unsigned int bus, unsigned int devfn, + int severity) +{ + unsigned long flags; + struct aer_recover_entry entry = { + .bus = bus, + .devfn = devfn, + .domain = domain, + .severity = severity, + }; + + spin_lock_irqsave(&aer_recover_ring_lock, flags); + if (kfifo_put(&aer_recover_ring, &entry)) + schedule_work(&aer_recover_work); + else + pr_err("AER recover: Buffer overflow when recovering AER for %04x:%02x:%02x:%x\n", + domain, bus, PCI_SLOT(devfn), PCI_FUNC(devfn)); + spin_unlock_irqrestore(&aer_recover_ring_lock, flags); +} +EXPORT_SYMBOL_GPL(aer_recover_queue); + +static void aer_recover_work_func(struct work_struct *work) +{ + struct aer_recover_entry entry; + struct pci_dev *pdev; + + while (kfifo_get(&aer_recover_ring, &entry)) { + pdev = pci_get_domain_bus_and_slot(entry.domain, entry.bus, + entry.devfn); + if (!pdev) { + pr_err("AER recover: Can not find pci_dev for %04x:%02x:%02x:%x\n", + entry.domain, entry.bus, + PCI_SLOT(entry.devfn), PCI_FUNC(entry.devfn)); + continue; + } + do_recovery(pdev, entry.severity); + } +} +#endif + /** * get_device_error_info - read error status from dev and store it to info * @dev: pointer to the device expected to have a error record diff --git a/drivers/pci/pcie/aer/aerdrv_errprint.c b/drivers/pci/pcie/aer/aerdrv_errprint.c index b07a42e0b35..3ea51736f18 100644 --- a/drivers/pci/pcie/aer/aerdrv_errprint.c +++ b/drivers/pci/pcie/aer/aerdrv_errprint.c @@ -204,7 +204,7 @@ void aer_print_port_info(struct pci_dev *dev, struct aer_err_info *info) } #ifdef CONFIG_ACPI_APEI_PCIEAER -static int cper_severity_to_aer(int cper_severity) +int cper_severity_to_aer(int cper_severity) { switch (cper_severity) { case CPER_SEV_RECOVERABLE: @@ -215,6 +215,7 @@ static int cper_severity_to_aer(int cper_severity) return AER_CORRECTABLE; } } +EXPORT_SYMBOL_GPL(cper_severity_to_aer); void cper_print_aer(const char *prefix, int cper_severity, struct aer_capability_regs *aer) -- cgit v1.2.3 From b1a98b695b4efe10067d0e1cb5b66146a4e517bf Mon Sep 17 00:00:00 2001 From: Tiejun Chen Date: Thu, 2 Jun 2011 11:02:50 +0800 Subject: PCI: enumerate the PCI device only removed out PCI hieratchy of OS when re-scanning PCI When hot-plugging a root bridge, we always prevent assigning a bus number that already exists. This makes sure we don't step over an existing bus. But sometimes we only remove PCI device in PCI hieratchy of OS, i,e. echo 1 > /sys/bus/pci/devices/.../remove but actually don't hotplug this device out the platform, so in this case we still should re-scan this bus to enumerate this device when re-scanning PCI again. Signed-off-by: Tiejun Chen Signed-off-by: Jesse Barnes --- drivers/pci/probe.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'drivers/pci') diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index bafb3c3d4a8..f03ed96533d 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -724,12 +724,14 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, pci_write_config_word(dev, PCI_STATUS, 0xffff); /* Prevent assigning a bus number that already exists. - * This can happen when a bridge is hot-plugged */ - if (pci_find_bus(pci_domain_nr(bus), max+1)) - goto out; - child = pci_add_new_bus(bus, dev, ++max); - if (!child) - goto out; + * This can happen when a bridge is hot-plugged, so in + * this case we only re-scan this bus. */ + child = pci_find_bus(pci_domain_nr(bus), max+1); + if (!child) { + child = pci_add_new_bus(bus, dev, ++max); + if (!child) + goto out; + } buses = (buses & 0xff000000) | ((unsigned int)(child->primary) << 0) | ((unsigned int)(child->secondary) << 8) -- cgit v1.2.3 From 69b3e6199a2d01ad2e3102052be08e0ced91f388 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Wed, 13 Jul 2011 19:21:25 +0400 Subject: PCI hotplug: cpqphp: use pci_dev->subsystem_{vendor|device} The driver reads PCI subsystem IDs from the PCI configuration registers while they are already stored by the PCI subsystem in the 'subsystem_{vendor|device}' fields of 'struct pci_dev'... Signed-off-by: Sergei Shtylyov Signed-off-by: Jesse Barnes --- drivers/pci/hotplug/cpqphp_core.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) (limited to 'drivers/pci') diff --git a/drivers/pci/hotplug/cpqphp_core.c b/drivers/pci/hotplug/cpqphp_core.c index 4952c3b9379..627274cc571 100644 --- a/drivers/pci/hotplug/cpqphp_core.c +++ b/drivers/pci/hotplug/cpqphp_core.c @@ -868,11 +868,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) /* TODO: This code can be made to support non-Compaq or Intel * subsystem IDs */ - rc = pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, &subsystem_vid); - if (rc) { - err("%s : pci_read_config_word failed\n", __func__); - goto err_disable_device; - } + subsystem_vid = pdev->subsystem_vendor; dbg("Subsystem Vendor ID: %x\n", subsystem_vid); if ((subsystem_vid != PCI_VENDOR_ID_COMPAQ) && (subsystem_vid != PCI_VENDOR_ID_INTEL)) { err(msg_HPC_non_compaq_or_intel); @@ -887,11 +883,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) goto err_disable_device; } - rc = pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, &subsystem_deviceid); - if (rc) { - err("%s : pci_read_config_word failed\n", __func__); - goto err_free_ctrl; - } + subsystem_deviceid = pdev->subsystem_device; info("Hot Plug Subsystem Device ID: %x\n", subsystem_deviceid); -- cgit v1.2.3 From 05d3ac267a9d10af6ca370afe21802333aad1d5c Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Wed, 13 Jul 2011 19:20:14 +0400 Subject: PCI hotplug: cpqphp: use pci_dev->vendor The driver reads PCI vendor ID from the PCI configuration register while it is already stored by the PCI subsystem in the 'vendor' field of 'struct pci_dev'... Signed-off-by: Sergei Shtylyov Signed-off-by: Jesse Barnes --- drivers/pci/hotplug/cpqphp_core.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/pci') diff --git a/drivers/pci/hotplug/cpqphp_core.c b/drivers/pci/hotplug/cpqphp_core.c index 627274cc571..f1ce99cceac 100644 --- a/drivers/pci/hotplug/cpqphp_core.c +++ b/drivers/pci/hotplug/cpqphp_core.c @@ -840,8 +840,9 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) /* Need to read VID early b/c it's used to differentiate CPQ and INTC * discovery */ - rc = pci_read_config_word(pdev, PCI_VENDOR_ID, &vendor_id); - if (rc || ((vendor_id != PCI_VENDOR_ID_COMPAQ) && (vendor_id != PCI_VENDOR_ID_INTEL))) { + vendor_id = pdev->vendor; + if ((vendor_id != PCI_VENDOR_ID_COMPAQ) && + (vendor_id != PCI_VENDOR_ID_INTEL)) { err(msg_HPC_non_compaq_or_intel); rc = -ENODEV; goto err_disable_device; -- cgit v1.2.3 From d5341942d784134f2997b3ff82cd63cf71d1f932 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Fri, 10 Jun 2011 15:30:21 +0100 Subject: PCI: Make the struct pci_dev * argument of pci_fixup_irqs const. Aside of the usual motivation for constification, this function has a history of being abused a hook for interrupt and other fixups so I turned this function const ages ago in the MIPS code but it should be done treewide. Due to function pointer passing in varous places a few other functions had to be constified as well. Signed-off-by: Ralf Baechle To: Anton Vorontsov To: Chris Metcalf To: Colin Cross Acked-by: "David S. Miller" To: Eric Miao To: Erik Gilling Acked-by: Guan Xuetao To: "H. Peter Anvin" To: Imre Kaloz To: Ingo Molnar To: Ivan Kokshaysky To: Jesse Barnes To: Krzysztof Halasa To: Lennert Buytenhek To: Matt Turner To: Nicolas Pitre To: Olof Johansson Acked-by: Paul Mundt To: Richard Henderson To: Russell King To: Thomas Gleixner Cc: Andrew Morton Cc: linux-alpha@vger.kernel.org Cc: linux-arm-kernel@lists.infradead.org Cc: linux-kernel@vger.kernel.org Cc: linux-mips@linux-mips.org Cc: linux-pci@vger.kernel.org Cc: linux-sh@vger.kernel.org Cc: linux-tegra@vger.kernel.org Cc: sparclinux@vger.kernel.org Cc: x86@kernel.org Signed-off-by: Jesse Barnes --- drivers/pci/setup-irq.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/pci') diff --git a/drivers/pci/setup-irq.c b/drivers/pci/setup-irq.c index eec9738f349..eb219a1d16f 100644 --- a/drivers/pci/setup-irq.c +++ b/drivers/pci/setup-irq.c @@ -21,7 +21,7 @@ static void __init pdev_fixup_irq(struct pci_dev *dev, u8 (*swizzle)(struct pci_dev *, u8 *), - int (*map_irq)(struct pci_dev *, u8, u8)) + int (*map_irq)(const struct pci_dev *, u8, u8)) { u8 pin, slot; int irq = 0; @@ -56,7 +56,7 @@ pdev_fixup_irq(struct pci_dev *dev, void __init pci_fixup_irqs(u8 (*swizzle)(struct pci_dev *, u8 *), - int (*map_irq)(struct pci_dev *, u8, u8)) + int (*map_irq)(const struct pci_dev *, u8, u8)) { struct pci_dev *dev = NULL; for_each_pci_dev(dev) -- cgit v1.2.3 From 864d296cf948aef0fa32b81407541572583f7572 Mon Sep 17 00:00:00 2001 From: Chris Wright Date: Wed, 13 Jul 2011 10:14:33 -0700 Subject: PCI: ARI is a PCIe v2 feature The function pci_enable_ari() may mistakenly set the downstream port of a v1 PCIe switch in ARI Forwarding mode. This is a PCIe v2 feature, and with an SR-IOV device on that switch port believing the switch above is ARI capable it may attempt to use functions 8-255, translating into invalid (non-zero) device numbers for that bus. This has been seen to cause Completion Timeouts and general misbehaviour including hangs and panics. Cc: stable@kernel.org Acked-by: Don Dutile Tested-by: Don Dutile Signed-off-by: Chris Wright Signed-off-by: Jesse Barnes --- drivers/pci/pci.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers/pci') diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 692671b1166..d549bbc93cd 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -1905,7 +1905,7 @@ void pci_enable_ari(struct pci_dev *dev) { int pos; u32 cap; - u16 ctrl; + u16 flags, ctrl; struct pci_dev *bridge; if (!pci_is_pcie(dev) || dev->devfn) @@ -1923,6 +1923,11 @@ void pci_enable_ari(struct pci_dev *dev) if (!pos) return; + /* ARI is a PCIe v2 feature */ + pci_read_config_word(bridge, pos + PCI_EXP_FLAGS, &flags); + if ((flags & PCI_EXP_FLAGS_VERS) < 2) + return; + pci_read_config_dword(bridge, pos + PCI_EXP_DEVCAP2, &cap); if (!(cap & PCI_EXP_DEVCAP2_ARI)) return; -- cgit v1.2.3 From 0cab0841dc1400f633a7e1ac1e448518692f927a Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Mon, 11 Jul 2011 10:15:45 +0900 Subject: PCI: pciehp: change wait time for valid configuration access Naoki Yanagimoto reported that configuration read on some hot-added PCIe device returns invalid value. This patch fixes this problem. According to the PCIe spec, software must wait for at least 1 second to judge if the hot-added device is broken after Data Link Layer State Changed Event. This patch changes pciehp driver to wait for 1 second after the Data Link Layer State Changed Event is detected before initiating a configuration access instead of 100 ms. Signed-off-by: Kenji Kaneshige Tested-by: Naoki Yanagimoto Signed-off-by: Jesse Barnes --- drivers/pci/hotplug/pciehp_ctrl.c | 3 +++ drivers/pci/hotplug/pciehp_hpc.c | 11 ++--------- 2 files changed, 5 insertions(+), 9 deletions(-) (limited to 'drivers/pci') diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c index 085dbb5fc16..1e9c9aacc3a 100644 --- a/drivers/pci/hotplug/pciehp_ctrl.c +++ b/drivers/pci/hotplug/pciehp_ctrl.c @@ -213,6 +213,9 @@ static int board_added(struct slot *p_slot) goto err_exit; } + /* Wait for 1 second after checking link training status */ + msleep(1000); + /* Check for a power fault */ if (ctrl->power_fault_detected || pciehp_query_power_fault(p_slot)) { ctrl_err(ctrl, "Power fault on slot %s\n", slot_name(p_slot)); diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index 50a23da5d24..96dc4734e4a 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c @@ -275,16 +275,9 @@ int pciehp_check_link_status(struct controller *ctrl) * hot-plug capable downstream port. But old controller might * not implement it. In this case, we wait for 1000 ms. */ - if (ctrl->link_active_reporting){ - /* Wait for Data Link Layer Link Active bit to be set */ + if (ctrl->link_active_reporting) pcie_wait_link_active(ctrl); - /* - * We must wait for 100 ms after the Data Link Layer - * Link Active bit reads 1b before initiating a - * configuration access to the hot added device. - */ - msleep(100); - } else + else msleep(1000); retval = pciehp_readw(ctrl, PCI_EXP_LNKSTA, &lnk_status); -- cgit v1.2.3 From c9b378c7cbf623649e4ca64f955f2afd12ef01b2 Mon Sep 17 00:00:00 2001 From: Jon Mason Date: Tue, 28 Jun 2011 18:26:25 -0500 Subject: PCI: correct pcie_set_readrq write size When setting the PCI-E MRRS, pcie_set_readrq queries the current settings via a pci_read_config_word call but writes the modified result via a pci_write_config_dword. This results in writing 16 more bits than were queried. Also, the function description comment is slightly incorrect. Signed-off-by: Jon Mason Signed-off-by: Jesse Barnes --- drivers/pci/pci.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/pci') diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index d549bbc93cd..08a95b369d8 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -3191,7 +3191,7 @@ EXPORT_SYMBOL(pcie_get_readrq); * @rq: maximum memory read count in bytes * valid values are 128, 256, 512, 1024, 2048, 4096 * - * If possible sets maximum read byte count + * If possible sets maximum memory read request in bytes */ int pcie_set_readrq(struct pci_dev *dev, int rq) { @@ -3214,7 +3214,7 @@ int pcie_set_readrq(struct pci_dev *dev, int rq) if ((ctl & PCI_EXP_DEVCTL_READRQ) != v) { ctl &= ~PCI_EXP_DEVCTL_READRQ; ctl |= v; - err = pci_write_config_dword(dev, cap + PCI_EXP_DEVCTL, ctl); + err = pci_write_config_word(dev, cap + PCI_EXP_DEVCTL, ctl); } out: -- cgit v1.2.3 From 8d6a6a47636648754dc371b01228520a2adaf430 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Tue, 14 Jun 2011 13:04:29 -0600 Subject: PCI: treat mem BAR type "11" (reserved) as 32-bit, not 64-bit, BAR This fixes a minor regression where broken PCI devices that use the reserved "11" memory BAR type worked before e354597cce but not after. The low four bits of a memory BAR are "PTT0" where P=1 for prefetchable BARs, and TT is as follows: 00 32-bit BAR, anywhere in lower 4GB 01 anywhere below 1MB (reserved as of PCI 2.2) 10 64-bit BAR 11 reserved Prior to e354597cce, we treated "0100" as a 64-bit BAR and all others, including prefetchable 64-bit BARs ("1100") as 32-bit BARs. The e354597cce fix, which appeared in 2.6.28, treats "x1x0" as 64-bit BARs, so the reserved "x110" types are treated as 64-bit instead of 32-bit. This patch returns to treating the reserved "11" type as a 32-bit BAR and adds a warning if we see it. It also logs a note if we see a 1M BAR. This is not a warning, because such hardware conforms to pre-PCI 2.2 spec, but I think it's worth noting because Linux ignores the 1M restriction if it ever has to assign the BAR. CC: Peter Chubb Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=35952 Reported-by: Jan Zwiegers Signed-off-by: Bjorn Helgaas Signed-off-by: Jesse Barnes --- drivers/pci/probe.c | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) (limited to 'drivers/pci') diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index f03ed96533d..3e7a00a3fc8 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -100,8 +100,11 @@ static u64 pci_size(u64 base, u64 maxbase, u64 mask) return size; } -static inline enum pci_bar_type decode_bar(struct resource *res, u32 bar) +static inline enum pci_bar_type decode_bar(struct pci_dev *dev, + struct resource *res, u32 bar) { + u32 mem_type; + if ((bar & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO) { res->flags = bar & ~PCI_BASE_ADDRESS_IO_MASK; return pci_bar_io; @@ -109,8 +112,21 @@ static inline enum pci_bar_type decode_bar(struct resource *res, u32 bar) res->flags = bar & ~PCI_BASE_ADDRESS_MEM_MASK; - if (res->flags & PCI_BASE_ADDRESS_MEM_TYPE_64) + mem_type = bar & PCI_BASE_ADDRESS_MEM_TYPE_MASK; + switch (mem_type) { + case PCI_BASE_ADDRESS_MEM_TYPE_32: + break; + case PCI_BASE_ADDRESS_MEM_TYPE_1M: + dev_info(&dev->dev, "1M mem BAR treated as 32-bit BAR\n"); + break; + case PCI_BASE_ADDRESS_MEM_TYPE_64: return pci_bar_mem64; + default: + dev_warn(&dev->dev, + "mem unknown type %x treated as 32-bit BAR\n", + mem_type); + break; + } return pci_bar_mem32; } @@ -164,7 +180,7 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, l = 0; if (type == pci_bar_unknown) { - type = decode_bar(res, l); + type = decode_bar(dev, res, l); res->flags |= pci_calc_resource_flags(l) | IORESOURCE_SIZEALIGN; if (type == pci_bar_io) { l &= PCI_BASE_ADDRESS_IO_MASK; -- cgit v1.2.3 From 28c6821a0f8e686d4f1a6107d970705d37475d87 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Tue, 14 Jun 2011 13:04:35 -0600 Subject: PCI: fold pci_calc_resource_flags() into decode_bar() decode_bar() and pci_calc_resource_flags() both looked at the PCI BAR type information, and it's simpler to just do it all in one place. decode_bar() sets IORESOURCE_IO, IORESOURCE_MEM, and IORESOURCE_MEM_64 as appropriate, so res->flags contains all the information pci_bar_type does, so we don't need to test the pci_bar_type return value. decode_bar() used to return pci_bar_type, which we no longer need. We can simplify it a bit by returning the struct resource flags rather than updating them internally. In pci_update_resource(), there's no need to decode the BAR type bits again; we can just test for IORESOURCE_MEM_64 directly. Signed-off-by: Bjorn Helgaas Signed-off-by: Jesse Barnes --- drivers/pci/probe.c | 45 +++++++++++++++++---------------------------- drivers/pci/setup-res.c | 3 +-- 2 files changed, 18 insertions(+), 30 deletions(-) (limited to 'drivers/pci') diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 3e7a00a3fc8..ef17cf99830 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -67,21 +67,6 @@ static int __init pcibus_class_init(void) } postcore_initcall(pcibus_class_init); -/* - * Translate the low bits of the PCI base - * to the resource type - */ -static inline unsigned int pci_calc_resource_flags(unsigned int flags) -{ - if (flags & PCI_BASE_ADDRESS_SPACE_IO) - return IORESOURCE_IO; - - if (flags & PCI_BASE_ADDRESS_MEM_PREFETCH) - return IORESOURCE_MEM | IORESOURCE_PREFETCH; - - return IORESOURCE_MEM; -} - static u64 pci_size(u64 base, u64 maxbase, u64 mask) { u64 size = mask & maxbase; /* Find the significant bits */ @@ -100,17 +85,21 @@ static u64 pci_size(u64 base, u64 maxbase, u64 mask) return size; } -static inline enum pci_bar_type decode_bar(struct pci_dev *dev, - struct resource *res, u32 bar) +static inline unsigned long decode_bar(struct pci_dev *dev, u32 bar) { u32 mem_type; + unsigned long flags; if ((bar & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO) { - res->flags = bar & ~PCI_BASE_ADDRESS_IO_MASK; - return pci_bar_io; + flags = bar & ~PCI_BASE_ADDRESS_IO_MASK; + flags |= IORESOURCE_IO; + return flags; } - res->flags = bar & ~PCI_BASE_ADDRESS_MEM_MASK; + flags = bar & ~PCI_BASE_ADDRESS_MEM_MASK; + flags |= IORESOURCE_MEM; + if (flags & PCI_BASE_ADDRESS_MEM_PREFETCH) + flags |= IORESOURCE_PREFETCH; mem_type = bar & PCI_BASE_ADDRESS_MEM_TYPE_MASK; switch (mem_type) { @@ -120,14 +109,15 @@ static inline enum pci_bar_type decode_bar(struct pci_dev *dev, dev_info(&dev->dev, "1M mem BAR treated as 32-bit BAR\n"); break; case PCI_BASE_ADDRESS_MEM_TYPE_64: - return pci_bar_mem64; + flags |= IORESOURCE_MEM_64; + break; default: dev_warn(&dev->dev, "mem unknown type %x treated as 32-bit BAR\n", mem_type); break; } - return pci_bar_mem32; + return flags; } /** @@ -180,9 +170,9 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, l = 0; if (type == pci_bar_unknown) { - type = decode_bar(dev, res, l); - res->flags |= pci_calc_resource_flags(l) | IORESOURCE_SIZEALIGN; - if (type == pci_bar_io) { + res->flags = decode_bar(dev, l); + res->flags |= IORESOURCE_SIZEALIGN; + if (res->flags & IORESOURCE_IO) { l &= PCI_BASE_ADDRESS_IO_MASK; mask = PCI_BASE_ADDRESS_IO_MASK & (u32) IO_SPACE_LIMIT; } else { @@ -195,7 +185,7 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, mask = (u32)PCI_ROM_ADDRESS_MASK; } - if (type == pci_bar_mem64) { + if (res->flags & IORESOURCE_MEM_64) { u64 l64 = l; u64 sz64 = sz; u64 mask64 = mask | (u64)~0 << 32; @@ -219,7 +209,6 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, goto fail; } - res->flags |= IORESOURCE_MEM_64; if ((sizeof(resource_size_t) < 8) && l) { /* Address above 32-bit boundary; disable the BAR */ pci_write_config_dword(dev, pos, 0); @@ -245,7 +234,7 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, } out: - return (type == pci_bar_mem64) ? 1 : 0; + return (res->flags & IORESOURCE_MEM_64) ? 1 : 0; fail: res->flags = 0; goto out; diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c index bc0e6eea0ff..319f359906e 100644 --- a/drivers/pci/setup-res.c +++ b/drivers/pci/setup-res.c @@ -74,8 +74,7 @@ void pci_update_resource(struct pci_dev *dev, int resno) resno, new, check); } - if ((new & (PCI_BASE_ADDRESS_SPACE|PCI_BASE_ADDRESS_MEM_TYPE_MASK)) == - (PCI_BASE_ADDRESS_SPACE_MEMORY|PCI_BASE_ADDRESS_MEM_TYPE_64)) { + if (res->flags & IORESOURCE_MEM_64) { new = region.start >> 16 >> 16; pci_write_config_dword(dev, reg + 4, new); pci_read_config_dword(dev, reg + 4, &check); -- cgit v1.2.3 From 7b87c9df5602efd6c7edeb291bbd104d49a6babf Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Tue, 14 Jun 2011 13:04:40 -0600 Subject: PCI: remove printks about disabled bridge windows I don't think there's enough value in the fact of a bridge window being disabled to justify cluttering the dmesg log with it. Signed-off-by: Bjorn Helgaas Signed-off-by: Jesse Barnes --- drivers/pci/probe.c | 12 ------------ drivers/pci/setup-bus.c | 3 --- 2 files changed, 15 deletions(-) (limited to 'drivers/pci') diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index ef17cf99830..fd6066dfde5 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -288,10 +288,6 @@ static void __devinit pci_read_bridge_io(struct pci_bus *child) if (!res->end) res->end = limit + 0xfff; dev_printk(KERN_DEBUG, &dev->dev, " bridge window %pR\n", res); - } else { - dev_printk(KERN_DEBUG, &dev->dev, - " bridge window [io %#06lx-%#06lx] (disabled)\n", - base, limit); } } @@ -312,10 +308,6 @@ static void __devinit pci_read_bridge_mmio(struct pci_bus *child) res->start = base; res->end = limit + 0xfffff; dev_printk(KERN_DEBUG, &dev->dev, " bridge window %pR\n", res); - } else { - dev_printk(KERN_DEBUG, &dev->dev, - " bridge window [mem %#010lx-%#010lx] (disabled)\n", - base, limit + 0xfffff); } } @@ -363,10 +355,6 @@ static void __devinit pci_read_bridge_mmio_pref(struct pci_bus *child) res->start = base; res->end = limit + 0xfffff; dev_printk(KERN_DEBUG, &dev->dev, " bridge window %pR\n", res); - } else { - dev_printk(KERN_DEBUG, &dev->dev, - " bridge window [mem %#010lx-%#010lx pref] (disabled)\n", - base, limit + 0xfffff); } } diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index 9995842e45b..8a1d3c7863a 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c @@ -336,7 +336,6 @@ static void pci_setup_bridge_io(struct pci_bus *bus) /* Clear upper 16 bits of I/O base/limit. */ io_upper16 = 0; l = 0x00f0; - dev_info(&bridge->dev, " bridge window [io disabled]\n"); } /* Temporarily disable the I/O range before updating PCI_IO_BASE. */ pci_write_config_dword(bridge, PCI_IO_BASE_UPPER16, 0x0000ffff); @@ -362,7 +361,6 @@ static void pci_setup_bridge_mmio(struct pci_bus *bus) dev_info(&bridge->dev, " bridge window %pR\n", res); } else { l = 0x0000fff0; - dev_info(&bridge->dev, " bridge window [mem disabled]\n"); } pci_write_config_dword(bridge, PCI_MEMORY_BASE, l); } @@ -393,7 +391,6 @@ static void pci_setup_bridge_mmio_pref(struct pci_bus *bus) dev_info(&bridge->dev, " bridge window %pR\n", res); } else { l = 0x0000fff0; - dev_info(&bridge->dev, " bridge window [mem pref disabled]\n"); } pci_write_config_dword(bridge, PCI_PREF_MEMORY_BASE, l); -- cgit v1.2.3