PCI: Remove MRRS modification from MPS setting code
[linux-2.6.git] / drivers / pci / pci.c
index 740fb4e..4e84fd4 100644 (file)
@@ -38,6 +38,19 @@ EXPORT_SYMBOL(pci_pci_problems);
 
 unsigned int pci_pm_d3_delay;
 
+static void pci_pme_list_scan(struct work_struct *work);
+
+static LIST_HEAD(pci_pme_list);
+static DEFINE_MUTEX(pci_pme_list_mutex);
+static DECLARE_DELAYED_WORK(pci_pme_work, pci_pme_list_scan);
+
+struct pci_pme_device {
+       struct list_head list;
+       struct pci_dev *dev;
+};
+
+#define PME_TIMEOUT 1000 /* How long between PME checks */
+
 static void pci_dev_d3_sleep(struct pci_dev *dev)
 {
        unsigned int delay = dev->d3_delay;
@@ -64,6 +77,8 @@ unsigned long pci_cardbus_mem_size = DEFAULT_CARDBUS_MEM_SIZE;
 unsigned long pci_hotplug_io_size  = DEFAULT_HOTPLUG_IO_SIZE;
 unsigned long pci_hotplug_mem_size = DEFAULT_HOTPLUG_MEM_SIZE;
 
+enum pcie_bus_config_types pcie_bus_config = PCIE_BUS_SAFE;
+
 /*
  * The default CLS is used if arch didn't set CLS explicitly and not
  * all pci devices agree on the same value.  Arch can override either
@@ -727,6 +742,12 @@ int pci_set_power_state(struct pci_dev *dev, pci_power_t state)
 
        if (!__pci_complete_power_transition(dev, state))
                error = 0;
+       /*
+        * When aspm_policy is "powersave" this call ensures
+        * that ASPM is configured.
+        */
+       if (!error && dev->bus->self)
+               pcie_aspm_powersave_config_link(dev->bus->self);
 
        return error;
 }
@@ -811,7 +832,7 @@ static int pci_save_pcie_state(struct pci_dev *dev)
                dev_err(&dev->dev, "buffer not found in %s\n", __func__);
                return -ENOMEM;
        }
-       cap = (u16 *)&save_state->data[0];
+       cap = (u16 *)&save_state->cap.data[0];
 
        pci_read_config_word(dev, pos + PCI_EXP_FLAGS, &flags);
 
@@ -844,7 +865,7 @@ static void pci_restore_pcie_state(struct pci_dev *dev)
        pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
        if (!save_state || pos <= 0)
                return;
-       cap = (u16 *)&save_state->data[0];
+       cap = (u16 *)&save_state->cap.data[0];
 
        pci_read_config_word(dev, pos + PCI_EXP_FLAGS, &flags);
 
@@ -880,7 +901,8 @@ static int pci_save_pcix_state(struct pci_dev *dev)
                return -ENOMEM;
        }
 
-       pci_read_config_word(dev, pos + PCI_X_CMD, (u16 *)save_state->data);
+       pci_read_config_word(dev, pos + PCI_X_CMD,
+                            (u16 *)save_state->cap.data);
 
        return 0;
 }
@@ -895,7 +917,7 @@ static void pci_restore_pcix_state(struct pci_dev *dev)
        pos = pci_find_capability(dev, PCI_CAP_ID_PCIX);
        if (!save_state || pos <= 0)
                return;
-       cap = (u16 *)&save_state->data[0];
+       cap = (u16 *)&save_state->cap.data[0];
 
        pci_write_config_word(dev, pos + PCI_X_CMD, cap[i++]);
 }
@@ -924,14 +946,13 @@ pci_save_state(struct pci_dev *dev)
  * pci_restore_state - Restore the saved state of a PCI device
  * @dev: - PCI device that we're dealing with
  */
-int 
-pci_restore_state(struct pci_dev *dev)
+void pci_restore_state(struct pci_dev *dev)
 {
        int i;
        u32 val;
 
        if (!dev->state_saved)
-               return 0;
+               return;
 
        /* PCI Express register must be restored first */
        pci_restore_pcie_state(dev);
@@ -955,9 +976,105 @@ pci_restore_state(struct pci_dev *dev)
        pci_restore_iov_state(dev);
 
        dev->state_saved = false;
+}
+
+struct pci_saved_state {
+       u32 config_space[16];
+       struct pci_cap_saved_data cap[0];
+};
+
+/**
+ * pci_store_saved_state - Allocate and return an opaque struct containing
+ *                        the device saved state.
+ * @dev: PCI device that we're dealing with
+ *
+ * Rerturn NULL if no state or error.
+ */
+struct pci_saved_state *pci_store_saved_state(struct pci_dev *dev)
+{
+       struct pci_saved_state *state;
+       struct pci_cap_saved_state *tmp;
+       struct pci_cap_saved_data *cap;
+       struct hlist_node *pos;
+       size_t size;
+
+       if (!dev->state_saved)
+               return NULL;
+
+       size = sizeof(*state) + sizeof(struct pci_cap_saved_data);
+
+       hlist_for_each_entry(tmp, pos, &dev->saved_cap_space, next)
+               size += sizeof(struct pci_cap_saved_data) + tmp->cap.size;
+
+       state = kzalloc(size, GFP_KERNEL);
+       if (!state)
+               return NULL;
+
+       memcpy(state->config_space, dev->saved_config_space,
+              sizeof(state->config_space));
+
+       cap = state->cap;
+       hlist_for_each_entry(tmp, pos, &dev->saved_cap_space, next) {
+               size_t len = sizeof(struct pci_cap_saved_data) + tmp->cap.size;
+               memcpy(cap, &tmp->cap, len);
+               cap = (struct pci_cap_saved_data *)((u8 *)cap + len);
+       }
+       /* Empty cap_save terminates list */
+
+       return state;
+}
+EXPORT_SYMBOL_GPL(pci_store_saved_state);
+
+/**
+ * pci_load_saved_state - Reload the provided save state into struct pci_dev.
+ * @dev: PCI device that we're dealing with
+ * @state: Saved state returned from pci_store_saved_state()
+ */
+int pci_load_saved_state(struct pci_dev *dev, struct pci_saved_state *state)
+{
+       struct pci_cap_saved_data *cap;
+
+       dev->state_saved = false;
+
+       if (!state)
+               return 0;
 
+       memcpy(dev->saved_config_space, state->config_space,
+              sizeof(state->config_space));
+
+       cap = state->cap;
+       while (cap->size) {
+               struct pci_cap_saved_state *tmp;
+
+               tmp = pci_find_saved_cap(dev, cap->cap_nr);
+               if (!tmp || tmp->cap.size != cap->size)
+                       return -EINVAL;
+
+               memcpy(tmp->cap.data, cap->data, tmp->cap.size);
+               cap = (struct pci_cap_saved_data *)((u8 *)cap +
+                      sizeof(struct pci_cap_saved_data) + cap->size);
+       }
+
+       dev->state_saved = true;
        return 0;
 }
+EXPORT_SYMBOL_GPL(pci_load_saved_state);
+
+/**
+ * pci_load_and_free_saved_state - Reload the save state pointed to by state,
+ *                                and free the memory allocated for it.
+ * @dev: PCI device that we're dealing with
+ * @state: Pointer to saved state returned from pci_store_saved_state()
+ */
+int pci_load_and_free_saved_state(struct pci_dev *dev,
+                                 struct pci_saved_state **state)
+{
+       int ret = pci_load_saved_state(dev, *state);
+       kfree(*state);
+       *state = NULL;
+       return ret;
+}
+EXPORT_SYMBOL_GPL(pci_load_and_free_saved_state);
 
 static int do_pci_enable_device(struct pci_dev *dev, int bars)
 {
@@ -994,6 +1111,18 @@ static int __pci_enable_device_flags(struct pci_dev *dev,
        int err;
        int i, bars = 0;
 
+       /*
+        * Power state could be unknown at this point, either due to a fresh
+        * boot or a device removal call.  So get the current power state
+        * so that things like MSI message writing will behave as expected
+        * (e.g. if the device really is in D0 at enable time).
+        */
+       if (dev->pm_cap) {
+               u16 pmcsr;
+               pci_read_config_word(dev, dev->pm_cap + PCI_PM_CTRL, &pmcsr);
+               dev->current_state = (pmcsr & PCI_PM_CTRL_STATE_MASK);
+       }
+
        if (atomic_add_return(1, &dev->enable_cnt) > 1)
                return 0;               /* already enabled */
 
@@ -1285,8 +1414,10 @@ bool pci_check_pme_status(struct pci_dev *dev)
  */
 static int pci_pme_wakeup(struct pci_dev *dev, void *ign)
 {
-       if (pci_check_pme_status(dev))
+       if (pci_check_pme_status(dev)) {
+               pci_wakeup_event(dev);
                pm_request_resume(&dev->dev);
+       }
        return 0;
 }
 
@@ -1313,6 +1444,32 @@ bool pci_pme_capable(struct pci_dev *dev, pci_power_t state)
        return !!(dev->pme_support & (1 << state));
 }
 
+static void pci_pme_list_scan(struct work_struct *work)
+{
+       struct pci_pme_device *pme_dev;
+
+       mutex_lock(&pci_pme_list_mutex);
+       if (!list_empty(&pci_pme_list)) {
+               list_for_each_entry(pme_dev, &pci_pme_list, list)
+                       pci_pme_wakeup(pme_dev->dev, NULL);
+               schedule_delayed_work(&pci_pme_work, msecs_to_jiffies(PME_TIMEOUT));
+       }
+       mutex_unlock(&pci_pme_list_mutex);
+}
+
+/**
+ * pci_external_pme - is a device an external PCI PME source?
+ * @dev: PCI device to check
+ *
+ */
+
+static bool pci_external_pme(struct pci_dev *dev)
+{
+       if (pci_is_pcie(dev) || dev->bus->number == 0)
+               return false;
+       return true;
+}
+
 /**
  * pci_pme_active - enable or disable PCI device's PME# function
  * @dev: PCI device to handle.
@@ -1336,6 +1493,44 @@ void pci_pme_active(struct pci_dev *dev, bool enable)
 
        pci_write_config_word(dev, dev->pm_cap + PCI_PM_CTRL, pmcsr);
 
+       /* PCI (as opposed to PCIe) PME requires that the device have
+          its PME# line hooked up correctly. Not all hardware vendors
+          do this, so the PME never gets delivered and the device
+          remains asleep. The easiest way around this is to
+          periodically walk the list of suspended devices and check
+          whether any have their PME flag set. The assumption is that
+          we'll wake up often enough anyway that this won't be a huge
+          hit, and the power savings from the devices will still be a
+          win. */
+
+       if (pci_external_pme(dev)) {
+               struct pci_pme_device *pme_dev;
+               if (enable) {
+                       pme_dev = kmalloc(sizeof(struct pci_pme_device),
+                                         GFP_KERNEL);
+                       if (!pme_dev)
+                               goto out;
+                       pme_dev->dev = dev;
+                       mutex_lock(&pci_pme_list_mutex);
+                       list_add(&pme_dev->list, &pci_pme_list);
+                       if (list_is_singular(&pci_pme_list))
+                               schedule_delayed_work(&pci_pme_work,
+                                                     msecs_to_jiffies(PME_TIMEOUT));
+                       mutex_unlock(&pci_pme_list_mutex);
+               } else {
+                       mutex_lock(&pci_pme_list_mutex);
+                       list_for_each_entry(pme_dev, &pci_pme_list, list) {
+                               if (pme_dev->dev == dev) {
+                                       list_del(&pme_dev->list);
+                                       kfree(pme_dev);
+                                       break;
+                               }
+                       }
+                       mutex_unlock(&pci_pme_list_mutex);
+               }
+       }
+
+out:
        dev_printk(KERN_DEBUG, &dev->dev, "PME# %s\n",
                        enable ? "enabled" : "disabled");
 }
@@ -1677,7 +1872,8 @@ static int pci_add_cap_save_buffer(
        if (!save_state)
                return -ENOMEM;
 
-       save_state->cap_nr = cap;
+       save_state->cap.cap_nr = cap;
+       save_state->cap.size = size;
        pci_add_saved_cap(dev, save_state);
 
        return 0;
@@ -1711,7 +1907,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)
@@ -1729,6 +1925,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;
@@ -1740,6 +1941,300 @@ void pci_enable_ari(struct pci_dev *dev)
        bridge->ari_enabled = 1;
 }
 
+/**
+ * pci_enable_ido - enable ID-based ordering on a device
+ * @dev: the PCI device
+ * @type: which types of IDO to enable
+ *
+ * Enable ID-based ordering on @dev.  @type can contain the bits
+ * %PCI_EXP_IDO_REQUEST and/or %PCI_EXP_IDO_COMPLETION to indicate
+ * which types of transactions are allowed to be re-ordered.
+ */
+void pci_enable_ido(struct pci_dev *dev, unsigned long type)
+{
+       int pos;
+       u16 ctrl;
+
+       pos = pci_pcie_cap(dev);
+       if (!pos)
+               return;
+
+       pci_read_config_word(dev, pos + PCI_EXP_DEVCTL2, &ctrl);
+       if (type & PCI_EXP_IDO_REQUEST)
+               ctrl |= PCI_EXP_IDO_REQ_EN;
+       if (type & PCI_EXP_IDO_COMPLETION)
+               ctrl |= PCI_EXP_IDO_CMP_EN;
+       pci_write_config_word(dev, pos + PCI_EXP_DEVCTL2, ctrl);
+}
+EXPORT_SYMBOL(pci_enable_ido);
+
+/**
+ * pci_disable_ido - disable ID-based ordering on a device
+ * @dev: the PCI device
+ * @type: which types of IDO to disable
+ */
+void pci_disable_ido(struct pci_dev *dev, unsigned long type)
+{
+       int pos;
+       u16 ctrl;
+
+       if (!pci_is_pcie(dev))
+               return;
+
+       pos = pci_pcie_cap(dev);
+       if (!pos)
+               return;
+
+       pci_read_config_word(dev, pos + PCI_EXP_DEVCTL2, &ctrl);
+       if (type & PCI_EXP_IDO_REQUEST)
+               ctrl &= ~PCI_EXP_IDO_REQ_EN;
+       if (type & PCI_EXP_IDO_COMPLETION)
+               ctrl &= ~PCI_EXP_IDO_CMP_EN;
+       pci_write_config_word(dev, pos + PCI_EXP_DEVCTL2, ctrl);
+}
+EXPORT_SYMBOL(pci_disable_ido);
+
+/**
+ * pci_enable_obff - enable optimized buffer flush/fill
+ * @dev: PCI device
+ * @type: type of signaling to use
+ *
+ * Try to enable @type OBFF signaling on @dev.  It will try using WAKE#
+ * signaling if possible, falling back to message signaling only if
+ * WAKE# isn't supported.  @type should indicate whether the PCIe link
+ * be brought out of L0s or L1 to send the message.  It should be either
+ * %PCI_EXP_OBFF_SIGNAL_ALWAYS or %PCI_OBFF_SIGNAL_L0.
+ *
+ * If your device can benefit from receiving all messages, even at the
+ * power cost of bringing the link back up from a low power state, use
+ * %PCI_EXP_OBFF_SIGNAL_ALWAYS.  Otherwise, use %PCI_OBFF_SIGNAL_L0 (the
+ * preferred type).
+ *
+ * RETURNS:
+ * Zero on success, appropriate error number on failure.
+ */
+int pci_enable_obff(struct pci_dev *dev, enum pci_obff_signal_type type)
+{
+       int pos;
+       u32 cap;
+       u16 ctrl;
+       int ret;
+
+       if (!pci_is_pcie(dev))
+               return -ENOTSUPP;
+
+       pos = pci_pcie_cap(dev);
+       if (!pos)
+               return -ENOTSUPP;
+
+       pci_read_config_dword(dev, pos + PCI_EXP_DEVCAP2, &cap);
+       if (!(cap & PCI_EXP_OBFF_MASK))
+               return -ENOTSUPP; /* no OBFF support at all */
+
+       /* Make sure the topology supports OBFF as well */
+       if (dev->bus) {
+               ret = pci_enable_obff(dev->bus->self, type);
+               if (ret)
+                       return ret;
+       }
+
+       pci_read_config_word(dev, pos + PCI_EXP_DEVCTL2, &ctrl);
+       if (cap & PCI_EXP_OBFF_WAKE)
+               ctrl |= PCI_EXP_OBFF_WAKE_EN;
+       else {
+               switch (type) {
+               case PCI_EXP_OBFF_SIGNAL_L0:
+                       if (!(ctrl & PCI_EXP_OBFF_WAKE_EN))
+                               ctrl |= PCI_EXP_OBFF_MSGA_EN;
+                       break;
+               case PCI_EXP_OBFF_SIGNAL_ALWAYS:
+                       ctrl &= ~PCI_EXP_OBFF_WAKE_EN;
+                       ctrl |= PCI_EXP_OBFF_MSGB_EN;
+                       break;
+               default:
+                       WARN(1, "bad OBFF signal type\n");
+                       return -ENOTSUPP;
+               }
+       }
+       pci_write_config_word(dev, pos + PCI_EXP_DEVCTL2, ctrl);
+
+       return 0;
+}
+EXPORT_SYMBOL(pci_enable_obff);
+
+/**
+ * pci_disable_obff - disable optimized buffer flush/fill
+ * @dev: PCI device
+ *
+ * Disable OBFF on @dev.
+ */
+void pci_disable_obff(struct pci_dev *dev)
+{
+       int pos;
+       u16 ctrl;
+
+       if (!pci_is_pcie(dev))
+               return;
+
+       pos = pci_pcie_cap(dev);
+       if (!pos)
+               return;
+
+       pci_read_config_word(dev, pos + PCI_EXP_DEVCTL2, &ctrl);
+       ctrl &= ~PCI_EXP_OBFF_WAKE_EN;
+       pci_write_config_word(dev, pos + PCI_EXP_DEVCTL2, ctrl);
+}
+EXPORT_SYMBOL(pci_disable_obff);
+
+/**
+ * pci_ltr_supported - check whether a device supports LTR
+ * @dev: PCI device
+ *
+ * RETURNS:
+ * True if @dev supports latency tolerance reporting, false otherwise.
+ */
+bool pci_ltr_supported(struct pci_dev *dev)
+{
+       int pos;
+       u32 cap;
+
+       if (!pci_is_pcie(dev))
+               return false;
+
+       pos = pci_pcie_cap(dev);
+       if (!pos)
+               return false;
+
+       pci_read_config_dword(dev, pos + PCI_EXP_DEVCAP2, &cap);
+
+       return cap & PCI_EXP_DEVCAP2_LTR;
+}
+EXPORT_SYMBOL(pci_ltr_supported);
+
+/**
+ * pci_enable_ltr - enable latency tolerance reporting
+ * @dev: PCI device
+ *
+ * Enable LTR on @dev if possible, which means enabling it first on
+ * upstream ports.
+ *
+ * RETURNS:
+ * Zero on success, errno on failure.
+ */
+int pci_enable_ltr(struct pci_dev *dev)
+{
+       int pos;
+       u16 ctrl;
+       int ret;
+
+       if (!pci_ltr_supported(dev))
+               return -ENOTSUPP;
+
+       pos = pci_pcie_cap(dev);
+       if (!pos)
+               return -ENOTSUPP;
+
+       /* Only primary function can enable/disable LTR */
+       if (PCI_FUNC(dev->devfn) != 0)
+               return -EINVAL;
+
+       /* Enable upstream ports first */
+       if (dev->bus) {
+               ret = pci_enable_ltr(dev->bus->self);
+               if (ret)
+                       return ret;
+       }
+
+       pci_read_config_word(dev, pos + PCI_EXP_DEVCTL2, &ctrl);
+       ctrl |= PCI_EXP_LTR_EN;
+       pci_write_config_word(dev, pos + PCI_EXP_DEVCTL2, ctrl);
+
+       return 0;
+}
+EXPORT_SYMBOL(pci_enable_ltr);
+
+/**
+ * pci_disable_ltr - disable latency tolerance reporting
+ * @dev: PCI device
+ */
+void pci_disable_ltr(struct pci_dev *dev)
+{
+       int pos;
+       u16 ctrl;
+
+       if (!pci_ltr_supported(dev))
+               return;
+
+       pos = pci_pcie_cap(dev);
+       if (!pos)
+               return;
+
+       /* Only primary function can enable/disable LTR */
+       if (PCI_FUNC(dev->devfn) != 0)
+               return;
+
+       pci_read_config_word(dev, pos + PCI_EXP_DEVCTL2, &ctrl);
+       ctrl &= ~PCI_EXP_LTR_EN;
+       pci_write_config_word(dev, pos + PCI_EXP_DEVCTL2, ctrl);
+}
+EXPORT_SYMBOL(pci_disable_ltr);
+
+static int __pci_ltr_scale(int *val)
+{
+       int scale = 0;
+
+       while (*val > 1023) {
+               *val = (*val + 31) / 32;
+               scale++;
+       }
+       return scale;
+}
+
+/**
+ * pci_set_ltr - set LTR latency values
+ * @dev: PCI device
+ * @snoop_lat_ns: snoop latency in nanoseconds
+ * @nosnoop_lat_ns: nosnoop latency in nanoseconds
+ *
+ * Figure out the scale and set the LTR values accordingly.
+ */
+int pci_set_ltr(struct pci_dev *dev, int snoop_lat_ns, int nosnoop_lat_ns)
+{
+       int pos, ret, snoop_scale, nosnoop_scale;
+       u16 val;
+
+       if (!pci_ltr_supported(dev))
+               return -ENOTSUPP;
+
+       snoop_scale = __pci_ltr_scale(&snoop_lat_ns);
+       nosnoop_scale = __pci_ltr_scale(&nosnoop_lat_ns);
+
+       if (snoop_lat_ns > PCI_LTR_VALUE_MASK ||
+           nosnoop_lat_ns > PCI_LTR_VALUE_MASK)
+               return -EINVAL;
+
+       if ((snoop_scale > (PCI_LTR_SCALE_MASK >> PCI_LTR_SCALE_SHIFT)) ||
+           (nosnoop_scale > (PCI_LTR_SCALE_MASK >> PCI_LTR_SCALE_SHIFT)))
+               return -EINVAL;
+
+       pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_LTR);
+       if (!pos)
+               return -ENOTSUPP;
+
+       val = (snoop_scale << PCI_LTR_SCALE_SHIFT) | snoop_lat_ns;
+       ret = pci_write_config_word(dev, pos + PCI_LTR_MAX_SNOOP_LAT, val);
+       if (ret != 4)
+               return -EIO;
+
+       val = (nosnoop_scale << PCI_LTR_SCALE_SHIFT) | nosnoop_lat_ns;
+       ret = pci_write_config_word(dev, pos + PCI_LTR_MAX_NOSNOOP_LAT, val);
+       if (ret != 4)
+               return -EIO;
+
+       return 0;
+}
+EXPORT_SYMBOL(pci_set_ltr);
+
 static int pci_acs_enable;
 
 /**
@@ -2294,21 +2789,17 @@ void pci_msi_off(struct pci_dev *dev)
 }
 EXPORT_SYMBOL_GPL(pci_msi_off);
 
-#ifndef HAVE_ARCH_PCI_SET_DMA_MAX_SEGMENT_SIZE
 int pci_set_dma_max_seg_size(struct pci_dev *dev, unsigned int size)
 {
        return dma_set_max_seg_size(&dev->dev, size);
 }
 EXPORT_SYMBOL(pci_set_dma_max_seg_size);
-#endif
 
-#ifndef HAVE_ARCH_PCI_SET_DMA_SEGMENT_BOUNDARY
 int pci_set_dma_seg_boundary(struct pci_dev *dev, unsigned long mask)
 {
        return dma_set_seg_boundary(&dev->dev, mask);
 }
 EXPORT_SYMBOL(pci_set_dma_seg_boundary);
-#endif
 
 static int pcie_flr(struct pci_dev *dev, int probe)
 {
@@ -2389,6 +2880,21 @@ clear:
        return 0;
 }
 
+/**
+ * pci_pm_reset - Put device into PCI_D3 and back into PCI_D0.
+ * @dev: Device to reset.
+ * @probe: If set, only check if the device can be reset this way.
+ *
+ * If @dev supports native PCI PM and its PCI_PM_CTRL_NO_SOFT_RESET flag is
+ * unset, it will be reinitialized internally when going from PCI_D3hot to
+ * PCI_D0.  If that's the case and the device is not in a low-power state
+ * already, force it into PCI_D3hot and back to PCI_D0, causing it to be reset.
+ *
+ * NOTE: This causes the caller to sleep for twice the device power transition
+ * cooldown period, which for the D0->D3hot and D3hot->D0 transitions is 10 ms
+ * by devault (i.e. unless the @dev's d3_delay field has a different value).
+ * Moreover, only devices in D0 can be reset by this function.
+ */
 static int pci_pm_reset(struct pci_dev *dev, int probe)
 {
        u16 csr;
@@ -2675,7 +3181,7 @@ int pcie_get_readrq(struct pci_dev *dev)
 
        ret = pci_read_config_word(dev, cap + PCI_EXP_DEVCTL, &ctl);
        if (!ret)
-       ret = 128 << ((ctl & PCI_EXP_DEVCTL_READRQ) >> 12);
+               ret = 128 << ((ctl & PCI_EXP_DEVCTL_READRQ) >> 12);
 
        return ret;
 }
@@ -2687,7 +3193,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)
 {
@@ -2710,7 +3216,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:
@@ -2719,6 +3225,67 @@ out:
 EXPORT_SYMBOL(pcie_set_readrq);
 
 /**
+ * pcie_get_mps - get PCI Express maximum payload size
+ * @dev: PCI device to query
+ *
+ * Returns maximum payload size in bytes
+ *    or appropriate error value.
+ */
+int pcie_get_mps(struct pci_dev *dev)
+{
+       int ret, cap;
+       u16 ctl;
+
+       cap = pci_pcie_cap(dev);
+       if (!cap)
+               return -EINVAL;
+
+       ret = pci_read_config_word(dev, cap + PCI_EXP_DEVCTL, &ctl);
+       if (!ret)
+               ret = 128 << ((ctl & PCI_EXP_DEVCTL_PAYLOAD) >> 5);
+
+       return ret;
+}
+
+/**
+ * pcie_set_mps - set PCI Express maximum payload size
+ * @dev: PCI device to query
+ * @mps: maximum payload size in bytes
+ *    valid values are 128, 256, 512, 1024, 2048, 4096
+ *
+ * If possible sets maximum payload size
+ */
+int pcie_set_mps(struct pci_dev *dev, int mps)
+{
+       int cap, err = -EINVAL;
+       u16 ctl, v;
+
+       if (mps < 128 || mps > 4096 || !is_power_of_2(mps))
+               goto out;
+
+       v = ffs(mps) - 8;
+       if (v > dev->pcie_mpss) 
+               goto out;
+       v <<= 5;
+
+       cap = pci_pcie_cap(dev);
+       if (!cap)
+               goto out;
+
+       err = pci_read_config_word(dev, cap + PCI_EXP_DEVCTL, &ctl);
+       if (err)
+               goto out;
+
+       if ((ctl & PCI_EXP_DEVCTL_PAYLOAD) != v) {
+               ctl &= ~PCI_EXP_DEVCTL_PAYLOAD;
+               ctl |= v;
+               err = pci_write_config_word(dev, cap + PCI_EXP_DEVCTL, ctl);
+       }
+out:
+       return err;
+}
+
+/**
  * pci_select_bars - Make BAR mask from the type of resource
  * @dev: the PCI device for which BAR mask is made
  * @flags: resource type mask to be selected
@@ -2772,11 +3339,11 @@ void __init pci_register_set_vga_state(arch_set_vga_state_t func)
 }
 
 static int pci_set_vga_state_arch(struct pci_dev *dev, bool decode,
-                     unsigned int command_bits, bool change_bridge)
+                     unsigned int command_bits, u32 flags)
 {
        if (arch_set_vga_state)
                return arch_set_vga_state(dev, decode, command_bits,
-                                               change_bridge);
+                                               flags);
        return 0;
 }
 
@@ -2785,31 +3352,34 @@ static int pci_set_vga_state_arch(struct pci_dev *dev, bool decode,
  * @dev: the PCI device
  * @decode: true = enable decoding, false = disable decoding
  * @command_bits: PCI_COMMAND_IO and/or PCI_COMMAND_MEMORY
- * @change_bridge: traverse ancestors and change bridges
+ * @flags: traverse ancestors and change bridges
+ * CHANGE_BRIDGE_ONLY / CHANGE_BRIDGE
  */
 int pci_set_vga_state(struct pci_dev *dev, bool decode,
-                     unsigned int command_bits, bool change_bridge)
+                     unsigned int command_bits, u32 flags)
 {
        struct pci_bus *bus;
        struct pci_dev *bridge;
        u16 cmd;
        int rc;
 
-       WARN_ON(command_bits & ~(PCI_COMMAND_IO|PCI_COMMAND_MEMORY));
+       WARN_ON((flags & PCI_VGA_STATE_CHANGE_DECODES) & (command_bits & ~(PCI_COMMAND_IO|PCI_COMMAND_MEMORY)));
 
        /* ARCH specific VGA enables */
-       rc = pci_set_vga_state_arch(dev, decode, command_bits, change_bridge);
+       rc = pci_set_vga_state_arch(dev, decode, command_bits, flags);
        if (rc)
                return rc;
 
-       pci_read_config_word(dev, PCI_COMMAND, &cmd);
-       if (decode == true)
-               cmd |= command_bits;
-       else
-               cmd &= ~command_bits;
-       pci_write_config_word(dev, PCI_COMMAND, cmd);
+       if (flags & PCI_VGA_STATE_CHANGE_DECODES) {
+               pci_read_config_word(dev, PCI_COMMAND, &cmd);
+               if (decode == true)
+                       cmd |= command_bits;
+               else
+                       cmd &= ~command_bits;
+               pci_write_config_word(dev, PCI_COMMAND, cmd);
+       }
 
-       if (change_bridge == false)
+       if (!(flags & PCI_VGA_STATE_CHANGE_BRIDGE))
                return 0;
 
        bus = dev->bus;
@@ -2981,6 +3551,8 @@ static int __init pci_setup(char *str)
                                pci_no_msi();
                        } else if (!strcmp(str, "noaer")) {
                                pci_no_aer();
+                       } else if (!strncmp(str, "realloc", 7)) {
+                               pci_realloc();
                        } else if (!strcmp(str, "nodomains")) {
                                pci_no_domains();
                        } else if (!strncmp(str, "cbiosize=", 9)) {
@@ -2996,6 +3568,10 @@ static int __init pci_setup(char *str)
                                pci_hotplug_io_size = memparse(str + 9, &str);
                        } else if (!strncmp(str, "hpmemsize=", 10)) {
                                pci_hotplug_mem_size = memparse(str + 10, &str);
+                       } else if (!strncmp(str, "pcie_bus_safe", 13)) {
+                               pcie_bus_config = PCIE_BUS_SAFE;
+                       } else if (!strncmp(str, "pcie_bus_perf", 13)) {
+                               pcie_bus_config = PCIE_BUS_PERFORMANCE;
                        } else {
                                printk(KERN_ERR "PCI: Unknown option `%s'\n",
                                                str);