[Skiboot] [PATCH 2/8] phb3+iov: Fixup support for config space filters

Benjamin Herrenschmidt benh at kernel.crashing.org
Tue Jun 6 08:59:18 AEST 2017


The filter should be called before the HW access and its
return value control whether to perform the access or not

Also fix the pci-iov.c return values to match accordingly
otherwise this breaks SR-IOV

Signed-off-by: Benjamin Herrenschmidt <benh at kernel.crashing.org>
---
 core/pci-iov.c | 11 +++++------
 hw/phb3.c      | 34 +++++++++++++++++++---------------
 2 files changed, 24 insertions(+), 21 deletions(-)

diff --git a/core/pci-iov.c b/core/pci-iov.c
index 6abb85a..9d75b37 100644
--- a/core/pci-iov.c
+++ b/core/pci-iov.c
@@ -33,9 +33,8 @@ static int64_t pci_iov_vf_devctl(void *dev, struct pci_cfg_reg_filter *pcrf,
 	uint32_t pos = pci_cap(vf, PCI_CFG_CAP_ID_EXP, false);
 	uint8_t *pcache;
 
-	if (offset != pcrf->start ||
-	    offset != (pos + PCICAP_EXP_DEVCTL))
-		return OPAL_SUCCESS;
+	if (offset != (pos + PCICAP_EXP_DEVCTL))
+		return OPAL_PARTIAL;
 
 	pcache = &pcrf->data[0];
 	if (write) {
@@ -130,13 +129,13 @@ static int64_t pci_iov_change(void *dev __unused,
 	/* Update SRIOV variable parameters */
 	changed = pci_iov_update_parameters(iov);
 	if (!changed)
-		return OPAL_SUCCESS;
+		return OPAL_PARTIAL;
 
 	/* Remove all VFs that have been attached to the parent */
 	if (!iov->enabled) {
 		list_for_each_safe(&pd->children, vf, tmp, link)
 			list_del(&vf->link);
-		return OPAL_SUCCESS;
+		return OPAL_PARTIAL;
 	}
 
 	/* Initialize the VFs and attach them to parent */
@@ -165,7 +164,7 @@ static int64_t pci_iov_change(void *dev __unused,
 			phb->ops->device_init(phb, pd, NULL);
 	}
 
-	return OPAL_SUCCESS;
+	return OPAL_PARTIAL;
 }
 
 /*
diff --git a/hw/phb3.c b/hw/phb3.c
index c99f1de..f32142e 100644
--- a/hw/phb3.c
+++ b/hw/phb3.c
@@ -216,9 +216,9 @@ static void phb3_link_update(struct phb *phb, uint16_t data)
 	}
 }
 
-static void phb3_pcicfg_filter(struct phb *phb, uint32_t bdfn,
-			       uint32_t offset, uint32_t len,
-			       uint32_t *data, bool write)
+static int64_t phb3_pcicfg_filter(struct phb *phb, uint32_t bdfn,
+				  uint32_t offset, uint32_t len,
+				  uint32_t *data, bool write)
 {
 	struct pci_device *pd;
 	struct pci_cfg_reg_filter *pcrf;
@@ -229,25 +229,25 @@ static void phb3_pcicfg_filter(struct phb *phb, uint32_t bdfn,
 	 */
 	if (bdfn == 0 && write && len == 4 && offset == 0x58) {
 		phb3_link_update(phb, (*data) >> 16);
-		return;
+		return OPAL_SUCCESS;
 	}
 	if (bdfn == 0 && write && len == 2 && offset == 0x5a) {
 		phb3_link_update(phb, *(uint16_t *)data);
-		return;
+		return OPAL_SUCCESS;
 	}
 
 	if (!pci_device_has_cfg_reg_filters(phb, bdfn))
-		return;
+		return OPAL_PARTIAL;
 	pd = pci_find_dev(phb, bdfn);
 	pcrf = pd ? pci_find_cfg_reg_filter(pd, offset, len) : NULL;
 	if (!pcrf || !pcrf->func)
-		return;
+		return OPAL_PARTIAL;
 
 	flags = write ? PCI_REG_FLAG_WRITE : PCI_REG_FLAG_READ;
 	if ((pcrf->flags & flags) != flags)
-		return;
+		return OPAL_PARTIAL;
 
-	pcrf->func(pd, pcrf, offset, len, data, write);
+	return pcrf->func(pd, pcrf, offset, len, data, write);
 }
 
 #define PHB3_PCI_CFG_READ(size, type)	\
@@ -275,6 +275,11 @@ static int64_t phb3_pcicfg_read##size(struct phb *phb, uint32_t bdfn,	\
 		return OPAL_HARDWARE;					\
 	}								\
 									\
+	rc = phb3_pcicfg_filter(phb, bdfn, offset, sizeof(type),	\
+			   (uint32_t *)data, false);			\
+	if (rc != OPAL_PARTIAL)						\
+		return rc;						\
+									\
 	addr = PHB_CA_ENABLE;						\
 	addr = SETFIELD(PHB_CA_BDFN, addr, bdfn);			\
 	addr = SETFIELD(PHB_CA_REG, addr, offset);			\
@@ -290,9 +295,6 @@ static int64_t phb3_pcicfg_read##size(struct phb *phb, uint32_t bdfn,	\
 				    (offset & (4 - sizeof(type))));	\
 	}								\
 									\
-	phb3_pcicfg_filter(phb, bdfn, offset, sizeof(type),		\
-			   (uint32_t *)data, false);			\
-									\
 	return OPAL_SUCCESS;						\
 }
 
@@ -318,6 +320,11 @@ static int64_t phb3_pcicfg_write##size(struct phb *phb, uint32_t bdfn,	\
 		return OPAL_HARDWARE;					\
 	}								\
 									\
+	rc = phb3_pcicfg_filter(phb, bdfn, offset, sizeof(type),	\
+			   (uint32_t *)&data, true);			\
+	if (rc != OPAL_PARTIAL)						\
+		return rc;						\
+									\
 	addr = PHB_CA_ENABLE;						\
 	addr = SETFIELD(PHB_CA_BDFN, addr, bdfn);			\
 	addr = SETFIELD(PHB_CA_REG, addr, offset);			\
@@ -334,9 +341,6 @@ static int64_t phb3_pcicfg_write##size(struct phb *phb, uint32_t bdfn,	\
 			     (offset & (4 - sizeof(type))), data);	\
 	}								\
 									\
-	phb3_pcicfg_filter(phb, bdfn, offset, sizeof(type),             \
-			   (uint32_t *)&data, true);			\
-									\
         return OPAL_SUCCESS;						\
 }
 
-- 
2.9.4



More information about the Skiboot mailing list