]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blobdiff - drivers/pci/pci.c
PCI: Avoid slot reset if bridge itself is broken
[mirror_ubuntu-artful-kernel.git] / drivers / pci / pci.c
index da5570cf5c6a4eddf115da1e18cfd6c1643c88e2..ba6b9b908acbefcabaf8a67512f81f5a347e1fd2 100644 (file)
@@ -514,7 +514,7 @@ EXPORT_SYMBOL(pci_find_resource);
  */
 struct pci_dev *pci_find_pcie_root_port(struct pci_dev *dev)
 {
-       struct pci_dev *bridge, *highest_pcie_bridge = NULL;
+       struct pci_dev *bridge, *highest_pcie_bridge = dev;
 
        bridge = pci_upstream_bridge(dev);
        while (bridge && pci_is_pcie(bridge)) {
@@ -522,11 +522,10 @@ struct pci_dev *pci_find_pcie_root_port(struct pci_dev *dev)
                bridge = pci_upstream_bridge(bridge);
        }
 
-       if (highest_pcie_bridge &&
-           pci_pcie_type(highest_pcie_bridge) == PCI_EXP_TYPE_ROOT_PORT)
-               return highest_pcie_bridge;
+       if (pci_pcie_type(highest_pcie_bridge) != PCI_EXP_TYPE_ROOT_PORT)
+               return NULL;
 
-       return NULL;
+       return highest_pcie_bridge;
 }
 EXPORT_SYMBOL(pci_find_pcie_root_port);
 
@@ -1891,7 +1890,7 @@ void pci_pme_active(struct pci_dev *dev, bool enable)
 EXPORT_SYMBOL(pci_pme_active);
 
 /**
- * pci_enable_wake - enable PCI device as wakeup event source
+ * __pci_enable_wake - enable PCI device as wakeup event source
  * @dev: PCI device affected
  * @state: PCI state from which device will issue wakeup events
  * @enable: True to enable event generation; false to disable
@@ -1909,7 +1908,7 @@ EXPORT_SYMBOL(pci_pme_active);
  * Error code depending on the platform is returned if both the platform and
  * the native mechanism fail to enable the generation of wake-up events
  */
-int pci_enable_wake(struct pci_dev *dev, pci_power_t state, bool enable)
+static int __pci_enable_wake(struct pci_dev *dev, pci_power_t state, bool enable)
 {
        int ret = 0;
 
@@ -1943,6 +1942,23 @@ int pci_enable_wake(struct pci_dev *dev, pci_power_t state, bool enable)
 
        return ret;
 }
+
+/**
+ * pci_enable_wake - change wakeup settings for a PCI device
+ * @pci_dev: Target device
+ * @state: PCI state from which device will issue wakeup events
+ * @enable: Whether or not to enable event generation
+ *
+ * If @enable is set, check device_may_wakeup() for the device before calling
+ * __pci_enable_wake() for it.
+ */
+int pci_enable_wake(struct pci_dev *pci_dev, pci_power_t state, bool enable)
+{
+       if (enable && !device_may_wakeup(&pci_dev->dev))
+               return -EINVAL;
+
+       return __pci_enable_wake(pci_dev, state, enable);
+}
 EXPORT_SYMBOL(pci_enable_wake);
 
 /**
@@ -1955,9 +1971,9 @@ EXPORT_SYMBOL(pci_enable_wake);
  * should not be called twice in a row to enable wake-up due to PCI PM vs ACPI
  * ordering constraints.
  *
- * This function only returns error code if the device is not capable of
- * generating PME# from both D3_hot and D3_cold, and the platform is unable to
- * enable wake-up power for it.
+ * This function only returns error code if the device is not allowed to wake
+ * up the system from sleep or it is not capable of generating PME# from both
+ * D3_hot and D3_cold and the platform is unable to enable wake-up power for it.
  */
 int pci_wake_from_d3(struct pci_dev *dev, bool enable)
 {
@@ -2088,7 +2104,7 @@ int pci_finish_runtime_suspend(struct pci_dev *dev)
 
        dev->runtime_d3cold = target_state == PCI_D3cold;
 
-       pci_enable_wake(dev, target_state, pci_dev_run_wake(dev));
+       __pci_enable_wake(dev, target_state, pci_dev_run_wake(dev));
 
        error = pci_set_power_state(dev, target_state);
 
@@ -2112,16 +2128,16 @@ bool pci_dev_run_wake(struct pci_dev *dev)
 {
        struct pci_bus *bus = dev->bus;
 
-       if (device_can_wakeup(&dev->dev))
-               return true;
-
        if (!dev->pme_support)
                return false;
 
        /* PME-capable in principle, but not from the target power state */
-       if (!pci_pme_capable(dev, pci_target_state(dev, false)))
+       if (!pci_pme_capable(dev, pci_target_state(dev, true)))
                return false;
 
+       if (device_can_wakeup(&dev->dev))
+               return true;
+
        while (bus->parent) {
                struct pci_dev *bridge = bus->self;
 
@@ -3256,7 +3272,7 @@ int pci_request_regions_exclusive(struct pci_dev *pdev, const char *res_name)
 }
 EXPORT_SYMBOL(pci_request_regions_exclusive);
 
-#ifdef PCI_IOBASE
+#if defined(PCI_IOBASE) && !defined(CONFIG_LIBIO)
 struct io_range {
        struct list_head list;
        phys_addr_t start;
@@ -3271,11 +3287,35 @@ static DEFINE_SPINLOCK(io_range_lock);
  * Record the PCI IO range (expressed as CPU physical address + size).
  * Return a negative value if an error has occured, zero otherwise
  */
-int __weak pci_register_io_range(phys_addr_t addr, resource_size_t size)
+int pci_register_io_range(struct fwnode_handle *fwnode, phys_addr_t addr,
+                       resource_size_t size)
 {
        int err = 0;
 
 #ifdef PCI_IOBASE
+#ifdef CONFIG_LIBIO
+       struct libio_range *range, *tmprange;
+
+       if (!size || addr + size < addr)
+               return -EINVAL;
+
+       WARN_ON(!PAGE_ALIGNED(addr) || !PAGE_ALIGNED(size));
+
+       range = kzalloc(sizeof(*range), GFP_KERNEL);
+       if (!range)
+               return -ENOMEM;
+       range->node = fwnode;
+       range->flags = IO_CPU_MMIO;
+       range->size = size;
+       range->hw_start = addr;
+
+       tmprange = register_libio_range(range);
+       if (tmprange != range) {
+               kfree(range);
+               if (IS_ERR(tmprange))
+                       return -EFAULT;
+       }
+#else
        struct io_range *range;
        resource_size_t allocated_size = 0;
 
@@ -3315,7 +3355,8 @@ int __weak pci_register_io_range(phys_addr_t addr, resource_size_t size)
 
 end_register:
        spin_unlock(&io_range_lock);
-#endif
+#endif /* CONFIG_LIBIO */
+#endif /* PCI_IOBASE */
 
        return err;
 }
@@ -3325,6 +3366,12 @@ phys_addr_t pci_pio_to_address(unsigned long pio)
        phys_addr_t address = (phys_addr_t)OF_BAD_ADDR;
 
 #ifdef PCI_IOBASE
+#ifdef CONFIG_LIBIO
+       if (pio > IO_SPACE_LIMIT)
+               return address;
+
+       address = libio_to_hwaddr(pio);
+#else
        struct io_range *range;
        resource_size_t allocated_size = 0;
 
@@ -3340,7 +3387,8 @@ phys_addr_t pci_pio_to_address(unsigned long pio)
                allocated_size += range->size;
        }
        spin_unlock(&io_range_lock);
-#endif
+#endif /* CONFIG_LIBIO */
+#endif /* PCI_IOBASE */
 
        return address;
 }
@@ -3348,6 +3396,9 @@ phys_addr_t pci_pio_to_address(unsigned long pio)
 unsigned long __weak pci_address_to_pio(phys_addr_t address)
 {
 #ifdef PCI_IOBASE
+#ifdef CONFIG_LIBIO
+       return libio_translate_cpuaddr(address);
+#else
        struct io_range *res;
        resource_size_t offset = 0;
        unsigned long addr = -1;
@@ -3363,10 +3414,12 @@ unsigned long __weak pci_address_to_pio(phys_addr_t address)
        spin_unlock(&io_range_lock);
 
        return addr;
+#endif
 #else
+#ifndef CONFIG_LIBIO
        if (address > IO_SPACE_LIMIT)
                return (unsigned long)-1;
-
+#endif
        return (unsigned long) address;
 #endif
 }
@@ -4326,6 +4379,10 @@ static bool pci_bus_resetable(struct pci_bus *bus)
 {
        struct pci_dev *dev;
 
+
+       if (bus->self && (bus->self->dev_flags & PCI_DEV_FLAGS_NO_BUS_RESET))
+               return false;
+
        list_for_each_entry(dev, &bus->devices, bus_list) {
                if (dev->dev_flags & PCI_DEV_FLAGS_NO_BUS_RESET ||
                    (dev->subordinate && !pci_bus_resetable(dev->subordinate)))
@@ -4390,6 +4447,10 @@ static bool pci_slot_resetable(struct pci_slot *slot)
 {
        struct pci_dev *dev;
 
+       if (slot->bus->self &&
+           (slot->bus->self->dev_flags & PCI_DEV_FLAGS_NO_BUS_RESET))
+               return false;
+
        list_for_each_entry(dev, &slot->bus->devices, bus_list) {
                if (!dev->slot || dev->slot != slot)
                        continue;