iommu/arm-smmu: Add support for not removing SMMU power votes

The SMMU driver will vote for the resources it needs before performing
a particular operation, and will remove its votes after the operation
is complete.

When power resources are not currently enabled by other drivers,
the SMMU driver's requests to enable its devices' power resources
go through the slow paths where the hardware power resources
get turned on. So, in a scenario where the SMMU driver is constantly
performing work and having to toggle the state of the power resources,
the SMMU driver operations take more time.

On GKI, the upstream implementation of the IOMMU page table management
code is used, which doesn't have the optimizations we have downstream,
which improve the performance of the SMMU driver when unmapping memory.

The GPU can go into slumber if it is not active, and can relinquish its
votes for the power resources that the SMMU driver votes for when
unmapping memory. This requires the SMMU driver to take the slowpath
of enabling all of these power resources and then disabling them
on every call to unmap memory, which can incur a considerable amount
of delay.

This delay, along with the usage of the unoptimized IOMMU page table
management code in GKI results in slow unmap calls.

Thus, add support for the SMMU driver to never remove its power votes,
so that it doesn't have to spend time voting for power resources while
it is operating.

Change-Id: Id93aafef18f69e377391875e2a7b340b34b4b3e8
Signed-off-by: Isaac J. Manjarres <isaacm@codeaurora.org>
This commit is contained in:
Isaac J. Manjarres 2020-11-05 11:29:45 -08:00
commit 8ffa6450ba
2 changed files with 39 additions and 0 deletions

View file

@ -548,6 +548,18 @@ config ARM_SMMU_SKIP_MAP_POWER_ON
If unsure, say N here.
config ARM_SMMU_POWER_ALWAYS_ON
bool "Never remove SMMU power resource votes"
depends on ARM_SMMU && !QGKI
help
Support for never removing SMMU power resource votes (i.e.
regulator, clocks, and interconnect votes). Never removing the
power resource votes allows for less time to be spent by the SMMU
driver in voting for power resources when it is actively working for
an extended period of time.
If unsure, say N here.
config ARM_SMMU_V3
tristate "ARM Ltd. System MMU Version 3 (SMMUv3) Support"
depends on ARM64

View file

@ -5049,6 +5049,28 @@ static int arm_smmu_device_dt_probe(struct platform_device *pdev)
arm_smmu_interrupt_selftest(smmu);
arm_smmu_power_off(smmu, smmu->pwr);
/*
* On GKI, we use the upstream implementation of the IOMMU page table
* management code, which lacks all of the optimizations that we have
* downstream to speed up calls into the SMMU driver to unmap memory.
*
* When the GPU goes into slumber, it relinquishes its votes for
* the regulators and clocks that the SMMU driver votes for. This
* means that when the SMMU driver adds/removes votes for the
* power resources required to access the GPU SMMU registers for
* TLB invalidations while unmapping memory, the SMMU driver has to
* wait for the resources to actually turn on/off, which incurs a
* considerable amount of delay.
*
* This delay, coupled with the use of the unoptimized IOMMU page table
* management code in GKI results in slow unmap calls. To alleviate
* that, we can remove the latency incurred by enabling/disabling the
* power resources, by always keeping them on.
*/
if (IS_ENABLED(CONFIG_ARM_SMMU_POWER_ALWAYS_ON) &&
of_property_read_bool(dev->of_node, "qcom,power-always-on"))
arm_smmu_power_on(smmu->pwr);
/*
* We want to avoid touching dev->power.lock in fastpaths unless
* it's really going to do something useful - pm_runtime_enabled()
@ -5104,6 +5126,11 @@ static int arm_smmu_device_remove(struct platform_device *pdev)
arm_smmu_gr0_write(smmu, ARM_SMMU_GR0_sCR0, sCR0_CLIENTPD);
arm_smmu_power_off(smmu, smmu->pwr);
/* Remove the extra reference that was taken in the probe function */
if (IS_ENABLED(CONFIG_ARM_SMMU_POWER_ALWAYS_ON) &&
of_property_read_bool(pdev->dev.of_node, "qcom,power-always-on"))
arm_smmu_power_off(smmu, smmu->pwr);
arm_smmu_exit_power_resources(smmu->pwr);
return 0;