From: Bjorn Andersson <bjorn.andersson@linaro.org>
To: Robin Murphy <robin.murphy@arm.com>
Cc: Will Deacon <will@kernel.org>, Joerg Roedel <joro@8bytes.org>,
Sai Prakash Ranjan <saiprakash.ranjan@codeaurora.org>,
Jordan Crouse <jcrouse@codeaurora.org>,
Thierry Reding <treding@nvidia.com>,
Rob Clark <robdclark@chromium.org>,
linux-arm-msm@vger.kernel.org, iommu@lists.linux-foundation.org,
linux-kernel@vger.kernel.org,
linux-arm-kernel@lists.infradead.org
Subject: Re: [PATCH v4 3/3] iommu/arm-smmu-qcom: Implement S2CR quirk
Date: Mon, 19 Oct 2020 13:12:25 -0500 [thread overview]
Message-ID: <20201019181225.GD6705@builder.lan> (raw)
In-Reply-To: <cf940a0e-03ec-ceb8-1c8b-533f541f64ba@arm.com>
On Mon 19 Oct 09:04 CDT 2020, Robin Murphy wrote:
> On 2020-10-17 05:39, Bjorn Andersson wrote:
> > The firmware found in some Qualcomm platforms intercepts writes to S2CR
> > in order to replace bypass type streams with fault; and ignore S2CR
> > updates of type fault.
> >
> > Detect this behavior and implement a custom write_s2cr function in order
> > to trick the firmware into supporting bypass streams by the means of
> > configuring the stream for translation using a reserved and disabled
> > context bank.
> >
> > Also circumvent the problem of configuring faulting streams by
> > configuring the stream as bypass.
> >
> > Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
> > ---
> >
> > Changes since v3:
> > - Move the reservation of the "identity context bank" to the Qualcomm specific
> > implementation.
> > - Implement the S2CR quirk with the newly introduced write_s2cr callback.
> >
> > drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c | 68 ++++++++++++++++++++++
> > 1 file changed, 68 insertions(+)
> >
> > diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
> > index 0089048342dd..c0f42d6a6e01 100644
> > --- a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
> > +++ b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
> > @@ -10,8 +10,14 @@
> > struct qcom_smmu {
> > struct arm_smmu_device smmu;
> > + bool bypass_cbndx;
>
> Nit: variables named "*ndx" usually hold an actual index value. If it's just
> a flag then maybe name it something like "use_bypass_context"?
>
> > };
> > +static struct qcom_smmu *to_qcom_smmu(struct arm_smmu_device *smmu)
> > +{
> > + return container_of(smmu, struct qcom_smmu, smmu);
> > +}
> > +
> > static const struct of_device_id qcom_smmu_client_of_match[] __maybe_unused = {
> > { .compatible = "qcom,adreno" },
> > { .compatible = "qcom,mdp4" },
> > @@ -25,9 +31,32 @@ static const struct of_device_id qcom_smmu_client_of_match[] __maybe_unused = {
> > 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;
> > u32 smr;
> > int i;
> > + /*
> > + * With some firmware versions writes to S2CR of type FAULT are
> > + * ignored, and writing BYPASS will end up written as FAULT in the
> > + * register. Perform a write to S2CR to detect if this is the case and
> > + * if so reserve a context bank to emulate bypass streams.
> > + */
> > + reg = FIELD_PREP(ARM_SMMU_S2CR_TYPE, S2CR_TYPE_BYPASS) |
> > + FIELD_PREP(ARM_SMMU_S2CR_CBNDX, 0xff) |
> > + 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) {
> > + qsmmu->bypass_cbndx = smmu->num_context_banks - 1;
>
> Oh, so maybe the name is in fact OK but the type is wrong :/
>
> I guess this does happens to work out, but for the wrong reason...
>
Odd, but "it works on my machine"... Sorry about that.
> > +
> > + set_bit(qsmmu->bypass_cbndx, smmu->context_map);
> > +
> > + reg = FIELD_PREP(ARM_SMMU_CBAR_TYPE, CBAR_TYPE_S1_TRANS_S2_BYPASS);
> > + arm_smmu_gr1_write(smmu, ARM_SMMU_GR1_CBAR(qsmmu->bypass_cbndx), reg);
> > + }
> > +
> > for (i = 0; i < smmu->num_mapping_groups; i++) {
> > smr = arm_smmu_gr0_read(smmu, ARM_SMMU_GR0_SMR(i));
> > @@ -46,6 +75,44 @@ static int qcom_smmu_cfg_probe(struct arm_smmu_device *smmu)
> > return 0;
> > }
> > +static void qcom_smmu_write_s2cr(struct arm_smmu_device *smmu, int idx)
> > +{
> > + struct arm_smmu_s2cr *s2cr = smmu->s2crs + idx;
> > + struct qcom_smmu *qsmmu = to_qcom_smmu(smmu);
> > + u32 cbndx = s2cr->cbndx;
> > + u32 type = s2cr->type;
> > + u32 reg;
> > +
> > + if (qsmmu->bypass_cbndx) {
>
> Note that if we are talking indices here then 0 would be perfectly valid in
> general. This works out OK in practice given that we're always reserving the
> last implemented context above, and if we ever *did* only have one such that
> index 0 is the last then we're going to have a bad time either way, but it's
> not necessarily the most obvious.
>
Right. In the event that we have a SMMU instance with a single context
bank hitting this quirk would probably be bad regardless, as the
cfg_probe would have just stolen the only available context bank for
bypass purposes :)
But I've updated this to keep track of the need for bypass separate from
the index. We don't have a lot of SMMU controllers, so it's not a big
waste.
> > + if (type == S2CR_TYPE_BYPASS) {
> > + /*
> > + * Firmware with quirky S2CR handling will substitute
> > + * BYPASS writes with FAULT, so point the stream to the
> > + * reserved context bank and ask for translation on the
> > + * stream
> > + */
> > + type = S2CR_TYPE_TRANS;
> > + cbndx = qsmmu->bypass_cbndx;
> > + } else if (type == S2CR_TYPE_FAULT) {
> > + /*
> > + * Firmware with quirky S2CR handling will ignore FAULT
> > + * writes, so trick it to write FAULT by asking for a
> > + * BYPASS.
> > + */
> > + type = S2CR_TYPE_BYPASS;
>
> Ha, that's brilliant :)
>
> > + cbndx = 0xff;
> > + }
> > + }
> > +
> > + reg = FIELD_PREP(ARM_SMMU_S2CR_TYPE, type) |
> > + FIELD_PREP(ARM_SMMU_S2CR_CBNDX, cbndx) |
> > + FIELD_PREP(ARM_SMMU_S2CR_PRIVCFG, s2cr->privcfg);
> > +
> > + if (smmu->features & ARM_SMMU_FEAT_EXIDS && smmu->smrs && smmu->smrs[idx].valid)
> > + reg |= ARM_SMMU_S2CR_EXIDVALID;
>
> Does any of your hardware actually have EXIDS implemented? No big deal if
> you only want this here "just in case", I'm just curious as I was under then
> impression that it was essentially a ThunderX special.
>
I tested a couple of platforms and I don't think we do. Dropping it
makes the code slightly better to read, so let's do that.
> Other than sorting out bypass_cbndx one way or the other, overall this is
> now looking about as nice as it ever could - thanks for persevering!
>
Thank you,
Bjorn
> Robin.
>
> > + arm_smmu_gr0_write(smmu, ARM_SMMU_GR0_S2CR(idx), reg);
> > +}
> > +
> > static int qcom_smmu_def_domain_type(struct device *dev)
> > {
> > const struct of_device_id *match =
> > @@ -87,6 +154,7 @@ static const struct arm_smmu_impl qcom_smmu_impl = {
> > .cfg_probe = qcom_smmu_cfg_probe,
> > .def_domain_type = qcom_smmu_def_domain_type,
> > .reset = qcom_smmu500_reset,
> > + .write_s2cr = qcom_smmu_write_s2cr,
> > };
> > struct arm_smmu_device *qcom_smmu_impl_init(struct arm_smmu_device *smmu)
> >
WARNING: multiple messages have this Message-ID (diff)
From: Bjorn Andersson <bjorn.andersson@linaro.org>
To: Robin Murphy <robin.murphy@arm.com>
Cc: Rob Clark <robdclark@chromium.org>,
linux-arm-msm@vger.kernel.org, iommu@lists.linux-foundation.org,
linux-kernel@vger.kernel.org, Thierry Reding <treding@nvidia.com>,
Will Deacon <will@kernel.org>,
linux-arm-kernel@lists.infradead.org
Subject: Re: [PATCH v4 3/3] iommu/arm-smmu-qcom: Implement S2CR quirk
Date: Mon, 19 Oct 2020 13:12:25 -0500 [thread overview]
Message-ID: <20201019181225.GD6705@builder.lan> (raw)
In-Reply-To: <cf940a0e-03ec-ceb8-1c8b-533f541f64ba@arm.com>
On Mon 19 Oct 09:04 CDT 2020, Robin Murphy wrote:
> On 2020-10-17 05:39, Bjorn Andersson wrote:
> > The firmware found in some Qualcomm platforms intercepts writes to S2CR
> > in order to replace bypass type streams with fault; and ignore S2CR
> > updates of type fault.
> >
> > Detect this behavior and implement a custom write_s2cr function in order
> > to trick the firmware into supporting bypass streams by the means of
> > configuring the stream for translation using a reserved and disabled
> > context bank.
> >
> > Also circumvent the problem of configuring faulting streams by
> > configuring the stream as bypass.
> >
> > Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
> > ---
> >
> > Changes since v3:
> > - Move the reservation of the "identity context bank" to the Qualcomm specific
> > implementation.
> > - Implement the S2CR quirk with the newly introduced write_s2cr callback.
> >
> > drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c | 68 ++++++++++++++++++++++
> > 1 file changed, 68 insertions(+)
> >
> > diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
> > index 0089048342dd..c0f42d6a6e01 100644
> > --- a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
> > +++ b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
> > @@ -10,8 +10,14 @@
> > struct qcom_smmu {
> > struct arm_smmu_device smmu;
> > + bool bypass_cbndx;
>
> Nit: variables named "*ndx" usually hold an actual index value. If it's just
> a flag then maybe name it something like "use_bypass_context"?
>
> > };
> > +static struct qcom_smmu *to_qcom_smmu(struct arm_smmu_device *smmu)
> > +{
> > + return container_of(smmu, struct qcom_smmu, smmu);
> > +}
> > +
> > static const struct of_device_id qcom_smmu_client_of_match[] __maybe_unused = {
> > { .compatible = "qcom,adreno" },
> > { .compatible = "qcom,mdp4" },
> > @@ -25,9 +31,32 @@ static const struct of_device_id qcom_smmu_client_of_match[] __maybe_unused = {
> > 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;
> > u32 smr;
> > int i;
> > + /*
> > + * With some firmware versions writes to S2CR of type FAULT are
> > + * ignored, and writing BYPASS will end up written as FAULT in the
> > + * register. Perform a write to S2CR to detect if this is the case and
> > + * if so reserve a context bank to emulate bypass streams.
> > + */
> > + reg = FIELD_PREP(ARM_SMMU_S2CR_TYPE, S2CR_TYPE_BYPASS) |
> > + FIELD_PREP(ARM_SMMU_S2CR_CBNDX, 0xff) |
> > + 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) {
> > + qsmmu->bypass_cbndx = smmu->num_context_banks - 1;
>
> Oh, so maybe the name is in fact OK but the type is wrong :/
>
> I guess this does happens to work out, but for the wrong reason...
>
Odd, but "it works on my machine"... Sorry about that.
> > +
> > + set_bit(qsmmu->bypass_cbndx, smmu->context_map);
> > +
> > + reg = FIELD_PREP(ARM_SMMU_CBAR_TYPE, CBAR_TYPE_S1_TRANS_S2_BYPASS);
> > + arm_smmu_gr1_write(smmu, ARM_SMMU_GR1_CBAR(qsmmu->bypass_cbndx), reg);
> > + }
> > +
> > for (i = 0; i < smmu->num_mapping_groups; i++) {
> > smr = arm_smmu_gr0_read(smmu, ARM_SMMU_GR0_SMR(i));
> > @@ -46,6 +75,44 @@ static int qcom_smmu_cfg_probe(struct arm_smmu_device *smmu)
> > return 0;
> > }
> > +static void qcom_smmu_write_s2cr(struct arm_smmu_device *smmu, int idx)
> > +{
> > + struct arm_smmu_s2cr *s2cr = smmu->s2crs + idx;
> > + struct qcom_smmu *qsmmu = to_qcom_smmu(smmu);
> > + u32 cbndx = s2cr->cbndx;
> > + u32 type = s2cr->type;
> > + u32 reg;
> > +
> > + if (qsmmu->bypass_cbndx) {
>
> Note that if we are talking indices here then 0 would be perfectly valid in
> general. This works out OK in practice given that we're always reserving the
> last implemented context above, and if we ever *did* only have one such that
> index 0 is the last then we're going to have a bad time either way, but it's
> not necessarily the most obvious.
>
Right. In the event that we have a SMMU instance with a single context
bank hitting this quirk would probably be bad regardless, as the
cfg_probe would have just stolen the only available context bank for
bypass purposes :)
But I've updated this to keep track of the need for bypass separate from
the index. We don't have a lot of SMMU controllers, so it's not a big
waste.
> > + if (type == S2CR_TYPE_BYPASS) {
> > + /*
> > + * Firmware with quirky S2CR handling will substitute
> > + * BYPASS writes with FAULT, so point the stream to the
> > + * reserved context bank and ask for translation on the
> > + * stream
> > + */
> > + type = S2CR_TYPE_TRANS;
> > + cbndx = qsmmu->bypass_cbndx;
> > + } else if (type == S2CR_TYPE_FAULT) {
> > + /*
> > + * Firmware with quirky S2CR handling will ignore FAULT
> > + * writes, so trick it to write FAULT by asking for a
> > + * BYPASS.
> > + */
> > + type = S2CR_TYPE_BYPASS;
>
> Ha, that's brilliant :)
>
> > + cbndx = 0xff;
> > + }
> > + }
> > +
> > + reg = FIELD_PREP(ARM_SMMU_S2CR_TYPE, type) |
> > + FIELD_PREP(ARM_SMMU_S2CR_CBNDX, cbndx) |
> > + FIELD_PREP(ARM_SMMU_S2CR_PRIVCFG, s2cr->privcfg);
> > +
> > + if (smmu->features & ARM_SMMU_FEAT_EXIDS && smmu->smrs && smmu->smrs[idx].valid)
> > + reg |= ARM_SMMU_S2CR_EXIDVALID;
>
> Does any of your hardware actually have EXIDS implemented? No big deal if
> you only want this here "just in case", I'm just curious as I was under then
> impression that it was essentially a ThunderX special.
>
I tested a couple of platforms and I don't think we do. Dropping it
makes the code slightly better to read, so let's do that.
> Other than sorting out bypass_cbndx one way or the other, overall this is
> now looking about as nice as it ever could - thanks for persevering!
>
Thank you,
Bjorn
> Robin.
>
> > + arm_smmu_gr0_write(smmu, ARM_SMMU_GR0_S2CR(idx), reg);
> > +}
> > +
> > static int qcom_smmu_def_domain_type(struct device *dev)
> > {
> > const struct of_device_id *match =
> > @@ -87,6 +154,7 @@ static const struct arm_smmu_impl qcom_smmu_impl = {
> > .cfg_probe = qcom_smmu_cfg_probe,
> > .def_domain_type = qcom_smmu_def_domain_type,
> > .reset = qcom_smmu500_reset,
> > + .write_s2cr = qcom_smmu_write_s2cr,
> > };
> > struct arm_smmu_device *qcom_smmu_impl_init(struct arm_smmu_device *smmu)
> >
_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu
WARNING: multiple messages have this Message-ID (diff)
From: Bjorn Andersson <bjorn.andersson@linaro.org>
To: Robin Murphy <robin.murphy@arm.com>
Cc: Rob Clark <robdclark@chromium.org>,
Sai Prakash Ranjan <saiprakash.ranjan@codeaurora.org>,
linux-arm-msm@vger.kernel.org, Joerg Roedel <joro@8bytes.org>,
iommu@lists.linux-foundation.org, linux-kernel@vger.kernel.org,
Jordan Crouse <jcrouse@codeaurora.org>,
Thierry Reding <treding@nvidia.com>,
Will Deacon <will@kernel.org>,
linux-arm-kernel@lists.infradead.org
Subject: Re: [PATCH v4 3/3] iommu/arm-smmu-qcom: Implement S2CR quirk
Date: Mon, 19 Oct 2020 13:12:25 -0500 [thread overview]
Message-ID: <20201019181225.GD6705@builder.lan> (raw)
In-Reply-To: <cf940a0e-03ec-ceb8-1c8b-533f541f64ba@arm.com>
On Mon 19 Oct 09:04 CDT 2020, Robin Murphy wrote:
> On 2020-10-17 05:39, Bjorn Andersson wrote:
> > The firmware found in some Qualcomm platforms intercepts writes to S2CR
> > in order to replace bypass type streams with fault; and ignore S2CR
> > updates of type fault.
> >
> > Detect this behavior and implement a custom write_s2cr function in order
> > to trick the firmware into supporting bypass streams by the means of
> > configuring the stream for translation using a reserved and disabled
> > context bank.
> >
> > Also circumvent the problem of configuring faulting streams by
> > configuring the stream as bypass.
> >
> > Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
> > ---
> >
> > Changes since v3:
> > - Move the reservation of the "identity context bank" to the Qualcomm specific
> > implementation.
> > - Implement the S2CR quirk with the newly introduced write_s2cr callback.
> >
> > drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c | 68 ++++++++++++++++++++++
> > 1 file changed, 68 insertions(+)
> >
> > diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
> > index 0089048342dd..c0f42d6a6e01 100644
> > --- a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
> > +++ b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
> > @@ -10,8 +10,14 @@
> > struct qcom_smmu {
> > struct arm_smmu_device smmu;
> > + bool bypass_cbndx;
>
> Nit: variables named "*ndx" usually hold an actual index value. If it's just
> a flag then maybe name it something like "use_bypass_context"?
>
> > };
> > +static struct qcom_smmu *to_qcom_smmu(struct arm_smmu_device *smmu)
> > +{
> > + return container_of(smmu, struct qcom_smmu, smmu);
> > +}
> > +
> > static const struct of_device_id qcom_smmu_client_of_match[] __maybe_unused = {
> > { .compatible = "qcom,adreno" },
> > { .compatible = "qcom,mdp4" },
> > @@ -25,9 +31,32 @@ static const struct of_device_id qcom_smmu_client_of_match[] __maybe_unused = {
> > 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;
> > u32 smr;
> > int i;
> > + /*
> > + * With some firmware versions writes to S2CR of type FAULT are
> > + * ignored, and writing BYPASS will end up written as FAULT in the
> > + * register. Perform a write to S2CR to detect if this is the case and
> > + * if so reserve a context bank to emulate bypass streams.
> > + */
> > + reg = FIELD_PREP(ARM_SMMU_S2CR_TYPE, S2CR_TYPE_BYPASS) |
> > + FIELD_PREP(ARM_SMMU_S2CR_CBNDX, 0xff) |
> > + 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) {
> > + qsmmu->bypass_cbndx = smmu->num_context_banks - 1;
>
> Oh, so maybe the name is in fact OK but the type is wrong :/
>
> I guess this does happens to work out, but for the wrong reason...
>
Odd, but "it works on my machine"... Sorry about that.
> > +
> > + set_bit(qsmmu->bypass_cbndx, smmu->context_map);
> > +
> > + reg = FIELD_PREP(ARM_SMMU_CBAR_TYPE, CBAR_TYPE_S1_TRANS_S2_BYPASS);
> > + arm_smmu_gr1_write(smmu, ARM_SMMU_GR1_CBAR(qsmmu->bypass_cbndx), reg);
> > + }
> > +
> > for (i = 0; i < smmu->num_mapping_groups; i++) {
> > smr = arm_smmu_gr0_read(smmu, ARM_SMMU_GR0_SMR(i));
> > @@ -46,6 +75,44 @@ static int qcom_smmu_cfg_probe(struct arm_smmu_device *smmu)
> > return 0;
> > }
> > +static void qcom_smmu_write_s2cr(struct arm_smmu_device *smmu, int idx)
> > +{
> > + struct arm_smmu_s2cr *s2cr = smmu->s2crs + idx;
> > + struct qcom_smmu *qsmmu = to_qcom_smmu(smmu);
> > + u32 cbndx = s2cr->cbndx;
> > + u32 type = s2cr->type;
> > + u32 reg;
> > +
> > + if (qsmmu->bypass_cbndx) {
>
> Note that if we are talking indices here then 0 would be perfectly valid in
> general. This works out OK in practice given that we're always reserving the
> last implemented context above, and if we ever *did* only have one such that
> index 0 is the last then we're going to have a bad time either way, but it's
> not necessarily the most obvious.
>
Right. In the event that we have a SMMU instance with a single context
bank hitting this quirk would probably be bad regardless, as the
cfg_probe would have just stolen the only available context bank for
bypass purposes :)
But I've updated this to keep track of the need for bypass separate from
the index. We don't have a lot of SMMU controllers, so it's not a big
waste.
> > + if (type == S2CR_TYPE_BYPASS) {
> > + /*
> > + * Firmware with quirky S2CR handling will substitute
> > + * BYPASS writes with FAULT, so point the stream to the
> > + * reserved context bank and ask for translation on the
> > + * stream
> > + */
> > + type = S2CR_TYPE_TRANS;
> > + cbndx = qsmmu->bypass_cbndx;
> > + } else if (type == S2CR_TYPE_FAULT) {
> > + /*
> > + * Firmware with quirky S2CR handling will ignore FAULT
> > + * writes, so trick it to write FAULT by asking for a
> > + * BYPASS.
> > + */
> > + type = S2CR_TYPE_BYPASS;
>
> Ha, that's brilliant :)
>
> > + cbndx = 0xff;
> > + }
> > + }
> > +
> > + reg = FIELD_PREP(ARM_SMMU_S2CR_TYPE, type) |
> > + FIELD_PREP(ARM_SMMU_S2CR_CBNDX, cbndx) |
> > + FIELD_PREP(ARM_SMMU_S2CR_PRIVCFG, s2cr->privcfg);
> > +
> > + if (smmu->features & ARM_SMMU_FEAT_EXIDS && smmu->smrs && smmu->smrs[idx].valid)
> > + reg |= ARM_SMMU_S2CR_EXIDVALID;
>
> Does any of your hardware actually have EXIDS implemented? No big deal if
> you only want this here "just in case", I'm just curious as I was under then
> impression that it was essentially a ThunderX special.
>
I tested a couple of platforms and I don't think we do. Dropping it
makes the code slightly better to read, so let's do that.
> Other than sorting out bypass_cbndx one way or the other, overall this is
> now looking about as nice as it ever could - thanks for persevering!
>
Thank you,
Bjorn
> Robin.
>
> > + arm_smmu_gr0_write(smmu, ARM_SMMU_GR0_S2CR(idx), reg);
> > +}
> > +
> > static int qcom_smmu_def_domain_type(struct device *dev)
> > {
> > const struct of_device_id *match =
> > @@ -87,6 +154,7 @@ static const struct arm_smmu_impl qcom_smmu_impl = {
> > .cfg_probe = qcom_smmu_cfg_probe,
> > .def_domain_type = qcom_smmu_def_domain_type,
> > .reset = qcom_smmu500_reset,
> > + .write_s2cr = qcom_smmu_write_s2cr,
> > };
> > struct arm_smmu_device *qcom_smmu_impl_init(struct arm_smmu_device *smmu)
> >
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
next prev parent reply other threads:[~2020-10-19 18:17 UTC|newest]
Thread overview: 27+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-10-17 4:39 [PATCH v4 0/3] iommu/arm-smmu-qcom: Support maintaining bootloader mappings Bjorn Andersson
2020-10-17 4:39 ` Bjorn Andersson
2020-10-17 4:39 ` Bjorn Andersson
2020-10-17 4:39 ` [PATCH v4 1/3] iommu/arm-smmu: Allow implementation specific write_s2cr Bjorn Andersson
2020-10-17 4:39 ` Bjorn Andersson
2020-10-17 4:39 ` Bjorn Andersson
2020-10-19 14:02 ` Robin Murphy
2020-10-19 14:02 ` Robin Murphy
2020-10-19 14:02 ` Robin Murphy
2020-10-17 4:39 ` [PATCH v4 2/3] iommu/arm-smmu-qcom: Read back stream mappings Bjorn Andersson
2020-10-17 4:39 ` Bjorn Andersson
2020-10-17 4:39 ` Bjorn Andersson
2020-10-19 14:03 ` Robin Murphy
2020-10-19 14:03 ` Robin Murphy
2020-10-19 14:03 ` Robin Murphy
2020-10-19 15:31 ` Bjorn Andersson
2020-10-19 15:31 ` Bjorn Andersson
2020-10-19 15:31 ` Bjorn Andersson
2020-10-17 4:39 ` [PATCH v4 3/3] iommu/arm-smmu-qcom: Implement S2CR quirk Bjorn Andersson
2020-10-17 4:39 ` Bjorn Andersson
2020-10-17 4:39 ` Bjorn Andersson
2020-10-19 14:04 ` Robin Murphy
2020-10-19 14:04 ` Robin Murphy
2020-10-19 14:04 ` Robin Murphy
2020-10-19 18:12 ` Bjorn Andersson [this message]
2020-10-19 18:12 ` Bjorn Andersson
2020-10-19 18:12 ` Bjorn Andersson
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20201019181225.GD6705@builder.lan \
--to=bjorn.andersson@linaro.org \
--cc=iommu@lists.linux-foundation.org \
--cc=jcrouse@codeaurora.org \
--cc=joro@8bytes.org \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-arm-msm@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=robdclark@chromium.org \
--cc=robin.murphy@arm.com \
--cc=saiprakash.ranjan@codeaurora.org \
--cc=treding@nvidia.com \
--cc=will@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.