On Tue, 2020-08-25 at 21:30 +0300, Abel Vesa wrote: [...] > > if (assert) > > pm_runtime_get_sync(); > > spin_lock_irqsave(); > > /* ... */ > > spin_unlock_irqrestore(); > > if (assert && asserted_before) > > pm_runtime_put(); > > > > On a second thought this doesn't work because, for the first assertion, > the runtime put will never be called, if the asserted_before does not count > the current assertion.
I'm not sure I follow. The first assert will increment device usage 0 -> 1, all others asserts will just temporarily increment and decrement 1 -> 2 -> 1. Isn't this just missing one if (!assert && !asserted_after) pm_runtime_put() to do the last deassert 1 -> 0 transition? > If it counts the current assertion, then every assertion > will end with runtime put. None of these options work here. > > How about the following: > > if (assert && !test_and_set_bit(1, &drvdata->rst_hws[id].asserted)) > pm_runtime_get_sync(rcdev->dev); > > spin_lock_irqsave(&drvdata->lock, flags); > > reg = readl(reg_addr); > if (assert) > writel(reg & ~(mask << shift), reg_addr); > else > writel(reg | (mask << shift), reg_addr); > > spin_unlock_irqrestore(&drvdata->lock, flags); > > if (!assert && test_and_clear_bit(1, &drvdata->rst_hws[id].asserted)) > pm_runtime_put(rcdev->dev); > > This would only call the get_sync/put once for each reset bit. Yes, that should work. I think it is a much better idea, no more looping through the entire reset control array. regards Philipp