RE: [PATCH 5/5] usb: typec: ucsi: Clear UCSI_CCI_RESET_COMPLETE before reset

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Christian,

> -----Original Message-----
> From: Christian A. Ehrhardt <lk@xxxxxxx>
> Sent: Tuesday, December 17, 2024 3:17 AM
> To: Sasha Levin <sashal@xxxxxxxxxx>
> Cc: linux-kernel@xxxxxxxxxxxxxxx; Heikki Krogerus
> <heikki.krogerus@xxxxxxxxxxxxxxx>; Greg Kroah-Hartman
> <gregkh@xxxxxxxxxxxxxxxxxxx>; Prashant Malani
> <pmalani@xxxxxxxxxxxx>; Jameson Thies <jthies@xxxxxxxxxx>;
> Abhishek Pandit-Subedi <abhishekpandit@xxxxxxxxxxxx>; Neil
> Armstrong <neil.armstrong@xxxxxxxxxx>; Uwe Kleine-König <u.kleine-
> koenig@xxxxxxxxxxxxxx>; Samuel Čavoj <samuel@xxxxxxxxx>; linux-
> usb@xxxxxxxxxxxxxxx; Kenneth Crudup <kenny@xxxxxxxxx>; Gopal,
> Saranya <saranya.gopal@xxxxxxxxx>
> Subject: Re: [PATCH 5/5] usb: typec: ucsi: Clear
> UCSI_CCI_RESET_COMPLETE before reset
> 
> 
> Hi,
> 
> [ CC: Saranya Gopal <saranya.gopal@xxxxxxxxx> ]
> 
> On Sun, Dec 15, 2024 at 01:34:12PM -0500, Sasha Levin wrote:
> > On Wed, Mar 20, 2024 at 08:39:26AM +0100, Christian A. Ehrhardt
> wrote:
> > > Check the UCSI_CCI_RESET_COMPLETE complete flag before
> starting
> > > another reset. Use a UCSI_SET_NOTIFICATION_ENABLE
> command to clear
> > > the flag if it is set.
> >
> > Hi Christian,
> >
> > It looks like kernelci is able to trigger the warning added by this
> > commit:
> >
> > [   15.988528] WARNING: CPU: 0 PID: 8 at
> drivers/usb/typec/ucsi/ucsi.c:1377 ucsi_reset_ppm+0x1af/0x1c0
> [typec_ucsi]
> > [ ... ]
> 
> I think I can see what's going on.
> 
> First of all: The warning is harmless and UCSI will still work as
> expected (but there is an additional delay during init).
> 
> The trigger for the warning is likely this commit (reviewed by me, so
> ...):
> 
> | commit fa48d7e81624efdf398b990a9049e9cd75a5aead
> | Author: Saranya Gopal <saranya.gopal@xxxxxxxxx>
> | Date:   Fri Aug 30 14:13:42 2024 +0530
> |
> |     usb: typec: ucsi: Do not call ACPI _DSM method for UCSI read
> |     operations
> 
> The (compile tested) diff below should fix it and I can turn this
> into a proper patch but I lost access to test hardware with UCSI,
> thus this would need a "Tested-by:" from someone else before it can
> be included. Maybe Saranya can do this?

I can get access to a couple of systems using UCSI and get this tested tomorrow.

Thanks,
Saranya
> 
>      Best regards   Christian
> 
> 
> commit b44ba223cd840e6dbab6c7f69da6203c7a8ba570
> Author: Christian A. Ehrhardt <lk@xxxxxxx>
> Date:   Mon Dec 16 21:52:46 2024 +0100
> 
>     acpi: typec: ucsi: Introduce a ->poll_cci method
> 
>     For the ACPI backend of UCSI the UCSI "registers" are just
>     a memory copy of the register values in an opregion. The ACPI
>     implementation in the BIOS ensures that the opregion contents
>     are synced to the embedded controller and it ensures that the
>     registers (in particular CCI) are synced back to the opregion
>     on notifications. While there is an ACPI call that syncs the
>     actual registers to the opregion there is rarely a need to do
>     this and on some ACPI implementations it actually breaks in
>     various interesting ways.
> 
>     The only reason to force a sync from the embedded controller
>     is to poll CCI while notifications are disabled. Only the
>     ucsi core knows if this is the case and guessing based on
>     the current command is suboptimal.
> 
>     Thus introduce a ->poll_cci() method that works like
>     ->read_cci() with an additional forced sync and document that
>     this should be used when polling with notifications disabled.
>     For all other backends that presumably don't have this issue
>     use the same implementation for both methods.
> 
>     Fixes: fa48d7e81624 ("usb: typec: ucsi: Do not call ACPI _DSM
> method for UCSI read operations")
>     Signed-off-by: Christian A. Ehrhardt <lk@xxxxxxx>
> 
> diff --git a/drivers/usb/typec/ucsi/ucsi.c
> b/drivers/usb/typec/ucsi/ucsi.c
> index fcf499cc9458..0fe1476f4c29 100644
> --- a/drivers/usb/typec/ucsi/ucsi.c
> +++ b/drivers/usb/typec/ucsi/ucsi.c
> @@ -1346,7 +1346,7 @@ static int ucsi_reset_ppm(struct ucsi *ucsi)
> 
>  	mutex_lock(&ucsi->ppm_lock);
> 
> -	ret = ucsi->ops->read_cci(ucsi, &cci);
> +	ret = ucsi->ops->poll_cci(ucsi, &cci);
>  	if (ret < 0)
>  		goto out;
> 
> @@ -1364,7 +1364,7 @@ static int ucsi_reset_ppm(struct ucsi *ucsi)
> 
>  		tmo = jiffies +
> msecs_to_jiffies(UCSI_TIMEOUT_MS);
>  		do {
> -			ret = ucsi->ops->read_cci(ucsi, &cci);
> +			ret = ucsi->ops->poll_cci(ucsi, &cci);
>  			if (ret < 0)
>  				goto out;
>  			if (cci & UCSI_CCI_COMMAND_COMPLETE)
> @@ -1393,7 +1393,7 @@ static int ucsi_reset_ppm(struct ucsi *ucsi)
>  		/* Give the PPM time to process a reset before
> reading CCI */
>  		msleep(20);
> 
> -		ret = ucsi->ops->read_cci(ucsi, &cci);
> +		ret = ucsi->ops->poll_cci(ucsi, &cci);
>  		if (ret)
>  			goto out;
> 
> @@ -1929,8 +1929,8 @@ struct ucsi *ucsi_create(struct device
> *dev, const struct ucsi_operations *ops)
>  	struct ucsi *ucsi;
> 
>  	if (!ops ||
> -	    !ops->read_version || !ops->read_cci || !ops-
> >read_message_in ||
> -	    !ops->sync_control || !ops->async_control)
> +	    !ops->read_version || !ops->read_cci || !ops->poll_cci ||
> +	    !ops->read_message_in || !ops->sync_control || !ops-
> >async_control)
>  		return ERR_PTR(-EINVAL);
> 
>  	ucsi = kzalloc(sizeof(*ucsi), GFP_KERNEL);
> diff --git a/drivers/usb/typec/ucsi/ucsi.h
> b/drivers/usb/typec/ucsi/ucsi.h
> index 5ff369c24a2f..e4c563da715f 100644
> --- a/drivers/usb/typec/ucsi/ucsi.h
> +++ b/drivers/usb/typec/ucsi/ucsi.h
> @@ -61,6 +61,7 @@ struct dentry;
>   * struct ucsi_operations - UCSI I/O operations
>   * @read_version: Read implemented UCSI version
>   * @read_cci: Read CCI register
> + * @poll_cci: Read CCI register while polling with notifications
> disabled
>   * @read_message_in: Read message data from UCSI
>   * @sync_control: Blocking control operation
>   * @async_control: Non-blocking control operation
> @@ -75,6 +76,7 @@ struct dentry;
>  struct ucsi_operations {
>  	int (*read_version)(struct ucsi *ucsi, u16 *version);
>  	int (*read_cci)(struct ucsi *ucsi, u32 *cci);
> +	int (*poll_cci)(struct ucsi *ucsi, u32 *cci);
>  	int (*read_message_in)(struct ucsi *ucsi, void *val, size_t
> val_len);
>  	int (*sync_control)(struct ucsi *ucsi, u64 command);
>  	int (*async_control)(struct ucsi *ucsi, u64 command);
> diff --git a/drivers/usb/typec/ucsi/ucsi_acpi.c
> b/drivers/usb/typec/ucsi/ucsi_acpi.c
> index 5c5515551963..ac1ebb5d9527 100644
> --- a/drivers/usb/typec/ucsi/ucsi_acpi.c
> +++ b/drivers/usb/typec/ucsi/ucsi_acpi.c
> @@ -59,19 +59,24 @@ static int ucsi_acpi_read_version(struct ucsi
> *ucsi, u16 *version)
>  static int ucsi_acpi_read_cci(struct ucsi *ucsi, u32 *cci)
>  {
>  	struct ucsi_acpi *ua = ucsi_get_drvdata(ucsi);
> -	int ret;
> -
> -	if (UCSI_COMMAND(ua->cmd) == UCSI_PPM_RESET) {
> -		ret = ucsi_acpi_dsm(ua, UCSI_DSM_FUNC_READ);
> -		if (ret)
> -			return ret;
> -	}
> 
>  	memcpy(cci, ua->base + UCSI_CCI, sizeof(*cci));
> 
>  	return 0;
>  }
> 
> +static int ucsi_acpi_poll_cci(struct ucsi *ucsi, u32 *cci)
> +{
> +	struct ucsi_acpi *ua = ucsi_get_drvdata(ucsi);
> +	int ret;
> +
> +	ret = ucsi_acpi_dsm(ua, UCSI_DSM_FUNC_READ);
> +	if (ret)
> +		return ret;
> +
> +	return ucsi_acpi_read_cci(ucsi, cci);
> +}
> +
>  static int ucsi_acpi_read_message_in(struct ucsi *ucsi, void *val,
> size_t val_len)
>  {
>  	struct ucsi_acpi *ua = ucsi_get_drvdata(ucsi);
> @@ -94,6 +99,7 @@ static int ucsi_acpi_async_control(struct ucsi
> *ucsi, u64 command)
>  static const struct ucsi_operations ucsi_acpi_ops = {
>  	.read_version = ucsi_acpi_read_version,
>  	.read_cci = ucsi_acpi_read_cci,
> +	.poll_cci = ucsi_acpi_poll_cci,
>  	.read_message_in = ucsi_acpi_read_message_in,
>  	.sync_control = ucsi_sync_control_common,
>  	.async_control = ucsi_acpi_async_control
> @@ -142,6 +148,7 @@ static int ucsi_gram_sync_control(struct ucsi
> *ucsi, u64 command)
>  static const struct ucsi_operations ucsi_gram_ops = {
>  	.read_version = ucsi_acpi_read_version,
>  	.read_cci = ucsi_acpi_read_cci,
> +	.poll_cci = ucsi_acpi_poll_cci,
>  	.read_message_in = ucsi_gram_read_message_in,
>  	.sync_control = ucsi_gram_sync_control,
>  	.async_control = ucsi_acpi_async_control
> diff --git a/drivers/usb/typec/ucsi/ucsi_ccg.c
> b/drivers/usb/typec/ucsi/ucsi_ccg.c
> index fcb8e61136cf..bb0dc2005c05 100644
> --- a/drivers/usb/typec/ucsi/ucsi_ccg.c
> +++ b/drivers/usb/typec/ucsi/ucsi_ccg.c
> @@ -664,6 +664,7 @@ static int ucsi_ccg_sync_control(struct ucsi
> *ucsi, u64 command)
>  static const struct ucsi_operations ucsi_ccg_ops = {
>  	.read_version = ucsi_ccg_read_version,
>  	.read_cci = ucsi_ccg_read_cci,
> +	.poll_cci = ucsi_ccg_read_cci,
>  	.read_message_in = ucsi_ccg_read_message_in,
>  	.sync_control = ucsi_ccg_sync_control,
>  	.async_control = ucsi_ccg_async_control,
> diff --git a/drivers/usb/typec/ucsi/ucsi_glink.c
> b/drivers/usb/typec/ucsi/ucsi_glink.c
> index 90948cd6d297..a78e53480875 100644
> --- a/drivers/usb/typec/ucsi/ucsi_glink.c
> +++ b/drivers/usb/typec/ucsi/ucsi_glink.c
> @@ -201,6 +201,7 @@ static void
> pmic_glink_ucsi_connector_status(struct ucsi_connector *con)
>  static const struct ucsi_operations pmic_glink_ucsi_ops = {
>  	.read_version = pmic_glink_ucsi_read_version,
>  	.read_cci = pmic_glink_ucsi_read_cci,
> +	.poll_cci = pmic_glink_ucsi_read_cci,
>  	.read_message_in = pmic_glink_ucsi_read_message_in,
>  	.sync_control = ucsi_sync_control_common,
>  	.async_control = pmic_glink_ucsi_async_control,
> diff --git a/drivers/usb/typec/ucsi/ucsi_stm32g0.c
> b/drivers/usb/typec/ucsi/ucsi_stm32g0.c
> index 6923fad31d79..57ef7d83a412 100644
> --- a/drivers/usb/typec/ucsi/ucsi_stm32g0.c
> +++ b/drivers/usb/typec/ucsi/ucsi_stm32g0.c
> @@ -424,6 +424,7 @@ static irqreturn_t
> ucsi_stm32g0_irq_handler(int irq, void *data)
>  static const struct ucsi_operations ucsi_stm32g0_ops = {
>  	.read_version = ucsi_stm32g0_read_version,
>  	.read_cci = ucsi_stm32g0_read_cci,
> +	.poll_cci = ucsi_stm32g0_read_cci,
>  	.read_message_in = ucsi_stm32g0_read_message_in,
>  	.sync_control = ucsi_sync_control_common,
>  	.async_control = ucsi_stm32g0_async_control,
> diff --git a/drivers/usb/typec/ucsi/ucsi_yoga_c630.c
> b/drivers/usb/typec/ucsi/ucsi_yoga_c630.c
> index f3a5e24ea84d..40e5da4fd2a4 100644
> --- a/drivers/usb/typec/ucsi/ucsi_yoga_c630.c
> +++ b/drivers/usb/typec/ucsi/ucsi_yoga_c630.c
> @@ -74,6 +74,7 @@ static int yoga_c630_ucsi_async_control(struct
> ucsi *ucsi, u64 command)
>  const struct ucsi_operations yoga_c630_ucsi_ops = {
>  	.read_version = yoga_c630_ucsi_read_version,
>  	.read_cci = yoga_c630_ucsi_read_cci,
> +	.poll_cci = yoga_c630_ucsi_read_cci,
>  	.read_message_in = yoga_c630_ucsi_read_message_in,
>  	.sync_control = ucsi_sync_control_common,
>  	.async_control = yoga_c630_ucsi_async_control,





[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux