All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/2] xen/x86: Patch re-factors MSI/X config code from, drivers/passthrough/pci.c to x86 specific
@ 2015-04-13  7:40 Manish Jaggi
  2015-04-13 10:15 ` Stefano Stabellini
  2015-04-13 10:28 ` Julien Grall
  0 siblings, 2 replies; 5+ messages in thread
From: Manish Jaggi @ 2015-04-13  7:40 UTC (permalink / raw)
  To: Xen Devel, Stefano Stabellini, Ian Campbell, Julien Grall,
	Kumar, Vijaya, Prasun.kapoor@cavium.com

This patch re-factors msi specific code to x86 specific files from
xen/drivers/passthrough/pci.c.

Signed-off-by: Manish Jaggi <manish.jaggi@caviumnetworks.com>
---
  xen/drivers/passthrough/pci.c        |  102 +-----------------------------
  xen/drivers/passthrough/x86/Makefile |    1 +
  xen/drivers/passthrough/x86/pci.c    |  115 ++++++++++++++++++++++++++++++++++
  xen/include/asm-x86/msi.h            |    1 -
  xen/include/xen/pci.h                |   20 +++++-
  5 files changed, 137 insertions(+), 102 deletions(-)

diff --git a/xen/drivers/passthrough/pci.c b/xen/drivers/passthrough/pci.c
index ecd061e..004aba9 100644
--- a/xen/drivers/passthrough/pci.c
+++ b/xen/drivers/passthrough/pci.c
@@ -23,7 +23,6 @@
  #include <xen/iommu.h>
  #include <xen/irq.h>
  #include <asm/hvm/iommu.h>
-#include <asm/hvm/irq.h>
  #include <xen/delay.h>
  #include <xen/keyhandler.h>
  #include <xen/event.h>
@@ -33,21 +32,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;
-    u16 nr;
-    unsigned long *ro_map;
-    /* bus2bridge_lock protects bus2bridge array */
-    spinlock_t bus2bridge_lock;
-#define MAX_BUSES 256
-    struct {
-        u8 map;
-        u8 bus;
-        u8 devfn;
-    } bus2bridge[MAX_BUSES];
-};
  
  spinlock_t pcidevs_lock = SPIN_LOCK_UNLOCKED;
  static struct radix_tree_root pci_segments;
@@ -282,22 +266,10 @@ static struct pci_dev *alloc_pdev(struct pci_seg *pseg, u8 bus, u8 devfn)
      *((u8*) &pdev->bus) = bus;
      *((u8*) &pdev->devfn) = devfn;
      pdev->domain = NULL;
-    INIT_LIST_HEAD(&pdev->msi_list);
-
-    if ( pci_find_cap_offset(pseg->nr, bus, PCI_SLOT(devfn), PCI_FUNC(devfn),
-                             PCI_CAP_ID_MSIX) )
+    if (!pci_alloc_msix (pdev, pseg, bus, devfn))
      {
-        struct arch_msix *msix = xzalloc(struct arch_msix);
-
-        if ( !msix )
-        {
-            xfree(pdev);
-            return NULL;
-        }
-        spin_lock_init(&msix->table_lock);
-        pdev->msix = msix;
+        return NULL;
      }
-
      list_add(&pdev->alldevs_list, &pseg->alldevs_list);
  
      /* update bus2bridge */
@@ -755,54 +727,6 @@ int pci_remove_device(u16 seg, u8 bus, u8 devfn)
      return ret;
  }
  
-static int pci_clean_dpci_irq(struct domain *d,
-                              struct hvm_pirq_dpci *pirq_dpci, void *arg)
-{
-    struct dev_intx_gsi_link *digl, *tmp;
-
-    pirq_guest_unbind(d, dpci_pirq(pirq_dpci));
-
-    if ( pt_irq_need_timer(pirq_dpci->flags) )
-        kill_timer(&pirq_dpci->timer);
-
-    list_for_each_entry_safe ( digl, tmp, &pirq_dpci->digl_list, list )
-    {
-        list_del(&digl->list);
-        xfree(digl);
-    }
-
-    return pt_pirq_softirq_active(pirq_dpci) ? -ERESTART : 0;
-}
-
-static int pci_clean_dpci_irqs(struct domain *d)
-{
-    struct hvm_irq_dpci *hvm_irq_dpci = NULL;
-
-    if ( !iommu_enabled )
-        return 0;
-
-    if ( !is_hvm_domain(d) )
-        return 0;
-
-    spin_lock(&d->event_lock);
-    hvm_irq_dpci = domain_get_irq_dpci(d);
-    if ( hvm_irq_dpci != NULL )
-    {
-        int ret = pt_pirq_iterate(d, pci_clean_dpci_irq, NULL);
-
-        if ( ret )
-        {
-            spin_unlock(&d->event_lock);
-            return ret;
-        }
-
-        d->arch.hvm_domain.irq.dpci = NULL;
-        free_hvm_irq_dpci(hvm_irq_dpci);
-    }
-    spin_unlock(&d->event_lock);
-    return 0;
-}
-
  int pci_release_devices(struct domain *d)
  {
      struct pci_dev *pdev;
@@ -1186,28 +1110,6 @@ bool_t pcie_aer_get_firmware_first(const struct pci_dev *pdev)
  }
  #endif
  
-static int _dump_pci_devices(struct pci_seg *pseg, void *arg)
-{
-    struct pci_dev *pdev;
-    struct msi_desc *msi;
-
-    printk("==== segment %04x ====\n", pseg->nr);
-
-    list_for_each_entry ( pdev, &pseg->alldevs_list, alldevs_list )
-    {
-        printk("%04x:%02x:%02x.%u - dom %-3d - node %-3d - MSIs < ",
-               pseg->nr, pdev->bus,
-               PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn),
-               pdev->domain ? pdev->domain->domain_id : -1,
-               (pdev->node != NUMA_NO_NODE) ? pdev->node : -1);
-        list_for_each_entry ( msi, &pdev->msi_list, list )
-               printk("%d ", msi->irq);
-        printk(">\n");
-    }
-
-    return 0;
-}
-
  static void dump_pci_devices(unsigned char ch)
  {
      printk("==== PCI devices ====\n");
diff --git a/xen/drivers/passthrough/x86/Makefile b/xen/drivers/passthrough/x86/Makefile
index a70cf94..a2bcf94 100644
--- a/xen/drivers/passthrough/x86/Makefile
+++ b/xen/drivers/passthrough/x86/Makefile
@@ -1,2 +1,3 @@
  obj-y += ats.o
  obj-y += iommu.o
+obj-$(HAS_PCI) += pci.o
diff --git a/xen/drivers/passthrough/x86/pci.c b/xen/drivers/passthrough/x86/pci.c
new file mode 100644
index 0000000..cf37b0a
--- /dev/null
+++ b/xen/drivers/passthrough/x86/pci.c
@@ -0,0 +1,115 @@
+/*
+ * x86 specific code for PCI MSI
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Copyright (C) 2015 Cavium Networks
+ *
+ * Author: Manish Jaggi <manish.jaggi@cavium.com>
+ */
+#include <xen/pci.h>
+#include <xen/sched.h>
+#include <asm/hvm/irq.h>
+#include <asm/msi.h>
+
+int _dump_pci_devices(struct pci_seg *pseg, void *arg)
+{
+    struct pci_dev *pdev;
+    struct msi_desc *msi;
+
+    printk("==== segment %04x ====\n", pseg->nr);
+
+    list_for_each_entry ( pdev, &pseg->alldevs_list, alldevs_list )
+    {
+        printk("%04x:%02x:%02x.%u - dom %-3d - node %-3d - MSIs < ",
+               pseg->nr, pdev->bus,
+               PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn),
+               pdev->domain ? pdev->domain->domain_id : -1,
+               (pdev->node != NUMA_NO_NODE) ? pdev->node : -1);
+        list_for_each_entry ( msi, &pdev->msi_list, list )
+               printk("%d ", msi->irq);
+        printk(">\n");
+    }
+
+    return 0;
+}
+
+int pci_clean_dpci_irq(struct domain *d,
+                              struct hvm_pirq_dpci *pirq_dpci, void *arg)
+{
+    struct dev_intx_gsi_link *digl, *tmp;
+
+    pirq_guest_unbind(d, dpci_pirq(pirq_dpci));
+
+    if ( pt_irq_need_timer(pirq_dpci->flags) )
+        kill_timer(&pirq_dpci->timer);
+
+    list_for_each_entry_safe ( digl, tmp, &pirq_dpci->digl_list, list )
+    {
+        list_del(&digl->list);
+        xfree(digl);
+    }
+
+    return pt_pirq_softirq_active(pirq_dpci) ? -ERESTART : 0;
+}
+
+int pci_clean_dpci_irqs(struct domain *d)
+{
+    struct hvm_irq_dpci *hvm_irq_dpci = NULL;
+
+    if ( !iommu_enabled )
+        return 0;
+
+    if ( !is_hvm_domain(d) )
+        return 0;
+
+    spin_lock(&d->event_lock);
+    hvm_irq_dpci = domain_get_irq_dpci(d);
+    if ( hvm_irq_dpci != NULL )
+    {
+        int ret = pt_pirq_iterate(d, pci_clean_dpci_irq, NULL);
+
+        if ( ret )
+        {
+            spin_unlock(&d->event_lock);
+            return ret;
+        }
+
+        d->arch.hvm_domain.irq.dpci = NULL;
+        free_hvm_irq_dpci(hvm_irq_dpci);
+    }
+    spin_unlock(&d->event_lock);
+    return 0;
+}
+
+struct pci_dev* pci_alloc_msix(struct pci_dev *pdev, struct pci_seg  *pseg, u8 bus, u8 devfn)
+{
+    INIT_LIST_HEAD(&pdev->msi_list);
+
+    if ( pci_find_cap_offset(pseg->nr, bus, PCI_SLOT(devfn), PCI_FUNC(devfn),
+                             PCI_CAP_ID_MSIX) )
+    {
+        struct arch_msix *msix = xzalloc(struct arch_msix);
+
+        if ( !msix )
+        {
+            xfree(pdev);
+            return NULL;
+        }
+        spin_lock_init(&msix->table_lock);
+        pdev->msix = msix;
+    }
+
+    return pdev;
+}
diff --git a/xen/include/asm-x86/msi.h b/xen/include/asm-x86/msi.h
index 4c62a3a..9b2b4a3 100644
--- a/xen/include/asm-x86/msi.h
+++ b/xen/include/asm-x86/msi.h
@@ -78,7 +78,6 @@ struct msi_desc;
  extern int pci_enable_msi(struct msi_info *msi, struct msi_desc **desc);
  extern void pci_disable_msi(struct msi_desc *desc);
  extern int pci_prepare_msix(u16 seg, u8 bus, u8 devfn, bool_t off);
-extern void pci_cleanup_msi(struct pci_dev *pdev);
  extern int setup_msi_irq(struct irq_desc *, struct msi_desc *);
  extern int __setup_msi_irq(struct irq_desc *, struct msi_desc *,
                             const struct hw_interrupt_type *);
diff --git a/xen/include/xen/pci.h b/xen/include/xen/pci.h
index 4377f3e..07e60fe 100644
--- a/xen/include/xen/pci.h
+++ b/xen/include/xen/pci.h
@@ -43,6 +43,20 @@ struct pci_dev_info {
      } physfn;
  };
  
+struct pci_seg {
+    struct list_head alldevs_list;
+    u16 nr;
+    unsigned long *ro_map;
+    /* bus2bridge_lock protects bus2bridge array */
+    spinlock_t bus2bridge_lock;
+#define MAX_BUSES 256
+    struct {
+        u8 map;
+        u8 bus;
+        u8 devfn;
+    } bus2bridge[MAX_BUSES];
+};
+
  struct pci_dev {
      struct list_head alldevs_list;
      struct list_head domain_list;
@@ -155,5 +169,9 @@ struct pirq;
  int msixtbl_pt_register(struct domain *, struct pirq *, uint64_t gtable);
  void msixtbl_pt_unregister(struct domain *, struct pirq *);
  void msixtbl_pt_cleanup(struct domain *d);
-
+struct pci_dev* pci_alloc_msix(struct pci_dev *pdev, struct pci_seg  *pseg,
+                                u8 bus, u8 devfn);
+int pci_clean_dpci_irqs(struct domain *d);
+void pci_cleanup_msi(struct pci_dev *pdev);
+int _dump_pci_devices(struct pci_seg *pseg, void *arg);
  #endif /* __XEN_PCI_H__ */
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH 1/2] xen/x86: Patch re-factors MSI/X config code from, drivers/passthrough/pci.c to x86 specific
  2015-04-13  7:40 [PATCH 1/2] xen/x86: Patch re-factors MSI/X config code from, drivers/passthrough/pci.c to x86 specific Manish Jaggi
@ 2015-04-13 10:15 ` Stefano Stabellini
  2015-04-13 10:34   ` Manish Jaggi
  2015-04-13 10:28 ` Julien Grall
  1 sibling, 1 reply; 5+ messages in thread
From: Stefano Stabellini @ 2015-04-13 10:15 UTC (permalink / raw)
  To: Manish Jaggi
  Cc: Prasun.kapoor@cavium.com, Ian Campbell, Stefano Stabellini,
	Kumar, Vijaya, Julien Grall, Xen Devel

On Mon, 13 Apr 2015, Manish Jaggi wrote:
> This patch re-factors msi specific code to x86 specific files from
> xen/drivers/passthrough/pci.c.
> 
> Signed-off-by: Manish Jaggi <manish.jaggi@caviumnetworks.com>
> ---
>  xen/drivers/passthrough/pci.c        |  102 +-----------------------------
>  xen/drivers/passthrough/x86/Makefile |    1 +
>  xen/drivers/passthrough/x86/pci.c    |  115
> ++++++++++++++++++++++++++++++++++
>  xen/include/asm-x86/msi.h            |    1 -
>  xen/include/xen/pci.h                |   20 +++++-
>  5 files changed, 137 insertions(+), 102 deletions(-)
> 
> diff --git a/xen/drivers/passthrough/pci.c b/xen/drivers/passthrough/pci.c
> index ecd061e..004aba9 100644
> --- a/xen/drivers/passthrough/pci.c
> +++ b/xen/drivers/passthrough/pci.c
> @@ -23,7 +23,6 @@
>  #include <xen/iommu.h>
>  #include <xen/irq.h>
>  #include <asm/hvm/iommu.h>
> -#include <asm/hvm/irq.h>
>  #include <xen/delay.h>
>  #include <xen/keyhandler.h>
>  #include <xen/event.h>
> @@ -33,21 +32,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;
> -    u16 nr;
> -    unsigned long *ro_map;
> -    /* bus2bridge_lock protects bus2bridge array */
> -    spinlock_t bus2bridge_lock;
> -#define MAX_BUSES 256
> -    struct {
> -        u8 map;
> -        u8 bus;
> -        u8 devfn;
> -    } bus2bridge[MAX_BUSES];
> -};
>   spinlock_t pcidevs_lock = SPIN_LOCK_UNLOCKED;
>  static struct radix_tree_root pci_segments;
> @@ -282,22 +266,10 @@ static struct pci_dev *alloc_pdev(struct pci_seg *pseg,
> u8 bus, u8 devfn)
>      *((u8*) &pdev->bus) = bus;
>      *((u8*) &pdev->devfn) = devfn;
>      pdev->domain = NULL;
> -    INIT_LIST_HEAD(&pdev->msi_list);
> -
> -    if ( pci_find_cap_offset(pseg->nr, bus, PCI_SLOT(devfn),
> PCI_FUNC(devfn),
> -                             PCI_CAP_ID_MSIX) )
> +    if (!pci_alloc_msix (pdev, pseg, bus, devfn))
>      {
> -        struct arch_msix *msix = xzalloc(struct arch_msix);
> -
> -        if ( !msix )
> -        {
> -            xfree(pdev);
> -            return NULL;
> -        }
> -        spin_lock_init(&msix->table_lock);
> -        pdev->msix = msix;
> +        return NULL;
>      }
> -

>From the look of it, this code doesn't seem x86 specific


>      list_add(&pdev->alldevs_list, &pseg->alldevs_list);
>       /* update bus2bridge */
> @@ -755,54 +727,6 @@ int pci_remove_device(u16 seg, u8 bus, u8 devfn)
>      return ret;
>  }
>  -static int pci_clean_dpci_irq(struct domain *d,
> -                              struct hvm_pirq_dpci *pirq_dpci, void *arg)
> -{
> -    struct dev_intx_gsi_link *digl, *tmp;
> -
> -    pirq_guest_unbind(d, dpci_pirq(pirq_dpci));
> -
> -    if ( pt_irq_need_timer(pirq_dpci->flags) )
> -        kill_timer(&pirq_dpci->timer);
> -
> -    list_for_each_entry_safe ( digl, tmp, &pirq_dpci->digl_list, list )
> -    {
> -        list_del(&digl->list);
> -        xfree(digl);
> -    }
> -
> -    return pt_pirq_softirq_active(pirq_dpci) ? -ERESTART : 0;
> -}
> -
> -static int pci_clean_dpci_irqs(struct domain *d)
> -{
> -    struct hvm_irq_dpci *hvm_irq_dpci = NULL;
> -
> -    if ( !iommu_enabled )
> -        return 0;
> -
> -    if ( !is_hvm_domain(d) )
> -        return 0;
> -
> -    spin_lock(&d->event_lock);
> -    hvm_irq_dpci = domain_get_irq_dpci(d);
> -    if ( hvm_irq_dpci != NULL )
> -    {
> -        int ret = pt_pirq_iterate(d, pci_clean_dpci_irq, NULL);
> -
> -        if ( ret )
> -        {
> -            spin_unlock(&d->event_lock);
> -            return ret;
> -        }
> -
> -        d->arch.hvm_domain.irq.dpci = NULL;
> -        free_hvm_irq_dpci(hvm_irq_dpci);
> -    }
> -    spin_unlock(&d->event_lock);
> -    return 0;
> -}

..but these two functions do


>  int pci_release_devices(struct domain *d)
>  {
>      struct pci_dev *pdev;
> @@ -1186,28 +1110,6 @@ bool_t pcie_aer_get_firmware_first(const struct
> pci_dev *pdev)
>  }
>  #endif
>  -static int _dump_pci_devices(struct pci_seg *pseg, void *arg)
> -{
> -    struct pci_dev *pdev;
> -    struct msi_desc *msi;
> -
> -    printk("==== segment %04x ====\n", pseg->nr);
> -
> -    list_for_each_entry ( pdev, &pseg->alldevs_list, alldevs_list )
> -    {
> -        printk("%04x:%02x:%02x.%u - dom %-3d - node %-3d - MSIs < ",
> -               pseg->nr, pdev->bus,
> -               PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn),
> -               pdev->domain ? pdev->domain->domain_id : -1,
> -               (pdev->node != NUMA_NO_NODE) ? pdev->node : -1);
> -        list_for_each_entry ( msi, &pdev->msi_list, list )
> -               printk("%d ", msi->irq);
> -        printk(">\n");
> -    }
> -
> -    return 0;
> -}
> -
>  static void dump_pci_devices(unsigned char ch)
>  {
>      printk("==== PCI devices ====\n");
> diff --git a/xen/drivers/passthrough/x86/Makefile
> b/xen/drivers/passthrough/x86/Makefile
> index a70cf94..a2bcf94 100644
> --- a/xen/drivers/passthrough/x86/Makefile
> +++ b/xen/drivers/passthrough/x86/Makefile
> @@ -1,2 +1,3 @@
>  obj-y += ats.o
>  obj-y += iommu.o
> +obj-$(HAS_PCI) += pci.o
> diff --git a/xen/drivers/passthrough/x86/pci.c
> b/xen/drivers/passthrough/x86/pci.c
> new file mode 100644
> index 0000000..cf37b0a
> --- /dev/null
> +++ b/xen/drivers/passthrough/x86/pci.c
> @@ -0,0 +1,115 @@
> +/*
> + * x86 specific code for PCI MSI
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * 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.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
> USA.
> + *
> + * Copyright (C) 2015 Cavium Networks
> + *
> + * Author: Manish Jaggi <manish.jaggi@cavium.com>
> + */
> +#include <xen/pci.h>
> +#include <xen/sched.h>
> +#include <asm/hvm/irq.h>
> +#include <asm/msi.h>
> +
> +int _dump_pci_devices(struct pci_seg *pseg, void *arg)
> +{
> +    struct pci_dev *pdev;
> +    struct msi_desc *msi;
> +
> +    printk("==== segment %04x ====\n", pseg->nr);
> +
> +    list_for_each_entry ( pdev, &pseg->alldevs_list, alldevs_list )
> +    {
> +        printk("%04x:%02x:%02x.%u - dom %-3d - node %-3d - MSIs < ",
> +               pseg->nr, pdev->bus,
> +               PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn),
> +               pdev->domain ? pdev->domain->domain_id : -1,
> +               (pdev->node != NUMA_NO_NODE) ? pdev->node : -1);
> +        list_for_each_entry ( msi, &pdev->msi_list, list )
> +               printk("%d ", msi->irq);
> +        printk(">\n");
> +    }
> +
> +    return 0;
> +}
> +
> +int pci_clean_dpci_irq(struct domain *d,
> +                              struct hvm_pirq_dpci *pirq_dpci, void *arg)
> +{
> +    struct dev_intx_gsi_link *digl, *tmp;
> +
> +    pirq_guest_unbind(d, dpci_pirq(pirq_dpci));
> +
> +    if ( pt_irq_need_timer(pirq_dpci->flags) )
> +        kill_timer(&pirq_dpci->timer);
> +
> +    list_for_each_entry_safe ( digl, tmp, &pirq_dpci->digl_list, list )
> +    {
> +        list_del(&digl->list);
> +        xfree(digl);
> +    }
> +
> +    return pt_pirq_softirq_active(pirq_dpci) ? -ERESTART : 0;
> +}
> +
> +int pci_clean_dpci_irqs(struct domain *d)
> +{
> +    struct hvm_irq_dpci *hvm_irq_dpci = NULL;
> +
> +    if ( !iommu_enabled )
> +        return 0;
> +
> +    if ( !is_hvm_domain(d) )
> +        return 0;
> +
> +    spin_lock(&d->event_lock);
> +    hvm_irq_dpci = domain_get_irq_dpci(d);
> +    if ( hvm_irq_dpci != NULL )
> +    {
> +        int ret = pt_pirq_iterate(d, pci_clean_dpci_irq, NULL);
> +
> +        if ( ret )
> +        {
> +            spin_unlock(&d->event_lock);
> +            return ret;
> +        }
> +
> +        d->arch.hvm_domain.irq.dpci = NULL;
> +        free_hvm_irq_dpci(hvm_irq_dpci);
> +    }
> +    spin_unlock(&d->event_lock);
> +    return 0;
> +}
> +
> +struct pci_dev* pci_alloc_msix(struct pci_dev *pdev, struct pci_seg  *pseg,
> u8 bus, u8 devfn)
> +{
> +    INIT_LIST_HEAD(&pdev->msi_list);
> +
> +    if ( pci_find_cap_offset(pseg->nr, bus, PCI_SLOT(devfn),
> PCI_FUNC(devfn),
> +                             PCI_CAP_ID_MSIX) )
> +    {
> +        struct arch_msix *msix = xzalloc(struct arch_msix);
> +
> +        if ( !msix )
> +        {
> +            xfree(pdev);
> +            return NULL;
> +        }
> +        spin_lock_init(&msix->table_lock);
> +        pdev->msix = msix;
> +    }
> +
> +    return pdev;
> +}
> diff --git a/xen/include/asm-x86/msi.h b/xen/include/asm-x86/msi.h
> index 4c62a3a..9b2b4a3 100644
> --- a/xen/include/asm-x86/msi.h
> +++ b/xen/include/asm-x86/msi.h
> @@ -78,7 +78,6 @@ struct msi_desc;
>  extern int pci_enable_msi(struct msi_info *msi, struct msi_desc **desc);
>  extern void pci_disable_msi(struct msi_desc *desc);
>  extern int pci_prepare_msix(u16 seg, u8 bus, u8 devfn, bool_t off);
> -extern void pci_cleanup_msi(struct pci_dev *pdev);
>  extern int setup_msi_irq(struct irq_desc *, struct msi_desc *);
>  extern int __setup_msi_irq(struct irq_desc *, struct msi_desc *,
>                             const struct hw_interrupt_type *);
> diff --git a/xen/include/xen/pci.h b/xen/include/xen/pci.h
> index 4377f3e..07e60fe 100644
> --- a/xen/include/xen/pci.h
> +++ b/xen/include/xen/pci.h
> @@ -43,6 +43,20 @@ struct pci_dev_info {
>      } physfn;
>  };
>  +struct pci_seg {
> +    struct list_head alldevs_list;
> +    u16 nr;
> +    unsigned long *ro_map;
> +    /* bus2bridge_lock protects bus2bridge array */
> +    spinlock_t bus2bridge_lock;
> +#define MAX_BUSES 256
> +    struct {
> +        u8 map;
> +        u8 bus;
> +        u8 devfn;
> +    } bus2bridge[MAX_BUSES];
> +};
> +
>  struct pci_dev {
>      struct list_head alldevs_list;
>      struct list_head domain_list;
> @@ -155,5 +169,9 @@ struct pirq;
>  int msixtbl_pt_register(struct domain *, struct pirq *, uint64_t gtable);
>  void msixtbl_pt_unregister(struct domain *, struct pirq *);
>  void msixtbl_pt_cleanup(struct domain *d);
> -
> +struct pci_dev* pci_alloc_msix(struct pci_dev *pdev, struct pci_seg  *pseg,
> +                                u8 bus, u8 devfn);
> +int pci_clean_dpci_irqs(struct domain *d);
> +void pci_cleanup_msi(struct pci_dev *pdev);
> +int _dump_pci_devices(struct pci_seg *pseg, void *arg);
>  #endif /* __XEN_PCI_H__ */
> -- 
> 1.7.9.5
> 

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH 1/2] xen/x86: Patch re-factors MSI/X config code from, drivers/passthrough/pci.c to x86 specific
  2015-04-13  7:40 [PATCH 1/2] xen/x86: Patch re-factors MSI/X config code from, drivers/passthrough/pci.c to x86 specific Manish Jaggi
  2015-04-13 10:15 ` Stefano Stabellini
@ 2015-04-13 10:28 ` Julien Grall
  1 sibling, 0 replies; 5+ messages in thread
From: Julien Grall @ 2015-04-13 10:28 UTC (permalink / raw)
  To: Manish Jaggi, Xen Devel, Stefano Stabellini, Ian Campbell,
	Julien Grall, Kumar, Vijaya, Prasun.kapoor@cavium.com

Hi Manish,

On 13/04/15 08:40, Manish Jaggi wrote:
> -static int _dump_pci_devices(struct pci_seg *pseg, void *arg)
> -{
> -    struct pci_dev *pdev;
> -    struct msi_desc *msi;
> -
> -    printk("==== segment %04x ====\n", pseg->nr);
> -
> -    list_for_each_entry ( pdev, &pseg->alldevs_list, alldevs_list )
> -    {
> -        printk("%04x:%02x:%02x.%u - dom %-3d - node %-3d - MSIs < ",
> -               pseg->nr, pdev->bus,
> -               PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn),
> -               pdev->domain ? pdev->domain->domain_id : -1,
> -               (pdev->node != NUMA_NO_NODE) ? pdev->node : -1);
> -        list_for_each_entry ( msi, &pdev->msi_list, list )
> -               printk("%d ", msi->irq);
> -        printk(">\n");
> -    }
> -
> -    return 0;
> -}
> -

This doesn't sound like x86 specific.

> diff --git a/xen/drivers/passthrough/x86/pci.c
> b/xen/drivers/passthrough/x86/pci.c
> new file mode 100644
> index 0000000..cf37b0a
> --- /dev/null
> +++ b/xen/drivers/passthrough/x86/pci.c
> @@ -0,0 +1,115 @@
> +/*
> + * x86 specific code for PCI MSI
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * 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.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
> 02111-1307, USA.
> + *
> + * Copyright (C) 2015 Cavium Networks
> + *
> + * Author: Manish Jaggi <manish.jaggi@cavium.com>

You are not the author of this code, you just move the code in another
place.

Please the retain the previous copyright author.

Regards,

-- 
Julien Grall

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH 1/2] xen/x86: Patch re-factors MSI/X config code from, drivers/passthrough/pci.c to x86 specific
  2015-04-13 10:15 ` Stefano Stabellini
@ 2015-04-13 10:34   ` Manish Jaggi
  2015-04-14  9:11     ` Jan Beulich
  0 siblings, 1 reply; 5+ messages in thread
From: Manish Jaggi @ 2015-04-13 10:34 UTC (permalink / raw)
  To: Stefano Stabellini
  Cc: Prasun.kapoor@cavium.com, Kumar, Vijaya, Julien Grall,
	Ian Campbell, Xen Devel


On Monday 13 April 2015 03:45 PM, Stefano Stabellini wrote:
> On Mon, 13 Apr 2015, Manish Jaggi wrote:
>> This patch re-factors msi specific code to x86 specific files from
>> xen/drivers/passthrough/pci.c.
>>
>> Signed-off-by: Manish Jaggi <manish.jaggi@caviumnetworks.com>
>> ---
>>   xen/drivers/passthrough/pci.c        |  102 +-----------------------------
>>   xen/drivers/passthrough/x86/Makefile |    1 +
>>   xen/drivers/passthrough/x86/pci.c    |  115
>> ++++++++++++++++++++++++++++++++++
>>   xen/include/asm-x86/msi.h            |    1 -
>>   xen/include/xen/pci.h                |   20 +++++-
>>   5 files changed, 137 insertions(+), 102 deletions(-)
>>
>> diff --git a/xen/drivers/passthrough/pci.c b/xen/drivers/passthrough/pci.c
>> index ecd061e..004aba9 100644
>> --- a/xen/drivers/passthrough/pci.c
>> +++ b/xen/drivers/passthrough/pci.c
>> @@ -23,7 +23,6 @@
>>   #include <xen/iommu.h>
>>   #include <xen/irq.h>
>>   #include <asm/hvm/iommu.h>
>> -#include <asm/hvm/irq.h>
>>   #include <xen/delay.h>
>>   #include <xen/keyhandler.h>
>>   #include <xen/event.h>
>> @@ -33,21 +32,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;
>> -    u16 nr;
>> -    unsigned long *ro_map;
>> -    /* bus2bridge_lock protects bus2bridge array */
>> -    spinlock_t bus2bridge_lock;
>> -#define MAX_BUSES 256
>> -    struct {
>> -        u8 map;
>> -        u8 bus;
>> -        u8 devfn;
>> -    } bus2bridge[MAX_BUSES];
>> -};
>>    spinlock_t pcidevs_lock = SPIN_LOCK_UNLOCKED;
>>   static struct radix_tree_root pci_segments;
>> @@ -282,22 +266,10 @@ static struct pci_dev *alloc_pdev(struct pci_seg *pseg,
>> u8 bus, u8 devfn)
>>       *((u8*) &pdev->bus) = bus;
>>       *((u8*) &pdev->devfn) = devfn;
>>       pdev->domain = NULL;
>> -    INIT_LIST_HEAD(&pdev->msi_list);
>> -
>> -    if ( pci_find_cap_offset(pseg->nr, bus, PCI_SLOT(devfn),
>> PCI_FUNC(devfn),
>> -                             PCI_CAP_ID_MSIX) )
>> +    if (!pci_alloc_msix (pdev, pseg, bus, devfn))
>>       {
>> -        struct arch_msix *msix = xzalloc(struct arch_msix);
>> -
>> -        if ( !msix )
>> -        {
>> -            xfree(pdev);
>> -            return NULL;
>> -        }
>> -        spin_lock_init(&msix->table_lock);
>> -        pdev->msix = msix;
>> +        return NULL;
>>       }
>> -
>  From the look of it, this code doesn't seem x86 specific
MSIX is only used for x86, dom0/U handles MSI/X in ARM. I think If ARM 
is not using MSI/X then code has to be in x86 specific file.
>
>>       list_add(&pdev->alldevs_list, &pseg->alldevs_list);
>>        /* update bus2bridge */
>> @@ -755,54 +727,6 @@ int pci_remove_device(u16 seg, u8 bus, u8 devfn)
>>       return ret;
>>   }
>>   -static int pci_clean_dpci_irq(struct domain *d,
>> -                              struct hvm_pirq_dpci *pirq_dpci, void *arg)
>> -{
>> -    struct dev_intx_gsi_link *digl, *tmp;
>> -
>> -    pirq_guest_unbind(d, dpci_pirq(pirq_dpci));
>> -
>> -    if ( pt_irq_need_timer(pirq_dpci->flags) )
>> -        kill_timer(&pirq_dpci->timer);
>> -
>> -    list_for_each_entry_safe ( digl, tmp, &pirq_dpci->digl_list, list )
>> -    {
>> -        list_del(&digl->list);
>> -        xfree(digl);
>> -    }
>> -
>> -    return pt_pirq_softirq_active(pirq_dpci) ? -ERESTART : 0;
>> -}
>> -
>> -static int pci_clean_dpci_irqs(struct domain *d)
>> -{
>> -    struct hvm_irq_dpci *hvm_irq_dpci = NULL;
>> -
>> -    if ( !iommu_enabled )
>> -        return 0;
>> -
>> -    if ( !is_hvm_domain(d) )
>> -        return 0;
>> -
>> -    spin_lock(&d->event_lock);
>> -    hvm_irq_dpci = domain_get_irq_dpci(d);
>> -    if ( hvm_irq_dpci != NULL )
>> -    {
>> -        int ret = pt_pirq_iterate(d, pci_clean_dpci_irq, NULL);
>> -
>> -        if ( ret )
>> -        {
>> -            spin_unlock(&d->event_lock);
>> -            return ret;
>> -        }
>> -
>> -        d->arch.hvm_domain.irq.dpci = NULL;
>> -        free_hvm_irq_dpci(hvm_irq_dpci);
>> -    }
>> -    spin_unlock(&d->event_lock);
>> -    return 0;
>> -}
> ..but these two functions do
>
>
>>   int pci_release_devices(struct domain *d)
>>   {
>>       struct pci_dev *pdev;
>> @@ -1186,28 +1110,6 @@ bool_t pcie_aer_get_firmware_first(const struct
>> pci_dev *pdev)
>>   }
>>   #endif
>>   -static int _dump_pci_devices(struct pci_seg *pseg, void *arg)
>> -{
>> -    struct pci_dev *pdev;
>> -    struct msi_desc *msi;
>> -
>> -    printk("==== segment %04x ====\n", pseg->nr);
>> -
>> -    list_for_each_entry ( pdev, &pseg->alldevs_list, alldevs_list )
>> -    {
>> -        printk("%04x:%02x:%02x.%u - dom %-3d - node %-3d - MSIs < ",
>> -               pseg->nr, pdev->bus,
>> -               PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn),
>> -               pdev->domain ? pdev->domain->domain_id : -1,
>> -               (pdev->node != NUMA_NO_NODE) ? pdev->node : -1);
>> -        list_for_each_entry ( msi, &pdev->msi_list, list )
>> -               printk("%d ", msi->irq);
>> -        printk(">\n");
>> -    }
>> -
>> -    return 0;
>> -}
>> -
>>   static void dump_pci_devices(unsigned char ch)
>>   {
>>       printk("==== PCI devices ====\n");
>> diff --git a/xen/drivers/passthrough/x86/Makefile
>> b/xen/drivers/passthrough/x86/Makefile
>> index a70cf94..a2bcf94 100644
>> --- a/xen/drivers/passthrough/x86/Makefile
>> +++ b/xen/drivers/passthrough/x86/Makefile
>> @@ -1,2 +1,3 @@
>>   obj-y += ats.o
>>   obj-y += iommu.o
>> +obj-$(HAS_PCI) += pci.o
>> diff --git a/xen/drivers/passthrough/x86/pci.c
>> b/xen/drivers/passthrough/x86/pci.c
>> new file mode 100644
>> index 0000000..cf37b0a
>> --- /dev/null
>> +++ b/xen/drivers/passthrough/x86/pci.c
>> @@ -0,0 +1,115 @@
>> +/*
>> + * x86 specific code for PCI MSI
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License version 2 as
>> + * published by the Free Software Foundation.
>> + *
>> + * 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.
>> + *
>> + * You should have received a copy of the GNU General Public License
>> + * along with this program; if not, write to the Free Software
>> + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
>> USA.
>> + *
>> + * Copyright (C) 2015 Cavium Networks
>> + *
>> + * Author: Manish Jaggi <manish.jaggi@cavium.com>
>> + */
>> +#include <xen/pci.h>
>> +#include <xen/sched.h>
>> +#include <asm/hvm/irq.h>
>> +#include <asm/msi.h>
>> +
>> +int _dump_pci_devices(struct pci_seg *pseg, void *arg)
>> +{
>> +    struct pci_dev *pdev;
>> +    struct msi_desc *msi;
>> +
>> +    printk("==== segment %04x ====\n", pseg->nr);
>> +
>> +    list_for_each_entry ( pdev, &pseg->alldevs_list, alldevs_list )
>> +    {
>> +        printk("%04x:%02x:%02x.%u - dom %-3d - node %-3d - MSIs < ",
>> +               pseg->nr, pdev->bus,
>> +               PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn),
>> +               pdev->domain ? pdev->domain->domain_id : -1,
>> +               (pdev->node != NUMA_NO_NODE) ? pdev->node : -1);
>> +        list_for_each_entry ( msi, &pdev->msi_list, list )
>> +               printk("%d ", msi->irq);
>> +        printk(">\n");
>> +    }
>> +
>> +    return 0;
>> +}
>> +
>> +int pci_clean_dpci_irq(struct domain *d,
>> +                              struct hvm_pirq_dpci *pirq_dpci, void *arg)
>> +{
>> +    struct dev_intx_gsi_link *digl, *tmp;
>> +
>> +    pirq_guest_unbind(d, dpci_pirq(pirq_dpci));
>> +
>> +    if ( pt_irq_need_timer(pirq_dpci->flags) )
>> +        kill_timer(&pirq_dpci->timer);
>> +
>> +    list_for_each_entry_safe ( digl, tmp, &pirq_dpci->digl_list, list )
>> +    {
>> +        list_del(&digl->list);
>> +        xfree(digl);
>> +    }
>> +
>> +    return pt_pirq_softirq_active(pirq_dpci) ? -ERESTART : 0;
>> +}
>> +
>> +int pci_clean_dpci_irqs(struct domain *d)
>> +{
>> +    struct hvm_irq_dpci *hvm_irq_dpci = NULL;
>> +
>> +    if ( !iommu_enabled )
>> +        return 0;
>> +
>> +    if ( !is_hvm_domain(d) )
>> +        return 0;
>> +
>> +    spin_lock(&d->event_lock);
>> +    hvm_irq_dpci = domain_get_irq_dpci(d);
>> +    if ( hvm_irq_dpci != NULL )
>> +    {
>> +        int ret = pt_pirq_iterate(d, pci_clean_dpci_irq, NULL);
>> +
>> +        if ( ret )
>> +        {
>> +            spin_unlock(&d->event_lock);
>> +            return ret;
>> +        }
>> +
>> +        d->arch.hvm_domain.irq.dpci = NULL;
>> +        free_hvm_irq_dpci(hvm_irq_dpci);
>> +    }
>> +    spin_unlock(&d->event_lock);
>> +    return 0;
>> +}
>> +
>> +struct pci_dev* pci_alloc_msix(struct pci_dev *pdev, struct pci_seg  *pseg,
>> u8 bus, u8 devfn)
>> +{
>> +    INIT_LIST_HEAD(&pdev->msi_list);
>> +
>> +    if ( pci_find_cap_offset(pseg->nr, bus, PCI_SLOT(devfn),
>> PCI_FUNC(devfn),
>> +                             PCI_CAP_ID_MSIX) )
>> +    {
>> +        struct arch_msix *msix = xzalloc(struct arch_msix);
>> +
>> +        if ( !msix )
>> +        {
>> +            xfree(pdev);
>> +            return NULL;
>> +        }
>> +        spin_lock_init(&msix->table_lock);
>> +        pdev->msix = msix;
>> +    }
>> +
>> +    return pdev;
>> +}
>> diff --git a/xen/include/asm-x86/msi.h b/xen/include/asm-x86/msi.h
>> index 4c62a3a..9b2b4a3 100644
>> --- a/xen/include/asm-x86/msi.h
>> +++ b/xen/include/asm-x86/msi.h
>> @@ -78,7 +78,6 @@ struct msi_desc;
>>   extern int pci_enable_msi(struct msi_info *msi, struct msi_desc **desc);
>>   extern void pci_disable_msi(struct msi_desc *desc);
>>   extern int pci_prepare_msix(u16 seg, u8 bus, u8 devfn, bool_t off);
>> -extern void pci_cleanup_msi(struct pci_dev *pdev);
>>   extern int setup_msi_irq(struct irq_desc *, struct msi_desc *);
>>   extern int __setup_msi_irq(struct irq_desc *, struct msi_desc *,
>>                              const struct hw_interrupt_type *);
>> diff --git a/xen/include/xen/pci.h b/xen/include/xen/pci.h
>> index 4377f3e..07e60fe 100644
>> --- a/xen/include/xen/pci.h
>> +++ b/xen/include/xen/pci.h
>> @@ -43,6 +43,20 @@ struct pci_dev_info {
>>       } physfn;
>>   };
>>   +struct pci_seg {
>> +    struct list_head alldevs_list;
>> +    u16 nr;
>> +    unsigned long *ro_map;
>> +    /* bus2bridge_lock protects bus2bridge array */
>> +    spinlock_t bus2bridge_lock;
>> +#define MAX_BUSES 256
>> +    struct {
>> +        u8 map;
>> +        u8 bus;
>> +        u8 devfn;
>> +    } bus2bridge[MAX_BUSES];
>> +};
>> +
>>   struct pci_dev {
>>       struct list_head alldevs_list;
>>       struct list_head domain_list;
>> @@ -155,5 +169,9 @@ struct pirq;
>>   int msixtbl_pt_register(struct domain *, struct pirq *, uint64_t gtable);
>>   void msixtbl_pt_unregister(struct domain *, struct pirq *);
>>   void msixtbl_pt_cleanup(struct domain *d);
>> -
>> +struct pci_dev* pci_alloc_msix(struct pci_dev *pdev, struct pci_seg  *pseg,
>> +                                u8 bus, u8 devfn);
>> +int pci_clean_dpci_irqs(struct domain *d);
>> +void pci_cleanup_msi(struct pci_dev *pdev);
>> +int _dump_pci_devices(struct pci_seg *pseg, void *arg);
>>   #endif /* __XEN_PCI_H__ */
>> -- 
>> 1.7.9.5
>>

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH 1/2] xen/x86: Patch re-factors MSI/X config code from, drivers/passthrough/pci.c to x86 specific
  2015-04-13 10:34   ` Manish Jaggi
@ 2015-04-14  9:11     ` Jan Beulich
  0 siblings, 0 replies; 5+ messages in thread
From: Jan Beulich @ 2015-04-14  9:11 UTC (permalink / raw)
  To: Manish Jaggi
  Cc: Prasun.kapoor@cavium.com, Ian Campbell, Stefano Stabellini,
	Vijaya Kumar, Julien Grall, Xen Devel

>>> On 13.04.15 at 12:34, <mjaggi@caviumnetworks.com> wrote:
> On Monday 13 April 2015 03:45 PM, Stefano Stabellini wrote:
>> On Mon, 13 Apr 2015, Manish Jaggi wrote:
>>> @@ -282,22 +266,10 @@ static struct pci_dev *alloc_pdev(struct pci_seg *pseg,
>>> u8 bus, u8 devfn)
>>>       *((u8*) &pdev->bus) = bus;
>>>       *((u8*) &pdev->devfn) = devfn;
>>>       pdev->domain = NULL;
>>> -    INIT_LIST_HEAD(&pdev->msi_list);
>>> -
>>> -    if ( pci_find_cap_offset(pseg->nr, bus, PCI_SLOT(devfn),
>>> PCI_FUNC(devfn),
>>> -                             PCI_CAP_ID_MSIX) )
>>> +    if (!pci_alloc_msix (pdev, pseg, bus, devfn))
>>>       {
>>> -        struct arch_msix *msix = xzalloc(struct arch_msix);
>>> -
>>> -        if ( !msix )
>>> -        {
>>> -            xfree(pdev);
>>> -            return NULL;
>>> -        }
>>> -        spin_lock_init(&msix->table_lock);
>>> -        pdev->msix = msix;
>>> +        return NULL;
>>>       }
>>> -
>>  From the look of it, this code doesn't seem x86 specific
> MSIX is only used for x86, dom0/U handles MSI/X in ARM. I think If ARM 
> is not using MSI/X then code has to be in x86 specific file.

No, you need to take a more general perspective here: MSI and
MSI-X are integral parts of PCI, and hence if ARM _really_ chooses
to hand control of it to DomU-s, the code here shouldn't become
x86-specific, but non-ARM-specific.

Jan

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2015-04-14  9:11 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-04-13  7:40 [PATCH 1/2] xen/x86: Patch re-factors MSI/X config code from, drivers/passthrough/pci.c to x86 specific Manish Jaggi
2015-04-13 10:15 ` Stefano Stabellini
2015-04-13 10:34   ` Manish Jaggi
2015-04-14  9:11     ` Jan Beulich
2015-04-13 10:28 ` Julien Grall

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.