diff mbox series

[PATCHv6,3/3] iommu: arm-smmu-impl: Add sdm845 implementation hook

Message ID 1513424ecec891d19c1aa3c599ec67db7964b6b2.1568712606.git.saiprakash.ranjan@codeaurora.org (mailing list archive)
State Superseded
Headers show
Series QCOM smmu-500 wait-for-safe handling for sdm845 | expand

Commit Message

Sai Prakash Ranjan Sept. 17, 2019, 9:45 a.m. UTC
From: Vivek Gautam <vivek.gautam@codeaurora.org>

Add reset hook for sdm845 based platforms to turn off
the wait-for-safe sequence.

Understanding how wait-for-safe logic affects USB and UFS performance
on MTP845 and DB845 boards:

Qcom's implementation of arm,mmu-500 adds a WAIT-FOR-SAFE logic
to address under-performance issues in real-time clients, such as
Display, and Camera.
On receiving an invalidation requests, the SMMU forwards SAFE request
to these clients and waits for SAFE ack signal from real-time clients.
The SAFE signal from such clients is used to qualify the start of
invalidation.
This logic is controlled by chicken bits, one for each - MDP (display),
IFE0, and IFE1 (camera), that can be accessed only from secure software
on sdm845.

This configuration, however, degrades the performance of non-real time
clients, such as USB, and UFS etc. This happens because, with wait-for-safe
logic enabled the hardware tries to throttle non-real time clients while
waiting for SAFE ack signals from real-time clients.

On mtp845 and db845 devices, with wait-for-safe logic enabled by the
bootloaders we see degraded performance of USB and UFS when kernel
enables the smmu stage-1 translations for these clients.
Turn off this wait-for-safe logic from the kernel gets us back the perf
of USB and UFS devices until we re-visit this when we start seeing perf
issues on display/camera on upstream supported SDM845 platforms.
The bootloaders on these boards implement secure monitor callbacks to
handle a specific command - QCOM_SCM_SVC_SMMU_PROGRAM with which the
logic can be toggled.

There are other boards such as cheza whose bootloaders don't enable this
logic. Such boards don't implement callbacks to handle the specific SCM
call so disabling this logic for such boards will be a no-op.

This change is inspired by the downstream change from Patrick Daly
to address performance issues with display and camera by handling
this wait-for-safe within separte io-pagetable ops to do TLB
maintenance. So a big thanks to him for the change and for all the
offline discussions.

Without this change the UFS reads are pretty slow:
$ time dd if=/dev/sda of=/dev/zero bs=1048576 count=10 conv=sync
10+0 records in
10+0 records out
10485760 bytes (10.0MB) copied, 22.394903 seconds, 457.2KB/s
real    0m 22.39s
user    0m 0.00s
sys     0m 0.01s

With this change they are back to rock!
$ time dd if=/dev/sda of=/dev/zero bs=1048576 count=300 conv=sync
300+0 records in
300+0 records out
314572800 bytes (300.0MB) copied, 1.030541 seconds, 291.1MB/s
real    0m 1.03s
user    0m 0.00s
sys     0m 0.54s

Signed-off-by: Vivek Gautam <vivek.gautam@codeaurora.org>
Reviewed-by: Robin Murphy <robin.murphy@arm.com>
Signed-off-by: Sai Prakash Ranjan <saiprakash.ranjan@codeaurora.org>
---
 drivers/iommu/Makefile        |  2 +-
 drivers/iommu/arm-smmu-impl.c |  6 +++--
 drivers/iommu/arm-smmu-qcom.c | 51 +++++++++++++++++++++++++++++++++++
 drivers/iommu/arm-smmu.h      |  3 +++
 4 files changed, 59 insertions(+), 3 deletions(-)
 create mode 100644 drivers/iommu/arm-smmu-qcom.c

Comments

Bjorn Andersson Sept. 19, 2019, 12:25 a.m. UTC | #1
On Tue 17 Sep 02:45 PDT 2019, Sai Prakash Ranjan wrote:

> From: Vivek Gautam <vivek.gautam@codeaurora.org>
> 
> Add reset hook for sdm845 based platforms to turn off
> the wait-for-safe sequence.
> 
> Understanding how wait-for-safe logic affects USB and UFS performance
> on MTP845 and DB845 boards:
> 
> Qcom's implementation of arm,mmu-500 adds a WAIT-FOR-SAFE logic
> to address under-performance issues in real-time clients, such as
> Display, and Camera.
> On receiving an invalidation requests, the SMMU forwards SAFE request
> to these clients and waits for SAFE ack signal from real-time clients.
> The SAFE signal from such clients is used to qualify the start of
> invalidation.
> This logic is controlled by chicken bits, one for each - MDP (display),
> IFE0, and IFE1 (camera), that can be accessed only from secure software
> on sdm845.
> 
> This configuration, however, degrades the performance of non-real time
> clients, such as USB, and UFS etc. This happens because, with wait-for-safe
> logic enabled the hardware tries to throttle non-real time clients while
> waiting for SAFE ack signals from real-time clients.
> 
> On mtp845 and db845 devices, with wait-for-safe logic enabled by the
> bootloaders we see degraded performance of USB and UFS when kernel
> enables the smmu stage-1 translations for these clients.
> Turn off this wait-for-safe logic from the kernel gets us back the perf
> of USB and UFS devices until we re-visit this when we start seeing perf
> issues on display/camera on upstream supported SDM845 platforms.
> The bootloaders on these boards implement secure monitor callbacks to
> handle a specific command - QCOM_SCM_SVC_SMMU_PROGRAM with which the
> logic can be toggled.
> 
> There are other boards such as cheza whose bootloaders don't enable this
> logic. Such boards don't implement callbacks to handle the specific SCM
> call so disabling this logic for such boards will be a no-op.
> 
> This change is inspired by the downstream change from Patrick Daly
> to address performance issues with display and camera by handling
> this wait-for-safe within separte io-pagetable ops to do TLB
> maintenance. So a big thanks to him for the change and for all the
> offline discussions.
> 
> Without this change the UFS reads are pretty slow:
> $ time dd if=/dev/sda of=/dev/zero bs=1048576 count=10 conv=sync
> 10+0 records in
> 10+0 records out
> 10485760 bytes (10.0MB) copied, 22.394903 seconds, 457.2KB/s
> real    0m 22.39s
> user    0m 0.00s
> sys     0m 0.01s
> 
> With this change they are back to rock!
> $ time dd if=/dev/sda of=/dev/zero bs=1048576 count=300 conv=sync
> 300+0 records in
> 300+0 records out
> 314572800 bytes (300.0MB) copied, 1.030541 seconds, 291.1MB/s
> real    0m 1.03s
> user    0m 0.00s
> sys     0m 0.54s
> 
> Signed-off-by: Vivek Gautam <vivek.gautam@codeaurora.org>
> Reviewed-by: Robin Murphy <robin.murphy@arm.com>
> Signed-off-by: Sai Prakash Ranjan <saiprakash.ranjan@codeaurora.org>
> ---
>  drivers/iommu/Makefile        |  2 +-
>  drivers/iommu/arm-smmu-impl.c |  6 +++--
>  drivers/iommu/arm-smmu-qcom.c | 51 +++++++++++++++++++++++++++++++++++
>  drivers/iommu/arm-smmu.h      |  3 +++
>  4 files changed, 59 insertions(+), 3 deletions(-)
>  create mode 100644 drivers/iommu/arm-smmu-qcom.c
> 
> diff --git a/drivers/iommu/Makefile b/drivers/iommu/Makefile
> index a2729aadd300..2816e49a8c46 100644
> --- a/drivers/iommu/Makefile
> +++ b/drivers/iommu/Makefile
> @@ -13,7 +13,7 @@ obj-$(CONFIG_MSM_IOMMU) += msm_iommu.o
>  obj-$(CONFIG_AMD_IOMMU) += amd_iommu.o amd_iommu_init.o
>  obj-$(CONFIG_AMD_IOMMU_DEBUGFS) += amd_iommu_debugfs.o
>  obj-$(CONFIG_AMD_IOMMU_V2) += amd_iommu_v2.o
> -obj-$(CONFIG_ARM_SMMU) += arm-smmu.o arm-smmu-impl.o
> +obj-$(CONFIG_ARM_SMMU) += arm-smmu.o arm-smmu-impl.o arm-smmu-qcom.o
>  obj-$(CONFIG_ARM_SMMU_V3) += arm-smmu-v3.o
>  obj-$(CONFIG_DMAR_TABLE) += dmar.o
>  obj-$(CONFIG_INTEL_IOMMU) += intel-iommu.o intel-pasid.o
> diff --git a/drivers/iommu/arm-smmu-impl.c b/drivers/iommu/arm-smmu-impl.c
> index 3f88cd078dd5..d62da270f430 100644
> --- a/drivers/iommu/arm-smmu-impl.c
> +++ b/drivers/iommu/arm-smmu-impl.c
> @@ -9,7 +9,6 @@
>  
>  #include "arm-smmu.h"
>  
> -
>  static int arm_smmu_gr0_ns(int offset)
>  {
>  	switch(offset) {
> @@ -109,7 +108,7 @@ static struct arm_smmu_device *cavium_smmu_impl_init(struct arm_smmu_device *smm
>  #define ARM_MMU500_ACR_S2CRB_TLBEN	(1 << 10)
>  #define ARM_MMU500_ACR_SMTNMB_TLBEN	(1 << 8)
>  
> -static int arm_mmu500_reset(struct arm_smmu_device *smmu)
> +int arm_mmu500_reset(struct arm_smmu_device *smmu)
>  {
>  	u32 reg, major;
>  	int i;
> @@ -170,5 +169,8 @@ struct arm_smmu_device *arm_smmu_impl_init(struct arm_smmu_device *smmu)
>  				  "calxeda,smmu-secure-config-access"))
>  		smmu->impl = &calxeda_impl;
>  
> +	if (of_device_is_compatible(smmu->dev->of_node, "qcom,sdm845-smmu-500"))
> +		return qcom_smmu_impl_init(smmu);
> +
>  	return smmu;
>  }
> diff --git a/drivers/iommu/arm-smmu-qcom.c b/drivers/iommu/arm-smmu-qcom.c
> new file mode 100644
> index 000000000000..24c071c1d8b0
> --- /dev/null
> +++ b/drivers/iommu/arm-smmu-qcom.c
> @@ -0,0 +1,51 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (c) 2019, The Linux Foundation. All rights reserved.
> + */
> +
> +#include <linux/qcom_scm.h>
> +
> +#include "arm-smmu.h"
> +
> +struct qcom_smmu {
> +	struct arm_smmu_device smmu;
> +};
> +
> +static int qcom_sdm845_smmu500_reset(struct arm_smmu_device *smmu)
> +{
> +	int ret;
> +
> +	arm_mmu500_reset(smmu);
> +
> +	/*
> +	 * To address performance degradation in non-real time clients,
> +	 * such as USB and UFS, turn off wait-for-safe on sdm845 based boards,
> +	 * such as MTP and db845, whose firmwares implement secure monitor
> +	 * call handlers to turn on/off the wait-for-safe logic.
> +	 */
> +	ret = qcom_scm_qsmmu500_wait_safe_toggle(0);

In the transition to this new design we lost the ability to
enable/disable the safe toggle per board, which according to Vivek
would result in some issue with Cheza.

Can you confirm that this is okay? (Or introduce the DT property for
enabling the safe_toggle logic?)

Regards,
Bjorn

> +	if (ret)
> +		dev_warn(smmu->dev, "Failed to turn off SAFE logic\n");
> +
> +	return ret;
> +}
> +
> +static const struct arm_smmu_impl qcom_smmu_impl = {
> +	.reset = qcom_sdm845_smmu500_reset,
> +};
> +
> +struct arm_smmu_device *qcom_smmu_impl_init(struct arm_smmu_device *smmu)
> +{
> +	struct qcom_smmu *qsmmu;
> +
> +	qsmmu = devm_kzalloc(smmu->dev, sizeof(*qsmmu), GFP_KERNEL);
> +	if (!qsmmu)
> +		return ERR_PTR(-ENOMEM);
> +
> +	qsmmu->smmu = *smmu;
> +
> +	qsmmu->smmu.impl = &qcom_smmu_impl;
> +	devm_kfree(smmu->dev, smmu);
> +
> +	return &qsmmu->smmu;
> +}
> diff --git a/drivers/iommu/arm-smmu.h b/drivers/iommu/arm-smmu.h
> index ac9eac966cf5..4bc9e853c95d 100644
> --- a/drivers/iommu/arm-smmu.h
> +++ b/drivers/iommu/arm-smmu.h
> @@ -391,5 +391,8 @@ static inline void arm_smmu_writeq(struct arm_smmu_device *smmu, int page,
>  	arm_smmu_writeq((s), ARM_SMMU_CB((s), (n)), (o), (v))
>  
>  struct arm_smmu_device *arm_smmu_impl_init(struct arm_smmu_device *smmu);
> +struct arm_smmu_device *qcom_smmu_impl_init(struct arm_smmu_device *smmu);
> +
> +int arm_mmu500_reset(struct arm_smmu_device *smmu);
>  
>  #endif /* _ARM_SMMU_H */
> -- 
> QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member
> of Code Aurora Forum, hosted by The Linux Foundation
>
Stephen Boyd Sept. 19, 2019, 12:52 a.m. UTC | #2
Quoting Bjorn Andersson (2019-09-18 17:25:01)
> On Tue 17 Sep 02:45 PDT 2019, Sai Prakash Ranjan wrote:
> 
> > From: Vivek Gautam <vivek.gautam@codeaurora.org>
> > 
> > There are other boards such as cheza whose bootloaders don't enable this
> > logic. Such boards don't implement callbacks to handle the specific SCM
> > call so disabling this logic for such boards will be a no-op.
> > 
[...]
> > diff --git a/drivers/iommu/arm-smmu-qcom.c b/drivers/iommu/arm-smmu-qcom.c
> > new file mode 100644
> > index 000000000000..24c071c1d8b0
> > --- /dev/null
> > +++ b/drivers/iommu/arm-smmu-qcom.c
> > @@ -0,0 +1,51 @@
> > +// SPDX-License-Identifier: GPL-2.0-only
> > +/*
> > + * Copyright (c) 2019, The Linux Foundation. All rights reserved.
> > + */
> > +
> > +#include <linux/qcom_scm.h>
> > +
> > +#include "arm-smmu.h"
> > +
> > +struct qcom_smmu {
> > +     struct arm_smmu_device smmu;
> > +};
> > +
> > +static int qcom_sdm845_smmu500_reset(struct arm_smmu_device *smmu)
> > +{
> > +     int ret;
> > +
> > +     arm_mmu500_reset(smmu);
> > +
> > +     /*
> > +      * To address performance degradation in non-real time clients,
> > +      * such as USB and UFS, turn off wait-for-safe on sdm845 based boards,
> > +      * such as MTP and db845, whose firmwares implement secure monitor
> > +      * call handlers to turn on/off the wait-for-safe logic.
> > +      */
> > +     ret = qcom_scm_qsmmu500_wait_safe_toggle(0);
> 
> In the transition to this new design we lost the ability to
> enable/disable the safe toggle per board, which according to Vivek
> would result in some issue with Cheza.
> 
> Can you confirm that this is okay? (Or introduce the DT property for
> enabling the safe_toggle logic?)
> 

I can test this on Cheza. Not sure if anything will happen but it's
worth a shot.
Stephen Boyd Sept. 19, 2019, 12:57 a.m. UTC | #3
Quoting Sai Prakash Ranjan (2019-09-17 02:45:04)
> diff --git a/drivers/iommu/arm-smmu-impl.c b/drivers/iommu/arm-smmu-impl.c
> index 3f88cd078dd5..d62da270f430 100644
> --- a/drivers/iommu/arm-smmu-impl.c
> +++ b/drivers/iommu/arm-smmu-impl.c
> @@ -9,7 +9,6 @@
>  
>  #include "arm-smmu.h"
>  
> -
>  static int arm_smmu_gr0_ns(int offset)
>  {
>         switch(offset) {

Why is this hunk still around?

> diff --git a/drivers/iommu/arm-smmu-qcom.c b/drivers/iommu/arm-smmu-qcom.c
> new file mode 100644
> index 000000000000..24c071c1d8b0
> --- /dev/null
> +++ b/drivers/iommu/arm-smmu-qcom.c
> @@ -0,0 +1,51 @@
[...]
> +struct arm_smmu_device *qcom_smmu_impl_init(struct arm_smmu_device *smmu)
> +{
> +       struct qcom_smmu *qsmmu;
> +
> +       qsmmu = devm_kzalloc(smmu->dev, sizeof(*qsmmu), GFP_KERNEL);
> +       if (!qsmmu)
> +               return ERR_PTR(-ENOMEM);
> +
> +       qsmmu->smmu = *smmu;
> +
> +       qsmmu->smmu.impl = &qcom_smmu_impl;
> +       devm_kfree(smmu->dev, smmu);

This copy is interesting but OK I guess cavium does it.

> +
> +       return &qsmmu->smmu;
> +}
Sai Prakash Ranjan Sept. 19, 2019, 3:13 a.m. UTC | #4
On 2019-09-19 06:27, Stephen Boyd wrote:
> Quoting Sai Prakash Ranjan (2019-09-17 02:45:04)
>> diff --git a/drivers/iommu/arm-smmu-impl.c 
>> b/drivers/iommu/arm-smmu-impl.c
>> index 3f88cd078dd5..d62da270f430 100644
>> --- a/drivers/iommu/arm-smmu-impl.c
>> +++ b/drivers/iommu/arm-smmu-impl.c
>> @@ -9,7 +9,6 @@
>> 
>>  #include "arm-smmu.h"
>> 
>> -
>>  static int arm_smmu_gr0_ns(int offset)
>>  {
>>         switch(offset) {
> 
> Why is this hunk still around?

I remember correcting this in previous version but somehow slipped in 
this version. Will correct it.

> 
>> diff --git a/drivers/iommu/arm-smmu-qcom.c 
>> b/drivers/iommu/arm-smmu-qcom.c
>> new file mode 100644
>> index 000000000000..24c071c1d8b0
>> --- /dev/null
>> +++ b/drivers/iommu/arm-smmu-qcom.c
>> @@ -0,0 +1,51 @@
> [...]
>> +struct arm_smmu_device *qcom_smmu_impl_init(struct arm_smmu_device 
>> *smmu)
>> +{
>> +       struct qcom_smmu *qsmmu;
>> +
>> +       qsmmu = devm_kzalloc(smmu->dev, sizeof(*qsmmu), GFP_KERNEL);
>> +       if (!qsmmu)
>> +               return ERR_PTR(-ENOMEM);
>> +
>> +       qsmmu->smmu = *smmu;
>> +
>> +       qsmmu->smmu.impl = &qcom_smmu_impl;
>> +       devm_kfree(smmu->dev, smmu);
> 
> This copy is interesting but OK I guess cavium does it.
> 

This is from nvidia impl since Robin pointed me at its implementation.

>> +
>> +       return &qsmmu->smmu;
>> +}

Thanks,
Sai
Sai Prakash Ranjan Sept. 19, 2019, 3:18 a.m. UTC | #5
On 2019-09-19 05:55, Bjorn Andersson wrote:
> In the transition to this new design we lost the ability to
> enable/disable the safe toggle per board, which according to Vivek
> would result in some issue with Cheza.
> 
> Can you confirm that this is okay? (Or introduce the DT property for
> enabling the safe_toggle logic?)
> 

Hmm, I don't remember Vivek telling about any issue on Cheza because of 
this logic.
But I will test this on Cheza and let you know.

Thanks,
Sai
Sai Prakash Ranjan Sept. 19, 2019, 6:54 p.m. UTC | #6
On 2019-09-19 08:48, Sai Prakash Ranjan wrote:
> On 2019-09-19 05:55, Bjorn Andersson wrote:
>> In the transition to this new design we lost the ability to
>> enable/disable the safe toggle per board, which according to Vivek
>> would result in some issue with Cheza.
>> 
>> Can you confirm that this is okay? (Or introduce the DT property for
>> enabling the safe_toggle logic?)
>> 
> 
> Hmm, I don't remember Vivek telling about any issue on Cheza because
> of this logic.
> But I will test this on Cheza and let you know.
> 

I tested this on Cheza and no perf degradation nor any other issue is 
seen
atleast openly, although I see this below stack dump always with 
cant_sleep change added.

[    5.048860] BUG: assuming atomic context at 
/mnt/host/source/src/third_party/kernel/v5.3/drivers/firmware/qcom_scm-64.c:206
[    5.060303] in_atomic(): 0, irqs_disabled(): 0, pid: 1, name: 
swapper/0
[    5.067118] CPU: 4 PID: 1 Comm: swapper/0 Not tainted 5.3.0 #102
[    5.073299] Hardware name: Google Cheza (rev3+) (DT)
[    5.078416] Call trace:
[    5.080953]  dump_backtrace+0x0/0x16c
[    5.084727]  show_stack+0x20/0x2c
[    5.088156]  dump_stack+0x90/0xcc
[    5.091585]  __cant_sleep+0xb4/0xc4
[    5.095192]  __qcom_scm_qsmmu500_wait_safe_toggle+0x5c/0xa0
[    5.100929]  qcom_scm_qsmmu500_wait_safe_toggle+0x28/0x34
[    5.106491]  qcom_sdm845_smmu500_reset+0x24/0x50
[    5.111249]  arm_smmu_device_reset+0x1a4/0x25c
[    5.115827]  arm_smmu_device_probe+0x418/0x50c
[    5.120406]  platform_drv_probe+0x90/0xb0
[    5.124542]  really_probe+0x14c/0x3b8
[    5.128327]  driver_probe_device+0x70/0x140
[    5.132643]  device_driver_attach+0x4c/0x6c
[    5.136960]  __driver_attach+0xc8/0x150
[    5.140917]  bus_for_each_dev+0x84/0xcc
[    5.144873]  driver_attach+0x2c/0x38
[    5.148555]  bus_add_driver+0x108/0x1fc
[    5.152512]  driver_register+0x64/0xf8
[    5.156375]  __platform_driver_register+0x4c/0x58
[    5.161226]  arm_smmu_driver_init+0x1c/0x24
[    5.165545]  do_one_initcall+0x11c/0x2dc
[    5.169595]  do_initcall_level+0x14c/0x174
[    5.173822]  do_basic_setup+0x30/0x48
[    5.177595]  kernel_init_freeable+0xc4/0x144
[    5.181990]  kernel_init+0x14/0x100
[    5.185584]  ret_from_fork+0x10/0x18
Stephen Boyd Sept. 19, 2019, 8 p.m. UTC | #7
Quoting Sai Prakash Ranjan (2019-09-19 11:54:27)
> On 2019-09-19 08:48, Sai Prakash Ranjan wrote:
> > On 2019-09-19 05:55, Bjorn Andersson wrote:
> >> In the transition to this new design we lost the ability to
> >> enable/disable the safe toggle per board, which according to Vivek
> >> would result in some issue with Cheza.
> >> 
> >> Can you confirm that this is okay? (Or introduce the DT property for
> >> enabling the safe_toggle logic?)
> >> 
> > 
> > Hmm, I don't remember Vivek telling about any issue on Cheza because
> > of this logic.
> > But I will test this on Cheza and let you know.
> > 
> 
> I tested this on Cheza and no perf degradation nor any other issue is 
> seen
> atleast openly, although I see this below stack dump always with 
> cant_sleep change added.

The usage of cant_sleep() here is wrong then, and the comment should be
removed from the scm API as well because it looks like it's perfectly OK
to call the function from a context that can sleep.

> 
> [    5.048860] BUG: assuming atomic context at 
> /mnt/host/source/src/third_party/kernel/v5.3/drivers/firmware/qcom_scm-64.c:206
> [    5.060303] in_atomic(): 0, irqs_disabled(): 0, pid: 1, name: 
> swapper/0
> [    5.067118] CPU: 4 PID: 1 Comm: swapper/0 Not tainted 5.3.0 #102
> [    5.073299] Hardware name: Google Cheza (rev3+) (DT)
> [    5.078416] Call trace:
> [    5.080953]  dump_backtrace+0x0/0x16c
> [    5.084727]  show_stack+0x20/0x2c
> [    5.088156]  dump_stack+0x90/0xcc
> [    5.091585]  __cant_sleep+0xb4/0xc4
> [    5.095192]  __qcom_scm_qsmmu500_wait_safe_toggle+0x5c/0xa0
> [    5.100929]  qcom_scm_qsmmu500_wait_safe_toggle+0x28/0x34
> [    5.106491]  qcom_sdm845_smmu500_reset+0x24/0x50
> [    5.111249]  arm_smmu_device_reset+0x1a4/0x25c
> [    5.115827]  arm_smmu_device_probe+0x418/0x50c
> [    5.120406]  platform_drv_probe+0x90/0xb0
Sai Prakash Ranjan Sept. 20, 2019, 7:54 a.m. UTC | #8
On 2019-09-20 01:30, Stephen Boyd wrote:
> Quoting Sai Prakash Ranjan (2019-09-19 11:54:27)
>> On 2019-09-19 08:48, Sai Prakash Ranjan wrote:
>> > On 2019-09-19 05:55, Bjorn Andersson wrote:
>> >> In the transition to this new design we lost the ability to
>> >> enable/disable the safe toggle per board, which according to Vivek
>> >> would result in some issue with Cheza.
>> >>
>> >> Can you confirm that this is okay? (Or introduce the DT property for
>> >> enabling the safe_toggle logic?)
>> >>
>> >
>> > Hmm, I don't remember Vivek telling about any issue on Cheza because
>> > of this logic.
>> > But I will test this on Cheza and let you know.
>> >
>> 
>> I tested this on Cheza and no perf degradation nor any other issue is
>> seen
>> atleast openly, although I see this below stack dump always with
>> cant_sleep change added.
> 
> The usage of cant_sleep() here is wrong then, and the comment should be
> removed from the scm API as well because it looks like it's perfectly 
> OK
> to call the function from a context that can sleep.
> 

Looking more into this downstream, it says this *can be called in atomic 
context*
and not *should be called only in atomic context*. So will remove 
cant_sleep and
modify the comment accordingly.
diff mbox series

Patch

diff --git a/drivers/iommu/Makefile b/drivers/iommu/Makefile
index a2729aadd300..2816e49a8c46 100644
--- a/drivers/iommu/Makefile
+++ b/drivers/iommu/Makefile
@@ -13,7 +13,7 @@  obj-$(CONFIG_MSM_IOMMU) += msm_iommu.o
 obj-$(CONFIG_AMD_IOMMU) += amd_iommu.o amd_iommu_init.o
 obj-$(CONFIG_AMD_IOMMU_DEBUGFS) += amd_iommu_debugfs.o
 obj-$(CONFIG_AMD_IOMMU_V2) += amd_iommu_v2.o
-obj-$(CONFIG_ARM_SMMU) += arm-smmu.o arm-smmu-impl.o
+obj-$(CONFIG_ARM_SMMU) += arm-smmu.o arm-smmu-impl.o arm-smmu-qcom.o
 obj-$(CONFIG_ARM_SMMU_V3) += arm-smmu-v3.o
 obj-$(CONFIG_DMAR_TABLE) += dmar.o
 obj-$(CONFIG_INTEL_IOMMU) += intel-iommu.o intel-pasid.o
diff --git a/drivers/iommu/arm-smmu-impl.c b/drivers/iommu/arm-smmu-impl.c
index 3f88cd078dd5..d62da270f430 100644
--- a/drivers/iommu/arm-smmu-impl.c
+++ b/drivers/iommu/arm-smmu-impl.c
@@ -9,7 +9,6 @@ 
 
 #include "arm-smmu.h"
 
-
 static int arm_smmu_gr0_ns(int offset)
 {
 	switch(offset) {
@@ -109,7 +108,7 @@  static struct arm_smmu_device *cavium_smmu_impl_init(struct arm_smmu_device *smm
 #define ARM_MMU500_ACR_S2CRB_TLBEN	(1 << 10)
 #define ARM_MMU500_ACR_SMTNMB_TLBEN	(1 << 8)
 
-static int arm_mmu500_reset(struct arm_smmu_device *smmu)
+int arm_mmu500_reset(struct arm_smmu_device *smmu)
 {
 	u32 reg, major;
 	int i;
@@ -170,5 +169,8 @@  struct arm_smmu_device *arm_smmu_impl_init(struct arm_smmu_device *smmu)
 				  "calxeda,smmu-secure-config-access"))
 		smmu->impl = &calxeda_impl;
 
+	if (of_device_is_compatible(smmu->dev->of_node, "qcom,sdm845-smmu-500"))
+		return qcom_smmu_impl_init(smmu);
+
 	return smmu;
 }
diff --git a/drivers/iommu/arm-smmu-qcom.c b/drivers/iommu/arm-smmu-qcom.c
new file mode 100644
index 000000000000..24c071c1d8b0
--- /dev/null
+++ b/drivers/iommu/arm-smmu-qcom.c
@@ -0,0 +1,51 @@ 
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ */
+
+#include <linux/qcom_scm.h>
+
+#include "arm-smmu.h"
+
+struct qcom_smmu {
+	struct arm_smmu_device smmu;
+};
+
+static int qcom_sdm845_smmu500_reset(struct arm_smmu_device *smmu)
+{
+	int ret;
+
+	arm_mmu500_reset(smmu);
+
+	/*
+	 * To address performance degradation in non-real time clients,
+	 * such as USB and UFS, turn off wait-for-safe on sdm845 based boards,
+	 * such as MTP and db845, whose firmwares implement secure monitor
+	 * call handlers to turn on/off the wait-for-safe logic.
+	 */
+	ret = qcom_scm_qsmmu500_wait_safe_toggle(0);
+	if (ret)
+		dev_warn(smmu->dev, "Failed to turn off SAFE logic\n");
+
+	return ret;
+}
+
+static const struct arm_smmu_impl qcom_smmu_impl = {
+	.reset = qcom_sdm845_smmu500_reset,
+};
+
+struct arm_smmu_device *qcom_smmu_impl_init(struct arm_smmu_device *smmu)
+{
+	struct qcom_smmu *qsmmu;
+
+	qsmmu = devm_kzalloc(smmu->dev, sizeof(*qsmmu), GFP_KERNEL);
+	if (!qsmmu)
+		return ERR_PTR(-ENOMEM);
+
+	qsmmu->smmu = *smmu;
+
+	qsmmu->smmu.impl = &qcom_smmu_impl;
+	devm_kfree(smmu->dev, smmu);
+
+	return &qsmmu->smmu;
+}
diff --git a/drivers/iommu/arm-smmu.h b/drivers/iommu/arm-smmu.h
index ac9eac966cf5..4bc9e853c95d 100644
--- a/drivers/iommu/arm-smmu.h
+++ b/drivers/iommu/arm-smmu.h
@@ -391,5 +391,8 @@  static inline void arm_smmu_writeq(struct arm_smmu_device *smmu, int page,
 	arm_smmu_writeq((s), ARM_SMMU_CB((s), (n)), (o), (v))
 
 struct arm_smmu_device *arm_smmu_impl_init(struct arm_smmu_device *smmu);
+struct arm_smmu_device *qcom_smmu_impl_init(struct arm_smmu_device *smmu);
+
+int arm_mmu500_reset(struct arm_smmu_device *smmu);
 
 #endif /* _ARM_SMMU_H */