PCI: Add weak pcibios_window_alignment() interface
authorGavin Shan <shangw@linux.vnet.ibm.com>
Tue, 11 Sep 2012 22:59:45 +0000 (16:59 -0600)
committerBjorn Helgaas <bhelgaas@google.com>
Tue, 11 Sep 2012 22:59:45 +0000 (16:59 -0600)
This patch implements a weak function to return the default I/O or memory
window alignment for a P2P bridge.  By default, I/O windows are aligned to
4KiB or 1KiB and memory windows are aligned to 4MiB.  Some platforms, e.g.,
powernv, have special alignment requirements and can override
pcibios_window_alignment().

[bhelgaas: changelog]
Signed-off-by: Gavin Shan <shangw@linux.vnet.ibm.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
drivers/pci/setup-bus.c
include/linux/pci.h

index fb506137aaee57049f615ffb59d50b12a7788eec..896f06e3e793621c49eca731044efae49b3099e9 100644 (file)
@@ -697,6 +697,38 @@ static resource_size_t calculate_memsize(resource_size_t size,
        return size;
 }
 
+resource_size_t __weak pcibios_window_alignment(struct pci_bus *bus,
+                                               unsigned long type)
+{
+       return 1;
+}
+
+#define PCI_P2P_DEFAULT_MEM_ALIGN      0x100000        /* 1MiB */
+#define PCI_P2P_DEFAULT_IO_ALIGN       0x1000          /* 4KiB */
+#define PCI_P2P_DEFAULT_IO_ALIGN_1K    0x400           /* 1KiB */
+
+static resource_size_t window_alignment(struct pci_bus *bus,
+                                       unsigned long type)
+{
+       resource_size_t align = 1, arch_align;
+
+       if (type & IORESOURCE_MEM)
+               align = PCI_P2P_DEFAULT_MEM_ALIGN;
+       else if (type & IORESOURCE_IO) {
+               /*
+                * Per spec, I/O windows are 4K-aligned, but some
+                * bridges have an extension to support 1K alignment.
+                */
+               if (bus->self->io_window_1k)
+                       align = PCI_P2P_DEFAULT_IO_ALIGN_1K;
+               else
+                       align = PCI_P2P_DEFAULT_IO_ALIGN;
+       }
+
+       arch_align = pcibios_window_alignment(bus, type);
+       return max(align, arch_align);
+}
+
 /**
  * pbus_size_io() - size the io window of a given bus
  *
index b8667e0548e0d159c068b8159daf8af5ad77d296..2c755243eef2aae5f5a513d24df427a7739cfbb6 100644 (file)
@@ -1064,6 +1064,8 @@ int pci_cfg_space_size_ext(struct pci_dev *dev);
 int pci_cfg_space_size(struct pci_dev *dev);
 unsigned char pci_bus_max_busnr(struct pci_bus *bus);
 void pci_setup_bridge(struct pci_bus *bus);
+resource_size_t pcibios_window_alignment(struct pci_bus *bus,
+                                        unsigned long type);
 
 #define PCI_VGA_STATE_CHANGE_BRIDGE (1 << 0)
 #define PCI_VGA_STATE_CHANGE_DECODES (1 << 1)