]> git.hungrycats.org Git - linux/commitdiff
[PATCH] ia64: update PCI segment support
authorAlex Williamson <alex_williamson@hp.com>
Thu, 3 Apr 2003 05:57:00 +0000 (21:57 -0800)
committerDavid Mosberger <davidm@tiger.hpl.hp.com>
Thu, 3 Apr 2003 05:57:00 +0000 (21:57 -0800)
Update to the PCI segment support that Bjorn posted around 2.5.19ish.

arch/ia64/kernel/acpi.c
arch/ia64/pci/pci.c
include/asm-ia64/acpi.h
include/asm-ia64/pci.h
include/asm-ia64/system.h

index 951d2ffc4baa87ce73db411192fb545acc77492a..b1c6734ded522ad34f7c2d9a9007963aa9f8bed1 100644 (file)
@@ -109,8 +109,6 @@ acpi_get_sysname (void)
        return "sn2";
 # elif defined (CONFIG_IA64_DIG)
        return "dig";
-# elif defined (CONFIG_IA64_HP_ZX1)
-       return "hpzx1";
 # else
 #      error Unknown platform.  Fix acpi.c.
 # endif
@@ -176,6 +174,73 @@ acpi_dispose_crs (struct acpi_buffer *buf)
        kfree(buf->pointer);
 }
 
+void
+acpi_get_crs_addr (struct acpi_buffer *buf, int type, u64 *base, u64 *size, u64 *tra)
+{
+       int offset = 0;
+       struct acpi_resource_address16 *addr16;
+       struct acpi_resource_address32 *addr32;
+       struct acpi_resource_address64 *addr64;
+
+       for (;;) {
+               struct acpi_resource *res = acpi_get_crs_next(buf, &offset);
+               if (!res)
+                       return;
+               switch (res->id) {
+                       case ACPI_RSTYPE_ADDRESS16:
+                               addr16 = (struct acpi_resource_address16 *) &res->data;
+
+                               if (type == addr16->resource_type) {
+                                       *base = addr16->min_address_range;
+                                       *size = addr16->address_length;
+                                       *tra = addr16->address_translation_offset;
+                                       return;
+                               }
+                               break;
+                       case ACPI_RSTYPE_ADDRESS32:
+                               addr32 = (struct acpi_resource_address32 *) &res->data;
+                               if (type == addr32->resource_type) {
+                                       *base = addr32->min_address_range;
+                                       *size = addr32->address_length;
+                                       *tra = addr32->address_translation_offset;
+                                       return;
+                               }
+                               break;
+                       case ACPI_RSTYPE_ADDRESS64:
+                               addr64 = (struct acpi_resource_address64 *) &res->data;
+                               if (type == addr64->resource_type) {
+                                       *base = addr64->min_address_range;
+                                       *size = addr64->address_length;
+                                       *tra = addr64->address_translation_offset;
+                                       return;
+                               }
+                               break;
+               }
+       }
+}
+
+int
+acpi_get_addr_space(void *obj, u8 type, u64 *base, u64 *length, u64 *tra)
+{
+       acpi_status status;
+       struct acpi_buffer buf;
+
+       *base = 0;
+       *length = 0;
+       *tra = 0;
+
+       status = acpi_get_crs((acpi_handle)obj, &buf);
+       if (ACPI_FAILURE(status)) {
+               printk(KERN_ERR PREFIX "Unable to get _CRS data on object\n");
+               return status;
+       }
+
+       acpi_get_crs_addr(&buf, type, base, length, tra);
+
+       acpi_dispose_crs(&buf);
+
+       return AE_OK;
+}
 #endif /* CONFIG_ACPI */
 
 #ifdef CONFIG_ACPI_BOOT
@@ -808,6 +873,7 @@ acpi_get_prt (struct pci_vector_struct **vectors, int *count)
 
        list_for_each(node, &acpi_prt.entries) {
                entry = (struct acpi_prt_entry *)node;
+               vector[i].segment = entry->id.segment;
                vector[i].bus    = entry->id.bus;
                vector[i].pci_id = ((u32) entry->id.device << 16) | 0xffff;
                vector[i].pin    = entry->pin;
index c0e7bac3b123fa29613d1a5cc6627fa0457b7877..88d9ee2f97b811b9a640e5a105926970d2eca445 100644 (file)
@@ -49,11 +49,13 @@ struct pci_fixup pcibios_fixups[1];
 /*
  * Low-level SAL-based PCI configuration access functions. Note that SAL
  * calls are already serialized (via sal_lock), so we don't need another
- * synchronization mechanism here.  Not using segment number (yet).
+ * synchronization mechanism here.
  */
 
-#define PCI_SAL_ADDRESS(bus, dev, fn, reg) \
-       ((u64)(bus << 16) | (u64)(dev << 11) | (u64)(fn << 8) | (u64)(reg))
+#define PCI_SAL_ADDRESS(seg, bus, dev, fn, reg) \
+       ((u64)(seg << 24) | (u64)(bus << 16) | \
+        (u64)(dev << 11) | (u64)(fn << 8) | (u64)(reg))
+
 
 static int
 __pci_sal_read (int seg, int bus, int dev, int fn, int reg, int len, u32 *value)
@@ -61,10 +63,10 @@ __pci_sal_read (int seg, int bus, int dev, int fn, int reg, int len, u32 *value)
        int result = 0;
        u64 data = 0;
 
-       if (!value || (bus > 255) || (dev > 31) || (fn > 7) || (reg > 255))
+       if (!value || (seg > 255) || (bus > 255) || (dev > 31) || (fn > 7) || (reg > 255))
                return -EINVAL;
 
-       result = ia64_sal_pci_config_read(PCI_SAL_ADDRESS(bus, dev, fn, reg), len, &data);
+       result = ia64_sal_pci_config_read(PCI_SAL_ADDRESS(seg, bus, dev, fn, reg), len, &data);
 
        *value = (u32) data;
 
@@ -74,24 +76,24 @@ __pci_sal_read (int seg, int bus, int dev, int fn, int reg, int len, u32 *value)
 static int
 __pci_sal_write (int seg, int bus, int dev, int fn, int reg, int len, u32 value)
 {
-       if ((bus > 255) || (dev > 31) || (fn > 7) || (reg > 255))
+       if ((seg > 255) || (bus > 255) || (dev > 31) || (fn > 7) || (reg > 255))
                return -EINVAL;
 
-       return ia64_sal_pci_config_write(PCI_SAL_ADDRESS(bus, dev, fn, reg), len, value);
+       return ia64_sal_pci_config_write(PCI_SAL_ADDRESS(seg, bus, dev, fn, reg), len, value);
 }
 
 
 static int
 pci_sal_read (struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *value)
 {
-       return __pci_sal_read(0, bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn),
+       return __pci_sal_read(PCI_SEGMENT(bus), bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn),
                              where, size, value);
 }
 
 static int
 pci_sal_write (struct pci_bus *bus, unsigned int devfn, int where, int size, u32 value)
 {
-       return __pci_sal_write(0, bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn),
+       return __pci_sal_write(PCI_SEGMENT(bus), bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn),
                               where, size, value);
 }
 
@@ -114,24 +116,91 @@ pci_acpi_init (void)
 
 subsys_initcall(pci_acpi_init);
 
+static void __init
+pcibios_fixup_resource(struct resource *res, u64 offset)
+{
+       res->start += offset;
+       res->end += offset;
+}
+
+void __init
+pcibios_fixup_device_resources(struct pci_dev *dev, struct pci_bus *bus)
+{
+       int i;
+
+       for (i = 0; i < PCI_NUM_RESOURCES; i++) {
+               if (!dev->resource[i].start)
+                       continue;
+               if (dev->resource[i].flags & IORESOURCE_MEM)
+                       pcibios_fixup_resource(&dev->resource[i],
+                                              PCI_CONTROLLER(dev)->mem_offset);
+       }
+}
+
 /* Called by ACPI when it finds a new root bus.  */
+
+static struct pci_controller *
+alloc_pci_controller(int seg)
+{
+       struct pci_controller *controller;
+
+       controller = kmalloc(sizeof(*controller), GFP_KERNEL);
+       if (!controller)
+               return NULL;
+
+       memset(controller, 0, sizeof(*controller));
+       controller->segment = seg;
+       return controller;
+}
+
 struct pci_bus *
-pcibios_scan_root (int bus)
+scan_root_bus(int bus, struct pci_ops *ops, void *sysdata)
 {
-       struct list_head *list;
-       struct pci_bus *pci_bus;
-
-       list_for_each(list, &pci_root_buses) {
-               pci_bus = pci_bus_b(list);
-               if (pci_bus->number == bus) {
-                       /* Already scanned */
-                       printk("PCI: Bus (%02x) already probed\n", bus);
-                       return pci_bus;
-               }
-       }
+       struct pci_bus *b;
 
-       printk("PCI: Probing PCI hardware on bus (%02x)\n", bus);
-       return pci_scan_bus(bus, pci_root_ops, NULL);
+       /*
+        * We know this is a new root bus we haven't seen before, so
+        * scan it, even if we've seen the same bus number in a different
+        * segment.
+        */
+       b = kmalloc(sizeof(*b), GFP_KERNEL);
+       if (!b)
+               return NULL;
+
+       memset(b, 0, sizeof(*b));
+       INIT_LIST_HEAD(&b->children);
+       INIT_LIST_HEAD(&b->devices);
+
+       list_add_tail(&b->node, &pci_root_buses);
+
+       b->number = b->secondary = bus;
+       b->resource[0] = &ioport_resource;
+       b->resource[1] = &iomem_resource;
+
+       b->sysdata = sysdata;
+       b->ops = ops;
+       b->subordinate = pci_do_scan_bus(b);
+
+       return b;
+}
+
+struct pci_bus *
+pcibios_scan_root(void *handle, int seg, int bus)
+{
+       struct pci_controller *controller;
+       u64 base, size, offset;
+
+       printk("PCI: Probing PCI hardware on bus (%02x:%02x)\n", seg, bus);
+       controller = alloc_pci_controller(seg);
+       if (!controller)
+               return NULL;
+
+       controller->acpi_handle = handle;
+
+       acpi_get_addr_space(handle, ACPI_MEMORY_RANGE, &base, &size, &offset);
+       controller->mem_offset = offset;
+
+       return scan_root_bus(bus, pci_root_ops, controller);
 }
 
 /*
@@ -140,6 +209,11 @@ pcibios_scan_root (int bus)
 void __devinit
 pcibios_fixup_bus (struct pci_bus *b)
 {
+       struct list_head *ln;
+
+       for (ln = b->devices.next; ln != &b->devices; ln = ln->next)
+               pcibios_fixup_device_resources(pci_dev_b(ln), b);
+
        return;
 }
 
index bbd4e9f8936994e8b97dc85afb9e15d6b115ccd6..580b1093f119d8ca8f2f64a252e19387515dfaa7 100644 (file)
@@ -100,7 +100,9 @@ const char *acpi_get_sysname (void);
 int acpi_request_vector (u32 int_type);
 int acpi_get_prt (struct pci_vector_struct **vectors, int *count);
 int acpi_get_interrupt_model (int *type);
+int acpi_register_irq (u32 gsi, u32 polarity, u32 trigger);
 int acpi_irq_to_vector (u32 irq);
+int acpi_get_addr_space (void *obj, u8 type, u64 *base, u64 *length,u64 *tra);
 
 #ifdef CONFIG_ACPI_NUMA
 #include <asm/numa.h>
index 62a7d5a544d57bbd67fb9bf1ac1d7a97ab498694..da5043aeafb4269662a9c45655776cc6db845e73 100644 (file)
@@ -21,7 +21,7 @@
 #define PCIBIOS_MIN_MEM                0x10000000
 
 void pcibios_config_init(void);
-struct pci_bus * pcibios_scan_root(int bus);
+struct pci_bus * pcibios_scan_root(void *acpi_handle, int segment, int bus);
 
 struct pci_dev;
 
@@ -58,7 +58,6 @@ extern int pcibios_prep_mwi (struct pci_dev *);
 #define pci_unmap_sg                   platform_pci_unmap_sg
 #define pci_dma_sync_single            platform_pci_dma_sync_single
 #define pci_dma_sync_sg                        platform_pci_dma_sync_sg
-#define sg_dma_address                 platform_pci_dma_address
 #define pci_dma_supported              platform_pci_dma_supported
 
 /* pci_unmap_{single,page} is not a nop, thus... */
@@ -92,9 +91,21 @@ extern int pcibios_prep_mwi (struct pci_dev *);
 #define pci_controller_num(PDEV)       (0)
 
 #define sg_dma_len(sg)         ((sg)->dma_length)
+#define sg_dma_address(sg)     ((sg)->dma_address)
 
 #define HAVE_PCI_MMAP
 extern int pci_mmap_page_range (struct pci_dev *dev, struct vm_area_struct *vma,
                                enum pci_mmap_state mmap_state, int write_combine);
 
+struct pci_controller {
+       void *acpi_handle;
+       void *iommu;
+       int segment;
+
+       u64 mem_offset;
+};
+
+#define PCI_CONTROLLER(busdev) ((struct pci_controller *) busdev->sysdata)
+#define PCI_SEGMENT(busdev)    (PCI_CONTROLLER(busdev)->segment)
+
 #endif /* _ASM_IA64_PCI_H */
index 6594d158a7c0de3291d6cee8e8d4f88f5b1f2526..14867853e1a0a38581c65e9869bb98616641d77e 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/types.h>
 
 struct pci_vector_struct {
+       __u16 segment;  /* PCI Segment number */
        __u16 bus;      /* PCI Bus number */
        __u32 pci_id;   /* ACPI split 16 bits device, 16 bits function (see section 6.1.1) */
        __u8 pin;       /* PCI PIN (0 = A, 1 = B, 2 = C, 3 = D) */