[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [RFC] [PATCH 3/3] XEN ARM PCI support



This patch adds support for pci in xen arm. Following features are
added
a) pci device tree node is parsed and platform callback is invoked
For thunderX the callback stores the reg property, which is later
used in generating address based on the s:b:d.f

b) ABI followed is segment no is mapped to the order of pci nodes in
the xen device tree.
---
 xen/arch/arm/Makefile         |   1 +
 xen/arch/arm/pci.c            | 111 ++++++++++++++++++++++++++++++++++++++++++
 xen/arch/arm/setup.c          |   3 +-
 xen/drivers/passthrough/pci.c |  28 ++++++++---
 xen/include/asm-arm/device.h  |   1 +
 xen/include/asm-arm/domain.h  |   3 ++
 xen/include/asm-arm/pci.h     |  25 ++++++++--
 7 files changed, 159 insertions(+), 13 deletions(-)

diff --git a/xen/arch/arm/Makefile b/xen/arch/arm/Makefile
index 41aba2e..41d0eab 100644
--- a/xen/arch/arm/Makefile
+++ b/xen/arch/arm/Makefile
@@ -38,6 +38,7 @@ obj-y += device.o
 obj-y += decode.o
 obj-y += processor.o
 obj-y += smc.o
+obj-$(HAS_PCI) += pci.o
#obj-bin-y += ....o diff --git a/xen/arch/arm/pci.c b/xen/arch/arm/pci.c
new file mode 100644
index 0000000..9877726
--- /dev/null
+++ b/xen/arch/arm/pci.c
@@ -0,0 +1,111 @@
+/*
+ * Architecture-dependent PCI access functions
+ *
+ * Manish Jaggi <manish.jaggi@xxxxxxxxxxxxxxxxxx>
+ * Copyright (c) 2015 Cavium Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <xen/pci.h>
+#include <asm/device.h>
+#include <asm/io.h>
+#include <xen/mm.h>
+#include <xen/vmap.h>
+#include <asm/pci.h>
+#include <asm/platform.h>
+
+static int __init pci_dt_node_init(struct dt_device_node *node, const void 
*data)
+{
+    return platform_pci_dt_node_init(node, data);
+}
+
+void pci_init(void)
+{
+    int rc;
+    struct dt_device_node *node;
+
+    //Enumerate the PCI nodes in device tree
+    dt_for_each_device_node( dt_host, node )
+    {
+        if ( !dt_device_type_is_equal(node, "pci") )
+        continue;
+
+        rc = device_init(node, DEVICE_PCI, NULL);
+        if ( !rc )
+            break;
+    }
+}
+
+uint8_t pci_conf_read8(unsigned int seg, unsigned int bus, unsigned int dev,
+                       unsigned int func, unsigned int reg)
+{
+    unsigned int val;
+
+    platform_pci_read_config(seg, bus, dev, func, reg, 1, &val);
+    return val;
+}
+
+uint16_t pci_conf_read16(unsigned int seg, unsigned int bus, unsigned int dev,
+                         unsigned int func, unsigned int reg)
+{
+    unsigned int val;
+
+    platform_pci_read_config(seg, bus, dev, func, reg, 2, &val);
+    return val;
+}
+
+uint32_t pci_conf_read32(unsigned int seg, unsigned int bus, unsigned int dev,
+                         unsigned int func, unsigned int reg)
+{
+    unsigned int val;
+
+    platform_pci_read_config(seg, bus, dev, func, reg, 4, &val);
+    return val;
+}
+
+void pci_conf_write8(unsigned int seg, unsigned int bus, unsigned int dev,
+                     unsigned int func, unsigned int reg, uint8_t data)
+{
+    platform_pci_write_config(seg, bus, dev, func, reg, 1, data);
+}
+
+void pci_conf_write16(unsigned int seg, unsigned int bus, unsigned int dev,
+                      unsigned int func, unsigned int reg, uint16_t data)
+{
+    platform_pci_write_config(seg, bus, dev, func, reg, 2, data);
+}
+
+void pci_conf_write32(unsigned int seg, unsigned int bus, unsigned int dev,
+                      unsigned int func, unsigned int reg, uint32_t data)
+{
+    platform_pci_write_config(seg, bus, dev, func, reg, 4, data);
+}
+
+static const char * const pci_dt_compat[] __initconst =
+{
+    "cavium,thunder-pcie",
+    NULL
+};
+
+DT_DEVICE_START(pci, "PCI", DEVICE_PCI)
+    .compatible =pci_dt_compat,
+    .init = pci_dt_node_init,
+DT_DEVICE_END
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c
index 43b626b..56119ff 100644
--- a/xen/arch/arm/setup.c
+++ b/xen/arch/arm/setup.c
@@ -769,7 +769,7 @@ void __init start_xen(unsigned long boot_phys_offset,
tasklet_subsys_init(); -
+    pci_init();
     xsm_dt_init();
init_maintenance_interrupt();
@@ -783,6 +783,7 @@ void __init start_xen(unsigned long boot_phys_offset,
arch_init_memory(); + pt_pci_init();
     local_irq_enable();
     local_abort_enable();
diff --git a/xen/drivers/passthrough/pci.c b/xen/drivers/passthrough/pci.c
index b93e7d8..aefaa3c 100644
--- a/xen/drivers/passthrough/pci.c
+++ b/xen/drivers/passthrough/pci.c
@@ -22,8 +22,11 @@
 #include <xen/prefetch.h>
 #include <xen/iommu.h>
 #include <xen/irq.h>
+#ifndef CONFIG_ARM
 #include <asm/hvm/iommu.h>
 #include <asm/hvm/irq.h>
+#include <asm/msi.h>
+#endif
 #include <xen/delay.h>
 #include <xen/keyhandler.h>
 #include <xen/event.h>
@@ -33,7 +36,6 @@
 #include <xen/softirq.h>
 #include <xen/tasklet.h>
 #include <xsm/xsm.h>
-#include <asm/msi.h>
struct pci_seg {
     struct list_head alldevs_list;
@@ -287,6 +289,7 @@ static struct pci_dev *alloc_pdev(struct pci_seg *pseg, u8 
bus, u8 devfn)
     if ( pci_find_cap_offset(pseg->nr, bus, PCI_SLOT(devfn), PCI_FUNC(devfn),
                              PCI_CAP_ID_MSIX) )
     {
+#ifndef CONFIG_ARM
         struct arch_msix *msix = xzalloc(struct arch_msix);
if ( !msix )
@@ -296,6 +299,7 @@ static struct pci_dev *alloc_pdev(struct pci_seg *pseg, u8 
bus, u8 devfn)
         }
         spin_lock_init(&msix->table_lock);
         pdev->msix = msix;
+#endif
     }
list_add(&pdev->alldevs_list, &pseg->alldevs_list);
@@ -396,7 +400,9 @@ static void free_pdev(struct pci_seg *pseg, struct pci_dev 
*pdev)
     }
list_del(&pdev->alldevs_list);
+#ifndef CONFIG_ARM
     xfree(pdev->msix);
+#endif
     xfree(pdev);
 }
@@ -424,7 +430,7 @@ int __init pci_hide_device(int bus, int devfn) return rc;
 }
-
+#ifndef CONFIG_ARM
 int __init pci_ro_device(int seg, int bus, int devfn)
 {
     struct pci_seg *pseg = alloc_pseg(seg);
@@ -452,7 +458,7 @@ int __init pci_ro_device(int seg, int bus, int devfn)
return 0;
 }
-
+#endif
 struct pci_dev *pci_get_pdev(int seg, int bus, int devfn)
 {
     struct pci_seg *pseg = get_pseg(seg);
@@ -740,7 +746,9 @@ int pci_remove_device(u16 seg, u8 bus, u8 devfn)
             ret = iommu_remove_device(pdev);
             if ( pdev->domain )
                 list_del(&pdev->domain_list);
+#ifndef CONFIG_ARM
             pci_cleanup_msi(pdev);
+#endif
             free_pdev(pseg, pdev);
             printk(XENLOG_DEBUG "PCI remove device %04x:%02x:%02x.%u\n",
                    seg, bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
@@ -750,7 +758,7 @@ int pci_remove_device(u16 seg, u8 bus, u8 devfn)
     spin_unlock(&pcidevs_lock);
     return ret;
 }
-
+#ifndef CONFIG_ARM
 static int pci_clean_dpci_irq(struct domain *d,
                               struct hvm_pirq_dpci *pirq_dpci, void *arg)
 {
@@ -798,11 +806,12 @@ static int pci_clean_dpci_irqs(struct domain *d)
     spin_unlock(&d->event_lock);
     return 0;
 }
-
+#endif
 int pci_release_devices(struct domain *d)
 {
     struct pci_dev *pdev;
     u8 bus, devfn;
+#ifndef CONFIG_ARM
     int ret;
spin_lock(&pcidevs_lock);
@@ -812,6 +821,8 @@ int pci_release_devices(struct domain *d)
         spin_unlock(&pcidevs_lock);
         return ret;
     }
+#endif
+
     while ( (pdev = pci_get_pdev_by_domain(d, -1, -1, -1)) )
     {
         bus = pdev->bus;
@@ -1184,6 +1195,7 @@ bool_t pcie_aer_get_firmware_first(const struct pci_dev 
*pdev)
static int _dump_pci_devices(struct pci_seg *pseg, void *arg)
 {
+#ifndef CONFIG_ARM
     struct pci_dev *pdev;
     struct msi_desc *msi;
@@ -1199,7 +1211,7 @@ static int _dump_pci_devices(struct pci_seg *pseg, void *arg)
                printk("%d ", msi->irq);
         printk(">\n");
     }
-
+#endif
     return 0;
 }
@@ -1341,7 +1353,7 @@ static int assign_device(struct domain *d, u16 seg, u8 bus, u8 devfn) if ( !iommu_enabled || !hd->platform_ops )
         return 0;
-
+#ifndef CONFIG_ARM
     /* Prevent device assign if mem paging or mem sharing have been
      * enabled for this domain */
     if ( unlikely(!need_iommu(d) &&
@@ -1349,7 +1361,7 @@ static int assign_device(struct domain *d, u16 seg, u8 
bus, u8 devfn)
              d->mem_event->paging.ring_page ||
              p2m_get_hostp2m(d)->global_logdirty)) )
         return -EXDEV;
-
+#endif
     if ( !spin_trylock(&pcidevs_lock) )
         return -ERESTART;
diff --git a/xen/include/asm-arm/device.h b/xen/include/asm-arm/device.h
index 74a80c6..8223034 100644
--- a/xen/include/asm-arm/device.h
+++ b/xen/include/asm-arm/device.h
@@ -9,6 +9,7 @@ enum device_type
     DEVICE_SERIAL,
     DEVICE_IOMMU,
     DEVICE_GIC,
+    DEVICE_PCI,
     /* Use for error */
     DEVICE_UNKNOWN,
 };
diff --git a/xen/include/asm-arm/domain.h b/xen/include/asm-arm/domain.h
index 9018c6a..0d17480 100644
--- a/xen/include/asm-arm/domain.h
+++ b/xen/include/asm-arm/domain.h
@@ -13,6 +13,8 @@
 #include <xen/serial.h>
 #include <xen/hvm/iommu.h>
+#define has_arch_pdevs(d) (!list_empty(&(d)->arch.pdev_list))
+
 struct hvm_domain
 {
     uint64_t              params[HVM_NR_PARAMS];
@@ -52,6 +54,7 @@ struct arch_domain
     struct p2m_domain p2m;
     uint64_t vttbr;
+ struct list_head pdev_list;
     struct hvm_domain hvm_domain;
     xen_pfn_t *grant_table_gpfn;
diff --git a/xen/include/asm-arm/pci.h b/xen/include/asm-arm/pci.h
index de13359..df8d1bc 100644
--- a/xen/include/asm-arm/pci.h
+++ b/xen/include/asm-arm/pci.h
@@ -1,7 +1,24 @@
-#ifndef __X86_PCI_H__
-#define __X86_PCI_H__
+/*
+ * PCI functions for ARM
+ *
+ * Manish Jaggi <manish.jaggi@xxxxxxxxxxxxxxxxxx>
+ * Copyright (c) 2015 Cavium Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#ifndef __ARM_PCI_H__
+#define __ARM_PCI_H__
 struct arch_pci_dev {
+    //placeholder
 };
-
-#endif /* __X86_PCI_H__ */
+void pci_init(void);
+#endif /* __ARM_PCI_H__ */
--
1.9.1



_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

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