[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [linux-2.6.18-xen] [IA64] Issue ioremap hypercall in pci_acpi_scan_root()
# HG changeset patch # User Alex Williamson <alex.williamson@xxxxxx> # Date 1185814887 21600 # Node ID 8f0c93df3e113058f0b582b06ce7d3d897ccc9d6 # Parent f017328288ea42600509b62882f687d7331ce194 [IA64] Issue ioremap hypercall in pci_acpi_scan_root() This setups up mapping in /dev/mem. Signed-off-by: Jun Kamada <kama@xxxxxxxxxxxxxx> --- arch/ia64/pci/pci.c | 184 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 184 insertions(+) diff -r f017328288ea -r 8f0c93df3e11 arch/ia64/pci/pci.c --- a/arch/ia64/pci/pci.c Mon Jul 30 10:53:36 2007 -0600 +++ b/arch/ia64/pci/pci.c Mon Jul 30 11:01:27 2007 -0600 @@ -29,6 +29,15 @@ #include <asm/smp.h> #include <asm/irq.h> #include <asm/hw_irq.h> + +#ifdef CONFIG_XEN +struct ioremap_issue_list { + struct list_head listp; + unsigned long start; + unsigned long end; +}; +typedef struct ioremap_issue_list ioremap_issue_list_t; +#endif /* CONFIG_XEN */ /* * Low-level SAL-based PCI configuration access functions. Note that SAL @@ -337,6 +346,169 @@ pcibios_setup_root_windows(struct pci_bu } } +#ifdef CONFIG_XEN +static void +__cleanup_issue_list(struct list_head *top) +{ + ioremap_issue_list_t *ptr, *tmp_ptr; + + list_for_each_entry_safe(ptr, tmp_ptr, top, listp) { + list_del(&(ptr->listp)); + kfree(ptr); + } +} + +static int +__add_issue_list(unsigned long start, unsigned long end, struct list_head *top) +{ + ioremap_issue_list_t *ptr, *new; + + if (start > end) { + printk(KERN_ERR "%s: Internal error (start addr > end addr)\n", + __FUNCTION__); + return 0; + } + + /* + * Head of the resource structure list contains + * dummy val.(start=0, end=~0), so skip it + */ + if ((start == 0) && (end == ~0)) + return 0; + + start &= PAGE_MASK; + end |= ~PAGE_MASK; + + /* We can merge specified address range into existing entry */ + list_for_each_entry(ptr, top, listp) { + if ((ptr->start > end + 1) || (ptr->end + 1 < start)) + continue; + ptr->start = min(start, ptr->start); + ptr->end = max(end, ptr->end); + return 0; + } + + /* We could not merge, so create new entry */ + new = kmalloc(sizeof(ioremap_issue_list_t), GFP_KERNEL); + if (new == NULL) { + printk(KERN_ERR "%s: Could not allocate memory. " + "HYPERVISOR_ioremap will not be issued\n", + __FUNCTION__); + return -ENOMEM; + } + + new->start = start; + new->end = end; + + /* Insert the new entry to the list by ascending order */ + if (list_empty(top)) { + list_add_tail(&(new->listp), top); + return 0; + } + list_for_each_entry(ptr, top, listp) { + if (new->start > ptr->start) + continue; + list_add(&(new->listp), ((struct list_head *)ptr)->prev); + return 0; + } + list_add_tail(&(new->listp), top); + + return 0; +} + +static int +__make_issue_list(struct resource *ptr, struct list_head *top) +{ + int ret; + + if (ptr->child) { + ret = __make_issue_list(ptr->child, top); + if (ret) + return ret; + } + if (ptr->sibling) { + ret = __make_issue_list(ptr->sibling, top); + if (ret) + return ret; + } + + if (ptr->flags & IORESOURCE_MEM) { + ret = __add_issue_list(ptr->start, ptr->end, top); + if (ret) + return ret; + } + + return 0; +} + +static void +__compress_issue_list(struct list_head *top) +{ + ioremap_issue_list_t *ptr, *tmp_ptr, *next; + int compressed; + + /* + * Merge adjacent entries, if overlapped + * (entries are sorted by ascending order) + */ + list_for_each_entry_safe(ptr, tmp_ptr, top, listp) { + if (list_is_last((struct list_head *)ptr, top)) + continue; + + next = (ioremap_issue_list_t *) + (((struct list_head *)ptr)->next); + if (next->start <= (ptr->end) + 1) { + next->start = min(ptr->start, next->start); + next->end = max(ptr->end, next->end); + + list_del(&(ptr->listp)); + kfree(ptr); + } + } +} + +static int +__issue_ioremap(struct list_head *top) +{ + ioremap_issue_list_t *ptr, *tmp_ptr; + unsigned int offset; + + list_for_each_entry_safe(ptr, tmp_ptr, top, listp) { + offset = HYPERVISOR_ioremap(ptr->start, + ptr->end - ptr->start + 1); + if (offset == ~0) { + printk(KERN_ERR "%s: HYPERVISOR_ioremap() failed. " + "Address Range: 0x%016lx-0x%016lx\n", + __FUNCTION__, ptr->start, ptr->end); + } + + list_del(&(ptr->listp)); + kfree(ptr); + } + + return 0; +} + +static int +do_ioremap_on_resource_list(struct resource *top) +{ + LIST_HEAD(ioremap_issue_list_top); + int ret; + + ret = __make_issue_list(top, &ioremap_issue_list_top); + if (ret) { + __cleanup_issue_list(&ioremap_issue_list_top); + return ret; + } + + __compress_issue_list(&ioremap_issue_list_top); + + (void)__issue_ioremap(&ioremap_issue_list_top); + + return 0; +} +#endif /* CONFIG_XEN */ + struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_device *device, int domain, int bus) { @@ -379,6 +551,18 @@ pci_acpi_scan_root(struct acpi_device *d pbus = pci_scan_bus_parented(NULL, bus, &pci_root_ops, controller); if (pbus) pcibios_setup_root_windows(pbus, controller); + +#ifdef CONFIG_XEN + if (is_initial_xendomain()) { + if (do_ioremap_on_resource_list(&iomem_resource) != 0) { + printk(KERN_ERR + "%s: Counld not issue HYPERVISOR_ioremap " + "due to lack of memory or hypercall failure\n", + __FUNCTION__); + goto out3; + } + } +#endif /* CONFIG_XEN */ return pbus; _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |