linux-usb.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2] usb: typec: fusb302: Fix masking of comparator and bc_lvl interrupts
@ 2021-11-08 10:28 Ondrej Jirman
  2021-11-08 11:24 ` Hans de Goede
  2021-11-15  7:11 ` Heikki Krogerus
  0 siblings, 2 replies; 6+ messages in thread
From: Ondrej Jirman @ 2021-11-08 10:28 UTC (permalink / raw)
  To: Guenter Roeck, Heikki Krogerus, Greg Kroah-Hartman,
	Ondrej Jirman, Badhri Jagan Sridharan, Hans de Goede,
	open list:USB TYPEC PORT CONTROLLER DRIVERS, open list

The code that enables either BC_LVL or COMP_CHNG interrupt in tcpm_set_cc
wrongly assumes that the interrupt is unmasked by writing 1 to the apropriate
bit in the mask register. In fact, interrupts are enabled when the mask
is 0, so the tcpm_set_cc enables interrupt for COMP_CHNG when it expects
BC_LVL interrupt to be enabled.

This causes inability of the driver to recognize cable unplug events
in host mode (unplug is recognized only via a COMP_CHNG interrupt).

In device mode this bug was masked by simultaneous triggering of the VBUS
change interrupt, because of loss of VBUS when the port peer is providing
power.

Fixes: 48242e30532b ("usb: typec: fusb302: Revert "Resolve fixed power role contract setup"")
Signed-off-by: Ondrej Jirman <megous@megous.com>
Cc: Hans de Goede <hdegoede@redhat.com>
---
 drivers/usb/typec/tcpm/fusb302.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/typec/tcpm/fusb302.c b/drivers/usb/typec/tcpm/fusb302.c
index 7a2a17866a823..72f9001b07921 100644
--- a/drivers/usb/typec/tcpm/fusb302.c
+++ b/drivers/usb/typec/tcpm/fusb302.c
@@ -669,25 +669,27 @@ static int tcpm_set_cc(struct tcpc_dev *dev, enum typec_cc_status cc)
 		ret = fusb302_i2c_mask_write(chip, FUSB_REG_MASK,
 					     FUSB_REG_MASK_BC_LVL |
 					     FUSB_REG_MASK_COMP_CHNG,
-					     FUSB_REG_MASK_COMP_CHNG);
+					     FUSB_REG_MASK_BC_LVL);
 		if (ret < 0) {
 			fusb302_log(chip, "cannot set SRC interrupt, ret=%d",
 				    ret);
 			goto done;
 		}
 		chip->intr_comp_chng = true;
+		chip->intr_bc_lvl = false;
 		break;
 	case TYPEC_CC_RD:
 		ret = fusb302_i2c_mask_write(chip, FUSB_REG_MASK,
 					     FUSB_REG_MASK_BC_LVL |
 					     FUSB_REG_MASK_COMP_CHNG,
-					     FUSB_REG_MASK_BC_LVL);
+					     FUSB_REG_MASK_COMP_CHNG);
 		if (ret < 0) {
 			fusb302_log(chip, "cannot set SRC interrupt, ret=%d",
 				    ret);
 			goto done;
 		}
 		chip->intr_bc_lvl = true;
+		chip->intr_comp_chng = false;
 		break;
 	default:
 		break;
-- 
2.33.1


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH v2] usb: typec: fusb302: Fix masking of comparator and bc_lvl interrupts
  2021-11-08 10:28 [PATCH v2] usb: typec: fusb302: Fix masking of comparator and bc_lvl interrupts Ondrej Jirman
@ 2021-11-08 11:24 ` Hans de Goede
  2021-11-15  7:11 ` Heikki Krogerus
  1 sibling, 0 replies; 6+ messages in thread
From: Hans de Goede @ 2021-11-08 11:24 UTC (permalink / raw)
  To: Ondrej Jirman, Guenter Roeck, Heikki Krogerus,
	Greg Kroah-Hartman, Badhri Jagan Sridharan,
	open list:USB TYPEC PORT CONTROLLER DRIVERS, open list

Hi,

On 11/8/21 11:28, Ondrej Jirman wrote:
> The code that enables either BC_LVL or COMP_CHNG interrupt in tcpm_set_cc
> wrongly assumes that the interrupt is unmasked by writing 1 to the apropriate
> bit in the mask register. In fact, interrupts are enabled when the mask
> is 0, so the tcpm_set_cc enables interrupt for COMP_CHNG when it expects
> BC_LVL interrupt to be enabled.
> 
> This causes inability of the driver to recognize cable unplug events
> in host mode (unplug is recognized only via a COMP_CHNG interrupt).
> 
> In device mode this bug was masked by simultaneous triggering of the VBUS
> change interrupt, because of loss of VBUS when the port peer is providing
> power.
> 
> Fixes: 48242e30532b ("usb: typec: fusb302: Revert "Resolve fixed power role contract setup"")
> Signed-off-by: Ondrej Jirman <megous@megous.com>
> Cc: Hans de Goede <hdegoede@redhat.com>

Thanks, patch looks good to me:

Reviewed-by: Hans de Goede <hdegoede@redhat.com>

Regards,

Hans

> ---
>  drivers/usb/typec/tcpm/fusb302.c | 6 ++++--
>  1 file changed, 4 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/usb/typec/tcpm/fusb302.c b/drivers/usb/typec/tcpm/fusb302.c
> index 7a2a17866a823..72f9001b07921 100644
> --- a/drivers/usb/typec/tcpm/fusb302.c
> +++ b/drivers/usb/typec/tcpm/fusb302.c
> @@ -669,25 +669,27 @@ static int tcpm_set_cc(struct tcpc_dev *dev, enum typec_cc_status cc)
>  		ret = fusb302_i2c_mask_write(chip, FUSB_REG_MASK,
>  					     FUSB_REG_MASK_BC_LVL |
>  					     FUSB_REG_MASK_COMP_CHNG,
> -					     FUSB_REG_MASK_COMP_CHNG);
> +					     FUSB_REG_MASK_BC_LVL);
>  		if (ret < 0) {
>  			fusb302_log(chip, "cannot set SRC interrupt, ret=%d",
>  				    ret);
>  			goto done;
>  		}
>  		chip->intr_comp_chng = true;


> +		chip->intr_bc_lvl = false;

FWIW this is not necessary because the fusb302_set_toggling(chip, TOGGLING_MODE_OFF)
already does this, but it makes the code more clear, so lets keep it.

>  		break;
>  	case TYPEC_CC_RD:
>  		ret = fusb302_i2c_mask_write(chip, FUSB_REG_MASK,
>  					     FUSB_REG_MASK_BC_LVL |
>  					     FUSB_REG_MASK_COMP_CHNG,
> -					     FUSB_REG_MASK_BC_LVL);
> +					     FUSB_REG_MASK_COMP_CHNG);
>  		if (ret < 0) {
>  			fusb302_log(chip, "cannot set SRC interrupt, ret=%d",
>  				    ret);
>  			goto done;
>  		}
>  		chip->intr_bc_lvl = true;


> +		chip->intr_comp_chng = false;

Idem.

>  		break;
>  	default:
>  		break;
> 

Regards,

Hans


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH v2] usb: typec: fusb302: Fix masking of comparator and bc_lvl interrupts
  2021-11-08 10:28 [PATCH v2] usb: typec: fusb302: Fix masking of comparator and bc_lvl interrupts Ondrej Jirman
  2021-11-08 11:24 ` Hans de Goede
@ 2021-11-15  7:11 ` Heikki Krogerus
  2021-11-15  7:15   ` Heikki Krogerus
  2021-11-15  8:55   ` Ondřej Jirman
  1 sibling, 2 replies; 6+ messages in thread
From: Heikki Krogerus @ 2021-11-15  7:11 UTC (permalink / raw)
  To: Ondrej Jirman
  Cc: Guenter Roeck, Greg Kroah-Hartman, Badhri Jagan Sridharan,
	Hans de Goede, open list:USB TYPEC PORT CONTROLLER DRIVERS,
	open list

On Mon, Nov 08, 2021 at 11:28:32AM +0100, Ondrej Jirman wrote:
> The code that enables either BC_LVL or COMP_CHNG interrupt in tcpm_set_cc
> wrongly assumes that the interrupt is unmasked by writing 1 to the apropriate
> bit in the mask register. In fact, interrupts are enabled when the mask
> is 0, so the tcpm_set_cc enables interrupt for COMP_CHNG when it expects
> BC_LVL interrupt to be enabled.
> 
> This causes inability of the driver to recognize cable unplug events
> in host mode (unplug is recognized only via a COMP_CHNG interrupt).
> 
> In device mode this bug was masked by simultaneous triggering of the VBUS
> change interrupt, because of loss of VBUS when the port peer is providing
> power.
> 
> Fixes: 48242e30532b ("usb: typec: fusb302: Revert "Resolve fixed power role contract setup"")
> Signed-off-by: Ondrej Jirman <megous@megous.com>
> Cc: Hans de Goede <hdegoede@redhat.com>

Should this go to stable?

Acked-by: Heikki Krogerus@linux.intel.com

> ---
>  drivers/usb/typec/tcpm/fusb302.c | 6 ++++--
>  1 file changed, 4 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/usb/typec/tcpm/fusb302.c b/drivers/usb/typec/tcpm/fusb302.c
> index 7a2a17866a823..72f9001b07921 100644
> --- a/drivers/usb/typec/tcpm/fusb302.c
> +++ b/drivers/usb/typec/tcpm/fusb302.c
> @@ -669,25 +669,27 @@ static int tcpm_set_cc(struct tcpc_dev *dev, enum typec_cc_status cc)
>  		ret = fusb302_i2c_mask_write(chip, FUSB_REG_MASK,
>  					     FUSB_REG_MASK_BC_LVL |
>  					     FUSB_REG_MASK_COMP_CHNG,
> -					     FUSB_REG_MASK_COMP_CHNG);
> +					     FUSB_REG_MASK_BC_LVL);
>  		if (ret < 0) {
>  			fusb302_log(chip, "cannot set SRC interrupt, ret=%d",
>  				    ret);
>  			goto done;
>  		}
>  		chip->intr_comp_chng = true;
> +		chip->intr_bc_lvl = false;
>  		break;
>  	case TYPEC_CC_RD:
>  		ret = fusb302_i2c_mask_write(chip, FUSB_REG_MASK,
>  					     FUSB_REG_MASK_BC_LVL |
>  					     FUSB_REG_MASK_COMP_CHNG,
> -					     FUSB_REG_MASK_BC_LVL);
> +					     FUSB_REG_MASK_COMP_CHNG);
>  		if (ret < 0) {
>  			fusb302_log(chip, "cannot set SRC interrupt, ret=%d",
>  				    ret);
>  			goto done;
>  		}
>  		chip->intr_bc_lvl = true;
> +		chip->intr_comp_chng = false;
>  		break;
>  	default:
>  		break;

thanks,

-- 
heikki

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH v2] usb: typec: fusb302: Fix masking of comparator and bc_lvl interrupts
  2021-11-15  7:11 ` Heikki Krogerus
@ 2021-11-15  7:15   ` Heikki Krogerus
  2021-11-15  8:55   ` Ondřej Jirman
  1 sibling, 0 replies; 6+ messages in thread
From: Heikki Krogerus @ 2021-11-15  7:15 UTC (permalink / raw)
  To: Ondrej Jirman
  Cc: Guenter Roeck, Greg Kroah-Hartman, Badhri Jagan Sridharan,
	Hans de Goede, open list:USB TYPEC PORT CONTROLLER DRIVERS,
	open list

On Mon, Nov 15, 2021 at 09:11:48AM +0200, Heikki Krogerus wrote:
> On Mon, Nov 08, 2021 at 11:28:32AM +0100, Ondrej Jirman wrote:
> > The code that enables either BC_LVL or COMP_CHNG interrupt in tcpm_set_cc
> > wrongly assumes that the interrupt is unmasked by writing 1 to the apropriate
> > bit in the mask register. In fact, interrupts are enabled when the mask
> > is 0, so the tcpm_set_cc enables interrupt for COMP_CHNG when it expects
> > BC_LVL interrupt to be enabled.
> > 
> > This causes inability of the driver to recognize cable unplug events
> > in host mode (unplug is recognized only via a COMP_CHNG interrupt).
> > 
> > In device mode this bug was masked by simultaneous triggering of the VBUS
> > change interrupt, because of loss of VBUS when the port peer is providing
> > power.
> > 
> > Fixes: 48242e30532b ("usb: typec: fusb302: Revert "Resolve fixed power role contract setup"")
> > Signed-off-by: Ondrej Jirman <megous@megous.com>
> > Cc: Hans de Goede <hdegoede@redhat.com>
> 
> Should this go to stable?
> 
> Acked-by: Heikki Krogerus@linux.intel.com

Sorry, that's wrong...

Acked-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>


> > ---
> >  drivers/usb/typec/tcpm/fusb302.c | 6 ++++--
> >  1 file changed, 4 insertions(+), 2 deletions(-)
> > 
> > diff --git a/drivers/usb/typec/tcpm/fusb302.c b/drivers/usb/typec/tcpm/fusb302.c
> > index 7a2a17866a823..72f9001b07921 100644
> > --- a/drivers/usb/typec/tcpm/fusb302.c
> > +++ b/drivers/usb/typec/tcpm/fusb302.c
> > @@ -669,25 +669,27 @@ static int tcpm_set_cc(struct tcpc_dev *dev, enum typec_cc_status cc)
> >  		ret = fusb302_i2c_mask_write(chip, FUSB_REG_MASK,
> >  					     FUSB_REG_MASK_BC_LVL |
> >  					     FUSB_REG_MASK_COMP_CHNG,
> > -					     FUSB_REG_MASK_COMP_CHNG);
> > +					     FUSB_REG_MASK_BC_LVL);
> >  		if (ret < 0) {
> >  			fusb302_log(chip, "cannot set SRC interrupt, ret=%d",
> >  				    ret);
> >  			goto done;
> >  		}
> >  		chip->intr_comp_chng = true;
> > +		chip->intr_bc_lvl = false;
> >  		break;
> >  	case TYPEC_CC_RD:
> >  		ret = fusb302_i2c_mask_write(chip, FUSB_REG_MASK,
> >  					     FUSB_REG_MASK_BC_LVL |
> >  					     FUSB_REG_MASK_COMP_CHNG,
> > -					     FUSB_REG_MASK_BC_LVL);
> > +					     FUSB_REG_MASK_COMP_CHNG);
> >  		if (ret < 0) {
> >  			fusb302_log(chip, "cannot set SRC interrupt, ret=%d",
> >  				    ret);
> >  			goto done;
> >  		}
> >  		chip->intr_bc_lvl = true;
> > +		chip->intr_comp_chng = false;
> >  		break;
> >  	default:
> >  		break;
> 
> thanks,

-- 
heikki

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH v2] usb: typec: fusb302: Fix masking of comparator and bc_lvl interrupts
  2021-11-15  7:11 ` Heikki Krogerus
  2021-11-15  7:15   ` Heikki Krogerus
@ 2021-11-15  8:55   ` Ondřej Jirman
  2021-11-15  9:21     ` Heikki Krogerus
  1 sibling, 1 reply; 6+ messages in thread
From: Ondřej Jirman @ 2021-11-15  8:55 UTC (permalink / raw)
  To: Heikki Krogerus
  Cc: Guenter Roeck, Greg Kroah-Hartman, Badhri Jagan Sridharan,
	Hans de Goede, open list:USB TYPEC PORT CONTROLLER DRIVERS,
	open list

On Mon, Nov 15, 2021 at 09:11:42AM +0200, Heikki Krogerus wrote:
> On Mon, Nov 08, 2021 at 11:28:32AM +0100, Ondrej Jirman wrote:
> > The code that enables either BC_LVL or COMP_CHNG interrupt in tcpm_set_cc
> > wrongly assumes that the interrupt is unmasked by writing 1 to the apropriate
> > bit in the mask register. In fact, interrupts are enabled when the mask
> > is 0, so the tcpm_set_cc enables interrupt for COMP_CHNG when it expects
> > BC_LVL interrupt to be enabled.
> > 
> > This causes inability of the driver to recognize cable unplug events
> > in host mode (unplug is recognized only via a COMP_CHNG interrupt).
> > 
> > In device mode this bug was masked by simultaneous triggering of the VBUS
> > change interrupt, because of loss of VBUS when the port peer is providing
> > power.
> > 
> > Fixes: 48242e30532b ("usb: typec: fusb302: Revert "Resolve fixed power role contract setup"")
> > Signed-off-by: Ondrej Jirman <megous@megous.com>
> > Cc: Hans de Goede <hdegoede@redhat.com>
> 
> Should this go to stable?

Without this patch, VBUS is not turned off when I disconnect a hub from the
Type-C port (because fusb302 will not notice the disconnect), and it stays on
until next plugin of some device, say a normal non PD charger.

So I guess for a brief period you can have both sides provide VBUS (until
fusb302/tcpm processes the next plugin). It may be a problem if VBUS was more
than 5V (not very likely for devices running this driver, I guess).

regards,
	o.

> Acked-by: Heikki Krogerus@linux.intel.com
> 
> > ---
> >  drivers/usb/typec/tcpm/fusb302.c | 6 ++++--
> >  1 file changed, 4 insertions(+), 2 deletions(-)
> > 
> > diff --git a/drivers/usb/typec/tcpm/fusb302.c b/drivers/usb/typec/tcpm/fusb302.c
> > index 7a2a17866a823..72f9001b07921 100644
> > --- a/drivers/usb/typec/tcpm/fusb302.c
> > +++ b/drivers/usb/typec/tcpm/fusb302.c
> > @@ -669,25 +669,27 @@ static int tcpm_set_cc(struct tcpc_dev *dev, enum typec_cc_status cc)
> >  		ret = fusb302_i2c_mask_write(chip, FUSB_REG_MASK,
> >  					     FUSB_REG_MASK_BC_LVL |
> >  					     FUSB_REG_MASK_COMP_CHNG,
> > -					     FUSB_REG_MASK_COMP_CHNG);
> > +					     FUSB_REG_MASK_BC_LVL);
> >  		if (ret < 0) {
> >  			fusb302_log(chip, "cannot set SRC interrupt, ret=%d",
> >  				    ret);
> >  			goto done;
> >  		}
> >  		chip->intr_comp_chng = true;
> > +		chip->intr_bc_lvl = false;
> >  		break;
> >  	case TYPEC_CC_RD:
> >  		ret = fusb302_i2c_mask_write(chip, FUSB_REG_MASK,
> >  					     FUSB_REG_MASK_BC_LVL |
> >  					     FUSB_REG_MASK_COMP_CHNG,
> > -					     FUSB_REG_MASK_BC_LVL);
> > +					     FUSB_REG_MASK_COMP_CHNG);
> >  		if (ret < 0) {
> >  			fusb302_log(chip, "cannot set SRC interrupt, ret=%d",
> >  				    ret);
> >  			goto done;
> >  		}
> >  		chip->intr_bc_lvl = true;
> > +		chip->intr_comp_chng = false;
> >  		break;
> >  	default:
> >  		break;
> 
> thanks,
> 
> -- 
> heikki

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH v2] usb: typec: fusb302: Fix masking of comparator and bc_lvl interrupts
  2021-11-15  8:55   ` Ondřej Jirman
@ 2021-11-15  9:21     ` Heikki Krogerus
  0 siblings, 0 replies; 6+ messages in thread
From: Heikki Krogerus @ 2021-11-15  9:21 UTC (permalink / raw)
  To: Ondřej Jirman, Guenter Roeck, Greg Kroah-Hartman,
	Badhri Jagan Sridharan, Hans de Goede,
	open list:USB TYPEC PORT CONTROLLER DRIVERS, open list

On Mon, Nov 15, 2021 at 09:55:32AM +0100, Ondřej Jirman wrote:
> On Mon, Nov 15, 2021 at 09:11:42AM +0200, Heikki Krogerus wrote:
> > On Mon, Nov 08, 2021 at 11:28:32AM +0100, Ondrej Jirman wrote:
> > > The code that enables either BC_LVL or COMP_CHNG interrupt in tcpm_set_cc
> > > wrongly assumes that the interrupt is unmasked by writing 1 to the apropriate
> > > bit in the mask register. In fact, interrupts are enabled when the mask
> > > is 0, so the tcpm_set_cc enables interrupt for COMP_CHNG when it expects
> > > BC_LVL interrupt to be enabled.
> > > 
> > > This causes inability of the driver to recognize cable unplug events
> > > in host mode (unplug is recognized only via a COMP_CHNG interrupt).
> > > 
> > > In device mode this bug was masked by simultaneous triggering of the VBUS
> > > change interrupt, because of loss of VBUS when the port peer is providing
> > > power.
> > > 
> > > Fixes: 48242e30532b ("usb: typec: fusb302: Revert "Resolve fixed power role contract setup"")
> > > Signed-off-by: Ondrej Jirman <megous@megous.com>
> > > Cc: Hans de Goede <hdegoede@redhat.com>
> > 
> > Should this go to stable?
> 
> Without this patch, VBUS is not turned off when I disconnect a hub from the
> Type-C port (because fusb302 will not notice the disconnect), and it stays on
> until next plugin of some device, say a normal non PD charger.
> 
> So I guess for a brief period you can have both sides provide VBUS (until
> fusb302/tcpm processes the next plugin). It may be a problem if VBUS was more
> than 5V (not very likely for devices running this driver, I guess).

OK. So this should find it's way to the stable kernel releases as
well, and it should have the appropriate "Cc: stable@vger.kernel.org"
tag:

https://www.kernel.org/doc/html/latest/process/submitting-patches.html#select-the-recipients-for-your-patch

thanks,

-- 
heikki

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2021-11-15  9:24 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-11-08 10:28 [PATCH v2] usb: typec: fusb302: Fix masking of comparator and bc_lvl interrupts Ondrej Jirman
2021-11-08 11:24 ` Hans de Goede
2021-11-15  7:11 ` Heikki Krogerus
2021-11-15  7:15   ` Heikki Krogerus
2021-11-15  8:55   ` Ondřej Jirman
2021-11-15  9:21     ` Heikki Krogerus

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).