[Skiboot] [PATCH] core/pci: Introduce virtual device and filter cache

Gavin Shan gwshan at linux.vnet.ibm.com
Thu Sep 8 17:19:32 AEST 2016


This introduces virtual device and filter cache to speed up the
searching for PCI virtual device and config space register filter
in PCI config access path. With this applied, the original bandwidth
is regained during the NPU1 bandwidth testing.

Original bandwidth before PCI virtual device patchset is applied:

garrison# pwd
/home/alistair/NVIDIA_CUDA-7.5_Samples/1_Utilities/bandwidthTest
garrison# ./bandwidthTest --memory=pinned
    :
 Host to Device Bandwidth, 1 Device(s)
 PINNED Memory Transfers
   Transfer Size (Bytes)	Bandwidth(MB/s)
   33554432			33205.6

With PCI virtual device patchset and this one is applied:

 Host to Device Bandwidth, 1 Device(s)
 PINNED Memory Transfers
   Transfer Size (Bytes)	Bandwidth(MB/s)
   33554432			33080.0

Signed-off-by: Gavin Shan <gwshan at linux.vnet.ibm.com>
---
 core/pci-virt.c    | 23 +++++++++++++++++++++--
 include/pci-virt.h |  1 +
 include/pci.h      |  1 +
 3 files changed, 23 insertions(+), 2 deletions(-)

diff --git a/core/pci-virt.c b/core/pci-virt.c
index b531470..663225a 100644
--- a/core/pci-virt.c
+++ b/core/pci-virt.c
@@ -55,6 +55,12 @@ static struct pci_cfg_reg_filter *pci_virt_find_filter(
 	if (!pvd || !len || start >= pvd->cfg_size)
 		return NULL;
 
+	/* Check the cache first */
+	pcrf = pvd->cached_pcrf;
+	if (pcrf && start < (pcrf->start + pcrf->len) &&
+	    (start + len) > pcrf->start)
+		return pcrf;
+
 	/* Return filter if there is overlapped region. We don't
 	 * require strict matching for more flexibility. It also
 	 * means the associated handler should validate the register
@@ -62,8 +68,12 @@ static struct pci_cfg_reg_filter *pci_virt_find_filter(
 	 */
 	list_for_each(&pvd->pcrf, pcrf, link) {
 		if (start < (pcrf->start + pcrf->len) &&
-		    (start + len) > pcrf->start)
+		    (start + len) > pcrf->start) {
+			/* Update the cache */
+			pvd->cached_pcrf = pcrf;
+
 			return pcrf;
+		}
 	}
 
 	return NULL;
@@ -111,9 +121,18 @@ struct pci_virt_device *pci_virt_find_device(struct phb *phb,
 {
 	struct pci_virt_device *pvd;
 
+	/* Check the cached virtual device firstly */
+	pvd = phb->cached_pvd;
+	if (pvd && pvd->bdfn == bdfn)
+		return pvd;
+
 	list_for_each(&phb->virt_devices, pvd, node) {
-		if (pvd->bdfn == bdfn)
+		if (pvd->bdfn == bdfn) {
+			/* Update the cache */
+			phb->cached_pvd = pvd;
+
 			return pvd;
+		}
 	}
 
 	return NULL;
diff --git a/include/pci-virt.h b/include/pci-virt.h
index 7c787cf..d1427bc 100644
--- a/include/pci-virt.h
+++ b/include/pci-virt.h
@@ -30,6 +30,7 @@ struct pci_virt_device {
 	uint32_t		bdfn;
 	uint32_t		cfg_size;
 	uint8_t			*config[PCI_VIRT_CFG_MAX];
+	struct pci_cfg_reg_filter	*cached_pcrf;
 	struct list_head	pcrf;
 	struct list_node	node;
 	void			*data;
diff --git a/include/pci.h b/include/pci.h
index 92e3dce..c326a88 100644
--- a/include/pci.h
+++ b/include/pci.h
@@ -324,6 +324,7 @@ struct phb {
 	enum phb_type		phb_type;
 	struct lock		lock;
 	struct list_head	devices;
+	struct pci_virt_device	*cached_pvd;
 	struct list_head	virt_devices;
 	const struct phb_ops	*ops;
 	struct pci_lsi_state	lstate;
-- 
2.1.0



More information about the Skiboot mailing list