Re: [bug report] usb: ucsi_acpi: Quirk to ack a connector change ack cmd

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

 



Hi Dan,

On Wed, Jan 31, 2024 at 09:59:43AM +0300, Dan Carpenter wrote:
> Hello Christian A. Ehrhardt,
> 
> The patch f3be347ea42d: "usb: ucsi_acpi: Quirk to ack a connector
> change ack cmd" from Jan 21, 2024 (linux-next), leads to the
> following Smatch static checker warning:
> 
> 	drivers/usb/typec/ucsi/ucsi_acpi.c:174 ucsi_dell_sync_write()
> 	warn: missing error code? 'ret'
> 
> drivers/usb/typec/ucsi/ucsi_acpi.c
>     138 static int
>     139 ucsi_dell_sync_write(struct ucsi *ucsi, unsigned int offset,
>     140                      const void *val, size_t val_len)
>     141 {
>     142         struct ucsi_acpi *ua = ucsi_get_drvdata(ucsi);
>     143         u64 cmd = *(u64 *)val, ack = 0;
>     144         int ret;
>     145 
>     146         if (UCSI_COMMAND(cmd) == UCSI_ACK_CC_CI &&
>     147             cmd & UCSI_ACK_CONNECTOR_CHANGE)
>     148                 ack = UCSI_ACK_CC_CI | UCSI_ACK_COMMAND_COMPLETE;
>     149 
>     150         ret = ucsi_acpi_sync_write(ucsi, offset, val, val_len);
>     151         if (ret != 0)
>     152                 return ret;
>     153         if (ack == 0)
>     154                 return ret;
> 
> This would be better as "return 0;"

While it is technically true that this could be written as "return 0;"
it was written in this way intentionally. The ucsi_dell_sync_write
quirk function is a wrapper around this call to ucsi_acpi_sync_write.
These if-statements handle the cases where nothing needs to be done
after that call and we just return with whatever ucsi_acpi_sync_write
returned.

>     155 
>     156         if (!ua->dell_quirk_probed) {
>     157                 ua->dell_quirk_probed = true;
>     158 
>     159                 cmd = UCSI_GET_CAPABILITY;
>     160                 ret = ucsi_acpi_sync_write(ucsi, UCSI_CONTROL, &cmd,
>     161                                            sizeof(cmd));
>     162                 if (ret == 0)
>     163                         return ucsi_acpi_sync_write(ucsi, UCSI_CONTROL,
>     164                                                     &ack, sizeof(ack));
>     165                 if (ret != -ETIMEDOUT)
>     166                         return ret;
>     167 
>     168                 ua->dell_quirk_active = true;
> 
> Here we set ->dell_quirk_active to true;
> 
>     169                 dev_err(ua->dev, "Firmware bug: Additional ACK required after ACKing a connector change.\n");
>     170                 dev_err(ua->dev, "Firmware bug: Enabling workaround\n");
>     171         }
>     172 
>     173         if (!ua->dell_quirk_active)
> --> 174                 return ret;
> 
> So this is basically an else statement and ret is zero.  Smatch thinks
> it should be an error code but I think it's intentional.  Why reverse
> the if statement, return a literal, and pull the code in a tab.  You
> could delete the ua->dell_quirk_active variable.  Or is the concern
> here that we'll be probing two of these quirky things concurrently?
> It's a bit strange and probably needs some cleanup or comments.
> 
> 	if (ua->dell_quirk_probed)
> 		return 0;

This is not correct. ->dell_quirk_active may have been set in a
previous run and that's the whole point of the probe: Setting
->dell_quirk_active to the correct value for future calls to this
function.

> 	ua->dell_quirk_probed = true;
> 
> 	cmd = UCSI_GET_CAPABILITY;
> 	ret = ucsi_acpi_sync_write(ucsi, UCSI_CONTROL, &cmd, sizeof(cmd));
> 	...

So this code should only be executed once.

> 
>     175 
>     176         return ucsi_acpi_sync_write(ucsi, UCSI_CONTROL, &ack, sizeof(ack));
>     177 }

This additional call is the actual quirk. It should not be neccessary
according to the spec but if the probe determines that it is required
it must be done each time an ack for an async event is sent. If the
quirk is not neccessary we just return whatever the above call to
ucsi_acpi_sync_write() returned.

So in summary, I don't think there's a bug here.

However, it is possible to silence smatch with the diff below
(or with the second hunk alone) and I'd be ok with this. I can
give this a try on the real hardware and send a patch later this
week.

     regards   Christian


diff --git a/drivers/usb/typec/ucsi/ucsi_acpi.c b/drivers/usb/typec/ucsi/ucsi_acpi.c
index 928eacbeb21a..99fbc7ae0f1e 100644
--- a/drivers/usb/typec/ucsi/ucsi_acpi.c
+++ b/drivers/usb/typec/ucsi/ucsi_acpi.c
@@ -151,7 +151,7 @@ ucsi_dell_sync_write(struct ucsi *ucsi, unsigned int offset,
 	if (ret != 0)
 		return ret;
 	if (ack == 0)
-		return ret;
+		return 0;
 
 	if (!ua->dell_quirk_probed) {
 		ua->dell_quirk_probed = true;
@@ -171,7 +171,7 @@ ucsi_dell_sync_write(struct ucsi *ucsi, unsigned int offset,
 	}
 
 	if (!ua->dell_quirk_active)
-		return ret;
+		return 0;
 
 	return ucsi_acpi_sync_write(ucsi, UCSI_CONTROL, &ack, sizeof(ack));
 }





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

  Powered by Linux