On 3/15/25 1:46 AM, Avri Altman wrote:
Shouldn't you now call for reinit_completion now? before wait_for_dev? Or at ufshcd_dev_cmd_completion ?
complete() increments the counter in struct completion and wait_for_complete() decrements it, isn't it? From kernel/sched/completion.c: void complete(struct completion *x) { complete_with_flags(x, 0); } EXPORT_SYMBOL(complete); static void complete_with_flags(struct completion *x, int wake_flags) { unsigned long flags; raw_spin_lock_irqsave(&x->wait.lock, flags); if (x->done != UINT_MAX) x->done++; swake_up_locked(&x->wait, wake_flags); raw_spin_unlock_irqrestore(&x->wait.lock, flags); } As one can see complete() increments x->done if it is less than UINT_MAX, which should be the case in the UFS driver. From the same file: void __sched wait_for_completion(struct completion *x) { wait_for_common(x, MAX_SCHEDULE_TIMEOUT, TASK_UNINTERRUPTIBLE); } EXPORT_SYMBOL(wait_for_completion); static long __sched wait_for_common(struct completion *x, long timeout, int state) { return __wait_for_common(x, schedule_timeout, timeout, state); } static inline long __sched __wait_for_common(struct completion *x, long (*action)(long), long timeout, int state) { might_sleep(); complete_acquire(x); raw_spin_lock_irq(&x->wait.lock); timeout = do_wait_for_common(x, action, timeout, state); raw_spin_unlock_irq(&x->wait.lock); complete_release(x); return timeout; } static inline long __sched do_wait_for_common(struct completion *x, long (*action)(long), long timeout, int state) { if (!x->done) { DECLARE_SWAITQUEUE(wait); do { if (signal_pending_state(state, current)) { timeout = -ERESTARTSYS; break; } __prepare_to_swait(&x->wait, &wait); __set_current_state(state); raw_spin_unlock_irq(&x->wait.lock); timeout = action(timeout); raw_spin_lock_irq(&x->wait.lock); } while (!x->done && timeout); __finish_swait(&x->wait, &wait); if (!x->done) return timeout; } if (x->done != UINT_MAX) x->done--; return timeout ?: 1; } If I read the above code correctly, it waits until x->done != 0 or the timeout has been reached. x->done is decremented if a strictly positive value is returned. do_wait_for_common() ignores pending signals because state == TASK_UNINTERRUPTIBLE. Bart.