Skip to content

Commit 3fc7c5c

Browse files
Marc Zyngierolofj
authored andcommitted
iommu/rockchip: Handle errors returned from PM framework
pm_runtime_get_if_in_use can fail: either PM has been disabled altogether (-EINVAL), or the device hasn't been enabled yet (0). Sadly, the Rockchip IOMMU driver tends to conflate the two things by considering a non-zero return value as successful. This has the consequence of hiding other bugs, so let's handle this case throughout the driver, with a WARN_ON_ONCE so that we can try and work out what happened. Fixes: 0f181d3 ("iommu/rockchip: Add runtime PM support") Reviewed-by: Heiko Stuebner <heiko@sntech.de> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com> Signed-off-by: Olof Johansson <olof@lixom.net>
1 parent 7db7a8f commit 3fc7c5c

File tree

1 file changed

+15
-6
lines changed

1 file changed

+15
-6
lines changed

drivers/iommu/rockchip-iommu.c

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -521,10 +521,11 @@ static irqreturn_t rk_iommu_irq(int irq, void *dev_id)
521521
u32 int_status;
522522
dma_addr_t iova;
523523
irqreturn_t ret = IRQ_NONE;
524-
int i;
524+
int i, err;
525525

526-
if (WARN_ON(!pm_runtime_get_if_in_use(iommu->dev)))
527-
return 0;
526+
err = pm_runtime_get_if_in_use(iommu->dev);
527+
if (WARN_ON_ONCE(err <= 0))
528+
return ret;
528529

529530
if (WARN_ON(clk_bulk_enable(iommu->num_clocks, iommu->clocks)))
530531
goto out;
@@ -620,11 +621,15 @@ static void rk_iommu_zap_iova(struct rk_iommu_domain *rk_domain,
620621
spin_lock_irqsave(&rk_domain->iommus_lock, flags);
621622
list_for_each(pos, &rk_domain->iommus) {
622623
struct rk_iommu *iommu;
624+
int ret;
623625

624626
iommu = list_entry(pos, struct rk_iommu, node);
625627

626628
/* Only zap TLBs of IOMMUs that are powered on. */
627-
if (pm_runtime_get_if_in_use(iommu->dev)) {
629+
ret = pm_runtime_get_if_in_use(iommu->dev);
630+
if (WARN_ON_ONCE(ret < 0))
631+
continue;
632+
if (ret) {
628633
WARN_ON(clk_bulk_enable(iommu->num_clocks,
629634
iommu->clocks));
630635
rk_iommu_zap_lines(iommu, iova, size);
@@ -891,6 +896,7 @@ static void rk_iommu_detach_device(struct iommu_domain *domain,
891896
struct rk_iommu *iommu;
892897
struct rk_iommu_domain *rk_domain = to_rk_domain(domain);
893898
unsigned long flags;
899+
int ret;
894900

895901
/* Allow 'virtual devices' (eg drm) to detach from domain */
896902
iommu = rk_iommu_from_dev(dev);
@@ -909,7 +915,9 @@ static void rk_iommu_detach_device(struct iommu_domain *domain,
909915
list_del_init(&iommu->node);
910916
spin_unlock_irqrestore(&rk_domain->iommus_lock, flags);
911917

912-
if (pm_runtime_get_if_in_use(iommu->dev)) {
918+
ret = pm_runtime_get_if_in_use(iommu->dev);
919+
WARN_ON_ONCE(ret < 0);
920+
if (ret > 0) {
913921
rk_iommu_disable(iommu);
914922
pm_runtime_put(iommu->dev);
915923
}
@@ -946,7 +954,8 @@ static int rk_iommu_attach_device(struct iommu_domain *domain,
946954
list_add_tail(&iommu->node, &rk_domain->iommus);
947955
spin_unlock_irqrestore(&rk_domain->iommus_lock, flags);
948956

949-
if (!pm_runtime_get_if_in_use(iommu->dev))
957+
ret = pm_runtime_get_if_in_use(iommu->dev);
958+
if (!ret || WARN_ON_ONCE(ret < 0))
950959
return 0;
951960

952961
ret = rk_iommu_enable(iommu);

0 commit comments

Comments
 (0)