@@ -2891,25 +2891,42 @@ static int64_t phb3_err_inject_cfg(struct phb3 *p, uint32_t pe_no,
{
uint64_t a, m, prefer;
uint64_t ctrl = PHB_PAPR_ERR_INJ_CTL_CFG;
- int bus_no, bdfn;
+ int bdfn;
+ bool is_bus_pe;
a = 0xffffull;
prefer = 0xffffull;
+ m = PHB_PAPR_ERR_INJ_MASK_CFG_ALL;
for (bdfn = 0; bdfn < RTT_TABLE_ENTRIES; bdfn++) {
if (p->rte_cache[bdfn] != pe_no)
continue;
- /* Select minimal bus number as PE
- * primary bus number
- */
- bus_no = (bdfn >> 8);
- if (prefer == 0xffffull)
- prefer = SETFIELD(PHB_PAPR_ERR_INJ_MASK_CFG, 0x0ull, bus_no);
+ /* The PE can be associated with PCI bus or device */
+ is_bus_pe = false;
+ if ((bdfn + 8) < RTT_TABLE_ENTRIES &&
+ p->rte_cache[bdfn + 8] == pe_no)
+ is_bus_pe = true;
+
+ /* Figure out the PCI config address */
+ if (prefer == 0xffffull) {
+ if (is_bus_pe) {
+ m = PHB_PAPR_ERR_INJ_MASK_CFG;
+ prefer = SETFIELD(m, 0x0ull, (bdfn >> 8));
+ } else {
+ m = PHB_PAPR_ERR_INJ_MASK_CFG_ALL;
+ prefer = SETFIELD(m, 0x0ull, bdfn);
+ }
+ }
- /* Address should no greater than max bus
- * number within PE
- */
- if ((GETFIELD(PHB_PAPR_ERR_INJ_MASK_CFG, addr) == bus_no)) {
+ /* Check the input address is valid or not */
+ if (!is_bus_pe &&
+ GETFIELD(PHB_PAPR_ERR_INJ_MASK_CFG_ALL, addr) == bdfn) {
+ a = addr;
+ break;
+ }
+
+ if (is_bus_pe &&
+ GETFIELD(PHB_PAPR_ERR_INJ_MASK_CFG, addr) == (bdfn >> 8)) {
a = addr;
break;
}
@@ -2920,12 +2937,10 @@ static int64_t phb3_err_inject_cfg(struct phb3 *p, uint32_t pe_no,
return OPAL_PARAMETER;
/* Specified address is out of range */
- if (a == 0xffffull) {
+ if (a == 0xffffull)
a = prefer;
- m = PHB_PAPR_ERR_INJ_MASK_CFG;
- } else {
+ else
m = mask;
- }
return phb3_err_inject_finalize(p, a, m, ctrl, is_write);
}
@@ -123,6 +123,7 @@
#define PHB_PAPR_ERR_INJ_ADDR_MMIO PPC_BITMASK(16,63)
#define PHB_PAPR_ERR_INJ_MASK 0x2c0
#define PHB_PAPR_ERR_INJ_MASK_CFG PPC_BITMASK(4,11)
+#define PHB_PAPR_ERR_INJ_MASK_CFG_ALL PPC_BITMASK(4,19)
#define PHB_PAPR_ERR_INJ_MASK_MMIO PPC_BITMASK(16,63)
#define PHB_ETU_ERR_SUMMARY 0x2c8
Before the SRIOV is enabled, the only supported PE type is PCI bus dependent PE when doing error injection via PCI config space. That means the device/function number are ignored when writing to PAPR error injection address/mask registers (0x2b8 and 0x2c0) to inject PCI config access caused errors. If user intends to inject error to one VF, which is binding with individual PE, all VFs hooked to same PCI bus might receive errors wrongly. The patch fixes above issue by writing correct PCI config address to the registers according to the PE type: bus dependent or PCI device dependent PE. Signed-off-by: Gavin Shan <gwshan@linux.vnet.ibm.com> --- hw/phb3.c | 45 ++++++++++++++++++++++++++++++--------------- include/phb3-regs.h | 1 + 2 files changed, 31 insertions(+), 15 deletions(-)