From 5e803bd9f5d5dce75bb482f6741ceac9d89992cf Mon Sep 17 00:00:00 2001 From: Bhaumik Bhatt Date: Mon, 11 May 2020 14:04:42 -0700 Subject: [PATCH] mhi: cntrl: qcom: Add support for fatal error processing MHI controller needs to handle the fatal error callback issued by the bus in case reset separation needs to be supported. This state will occur as a SYS ERROR state with the device being in PBL. Perform a full power cycle and issue an MHI RESET during power down. Change-Id: I467943924302ba773c8f6d0c4ad09b51faaeb490 Signed-off-by: Bhaumik Bhatt --- drivers/bus/mhi/controllers/mhi_qcom.c | 21 +++++++++++++++++++++ drivers/bus/mhi/controllers/mhi_qcom.h | 1 + 2 files changed, 22 insertions(+) diff --git a/drivers/bus/mhi/controllers/mhi_qcom.c b/drivers/bus/mhi/controllers/mhi_qcom.c index cd252739c3a2..e57bdd0e377c 100644 --- a/drivers/bus/mhi/controllers/mhi_qcom.c +++ b/drivers/bus/mhi/controllers/mhi_qcom.c @@ -525,6 +525,22 @@ static int mhi_qcom_power_up(struct mhi_controller *mhi_cntrl) return ret; } +static void mhi_qcom_fatal_worker(struct work_struct *work) +{ + struct mhi_dev *mhi_dev = container_of(work, struct mhi_dev, + fatal_worker); + struct device *dev = &mhi_dev->pci_dev->dev; + struct mhi_controller *mhi_cntrl = dev_get_drvdata(dev); + int ret; + + mhi_power_down(mhi_cntrl, true); + + ret = mhi_qcom_power_up(mhi_cntrl); + if (ret) + MHI_ERR("Power up failure after SYS ERROR in PBL, ret:%d\n", + ret); +} + static int mhi_runtime_get(struct mhi_controller *mhi_cntrl, void *priv) { struct mhi_dev *mhi_dev = priv; @@ -569,6 +585,10 @@ static void mhi_status_cb(struct mhi_controller *mhi_cntrl, pm_runtime_put(dev); mhi_arch_mission_mode_enter(mhi_cntrl); break; + case MHI_CB_FATAL_ERROR: + MHI_CNTRL_ERR("Perform power cycle due to SYS ERROR in PBL\n"); + schedule_work(&mhi_dev->fatal_worker); + break; default: MHI_CNTRL_LOG("Unhandled cb:0x%x\n", reason); } @@ -782,6 +802,7 @@ static struct mhi_controller *mhi_register_controller(struct pci_dev *pci_dev) goto error_register; INIT_WORK(&mhi_cntrl->reg_write_work, mhi_reg_write_work); + INIT_WORK(&mhi_dev->fatal_worker, mhi_qcom_fatal_worker); mhi_cntrl->reg_write_q = kcalloc(REG_WRITE_QUEUE_LEN, sizeof(*mhi_cntrl->reg_write_q), diff --git a/drivers/bus/mhi/controllers/mhi_qcom.h b/drivers/bus/mhi/controllers/mhi_qcom.h index 3b5e74b912c4..2fc3ab727b21 100644 --- a/drivers/bus/mhi/controllers/mhi_qcom.h +++ b/drivers/bus/mhi/controllers/mhi_qcom.h @@ -63,6 +63,7 @@ struct mhi_dev { dma_addr_t iova_start; dma_addr_t iova_stop; enum mhi_suspend_mode suspend_mode; + struct work_struct fatal_worker; /* hardware info */ u32 serial_num;