lkml.org 
[lkml]   [2020]   [Sep]   [4]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v3 5/8] iommu/arm-smmu-qcom: Consistently initialize stream mappings
    Date
    Firmware that traps writes to S2CR to translate BYPASS into FAULT also
    ignores writes of type FAULT. As such booting with "disable_bypass" set
    will result in all S2CR registers left as configured by the bootloader.

    This has been seen to result in indeterministic results, as these
    mappings might linger and reference context banks that Linux is
    reconfiguring.

    Use the fact that BYPASS writes result in FAULT type to force all stream
    mappings to FAULT.

    Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
    ---

    Changes since v2:
    - None
    drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c | 18 +++++++++++++++++-
    1 file changed, 17 insertions(+), 1 deletion(-)

    diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
    index 284761a1cd8e..70a1eaa52e14 100644
    --- a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
    +++ b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
    @@ -195,6 +195,7 @@ static int qcom_smmu_cfg_probe(struct arm_smmu_device *smmu)
    unsigned int last_s2cr = ARM_SMMU_GR0_S2CR(smmu->num_mapping_groups - 1);
    struct qcom_smmu *qsmmu = to_qcom_smmu(smmu);
    u32 reg;
    + int i;

    /*
    * With some firmware writes to S2CR of type FAULT are ignored, and
    @@ -206,9 +207,24 @@ static int qcom_smmu_cfg_probe(struct arm_smmu_device *smmu)
    FIELD_PREP(ARM_SMMU_S2CR_PRIVCFG, S2CR_PRIVCFG_DEFAULT);
    arm_smmu_gr0_write(smmu, last_s2cr, reg);
    reg = arm_smmu_gr0_read(smmu, last_s2cr);
    - if (FIELD_GET(ARM_SMMU_S2CR_TYPE, reg) != S2CR_TYPE_BYPASS)
    + if (FIELD_GET(ARM_SMMU_S2CR_TYPE, reg) != S2CR_TYPE_BYPASS) {
    qsmmu->bypass_broken = true;

    + /*
    + * With firmware ignoring writes of type FAULT, booting the
    + * Linux kernel with disable_bypass disabled (i.e. "enable
    + * bypass") the initialization during probe will leave mappings
    + * in an inconsistent state. Avoid this by configuring all
    + * S2CRs to BYPASS.
    + */
    + for (i = 0; i < smmu->num_mapping_groups; i++) {
    + smmu->s2crs[i].type = S2CR_TYPE_BYPASS;
    + smmu->s2crs[i].privcfg = S2CR_PRIVCFG_DEFAULT;
    + smmu->s2crs[i].cbndx = 0xff;
    + smmu->s2crs[i].count = 0;
    + }
    + }
    +
    return 0;
    }

    --
    2.28.0
    \
     
     \ /
      Last update: 2020-09-04 17:56    [W:4.022 / U:0.112 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site