[Skiboot] [PATCH V4 5/6] hmi: Recover both CAPP units on Naples after malfunction alert
Philippe Bergheaud
felix at linux.vnet.ibm.com
Fri Apr 1 23:28:00 AEDT 2016
Naples has two capp units. Probe both units to identify the card in
error. Use the xscom register offset to operate on the right unit.
Signed-off-by: Philippe Bergheaud <felix at linux.vnet.ibm.com>
---
V2: after Mikey's review
- Identify and recover the broken card (not both)
- Add reg_offset to register adresses in do_capp_recovery_scoms
V3:
- Parenthesis around macro arguments
- New macro CHIP_IS_NAPLES(chip)
- Added a comment to clarify handle_capp_recoverable
- Use int capp_num instead of boolean dual_capp
- Use new macro PHB3_CAPP_REG_OFFSET(p)
- s/reg_offset/offset/
- s/capp/capp_index/
V4:
- No change
core/hmi.c | 47 +++++++++++++++++++++++++++++++++++------------
hw/phb3.c | 16 +++++++++++-----
2 files changed, 46 insertions(+), 17 deletions(-)
diff --git a/core/hmi.c b/core/hmi.c
index 1817ab1..ee490b0 100644
--- a/core/hmi.c
+++ b/core/hmi.c
@@ -245,14 +245,21 @@ static int queue_hmi_event(struct OpalHMIEvent *hmi_evt, int recover)
num_params, (uint64_t *)hmi_evt);
}
-static int is_capp_recoverable(int chip_id)
+static int is_capp_recoverable(int chip_id, int capp_index)
{
uint64_t reg;
- xscom_read(chip_id, CAPP_ERR_STATUS_CTRL, ®);
+ uint32_t reg_offset = capp_index ? CAPP1_REG_OFFSET : 0x0;
+
+ xscom_read(chip_id, CAPP_ERR_STATUS_CTRL + reg_offset, ®);
return (reg & PPC_BIT(0)) != 0;
}
-static int handle_capp_recoverable(int chip_id)
+#define CAPP_PHB3_ATTACHED(chip, phb_index) \
+ ((chip)->capp_phb3_attached_mask & (1 << (phb_index)))
+
+#define CHIP_IS_NAPLES(chip) ((chip)->type == PROC_CHIP_P8_NAPLES)
+
+static int handle_capp_recoverable(int chip_id, int capp_index)
{
struct dt_node *np;
u64 phb_id;
@@ -260,14 +267,26 @@ static int handle_capp_recoverable(int chip_id)
struct phb *phb;
u32 phb_index;
struct proc_chip *chip = get_chip(chip_id);
- u8 mask = chip->capp_phb3_attached_mask;
dt_for_each_compatible(dt_root, np, "ibm,power8-pciex") {
dt_chip_id = dt_prop_get_u32(np, "ibm,chip-id");
phb_index = dt_prop_get_u32(np, "ibm,phb-index");
phb_id = dt_prop_get_u64(np, "ibm,opal-phbid");
- if ((mask & (1 << phb_index)) && (chip_id == dt_chip_id)) {
+ /*
+ * Murano/Venice have a single capp (capp0) per chip,
+ * that can be attached to phb0, phb1 or phb2.
+ * The capp is identified as being attached to the chip,
+ * regardless of the phb index.
+ *
+ * Naples has two capps per chip: capp0 attached to phb0,
+ * and capp1 attached to phb1.
+ * Once we know that the capp is attached to the chip,
+ * we must also check that capp/phb indices are equal.
+ */
+ if ((chip_id == dt_chip_id) &&
+ CAPP_PHB3_ATTACHED(chip, phb_index) &&
+ (!CHIP_IS_NAPLES(chip) || phb_index == capp_index)) {
phb = pci_get_phb(phb_id);
phb->ops->lock(phb);
phb->ops->set_capp_recovery(phb);
@@ -280,17 +299,21 @@ static int handle_capp_recoverable(int chip_id)
static int decode_one_malfunction(int flat_chip_id, struct OpalHMIEvent *hmi_evt)
{
+ int capp_index;
+ struct proc_chip *chip = get_chip(flat_chip_id);
+ int capp_num = CHIP_IS_NAPLES(chip) ? 2 : 1;
+
hmi_evt->severity = OpalHMI_SEV_FATAL;
hmi_evt->type = OpalHMI_ERROR_MALFUNC_ALERT;
- if (is_capp_recoverable(flat_chip_id)) {
- if (handle_capp_recoverable(flat_chip_id) == 0)
- return 0;
+ for (capp_index = 0; capp_index < capp_num; capp_index++)
+ if (is_capp_recoverable(flat_chip_id, capp_index))
+ if (handle_capp_recoverable(flat_chip_id, capp_index)) {
+ hmi_evt->severity = OpalHMI_SEV_NO_ERROR;
+ hmi_evt->type = OpalHMI_ERROR_CAPP_RECOVERY;
+ return 1;
+ }
- hmi_evt->severity = OpalHMI_SEV_NO_ERROR;
- hmi_evt->type = OpalHMI_ERROR_CAPP_RECOVERY;
- return 1;
- }
/* TODO check other FIRs */
return 0;
}
diff --git a/hw/phb3.c b/hw/phb3.c
index 8374584..63fbc78 100644
--- a/hw/phb3.c
+++ b/hw/phb3.c
@@ -2442,16 +2442,22 @@ static int64_t capp_load_ucode(struct phb3 *p)
static void do_capp_recovery_scoms(struct phb3 *p)
{
uint64_t reg;
+ uint32_t offset;
+
PHBDBG(p, "Doing CAPP recovery scoms\n");
- xscom_write(p->chip_id, SNOOP_CAPI_CONFIG, 0); /* disable snoops */
+ offset = PHB3_CAPP_REG_OFFSET(p);
+ /* disable snoops */
+ xscom_write(p->chip_id, SNOOP_CAPI_CONFIG + offset, 0);
capp_load_ucode(p);
- xscom_write(p->chip_id, CAPP_ERR_RPT_CLR, 0); /* clear err rpt reg*/
- xscom_write(p->chip_id, CAPP_FIR, 0); /* clear capp fir */
+ /* clear err rpt reg*/
+ xscom_write(p->chip_id, CAPP_ERR_RPT_CLR + offset, 0);
+ /* clear capp fir */
+ xscom_write(p->chip_id, CAPP_FIR + offset, 0);
- xscom_read(p->chip_id, CAPP_ERR_STATUS_CTRL, ®);
+ xscom_read(p->chip_id, CAPP_ERR_STATUS_CTRL + offset, ®);
reg &= ~(PPC_BIT(0) | PPC_BIT(1));
- xscom_write(p->chip_id, CAPP_ERR_STATUS_CTRL, reg);
+ xscom_write(p->chip_id, CAPP_ERR_STATUS_CTRL + offset, reg);
}
/*
--
2.1.0
More information about the Skiboot
mailing list