| From c52938338eaa28b412788c8b90196b0dbec0b279 Mon Sep 17 00:00:00 2001 |
| From: Bjorn Andersson <bjorn.andersson@linaro.org> |
| Date: Thu, 5 Mar 2020 01:17:27 +0530 |
| Subject: [PATCH] remoteproc: qcom_q6v5_mss: Don't reassign mpss region on |
| shutdown |
| |
| commit 900fc60df22748dbc28e4970838e8f7b8f1013ce upstream. |
| |
| Trying to reclaim mpss memory while the mba is not running causes the |
| system to crash on devices with security fuses blown, so leave it |
| assigned to the remote on shutdown and recover it on a subsequent boot. |
| |
| Fixes: 6c5a9dc2481b ("remoteproc: qcom: Make secure world call for mem ownership switch") |
| Cc: stable@vger.kernel.org |
| Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org> |
| Signed-off-by: Sibi Sankar <sibis@codeaurora.org> |
| Tested-by: Bjorn Andersson <bjorn.andersson@linaro.org> |
| Link: https://lore.kernel.org/r/20200304194729.27979-2-sibis@codeaurora.org |
| Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/drivers/remoteproc/qcom_q6v5_mss.c b/drivers/remoteproc/qcom_q6v5_mss.c |
| index 981581bcdd56..ec819af00502 100644 |
| --- a/drivers/remoteproc/qcom_q6v5_mss.c |
| +++ b/drivers/remoteproc/qcom_q6v5_mss.c |
| @@ -869,11 +869,6 @@ static void q6v5_mba_reclaim(struct q6v5 *qproc) |
| writel(val, qproc->reg_base + QDSP6SS_PWR_CTL_REG); |
| } |
| |
| - ret = q6v5_xfer_mem_ownership(qproc, &qproc->mpss_perm, |
| - false, qproc->mpss_phys, |
| - qproc->mpss_size); |
| - WARN_ON(ret); |
| - |
| q6v5_reset_assert(qproc); |
| |
| q6v5_clk_disable(qproc->dev, qproc->reset_clks, |
| @@ -963,6 +958,14 @@ static int q6v5_mpss_load(struct q6v5 *qproc) |
| max_addr = ALIGN(phdr->p_paddr + phdr->p_memsz, SZ_4K); |
| } |
| |
| + /** |
| + * In case of a modem subsystem restart on secure devices, the modem |
| + * memory can be reclaimed only after MBA is loaded. For modem cold |
| + * boot this will be a nop |
| + */ |
| + q6v5_xfer_mem_ownership(qproc, &qproc->mpss_perm, false, |
| + qproc->mpss_phys, qproc->mpss_size); |
| + |
| mpss_reloc = relocate ? min_addr : qproc->mpss_phys; |
| qproc->mpss_reloc = mpss_reloc; |
| /* Load firmware segments */ |
| @@ -1041,8 +1044,16 @@ static void qcom_q6v5_dump_segment(struct rproc *rproc, |
| void *ptr = rproc_da_to_va(rproc, segment->da, segment->size); |
| |
| /* Unlock mba before copying segments */ |
| - if (!qproc->dump_mba_loaded) |
| + if (!qproc->dump_mba_loaded) { |
| ret = q6v5_mba_load(qproc); |
| + if (!ret) { |
| + /* Reset ownership back to Linux to copy segments */ |
| + ret = q6v5_xfer_mem_ownership(qproc, &qproc->mpss_perm, |
| + false, |
| + qproc->mpss_phys, |
| + qproc->mpss_size); |
| + } |
| + } |
| |
| if (!ptr || ret) |
| memset(dest, 0xff, segment->size); |
| @@ -1053,8 +1064,14 @@ static void qcom_q6v5_dump_segment(struct rproc *rproc, |
| |
| /* Reclaim mba after copying segments */ |
| if (qproc->dump_segment_mask == qproc->dump_complete_mask) { |
| - if (qproc->dump_mba_loaded) |
| + if (qproc->dump_mba_loaded) { |
| + /* Try to reset ownership back to Q6 */ |
| + q6v5_xfer_mem_ownership(qproc, &qproc->mpss_perm, |
| + true, |
| + qproc->mpss_phys, |
| + qproc->mpss_size); |
| q6v5_mba_reclaim(qproc); |
| + } |
| } |
| } |
| |
| @@ -1094,10 +1111,6 @@ static int q6v5_start(struct rproc *rproc) |
| return 0; |
| |
| reclaim_mpss: |
| - xfermemop_ret = q6v5_xfer_mem_ownership(qproc, &qproc->mpss_perm, |
| - false, qproc->mpss_phys, |
| - qproc->mpss_size); |
| - WARN_ON(xfermemop_ret); |
| q6v5_mba_reclaim(qproc); |
| |
| return ret; |
| -- |
| 2.7.4 |
| |