Message ID | 20230327-tegra-pmic-reboot-v3-2-3c0ee3567e14@skidata.com |
---|---|
State | Superseded |
Headers | show |
Series | mfd: tps6586x: register restart handler | expand |
> - return system_state > SYSTEM_RUNNING && irqs_disabled(); > + return system_state > SYSTEM_RUNNING && !preemptible(); For the !CONFIG_PREEMPT_COUNT case, preemptible() is defined 0. So, don't we lose the irqs_disabled() check in that case?
On Mon, Mar 27, 2023 at 06:23:24PM +0200, Benjamin Bara wrote: > On Mon, 27 Mar 2023 at 16:54, Wolfram Sang <wsa@kernel.org> wrote: > > For the !CONFIG_PREEMPT_COUNT case, preemptible() is defined 0. So, > > don't we lose the irqs_disabled() check in that case? > > Thanks for the feedback! > PREEMPT_COUNT is selected by PREEMPTION, so I guess in the case of > !PREEMPT_COUNT, > we should be atomic (anyways)? Could you make sure please? Asking Peter Zijlstra might be a good idea. He helped me with the current implementation.
On Wed, 29 Mar 2023 at 21:50, Wolfram Sang <wsa@kernel.org> wrote:
> Could you make sure please?
Sure, I'll try. The check before bae1d3a was:
in_atomic() || irqs_disabled()
which boils down to:
(preempt_count() != 0) || irqs_disabled()
preemptible() is defined as:
(preempt_count() == 0 && !irqs_disabled())
so this patch should behave the same as pre-v5.2, but with the
additional system state check. From my point of view, the additional
value of the in_atomic() check was that it activated atomic i2c xfers
when preemption is disabled, like in the case of panic(). So reverting
that commit would also re-activate atomic i2c transfers during emergency
restarts. However, I think considering the system state makes sense
here.
On Sun, Apr 02, 2023 at 12:04:48PM +0200, Benjamin Bara wrote: > On Wed, 29 Mar 2023 at 21:50, Wolfram Sang <wsa@kernel.org> wrote: > > Could you make sure please? > > Sure, I'll try. The check before bae1d3a was: > in_atomic() || irqs_disabled() > which boils down to: > (preempt_count() != 0) || irqs_disabled() > preemptible() is defined as: > (preempt_count() == 0 && !irqs_disabled()) > > so this patch should behave the same as pre-v5.2, but with the > additional system state check. From my point of view, the additional > value of the in_atomic() check was that it activated atomic i2c xfers > when preemption is disabled, like in the case of panic(). So reverting > that commit would also re-activate atomic i2c transfers during emergency > restarts. However, I think considering the system state makes sense > here. > > From my understanding, non-atomic i2c transfers require enabled IRQs, > but atomic i2c transfers do not have any "requirements". So the > irqs_disabled() check is not here to ensure that the following atomic > i2c transfer works correctly, but to use non-atomic i2c xfer as > long/often as possible. > > Unfortunately, I am not sure yet about !CONFIG_PREEMPTION. I looked into > some i2c-bus implementations which implement both, atomic and > non-atomic. As far as I saw, the basic difference is that the non-atomic > variants usually utilize the DMA and then call a variant of > wait_for_completion(), like in i2c_imx_dma_write() [1]. However, the > documentation of wait_for_completion [2] states that: > "wait_for_completion() and its variants are only safe in process context > (as they can sleep) but not (...) [if] preemption is disabled". > Therefore, I am not quite sure yet if !CONFIG_PREEMPTION uses the > non-atomic variant at all or if this case is handled differently. > > > Asking Peter Zijlstra might be a good idea. > > He helped me with the current implementation. > > Thanks for the hint! I wrote an extra email to him and added him to CC. So yeah, can't call schedule() if non preemptible (which is either preempt_disable(), local_bh_disable() (true for bh handlers) or local_irq_disable() (true for IRQ handlers) and mostly rcu_read_lock()). You can mostly forget about CONFIG_PREEMPT=n (or more specifically CONFIG_PREMPT_COUNT=n) things that work for PREEMPT typically also work for !PREEMPT. The question here seems to be if i2c_in_atomic_xfer_mode() should have an in_atomic() / !preemptible() check, right? IIUC Wolfram doesn't like it being used outside of extra special cicumstances?
On Tue, 4 Apr 2023 at 10:23, Peter Zijlstra <peterz@infradead.org> wrote: > You can mostly forget about CONFIG_PREEMPT=n (or more specifically > CONFIG_PREMPT_COUNT=n) things that work for PREEMPT typically also work > for !PREEMPT. Thanks for the clarification! > The question here seems to be if i2c_in_atomic_xfer_mode() should have > an in_atomic() / !preemptible() check, right? IIUC Wolfram doesn't like > it being used outside of extra special cicumstances? Sorry for expressing things more complicated than needed. Yes, exactly. Wolfram expressed considerations of adding preemptible() as check, as the now existing irq_disabled() check is lost with !PREEMPT. I tried to clarify that the check seems to be there for "performance reasons" and that the check essentially was !preemptible() before v5.2, so nothing should break. However, what came to my mind during my "research", is that it might make sense to handle all i2c transfers atomically when in a post RUNNING state (namely HALT, POWER_OFF, RESTART, SUSPEND). The outcome would basically be the same as with this patch series applied, but I guess the reasoning behind it would be simplified: If in a restart handler, the i2c transfer is atomic, independent of current IRQ or preemption state. Currently, the state depends on from where the handler is triggered. As you have stated, most of the i2c transfers in the mentioned states will just update single bits for power-off/sleep/suspend, so IMHO nothing where not using a DMA would matter from a performance point of view. But there might be other reasons for not doing so - I guess in this case the provided patch is fine (at least from my side).
diff --git a/drivers/i2c/i2c-core.h b/drivers/i2c/i2c-core.h index 1247e6e6e975..05b8b8dfa9bd 100644 --- a/drivers/i2c/i2c-core.h +++ b/drivers/i2c/i2c-core.h @@ -29,7 +29,7 @@ int i2c_dev_irq_from_resources(const struct resource *resources, */ static inline bool i2c_in_atomic_xfer_mode(void) { - return system_state > SYSTEM_RUNNING && irqs_disabled(); + return system_state > SYSTEM_RUNNING && !preemptible(); } static inline int __i2c_lock_bus_helper(struct i2c_adapter *adap)