aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2017-06-06 08:59:18 +1000
committerStewart Smith <stewart@linux.vnet.ibm.com>2017-06-06 20:49:05 +1000
commit97357c7d26793133e9e76eb954c505a4ffa16949 (patch)
treea9af492a948f4fe1633805da6878eb27b124b2f0
parentacd94a9c7c589e36db013c026b5910d24af26bab (diff)
downloadskiboot-97357c7d26793133e9e76eb954c505a4ffa16949.zip
skiboot-97357c7d26793133e9e76eb954c505a4ffa16949.tar.gz
skiboot-97357c7d26793133e9e76eb954c505a4ffa16949.tar.bz2
phb3+iov: Fixup support for config space filters
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@kernel.crashing.org> Signed-off-by: Stewart Smith <stewart@linux.vnet.ibm.com>
-rw-r--r--core/pci-iov.c11
-rw-r--r--hw/phb3.c34
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; \
}