The Linux Kernel Mailing List
 help / color / mirror / Atom feed
From: Mathias Nyman <mathias.nyman@linux.intel.com>
To: Yang Zi <2959243019@qq.com>,
	mathias.nyman@intel.com, gregkh@linuxfoundation.org
Cc: linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: Re: [PATCH] usb: xhci: Fix lockdep warning when entering test mode
Date: Tue, 25 Aug 2026 14:29:22 +0300	[thread overview]
Message-ID: <3d38c703-8d10-4017-812a-cf6b335ef496@linux.intel.com> (raw)
In-Reply-To: <tencent_0F874E79839C91CD14A58265BF7B6D89850A@qq.com>

On 8/25/26 12:09, Yang Zi wrote:
> xhci_enter_test_mode() and xhci_set_port_power() are annotated
> __must_hold(&xhci->lock), yet both drop the lock in the middle of the
> function: xhci_enter_test_mode() around the slot-disable loop (because
> xhci_disable_and_free_slot() takes the lock itself and can sleep) and
> xhci_set_port_power() around the ACPI power-state calls.
> 
> xhci->lock is also taken from hardirq context in xhci_irq(), so it is a
> hardirq-safe lock.  Dropping it with spin_unlock_irqrestore() re-enables
> interrupts while the lock is still held, and lockdep's
> trace_hardirqs_on() -> mark_held_locks() then records the lock as
> HARDIRQ-ON-W, which conflicts with the IN-HARDIRQ-W usage registered by
> xhci_irq():
> 
>      inconsistent {IN-HARDIRQ-W} -> {HARDIRQ-ON-W} usage.
> 

This sounds odd, shouldn't spin_unlock_irqresore() first release the
spinlock and then enable interrupts?

Wouldn't this be an issue for every driver that shares a spinlock
in interrupt context and elsewhere?

spinlock_api_smp.h has:

static inline void __raw_spin_unlock_irqrestore(raw_spinlock_t *lock,
unsigned long flags)
	__releases(lock)
{
         spin_release(&lock->dep_map, _RET_IP_);
         do_raw_spin_unlock(lock);
	local_irq_restore(flags);
         preempt_enable();
}


To be fair it looks odd on a uniprocessor system:

spinlock_api_up.h:

#define __UNLOCK_IRQRESTORE(lock, flags, ...) \
   do { local_irq_restore(flags); __UNLOCK(lock, ##__VA_ARGS__); } while (0)

Are you running this on a single processor system?

> Fix this by releasing the lock *before* re-enabling interrupts (and, on
> the way back, disabling interrupts before re-acquiring the lock), so the
> hardirq-safe lock is never held with IRQs enabled.  Also drop the
> incorrect __must_hold() annotations and pass the saved IRQ state by
> value so these helpers cannot clobber the caller's flags.
> 
> This patch is tentative and needs maintainer review.
> 
> Signed-off-by: Yang Zi <2959243019@qq.com>
> ---
> diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c
> index b0264bd8577a..c28d278f45b0 100644
> --- a/drivers/usb/host/xhci-hub.c
> +++ b/drivers/usb/host/xhci-hub.c
> @@ -638,12 +638,19 @@ struct xhci_hub *xhci_get_rhub(struct usb_hcd *hcd)
>   
>   /*
>    * xhci_set_port_power() must be called with xhci->lock held.
> - * It will release and re-acquire the lock while calling ACPI
> - * method.
> + * It drops the lock while calling the ACPI method, which may sleep, and
> + * re-acquires it before returning.
> + *
> + * The lock is released *before* interrupts are re-enabled because
> + * xhci->lock is also taken in hardirq context (xhci_irq()) and must never
> + * be held with IRQs enabled.
> + *
> + * @flags is passed by value: it is the IRQ state saved by the caller's
> + * spin_lock_irqsave() and must not be clobbered by the lock/irqsave dance
> + * below, so the caller can later restore it with spin_unlock_irqrestore().

The caller should restore it to the flags value set during latest spin_lock_irqsave()
which is during the lock/irqsace dance.

Thanks
Mathias


      reply	other threads:[~2026-08-25 11:29 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-25  9:09 [PATCH] usb: xhci: Fix lockdep warning when entering test mode Yang Zi
2026-08-25 11:29 ` Mathias Nyman [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=3d38c703-8d10-4017-812a-cf6b335ef496@linux.intel.com \
    --to=mathias.nyman@linux.intel.com \
    --cc=2959243019@qq.com \
    --cc=gregkh@linuxfoundation.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-usb@vger.kernel.org \
    --cc=mathias.nyman@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox