All of lore.kernel.org
 help / color / mirror / Atom feed
From: Guenter Roeck <linux@roeck-us.net>
To: Xu Yang <xu.yang_2@nxp.com>
Cc: jun.li@nxp.com, heikki.krogerus@linux.intel.com,
	gregkh@linuxfoundation.org, linux-usb@vger.kernel.org,
	linux-imx@nxp.com
Subject: Re: [PATCH 2/2] usb: typec: tcpm: Don't handle two continuous same state
Date: Tue, 24 Aug 2021 09:41:27 -0700	[thread overview]
Message-ID: <20669608-3cef-69bb-6668-b110d91011a8@roeck-us.net> (raw)
In-Reply-To: <20210824113014.1420117-2-xu.yang_2@nxp.com>

On 8/24/21 4:30 AM, Xu Yang wrote:
> When two tcpm_set_state are successively executed in non-worker context,
> such as tcpm_init, an abnormal sequence may be exist which causes two
> continuous same state to be handled.
> 
> tcpm_init:
> [    1.686293] CC1: 0 -> 0, CC2: 0 -> 0 [state SNK_UNATTACHED, polarity 0, disconnected]
> [    1.686300] state change SNK_UNATTACHED -> PORT_RESET [rev1 NONE_AMS]
> [    1.686309] 1-0050: registered
> [    1.686315] Setting usb_comm capable false
> [    1.687417] Setting voltage/current limit 0 mV 0 mA
> [    1.687425] polarity 0
> [    1.690709] Requesting mux state 0, usb-role 0, orientation 0
> [    1.691599] cc:=0
> [    1.691871] pending state change PORT_RESET -> PORT_RESET_WAIT_OFF @ 100 ms [rev1 NONE_AMS]
> [    1.691880] Setting usb_comm capable false
> [    1.692973] Setting voltage/current limit 0 mV 0 mA
> [    1.692980] polarity 0
> [    1.696843] Requesting mux state 0, usb-role 0, orientation 0
> [    1.697729] cc:=0
> [    1.697994] pending state change PORT_RESET -> PORT_RESET_WAIT_OFF @ 100 ms [rev1 NONE_AMS]
> 
> abnormal sequence:
>              [tcpm_init]                 [tcpm_state_machine_work]
> 1       tcpm_set_state(A)
> 2           port->state = A
> 3           kthread_queue_work
> 4           queue work to worker_list
> 5                                       dequeue work from worker_list
> 6       tcpm_set_state(B)
> 7           port->state = B
> 8           kthread_queue_work
> 9           queue work to worker_list
> 10                                      tcpm_state_machine_work(B)
> 11                                      port->state not change
> 12                                      dequeue work from worker_list
> 13                                      tcpm_state_machine_work(B)
> 
> state B is handled twice.
> 
> Fixes: 4b4e02c83167 ("typec: tcpm: Move out of staging")
> cc: <stable@vger.kernel.org>
> Signed-off-by: Xu Yang <xu.yang_2@nxp.com>
> 
> diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c
> index 4bdf119b1306..e0a319e00b12 100644
> --- a/drivers/usb/typec/tcpm/tcpm.c
> +++ b/drivers/usb/typec/tcpm/tcpm.c
> @@ -4825,6 +4825,10 @@ static void tcpm_state_machine_work(struct kthread_work *work)
>   		port->delayed_state = INVALID_STATE;
>   	}
>   
> +	/* If target state is the same as the last entered state, skip it */
> +	if (port->enter_state == port->state)
> +		goto done;
> +

I don't think that really solves the problem; it looks more like a bandage around
a race condition between setting a state in one context and executing the state
machine in another. I think it would be better to solve the underlying race condition.

The problem is ultimately that tcpm_init() ends up calling tcpm_set_state() several
times, the last time being PORT_RESET. The worker starts running and waits for the
port lock to be released. Since the worker is already running, but state_machine_running
is not yet set, tcpm_set_state() triggers it again. Maybe we need a second flag to detect
and handle that situation, or a better means to determine if the worker is running.

Guenter

  reply	other threads:[~2021-08-24 16:41 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-08-24 11:30 [PATCH 1/2] usb: typec: tcpm: Fix up tcpm set delayed state which may not delay Xu Yang
2021-08-24 11:30 ` [PATCH 2/2] usb: typec: tcpm: Don't handle two continuous same state Xu Yang
2021-08-24 16:41   ` Guenter Roeck [this message]
2021-08-24 16:56 ` [PATCH 1/2] usb: typec: tcpm: Fix up tcpm set delayed state which may not delay Guenter Roeck

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=20669608-3cef-69bb-6668-b110d91011a8@roeck-us.net \
    --to=linux@roeck-us.net \
    --cc=gregkh@linuxfoundation.org \
    --cc=heikki.krogerus@linux.intel.com \
    --cc=jun.li@nxp.com \
    --cc=linux-imx@nxp.com \
    --cc=linux-usb@vger.kernel.org \
    --cc=xu.yang_2@nxp.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.