2024-01-23 22:31:06

by Abhishek Pandit-Subedi

[permalink] [raw]
Subject: [PATCH v1 0/3] usb: typec: ucsi: Adding support for UCSI 3.0

From: Abhishek Pandit-Subedi <[email protected]>


Hi Heikki,

This series starts the work adding UCSI 3.0 support to the UCSI driver.

There's a couple of pieces to start here:
* Add version checks and limit read size on 1.2.
* Update Connector Status and Connector Capability structures.
* Expose Partner PD revision from Capability data.

These were tested against on a 6.6 kernel running a usermode PPM against
a Realtek Evaluation board.

One additional note: there are a lot more unaligned fields in UCSI now
and the struct definitions are getting a bit out of hand. We can discuss
alternate mechanisms for defining these structs in the patch that
changes these structures.

Thanks,
Abhishek


Abhishek Pandit-Subedi (3):
usb: typec: ucsi: Limit read size on v1.2
usb: typec: ucsi: Update connector cap and status
usb: typec: ucsi: Get PD revision for partner

drivers/usb/typec/ucsi/ucsi.c | 51 ++++++++++++++++++++++++++--
drivers/usb/typec/ucsi/ucsi.h | 64 ++++++++++++++++++++++++++++++++---
2 files changed, 109 insertions(+), 6 deletions(-)

--
2.43.0.429.g432eaa2c6b-goog



2024-01-23 22:31:23

by Abhishek Pandit-Subedi

[permalink] [raw]
Subject: [PATCH v1 1/3] usb: typec: ucsi: Limit read size on v1.2

From: Abhishek Pandit-Subedi <[email protected]>

Between UCSI 1.2 and UCSI 2.0, the size of the MESSAGE_IN region was
increased from 16 to 256. In order to avoid overflowing reads for older
systems, add a mechanism to use the read UCSI version to truncate read
sizes on UCSI v1.2.

Signed-off-by: Abhishek Pandit-Subedi <[email protected]>
---
Tested on 6.6 kernel. Dmesg output from this change:
[ 105.058162] ucsi_um_test ucsi_um_test_device.0: Registered UCSI
interface with version 3.0.0


drivers/usb/typec/ucsi/ucsi.c | 26 ++++++++++++++++++++++++--
drivers/usb/typec/ucsi/ucsi.h | 11 +++++++++++
2 files changed, 35 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/typec/ucsi/ucsi.c b/drivers/usb/typec/ucsi/ucsi.c
index 5392ec698959..4edf785d203b 100644
--- a/drivers/usb/typec/ucsi/ucsi.c
+++ b/drivers/usb/typec/ucsi/ucsi.c
@@ -36,6 +36,19 @@
*/
#define UCSI_SWAP_TIMEOUT_MS 5000

+static int ucsi_read_message_in(struct ucsi *ucsi, void *buf,
+ size_t buf_size)
+{
+ /*
+ * Below UCSI 2.0, MESSAGE_IN was limited to 16 bytes. Truncate the
+ * reads here.
+ */
+ if (ucsi->version <= UCSI_VERSION_1_2)
+ buf_size = min_t(size_t, 16, buf_size);
+
+ return ucsi->ops->read(ucsi, UCSI_MESSAGE_IN, buf, buf_size);
+}
+
static int ucsi_acknowledge_command(struct ucsi *ucsi)
{
u64 ctrl;
@@ -72,7 +85,7 @@ static int ucsi_read_error(struct ucsi *ucsi)
if (ret < 0)
return ret;

- ret = ucsi->ops->read(ucsi, UCSI_MESSAGE_IN, &error, sizeof(error));
+ ret = ucsi_read_message_in(ucsi, &error, sizeof(error));
if (ret)
return ret;

@@ -170,7 +183,7 @@ int ucsi_send_command(struct ucsi *ucsi, u64 command,
length = ret;

if (data) {
- ret = ucsi->ops->read(ucsi, UCSI_MESSAGE_IN, data, size);
+ ret = ucsi_read_message_in(ucsi, data, size);
if (ret)
goto out;
}
@@ -1556,6 +1569,15 @@ int ucsi_register(struct ucsi *ucsi)
if (!ucsi->version)
return -ENODEV;

+ /*
+ * Version format is JJ.M.N (JJ = Major version, M = Minor version,
+ * N = sub-minor version).
+ */
+ dev_info(ucsi->dev, "Registered UCSI interface with version %x.%x.%x",
+ UCSI_BCD_GET_MAJOR(ucsi->version),
+ UCSI_BCD_GET_MINOR(ucsi->version),
+ UCSI_BCD_GET_SUBMINOR(ucsi->version));
+
queue_delayed_work(system_long_wq, &ucsi->work, 0);

ucsi_debugfs_register(ucsi);
diff --git a/drivers/usb/typec/ucsi/ucsi.h b/drivers/usb/typec/ucsi/ucsi.h
index 6478016d5cb8..bec920fa6b8a 100644
--- a/drivers/usb/typec/ucsi/ucsi.h
+++ b/drivers/usb/typec/ucsi/ucsi.h
@@ -23,6 +23,17 @@ struct dentry;
#define UCSI_CONTROL 8
#define UCSI_MESSAGE_IN 16
#define UCSI_MESSAGE_OUT 32
+#define UCSIv2_MESSAGE_OUT 272
+
+/* UCSI versions */
+#define UCSI_VERSION_1_2 0x0120
+#define UCSI_VERSION_2_0 0x0200
+#define UCSI_VERSION_2_1 0x0210
+#define UCSI_VERSION_3_0 0x0300
+
+#define UCSI_BCD_GET_MAJOR(_v_) (((_v_) >> 8) & 0xFF)
+#define UCSI_BCD_GET_MINOR(_v_) (((_v_) >> 4) & 0x0F)
+#define UCSI_BCD_GET_SUBMINOR(_v_) ((_v_) & 0x0F)

/* Command Status and Connector Change Indication (CCI) bits */
#define UCSI_CCI_CONNECTOR(_c_) (((_c_) & GENMASK(7, 1)) >> 1)
--
2.43.0.429.g432eaa2c6b-goog


2024-01-23 22:33:18

by Abhishek Pandit-Subedi

[permalink] [raw]
Subject: [PATCH v1 3/3] usb: typec: ucsi: Get PD revision for partner

From: Abhishek Pandit-Subedi <[email protected]>

PD major revision for the port partner is described in
GET_CONNECTOR_CAPABILITY and is only valid on UCSI 2.0 and newer. Update
the pd_revision on the partner if the UCSI version is 2.0 or newer.

Signed-off-by: Abhishek Pandit-Subedi <[email protected]>
---
$ cat /sys/class/typec/port2-partner/usb_power_delivery_revision
3.0

drivers/usb/typec/ucsi/ucsi.c | 25 +++++++++++++++++++++++++
drivers/usb/typec/ucsi/ucsi.h | 3 +++
2 files changed, 28 insertions(+)

diff --git a/drivers/usb/typec/ucsi/ucsi.c b/drivers/usb/typec/ucsi/ucsi.c
index 4edf785d203b..8e0a512853ba 100644
--- a/drivers/usb/typec/ucsi/ucsi.c
+++ b/drivers/usb/typec/ucsi/ucsi.c
@@ -782,6 +782,8 @@ static int ucsi_register_partner(struct ucsi_connector *con)
}

desc.usb_pd = pwr_opmode == UCSI_CONSTAT_PWR_OPMODE_PD;
+ desc.pd_revision =
+ UCSI_CONCAP_FLAG_PARTNER_PD_MAJOR_REV_AS_BCD(con->cap.flags);

partner = typec_register_partner(con->port, &desc);
if (IS_ERR(partner)) {
@@ -856,6 +858,28 @@ static void ucsi_partner_change(struct ucsi_connector *con)
con->num, u_role);
}

+static int ucsi_check_connector_capability(struct ucsi_connector *con)
+{
+ u64 command;
+ int ret;
+
+ if (!con->partner && !IS_MIN_VERSION_2_0(con->ucsi))
+ return 0;
+
+ command = UCSI_GET_CONNECTOR_CAPABILITY | UCSI_CONNECTOR_NUMBER(con->num);
+ ret = ucsi_send_command(con->ucsi, command, &con->cap, sizeof(con->cap));
+ if (ret < 0) {
+ dev_err(con->ucsi->dev, "GET_CONNECTOR_CAPABILITY failed (%d)\n", ret);
+ return ret;
+ }
+
+ typec_partner_set_pd_revision(
+ con->partner,
+ UCSI_CONCAP_FLAG_PARTNER_PD_MAJOR_REV_AS_BCD(con->cap.flags));
+
+ return ret;
+}
+
static int ucsi_check_connection(struct ucsi_connector *con)
{
u8 prev_flags = con->status.flags;
@@ -925,6 +949,7 @@ static void ucsi_handle_connector_change(struct work_struct *work)
if (con->status.flags & UCSI_CONSTAT_CONNECTED) {
ucsi_register_partner(con);
ucsi_partner_task(con, ucsi_check_connection, 1, HZ);
+ ucsi_partner_task(con, ucsi_check_connector_capability, 1, HZ);

if (UCSI_CONSTAT_PWR_OPMODE(con->status.flags) ==
UCSI_CONSTAT_PWR_OPMODE_PD)
diff --git a/drivers/usb/typec/ucsi/ucsi.h b/drivers/usb/typec/ucsi/ucsi.h
index 94b373378f63..5e60328f398e 100644
--- a/drivers/usb/typec/ucsi/ucsi.h
+++ b/drivers/usb/typec/ucsi/ucsi.h
@@ -36,6 +36,9 @@ struct dentry;
#define UCSI_BCD_GET_MINOR(_v_) (((_v_) >> 4) & 0x0F)
#define UCSI_BCD_GET_SUBMINOR(_v_) ((_v_) & 0x0F)

+#define IS_MIN_VERSION(ucsi, min_ver) ((ucsi)->version >= min_ver)
+#define IS_MIN_VERSION_2_0(ucsi) IS_MIN_VERSION(ucsi, UCSI_VERSION_2_0)
+
/* Command Status and Connector Change Indication (CCI) bits */
#define UCSI_CCI_CONNECTOR(_c_) (((_c_) & GENMASK(7, 1)) >> 1)
#define UCSI_CCI_LENGTH(_c_) (((_c_) & GENMASK(15, 8)) >> 8)
--
2.43.0.429.g432eaa2c6b-goog


2024-01-24 08:12:51

by Prashant Malani

[permalink] [raw]
Subject: Re: [PATCH v1 1/3] usb: typec: ucsi: Limit read size on v1.2

Hi Abhishek,

On Tue, Jan 23, 2024 at 2:30 PM Abhishek Pandit-Subedi
<[email protected]> wrote:
>
> From: Abhishek Pandit-Subedi <[email protected]>
>
> Between UCSI 1.2 and UCSI 2.0, the size of the MESSAGE_IN region was
> increased from 16 to 256. In order to avoid overflowing reads for older
> systems, add a mechanism to use the read UCSI version to truncate read
> sizes on UCSI v1.2.
>
> Signed-off-by: Abhishek Pandit-Subedi <[email protected]>
I have one nit (mentioned in side-band but reproducing here for consistency),
but will defer to the maintainer on that.

The above notwithstanding, FWIW:
Reviewed-by: Prashant Malani<[email protected]>

> @@ -1556,6 +1569,15 @@ int ucsi_register(struct ucsi *ucsi)
> if (!ucsi->version)
> return -ENODEV;
>
> + /*
> + * Version format is JJ.M.N (JJ = Major version, M = Minor version,
> + * N = sub-minor version).
> + */
> + dev_info(ucsi->dev, "Registered UCSI interface with version %x.%x%x",
> + UCSI_BCD_GET_MAJOR(ucsi->version),
> + UCSI_BCD_GET_MINOR(ucsi->version),
> + UCSI_BCD_GET_SUBMINOR(ucsi->version));

nit: I think this doesn't need to be dev_info() and can be just
dev_dbg(), but will
defer to the maintainer.

Thanks,

-Prashant

2024-01-24 12:45:05

by Neil Armstrong

[permalink] [raw]
Subject: Re: [PATCH v1 0/3] usb: typec: ucsi: Adding support for UCSI 3.0

On 23/01/2024 23:30, Abhishek Pandit-Subedi wrote:
> From: Abhishek Pandit-Subedi <[email protected]>
>
>
> Hi Heikki,
>
> This series starts the work adding UCSI 3.0 support to the UCSI driver.
>
> There's a couple of pieces to start here:
> * Add version checks and limit read size on 1.2.
> * Update Connector Status and Connector Capability structures.
> * Expose Partner PD revision from Capability data.
>
> These were tested against on a 6.6 kernel running a usermode PPM against
> a Realtek Evaluation board.
>
> One additional note: there are a lot more unaligned fields in UCSI now
> and the struct definitions are getting a bit out of hand. We can discuss
> alternate mechanisms for defining these structs in the patch that
> changes these structures.
>
> Thanks,
> Abhishek
>
>
> Abhishek Pandit-Subedi (3):
> usb: typec: ucsi: Limit read size on v1.2
> usb: typec: ucsi: Update connector cap and status
> usb: typec: ucsi: Get PD revision for partner
>
> drivers/usb/typec/ucsi/ucsi.c | 51 ++++++++++++++++++++++++++--
> drivers/usb/typec/ucsi/ucsi.h | 64 ++++++++++++++++++++++++++++++++---
> 2 files changed, 109 insertions(+), 6 deletions(-)
>

[ 7.417925] ucsi_glink.pmic_glink_ucsi pmic_glink.ucsi.0: Registered UCSI interface with version 1.1.0

Tested-by: Neil Armstrong <[email protected]> # on SM8650-QRD

[ 9.085733] ucsi_glink.pmic_glink_ucsi pmic_glink.ucsi.0: Registered UCSI interface with version 1.1.0

Tested-by: Neil Armstrong <[email protected]> # on SM8550-QRD

Thanks,
Neil

2024-01-24 14:17:40

by Greg KH

[permalink] [raw]
Subject: Re: [PATCH v1 1/3] usb: typec: ucsi: Limit read size on v1.2

On Wed, Jan 24, 2024 at 03:51:58PM +0200, Heikki Krogerus wrote:
> On Wed, Jan 24, 2024 at 12:12:26AM -0800, Prashant Malani wrote:
> > Hi Abhishek,
> >
> > On Tue, Jan 23, 2024 at 2:30 PM Abhishek Pandit-Subedi
> > <[email protected]> wrote:
> > >
> > > From: Abhishek Pandit-Subedi <[email protected]>
> > >
> > > Between UCSI 1.2 and UCSI 2.0, the size of the MESSAGE_IN region was
> > > increased from 16 to 256. In order to avoid overflowing reads for older
> > > systems, add a mechanism to use the read UCSI version to truncate read
> > > sizes on UCSI v1.2.
> > >
> > > Signed-off-by: Abhishek Pandit-Subedi <[email protected]>
> > I have one nit (mentioned in side-band but reproducing here for consistency),
> > but will defer to the maintainer on that.
> >
> > The above notwithstanding, FWIW:
> > Reviewed-by: Prashant Malani<[email protected]>
> >
> > > @@ -1556,6 +1569,15 @@ int ucsi_register(struct ucsi *ucsi)
> > > if (!ucsi->version)
> > > return -ENODEV;
> > >
> > > + /*
> > > + * Version format is JJ.M.N (JJ = Major version, M = Minor version,
> > > + * N = sub-minor version).
> > > + */
> > > + dev_info(ucsi->dev, "Registered UCSI interface with version %x.%x.%x",
> > > + UCSI_BCD_GET_MAJOR(ucsi->version),
> > > + UCSI_BCD_GET_MINOR(ucsi->version),
> > > + UCSI_BCD_GET_SUBMINOR(ucsi->version));
> >
> > nit: I think this doesn't need to be dev_info() and can be just
> > dev_dbg(), but will
> > defer to the maintainer.
>
> I think that's okay.
>
> Reviewewd-by: Heikki Krogerus <[email protected]>

No, when drivers are working properly they are quiet, this needs to be
dev_dbg().

thanks,

greg k-h

2024-01-24 16:21:08

by Heikki Krogerus

[permalink] [raw]
Subject: Re: [PATCH v1 1/3] usb: typec: ucsi: Limit read size on v1.2

On Wed, Jan 24, 2024 at 12:12:26AM -0800, Prashant Malani wrote:
> Hi Abhishek,
>
> On Tue, Jan 23, 2024 at 2:30 PM Abhishek Pandit-Subedi
> <[email protected]> wrote:
> >
> > From: Abhishek Pandit-Subedi <[email protected]>
> >
> > Between UCSI 1.2 and UCSI 2.0, the size of the MESSAGE_IN region was
> > increased from 16 to 256. In order to avoid overflowing reads for older
> > systems, add a mechanism to use the read UCSI version to truncate read
> > sizes on UCSI v1.2.
> >
> > Signed-off-by: Abhishek Pandit-Subedi <[email protected]>
> I have one nit (mentioned in side-band but reproducing here for consistency),
> but will defer to the maintainer on that.
>
> The above notwithstanding, FWIW:
> Reviewed-by: Prashant Malani<[email protected]>
>
> > @@ -1556,6 +1569,15 @@ int ucsi_register(struct ucsi *ucsi)
> > if (!ucsi->version)
> > return -ENODEV;
> >
> > + /*
> > + * Version format is JJ.M.N (JJ = Major version, M = Minor version,
> > + * N = sub-minor version).
> > + */
> > + dev_info(ucsi->dev, "Registered UCSI interface with version %x.%x.%x",
> > + UCSI_BCD_GET_MAJOR(ucsi->version),
> > + UCSI_BCD_GET_MINOR(ucsi->version),
> > + UCSI_BCD_GET_SUBMINOR(ucsi->version));
>
> nit: I think this doesn't need to be dev_info() and can be just
> dev_dbg(), but will
> defer to the maintainer.

I think that's okay.

Reviewewd-by: Heikki Krogerus <[email protected]>

--
heikki

2024-01-24 18:59:56

by Abhishek Pandit-Subedi

[permalink] [raw]
Subject: Re: [PATCH v1 1/3] usb: typec: ucsi: Limit read size on v1.2

Ack. Will make dev_dbg on the next iteration.

This seems like a good addition to the style guide too:
https://www.kernel.org/doc/html/v6.7/process/coding-style.html#printing-kernel-messages.
"When drivers are working properly, they are quiet. Prefer to use
DEBUG messages unless something is wrong."

What do you think Greg?

On Wed, Jan 24, 2024 at 6:17 AM Greg Kroah-Hartman
<[email protected]> wrote:
>
> On Wed, Jan 24, 2024 at 03:51:58PM +0200, Heikki Krogerus wrote:
> > On Wed, Jan 24, 2024 at 12:12:26AM -0800, Prashant Malani wrote:
> > > Hi Abhishek,
> > >
> > > On Tue, Jan 23, 2024 at 2:30 PM Abhishek Pandit-Subedi
> > > <[email protected]> wrote:
> > > >
> > > > From: Abhishek Pandit-Subedi <[email protected]>
> > > >
> > > > Between UCSI 1.2 and UCSI 2.0, the size of the MESSAGE_IN region was
> > > > increased from 16 to 256. In order to avoid overflowing reads for older
> > > > systems, add a mechanism to use the read UCSI version to truncate read
> > > > sizes on UCSI v1.2.
> > > >
> > > > Signed-off-by: Abhishek Pandit-Subedi <[email protected]>
> > > I have one nit (mentioned in side-band but reproducing here for consistency),
> > > but will defer to the maintainer on that.
> > >
> > > The above notwithstanding, FWIW:
> > > Reviewed-by: Prashant Malani<[email protected]>
> > >
> > > > @@ -1556,6 +1569,15 @@ int ucsi_register(struct ucsi *ucsi)
> > > > if (!ucsi->version)
> > > > return -ENODEV;
> > > >
> > > > + /*
> > > > + * Version format is JJ.M.N (JJ = Major version, M = Minor version,
> > > > + * N = sub-minor version).
> > > > + */
> > > > + dev_info(ucsi->dev, "Registered UCSI interface with version %x.%x.%x",
> > > > + UCSI_BCD_GET_MAJOR(ucsi->version),
> > > > + UCSI_BCD_GET_MINOR(ucsi->version),
> > > > + UCSI_BCD_GET_SUBMINOR(ucsi->version));
> > >
> > > nit: I think this doesn't need to be dev_info() and can be just
> > > dev_dbg(), but will
> > > defer to the maintainer.
> >
> > I think that's okay.
> >
> > Reviewewd-by: Heikki Krogerus <[email protected]>
>
> No, when drivers are working properly they are quiet, this needs to be
> dev_dbg().
>
> thanks,
>
> greg k-h
>

2024-01-24 19:20:23

by Abhishek Pandit-Subedi

[permalink] [raw]
Subject: Re: [PATCH v1 3/3] usb: typec: ucsi: Get PD revision for partner

On Wed, Jan 24, 2024 at 10:49 AM Prashant Malani <[email protected]> wrote:
>
> Hi Abhishek,
>
> On Tue, Jan 23, 2024 at 2:30 PM Abhishek Pandit-Subedi
> <[email protected]> wrote:
> >
> > From: Abhishek Pandit-Subedi <[email protected]>
> >
> > PD major revision for the port partner is described in
> > GET_CONNECTOR_CAPABILITY and is only valid on UCSI 2.0 and newer. Update
> > the pd_revision on the partner if the UCSI version is 2.0 or newer.
> >
> > Signed-off-by: Abhishek Pandit-Subedi <[email protected]>
> > ---
> > $ cat /sys/class/typec/port2-partner/usb_power_delivery_revision
> > 3.0
> >
> > drivers/usb/typec/ucsi/ucsi.c | 25 +++++++++++++++++++++++++
> > drivers/usb/typec/ucsi/ucsi.h | 3 +++
> > 2 files changed, 28 insertions(+)
> >
> > diff --git a/drivers/usb/typec/ucsi/ucsi.c b/drivers/usb/typec/ucsi/ucsi.c
> > index 4edf785d203b..8e0a512853ba 100644
> > --- a/drivers/usb/typec/ucsi/ucsi.c
> > +++ b/drivers/usb/typec/ucsi/ucsi.c
> > @@ -782,6 +782,8 @@ static int ucsi_register_partner(struct ucsi_connector *con)
> > }
> >
> > desc.usb_pd = pwr_opmode == UCSI_CONSTAT_PWR_OPMODE_PD;
> > + desc.pd_revision =
> > + UCSI_CONCAP_FLAG_PARTNER_PD_MAJOR_REV_AS_BCD(con->cap.flags);
> >
> > partner = typec_register_partner(con->port, &desc);
> > if (IS_ERR(partner)) {
> > @@ -856,6 +858,28 @@ static void ucsi_partner_change(struct ucsi_connector *con)
> > con->num, u_role);
> > }
> >
> > +static int ucsi_check_connector_capability(struct ucsi_connector *con)
> > +{
> > + u64 command;
> > + int ret;
> > +
> > + if (!con->partner && !IS_MIN_VERSION_2_0(con->ucsi))
>
> (Mentioned side-band but reproducing here for consistency)
> This macro is unnecessary. It's just doing a comparison, which can be inlined
> without any perceptible change in readability (actually, I'd argue adding the !
> to an english idiom makes things *less* readable):

I prefer the macro because it makes it easier to search where version
checks are being done and it keeps the `<` vs `<=` consistent. UCSI
only has a few published revisions: 1.2, 2.0, 2.1 and 3.0 and major
changes seem to have happened in 2.0 and 3.0 so there should be very
few of these macros created/used.

>
> if (!con->partner && con->ucsi->version < UCSI_VERSION_2_0)
> return 0;
>
> Besides that, I think you want an || operator instead of the && operator, right?

Good catch on that. It should be OR.
i.e. if (!con->partner || !IS_MIN_VERSION_2_0(con->ucsi))

>
> > + return 0;
> > +
> > + command = UCSI_GET_CONNECTOR_CAPABILITY | UCSI_CONNECTOR_NUMBER(con->num);
> > + ret = ucsi_send_command(con->ucsi, command, &con->cap, sizeof(con->cap));
> > + if (ret < 0) {
> > + dev_err(con->ucsi->dev, "GET_CONNECTOR_CAPABILITY failed (%d)\n", ret);
> > + return ret;
> > + }
> > +
> > + typec_partner_set_pd_revision(
> > + con->partner,
> > + UCSI_CONCAP_FLAG_PARTNER_PD_MAJOR_REV_AS_BCD(con->cap.flags));
> > +
> > + return ret;
> > +}
> > +
> > static int ucsi_check_connection(struct ucsi_connector *con)
> > {
> > u8 prev_flags = con->status.flags;
>
> Thanks,

2024-01-24 19:22:25

by Prashant Malani

[permalink] [raw]
Subject: Re: [PATCH v1 3/3] usb: typec: ucsi: Get PD revision for partner

Hi Abhishek,

On Tue, Jan 23, 2024 at 2:30 PM Abhishek Pandit-Subedi
<[email protected]> wrote:
>
> From: Abhishek Pandit-Subedi <[email protected]>
>
> PD major revision for the port partner is described in
> GET_CONNECTOR_CAPABILITY and is only valid on UCSI 2.0 and newer. Update
> the pd_revision on the partner if the UCSI version is 2.0 or newer.
>
> Signed-off-by: Abhishek Pandit-Subedi <[email protected]>
> ---
> $ cat /sys/class/typec/port2-partner/usb_power_delivery_revision
> 3.0
>
> drivers/usb/typec/ucsi/ucsi.c | 25 +++++++++++++++++++++++++
> drivers/usb/typec/ucsi/ucsi.h | 3 +++
> 2 files changed, 28 insertions(+)
>
> diff --git a/drivers/usb/typec/ucsi/ucsi.c b/drivers/usb/typec/ucsi/ucsi.c
> index 4edf785d203b..8e0a512853ba 100644
> --- a/drivers/usb/typec/ucsi/ucsi.c
> +++ b/drivers/usb/typec/ucsi/ucsi.c
> @@ -782,6 +782,8 @@ static int ucsi_register_partner(struct ucsi_connector *con)
> }
>
> desc.usb_pd = pwr_opmode == UCSI_CONSTAT_PWR_OPMODE_PD;
> + desc.pd_revision =
> + UCSI_CONCAP_FLAG_PARTNER_PD_MAJOR_REV_AS_BCD(con->cap.flags);
>
> partner = typec_register_partner(con->port, &desc);
> if (IS_ERR(partner)) {
> @@ -856,6 +858,28 @@ static void ucsi_partner_change(struct ucsi_connector *con)
> con->num, u_role);
> }
>
> +static int ucsi_check_connector_capability(struct ucsi_connector *con)
> +{
> + u64 command;
> + int ret;
> +
> + if (!con->partner && !IS_MIN_VERSION_2_0(con->ucsi))

(Mentioned side-band but reproducing here for consistency)
This macro is unnecessary. It's just doing a comparison, which can be inlined
without any perceptible change in readability (actually, I'd argue adding the !
to an english idiom makes things *less* readable):

if (!con->partner && con->ucsi->version < UCSI_VERSION_2_0)
return 0;

Besides that, I think you want an || operator instead of the && operator, right?

> + return 0;
> +
> + command = UCSI_GET_CONNECTOR_CAPABILITY | UCSI_CONNECTOR_NUMBER(con->num);
> + ret = ucsi_send_command(con->ucsi, command, &con->cap, sizeof(con->cap));
> + if (ret < 0) {
> + dev_err(con->ucsi->dev, "GET_CONNECTOR_CAPABILITY failed (%d)\n", ret);
> + return ret;
> + }
> +
> + typec_partner_set_pd_revision(
> + con->partner,
> + UCSI_CONCAP_FLAG_PARTNER_PD_MAJOR_REV_AS_BCD(con->cap.flags));
> +
> + return ret;
> +}
> +
> static int ucsi_check_connection(struct ucsi_connector *con)
> {
> u8 prev_flags = con->status.flags;

Thanks,

2024-01-24 19:34:49

by Prashant Malani

[permalink] [raw]
Subject: Re: [PATCH v1 3/3] usb: typec: ucsi: Get PD revision for partner

On Wed, Jan 24, 2024 at 11:18 AM Abhishek Pandit-Subedi
<[email protected]> wrote:
>
> On Wed, Jan 24, 2024 at 10:49 AM Prashant Malani <[email protected]> wrote:
> >
> > Hi Abhishek,
> >
> > On Tue, Jan 23, 2024 at 2:30 PM Abhishek Pandit-Subedi
> > <[email protected]> wrote:
> > >
> > > From: Abhishek Pandit-Subedi <[email protected]>
> > >
> > > PD major revision for the port partner is described in
> > > GET_CONNECTOR_CAPABILITY and is only valid on UCSI 2.0 and newer. Update
> > > the pd_revision on the partner if the UCSI version is 2.0 or newer.
> > >
> > > Signed-off-by: Abhishek Pandit-Subedi <[email protected]>
> > > ---
> > > $ cat /sys/class/typec/port2-partner/usb_power_delivery_revision
> > > 3.0
> > >
> > > drivers/usb/typec/ucsi/ucsi.c | 25 +++++++++++++++++++++++++
> > > drivers/usb/typec/ucsi/ucsi.h | 3 +++
> > > 2 files changed, 28 insertions(+)
> > >
> > > diff --git a/drivers/usb/typec/ucsi/ucsi.c b/drivers/usb/typec/ucsi/ucsi.c
> > > index 4edf785d203b..8e0a512853ba 100644
> > > --- a/drivers/usb/typec/ucsi/ucsi.c
> > > +++ b/drivers/usb/typec/ucsi/ucsi.c
> > > @@ -782,6 +782,8 @@ static int ucsi_register_partner(struct ucsi_connector *con)
> > > }
> > >
> > > desc.usb_pd = pwr_opmode == UCSI_CONSTAT_PWR_OPMODE_PD;
> > > + desc.pd_revision =
> > > + UCSI_CONCAP_FLAG_PARTNER_PD_MAJOR_REV_AS_BCD(con->capflags);
> > >
> > > partner = typec_register_partner(con->port, &desc);
> > > if (IS_ERR(partner)) {
> > > @@ -856,6 +858,28 @@ static void ucsi_partner_change(struct ucsi_connector *con)
> > > con->num, u_role);
> > > }
> > >
> > > +static int ucsi_check_connector_capability(struct ucsi_connector *con)
> > > +{
> > > + u64 command;
> > > + int ret;
> > > +
> > > + if (!con->partner && !IS_MIN_VERSION_2_0(con->ucsi))
> >
> > (Mentioned side-band but reproducing here for consistency)
> > This macro is unnecessary. It's just doing a comparison, which can be inlined
> > without any perceptible change in readability (actually, I'd argue adding the !
> > to an english idiom makes things *less* readable):
>
> I prefer the macro because it makes it easier to search where version
> checks are being done.

I don't see how searching for "IS_MIN_VERSION_2_0" is easier
than just searching for "UCSI_VERSION_2_0".

I didn't quite understand what you meant by

> it keeps the `<` vs `<=` consistent.

Perhaps I'm missing something... (are these comparisons being
used elsewhere/in some other fashion?).

In any case, I don't want to bike-shed so I'll defer to the
maintainer's call on this.

BR,

-Prashant

2024-01-24 21:51:16

by Heikki Krogerus

[permalink] [raw]
Subject: Re: [PATCH v1 3/3] usb: typec: ucsi: Get PD revision for partner

Hi Abhishek,

Few nitpicks for this one.

On Tue, Jan 23, 2024 at 02:30:36PM -0800, Abhishek Pandit-Subedi wrote:
> From: Abhishek Pandit-Subedi <[email protected]>
>
> PD major revision for the port partner is described in
> GET_CONNECTOR_CAPABILITY and is only valid on UCSI 2.0 and newer. Update
> the pd_revision on the partner if the UCSI version is 2.0 or newer.
>
> Signed-off-by: Abhishek Pandit-Subedi <[email protected]>
> ---
> $ cat /sys/class/typec/port2-partner/usb_power_delivery_revision
> 3.0
>
> drivers/usb/typec/ucsi/ucsi.c | 25 +++++++++++++++++++++++++
> drivers/usb/typec/ucsi/ucsi.h | 3 +++
> 2 files changed, 28 insertions(+)
>
> diff --git a/drivers/usb/typec/ucsi/ucsi.c b/drivers/usb/typec/ucsi/ucsi.c
> index 4edf785d203b..8e0a512853ba 100644
> --- a/drivers/usb/typec/ucsi/ucsi.c
> +++ b/drivers/usb/typec/ucsi/ucsi.c
> @@ -782,6 +782,8 @@ static int ucsi_register_partner(struct ucsi_connector *con)
> }
>
> desc.usb_pd = pwr_opmode == UCSI_CONSTAT_PWR_OPMODE_PD;
> + desc.pd_revision =
> + UCSI_CONCAP_FLAG_PARTNER_PD_MAJOR_REV_AS_BCD(con->cap.flags);

desc.pd_revision = UCSI_CONCAP_FLAG_PARTNER_PD_MAJOR_REV_AS_BCD(con->cap.flags);

> partner = typec_register_partner(con->port, &desc);
> if (IS_ERR(partner)) {
> @@ -856,6 +858,28 @@ static void ucsi_partner_change(struct ucsi_connector *con)
> con->num, u_role);
> }
>
> +static int ucsi_check_connector_capability(struct ucsi_connector *con)
> +{
> + u64 command;
> + int ret;
> +
> + if (!con->partner && !IS_MIN_VERSION_2_0(con->ucsi))
> + return 0;
> +
> + command = UCSI_GET_CONNECTOR_CAPABILITY | UCSI_CONNECTOR_NUMBER(con->num);
> + ret = ucsi_send_command(con->ucsi, command, &con->cap, sizeof(con->cap));
> + if (ret < 0) {
> + dev_err(con->ucsi->dev, "GET_CONNECTOR_CAPABILITY failed (%d)\n", ret);
> + return ret;
> + }
> +
> + typec_partner_set_pd_revision(
> + con->partner,
> + UCSI_CONCAP_FLAG_PARTNER_PD_MAJOR_REV_AS_BCD(con->cap.flags));

typec_partner_set_pd_revision(con->partner,
UCSI_CONCAP_FLAG_PARTNER_PD_MAJOR_REV_AS_BCD(con->cap.flags));

> +
> + return ret;
> +}
> +
> static int ucsi_check_connection(struct ucsi_connector *con)
> {
> u8 prev_flags = con->status.flags;
> @@ -925,6 +949,7 @@ static void ucsi_handle_connector_change(struct work_struct *work)
> if (con->status.flags & UCSI_CONSTAT_CONNECTED) {
> ucsi_register_partner(con);
> ucsi_partner_task(con, ucsi_check_connection, 1, HZ);
> + ucsi_partner_task(con, ucsi_check_connector_capability, 1, HZ);
>
> if (UCSI_CONSTAT_PWR_OPMODE(con->status.flags) ==
> UCSI_CONSTAT_PWR_OPMODE_PD)
> diff --git a/drivers/usb/typec/ucsi/ucsi.h b/drivers/usb/typec/ucsi/ucsi.h
> index 94b373378f63..5e60328f398e 100644
> --- a/drivers/usb/typec/ucsi/ucsi.h
> +++ b/drivers/usb/typec/ucsi/ucsi.h
> @@ -36,6 +36,9 @@ struct dentry;
> #define UCSI_BCD_GET_MINOR(_v_) (((_v_) >> 4) & 0x0F)
> #define UCSI_BCD_GET_SUBMINOR(_v_) ((_v_) & 0x0F)
>
> +#define IS_MIN_VERSION(ucsi, min_ver) ((ucsi)->version >= min_ver)

Probable better to use brackets also with that min_ver:

#define IS_MIN_VERSION(ucsi, min_ver) ((ucsi)->version >= (min_ver))

> +#define IS_MIN_VERSION_2_0(ucsi) IS_MIN_VERSION(ucsi, UCSI_VERSION_2_0)
> +
> /* Command Status and Connector Change Indication (CCI) bits */
> #define UCSI_CCI_CONNECTOR(_c_) (((_c_) & GENMASK(7, 1)) >> 1)
> #define UCSI_CCI_LENGTH(_c_) (((_c_) & GENMASK(15, 8)) >> 8)
> --
> 2.43.0.429.g432eaa2c6b-goog

thanks,

--
heikki

2024-01-24 23:06:32

by Abhishek Pandit-Subedi

[permalink] [raw]
Subject: Re: [PATCH v1 3/3] usb: typec: ucsi: Get PD revision for partner

On Wed, Jan 24, 2024 at 11:34 AM Prashant Malani <[email protected]> wrote:
>
> On Wed, Jan 24, 2024 at 11:18 AM Abhishek Pandit-Subedi
> <[email protected]> wrote:
> >
> > On Wed, Jan 24, 2024 at 10:49 AM Prashant Malani <[email protected]> wrote:
> > >
> > > Hi Abhishek,
> > >
> > > On Tue, Jan 23, 2024 at 2:30 PM Abhishek Pandit-Subedi
> > > <[email protected]> wrote:
> > > >
> > > > From: Abhishek Pandit-Subedi <[email protected]>
> > > >
> > > > PD major revision for the port partner is described in
> > > > GET_CONNECTOR_CAPABILITY and is only valid on UCSI 2.0 and newer. Update
> > > > the pd_revision on the partner if the UCSI version is 2.0 or newer.
> > > >
> > > > Signed-off-by: Abhishek Pandit-Subedi <[email protected]>
> > > > ---
> > > > $ cat /sys/class/typec/port2-partner/usb_power_delivery_revision
> > > > 3.0
> > > >
> > > > drivers/usb/typec/ucsi/ucsi.c | 25 +++++++++++++++++++++++++
> > > > drivers/usb/typec/ucsi/ucsi.h | 3 +++
> > > > 2 files changed, 28 insertions(+)
> > > >
> > > > diff --git a/drivers/usb/typec/ucsi/ucsi.c b/drivers/usb/typec/ucsi/ucsi.c
> > > > index 4edf785d203b..8e0a512853ba 100644
> > > > --- a/drivers/usb/typec/ucsi/ucsi.c
> > > > +++ b/drivers/usb/typec/ucsi/ucsi.c
> > > > @@ -782,6 +782,8 @@ static int ucsi_register_partner(struct ucsi_connector *con)
> > > > }
> > > >
> > > > desc.usb_pd = pwr_opmode == UCSI_CONSTAT_PWR_OPMODE_PD;
> > > > + desc.pd_revision =
> > > > + UCSI_CONCAP_FLAG_PARTNER_PD_MAJOR_REV_AS_BCD(con->cap.flags);
> > > >
> > > > partner = typec_register_partner(con->port, &desc);
> > > > if (IS_ERR(partner)) {
> > > > @@ -856,6 +858,28 @@ static void ucsi_partner_change(struct ucsi_connector *con)
> > > > con->num, u_role);
> > > > }
> > > >
> > > > +static int ucsi_check_connector_capability(struct ucsi_connector *con)
> > > > +{
> > > > + u64 command;
> > > > + int ret;
> > > > +
> > > > + if (!con->partner && !IS_MIN_VERSION_2_0(con->ucsi))
> > >
> > > (Mentioned side-band but reproducing here for consistency)
> > > This macro is unnecessary. It's just doing a comparison, which can be inlined
> > > without any perceptible change in readability (actually, I'd argue adding the !
> > > to an english idiom makes things *less* readable):
> >
> > I prefer the macro because it makes it easier to search where version
> > checks are being done.
>
> I don't see how searching for "IS_MIN_VERSION_2_0" is easier
> than just searching for "UCSI_VERSION_2_0".
>
> I didn't quite understand what you meant by
>
> > it keeps the `<` vs `<=` consistent.
>
> Perhaps I'm missing something... (are these comparisons being
> used elsewhere/in some other fashion?).

Let's say someone wants to guard code for UCSI 2.0.
Should they use:

// Guard against older versions.
if (ucsi->version < UCSI_VERSION_2_0) return;

// This also guards since the version jumps from 1.2 to 2.0.
if (ucsi->version <= UCSI_VERSION_1_2) return;

// Only do something on newer versions.
if (ucsi->version >= UCSI_VERSION_2_0) {
// Fill out something available in newer spec.
}

I'd rather everyone just use a macro that normalizes comparisons. It's
always IS_MIN_VERSION and its inverse !IS_MIN_VERSION.
It's personal preference so deferring to the maintainer is IMO the
right call here.

>
> In any case, I don't want to bike-shed so I'll defer to the
> maintainer's call on this.
>
> BR,
>
> -Prashant

2024-01-25 23:17:34

by Greg KH

[permalink] [raw]
Subject: Re: [PATCH v1 1/3] usb: typec: ucsi: Limit read size on v1.2

On Wed, Jan 24, 2024 at 10:59:28AM -0800, Abhishek Pandit-Subedi wrote:
> Ack. Will make dev_dbg on the next iteration.
>
> This seems like a good addition to the style guide too:
> https://www.kernel.org/doc/html/v6.7/process/coding-style.html#printing-kernel-messages.
> "When drivers are working properly, they are quiet. Prefer to use
> DEBUG messages unless something is wrong."
>
> What do you think Greg?

I think you need to stop top-posting :)

But yes, that would be nice, hopefully people actually notice it there.
Would you have read this and seen it?

thanks,

greg k-h

2024-01-25 23:37:39

by Abhishek Pandit-Subedi

[permalink] [raw]
Subject: Re: [PATCH v1 1/3] usb: typec: ucsi: Limit read size on v1.2

On Thu, Jan 25, 2024 at 3:16 PM Greg Kroah-Hartman
<[email protected]> wrote:
>
> On Wed, Jan 24, 2024 at 10:59:28AM -0800, Abhishek Pandit-Subedi wrote:
> > Ack. Will make dev_dbg on the next iteration.
> >
> > This seems like a good addition to the style guide too:
> > https://www.kernel.org/doc/html/v6.7/process/coding-style.html#printing-kernel-messages.
> > "When drivers are working properly, they are quiet. Prefer to use
> > DEBUG messages unless something is wrong."
> >
> > What do you think Greg?
>
> I think you need to stop top-posting :)
>
> But yes, that would be nice, hopefully people actually notice it there.
> Would you have read this and seen it?
>
> thanks,
>
> greg k-h

I blame gmail web-interface for the top-posting :)

Prashant also mentioned the dev_info when we were reviewing this so I
did a quick search for "kernel coding style" (to see if there was
guidance) before sending this up so I would definitely have noticed it
there.
In Bluetooth (where I've previously contributed), dev_info is used for
printing version info (example:
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/bluetooth/btintel.c?h=v6.8-rc1#n337)
and it's very useful for debugging so I assumed it was acceptable.

The added benefit of this guidance being in the coding style guide is
it's a quick change to checkpatch.pl to add a warning for this (and
point to the coding style as the source). I'm fairly sure Chromium
actually has a lint that warns whenever you use LOG_INFO(...) for
similar reasons (too many INFO messages that should be DEBUG).

I will send up a patch with the change soon (both to coding style and
checkpatch.pl).

Thanks,
Abhishek