diff options
author | Gavin Shan <gwshan@linux.vnet.ibm.com> | 2015-06-29 10:44:21 +1000 |
---|---|---|
committer | Stewart Smith <stewart@linux.vnet.ibm.com> | 2015-07-03 07:23:49 +1000 |
commit | b2636472eef708006a017fa3858ac754968e6cc9 (patch) | |
tree | 38654f30ab2e4237ec92833e5a8c64cf0d247f2f /hw/phb3.c | |
parent | aa617925bb0e21550ec69b625cb9bd48f66655fb (diff) | |
download | talos-skiboot-b2636472eef708006a017fa3858ac754968e6cc9.tar.gz talos-skiboot-b2636472eef708006a017fa3858ac754968e6cc9.zip |
hw/phb3: Support config error injection to VF PE
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>
Signed-off-by: Stewart Smith <stewart@linux.vnet.ibm.com>
Diffstat (limited to 'hw/phb3.c')
-rw-r--r-- | hw/phb3.c | 45 |
1 files changed, 30 insertions, 15 deletions
@@ -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); } |