Merge branch 'pci/ptm'
[linux-2.6-microblaze.git] / drivers / pci / pci.c
index e578d34..b9fecc2 100644 (file)
@@ -399,8 +399,8 @@ found:
        return 1;
 }
 
-static int __pci_find_next_cap_ttl(struct pci_bus *bus, unsigned int devfn,
-                                  u8 pos, int cap, int *ttl)
+static u8 __pci_find_next_cap_ttl(struct pci_bus *bus, unsigned int devfn,
+                                 u8 pos, int cap, int *ttl)
 {
        u8 id;
        u16 ent;
@@ -423,22 +423,22 @@ static int __pci_find_next_cap_ttl(struct pci_bus *bus, unsigned int devfn,
        return 0;
 }
 
-static int __pci_find_next_cap(struct pci_bus *bus, unsigned int devfn,
-                              u8 pos, int cap)
+static u8 __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)
+u8 pci_find_next_capability(struct pci_dev *dev, u8 pos, int cap)
 {
        return __pci_find_next_cap(dev->bus, dev->devfn,
                                   pos + PCI_CAP_LIST_NEXT, cap);
 }
 EXPORT_SYMBOL_GPL(pci_find_next_capability);
 
-static int __pci_bus_find_cap_start(struct pci_bus *bus,
+static u8 __pci_bus_find_cap_start(struct pci_bus *bus,
                                    unsigned int devfn, u8 hdr_type)
 {
        u16 status;
@@ -477,9 +477,9 @@ static int __pci_bus_find_cap_start(struct pci_bus *bus,
  *  %PCI_CAP_ID_PCIX         PCI-X
  *  %PCI_CAP_ID_EXP          PCI Express
  */
-int pci_find_capability(struct pci_dev *dev, int cap)
+u8 pci_find_capability(struct pci_dev *dev, int cap)
 {
-       int pos;
+       u8 pos;
 
        pos = __pci_bus_find_cap_start(dev->bus, dev->devfn, dev->hdr_type);
        if (pos)
@@ -502,10 +502,9 @@ EXPORT_SYMBOL(pci_find_capability);
  * device's PCI configuration space or 0 in case the device does not
  * support it.
  */
-int pci_bus_find_capability(struct pci_bus *bus, unsigned int devfn, int cap)
+u8 pci_bus_find_capability(struct pci_bus *bus, unsigned int devfn, int cap)
 {
-       int pos;
-       u8 hdr_type;
+       u8 hdr_type, pos;
 
        pci_bus_read_config_byte(bus, devfn, PCI_HEADER_TYPE, &hdr_type);
 
@@ -528,11 +527,11 @@ EXPORT_SYMBOL(pci_bus_find_capability);
  * not support it.  Some capabilities can occur several times, e.g., the
  * vendor-specific capability, and this provides a way to find them all.
  */
-int pci_find_next_ext_capability(struct pci_dev *dev, int start, int cap)
+u16 pci_find_next_ext_capability(struct pci_dev *dev, u16 start, int cap)
 {
        u32 header;
        int ttl;
-       int pos = PCI_CFG_SPACE_SIZE;
+       u16 pos = PCI_CFG_SPACE_SIZE;
 
        /* minimum 8 bytes per capability */
        ttl = (PCI_CFG_SPACE_EXP_SIZE - PCI_CFG_SPACE_SIZE) / 8;
@@ -583,7 +582,7 @@ EXPORT_SYMBOL_GPL(pci_find_next_ext_capability);
  *  %PCI_EXT_CAP_ID_DSN                Device Serial Number
  *  %PCI_EXT_CAP_ID_PWR                Power Budgeting
  */
-int pci_find_ext_capability(struct pci_dev *dev, int cap)
+u16 pci_find_ext_capability(struct pci_dev *dev, int cap)
 {
        return pci_find_next_ext_capability(dev, 0, cap);
 }
@@ -623,7 +622,7 @@ u64 pci_get_dsn(struct pci_dev *dev)
 }
 EXPORT_SYMBOL_GPL(pci_get_dsn);
 
-static int __pci_find_next_ht_cap(struct pci_dev *dev, int pos, int ht_cap)
+static u8 __pci_find_next_ht_cap(struct pci_dev *dev, u8 pos, int ht_cap)
 {
        int rc, ttl = PCI_FIND_CAP_TTL;
        u8 cap, mask;
@@ -650,11 +649,12 @@ static int __pci_find_next_ht_cap(struct pci_dev *dev, int pos, int ht_cap)
 
        return 0;
 }
+
 /**
- * pci_find_next_ht_capability - query a device's Hypertransport capabilities
+ * 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
+ * @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
@@ -663,26 +663,26 @@ static int __pci_find_next_ht_cap(struct pci_dev *dev, int pos, int ht_cap)
  * 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)
+u8 pci_find_next_ht_capability(struct pci_dev *dev, u8 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
+ * pci_find_ht_capability - query a device's HyperTransport capabilities
  * @dev: PCI device to query
- * @ht_cap: Hypertransport capability code
+ * @ht_cap: HyperTransport capability code
  *
- * Tell if a device supports a given Hypertransport capability.
+ * 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.
+ * which has a HyperTransport capability matching @ht_cap.
  */
-int pci_find_ht_capability(struct pci_dev *dev, int ht_cap)
+u8 pci_find_ht_capability(struct pci_dev *dev, int ht_cap)
 {
-       int pos;
+       u8 pos;
 
        pos = __pci_bus_find_cap_start(dev->bus, dev->devfn, dev->hdr_type);
        if (pos)
@@ -1174,26 +1174,20 @@ int pci_platform_power_transition(struct pci_dev *dev, pci_power_t state)
 }
 EXPORT_SYMBOL_GPL(pci_platform_power_transition);
 
-/**
- * pci_wakeup - Wake up a PCI device
- * @pci_dev: Device to handle.
- * @ign: ignored parameter
- */
-static int pci_wakeup(struct pci_dev *pci_dev, void *ign)
+static int pci_resume_one(struct pci_dev *pci_dev, void *ign)
 {
-       pci_wakeup_event(pci_dev);
        pm_request_resume(&pci_dev->dev);
        return 0;
 }
 
 /**
- * pci_wakeup_bus - Walk given bus and wake up devices on it
+ * pci_resume_bus - Walk given bus and runtime resume devices on it
  * @bus: Top bus of the subtree to walk.
  */
-void pci_wakeup_bus(struct pci_bus *bus)
+void pci_resume_bus(struct pci_bus *bus)
 {
        if (bus)
-               pci_walk_bus(bus, pci_wakeup, NULL);
+               pci_walk_bus(bus, pci_resume_one, NULL);
 }
 
 static int pci_dev_wait(struct pci_dev *dev, char *reset_type, int timeout)
@@ -1256,7 +1250,7 @@ int pci_power_up(struct pci_dev *dev)
                 * may be powered on into D0uninitialized state, resume them to
                 * give them a chance to suspend again
                 */
-               pci_wakeup_bus(dev->subordinate);
+               pci_resume_bus(dev->subordinate);
        }
 
        return pci_raw_set_power_state(dev, PCI_D0);
@@ -1564,8 +1558,10 @@ int pci_save_state(struct pci_dev *dev)
                return i;
 
        pci_save_ltr_state(dev);
+       pci_save_aspm_l1ss_state(dev);
        pci_save_dpc_state(dev);
        pci_save_aer_state(dev);
+       pci_save_ptm_state(dev);
        return pci_save_vc_state(dev);
 }
 EXPORT_SYMBOL(pci_save_state);
@@ -1669,6 +1665,7 @@ void pci_restore_state(struct pci_dev *dev)
         * LTR itself (in the PCIe capability).
         */
        pci_restore_ltr_state(dev);
+       pci_restore_aspm_l1ss_state(dev);
 
        pci_restore_pcie_state(dev);
        pci_restore_pasid_state(dev);
@@ -1677,6 +1674,7 @@ void pci_restore_state(struct pci_dev *dev)
        pci_restore_vc_state(dev);
        pci_restore_rebar_state(dev);
        pci_restore_dpc_state(dev);
+       pci_restore_ptm_state(dev);
 
        pci_aer_clear_status(dev);
        pci_restore_aer_state(dev);
@@ -2606,12 +2604,24 @@ int pci_prepare_to_sleep(struct pci_dev *dev)
        if (target_state == PCI_POWER_ERROR)
                return -EIO;
 
+       /*
+        * There are systems (for example, Intel mobile chips since Coffee
+        * Lake) where the power drawn while suspended can be significantly
+        * reduced by disabling PTM on PCIe root ports as this allows the
+        * port to enter a lower-power PM state and the SoC to reach a
+        * lower-power idle state as a whole.
+        */
+       if (pci_pcie_type(dev) == PCI_EXP_TYPE_ROOT_PORT)
+               pci_disable_ptm(dev);
+
        pci_enable_wake(dev, target_state, wakeup);
 
        error = pci_set_power_state(dev, target_state);
 
-       if (error)
+       if (error) {
                pci_enable_wake(dev, target_state, false);
+               pci_restore_ptm_state(dev);
+       }
 
        return error;
 }
@@ -2649,12 +2659,23 @@ int pci_finish_runtime_suspend(struct pci_dev *dev)
 
        dev->runtime_d3cold = target_state == PCI_D3cold;
 
+       /*
+        * There are systems (for example, Intel mobile chips since Coffee
+        * Lake) where the power drawn while suspended can be significantly
+        * reduced by disabling PTM on PCIe root ports as this allows the
+        * port to enter a lower-power PM state and the SoC to reach a
+        * lower-power idle state as a whole.
+        */
+       if (pci_pcie_type(dev) == PCI_EXP_TYPE_ROOT_PORT)
+               pci_disable_ptm(dev);
+
        __pci_enable_wake(dev, target_state, pci_dev_run_wake(dev));
 
        error = pci_set_power_state(dev, target_state);
 
        if (error) {
                pci_enable_wake(dev, target_state, false);
+               pci_restore_ptm_state(dev);
                dev->runtime_d3cold = false;
        }
 
@@ -3332,6 +3353,11 @@ void pci_allocate_cap_save_buffers(struct pci_dev *dev)
        if (error)
                pci_err(dev, "unable to allocate suspend buffer for LTR\n");
 
+       error = pci_add_ext_cap_save_buffer(dev, PCI_EXT_CAP_ID_L1SS,
+                                           2 * sizeof(u32));
+       if (error)
+               pci_err(dev, "unable to allocate suspend buffer for ASPM-L1SS\n");
+
        pci_allocate_vc_save_buffers(dev);
 }
 
@@ -3480,7 +3506,7 @@ bool pci_acs_enabled(struct pci_dev *pdev, u16 acs_flags)
 }
 
 /**
- * pci_acs_path_enable - test ACS flags from start to end in a hierarchy
+ * pci_acs_path_enabled - test ACS flags from start to end in a hierarchy
  * @start: starting downstream device
  * @end: ending upstream device or NULL to search to the root bus
  * @acs_flags: required flags
@@ -4188,7 +4214,14 @@ void __iomem *devm_pci_remap_cfg_resource(struct device *dev,
        }
 
        size = resource_size(res);
-       name = res->name ?: dev_name(dev);
+
+       if (res->name)
+               name = devm_kasprintf(dev, GFP_KERNEL, "%s %s", dev_name(dev),
+                                     res->name);
+       else
+               name = devm_kstrdup(dev, dev_name(dev), GFP_KERNEL);
+       if (!name)
+               return IOMEM_ERR_PTR(-ENOMEM);
 
        if (!devm_request_mem_region(dev, res->start, size, name)) {
                dev_err(dev, "can't request region for resource %pR\n", res);
@@ -4317,7 +4350,7 @@ int pci_set_cacheline_size(struct pci_dev *dev)
        if (cacheline_size == pci_cache_line_size)
                return 0;
 
-       pci_info(dev, "cache line size of %d is not supported\n",
+       pci_dbg(dev, "cache line size of %d is not supported\n",
                   pci_cache_line_size << 2);
 
        return -EINVAL;
@@ -6202,19 +6235,21 @@ static resource_size_t pci_specified_resource_alignment(struct pci_dev *dev,
        while (*p) {
                count = 0;
                if (sscanf(p, "%d%n", &align_order, &count) == 1 &&
-                                                       p[count] == '@') {
+                   p[count] == '@') {
                        p += count + 1;
+                       if (align_order > 63) {
+                               pr_err("PCI: Invalid requested alignment (order %d)\n",
+                                      align_order);
+                               align_order = PAGE_SHIFT;
+                       }
                } else {
-                       align_order = -1;
+                       align_order = PAGE_SHIFT;
                }
 
                ret = pci_dev_str_match(dev, p, &p);
                if (ret == 1) {
                        *resize = true;
-                       if (align_order == -1)
-                               align = PAGE_SIZE;
-                       else
-                               align = 1 << align_order;
+                       align = 1ULL << align_order;
                        break;
                } else if (ret < 0) {
                        pr_err("PCI: Can't parse resource_alignment parameter: %s\n",