All of lore.kernel.org
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Yaohan Li" <shunsheng1218@gmail.com>
Cc: linux-usb@vger.kernel.org
Subject: Re: [PATCH v4] usb: typec: tcpci: acknowledge masked alerts and quiesce the IRQ
Date: Fri, 13 Nov 2026 09:14:30 +0000	[thread overview]
Message-ID: <sashiko-outbox-212527@kernel.org> (raw)
In-Reply-To: <20261113084928.211885-1-shunsheng1218@gmail.com>

Thank you for your contribution! Sashiko AI review found 1 potential
issue to consider:
- [Medium] usb: typec: tcpci: race in tcpci_irq() with
  tcpci_quiesce_alerts() skips alert ack
--

commit b4f078603381d8a805defdf53c50acdc29717943
Author: Yaohan Li <shunsheng1218@gmail.com>

usb: typec: tcpci: acknowledge masked alerts and quiesce the IRQ

This commit acknowledges all non-RX_STATUS alert bits before filtering
against the software alert_mask, and quiesces and synchronizes the IRQ
during teardown and probe error cleanup before unregistering the TCPM
port.

> diff --git a/drivers/usb/typec/tcpm/tcpci.c b/drivers/usb/typec/tcpm/tcpci.c
> index c6165466c54b6..b11c30e67055f 100644
> --- a/drivers/usb/typec/tcpm/tcpci.c
> +++ b/drivers/usb/typec/tcpm/tcpci.c

[ ... ]

> @@ -648,10 +650,21 @@ static bool tcpci_attempt_vconn_swap_discovery(struct tcpc_dev *tcpc)
>  	return false;
>  }
>  
> +static void tcpci_quiesce_alerts(struct tcpci *tcpci)
> +{
> +	unsigned long flags;
> +
> +	spin_lock_irqsave(&tcpci->alert_mask_lock, flags);
> +	tcpci->alerts_quiesced = true;
> +	WRITE_ONCE(tcpci->alert_mask, 0);
> +	spin_unlock_irqrestore(&tcpci->alert_mask_lock, flags);
> +}

[ ... ]

> @@ -710,29 +723,60 @@ static int tcpci_init(struct tcpc_dev *tcpc)

[ ... ]

>  irqreturn_t tcpci_irq(struct tcpci *tcpci)
>  {
> -	u16 status;
> +	u16 status = 0;
>  	int ret;
> -	int irq_ret;
> +	int irq_ret = 0;
>  	unsigned int raw;
>  
> -	tcpci_read16(tcpci, TCPC_ALERT, &status);
> -	irq_ret = status & tcpci->alert_mask;
> +	/*
> +	 * During teardown, acknowledge a latched alert without dispatching
> +	 * it to TCPM.  A level-triggered Alert# must not keep retriggering
> +	 * after the software mask was cleared or the hardware mask write
> +	 * failed; the port may already be going away.
> +	 */
> +	if (READ_ONCE(tcpci->alerts_quiesced)) {
> +		ret = tcpci_read16(tcpci, TCPC_ALERT, &status);
> +		if (ret < 0)
> +			return IRQ_NONE;
> +		if (status) {
> +			ret = tcpci_write16(tcpci, TCPC_ALERT, status);
> +			if (ret < 0)
> +				return IRQ_HANDLED;
> +			irq_ret = 1;
> +		}
> +		return IRQ_RETVAL(irq_ret);
> +	}
> +
> +	if (!READ_ONCE(tcpci->alert_mask))
> +		return IRQ_NONE;
>  
> -process_status:
>  	/*
> -	 * Clear alert status for everything except RX_STATUS, which shouldn't
> -	 * be cleared until we have successfully retrieved message.
> +	 * Acknowledge every non-RX_STATUS bit from the raw alert value, not
> +	 * only the bits enabled in the software mask.  Some controllers
> +	 * enable additional alerts in TCPC_ALERT_MASK (for example RT1711H
> +	 * enables FAULT and RX_BUF_OVF); dropping those bits before the
> +	 * write would leave a level-triggered Alert# asserted.  RX_STATUS is
> +	 * cleared only after the message has been read successfully.
>  	 */
> +	tcpci_read16(tcpci, TCPC_ALERT, &status);
>  	if (status & ~TCPC_ALERT_RX_STATUS)
>  		tcpci_write16(tcpci, TCPC_ALERT,
>  			      status & ~TCPC_ALERT_RX_STATUS);
> +	irq_ret = status;
> +
> +	status &= READ_ONCE(tcpci->alert_mask);
> +
> +process_status:

[ ... ]

> @@ -806,8 +850,13 @@ irqreturn_t tcpci_irq(struct tcpci *tcpci)
>  		tcpm_pd_transmit_complete(tcpci->port, TCPC_TX_FAILED);
>  
>  	tcpci_read16(tcpci, TCPC_ALERT, &status);
> +	if (status & ~TCPC_ALERT_RX_STATUS)
> +		tcpci_write16(tcpci, TCPC_ALERT,
> +			      status & ~TCPC_ALERT_RX_STATUS);
> +	irq_ret |= status;
>  
> -	if (status & tcpci->alert_mask)
> +	status &= READ_ONCE(tcpci->alert_mask);
> +	if (status)
>  		goto process_status;
>  
>  	return IRQ_RETVAL(irq_ret);

[Severity: Medium]
Can tcpci_irq() race with tcpci_quiesce_alerts() and return without
acknowledging TCPC_ALERT?

CPU0                              CPU1
tcpci_irq()
  READ_ONCE(tcpci->alerts_quiesced)
    -> false
                                  tcpci_remove()
                                    tcpci_quiesce_alerts()
                                      tcpci->alerts_quiesced = true;
                                      WRITE_ONCE(tcpci->alert_mask, 0);
  if (!READ_ONCE(tcpci->alert_mask))
    return IRQ_NONE;              <-- skips TCPC_ALERT read and ack

Because tcpci_irq() reads tcpci->alerts_quiesced and tcpci->alert_mask
in separate unlocked steps, a concurrent tcpci_quiesce_alerts() can zero
tcpci->alert_mask after the quiesced check has already passed.

A second window exists just below and in the loop tail before jumping to
process_status: if tcpci_irq() reads TCPC_ALERT with TCPC_ALERT_RX_STATUS
set, the upfront write clears only status & ~TCPC_ALERT_RX_STATUS, and if
tcpci_quiesce_alerts() zeroes tcpci->alert_mask before
status &= READ_ONCE(tcpci->alert_mask), TCPC_ALERT_RX_STATUS is masked
out and never cleared in the RX handler.  Similarly, if tcpci_init()
fails before publishing tcpci->alert_mask (tcpm_init() ignores the
return value of port->tcpc->init()), tcpci->alert_mask remains 0 and
tcpci_irq() returns IRQ_NONE without acknowledging hardware alerts on
subdrivers such as tcpci_rt1711h that program TCPC_ALERT_MASK
independently.  In all of these cases, a latched alert can keep a
level-triggered Alert# line asserted and cause an interrupt storm or
spurious IRQ disablement.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261113084928.211885-1-shunsheng1218@gmail.com?part=1

      reply	other threads:[~2026-11-13  9:14 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-13  8:49 [PATCH v4] usb: typec: tcpci: acknowledge masked alerts and quiesce the IRQ Yaohan Li
2026-11-13  9:14 ` sashiko-bot [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=sashiko-outbox-212527@kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=linux-usb@vger.kernel.org \
    --cc=sashiko-reviews@lists.linux.dev \
    --cc=shunsheng1218@gmail.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.