[Skiboot] [PATCH V5 5/5] capi: Handle HMI events
Frederic Barrat
fbarrat at linux.vnet.ibm.com
Mon Jun 12 20:41:55 AEST 2017
Le 07/06/2017 à 11:21, Christophe Lombard a écrit :
> Find the CAPP on the chip associated with the HMI event for PHB4.
> If a recoverable error has been detected the capp is re-initialize and
> functional operations are resumed.
>
> Signed-off-by: Christophe Lombard <clombard at linux.vnet.ibm.com>
> ---
I'm guessing it will really be tested on p9 later (we need DD2 to test
recovery), but since there doesn't seem to be any regression on p8,
that's a good sign.
Reviewed-by: Frederic Barrat <fbarrat at linux.vnet.ibm.com>
> core/hmi.c | 118 ++++++++++++++++------------------------------------
> hw/capp.c | 9 ++++
> hw/phb3.c | 34 +++++++++++++++
> hw/phb4.c | 32 ++++++++++++++
> include/capp.h | 18 ++++++++
> include/phb4-capp.h | 3 ++
> 6 files changed, 131 insertions(+), 83 deletions(-)
>
> diff --git a/core/hmi.c b/core/hmi.c
> index c5c554a..230d07b 100644
> --- a/core/hmi.c
> +++ b/core/hmi.c
> @@ -19,7 +19,6 @@
> #include <processor.h>
> #include <chiptod.h>
> #include <xscom.h>
> -#include <phb3-capp.h>
> #include <pci.h>
> #include <cpu.h>
> #include <chip.h>
> @@ -245,58 +244,6 @@ 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, int capp_index)
> -{
> - uint64_t reg;
> - 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;
> -}
> -
> -#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;
> - u32 dt_chip_id;
> - struct phb *phb;
> - u32 phb_index;
> - struct proc_chip *chip = get_chip(chip_id);
> -
> - 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");
> -
> - /*
> - * 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_lock(phb);
> - phb->ops->set_capp_recovery(phb);
> - phb_unlock(phb);
> - return 1;
> - }
> - }
> - return 0;
> -}
> -
> static bool decode_core_fir(struct cpu_thread *cpu,
> struct OpalHMIEvent *hmi_evt)
> {
> @@ -385,47 +332,52 @@ static void find_capp_checkstop_reason(int flat_chip_id,
> struct OpalHMIEvent *hmi_evt,
> bool *event_generated)
> {
> - int capp_index;
> - struct proc_chip *chip = get_chip(flat_chip_id);
> - int capp_num = CHIP_IS_NAPLES(chip) ? 2 : 1;
> - uint32_t reg_offset;
> + struct capp_info info;
> + struct phb *phb;
> uint64_t capp_fir;
> uint64_t capp_fir_mask;
> uint64_t capp_fir_action0;
> uint64_t capp_fir_action1;
> + uint64_t reg;
> + int64_t rc;
> +
> + /* Find the CAPP on the chip associated with the HMI. */
> + for_each_phb(phb) {
> + /* get the CAPP info */
> + rc = capp_get_info(flat_chip_id, phb, &info);
> + if (rc == OPAL_PARAMETER)
> + continue;
>
> - for (capp_index = 0; capp_index < capp_num; capp_index++) {
> - reg_offset = capp_index ? CAPP1_REG_OFFSET : 0x0;
> -
> - if (xscom_read(flat_chip_id,
> - CAPP_FIR + reg_offset, &capp_fir) ||
> - xscom_read(flat_chip_id,
> - CAPP_FIR_MASK + reg_offset, &capp_fir_mask) ||
> - xscom_read(flat_chip_id,
> - CAPP_FIR_ACTION0 + reg_offset, &capp_fir_action0) ||
> - xscom_read(flat_chip_id,
> - CAPP_FIR_ACTION1 + reg_offset, &capp_fir_action1)) {
> - prerror("CAPP: Couldn't read CAPP#%d FIR registers by XSCOM!\n",
> - capp_index);
> + if (xscom_read(flat_chip_id, info.capp_fir_reg, &capp_fir) ||
> + xscom_read(flat_chip_id, info.capp_fir_mask_reg, &capp_fir_mask) ||
> + xscom_read(flat_chip_id, info.capp_fir_action0_reg, &capp_fir_action0) ||
> + xscom_read(flat_chip_id, info.capp_fir_action1_reg, &capp_fir_action1)) {
> + prerror("CAPP: Couldn't read CAPP#%d (PHB:#%x) FIR registers by XSCOM!\n",
> + info.capp_index, info.phb_index);
> continue;
> }
>
> if (!(capp_fir & ~capp_fir_mask))
> continue;
>
> - prlog(PR_DEBUG, "HMI: CAPP#%d: FIR 0x%016llx mask 0x%016llx\n",
> - capp_index, capp_fir, capp_fir_mask);
> - prlog(PR_DEBUG, "HMI: CAPP#%d: ACTION0 0x%016llx, ACTION1 0x%016llx\n",
> - capp_index, capp_fir_action0, capp_fir_action1);
> -
> - 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;
> - queue_hmi_event(hmi_evt, 1);
> - *event_generated = true;
> - return;
> - }
> + prlog(PR_DEBUG, "HMI: CAPP#%d (PHB:#%x): FIR 0x%016llx mask 0x%016llx\n",
> + info.capp_index, info.phb_index, capp_fir, capp_fir_mask);
> + prlog(PR_DEBUG, "HMI: CAPP#%d (PHB:#%x): ACTION0 0x%016llx, ACTION1 0x%016llx\n",
> + info.capp_index, info.phb_index, capp_fir_action0, capp_fir_action1);
> +
> + /* If this bit is set (=1) a Recoverable Error has been detected */
> + xscom_read(flat_chip_id, info.capp_err_status_ctrl_reg, ®);
> + if ((reg & PPC_BIT(0)) != 0) {
> + phb_lock(phb);
> + phb->ops->set_capp_recovery(phb);
> + phb_unlock(phb);
> +
> + hmi_evt->severity = OpalHMI_SEV_NO_ERROR;
> + hmi_evt->type = OpalHMI_ERROR_CAPP_RECOVERY;
> + queue_hmi_event(hmi_evt, 1);
> + *event_generated = true;
> +
> + return;
> }
> }
> }
> diff --git a/hw/capp.c b/hw/capp.c
> index 843c23b..01da071 100644
> --- a/hw/capp.c
> +++ b/hw/capp.c
> @@ -35,6 +35,7 @@ static struct {
> #define CAPP_UCODE_MAX_SIZE 0x20000
>
> struct lock capi_lock = LOCK_UNLOCKED;
> +struct capp_ops capi_ops = { NULL };
>
> bool capp_ucode_loaded(struct proc_chip *chip, unsigned int index)
> {
> @@ -228,3 +229,11 @@ int64_t capp_load_ucode(unsigned int chip_id, uint32_t opal_id,
>
> return OPAL_SUCCESS;
> }
> +
> +int64_t capp_get_info(int chip_id, struct phb *phb, struct capp_info *info)
> +{
> + if (capi_ops.get_capp_info)
> + return capi_ops.get_capp_info(chip_id, phb, info);
> +
> + return OPAL_PARAMETER;
> +}
> diff --git a/hw/phb3.c b/hw/phb3.c
> index 81acb54..005d7cf 100644
> --- a/hw/phb3.c
> +++ b/hw/phb3.c
> @@ -3393,6 +3393,37 @@ static int64_t phb3_get_diag_data(struct phb *phb,
> return OPAL_SUCCESS;
> }
>
> +static int64_t phb3_get_capp_info(int chip_id, struct phb *phb, struct capp_info *info)
> +{
> + struct phb3 *p = phb_to_phb3(phb);
> + struct proc_chip *chip = get_chip(p->chip_id);
> + uint32_t offset;
> +
> + if (chip_id != p->chip_id)
> + return OPAL_PARAMETER;
> +
> + if (!((1 << p->index) & chip->capp_phb3_attached_mask))
> + return OPAL_PARAMETER;
> +
> + offset = PHB3_CAPP_REG_OFFSET(p);
> +
> + if (PHB3_IS_NAPLES(p)) {
> + if (p->index == 0)
> + info->capp_index = 0;
> + else
> + info->capp_index = 1;
> + } else
> + info->capp_index = 0;
> + info->phb_index = p->index;
> + info->capp_fir_reg = CAPP_FIR + offset;
> + info->capp_fir_mask_reg = CAPP_FIR_MASK + offset;
> + info->capp_fir_action0_reg = CAPP_FIR_ACTION0 + offset;
> + info->capp_fir_action1_reg = CAPP_FIR_ACTION1 + offset;
> + info->capp_err_status_ctrl_reg = CAPP_ERR_STATUS_CTRL + offset;
> +
> + return OPAL_SUCCESS;
> +}
> +
> static void phb3_init_capp_regs(struct phb3 *p, bool dma_mode)
> {
> uint64_t reg;
> @@ -3604,6 +3635,9 @@ static int64_t enable_capi_mode(struct phb3 *p, uint64_t pe_number, bool dma_mod
> return OPAL_HARDWARE;
> }
>
> + /* set callbacks to handle HMI events */
> + capi_ops.get_capp_info = &phb3_get_capp_info;
> +
> return OPAL_SUCCESS;
> }
>
> diff --git a/hw/phb4.c b/hw/phb4.c
> index 6414a78..779df37 100644
> --- a/hw/phb4.c
> +++ b/hw/phb4.c
> @@ -2549,6 +2549,34 @@ static uint64_t tve_encode_50b_noxlate(uint64_t start_addr, uint64_t end_addr)
> return tve;
> }
>
> +static int64_t phb4_get_capp_info(int chip_id, struct phb *phb, struct capp_info *info)
> +{
> + struct phb4 *p = phb_to_phb4(phb);
> + struct proc_chip *chip = get_chip(p->chip_id);
> + uint32_t offset;
> +
> + if (chip_id != p->chip_id)
> + return OPAL_PARAMETER;
> +
> + if (!((1 << p->index) & chip->capp_phb4_attached_mask))
> + return OPAL_PARAMETER;
> +
> + offset = PHB4_CAPP_REG_OFFSET(p);
> +
> + if (p->index == CAPP0_PHB_INDEX)
> + info->capp_index = 0;
> + if (p->index == CAPP1_PHB_INDEX)
> + info->capp_index = 1;
> + info->phb_index = p->index;
> + info->capp_fir_reg = CAPP_FIR + offset;
> + info->capp_fir_mask_reg = CAPP_FIR_MASK + offset;
> + info->capp_fir_action0_reg = CAPP_FIR_ACTION0 + offset;
> + info->capp_fir_action1_reg = CAPP_FIR_ACTION1 + offset;
> + info->capp_err_status_ctrl_reg = CAPP_ERR_STATUS_CTRL + offset;
> +
> + return OPAL_SUCCESS;
> +}
> +
> static void phb4_init_capp_regs(struct phb4 *p)
> {
> uint64_t reg;
> @@ -2806,6 +2834,10 @@ static int64_t enable_capi_mode(struct phb4 *p, uint64_t pe_number,
> PHBERR(p, "CAPP: Failed to sync timebase\n");
> return OPAL_HARDWARE;
> }
> +
> + /* set callbacks to handle HMI events */
> + capi_ops.get_capp_info = &phb4_get_capp_info;
> +
> return OPAL_SUCCESS;
> }
>
> diff --git a/include/capp.h b/include/capp.h
> index c1aa8d2..4075a51 100644
> --- a/include/capp.h
> +++ b/include/capp.h
> @@ -65,8 +65,24 @@ enum capp_reg {
> apc_master_powerbus_ctrl = 0xB
> };
>
> +struct capp_info {
> + unsigned int capp_index;
> + unsigned int phb_index;
> + uint64_t capp_fir_reg;
> + uint64_t capp_fir_mask_reg;
> + uint64_t capp_fir_action0_reg;
> + uint64_t capp_fir_action1_reg;
> + uint64_t capp_err_status_ctrl_reg;
> +};
> +
> +struct capp_ops {
> + int64_t (*get_capp_info)(int, struct phb *, struct capp_info *);
> +};
> +
> struct proc_chip;
> extern struct lock capi_lock;
> +extern struct capp_ops capi_ops;
> +
> extern bool capp_ucode_loaded(struct proc_chip *chip, unsigned int index);
>
> extern int64_t capp_load_ucode(unsigned int chip_id, uint32_t opal_id,
> @@ -74,4 +90,6 @@ extern int64_t capp_load_ucode(unsigned int chip_id, uint32_t opal_id,
> uint64_t apc_master_addr, uint64_t apc_master_write,
> uint64_t snp_array_addr, uint64_t snp_array_write);
>
> +extern int64_t capp_get_info(int, struct phb *phb, struct capp_info *info);
> +
> #endif /* __CAPP_H */
> diff --git a/include/phb4-capp.h b/include/phb4-capp.h
> index 418838d..d6128c7 100644
> --- a/include/phb4-capp.h
> +++ b/include/phb4-capp.h
> @@ -23,6 +23,9 @@
> #define CAPP_APC_MASTER_ARRAY_WRITE_REG 0x2010842 /* Satellite 2 */
>
> #define CAPP_FIR 0x2010800
> +#define CAPP_FIR_MASK 0x2010803
> +#define CAPP_FIR_ACTION0 0x2010806
> +#define CAPP_FIR_ACTION1 0x2010807
> #define CAPP_ERR_RPT_CLR 0x2010813
> #define APC_MASTER_PB_CTRL 0x2010818
> #define APC_MASTER_CAPI_CTRL 0x2010819
>
More information about the Skiboot
mailing list