Merge branches 'acpica-fixes', 'acpi-video' and 'acpi-processor'
[linux-2.6-block.git] / drivers / pci / pci.c
index 25e0327d4429bfc00a694f66f4a28fc7233fb7df..c8b4dbdd1bddae95c214e92b52492b82364afcaf 100644 (file)
@@ -2228,7 +2228,7 @@ void pci_pm_init(struct pci_dev *dev)
 
 static unsigned long pci_ea_flags(struct pci_dev *dev, u8 prop)
 {
-       unsigned long flags = IORESOURCE_PCI_FIXED;
+       unsigned long flags = IORESOURCE_PCI_FIXED | IORESOURCE_PCI_EA_BEI;
 
        switch (prop) {
        case PCI_EA_P_MEM:
@@ -2389,7 +2389,7 @@ out:
        return offset + ent_size;
 }
 
-/* Enhanced Allocation Initalization */
+/* Enhanced Allocation Initialization */
 void pci_ea_init(struct pci_dev *dev)
 {
        int ea;
@@ -2547,7 +2547,7 @@ void pci_request_acs(void)
  * pci_std_enable_acs - enable ACS on devices using standard ACS capabilites
  * @dev: the PCI device
  */
-static int pci_std_enable_acs(struct pci_dev *dev)
+static void pci_std_enable_acs(struct pci_dev *dev)
 {
        int pos;
        u16 cap;
@@ -2555,7 +2555,7 @@ static int pci_std_enable_acs(struct pci_dev *dev)
 
        pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ACS);
        if (!pos)
-               return -ENODEV;
+               return;
 
        pci_read_config_word(dev, pos + PCI_ACS_CAP, &cap);
        pci_read_config_word(dev, pos + PCI_ACS_CTRL, &ctrl);
@@ -2573,8 +2573,6 @@ static int pci_std_enable_acs(struct pci_dev *dev)
        ctrl |= (cap & PCI_ACS_UF);
 
        pci_write_config_word(dev, pos + PCI_ACS_CTRL, ctrl);
-
-       return 0;
 }
 
 /**
@@ -2586,10 +2584,10 @@ void pci_enable_acs(struct pci_dev *dev)
        if (!pci_acs_enable)
                return;
 
-       if (!pci_std_enable_acs(dev))
+       if (!pci_dev_specific_enable_acs(dev))
                return;
 
-       pci_dev_specific_enable_acs(dev);
+       pci_std_enable_acs(dev);
 }
 
 static bool pci_acs_flags_enabled(struct pci_dev *pdev, u16 acs_flags)
@@ -3021,6 +3019,121 @@ int pci_request_regions_exclusive(struct pci_dev *pdev, const char *res_name)
 }
 EXPORT_SYMBOL(pci_request_regions_exclusive);
 
+#ifdef PCI_IOBASE
+struct io_range {
+       struct list_head list;
+       phys_addr_t start;
+       resource_size_t size;
+};
+
+static LIST_HEAD(io_range_list);
+static DEFINE_SPINLOCK(io_range_lock);
+#endif
+
+/*
+ * 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 err = 0;
+
+#ifdef PCI_IOBASE
+       struct io_range *range;
+       resource_size_t allocated_size = 0;
+
+       /* check if the range hasn't been previously recorded */
+       spin_lock(&io_range_lock);
+       list_for_each_entry(range, &io_range_list, list) {
+               if (addr >= range->start && addr + size <= range->start + size) {
+                       /* range already registered, bail out */
+                       goto end_register;
+               }
+               allocated_size += range->size;
+       }
+
+       /* range not registed yet, check for available space */
+       if (allocated_size + size - 1 > IO_SPACE_LIMIT) {
+               /* if it's too big check if 64K space can be reserved */
+               if (allocated_size + SZ_64K - 1 > IO_SPACE_LIMIT) {
+                       err = -E2BIG;
+                       goto end_register;
+               }
+
+               size = SZ_64K;
+               pr_warn("Requested IO range too big, new size set to 64K\n");
+       }
+
+       /* add the range to the list */
+       range = kzalloc(sizeof(*range), GFP_ATOMIC);
+       if (!range) {
+               err = -ENOMEM;
+               goto end_register;
+       }
+
+       range->start = addr;
+       range->size = size;
+
+       list_add_tail(&range->list, &io_range_list);
+
+end_register:
+       spin_unlock(&io_range_lock);
+#endif
+
+       return err;
+}
+
+phys_addr_t pci_pio_to_address(unsigned long pio)
+{
+       phys_addr_t address = (phys_addr_t)OF_BAD_ADDR;
+
+#ifdef PCI_IOBASE
+       struct io_range *range;
+       resource_size_t allocated_size = 0;
+
+       if (pio > IO_SPACE_LIMIT)
+               return address;
+
+       spin_lock(&io_range_lock);
+       list_for_each_entry(range, &io_range_list, list) {
+               if (pio >= allocated_size && pio < allocated_size + range->size) {
+                       address = range->start + pio - allocated_size;
+                       break;
+               }
+               allocated_size += range->size;
+       }
+       spin_unlock(&io_range_lock);
+#endif
+
+       return address;
+}
+
+unsigned long __weak pci_address_to_pio(phys_addr_t address)
+{
+#ifdef PCI_IOBASE
+       struct io_range *res;
+       resource_size_t offset = 0;
+       unsigned long addr = -1;
+
+       spin_lock(&io_range_lock);
+       list_for_each_entry(res, &io_range_list, list) {
+               if (address >= res->start && address < res->start + res->size) {
+                       addr = address - res->start + offset;
+                       break;
+               }
+               offset += res->size;
+       }
+       spin_unlock(&io_range_lock);
+
+       return addr;
+#else
+       if (address > IO_SPACE_LIMIT)
+               return (unsigned long)-1;
+
+       return (unsigned long) address;
+#endif
+}
+
 /**
  *     pci_remap_iospace - Remap the memory mapped I/O space
  *     @res: Resource describing the I/O space
@@ -4578,6 +4691,37 @@ int pci_set_vga_state(struct pci_dev *dev, bool decode,
        return 0;
 }
 
+/**
+ * pci_add_dma_alias - Add a DMA devfn alias for a device
+ * @dev: the PCI device for which alias is added
+ * @devfn: alias slot and function
+ *
+ * This helper encodes 8-bit devfn as bit number in dma_alias_mask.
+ * It should be called early, preferably as PCI fixup header quirk.
+ */
+void pci_add_dma_alias(struct pci_dev *dev, u8 devfn)
+{
+       if (!dev->dma_alias_mask)
+               dev->dma_alias_mask = kcalloc(BITS_TO_LONGS(U8_MAX),
+                                             sizeof(long), GFP_KERNEL);
+       if (!dev->dma_alias_mask) {
+               dev_warn(&dev->dev, "Unable to allocate DMA alias mask\n");
+               return;
+       }
+
+       set_bit(devfn, dev->dma_alias_mask);
+       dev_info(&dev->dev, "Enabling fixed DMA alias to %02x.%d\n",
+                PCI_SLOT(devfn), PCI_FUNC(devfn));
+}
+
+bool pci_devs_are_dma_aliases(struct pci_dev *dev1, struct pci_dev *dev2)
+{
+       return (dev1->dma_alias_mask &&
+               test_bit(dev2->devfn, dev1->dma_alias_mask)) ||
+              (dev2->dma_alias_mask &&
+               test_bit(dev1->devfn, dev2->dma_alias_mask));
+}
+
 bool pci_device_is_present(struct pci_dev *pdev)
 {
        u32 v;