On Thu, Feb 29, 2024 at 3:28 PM Jameson Thies <jthies@xxxxxxxxxx> wrote: > diff --git a/drivers/usb/typec/ucsi/ucsi.c b/drivers/usb/typec/ucsi/ucsi.c > index 7c84687b5d1a3..4088422b33c74 100644 > --- a/drivers/usb/typec/ucsi/ucsi.c > +++ b/drivers/usb/typec/ucsi/ucsi.c > @@ -646,6 +646,121 @@ static int ucsi_get_src_pdos(struct ucsi_connector *con) > return ret; > } > > +static int ucsi_read_identity(struct ucsi_connector *con, u8 recipient, > + struct usb_pd_identity *id) > +{ > + struct ucsi *ucsi = con->ucsi; > + struct ucsi_pd_message_disc_id resp = {}; > + u64 command; > + int ret; > + > + if (ucsi->version < UCSI_VERSION_2_0) { > + /* > + * Before UCSI v2.0, MESSAGE_IN is 16 bytes which cannot fit > + * the 28 byte identity response including the VDM header. > + * First request the VDM header, ID Header VDO, Cert Stat VDO > + * and Product VDO. > + */ > + command = UCSI_COMMAND(UCSI_GET_PD_MESSAGE) | > + UCSI_CONNECTOR_NUMBER(con->num); > + command |= UCSI_GET_PD_MESSAGE_RECIPIENT(recipient); > + command |= UCSI_GET_PD_MESSAGE_OFFSET(0); > + command |= UCSI_GET_PD_MESSAGE_BYTES(0x10); > + command |= UCSI_GET_PD_MESSAGE_TYPE( > + UCSI_GET_PD_MESSAGE_TYPE_IDENTITY); > + > + ret = ucsi_send_command(ucsi, command, &resp, 0x10); > + if (ret < 0) { > + dev_err(ucsi->dev, > + "UCSI_GET_PD_MESSAGE v1.2 failed first request (%d)\n", > + ret); > + return ret; > + } > + > + /* Then request Product Type VDO1 through Product Type VDO3. */ > + command = UCSI_COMMAND(UCSI_GET_PD_MESSAGE) | > + UCSI_CONNECTOR_NUMBER(con->num); > + command |= UCSI_GET_PD_MESSAGE_RECIPIENT(recipient); > + command |= UCSI_GET_PD_MESSAGE_OFFSET(0x10); > + command |= UCSI_GET_PD_MESSAGE_BYTES(0xc); > + command |= UCSI_GET_PD_MESSAGE_TYPE( > + UCSI_GET_PD_MESSAGE_TYPE_IDENTITY); > + > + ret = ucsi_send_command(ucsi, command, &resp.vdo[0], 0xc); > + if (ret < 0) { > + dev_err(ucsi->dev, > + "UCSI_GET_PD_MESSAGE v1.2 failed second request (%d)\n", > + ret); > + return ret; > + } > + } else { > + /* > + * In UCSI v2.0 and after, MESSAGE_IN is large enough to request > + * the large enough to request the full Discover Identity > + * response at once. > + */ > + command = UCSI_COMMAND(UCSI_GET_PD_MESSAGE) | > + UCSI_CONNECTOR_NUMBER(con->num); > + command |= UCSI_GET_PD_MESSAGE_RECIPIENT(recipient); > + /* VDM Header + 6 VDOs (0x1c bytes) without an offset */ > + command |= UCSI_GET_PD_MESSAGE_OFFSET(0); > + command |= UCSI_GET_PD_MESSAGE_BYTES(0x1c); > + command |= UCSI_GET_PD_MESSAGE_TYPE( > + UCSI_GET_PD_MESSAGE_TYPE_IDENTITY); > + > + ret = ucsi_send_command(ucsi, command, &resp, sizeof(resp)); > + if (ret < 0) { > + dev_err(ucsi->dev, "UCSI_GET_PD_MESSAGE failed (%d)\n", > + ret); > + return ret; > + } > + } > + > + id->id_header = resp.id_header; > + id->cert_stat = resp.cert_stat; > + id->product = resp.product; > + id->vdo[0] = resp.vdo[0]; > + id->vdo[1] = resp.vdo[1]; > + id->vdo[2] = resp.vdo[2]; > + return 0; > +} There is some repetition here, both with the "if" block and the UCSI command itself. You can factor out the command setup code into a separate function (it can take offset and size as arguments). Then, factor out common parts in the "if" block. For example: int ucsi_pd_message_get_identity(struct *ucsi, u8 offset, u8 size, u8 recipient, void *data) { u64 command = UCSI_COMMAND(UCSI_GET_PD_MESSAGE) | UCSI_CONNECTOR_NUMBER(ucsi->con->num) | UCSI_GET_PD_MESSAGE_RECIPIENT(recipient) | UCSI_GET_PD_MESSAGE_OFFSET(offset) | UCSI_GET_PD_MESSAGE_BYTES(size) | UCSI_GET_PD_MESSAGE_TYPE(UCSI_GET_PD_MESSAGE_TYPE_IDENTITY); return ucsi_send_command(ucsi, command, data, size); } Then in the ucsi_read_identity() : u8 offset = 0; u8 size; /* * In UCSI v2.0 and after, MESSAGE_IN is large enough to request * the large enough to request the full Discover Identity * response at once. */ if (ucsi->version >= UCSI_VERSION_2_0) { size = 0x1c; else size = 0x10; ret = ucsi_pd_message_get_identity(ucsi, offset, size, &resp); if (ret < 0) { /* Handle error */ } /* Request Product Type VDO1 through Product Type VDO3. */ if (ucsi->version < UCSI_VERSION_2_0) { offset = 0x10; size = 0xC; ret = ucsi_pd_message_get_identity(ucsi, offset, size, &resp.vdo[0]); if (ret < 0) { /* Handle error */ } } BR, -Prashant