Loading drivers/soc/qcom/rpmh-internal.h +3 −0 Original line number Diff line number Diff line Loading @@ -95,6 +95,7 @@ struct rpmh_ctrlr { * @tcs_in_use: s/w state of the TCS * @lock: synchronize state of the controller * @client: handle to the DRV's client. * @irq: IRQ at gic */ struct rsc_drv { const char *name; Loading @@ -106,6 +107,7 @@ struct rsc_drv { DECLARE_BITMAP(tcs_in_use, MAX_TCS_NR); spinlock_t lock; struct rpmh_ctrlr client; int irq; }; int rpmh_rsc_send_data(struct rsc_drv *drv, const struct tcs_request *msg); Loading @@ -117,4 +119,5 @@ int rpmh_rsc_write_pdc_data(struct rsc_drv *drv, const struct tcs_request *msg); void rpmh_tx_done(const struct tcs_request *msg, int r); void rpmh_rsc_debug(struct rsc_drv *drv); #endif /* __RPM_INTERNAL_H__ */ drivers/soc/qcom/rpmh-rsc.c +104 −2 Original line number Diff line number Diff line Loading @@ -446,8 +446,8 @@ int rpmh_rsc_send_data(struct rsc_drv *drv, const struct tcs_request *msg) do { ret = tcs_write(drv, msg); if (ret == -EBUSY) { pr_info_ratelimited("TCS Busy, retrying RPMH message send: addr=%#x\n", msg->cmds[0].addr); pr_info_ratelimited("DRV:%s TCS Busy, retrying RPMH message send: addr=%#x\n", drv->name, msg->cmds[0].addr); udelay(10); } } while (ret == -EBUSY); Loading Loading @@ -596,6 +596,106 @@ int rpmh_rsc_write_pdc_data(struct rsc_drv *drv, const struct tcs_request *msg) return 0; } static struct tcs_group *get_tcs_from_index(struct rsc_drv *drv, int tcs_id) { unsigned int i; for (i = 0; i < TCS_TYPE_NR; i++) { if (drv->tcs[i].mask & BIT(tcs_id)) return &drv->tcs[i]; } return NULL; } static void print_tcs_info(struct rsc_drv *drv, int tcs_id) { struct tcs_group *tcs_grp = get_tcs_from_index(drv, tcs_id); const struct tcs_request *req = get_req_from_tcs(drv, tcs_id); struct tcs_cmd *cmd; unsigned long cmds_enabled; u32 addr, data, msgid, sts, irq_sts; bool in_use = test_bit(tcs_id, drv->tcs_in_use); int i; if (!tcs_grp || !req) return; sts = read_tcs_reg(drv, RSC_DRV_STATUS, tcs_id, 0); cmds_enabled = read_tcs_reg(drv, RSC_DRV_CMD_ENABLE, tcs_id, 0); if (!cmds_enabled) return; data = read_tcs_reg(drv, RSC_DRV_CONTROL, tcs_id, 0); irq_sts = read_tcs_reg(drv, RSC_DRV_IRQ_STATUS, 0, 0); pr_warn("Request: tcs-in-use:%s active_tcs=%s(%d) state=%d wait_for_compl=%u]\n", (in_use ? "YES" : "NO"), ((tcs_grp->type == ACTIVE_TCS) ? "YES" : "NO"), tcs_grp->type, req->state, req->wait_for_compl); pr_warn("TCS=%d [ctrlr-sts:%s amc-mode:0x%x irq-sts:%s]\n", tcs_id, sts ? "IDLE" : "BUSY", data, (irq_sts & BIT(tcs_id)) ? "COMPLETED" : "PENDING"); for (i = 0; i < req->num_cmds; i++) { cmd = &req->cmds[i]; pr_warn("\tREQ=%d [addr=0x%x data=0x%x wait=0x%x]\n", i, cmd->addr, cmd->data, cmd->wait); if (i < MAX_CMDS_PER_TCS) { addr = read_tcs_reg(drv, RSC_DRV_CMD_ADDR, tcs_id, i); data = read_tcs_reg(drv, RSC_DRV_CMD_DATA, tcs_id, i); msgid = read_tcs_reg(drv, RSC_DRV_CMD_MSGID, tcs_id, i); sts = read_tcs_reg(drv, RSC_DRV_CMD_STATUS, tcs_id, i); pr_warn("\tCMD=%d [addr=0x%x data=0x%x hdr=0x%x sts=0x%x enabled=%ld]\n", i, addr, data, msgid, sts, (cmds_enabled & BIT(i))); } } for_each_set_bit_from(i, &cmds_enabled, MAX_CMDS_PER_TCS) { addr = read_tcs_reg(drv, RSC_DRV_CMD_ADDR, tcs_id, i); data = read_tcs_reg(drv, RSC_DRV_CMD_DATA, tcs_id, i); msgid = read_tcs_reg(drv, RSC_DRV_CMD_MSGID, tcs_id, i); sts = read_tcs_reg(drv, RSC_DRV_CMD_STATUS, tcs_id, i); pr_warn("\tCMD=%d [addr=0x%x data=0x%x hdr=0x%x sts=0x%x enabled=1]\n", i, addr, data, msgid, sts); } } void rpmh_rsc_debug(struct rsc_drv *drv) { struct irq_data *rsc_irq_data = irq_get_irq_data(drv->irq); bool irq_sts; int i; int busy = 0; pr_warn("RSC:%s\n", drv->name); for (i = 0; i < drv->num_tcs; i++) { if (!test_bit(i, drv->tcs_in_use)) continue; busy++; print_tcs_info(drv, i); } if (!rsc_irq_data) { pr_err("No IRQ data for RSC:%s\n", drv->name); return; } irq_get_irqchip_state(drv->irq, IRQCHIP_STATE_PENDING, &irq_sts); pr_warn("HW IRQ %lu is %s at GIC\n", rsc_irq_data->hwirq, irq_sts ? "PENDING" : "NOT PENDING"); /* * The TCS(s) are busy waiting, we have no way to recover from this. * If this debug function is called, we assume it's because timeout * has happened. * Crash and report. */ BUG_ON(busy); } static int rpmh_probe_tcs_config(struct platform_device *pdev, struct rsc_drv *drv) { Loading Loading @@ -731,6 +831,8 @@ static int rpmh_rsc_probe(struct platform_device *pdev) if (irq < 0) return irq; drv->irq = irq; ret = devm_request_irq(&pdev->dev, irq, tcs_tx_done, IRQF_TRIGGER_HIGH | IRQF_NO_SUSPEND, drv->name, drv); Loading drivers/soc/qcom/rpmh.c +7 −3 Original line number Diff line number Diff line Loading @@ -331,8 +331,12 @@ int rpmh_write(const struct device *dev, enum rpmh_state state, return ret; ret = wait_for_completion_timeout(&compl, RPMH_TIMEOUT_MS); WARN_ON(!ret); return (ret > 0) ? 0 : -ETIMEDOUT; if (!ret) { rpmh_rsc_debug(ctrlr_to_drv(ctrlr)); return -ETIMEDOUT; } return 0; } EXPORT_SYMBOL(rpmh_write); Loading Loading @@ -459,7 +463,7 @@ int rpmh_write_batch(const struct device *dev, enum rpmh_state state, * the completion on our stack and that's bad once * we've returned from the function. */ WARN_ON(1); rpmh_rsc_debug(ctrlr_to_drv(ctrlr)); ret = -ETIMEDOUT; goto exit; } Loading Loading
drivers/soc/qcom/rpmh-internal.h +3 −0 Original line number Diff line number Diff line Loading @@ -95,6 +95,7 @@ struct rpmh_ctrlr { * @tcs_in_use: s/w state of the TCS * @lock: synchronize state of the controller * @client: handle to the DRV's client. * @irq: IRQ at gic */ struct rsc_drv { const char *name; Loading @@ -106,6 +107,7 @@ struct rsc_drv { DECLARE_BITMAP(tcs_in_use, MAX_TCS_NR); spinlock_t lock; struct rpmh_ctrlr client; int irq; }; int rpmh_rsc_send_data(struct rsc_drv *drv, const struct tcs_request *msg); Loading @@ -117,4 +119,5 @@ int rpmh_rsc_write_pdc_data(struct rsc_drv *drv, const struct tcs_request *msg); void rpmh_tx_done(const struct tcs_request *msg, int r); void rpmh_rsc_debug(struct rsc_drv *drv); #endif /* __RPM_INTERNAL_H__ */
drivers/soc/qcom/rpmh-rsc.c +104 −2 Original line number Diff line number Diff line Loading @@ -446,8 +446,8 @@ int rpmh_rsc_send_data(struct rsc_drv *drv, const struct tcs_request *msg) do { ret = tcs_write(drv, msg); if (ret == -EBUSY) { pr_info_ratelimited("TCS Busy, retrying RPMH message send: addr=%#x\n", msg->cmds[0].addr); pr_info_ratelimited("DRV:%s TCS Busy, retrying RPMH message send: addr=%#x\n", drv->name, msg->cmds[0].addr); udelay(10); } } while (ret == -EBUSY); Loading Loading @@ -596,6 +596,106 @@ int rpmh_rsc_write_pdc_data(struct rsc_drv *drv, const struct tcs_request *msg) return 0; } static struct tcs_group *get_tcs_from_index(struct rsc_drv *drv, int tcs_id) { unsigned int i; for (i = 0; i < TCS_TYPE_NR; i++) { if (drv->tcs[i].mask & BIT(tcs_id)) return &drv->tcs[i]; } return NULL; } static void print_tcs_info(struct rsc_drv *drv, int tcs_id) { struct tcs_group *tcs_grp = get_tcs_from_index(drv, tcs_id); const struct tcs_request *req = get_req_from_tcs(drv, tcs_id); struct tcs_cmd *cmd; unsigned long cmds_enabled; u32 addr, data, msgid, sts, irq_sts; bool in_use = test_bit(tcs_id, drv->tcs_in_use); int i; if (!tcs_grp || !req) return; sts = read_tcs_reg(drv, RSC_DRV_STATUS, tcs_id, 0); cmds_enabled = read_tcs_reg(drv, RSC_DRV_CMD_ENABLE, tcs_id, 0); if (!cmds_enabled) return; data = read_tcs_reg(drv, RSC_DRV_CONTROL, tcs_id, 0); irq_sts = read_tcs_reg(drv, RSC_DRV_IRQ_STATUS, 0, 0); pr_warn("Request: tcs-in-use:%s active_tcs=%s(%d) state=%d wait_for_compl=%u]\n", (in_use ? "YES" : "NO"), ((tcs_grp->type == ACTIVE_TCS) ? "YES" : "NO"), tcs_grp->type, req->state, req->wait_for_compl); pr_warn("TCS=%d [ctrlr-sts:%s amc-mode:0x%x irq-sts:%s]\n", tcs_id, sts ? "IDLE" : "BUSY", data, (irq_sts & BIT(tcs_id)) ? "COMPLETED" : "PENDING"); for (i = 0; i < req->num_cmds; i++) { cmd = &req->cmds[i]; pr_warn("\tREQ=%d [addr=0x%x data=0x%x wait=0x%x]\n", i, cmd->addr, cmd->data, cmd->wait); if (i < MAX_CMDS_PER_TCS) { addr = read_tcs_reg(drv, RSC_DRV_CMD_ADDR, tcs_id, i); data = read_tcs_reg(drv, RSC_DRV_CMD_DATA, tcs_id, i); msgid = read_tcs_reg(drv, RSC_DRV_CMD_MSGID, tcs_id, i); sts = read_tcs_reg(drv, RSC_DRV_CMD_STATUS, tcs_id, i); pr_warn("\tCMD=%d [addr=0x%x data=0x%x hdr=0x%x sts=0x%x enabled=%ld]\n", i, addr, data, msgid, sts, (cmds_enabled & BIT(i))); } } for_each_set_bit_from(i, &cmds_enabled, MAX_CMDS_PER_TCS) { addr = read_tcs_reg(drv, RSC_DRV_CMD_ADDR, tcs_id, i); data = read_tcs_reg(drv, RSC_DRV_CMD_DATA, tcs_id, i); msgid = read_tcs_reg(drv, RSC_DRV_CMD_MSGID, tcs_id, i); sts = read_tcs_reg(drv, RSC_DRV_CMD_STATUS, tcs_id, i); pr_warn("\tCMD=%d [addr=0x%x data=0x%x hdr=0x%x sts=0x%x enabled=1]\n", i, addr, data, msgid, sts); } } void rpmh_rsc_debug(struct rsc_drv *drv) { struct irq_data *rsc_irq_data = irq_get_irq_data(drv->irq); bool irq_sts; int i; int busy = 0; pr_warn("RSC:%s\n", drv->name); for (i = 0; i < drv->num_tcs; i++) { if (!test_bit(i, drv->tcs_in_use)) continue; busy++; print_tcs_info(drv, i); } if (!rsc_irq_data) { pr_err("No IRQ data for RSC:%s\n", drv->name); return; } irq_get_irqchip_state(drv->irq, IRQCHIP_STATE_PENDING, &irq_sts); pr_warn("HW IRQ %lu is %s at GIC\n", rsc_irq_data->hwirq, irq_sts ? "PENDING" : "NOT PENDING"); /* * The TCS(s) are busy waiting, we have no way to recover from this. * If this debug function is called, we assume it's because timeout * has happened. * Crash and report. */ BUG_ON(busy); } static int rpmh_probe_tcs_config(struct platform_device *pdev, struct rsc_drv *drv) { Loading Loading @@ -731,6 +831,8 @@ static int rpmh_rsc_probe(struct platform_device *pdev) if (irq < 0) return irq; drv->irq = irq; ret = devm_request_irq(&pdev->dev, irq, tcs_tx_done, IRQF_TRIGGER_HIGH | IRQF_NO_SUSPEND, drv->name, drv); Loading
drivers/soc/qcom/rpmh.c +7 −3 Original line number Diff line number Diff line Loading @@ -331,8 +331,12 @@ int rpmh_write(const struct device *dev, enum rpmh_state state, return ret; ret = wait_for_completion_timeout(&compl, RPMH_TIMEOUT_MS); WARN_ON(!ret); return (ret > 0) ? 0 : -ETIMEDOUT; if (!ret) { rpmh_rsc_debug(ctrlr_to_drv(ctrlr)); return -ETIMEDOUT; } return 0; } EXPORT_SYMBOL(rpmh_write); Loading Loading @@ -459,7 +463,7 @@ int rpmh_write_batch(const struct device *dev, enum rpmh_state state, * the completion on our stack and that's bad once * we've returned from the function. */ WARN_ON(1); rpmh_rsc_debug(ctrlr_to_drv(ctrlr)); ret = -ETIMEDOUT; goto exit; } Loading