From: Alex Williamson <alex_williamson@hp.com>
To: linux-ia64@vger.kernel.org
Subject: [Linux-ia64] [PATCH] 2/4 pci segments
Date: Thu, 03 Apr 2003 17:51:38 +0000 [thread overview]
Message-ID: <marc-linux-ia64-105590723705394@msgid-missing> (raw)
[-- Attachment #1: Type: text/plain, Size: 209 bytes --]
Patch 2 is an update to the PCI segment support that Bjorn posted
around 2.5.19ish. Also against 2.5.64 + 030307. Thanks,
Alex
--
Alex Williamson HP Linux & Open Source Lab
[-- Attachment #2: patch-02.diff --]
[-- Type: text/plain, Size: 10679 bytes --]
diff -urN linux-2.5.64/arch/ia64/kernel/acpi.c linux-work/arch/ia64/kernel/acpi.c
--- linux-2.5.64/arch/ia64/kernel/acpi.c Tue Apr 1 08:49:07 2003
+++ linux-work/arch/ia64/kernel/acpi.c Tue Apr 1 15:20:36 2003
@@ -109,8 +109,6 @@
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 @@
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 @@
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;
diff -urN linux-2.5.64/arch/ia64/pci/pci.c linux-work/arch/ia64/pci/pci.c
--- linux-2.5.64/arch/ia64/pci/pci.c Tue Apr 1 08:49:07 2003
+++ linux-work/arch/ia64/pci/pci.c Tue Apr 1 09:19:53 2003
@@ -49,11 +49,13 @@
/*
* 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 @@
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 @@
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 @@
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;
+ struct pci_bus *b;
- 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;
- }
- }
+ /*
+ * 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;
- printk("PCI: Probing PCI hardware on bus (%02x)\n", bus);
- return pci_scan_bus(bus, pci_root_ops, NULL);
+ 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 @@
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;
}
diff -urN linux-2.5.64/drivers/acpi/pci_root.c linux-work/drivers/acpi/pci_root.c
--- linux-2.5.64/drivers/acpi/pci_root.c Tue Mar 4 20:29:04 2003
+++ linux-work/drivers/acpi/pci_root.c Tue Apr 1 09:19:53 2003
@@ -265,7 +265,8 @@
* PCI namespace does not get created until this call is made (and
* thus the root bridge's pci_dev does not exist).
*/
- root->bus = pcibios_scan_root(root->id.bus);
+ root->bus = pcibios_scan_root(root->handle,
+ root->id.segment, root->id.bus);
if (!root->bus) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"Bus %02x:%02x not present in PCI namespace\n",
diff -urN linux-2.5.64/include/asm-ia64/acpi.h linux-work/include/asm-ia64/acpi.h
--- linux-2.5.64/include/asm-ia64/acpi.h Tue Mar 4 20:29:34 2003
+++ linux-work/include/asm-ia64/acpi.h Wed Apr 2 13:20:35 2003
@@ -100,7 +100,9 @@
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>
diff -urN linux-2.5.64/include/asm-ia64/pci.h linux-work/include/asm-ia64/pci.h
--- linux-2.5.64/include/asm-ia64/pci.h Tue Apr 1 08:49:07 2003
+++ linux-work/include/asm-ia64/pci.h Tue Apr 1 09:19:53 2003
@@ -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 @@
#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 @@
#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 */
diff -urN linux-2.5.64/include/asm-ia64/system.h linux-work/include/asm-ia64/system.h
--- linux-2.5.64/include/asm-ia64/system.h Tue Apr 1 08:49:07 2003
+++ linux-work/include/asm-ia64/system.h Tue Apr 1 09:19:53 2003
@@ -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) */
next reply other threads:[~2003-04-03 17:51 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2003-04-03 17:51 Alex Williamson [this message]
2003-04-03 20:34 ` [Linux-ia64] [PATCH] 2/4 pci segments David Mosberger
2003-04-03 20:42 ` Alex Williamson
2003-04-03 20:42 ` Alex Williamson
2003-04-03 20:42 ` Alex Williamson
2003-04-03 20:44 ` Matthew Wilcox
2003-04-03 21:30 ` David Mosberger
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=marc-linux-ia64-105590723705394@msgid-missing \
--to=alex_williamson@hp.com \
--cc=linux-ia64@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.