Message ID | 20240510201244.2968152-5-jthies@google.com |
---|---|
State | Superseded |
Headers | show |
Series | usb: typec: ucsi: Update UCSI alternate mode | expand |
On Fri, May 10, 2024 at 08:12:44PM +0000, Jameson Thies wrote: > Providing the number of known alternate modes allows user space to > determine when device registration has completed. Always register a > number of known alternate modes for the partner and cable plug, even > when the number of supported alternate modes is 0. > > Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com> > Reviewed-by: Benson Leung <bleung@chromium.org> > Signed-off-by: Jameson Thies <jthies@google.com> > --- Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
On 24/06/2024 15:33, Dmitry Baryshkov wrote: > On Mon, 24 Jun 2024 at 16:42, Jon Hunter <jonathanh@nvidia.com> wrote: >> >> >> On 24/06/2024 13:51, Jon Hunter wrote: >>> Hi Jameson, >>> >>> On 10/05/2024 21:12, Jameson Thies wrote: >>>> Providing the number of known alternate modes allows user space to >>>> determine when device registration has completed. Always register a >>>> number of known alternate modes for the partner and cable plug, even >>>> when the number of supported alternate modes is 0. >>>> >>>> Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com> >>>> Reviewed-by: Benson Leung <bleung@chromium.org> >>>> Signed-off-by: Jameson Thies <jthies@google.com> >>>> --- >>>> Changes in V5: >>>> - None. >>>> >>>> Changes in V4: >>>> - None. >>>> >>>> Changes in V3: >>>> - None. >>>> >>>> Changes in V2: >>>> - None. >>>> >>>> drivers/usb/typec/ucsi/ucsi.c | 14 +++++++++++--- >>>> 1 file changed, 11 insertions(+), 3 deletions(-) >>>> >>>> diff --git a/drivers/usb/typec/ucsi/ucsi.c >>>> b/drivers/usb/typec/ucsi/ucsi.c >>>> index bb6e57064513d..52a14bfe4107e 100644 >>>> --- a/drivers/usb/typec/ucsi/ucsi.c >>>> +++ b/drivers/usb/typec/ucsi/ucsi.c >>>> @@ -812,10 +812,11 @@ static int ucsi_check_altmodes(struct >>>> ucsi_connector *con) >>>> /* Ignoring the errors in this case. */ >>>> if (con->partner_altmode[0]) { >>>> num_partner_am = ucsi_get_num_altmode(con->partner_altmode); >>>> - if (num_partner_am > 0) >>>> - typec_partner_set_num_altmodes(con->partner, >>>> num_partner_am); >>>> + typec_partner_set_num_altmodes(con->partner, num_partner_am); >>>> ucsi_altmode_update_active(con); >>>> return 0; >>>> + } else { >>>> + typec_partner_set_num_altmodes(con->partner, 0); >>>> } >>>> return ret; >>>> @@ -1138,7 +1139,7 @@ static int ucsi_check_connection(struct >>>> ucsi_connector *con) >>>> static int ucsi_check_cable(struct ucsi_connector *con) >>>> { >>>> u64 command; >>>> - int ret; >>>> + int ret, num_plug_am; >>>> if (con->cable) >>>> return 0; >>>> @@ -1172,6 +1173,13 @@ static int ucsi_check_cable(struct >>>> ucsi_connector *con) >>>> return ret; >>>> } >>>> + if (con->plug_altmode[0]) { >>>> + num_plug_am = ucsi_get_num_altmode(con->plug_altmode); >>>> + typec_plug_set_num_altmodes(con->plug, num_plug_am); >>>> + } else { >>>> + typec_plug_set_num_altmodes(con->plug, 0); >>>> + } >>>> + >>>> return 0; >>>> } Looking at this some more, the plug is only registered in ucsi_check_cable() if UCSI_CAP_ALT_MODE_DETAILS is specified for the Type C controller. The Cypress CCG explicitly clears this flag. The following will only call typec_plug_set_num_altmodes() if the call to ucsi_register_plug() is successful ... diff --git a/drivers/usb/typec/ucsi/ucsi.c b/drivers/usb/typec/ucsi/ucsi.c index 134ef4e17d85..e268af88a7d2 100644 --- a/drivers/usb/typec/ucsi/ucsi.c +++ b/drivers/usb/typec/ucsi/ucsi.c @@ -1176,13 +1176,13 @@ static int ucsi_check_cable(struct ucsi_connector *con) ret = ucsi_register_altmodes(con, UCSI_RECIPIENT_SOP_P); if (ret < 0) return ret; - } - if (con->plug_altmode[0]) { - num_plug_am = ucsi_get_num_altmode(con->plug_altmode); - typec_plug_set_num_altmodes(con->plug, num_plug_am); - } else { - typec_plug_set_num_altmodes(con->plug, 0); + if (con->plug_altmode[0]) { + num_plug_am = ucsi_get_num_altmode(con->plug_altmode); + typec_plug_set_num_altmodes(con->plug, num_plug_am); + } else { + typec_plug_set_num_altmodes(con->plug, 0); + } } return 0; >> It is crashing because 'con->plug' is not initialised when >> typec_plug_set_num_altmodes() is called. Do we need to add a check to >> see if 'con->plug' is valid in ucsi_check_cable()? > > Yes. Either of con->calbe and con->plug can be NULL. Thanks for confirming. Jon
Hi Jon, thank you for catching this. I'll post a fix to address the null pointer dereferencing. Thanks, Jameson
diff --git a/drivers/usb/typec/ucsi/ucsi.c b/drivers/usb/typec/ucsi/ucsi.c index bb6e57064513d..52a14bfe4107e 100644 --- a/drivers/usb/typec/ucsi/ucsi.c +++ b/drivers/usb/typec/ucsi/ucsi.c @@ -812,10 +812,11 @@ static int ucsi_check_altmodes(struct ucsi_connector *con) /* Ignoring the errors in this case. */ if (con->partner_altmode[0]) { num_partner_am = ucsi_get_num_altmode(con->partner_altmode); - if (num_partner_am > 0) - typec_partner_set_num_altmodes(con->partner, num_partner_am); + typec_partner_set_num_altmodes(con->partner, num_partner_am); ucsi_altmode_update_active(con); return 0; + } else { + typec_partner_set_num_altmodes(con->partner, 0); } return ret; @@ -1138,7 +1139,7 @@ static int ucsi_check_connection(struct ucsi_connector *con) static int ucsi_check_cable(struct ucsi_connector *con) { u64 command; - int ret; + int ret, num_plug_am; if (con->cable) return 0; @@ -1172,6 +1173,13 @@ static int ucsi_check_cable(struct ucsi_connector *con) return ret; } + if (con->plug_altmode[0]) { + num_plug_am = ucsi_get_num_altmode(con->plug_altmode); + typec_plug_set_num_altmodes(con->plug, num_plug_am); + } else { + typec_plug_set_num_altmodes(con->plug, 0); + } + return 0; }