diff options
Diffstat (limited to 'drivers/pci')
-rw-r--r-- | drivers/pci/access.c | 40 | ||||
-rw-r--r-- | drivers/pci/hotplug/ibmphp_pci.c | 10 | ||||
-rw-r--r-- | drivers/pci/hotplug/pciehp_hpc.c | 12 | ||||
-rw-r--r-- | drivers/pci/pci-sysfs.c | 4 | ||||
-rw-r--r-- | drivers/pci/pci.c | 8 | ||||
-rw-r--r-- | drivers/pci/pcie/aer.c | 15 | ||||
-rw-r--r-- | drivers/pci/pcie/aspm.c | 30 | ||||
-rw-r--r-- | drivers/pci/probe.c | 1 | ||||
-rw-r--r-- | drivers/pci/quirks.c | 2 |
9 files changed, 57 insertions, 65 deletions
diff --git a/drivers/pci/access.c b/drivers/pci/access.c index 3c230ca3de58..6554a2e89d36 100644 --- a/drivers/pci/access.c +++ b/drivers/pci/access.c @@ -497,22 +497,35 @@ int pcie_capability_write_dword(struct pci_dev *dev, int pos, u32 val) } EXPORT_SYMBOL(pcie_capability_write_dword); -int pcie_capability_clear_and_set_word(struct pci_dev *dev, int pos, - u16 clear, u16 set) +int pcie_capability_clear_and_set_word_unlocked(struct pci_dev *dev, int pos, + u16 clear, u16 set) { int ret; u16 val; ret = pcie_capability_read_word(dev, pos, &val); - if (!ret) { - val &= ~clear; - val |= set; - ret = pcie_capability_write_word(dev, pos, val); - } + if (ret) + return ret; + + val &= ~clear; + val |= set; + return pcie_capability_write_word(dev, pos, val); +} +EXPORT_SYMBOL(pcie_capability_clear_and_set_word_unlocked); + +int pcie_capability_clear_and_set_word_locked(struct pci_dev *dev, int pos, + u16 clear, u16 set) +{ + unsigned long flags; + int ret; + + spin_lock_irqsave(&dev->pcie_cap_lock, flags); + ret = pcie_capability_clear_and_set_word_unlocked(dev, pos, clear, set); + spin_unlock_irqrestore(&dev->pcie_cap_lock, flags); return ret; } -EXPORT_SYMBOL(pcie_capability_clear_and_set_word); +EXPORT_SYMBOL(pcie_capability_clear_and_set_word_locked); int pcie_capability_clear_and_set_dword(struct pci_dev *dev, int pos, u32 clear, u32 set) @@ -521,13 +534,12 @@ int pcie_capability_clear_and_set_dword(struct pci_dev *dev, int pos, u32 val; ret = pcie_capability_read_dword(dev, pos, &val); - if (!ret) { - val &= ~clear; - val |= set; - ret = pcie_capability_write_dword(dev, pos, val); - } + if (ret) + return ret; - return ret; + val &= ~clear; + val |= set; + return pcie_capability_write_dword(dev, pos, val); } EXPORT_SYMBOL(pcie_capability_clear_and_set_dword); diff --git a/drivers/pci/hotplug/ibmphp_pci.c b/drivers/pci/hotplug/ibmphp_pci.c index 754c3f23282e..50038e5f9ca4 100644 --- a/drivers/pci/hotplug/ibmphp_pci.c +++ b/drivers/pci/hotplug/ibmphp_pci.c @@ -329,7 +329,7 @@ error: static int configure_device(struct pci_func *func) { u32 bar[6]; - u32 address[] = { + static const u32 address[] = { PCI_BASE_ADDRESS_0, PCI_BASE_ADDRESS_1, PCI_BASE_ADDRESS_2, @@ -564,7 +564,7 @@ static int configure_bridge(struct pci_func **func_passed, u8 slotno) struct resource_node *pfmem = NULL; struct resource_node *bus_pfmem[2] = {NULL, NULL}; struct bus_node *bus; - u32 address[] = { + static const u32 address[] = { PCI_BASE_ADDRESS_0, PCI_BASE_ADDRESS_1, 0 @@ -1053,7 +1053,7 @@ static struct res_needed *scan_behind_bridge(struct pci_func *func, u8 busno) int howmany = 0; /*this is to see if there are any devices behind the bridge */ u32 bar[6], class; - u32 address[] = { + static const u32 address[] = { PCI_BASE_ADDRESS_0, PCI_BASE_ADDRESS_1, PCI_BASE_ADDRESS_2, @@ -1182,7 +1182,7 @@ static struct res_needed *scan_behind_bridge(struct pci_func *func, u8 busno) static int unconfigure_boot_device(u8 busno, u8 device, u8 function) { u32 start_address; - u32 address[] = { + static const u32 address[] = { PCI_BASE_ADDRESS_0, PCI_BASE_ADDRESS_1, PCI_BASE_ADDRESS_2, @@ -1310,7 +1310,7 @@ static int unconfigure_boot_bridge(u8 busno, u8 device, u8 function) struct resource_node *mem = NULL; struct resource_node *pfmem = NULL; struct bus_node *bus; - u32 address[] = { + static const u32 address[] = { PCI_BASE_ADDRESS_0, PCI_BASE_ADDRESS_1, 0 diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index 8711325605f0..fd713abdfb9f 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c @@ -332,17 +332,11 @@ int pciehp_check_link_status(struct controller *ctrl) static int __pciehp_link_set(struct controller *ctrl, bool enable) { struct pci_dev *pdev = ctrl_dev(ctrl); - u16 lnk_ctrl; - pcie_capability_read_word(pdev, PCI_EXP_LNKCTL, &lnk_ctrl); + pcie_capability_clear_and_set_word(pdev, PCI_EXP_LNKCTL, + PCI_EXP_LNKCTL_LD, + enable ? 0 : PCI_EXP_LNKCTL_LD); - if (enable) - lnk_ctrl &= ~PCI_EXP_LNKCTL_LD; - else - lnk_ctrl |= PCI_EXP_LNKCTL_LD; - - pcie_capability_write_word(pdev, PCI_EXP_LNKCTL, lnk_ctrl); - ctrl_dbg(ctrl, "%s: lnk_ctrl = %x\n", __func__, lnk_ctrl); return 0; } diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index ab32a91f287b..d9eede2dbc0e 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c @@ -1083,6 +1083,7 @@ static ssize_t pci_resource_io(struct file *filp, struct kobject *kobj, struct bin_attribute *attr, char *buf, loff_t off, size_t count, bool write) { +#ifdef CONFIG_HAS_IOPORT struct pci_dev *pdev = to_pci_dev(kobj_to_dev(kobj)); int bar = (unsigned long)attr->private; unsigned long port = off; @@ -1116,6 +1117,9 @@ static ssize_t pci_resource_io(struct file *filp, struct kobject *kobj, return 4; } return -EINVAL; +#else + return -ENXIO; +#endif } static ssize_t pci_read_resource_io(struct file *filp, struct kobject *kobj, diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 39728196e295..702fe577089b 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -4932,7 +4932,6 @@ static int pcie_wait_for_link_status(struct pci_dev *pdev, int pcie_retrain_link(struct pci_dev *pdev, bool use_lt) { int rc; - u16 lnkctl; /* * Ensure the updated LNKCTL parameters are used during link @@ -4944,17 +4943,14 @@ int pcie_retrain_link(struct pci_dev *pdev, bool use_lt) if (rc) return rc; - pcie_capability_read_word(pdev, PCI_EXP_LNKCTL, &lnkctl); - lnkctl |= PCI_EXP_LNKCTL_RL; - pcie_capability_write_word(pdev, PCI_EXP_LNKCTL, lnkctl); + pcie_capability_set_word(pdev, PCI_EXP_LNKCTL, PCI_EXP_LNKCTL_RL); if (pdev->clear_retrain_link) { /* * Due to an erratum in some devices the Retrain Link bit * needs to be cleared again manually to allow the link * training to succeed. */ - lnkctl &= ~PCI_EXP_LNKCTL_RL; - pcie_capability_write_word(pdev, PCI_EXP_LNKCTL, lnkctl); + pcie_capability_clear_word(pdev, PCI_EXP_LNKCTL, PCI_EXP_LNKCTL_RL); } return pcie_wait_for_link_status(pdev, use_lt, !use_lt); diff --git a/drivers/pci/pcie/aer.c b/drivers/pci/pcie/aer.c index f6c24ded134c..645149608054 100644 --- a/drivers/pci/pcie/aer.c +++ b/drivers/pci/pcie/aer.c @@ -230,7 +230,7 @@ int pcie_aer_is_native(struct pci_dev *dev) return pcie_ports_native || host->native_aer; } -int pci_enable_pcie_error_reporting(struct pci_dev *dev) +static int pci_enable_pcie_error_reporting(struct pci_dev *dev) { int rc; @@ -240,19 +240,6 @@ int pci_enable_pcie_error_reporting(struct pci_dev *dev) rc = pcie_capability_set_word(dev, PCI_EXP_DEVCTL, PCI_EXP_AER_FLAGS); return pcibios_err_to_errno(rc); } -EXPORT_SYMBOL_GPL(pci_enable_pcie_error_reporting); - -int pci_disable_pcie_error_reporting(struct pci_dev *dev) -{ - int rc; - - if (!pcie_aer_is_native(dev)) - return -EIO; - - rc = pcie_capability_clear_word(dev, PCI_EXP_DEVCTL, PCI_EXP_AER_FLAGS); - return pcibios_err_to_errno(rc); -} -EXPORT_SYMBOL_GPL(pci_disable_pcie_error_reporting); int pci_aer_clear_nonfatal_status(struct pci_dev *dev) { diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c index 3dafba0b5f41..1bf630059264 100644 --- a/drivers/pci/pcie/aspm.c +++ b/drivers/pci/pcie/aspm.c @@ -199,7 +199,7 @@ static void pcie_clkpm_cap_init(struct pcie_link_state *link, int blacklist) static void pcie_aspm_configure_common_clock(struct pcie_link_state *link) { int same_clock = 1; - u16 reg16, parent_reg, child_reg[8]; + u16 reg16, ccc, parent_old_ccc, child_old_ccc[8]; struct pci_dev *child, *parent = link->pdev; struct pci_bus *linkbus = parent->subordinate; /* @@ -221,6 +221,7 @@ static void pcie_aspm_configure_common_clock(struct pcie_link_state *link) /* Port might be already in common clock mode */ pcie_capability_read_word(parent, PCI_EXP_LNKCTL, ®16); + parent_old_ccc = reg16 & PCI_EXP_LNKCTL_CCC; if (same_clock && (reg16 & PCI_EXP_LNKCTL_CCC)) { bool consistent = true; @@ -237,34 +238,29 @@ static void pcie_aspm_configure_common_clock(struct pcie_link_state *link) pci_info(parent, "ASPM: current common clock configuration is inconsistent, reconfiguring\n"); } + ccc = same_clock ? PCI_EXP_LNKCTL_CCC : 0; /* Configure downstream component, all functions */ list_for_each_entry(child, &linkbus->devices, bus_list) { pcie_capability_read_word(child, PCI_EXP_LNKCTL, ®16); - child_reg[PCI_FUNC(child->devfn)] = reg16; - if (same_clock) - reg16 |= PCI_EXP_LNKCTL_CCC; - else - reg16 &= ~PCI_EXP_LNKCTL_CCC; - pcie_capability_write_word(child, PCI_EXP_LNKCTL, reg16); + child_old_ccc[PCI_FUNC(child->devfn)] = reg16 & PCI_EXP_LNKCTL_CCC; + pcie_capability_clear_and_set_word(child, PCI_EXP_LNKCTL, + PCI_EXP_LNKCTL_CCC, ccc); } /* Configure upstream component */ - pcie_capability_read_word(parent, PCI_EXP_LNKCTL, ®16); - parent_reg = reg16; - if (same_clock) - reg16 |= PCI_EXP_LNKCTL_CCC; - else - reg16 &= ~PCI_EXP_LNKCTL_CCC; - pcie_capability_write_word(parent, PCI_EXP_LNKCTL, reg16); + pcie_capability_clear_and_set_word(parent, PCI_EXP_LNKCTL, + PCI_EXP_LNKCTL_CCC, ccc); if (pcie_retrain_link(link->pdev, true)) { /* Training failed. Restore common clock configurations */ pci_err(parent, "ASPM: Could not configure common clock\n"); list_for_each_entry(child, &linkbus->devices, bus_list) - pcie_capability_write_word(child, PCI_EXP_LNKCTL, - child_reg[PCI_FUNC(child->devfn)]); - pcie_capability_write_word(parent, PCI_EXP_LNKCTL, parent_reg); + pcie_capability_clear_and_set_word(child, PCI_EXP_LNKCTL, + PCI_EXP_LNKCTL_CCC, + child_old_ccc[PCI_FUNC(child->devfn)]); + pcie_capability_clear_and_set_word(parent, PCI_EXP_LNKCTL, + PCI_EXP_LNKCTL_CCC, parent_old_ccc); } } diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 8bac3ce02609..f1587fb0ba71 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -2324,6 +2324,7 @@ struct pci_dev *pci_alloc_dev(struct pci_bus *bus) .end = -1, }; + spin_lock_init(&dev->pcie_cap_lock); #ifdef CONFIG_PCI_MSI raw_spin_lock_init(&dev->msi_lock); #endif diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 321156ca273d..ef193661c3d1 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -361,6 +361,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_CBUS_2, quirk_isa_d DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_CBUS_3, quirk_isa_dma_hangs); #endif +#ifdef CONFIG_HAS_IOPORT /* * Intel NM10 "TigerPoint" LPC PM1a_STS.BM_STS must be clear * for some HT machines to use C4 w/o hanging. @@ -380,6 +381,7 @@ static void quirk_tigerpoint_bm_sts(struct pci_dev *dev) } } DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_TGP_LPC, quirk_tigerpoint_bm_sts); +#endif /* Chipsets where PCI->PCI transfers vanish or hang */ static void quirk_nopcipci(struct pci_dev *dev) |