diff options
author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2017-06-06 08:59:18 +1000 |
---|---|---|
committer | Stewart Smith <stewart@linux.vnet.ibm.com> | 2017-06-06 20:49:05 +1000 |
commit | 97357c7d26793133e9e76eb954c505a4ffa16949 (patch) | |
tree | a9af492a948f4fe1633805da6878eb27b124b2f0 /hw/phb3.c | |
parent | acd94a9c7c589e36db013c026b5910d24af26bab (diff) | |
download | skiboot-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>
Diffstat (limited to 'hw/phb3.c')
-rw-r--r-- | hw/phb3.c | 34 |
1 files changed, 19 insertions, 15 deletions
@@ -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; \ } |