aboutsummaryrefslogtreecommitdiff
path: root/hw/phb3.c
diff options
context:
space:
mode:
authorGavin Shan <gwshan@linux.vnet.ibm.com>2014-10-02 16:30:12 +1000
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2014-10-08 14:07:46 +1100
commit666ee3d06824400eff61c30d7722ea60d673fe8c (patch)
tree29b9cabdea0858ffad3d1b7f268382969649a177 /hw/phb3.c
parent4bb318eeeb67d40071020de87dedbf5a04538b48 (diff)
downloadskiboot-666ee3d06824400eff61c30d7722ea60d673fe8c.zip
skiboot-666ee3d06824400eff61c30d7722ea60d673fe8c.tar.gz
skiboot-666ee3d06824400eff61c30d7722ea60d673fe8c.tar.bz2
PHB3: Support multiple MM32 segments for error injection
When doing error injection to 32-bits MMIO range, fixed length 8MB is used. That's incorrect as one PE might span multile segments. Also the 32-bits MMIO segment size isn't 8MB necessarily. The patch fixes the issue to cover all (contiguous) 32-bits MMIO segments assigned to the specified PE. Also, it fixes the 48 bits of 50 bits AIB address, instead of all bits used for comparison. BZ: 115222 Signed-off-by: Gavin Shan <gwshan@linux.vnet.ibm.com> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'hw/phb3.c')
-rw-r--r--hw/phb3.c43
1 files changed, 26 insertions, 17 deletions
diff --git a/hw/phb3.c b/hw/phb3.c
index 2623d5a..b8019ac 100644
--- a/hw/phb3.c
+++ b/hw/phb3.c
@@ -2613,44 +2613,53 @@ static int64_t phb3_err_inject_mem32(struct phb3 *p, uint32_t pe_no,
uint64_t addr, uint64_t mask,
bool is_write)
{
- uint64_t a, m, prefer, base;
+ uint64_t base, len, segstart, segsize;
+ uint64_t a, m;
uint64_t ctrl = PHB_PAPR_ERR_INJ_CTL_OUTB;
- int index;
+ uint32_t index;
+
+ segsize = (M32_PCI_SIZE / PHB3_MAX_PE_NUM);
+ a = base = len = 0x0ull;
- a = 0x0ull;
- prefer = 0x0ull;
for (index = 0; index < PHB3_MAX_PE_NUM; index++) {
if (GETFIELD(IODA2_M32DT_PE, p->m32d_cache[index]) != pe_no)
continue;
- base = p->mm1_base + (M32_PCI_SIZE / PHB3_MAX_PE_NUM) * index;
-
- /* Update preferred address */
- if (!prefer) {
- prefer = GETFIELD(PHB_PAPR_ERR_INJ_MASK_MMIO, base);
- prefer = SETFIELD(PHB_PAPR_ERR_INJ_MASK_MMIO, 0x0ull, prefer);
+ /* Obviously, we can't support discontiguous segments.
+ * We have to pick the first batch of contiguous segments
+ * for that case
+ */
+ segstart = p->mm1_base + segsize * index;
+ if (!len) {
+ base = segstart;
+ len = segsize;
+ } else if ((base + len) == segstart) {
+ len += segsize;
}
- /* The input address matches ? */
- if (addr >= base &&
- addr < base + M32_PCI_SIZE / PHB3_MAX_PE_NUM) {
+ /* Check the specified address is valid one */
+ if (addr >= segstart && addr < (segstart + segsize)) {
a = addr;
break;
}
}
- /* Invalid PE number */
- if (!prefer)
+ /* No MM32 segments assigned to the PE */
+ if (!len)
return OPAL_PARAMETER;
/* Specified address is out of range */
if (!a) {
- a = prefer;
- m = PHB_PAPR_ERR_INJ_MASK_MMIO_MASK;
+ a = base;
+ len = len & ~(len - 1);
+ m = ~(len - 1);
} else {
m = mask;
}
+ a = SETFIELD(PHB_PAPR_ERR_INJ_ADDR_MMIO, 0x0ull, a);
+ m = SETFIELD(PHB_PAPR_ERR_INJ_MASK_MMIO, 0x0ull, m);
+
return phb3_err_inject_finalize(p, a, m, ctrl, is_write);
}