Merge branch 'for-john' of git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi...
[firefly-linux-kernel-4.4.55.git] / drivers / pci / pci.c
index fdbc294821e6468d55ca7d5fd68162b407607e97..7325d43bf030ce65d5f386f6aeeeb3bfa4d5c482 100644 (file)
@@ -108,12 +108,12 @@ static bool pcie_ari_disabled;
  */
 unsigned char pci_bus_max_busnr(struct pci_bus* bus)
 {
-       struct list_head *tmp;
+       struct pci_bus *tmp;
        unsigned char max, n;
 
        max = bus->busn_res.end;
-       list_for_each(tmp, &bus->children) {
-               n = pci_bus_max_busnr(pci_bus_b(tmp));
+       list_for_each_entry(tmp, &bus->children, node) {
+               n = pci_bus_max_busnr(tmp);
                if(n > max)
                        max = n;
        }
@@ -401,33 +401,40 @@ EXPORT_SYMBOL_GPL(pci_find_ht_capability);
  * @res: child resource record for which parent is sought
  *
  *  For given resource region of given device, return the resource
- *  region of parent bus the given region is contained in or where
- *  it should be allocated from.
+ *  region of parent bus the given region is contained in.
  */
 struct resource *
 pci_find_parent_resource(const struct pci_dev *dev, struct resource *res)
 {
        const struct pci_bus *bus = dev->bus;
+       struct resource *r;
        int i;
-       struct resource *best = NULL, *r;
 
        pci_bus_for_each_resource(bus, r, i) {
                if (!r)
                        continue;
-               if (res->start && !(res->start >= r->start && res->end <= r->end))
-                       continue;       /* Not contained */
-               if ((res->flags ^ r->flags) & (IORESOURCE_IO | IORESOURCE_MEM))
-                       continue;       /* Wrong type */
-               if (!((res->flags ^ r->flags) & IORESOURCE_PREFETCH))
-                       return r;       /* Exact match */
-               /* We can't insert a non-prefetch resource inside a prefetchable parent .. */
-               if (r->flags & IORESOURCE_PREFETCH)
-                       continue;
-               /* .. but we can put a prefetchable resource inside a non-prefetchable one */
-               if (!best)
-                       best = r;
+               if (res->start && resource_contains(r, res)) {
+
+                       /*
+                        * If the window is prefetchable but the BAR is
+                        * not, the allocator made a mistake.
+                        */
+                       if (r->flags & IORESOURCE_PREFETCH &&
+                           !(res->flags & IORESOURCE_PREFETCH))
+                               return NULL;
+
+                       /*
+                        * If we're below a transparent bridge, there may
+                        * be both a positively-decoded aperture and a
+                        * subtractively-decoded region that contain the BAR.
+                        * We want the positively-decoded one, so this depends
+                        * on pci_bus_for_each_resource() giving us those
+                        * first.
+                        */
+                       return r;
+               }
        }
-       return best;
+       return NULL;
 }
 
 /**
@@ -1178,6 +1185,11 @@ int pci_load_and_free_saved_state(struct pci_dev *dev,
 }
 EXPORT_SYMBOL_GPL(pci_load_and_free_saved_state);
 
+int __weak pcibios_enable_device(struct pci_dev *dev, int bars)
+{
+       return pci_enable_resources(dev, bars);
+}
+
 static int do_pci_enable_device(struct pci_dev *dev, int bars)
 {
        int err;
@@ -1624,29 +1636,27 @@ static void pci_pme_list_scan(struct work_struct *work)
        struct pci_pme_device *pme_dev, *n;
 
        mutex_lock(&pci_pme_list_mutex);
-       if (!list_empty(&pci_pme_list)) {
-               list_for_each_entry_safe(pme_dev, n, &pci_pme_list, list) {
-                       if (pme_dev->dev->pme_poll) {
-                               struct pci_dev *bridge;
-
-                               bridge = pme_dev->dev->bus->self;
-                               /*
-                                * If bridge is in low power state, the
-                                * configuration space of subordinate devices
-                                * may be not accessible
-                                */
-                               if (bridge && bridge->current_state != PCI_D0)
-                                       continue;
-                               pci_pme_wakeup(pme_dev->dev, NULL);
-                       } else {
-                               list_del(&pme_dev->list);
-                               kfree(pme_dev);
-                       }
+       list_for_each_entry_safe(pme_dev, n, &pci_pme_list, list) {
+               if (pme_dev->dev->pme_poll) {
+                       struct pci_dev *bridge;
+
+                       bridge = pme_dev->dev->bus->self;
+                       /*
+                        * If bridge is in low power state, the
+                        * configuration space of subordinate devices
+                        * may be not accessible
+                        */
+                       if (bridge && bridge->current_state != PCI_D0)
+                               continue;
+                       pci_pme_wakeup(pme_dev->dev, NULL);
+               } else {
+                       list_del(&pme_dev->list);
+                       kfree(pme_dev);
                }
-               if (!list_empty(&pci_pme_list))
-                       schedule_delayed_work(&pci_pme_work,
-                                             msecs_to_jiffies(PME_TIMEOUT));
        }
+       if (!list_empty(&pci_pme_list))
+               schedule_delayed_work(&pci_pme_work,
+                                     msecs_to_jiffies(PME_TIMEOUT));
        mutex_unlock(&pci_pme_list_mutex);
 }
 
@@ -2193,21 +2203,18 @@ void pci_request_acs(void)
 }
 
 /**
- * pci_enable_acs - enable ACS if hardware support it
+ * pci_std_enable_acs - enable ACS on devices using standard ACS capabilites
  * @dev: the PCI device
  */
-void pci_enable_acs(struct pci_dev *dev)
+static int pci_std_enable_acs(struct pci_dev *dev)
 {
        int pos;
        u16 cap;
        u16 ctrl;
 
-       if (!pci_acs_enable)
-               return;
-
        pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ACS);
        if (!pos)
-               return;
+               return -ENODEV;
 
        pci_read_config_word(dev, pos + PCI_ACS_CAP, &cap);
        pci_read_config_word(dev, pos + PCI_ACS_CTRL, &ctrl);
@@ -2225,6 +2232,23 @@ void pci_enable_acs(struct pci_dev *dev)
        ctrl |= (cap & PCI_ACS_UF);
 
        pci_write_config_word(dev, pos + PCI_ACS_CTRL, ctrl);
+
+       return 0;
+}
+
+/**
+ * pci_enable_acs - enable ACS if hardware support it
+ * @dev: the PCI device
+ */
+void pci_enable_acs(struct pci_dev *dev)
+{
+       if (!pci_acs_enable)
+               return;
+
+       if (!pci_std_enable_acs(dev))
+               return;
+
+       pci_dev_specific_enable_acs(dev);
 }
 
 static bool pci_acs_flags_enabled(struct pci_dev *pdev, u16 acs_flags)
@@ -4250,6 +4274,7 @@ void pci_reassigndev_resource_alignment(struct pci_dev *dev)
                                "Rounding up size of resource #%d to %#llx.\n",
                                i, (unsigned long long)size);
                }
+               r->flags |= IORESOURCE_UNSET;
                r->end = size - 1;
                r->start = 0;
        }
@@ -4263,6 +4288,7 @@ void pci_reassigndev_resource_alignment(struct pci_dev *dev)
                        r = &dev->resource[i];
                        if (!(r->flags & IORESOURCE_MEM))
                                continue;
+                       r->flags |= IORESOURCE_UNSET;
                        r->end = resource_size(r) - 1;
                        r->start = 0;
                }