- Update to 2.6.25-rc3.
[linux-flexiantxendom0-3.2.10.git] / drivers / pci / pci.c
index 71d561f..183fdda 100644 (file)
@@ -314,6 +314,24 @@ int pci_find_ht_capability(struct pci_dev *dev, int ht_cap)
 }
 EXPORT_SYMBOL_GPL(pci_find_ht_capability);
 
+void pcie_wait_pending_transaction(struct pci_dev *dev)
+{
+       int pos;
+       u16 reg16;
+
+       pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
+       if (!pos)
+               return;
+       while (1) {
+               pci_read_config_word(dev, pos + PCI_EXP_DEVSTA, &reg16);
+               if (!(reg16 & PCI_EXP_DEVSTA_TRPND))
+                       break;
+               cpu_relax();
+       }
+
+}
+EXPORT_SYMBOL_GPL(pcie_wait_pending_transaction);
+
 /**
  * pci_find_parent_resource - return resource region of parent bus of given region
  * @dev: PCI device structure contains resources to be searched
@@ -353,7 +371,7 @@ pci_find_parent_resource(const struct pci_dev *dev, struct resource *res)
  * Restore the BAR values for a given device, so as to make it
  * accessible by its driver.
  */
-void
+static void
 pci_restore_bars(struct pci_dev *dev)
 {
        int i, numres;
@@ -536,6 +554,7 @@ pci_power_t pci_choose_state(struct pci_dev *dev, pm_message_t state)
        case PM_EVENT_PRETHAW:
                /* REVISIT both freeze and pre-thaw "should" use D0 */
        case PM_EVENT_SUSPEND:
+       case PM_EVENT_HIBERNATE:
                return PCI_D3hot;
        default:
                printk("Unrecognized suspend event %d\n", state.event);
@@ -551,6 +570,7 @@ static int pci_save_pcie_state(struct pci_dev *dev)
        int pos, i = 0;
        struct pci_cap_saved_state *save_state;
        u16 *cap;
+       int found = 0;
 
        pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
        if (pos <= 0)
@@ -559,6 +579,8 @@ static int pci_save_pcie_state(struct pci_dev *dev)
        save_state = pci_find_saved_cap(dev, PCI_CAP_ID_EXP);
        if (!save_state)
                save_state = kzalloc(sizeof(*save_state) + sizeof(u16) * 4, GFP_KERNEL);
+       else
+               found = 1;
        if (!save_state) {
                dev_err(&dev->dev, "Out of memory in pci_save_pcie_state\n");
                return -ENOMEM;
@@ -569,7 +591,9 @@ static int pci_save_pcie_state(struct pci_dev *dev)
        pci_read_config_word(dev, pos + PCI_EXP_LNKCTL, &cap[i++]);
        pci_read_config_word(dev, pos + PCI_EXP_SLTCTL, &cap[i++]);
        pci_read_config_word(dev, pos + PCI_EXP_RTCTL, &cap[i++]);
-       pci_add_saved_cap(dev, save_state);
+       save_state->cap_nr = PCI_CAP_ID_EXP;
+       if (!found)
+               pci_add_saved_cap(dev, save_state);
        return 0;
 }
 
@@ -597,14 +621,17 @@ static int pci_save_pcix_state(struct pci_dev *dev)
        int pos, i = 0;
        struct pci_cap_saved_state *save_state;
        u16 *cap;
+       int found = 0;
 
        pos = pci_find_capability(dev, PCI_CAP_ID_PCIX);
        if (pos <= 0)
                return 0;
 
-       save_state = pci_find_saved_cap(dev, PCI_CAP_ID_EXP);
+       save_state = pci_find_saved_cap(dev, PCI_CAP_ID_PCIX);
        if (!save_state)
                save_state = kzalloc(sizeof(*save_state) + sizeof(u16), GFP_KERNEL);
+       else
+               found = 1;
        if (!save_state) {
                dev_err(&dev->dev, "Out of memory in pci_save_pcie_state\n");
                return -ENOMEM;
@@ -612,7 +639,9 @@ static int pci_save_pcix_state(struct pci_dev *dev)
        cap = (u16 *)&save_state->data[0];
 
        pci_read_config_word(dev, pos + PCI_X_CMD, &cap[i++]);
-       pci_add_saved_cap(dev, save_state);
+       save_state->cap_nr = PCI_CAP_ID_PCIX;
+       if (!found)
+               pci_add_saved_cap(dev, save_state);
        return 0;
 }
 
@@ -713,23 +742,19 @@ int pci_reenable_device(struct pci_dev *dev)
        return 0;
 }
 
-/**
- * pci_enable_device_bars - Initialize some of a device for use
- * @dev: PCI device to be initialized
- * @bars: bitmask of BAR's that must be configured
- *
- *  Initialize device before it's used by a driver. Ask low-level code
- *  to enable selected I/O and memory resources. Wake up the device if it
- *  was suspended. Beware, this function can fail.
- */
-int
-pci_enable_device_bars(struct pci_dev *dev, int bars)
+static int __pci_enable_device_flags(struct pci_dev *dev,
+                                    resource_size_t flags)
 {
        int err;
+       int i, bars = 0;
 
        if (atomic_add_return(1, &dev->enable_cnt) > 1)
                return 0;               /* already enabled */
 
+       for (i = 0; i < DEVICE_COUNT_RESOURCE; i++)
+               if (dev->resource[i].flags & flags)
+                       bars |= (1 << i);
+
        err = do_pci_enable_device(dev, bars);
        if (err < 0)
                atomic_dec(&dev->enable_cnt);
@@ -737,6 +762,32 @@ pci_enable_device_bars(struct pci_dev *dev, int bars)
 }
 
 /**
+ * pci_enable_device_io - Initialize a device for use with IO space
+ * @dev: PCI device to be initialized
+ *
+ *  Initialize device before it's used by a driver. Ask low-level code
+ *  to enable I/O resources. Wake up the device if it was suspended.
+ *  Beware, this function can fail.
+ */
+int pci_enable_device_io(struct pci_dev *dev)
+{
+       return __pci_enable_device_flags(dev, IORESOURCE_IO);
+}
+
+/**
+ * pci_enable_device_mem - Initialize a device for use with Memory space
+ * @dev: PCI device to be initialized
+ *
+ *  Initialize device before it's used by a driver. Ask low-level code
+ *  to enable Memory resources. Wake up the device if it was suspended.
+ *  Beware, this function can fail.
+ */
+int pci_enable_device_mem(struct pci_dev *dev)
+{
+       return __pci_enable_device_flags(dev, IORESOURCE_MEM);
+}
+
+/**
  * pci_enable_device - Initialize device before it's used by a driver.
  * @dev: PCI device to be initialized
  *
@@ -749,7 +800,7 @@ pci_enable_device_bars(struct pci_dev *dev, int bars)
  */
 int pci_enable_device(struct pci_dev *dev)
 {
-       return pci_enable_device_bars(dev, (1 << PCI_NUM_RESOURCES) - 1);
+       return __pci_enable_device_flags(dev, IORESOURCE_MEM | IORESOURCE_IO);
 }
 
 /*
@@ -823,7 +874,8 @@ int pcim_enable_device(struct pci_dev *pdev)
        dr = get_pci_dr(pdev);
        if (unlikely(!dr))
                return -ENOMEM;
-       WARN_ON(!!dr->enabled);
+       if (dr->enabled)
+               return 0;
 
        rc = pci_enable_device(pdev);
        if (!rc) {
@@ -884,6 +936,9 @@ pci_disable_device(struct pci_dev *dev)
        if (atomic_sub_return(1, &dev->enable_cnt) != 0)
                return;
 
+       /* Wait for all transactions are finished before disabling the device */
+       pcie_wait_pending_transaction(dev);
+
        pci_read_config_word(dev, PCI_COMMAND, &pci_command);
        if (pci_command & PCI_COMMAND_MASTER) {
                pci_command &= ~PCI_COMMAND_MASTER;
@@ -1397,6 +1452,22 @@ pci_set_consistent_dma_mask(struct pci_dev *dev, u64 mask)
 }
 #endif
 
+#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
+
 /**
  * pcix_get_max_mmrbc - get PCI-X maximum designed memory read byte count
  * @dev: PCI device to query
@@ -1618,9 +1689,9 @@ early_param("pci", pci_setup);
 
 device_initcall(pci_init);
 
-EXPORT_SYMBOL_GPL(pci_restore_bars);
 EXPORT_SYMBOL(pci_reenable_device);
-EXPORT_SYMBOL(pci_enable_device_bars);
+EXPORT_SYMBOL(pci_enable_device_io);
+EXPORT_SYMBOL(pci_enable_device_mem);
 EXPORT_SYMBOL(pci_enable_device);
 EXPORT_SYMBOL(pcim_enable_device);
 EXPORT_SYMBOL(pcim_pin_device);