All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH v2 0/5] pci/pcie: implement ARI enable bit correctly
@ 2011-01-27  6:56 Isaku Yamahata
  2011-01-27  6:56 ` [Qemu-devel] [PATCH v2 1/5] pci: replace the magic, 256, for the maximum of devfn Isaku Yamahata
                   ` (5 more replies)
  0 siblings, 6 replies; 13+ messages in thread
From: Isaku Yamahata @ 2011-01-27  6:56 UTC (permalink / raw)
  To: qemu-devel; +Cc: yamahata, mst

Changes v1 -> v2:
- dropped PCI_DEVFN_MAX
- use uint8_t for devfn instead of int
- move pcie_check_slot into pci.h and made it static inline
- minor clean ups

Isaku Yamahata (5):
  pci: replace the magic, 256, for the maximum of devfn
  pci: use devfn for pci_find_device() instead of (slot, fn) pair
  pci/pcie: make pci_find_device() ARI aware.
  pci: use PCI_SLOT in pci_get_bus_devfn()
  pci: use uint8_t for devfn_min

 hw/pci-hotplug.c   |    5 +++--
 hw/pci.c           |   18 ++++++++++++------
 hw/pci.h           |   51 +++++++++++++++++++++++++++++++++++++++++++++++----
 hw/pci_host.c      |    2 +-
 hw/pci_internals.h |    4 ++--
 hw/pcie.c          |   13 -------------
 hw/pcie.h          |    1 -
 hw/pcie_host.c     |    3 +--
 8 files changed, 66 insertions(+), 31 deletions(-)

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

* [Qemu-devel] [PATCH v2 1/5] pci: replace the magic, 256, for the maximum of devfn
  2011-01-27  6:56 [Qemu-devel] [PATCH v2 0/5] pci/pcie: implement ARI enable bit correctly Isaku Yamahata
@ 2011-01-27  6:56 ` Isaku Yamahata
  2011-01-27  7:09   ` [Qemu-devel] " Michael S. Tsirkin
  2011-01-27  6:56 ` [Qemu-devel] [PATCH v2 2/5] pci: use devfn for pci_find_device() instead of (slot, fn) pair Isaku Yamahata
                   ` (4 subsequent siblings)
  5 siblings, 1 reply; 13+ messages in thread
From: Isaku Yamahata @ 2011-01-27  6:56 UTC (permalink / raw)
  To: qemu-devel; +Cc: yamahata, mst

Introduce symbol PCI_DEVFN_MAX for the maximum of devfn
and replace the magic, 256.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 hw/pci.h           |    1 +
 hw/pci_internals.h |    2 +-
 2 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/hw/pci.h b/hw/pci.h
index 0d2753f..aa5f912 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -16,6 +16,7 @@
 #define PCI_DEVFN(slot, func)   ((((slot) & 0x1f) << 3) | ((func) & 0x07))
 #define PCI_SLOT(devfn)         (((devfn) >> 3) & 0x1f)
 #define PCI_FUNC(devfn)         ((devfn) & 0x07)
+#define PCI_SLOT_MAX            32
 #define PCI_FUNC_MAX            8
 
 /* Class, Vendor and Device IDs from Linux's pci_ids.h */
diff --git a/hw/pci_internals.h b/hw/pci_internals.h
index e3c93a3..efaefcd 100644
--- a/hw/pci_internals.h
+++ b/hw/pci_internals.h
@@ -22,7 +22,7 @@ struct PCIBus {
     pci_hotplug_fn hotplug;
     DeviceState *hotplug_qdev;
     void *irq_opaque;
-    PCIDevice *devices[256];
+    PCIDevice *devices[PCI_SLOT_MAX * PCI_FUNC_MAX];
     PCIDevice *parent_dev;
     target_phys_addr_t mem_base;
 
-- 
1.7.1.1

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

* [Qemu-devel] [PATCH v2 2/5] pci: use devfn for pci_find_device() instead of (slot, fn) pair
  2011-01-27  6:56 [Qemu-devel] [PATCH v2 0/5] pci/pcie: implement ARI enable bit correctly Isaku Yamahata
  2011-01-27  6:56 ` [Qemu-devel] [PATCH v2 1/5] pci: replace the magic, 256, for the maximum of devfn Isaku Yamahata
@ 2011-01-27  6:56 ` Isaku Yamahata
  2011-01-27  7:11   ` [Qemu-devel] " Michael S. Tsirkin
  2011-01-27  6:56 ` [Qemu-devel] [PATCH v2 3/5] pci/pcie: make pci_find_device() ARI aware Isaku Yamahata
                   ` (3 subsequent siblings)
  5 siblings, 1 reply; 13+ messages in thread
From: Isaku Yamahata @ 2011-01-27  6:56 UTC (permalink / raw)
  To: qemu-devel; +Cc: yamahata, mst

(slot, fn) pair is somewhat confusing because of ARI.
So use devfn for pci_find_device() instead of (slot, fn).

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 hw/pci-hotplug.c |    5 +++--
 hw/pci.c         |    4 ++--
 hw/pci.h         |    2 +-
 hw/pci_host.c    |    2 +-
 hw/pcie_host.c   |    3 +--
 5 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/hw/pci-hotplug.c b/hw/pci-hotplug.c
index 270a982..9715235 100644
--- a/hw/pci-hotplug.c
+++ b/hw/pci-hotplug.c
@@ -126,7 +126,8 @@ void drive_hot_add(Monitor *mon, const QDict *qdict)
         if (pci_read_devaddr(mon, pci_addr, &dom, &pci_bus, &slot)) {
             goto err;
         }
-        dev = pci_find_device(pci_find_root_bus(dom), pci_bus, slot, 0);
+        dev = pci_find_device(pci_find_root_bus(dom), pci_bus,
+                              PCI_DEVFN(slot, 0));
         if (!dev) {
             monitor_printf(mon, "no pci device with address %s\n", pci_addr);
             goto err;
@@ -276,7 +277,7 @@ static int pci_device_hot_remove(Monitor *mon, const char *pci_addr)
         return -1;
     }
 
-    d = pci_find_device(pci_find_root_bus(dom), bus, slot, 0);
+    d = pci_find_device(pci_find_root_bus(dom), bus, PCI_DEVFN(slot, 0));
     if (!d) {
         monitor_printf(mon, "slot %d empty\n", slot);
         return -1;
diff --git a/hw/pci.c b/hw/pci.c
index 9085680..899b23d 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -1602,14 +1602,14 @@ PCIBus *pci_find_bus(PCIBus *bus, int bus_num)
     return NULL;
 }
 
-PCIDevice *pci_find_device(PCIBus *bus, int bus_num, int slot, int function)
+PCIDevice *pci_find_device(PCIBus *bus, int bus_num, uint8_t devfn)
 {
     bus = pci_find_bus(bus, bus_num);
 
     if (!bus)
         return NULL;
 
-    return bus->devices[PCI_DEVFN(slot, function)];
+    return bus->devices[devfn];
 }
 
 static int pci_qdev_init(DeviceState *qdev, DeviceInfo *base)
diff --git a/hw/pci.h b/hw/pci.h
index aa5f912..72025b1 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -252,7 +252,7 @@ void pci_for_each_device(PCIBus *bus, int bus_num, void (*fn)(PCIBus *bus, PCIDe
 PCIBus *pci_find_root_bus(int domain);
 int pci_find_domain(const PCIBus *bus);
 PCIBus *pci_find_bus(PCIBus *bus, int bus_num);
-PCIDevice *pci_find_device(PCIBus *bus, int bus_num, int slot, int function);
+PCIDevice *pci_find_device(PCIBus *bus, int bus_num, uint8_t devfn);
 int pci_qdev_find_device(const char *id, PCIDevice **pdev);
 PCIBus *pci_get_bus_devfn(int *devfnp, const char *devaddr);
 
diff --git a/hw/pci_host.c b/hw/pci_host.c
index 7c40155..728e2d4 100644
--- a/hw/pci_host.c
+++ b/hw/pci_host.c
@@ -44,7 +44,7 @@ static inline PCIDevice *pci_dev_find_by_addr(PCIBus *bus, uint32_t addr)
     uint8_t bus_num = addr >> 16;
     uint8_t devfn = addr >> 8;
 
-    return pci_find_device(bus, bus_num, PCI_SLOT(devfn), PCI_FUNC(devfn));
+    return pci_find_device(bus, bus_num, devfn);
 }
 
 void pci_data_write(PCIBus *s, uint32_t addr, uint32_t val, int len)
diff --git a/hw/pcie_host.c b/hw/pcie_host.c
index 21069ee..b749865 100644
--- a/hw/pcie_host.c
+++ b/hw/pcie_host.c
@@ -49,8 +49,7 @@ static inline PCIDevice *pcie_dev_find_by_mmcfg_addr(PCIBus *s,
                                                      uint32_t mmcfg_addr)
 {
     return pci_find_device(s, PCIE_MMCFG_BUS(mmcfg_addr),
-                           PCI_SLOT(PCIE_MMCFG_DEVFN(mmcfg_addr)),
-                           PCI_FUNC(PCIE_MMCFG_DEVFN(mmcfg_addr)));
+                           PCIE_MMCFG_DEVFN(mmcfg_addr));
 }
 
 static void pcie_mmcfg_data_write(PCIBus *s,
-- 
1.7.1.1

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

* [Qemu-devel] [PATCH v2 3/5] pci/pcie: make pci_find_device() ARI aware.
  2011-01-27  6:56 [Qemu-devel] [PATCH v2 0/5] pci/pcie: implement ARI enable bit correctly Isaku Yamahata
  2011-01-27  6:56 ` [Qemu-devel] [PATCH v2 1/5] pci: replace the magic, 256, for the maximum of devfn Isaku Yamahata
  2011-01-27  6:56 ` [Qemu-devel] [PATCH v2 2/5] pci: use devfn for pci_find_device() instead of (slot, fn) pair Isaku Yamahata
@ 2011-01-27  6:56 ` Isaku Yamahata
  2011-01-27  7:30   ` [Qemu-devel] " Michael S. Tsirkin
  2011-01-27  6:56 ` [Qemu-devel] [PATCH v2 4/5] pci: use PCI_SLOT in pci_get_bus_devfn() Isaku Yamahata
                   ` (2 subsequent siblings)
  5 siblings, 1 reply; 13+ messages in thread
From: Isaku Yamahata @ 2011-01-27  6:56 UTC (permalink / raw)
  To: qemu-devel; +Cc: yamahata, mst

make pci_find_device() ARI aware.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 hw/pci.c  |    6 ++++++
 hw/pci.h  |   42 ++++++++++++++++++++++++++++++++++++++++++
 hw/pcie.c |   13 -------------
 hw/pcie.h |    1 -
 4 files changed, 48 insertions(+), 14 deletions(-)

diff --git a/hw/pci.c b/hw/pci.c
index 899b23d..471d4d7 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -1604,11 +1604,17 @@ PCIBus *pci_find_bus(PCIBus *bus, int bus_num)
 
 PCIDevice *pci_find_device(PCIBus *bus, int bus_num, uint8_t devfn)
 {
+    PCIDevice *d;
     bus = pci_find_bus(bus, bus_num);
 
     if (!bus)
         return NULL;
 
+    d = bus->parent_dev;
+    /* ARI: See the comment above the pcie_check_slot() for details */
+    if (d && !pcie_check_slot(d, devfn)) {
+        return NULL;
+    }
     return bus->devices[devfn];
 }
 
diff --git a/hw/pci.h b/hw/pci.h
index 72025b1..2266a47 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -467,4 +467,46 @@ static inline uint32_t pci_config_size(const PCIDevice *d)
     return pci_is_express(d) ? PCIE_CONFIG_SPACE_SIZE : PCI_CONFIG_SPACE_SIZE;
 }
 
+/*
+ * Although this function should be in pcie.h ideally,
+ * it is here because pci.h depends on pcie.h and this function depdnds
+ * on pci.h
+ *
+ * 6.13 Alternative routing-ID Interpretation(ARI)
+ * 7.8.16 Device control 2 register
+ *   ARI forwarding Enable
+ *
+ * With PCI Express Endpoints, there's a single device behind
+ * each downstream port bus, and bits 3:7 of the function number get
+ * encoded in the slot number (the Express spec calls it the Device
+ * Number). This allows > 8 functions, but
+ * these extended functions are only accessible when the
+ * Alternative routing-ID Interpretation (ARI)
+ * capability is enabled in the root/downstream port. With that capability
+ * disabled the port enforces the Device Number field being 0.
+ */
+static inline bool pcie_check_slot(const PCIDevice *dev, uint8_t devfn)
+{
+    uint8_t type;
+
+    if (!pci_is_express(dev)) {
+        return true;
+    }
+
+    type = pcie_cap_get_type(dev);
+    if (!(type == PCI_EXP_TYPE_ROOT_PORT ||
+          type == PCI_EXP_TYPE_DOWNSTREAM)) {
+        return true;
+    }
+
+    if (!PCI_SLOT(devfn)) {
+        /* With ARI, this means function < 8.
+           functions < 8 are always accesible. */
+        return true;
+    }
+
+    return pci_get_long(dev->config + dev->exp.exp_cap + PCI_EXP_DEVCTL2) &
+        PCI_EXP_DEVCTL2_ARI;
+}
+
 #endif
diff --git a/hw/pcie.c b/hw/pcie.c
index 6a113a9..006e2a8 100644
--- a/hw/pcie.c
+++ b/hw/pcie.c
@@ -424,19 +424,6 @@ void pcie_cap_ari_reset(PCIDevice *dev)
     pci_long_test_and_clear_mask(devctl2, PCI_EXP_DEVCTL2_ARI);
 }
 
-bool pcie_cap_is_ari_enabled(const PCIDevice *dev)
-{
-    if (!pci_is_express(dev)) {
-        return false;
-    }
-    if (!dev->exp.exp_cap) {
-        return false;
-    }
-
-    return pci_get_long(dev->config + dev->exp.exp_cap + PCI_EXP_DEVCTL2) &
-        PCI_EXP_DEVCTL2_ARI;
-}
-
 /**************************************************************************
  * pci express extended capability allocation functions
  * uint16_t ext_cap_id (16 bit)
diff --git a/hw/pcie.h b/hw/pcie.h
index bc909e2..ee3988f 100644
--- a/hw/pcie.h
+++ b/hw/pcie.h
@@ -119,7 +119,6 @@ void pcie_cap_flr_write_config(PCIDevice *dev,
 
 void pcie_cap_ari_init(PCIDevice *dev);
 void pcie_cap_ari_reset(PCIDevice *dev);
-bool pcie_cap_is_ari_enabled(const PCIDevice *dev);
 
 /* PCI express extended capability helper functions */
 uint16_t pcie_find_capability(PCIDevice *dev, uint16_t cap_id);
-- 
1.7.1.1

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

* [Qemu-devel] [PATCH v2 4/5] pci: use PCI_SLOT in pci_get_bus_devfn()
  2011-01-27  6:56 [Qemu-devel] [PATCH v2 0/5] pci/pcie: implement ARI enable bit correctly Isaku Yamahata
                   ` (2 preceding siblings ...)
  2011-01-27  6:56 ` [Qemu-devel] [PATCH v2 3/5] pci/pcie: make pci_find_device() ARI aware Isaku Yamahata
@ 2011-01-27  6:56 ` Isaku Yamahata
  2011-01-27  7:31   ` [Qemu-devel] " Michael S. Tsirkin
  2011-01-27  6:56 ` [Qemu-devel] [PATCH v2 5/5] pci: use uint8_t for devfn_min Isaku Yamahata
  2011-01-27  8:42 ` [Qemu-devel] Re: [PATCH v2 0/5] pci/pcie: implement ARI enable bit correctly Michael S. Tsirkin
  5 siblings, 1 reply; 13+ messages in thread
From: Isaku Yamahata @ 2011-01-27  6:56 UTC (permalink / raw)
  To: qemu-devel; +Cc: yamahata, mst

use PCI_SLOT in pci_get_bus_devfn().

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 hw/pci.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/hw/pci.c b/hw/pci.c
index 471d4d7..e25bf7a 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -558,7 +558,7 @@ PCIBus *pci_get_bus_devfn(int *devfnp, const char *devaddr)
         return NULL;
     }
 
-    *devfnp = slot << 3;
+    *devfnp = PCI_DEVFN(slot, 0);
     return pci_find_bus(pci_find_root_bus(dom), bus);
 }
 
-- 
1.7.1.1

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

* [Qemu-devel] [PATCH v2 5/5] pci: use uint8_t for devfn_min
  2011-01-27  6:56 [Qemu-devel] [PATCH v2 0/5] pci/pcie: implement ARI enable bit correctly Isaku Yamahata
                   ` (3 preceding siblings ...)
  2011-01-27  6:56 ` [Qemu-devel] [PATCH v2 4/5] pci: use PCI_SLOT in pci_get_bus_devfn() Isaku Yamahata
@ 2011-01-27  6:56 ` Isaku Yamahata
  2011-01-27  7:32   ` [Qemu-devel] " Michael S. Tsirkin
  2011-01-27  8:42 ` [Qemu-devel] Re: [PATCH v2 0/5] pci/pcie: implement ARI enable bit correctly Michael S. Tsirkin
  5 siblings, 1 reply; 13+ messages in thread
From: Isaku Yamahata @ 2011-01-27  6:56 UTC (permalink / raw)
  To: qemu-devel; +Cc: yamahata, mst

use uint8_t for devfn_min instead of int.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 hw/pci.c           |    6 +++---
 hw/pci.h           |    6 +++---
 hw/pci_internals.h |    2 +-
 3 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/hw/pci.c b/hw/pci.c
index e25bf7a..6725f50 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -256,7 +256,7 @@ int pci_find_domain(const PCIBus *bus)
 }
 
 void pci_bus_new_inplace(PCIBus *bus, DeviceState *parent,
-                         const char *name, int devfn_min)
+                         const char *name, uint8_t devfn_min)
 {
     qbus_create_inplace(&bus->qbus, &pci_bus_info, parent, name);
     assert(PCI_FUNC(devfn_min) == 0);
@@ -269,7 +269,7 @@ void pci_bus_new_inplace(PCIBus *bus, DeviceState *parent,
     vmstate_register(NULL, -1, &vmstate_pcibus, bus);
 }
 
-PCIBus *pci_bus_new(DeviceState *parent, const char *name, int devfn_min)
+PCIBus *pci_bus_new(DeviceState *parent, const char *name, uint8_t devfn_min)
 {
     PCIBus *bus;
 
@@ -303,7 +303,7 @@ void pci_bus_set_mem_base(PCIBus *bus, target_phys_addr_t base)
 
 PCIBus *pci_register_bus(DeviceState *parent, const char *name,
                          pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
-                         void *irq_opaque, int devfn_min, int nirq)
+                         void *irq_opaque, uint8_t devfn_min, int nirq)
 {
     PCIBus *bus;
 
diff --git a/hw/pci.h b/hw/pci.h
index 2266a47..2af709a 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -230,14 +230,14 @@ typedef enum {
 typedef int (*pci_hotplug_fn)(DeviceState *qdev, PCIDevice *pci_dev,
                               PCIHotplugState state);
 void pci_bus_new_inplace(PCIBus *bus, DeviceState *parent,
-                         const char *name, int devfn_min);
-PCIBus *pci_bus_new(DeviceState *parent, const char *name, int devfn_min);
+                         const char *name, uint8_t devfn_min);
+PCIBus *pci_bus_new(DeviceState *parent, const char *name, uint8_t devfn_min);
 void pci_bus_irqs(PCIBus *bus, pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
                   void *irq_opaque, int nirq);
 void pci_bus_hotplug(PCIBus *bus, pci_hotplug_fn hotplug, DeviceState *dev);
 PCIBus *pci_register_bus(DeviceState *parent, const char *name,
                          pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
-                         void *irq_opaque, int devfn_min, int nirq);
+                         void *irq_opaque, uint8_t devfn_min, int nirq);
 void pci_device_reset(PCIDevice *dev);
 void pci_bus_reset(PCIBus *bus);
 
diff --git a/hw/pci_internals.h b/hw/pci_internals.h
index efaefcd..fbe1866 100644
--- a/hw/pci_internals.h
+++ b/hw/pci_internals.h
@@ -16,7 +16,7 @@ extern struct BusInfo pci_bus_info;
 
 struct PCIBus {
     BusState qbus;
-    int devfn_min;
+    uint8_t devfn_min;
     pci_set_irq_fn set_irq;
     pci_map_irq_fn map_irq;
     pci_hotplug_fn hotplug;
-- 
1.7.1.1

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

* [Qemu-devel] Re: [PATCH v2 1/5] pci: replace the magic, 256, for the maximum of devfn
  2011-01-27  6:56 ` [Qemu-devel] [PATCH v2 1/5] pci: replace the magic, 256, for the maximum of devfn Isaku Yamahata
@ 2011-01-27  7:09   ` Michael S. Tsirkin
  0 siblings, 0 replies; 13+ messages in thread
From: Michael S. Tsirkin @ 2011-01-27  7:09 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: qemu-devel

On Thu, Jan 27, 2011 at 03:56:35PM +0900, Isaku Yamahata wrote:
> Introduce symbol PCI_DEVFN_MAX for the maximum of devfn
> and replace the magic, 256.
> 
> Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>

Applied, tweaked the comment.

> ---
>  hw/pci.h           |    1 +
>  hw/pci_internals.h |    2 +-
>  2 files changed, 2 insertions(+), 1 deletions(-)
> 
> diff --git a/hw/pci.h b/hw/pci.h
> index 0d2753f..aa5f912 100644
> --- a/hw/pci.h
> +++ b/hw/pci.h
> @@ -16,6 +16,7 @@
>  #define PCI_DEVFN(slot, func)   ((((slot) & 0x1f) << 3) | ((func) & 0x07))
>  #define PCI_SLOT(devfn)         (((devfn) >> 3) & 0x1f)
>  #define PCI_FUNC(devfn)         ((devfn) & 0x07)
> +#define PCI_SLOT_MAX            32
>  #define PCI_FUNC_MAX            8
>  
>  /* Class, Vendor and Device IDs from Linux's pci_ids.h */
> diff --git a/hw/pci_internals.h b/hw/pci_internals.h
> index e3c93a3..efaefcd 100644
> --- a/hw/pci_internals.h
> +++ b/hw/pci_internals.h
> @@ -22,7 +22,7 @@ struct PCIBus {
>      pci_hotplug_fn hotplug;
>      DeviceState *hotplug_qdev;
>      void *irq_opaque;
> -    PCIDevice *devices[256];
> +    PCIDevice *devices[PCI_SLOT_MAX * PCI_FUNC_MAX];
>      PCIDevice *parent_dev;
>      target_phys_addr_t mem_base;
>  
> -- 
> 1.7.1.1

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

* [Qemu-devel] Re: [PATCH v2 2/5] pci: use devfn for pci_find_device() instead of (slot, fn) pair
  2011-01-27  6:56 ` [Qemu-devel] [PATCH v2 2/5] pci: use devfn for pci_find_device() instead of (slot, fn) pair Isaku Yamahata
@ 2011-01-27  7:11   ` Michael S. Tsirkin
  0 siblings, 0 replies; 13+ messages in thread
From: Michael S. Tsirkin @ 2011-01-27  7:11 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: qemu-devel

On Thu, Jan 27, 2011 at 03:56:36PM +0900, Isaku Yamahata wrote:
> (slot, fn) pair is somewhat confusing because of ARI.
> So use devfn for pci_find_device() instead of (slot, fn).
> 
> Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>

Applied, thanks.

> ---
>  hw/pci-hotplug.c |    5 +++--
>  hw/pci.c         |    4 ++--
>  hw/pci.h         |    2 +-
>  hw/pci_host.c    |    2 +-
>  hw/pcie_host.c   |    3 +--
>  5 files changed, 8 insertions(+), 8 deletions(-)
> 
> diff --git a/hw/pci-hotplug.c b/hw/pci-hotplug.c
> index 270a982..9715235 100644
> --- a/hw/pci-hotplug.c
> +++ b/hw/pci-hotplug.c
> @@ -126,7 +126,8 @@ void drive_hot_add(Monitor *mon, const QDict *qdict)
>          if (pci_read_devaddr(mon, pci_addr, &dom, &pci_bus, &slot)) {
>              goto err;
>          }
> -        dev = pci_find_device(pci_find_root_bus(dom), pci_bus, slot, 0);
> +        dev = pci_find_device(pci_find_root_bus(dom), pci_bus,
> +                              PCI_DEVFN(slot, 0));
>          if (!dev) {
>              monitor_printf(mon, "no pci device with address %s\n", pci_addr);
>              goto err;
> @@ -276,7 +277,7 @@ static int pci_device_hot_remove(Monitor *mon, const char *pci_addr)
>          return -1;
>      }
>  
> -    d = pci_find_device(pci_find_root_bus(dom), bus, slot, 0);
> +    d = pci_find_device(pci_find_root_bus(dom), bus, PCI_DEVFN(slot, 0));
>      if (!d) {
>          monitor_printf(mon, "slot %d empty\n", slot);
>          return -1;
> diff --git a/hw/pci.c b/hw/pci.c
> index 9085680..899b23d 100644
> --- a/hw/pci.c
> +++ b/hw/pci.c
> @@ -1602,14 +1602,14 @@ PCIBus *pci_find_bus(PCIBus *bus, int bus_num)
>      return NULL;
>  }
>  
> -PCIDevice *pci_find_device(PCIBus *bus, int bus_num, int slot, int function)
> +PCIDevice *pci_find_device(PCIBus *bus, int bus_num, uint8_t devfn)
>  {
>      bus = pci_find_bus(bus, bus_num);
>  
>      if (!bus)
>          return NULL;
>  
> -    return bus->devices[PCI_DEVFN(slot, function)];
> +    return bus->devices[devfn];
>  }
>  
>  static int pci_qdev_init(DeviceState *qdev, DeviceInfo *base)
> diff --git a/hw/pci.h b/hw/pci.h
> index aa5f912..72025b1 100644
> --- a/hw/pci.h
> +++ b/hw/pci.h
> @@ -252,7 +252,7 @@ void pci_for_each_device(PCIBus *bus, int bus_num, void (*fn)(PCIBus *bus, PCIDe
>  PCIBus *pci_find_root_bus(int domain);
>  int pci_find_domain(const PCIBus *bus);
>  PCIBus *pci_find_bus(PCIBus *bus, int bus_num);
> -PCIDevice *pci_find_device(PCIBus *bus, int bus_num, int slot, int function);
> +PCIDevice *pci_find_device(PCIBus *bus, int bus_num, uint8_t devfn);
>  int pci_qdev_find_device(const char *id, PCIDevice **pdev);
>  PCIBus *pci_get_bus_devfn(int *devfnp, const char *devaddr);
>  
> diff --git a/hw/pci_host.c b/hw/pci_host.c
> index 7c40155..728e2d4 100644
> --- a/hw/pci_host.c
> +++ b/hw/pci_host.c
> @@ -44,7 +44,7 @@ static inline PCIDevice *pci_dev_find_by_addr(PCIBus *bus, uint32_t addr)
>      uint8_t bus_num = addr >> 16;
>      uint8_t devfn = addr >> 8;
>  
> -    return pci_find_device(bus, bus_num, PCI_SLOT(devfn), PCI_FUNC(devfn));
> +    return pci_find_device(bus, bus_num, devfn);
>  }
>  
>  void pci_data_write(PCIBus *s, uint32_t addr, uint32_t val, int len)
> diff --git a/hw/pcie_host.c b/hw/pcie_host.c
> index 21069ee..b749865 100644
> --- a/hw/pcie_host.c
> +++ b/hw/pcie_host.c
> @@ -49,8 +49,7 @@ static inline PCIDevice *pcie_dev_find_by_mmcfg_addr(PCIBus *s,
>                                                       uint32_t mmcfg_addr)
>  {
>      return pci_find_device(s, PCIE_MMCFG_BUS(mmcfg_addr),
> -                           PCI_SLOT(PCIE_MMCFG_DEVFN(mmcfg_addr)),
> -                           PCI_FUNC(PCIE_MMCFG_DEVFN(mmcfg_addr)));
> +                           PCIE_MMCFG_DEVFN(mmcfg_addr));
>  }
>  
>  static void pcie_mmcfg_data_write(PCIBus *s,
> -- 
> 1.7.1.1

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

* [Qemu-devel] Re: [PATCH v2 3/5] pci/pcie: make pci_find_device() ARI aware.
  2011-01-27  6:56 ` [Qemu-devel] [PATCH v2 3/5] pci/pcie: make pci_find_device() ARI aware Isaku Yamahata
@ 2011-01-27  7:30   ` Michael S. Tsirkin
  0 siblings, 0 replies; 13+ messages in thread
From: Michael S. Tsirkin @ 2011-01-27  7:30 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: qemu-devel

On Thu, Jan 27, 2011 at 03:56:37PM +0900, Isaku Yamahata wrote:
> make pci_find_device() ARI aware.
> 
> Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>

I moved the function to pci.c and renamed it to
pci_devfn_enabled (it does not deal with the slot anymore).

> ---
>  hw/pci.c  |    6 ++++++
>  hw/pci.h  |   42 ++++++++++++++++++++++++++++++++++++++++++
>  hw/pcie.c |   13 -------------
>  hw/pcie.h |    1 -
>  4 files changed, 48 insertions(+), 14 deletions(-)
> 
> diff --git a/hw/pci.c b/hw/pci.c
> index 899b23d..471d4d7 100644
> --- a/hw/pci.c
> +++ b/hw/pci.c
> @@ -1604,11 +1604,17 @@ PCIBus *pci_find_bus(PCIBus *bus, int bus_num)
>  
>  PCIDevice *pci_find_device(PCIBus *bus, int bus_num, uint8_t devfn)
>  {
> +    PCIDevice *d;
>      bus = pci_find_bus(bus, bus_num);
>  
>      if (!bus)
>          return NULL;
>  
> +    d = bus->parent_dev;
> +    /* ARI: See the comment above the pcie_check_slot() for details */
> +    if (d && !pcie_check_slot(d, devfn)) {
> +        return NULL;
> +    }
>      return bus->devices[devfn];
>  }
>  
> diff --git a/hw/pci.h b/hw/pci.h
> index 72025b1..2266a47 100644
> --- a/hw/pci.h
> +++ b/hw/pci.h
> @@ -467,4 +467,46 @@ static inline uint32_t pci_config_size(const PCIDevice *d)
>      return pci_is_express(d) ? PCIE_CONFIG_SPACE_SIZE : PCI_CONFIG_SPACE_SIZE;
>  }
>  
> +/*
> + * Although this function should be in pcie.h ideally,
> + * it is here because pci.h depends on pcie.h and this function depdnds
> + * on pci.h
> + *
> + * 6.13 Alternative routing-ID Interpretation(ARI)
> + * 7.8.16 Device control 2 register
> + *   ARI forwarding Enable
> + *
> + * With PCI Express Endpoints, there's a single device behind
> + * each downstream port bus, and bits 3:7 of the function number get
> + * encoded in the slot number (the Express spec calls it the Device
> + * Number). This allows > 8 functions, but
> + * these extended functions are only accessible when the
> + * Alternative routing-ID Interpretation (ARI)
> + * capability is enabled in the root/downstream port. With that capability
> + * disabled the port enforces the Device Number field being 0.
> + */
> +static inline bool pcie_check_slot(const PCIDevice *dev, uint8_t devfn)
> +{
> +    uint8_t type;
> +
> +    if (!pci_is_express(dev)) {
> +        return true;
> +    }
> +
> +    type = pcie_cap_get_type(dev);
> +    if (!(type == PCI_EXP_TYPE_ROOT_PORT ||
> +          type == PCI_EXP_TYPE_DOWNSTREAM)) {
> +        return true;
> +    }
> +
> +    if (!PCI_SLOT(devfn)) {
> +        /* With ARI, this means function < 8.
> +           functions < 8 are always accesible. */
> +        return true;
> +    }
> +
> +    return pci_get_long(dev->config + dev->exp.exp_cap + PCI_EXP_DEVCTL2) &
> +        PCI_EXP_DEVCTL2_ARI;
> +}
> +
>  #endif
> diff --git a/hw/pcie.c b/hw/pcie.c
> index 6a113a9..006e2a8 100644
> --- a/hw/pcie.c
> +++ b/hw/pcie.c
> @@ -424,19 +424,6 @@ void pcie_cap_ari_reset(PCIDevice *dev)
>      pci_long_test_and_clear_mask(devctl2, PCI_EXP_DEVCTL2_ARI);
>  }
>  
> -bool pcie_cap_is_ari_enabled(const PCIDevice *dev)
> -{
> -    if (!pci_is_express(dev)) {
> -        return false;
> -    }
> -    if (!dev->exp.exp_cap) {
> -        return false;
> -    }
> -
> -    return pci_get_long(dev->config + dev->exp.exp_cap + PCI_EXP_DEVCTL2) &
> -        PCI_EXP_DEVCTL2_ARI;
> -}
> -
>  /**************************************************************************
>   * pci express extended capability allocation functions
>   * uint16_t ext_cap_id (16 bit)
> diff --git a/hw/pcie.h b/hw/pcie.h
> index bc909e2..ee3988f 100644
> --- a/hw/pcie.h
> +++ b/hw/pcie.h
> @@ -119,7 +119,6 @@ void pcie_cap_flr_write_config(PCIDevice *dev,
>  
>  void pcie_cap_ari_init(PCIDevice *dev);
>  void pcie_cap_ari_reset(PCIDevice *dev);
> -bool pcie_cap_is_ari_enabled(const PCIDevice *dev);
>  
>  /* PCI express extended capability helper functions */
>  uint16_t pcie_find_capability(PCIDevice *dev, uint16_t cap_id);
> -- 
> 1.7.1.1

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

* [Qemu-devel] Re: [PATCH v2 4/5] pci: use PCI_SLOT in pci_get_bus_devfn()
  2011-01-27  6:56 ` [Qemu-devel] [PATCH v2 4/5] pci: use PCI_SLOT in pci_get_bus_devfn() Isaku Yamahata
@ 2011-01-27  7:31   ` Michael S. Tsirkin
  0 siblings, 0 replies; 13+ messages in thread
From: Michael S. Tsirkin @ 2011-01-27  7:31 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: qemu-devel

On Thu, Jan 27, 2011 at 03:56:38PM +0900, Isaku Yamahata wrote:
> use PCI_SLOT in pci_get_bus_devfn().
> 
> Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>

Tweaked the comment and applied.

> ---
>  hw/pci.c |    2 +-
>  1 files changed, 1 insertions(+), 1 deletions(-)
> 
> diff --git a/hw/pci.c b/hw/pci.c
> index 471d4d7..e25bf7a 100644
> --- a/hw/pci.c
> +++ b/hw/pci.c
> @@ -558,7 +558,7 @@ PCIBus *pci_get_bus_devfn(int *devfnp, const char *devaddr)
>          return NULL;
>      }
>  
> -    *devfnp = slot << 3;
> +    *devfnp = PCI_DEVFN(slot, 0);
>      return pci_find_bus(pci_find_root_bus(dom), bus);
>  }
>  
> -- 
> 1.7.1.1

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

* [Qemu-devel] Re: [PATCH v2 5/5] pci: use uint8_t for devfn_min
  2011-01-27  6:56 ` [Qemu-devel] [PATCH v2 5/5] pci: use uint8_t for devfn_min Isaku Yamahata
@ 2011-01-27  7:32   ` Michael S. Tsirkin
  0 siblings, 0 replies; 13+ messages in thread
From: Michael S. Tsirkin @ 2011-01-27  7:32 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: qemu-devel

On Thu, Jan 27, 2011 at 03:56:39PM +0900, Isaku Yamahata wrote:
> use uint8_t for devfn_min instead of int.
> 
> Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>

Applied, thanks.

> ---
>  hw/pci.c           |    6 +++---
>  hw/pci.h           |    6 +++---
>  hw/pci_internals.h |    2 +-
>  3 files changed, 7 insertions(+), 7 deletions(-)
> 
> diff --git a/hw/pci.c b/hw/pci.c
> index e25bf7a..6725f50 100644
> --- a/hw/pci.c
> +++ b/hw/pci.c
> @@ -256,7 +256,7 @@ int pci_find_domain(const PCIBus *bus)
>  }
>  
>  void pci_bus_new_inplace(PCIBus *bus, DeviceState *parent,
> -                         const char *name, int devfn_min)
> +                         const char *name, uint8_t devfn_min)
>  {
>      qbus_create_inplace(&bus->qbus, &pci_bus_info, parent, name);
>      assert(PCI_FUNC(devfn_min) == 0);
> @@ -269,7 +269,7 @@ void pci_bus_new_inplace(PCIBus *bus, DeviceState *parent,
>      vmstate_register(NULL, -1, &vmstate_pcibus, bus);
>  }
>  
> -PCIBus *pci_bus_new(DeviceState *parent, const char *name, int devfn_min)
> +PCIBus *pci_bus_new(DeviceState *parent, const char *name, uint8_t devfn_min)
>  {
>      PCIBus *bus;
>  
> @@ -303,7 +303,7 @@ void pci_bus_set_mem_base(PCIBus *bus, target_phys_addr_t base)
>  
>  PCIBus *pci_register_bus(DeviceState *parent, const char *name,
>                           pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
> -                         void *irq_opaque, int devfn_min, int nirq)
> +                         void *irq_opaque, uint8_t devfn_min, int nirq)
>  {
>      PCIBus *bus;
>  
> diff --git a/hw/pci.h b/hw/pci.h
> index 2266a47..2af709a 100644
> --- a/hw/pci.h
> +++ b/hw/pci.h
> @@ -230,14 +230,14 @@ typedef enum {
>  typedef int (*pci_hotplug_fn)(DeviceState *qdev, PCIDevice *pci_dev,
>                                PCIHotplugState state);
>  void pci_bus_new_inplace(PCIBus *bus, DeviceState *parent,
> -                         const char *name, int devfn_min);
> -PCIBus *pci_bus_new(DeviceState *parent, const char *name, int devfn_min);
> +                         const char *name, uint8_t devfn_min);
> +PCIBus *pci_bus_new(DeviceState *parent, const char *name, uint8_t devfn_min);
>  void pci_bus_irqs(PCIBus *bus, pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
>                    void *irq_opaque, int nirq);
>  void pci_bus_hotplug(PCIBus *bus, pci_hotplug_fn hotplug, DeviceState *dev);
>  PCIBus *pci_register_bus(DeviceState *parent, const char *name,
>                           pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
> -                         void *irq_opaque, int devfn_min, int nirq);
> +                         void *irq_opaque, uint8_t devfn_min, int nirq);
>  void pci_device_reset(PCIDevice *dev);
>  void pci_bus_reset(PCIBus *bus);
>  
> diff --git a/hw/pci_internals.h b/hw/pci_internals.h
> index efaefcd..fbe1866 100644
> --- a/hw/pci_internals.h
> +++ b/hw/pci_internals.h
> @@ -16,7 +16,7 @@ extern struct BusInfo pci_bus_info;
>  
>  struct PCIBus {
>      BusState qbus;
> -    int devfn_min;
> +    uint8_t devfn_min;
>      pci_set_irq_fn set_irq;
>      pci_map_irq_fn map_irq;
>      pci_hotplug_fn hotplug;
> -- 
> 1.7.1.1

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

* [Qemu-devel] Re: [PATCH v2 0/5] pci/pcie: implement ARI enable bit correctly
  2011-01-27  6:56 [Qemu-devel] [PATCH v2 0/5] pci/pcie: implement ARI enable bit correctly Isaku Yamahata
                   ` (4 preceding siblings ...)
  2011-01-27  6:56 ` [Qemu-devel] [PATCH v2 5/5] pci: use uint8_t for devfn_min Isaku Yamahata
@ 2011-01-27  8:42 ` Michael S. Tsirkin
  2011-01-27 10:22   ` Isaku Yamahata
  5 siblings, 1 reply; 13+ messages in thread
From: Michael S. Tsirkin @ 2011-01-27  8:42 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: qemu-devel

On Thu, Jan 27, 2011 at 03:56:34PM +0900, Isaku Yamahata wrote:
> Changes v1 -> v2:
> - dropped PCI_DEVFN_MAX
> - use uint8_t for devfn instead of int
> - move pcie_check_slot into pci.h and made it static inline
> - minor clean ups

So I put this on the pci branch but
we need to at least consider the following:
- command line/monitor/qmp: do we need to tweak it to force slot 0?
  Or just declare that slot >= 1 should be used to support
  insane # of functions?
- management needs to learn about ARI anyway, so
  maybe a clean change is better?
- multifunction: need to detect and support ARI:
  see pci_init_multifunction.
- And, we still did not implement the idea
  where parent id for the device is specified.

So while I don't think these patches make anything
worse, I think I'll give these a bit of time to stew
on my branch so we can hopefully see a bit more of the
full picture.

> Isaku Yamahata (5):
>   pci: replace the magic, 256, for the maximum of devfn
>   pci: use devfn for pci_find_device() instead of (slot, fn) pair
>   pci/pcie: make pci_find_device() ARI aware.
>   pci: use PCI_SLOT in pci_get_bus_devfn()
>   pci: use uint8_t for devfn_min
> 
>  hw/pci-hotplug.c   |    5 +++--
>  hw/pci.c           |   18 ++++++++++++------
>  hw/pci.h           |   51 +++++++++++++++++++++++++++++++++++++++++++++++----
>  hw/pci_host.c      |    2 +-
>  hw/pci_internals.h |    4 ++--
>  hw/pcie.c          |   13 -------------
>  hw/pcie.h          |    1 -
>  hw/pcie_host.c     |    3 +--
>  8 files changed, 66 insertions(+), 31 deletions(-)

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

* [Qemu-devel] Re: [PATCH v2 0/5] pci/pcie: implement ARI enable bit correctly
  2011-01-27  8:42 ` [Qemu-devel] Re: [PATCH v2 0/5] pci/pcie: implement ARI enable bit correctly Michael S. Tsirkin
@ 2011-01-27 10:22   ` Isaku Yamahata
  0 siblings, 0 replies; 13+ messages in thread
From: Isaku Yamahata @ 2011-01-27 10:22 UTC (permalink / raw)
  To: Michael S. Tsirkin; +Cc: qemu-devel

On Thu, Jan 27, 2011 at 10:42:53AM +0200, Michael S. Tsirkin wrote:
> On Thu, Jan 27, 2011 at 03:56:34PM +0900, Isaku Yamahata wrote:
> > Changes v1 -> v2:
> > - dropped PCI_DEVFN_MAX
> > - use uint8_t for devfn instead of int
> > - move pcie_check_slot into pci.h and made it static inline
> > - minor clean ups
> 
> So I put this on the pci branch but

Thank you.


> we need to at least consider the following:

Yes, there are several issues to consider.
What I have in mind at the moment for the first step is
to directly assign a physical pcie ARI device to a guest as a while.


> - command line/monitor/qmp: do we need to tweak it to force slot 0?
>   Or just declare that slot >= 1 should be used to support
>   insane # of functions?

So far I've thought of slot >= 1 way.
But I'm not sure it's good or not. Anyway we will see.


> - management needs to learn about ARI anyway, so
>   maybe a clean change is better?
> - multifunction: need to detect and support ARI:
>   see pci_init_multifunction.
> - And, we still did not implement the idea
>   where parent id for the device is specified.

Parent id is definitely necessary for pcie hot plug too.

thanks,

> So while I don't think these patches make anything
> worse, I think I'll give these a bit of time to stew
> on my branch so we can hopefully see a bit more of the
> full picture.
> 
> > Isaku Yamahata (5):
> >   pci: replace the magic, 256, for the maximum of devfn
> >   pci: use devfn for pci_find_device() instead of (slot, fn) pair
> >   pci/pcie: make pci_find_device() ARI aware.
> >   pci: use PCI_SLOT in pci_get_bus_devfn()
> >   pci: use uint8_t for devfn_min
> > 
> >  hw/pci-hotplug.c   |    5 +++--
> >  hw/pci.c           |   18 ++++++++++++------
> >  hw/pci.h           |   51 +++++++++++++++++++++++++++++++++++++++++++++++----
> >  hw/pci_host.c      |    2 +-
> >  hw/pci_internals.h |    4 ++--
> >  hw/pcie.c          |   13 -------------
> >  hw/pcie.h          |    1 -
> >  hw/pcie_host.c     |    3 +--
> >  8 files changed, 66 insertions(+), 31 deletions(-)
> 

-- 
yamahata

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

end of thread, other threads:[~2011-01-27 10:23 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-01-27  6:56 [Qemu-devel] [PATCH v2 0/5] pci/pcie: implement ARI enable bit correctly Isaku Yamahata
2011-01-27  6:56 ` [Qemu-devel] [PATCH v2 1/5] pci: replace the magic, 256, for the maximum of devfn Isaku Yamahata
2011-01-27  7:09   ` [Qemu-devel] " Michael S. Tsirkin
2011-01-27  6:56 ` [Qemu-devel] [PATCH v2 2/5] pci: use devfn for pci_find_device() instead of (slot, fn) pair Isaku Yamahata
2011-01-27  7:11   ` [Qemu-devel] " Michael S. Tsirkin
2011-01-27  6:56 ` [Qemu-devel] [PATCH v2 3/5] pci/pcie: make pci_find_device() ARI aware Isaku Yamahata
2011-01-27  7:30   ` [Qemu-devel] " Michael S. Tsirkin
2011-01-27  6:56 ` [Qemu-devel] [PATCH v2 4/5] pci: use PCI_SLOT in pci_get_bus_devfn() Isaku Yamahata
2011-01-27  7:31   ` [Qemu-devel] " Michael S. Tsirkin
2011-01-27  6:56 ` [Qemu-devel] [PATCH v2 5/5] pci: use uint8_t for devfn_min Isaku Yamahata
2011-01-27  7:32   ` [Qemu-devel] " Michael S. Tsirkin
2011-01-27  8:42 ` [Qemu-devel] Re: [PATCH v2 0/5] pci/pcie: implement ARI enable bit correctly Michael S. Tsirkin
2011-01-27 10:22   ` Isaku Yamahata

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.