[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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.