diff mbox series

typec: Provide USB PD Specification Revision for cable and partner

Message ID 20201030044224.GA1269490@google.com (mailing list archive)
State New, archived
Headers show
Series typec: Provide USB PD Specification Revision for cable and partner | expand

Commit Message

Benson Leung Oct. 30, 2020, 4:42 a.m. UTC
The USB Power Delivery specification Section 6.2.1.1.5 outlines
revision backward compatibility requirements starting from Revision 3.0.

The Port, the Cable Plug, and the Port Partner may support either revision
2 or revision 3 individually, and communication between ports, partners,
and cables of different revisions are allowed under rules that the parties
agree to communicate between each other using the lowest common operating
revision.

This may mean that Port-to-Port operating revision comms may be different
than Port-to-CablePlug operating revision comms. For example, it is
possible for a R3.0 port to communicate with a R3.0 cable using R3.0
messages, while the R3.0 port (in the same session) must communicate with
a R2.0 partner using PD R2.0 messages only.

This change will introduce individual revision number tracking for cable
and port partner so that the port can track them independently.

This will also enable future changes which change cable identifier
decoding and visible sysfs nodes based on revision 2 or 3.

Signed-off-by: Benson Leung <bleung@chromium.org>
---
 Documentation/ABI/testing/sysfs-class-typec |  8 +++++
 drivers/usb/typec/class.c                   | 38 +++++++++++++++------
 include/linux/usb/typec.h                   | 10 ++++++
 3 files changed, 46 insertions(+), 10 deletions(-)

Comments

Greg Kroah-Hartman Oct. 30, 2020, 10:34 a.m. UTC | #1
On Thu, Oct 29, 2020 at 09:42:24PM -0700, Benson Leung wrote:
> The USB Power Delivery specification Section 6.2.1.1.5 outlines
> revision backward compatibility requirements starting from Revision 3.0.
> 
> The Port, the Cable Plug, and the Port Partner may support either revision
> 2 or revision 3 individually, and communication between ports, partners,
> and cables of different revisions are allowed under rules that the parties
> agree to communicate between each other using the lowest common operating
> revision.
> 
> This may mean that Port-to-Port operating revision comms may be different
> than Port-to-CablePlug operating revision comms. For example, it is
> possible for a R3.0 port to communicate with a R3.0 cable using R3.0
> messages, while the R3.0 port (in the same session) must communicate with
> a R2.0 partner using PD R2.0 messages only.
> 
> This change will introduce individual revision number tracking for cable
> and port partner so that the port can track them independently.
> 
> This will also enable future changes which change cable identifier
> decoding and visible sysfs nodes based on revision 2 or 3.
> 
> Signed-off-by: Benson Leung <bleung@chromium.org>
> ---
>  Documentation/ABI/testing/sysfs-class-typec |  8 +++++
>  drivers/usb/typec/class.c                   | 38 +++++++++++++++------
>  include/linux/usb/typec.h                   | 10 ++++++
>  3 files changed, 46 insertions(+), 10 deletions(-)
> 
> diff --git a/Documentation/ABI/testing/sysfs-class-typec b/Documentation/ABI/testing/sysfs-class-typec
> index b834671522d6..740b226bb80e 100644
> --- a/Documentation/ABI/testing/sysfs-class-typec
> +++ b/Documentation/ABI/testing/sysfs-class-typec
> @@ -102,6 +102,14 @@ Description:
>  		Revision number of the supported USB Power Delivery
>  		specification, or 0 when USB Power Delivery is not supported.
>  
> +What:		/sys/class/typec/<port>-{partner|cable}/usb_power_delivery_revision
> +Date:		October 2020
> +Contact:	Benson Leung <bleung@chromium.org>
> +Description:
> +		Revision number of the supported USB Power Delivery
> +		specification of the port partner or cable, or 0 when USB Power
> +		Delivery is not supported.
> +
>  What:		/sys/class/typec/<port>/usb_typec_revision
>  Date:		April 2017
>  Contact:	Heikki Krogerus <heikki.krogerus@linux.intel.com>
> diff --git a/drivers/usb/typec/class.c b/drivers/usb/typec/class.c
> index 35eec707cb51..abae4cbe66d5 100644
> --- a/drivers/usb/typec/class.c
> +++ b/drivers/usb/typec/class.c
> @@ -25,6 +25,7 @@ struct typec_cable {
>  	enum typec_plug_type		type;
>  	struct usb_pd_identity		*identity;
>  	unsigned int			active:1;
> +	u16				pd_revision; /* 0300H = "3.0" */
>  };
>  
>  struct typec_partner {
> @@ -33,6 +34,7 @@ struct typec_partner {
>  	struct usb_pd_identity		*identity;
>  	enum typec_accessory		accessory;
>  	struct ida			mode_ids;
> +	u16				pd_revision; /* 0300H = "3.0" */
>  };
>  
>  struct typec_port {
> @@ -146,6 +148,28 @@ static void typec_report_identity(struct device *dev)
>  	sysfs_notify(&dev->kobj, "identity", "product");
>  }
>  
> +static ssize_t usb_power_delivery_revision_show(struct device *dev,
> +						struct device_attribute *attr,
> +						char *buf)
> +{
> +	if (is_typec_partner(dev)) {
> +		struct typec_partner *partner = to_typec_partner(dev);
> +
> +		return sprintf(buf, "%d\n", (partner->pd_revision >> 8) & 0xff);
> +	} else if (is_typec_cable(dev)) {
> +		struct typec_cable *cable = to_typec_cable(dev);
> +
> +		return sprintf(buf, "%d\n", (cable->pd_revision >> 8) & 0xff);
> +	} else if (is_typec_port(dev)) {
> +		struct typec_port *p = to_typec_port(dev);
> +
> +		return sprintf(buf, "%d\n", (p->cap->pd_revision >> 8) & 0xff);

nit, you can use sysfs_emit() for the sprintf() calls in sysfs
attributes now.

> +	}
> +}
> +static DEVICE_ATTR_RO(usb_power_delivery_revision);
> +
> +
> +

2 extra blank lines are not needed :(

>  /* ------------------------------------------------------------------------- */
>  /* Alternate Modes */
>  
> @@ -535,6 +559,7 @@ static DEVICE_ATTR_RO(supports_usb_power_delivery);
>  static struct attribute *typec_partner_attrs[] = {
>  	&dev_attr_accessory_mode.attr,
>  	&dev_attr_supports_usb_power_delivery.attr,
> +	&dev_attr_usb_power_delivery_revision.attr,
>  	NULL
>  };
>  ATTRIBUTE_GROUPS(typec_partner);
> @@ -612,6 +637,7 @@ struct typec_partner *typec_register_partner(struct typec_port *port,
>  	ida_init(&partner->mode_ids);
>  	partner->usb_pd = desc->usb_pd;
>  	partner->accessory = desc->accessory;
> +	partner->pd_revision = desc->pd_revision;
>  
>  	if (desc->identity) {
>  		/*
> @@ -773,6 +799,7 @@ static DEVICE_ATTR_RO(plug_type);
>  static struct attribute *typec_cable_attrs[] = {
>  	&dev_attr_type.attr,
>  	&dev_attr_plug_type.attr,
> +	&dev_attr_usb_power_delivery_revision.attr,
>  	NULL
>  };
>  ATTRIBUTE_GROUPS(typec_cable);
> @@ -875,6 +902,7 @@ struct typec_cable *typec_register_cable(struct typec_port *port,
>  
>  	cable->type = desc->type;
>  	cable->active = desc->active;
> +	cable->pd_revision = desc->pd_revision;
>  
>  	if (desc->identity) {
>  		/*
> @@ -1240,16 +1268,6 @@ static ssize_t usb_typec_revision_show(struct device *dev,
>  }
>  static DEVICE_ATTR_RO(usb_typec_revision);
>  
> -static ssize_t usb_power_delivery_revision_show(struct device *dev,
> -						struct device_attribute *attr,
> -						char *buf)
> -{
> -	struct typec_port *p = to_typec_port(dev);
> -
> -	return sprintf(buf, "%d\n", (p->cap->pd_revision >> 8) & 0xff);
> -}
> -static DEVICE_ATTR_RO(usb_power_delivery_revision);
> -
>  static ssize_t orientation_show(struct device *dev,
>  				   struct device_attribute *attr,
>  				   char *buf)
> diff --git a/include/linux/usb/typec.h b/include/linux/usb/typec.h
> index 6be558045942..2306d40e18a1 100644
> --- a/include/linux/usb/typec.h
> +++ b/include/linux/usb/typec.h
> @@ -162,6 +162,7 @@ struct typec_plug_desc {
>   * @type: The plug type from USB PD Cable VDO
>   * @active: Is the cable active or passive
>   * @identity: Result of Discover Identity command
> + * @pd_revision: USB Power Delivery Specification revision if supported
>   *
>   * Represents USB Type-C Cable attached to USB Type-C port.
>   */
> @@ -169,6 +170,8 @@ struct typec_cable_desc {
>  	enum typec_plug_type	type;
>  	unsigned int		active:1;
>  	struct usb_pd_identity	*identity;
> +	u16			pd_revision; /* 0300H = "3.0" */
> +
>  };
>  
>  /*
> @@ -176,15 +179,22 @@ struct typec_cable_desc {
>   * @usb_pd: USB Power Delivery support
>   * @accessory: Audio, Debug or none.
>   * @identity: Discover Identity command data
> + * @pd_revision: USB Power Delivery Specification Revision if supported
>   *
>   * Details about a partner that is attached to USB Type-C port. If @identity
>   * member exists when partner is registered, a directory named "identity" is
>   * created to sysfs for the partner device.
> + *
> + * @pd_revision is based on the setting of the "Specification Revision" field
> + * in the message header on the initial "Source Capabilities" message receieved
> + * from the partner, or a "Request" message received from the partner, depending
> + * on whether our port is a Sink or a Source.
>   */
>  struct typec_partner_desc {
>  	unsigned int		usb_pd:1;
>  	enum typec_accessory	accessory;
>  	struct usb_pd_identity	*identity;
> +	u16			pd_revision; /* 0300H = "3.0" */

No endian issues?  Where are you reading this data from?  How is it in
"native cpu" endian already?

thanks,

greg k-h
kernel test robot Nov. 2, 2020, 1:32 p.m. UTC | #2
Hi Benson,

I love your patch! Yet something to improve:

[auto build test ERROR on usb/usb-testing]
[also build test ERROR on chrome-platform-linux/for-next linus/master v5.10-rc2 next-20201102]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Benson-Leung/typec-Provide-USB-PD-Specification-Revision-for-cable-and-partner/20201030-124250
base:   https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb.git usb-testing
config: arm-randconfig-r033-20201030 (attached as .config)
compiler: clang version 12.0.0 (https://github.com/llvm/llvm-project fa5a13276764a2657b3571fa3c57b07ee5d2d661)
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # install arm cross compiling tool for clang build
        # apt-get install binutils-arm-linux-gnueabi
        # https://github.com/0day-ci/linux/commit/dca7134400af678fe4f5e4d94a7ec74487d9fcc1
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Benson-Leung/typec-Provide-USB-PD-Specification-Revision-for-cable-and-partner/20201030-124250
        git checkout dca7134400af678fe4f5e4d94a7ec74487d9fcc1
        # save the attached .config to linux build tree
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross ARCH=arm 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All errors (new ones prefixed by >>):

>> drivers/usb/typec/class.c:168:1: error: non-void function does not return a value in all control paths [-Werror,-Wreturn-type]
   }
   ^
   1 error generated.

vim +168 drivers/usb/typec/class.c

   150	
   151	static ssize_t usb_power_delivery_revision_show(struct device *dev,
   152							struct device_attribute *attr,
   153							char *buf)
   154	{
   155		if (is_typec_partner(dev)) {
   156			struct typec_partner *partner = to_typec_partner(dev);
   157	
   158			return sprintf(buf, "%d\n", (partner->pd_revision >> 8) & 0xff);
   159		} else if (is_typec_cable(dev)) {
   160			struct typec_cable *cable = to_typec_cable(dev);
   161	
   162			return sprintf(buf, "%d\n", (cable->pd_revision >> 8) & 0xff);
   163		} else if (is_typec_port(dev)) {
   164			struct typec_port *p = to_typec_port(dev);
   165	
   166			return sprintf(buf, "%d\n", (p->cap->pd_revision >> 8) & 0xff);
   167		}
 > 168	}
   169	static DEVICE_ATTR_RO(usb_power_delivery_revision);
   170	
   171	
   172	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
diff mbox series

Patch

diff --git a/Documentation/ABI/testing/sysfs-class-typec b/Documentation/ABI/testing/sysfs-class-typec
index b834671522d6..740b226bb80e 100644
--- a/Documentation/ABI/testing/sysfs-class-typec
+++ b/Documentation/ABI/testing/sysfs-class-typec
@@ -102,6 +102,14 @@  Description:
 		Revision number of the supported USB Power Delivery
 		specification, or 0 when USB Power Delivery is not supported.
 
+What:		/sys/class/typec/<port>-{partner|cable}/usb_power_delivery_revision
+Date:		October 2020
+Contact:	Benson Leung <bleung@chromium.org>
+Description:
+		Revision number of the supported USB Power Delivery
+		specification of the port partner or cable, or 0 when USB Power
+		Delivery is not supported.
+
 What:		/sys/class/typec/<port>/usb_typec_revision
 Date:		April 2017
 Contact:	Heikki Krogerus <heikki.krogerus@linux.intel.com>
diff --git a/drivers/usb/typec/class.c b/drivers/usb/typec/class.c
index 35eec707cb51..abae4cbe66d5 100644
--- a/drivers/usb/typec/class.c
+++ b/drivers/usb/typec/class.c
@@ -25,6 +25,7 @@  struct typec_cable {
 	enum typec_plug_type		type;
 	struct usb_pd_identity		*identity;
 	unsigned int			active:1;
+	u16				pd_revision; /* 0300H = "3.0" */
 };
 
 struct typec_partner {
@@ -33,6 +34,7 @@  struct typec_partner {
 	struct usb_pd_identity		*identity;
 	enum typec_accessory		accessory;
 	struct ida			mode_ids;
+	u16				pd_revision; /* 0300H = "3.0" */
 };
 
 struct typec_port {
@@ -146,6 +148,28 @@  static void typec_report_identity(struct device *dev)
 	sysfs_notify(&dev->kobj, "identity", "product");
 }
 
+static ssize_t usb_power_delivery_revision_show(struct device *dev,
+						struct device_attribute *attr,
+						char *buf)
+{
+	if (is_typec_partner(dev)) {
+		struct typec_partner *partner = to_typec_partner(dev);
+
+		return sprintf(buf, "%d\n", (partner->pd_revision >> 8) & 0xff);
+	} else if (is_typec_cable(dev)) {
+		struct typec_cable *cable = to_typec_cable(dev);
+
+		return sprintf(buf, "%d\n", (cable->pd_revision >> 8) & 0xff);
+	} else if (is_typec_port(dev)) {
+		struct typec_port *p = to_typec_port(dev);
+
+		return sprintf(buf, "%d\n", (p->cap->pd_revision >> 8) & 0xff);
+	}
+}
+static DEVICE_ATTR_RO(usb_power_delivery_revision);
+
+
+
 /* ------------------------------------------------------------------------- */
 /* Alternate Modes */
 
@@ -535,6 +559,7 @@  static DEVICE_ATTR_RO(supports_usb_power_delivery);
 static struct attribute *typec_partner_attrs[] = {
 	&dev_attr_accessory_mode.attr,
 	&dev_attr_supports_usb_power_delivery.attr,
+	&dev_attr_usb_power_delivery_revision.attr,
 	NULL
 };
 ATTRIBUTE_GROUPS(typec_partner);
@@ -612,6 +637,7 @@  struct typec_partner *typec_register_partner(struct typec_port *port,
 	ida_init(&partner->mode_ids);
 	partner->usb_pd = desc->usb_pd;
 	partner->accessory = desc->accessory;
+	partner->pd_revision = desc->pd_revision;
 
 	if (desc->identity) {
 		/*
@@ -773,6 +799,7 @@  static DEVICE_ATTR_RO(plug_type);
 static struct attribute *typec_cable_attrs[] = {
 	&dev_attr_type.attr,
 	&dev_attr_plug_type.attr,
+	&dev_attr_usb_power_delivery_revision.attr,
 	NULL
 };
 ATTRIBUTE_GROUPS(typec_cable);
@@ -875,6 +902,7 @@  struct typec_cable *typec_register_cable(struct typec_port *port,
 
 	cable->type = desc->type;
 	cable->active = desc->active;
+	cable->pd_revision = desc->pd_revision;
 
 	if (desc->identity) {
 		/*
@@ -1240,16 +1268,6 @@  static ssize_t usb_typec_revision_show(struct device *dev,
 }
 static DEVICE_ATTR_RO(usb_typec_revision);
 
-static ssize_t usb_power_delivery_revision_show(struct device *dev,
-						struct device_attribute *attr,
-						char *buf)
-{
-	struct typec_port *p = to_typec_port(dev);
-
-	return sprintf(buf, "%d\n", (p->cap->pd_revision >> 8) & 0xff);
-}
-static DEVICE_ATTR_RO(usb_power_delivery_revision);
-
 static ssize_t orientation_show(struct device *dev,
 				   struct device_attribute *attr,
 				   char *buf)
diff --git a/include/linux/usb/typec.h b/include/linux/usb/typec.h
index 6be558045942..2306d40e18a1 100644
--- a/include/linux/usb/typec.h
+++ b/include/linux/usb/typec.h
@@ -162,6 +162,7 @@  struct typec_plug_desc {
  * @type: The plug type from USB PD Cable VDO
  * @active: Is the cable active or passive
  * @identity: Result of Discover Identity command
+ * @pd_revision: USB Power Delivery Specification revision if supported
  *
  * Represents USB Type-C Cable attached to USB Type-C port.
  */
@@ -169,6 +170,8 @@  struct typec_cable_desc {
 	enum typec_plug_type	type;
 	unsigned int		active:1;
 	struct usb_pd_identity	*identity;
+	u16			pd_revision; /* 0300H = "3.0" */
+
 };
 
 /*
@@ -176,15 +179,22 @@  struct typec_cable_desc {
  * @usb_pd: USB Power Delivery support
  * @accessory: Audio, Debug or none.
  * @identity: Discover Identity command data
+ * @pd_revision: USB Power Delivery Specification Revision if supported
  *
  * Details about a partner that is attached to USB Type-C port. If @identity
  * member exists when partner is registered, a directory named "identity" is
  * created to sysfs for the partner device.
+ *
+ * @pd_revision is based on the setting of the "Specification Revision" field
+ * in the message header on the initial "Source Capabilities" message receieved
+ * from the partner, or a "Request" message received from the partner, depending
+ * on whether our port is a Sink or a Source.
  */
 struct typec_partner_desc {
 	unsigned int		usb_pd:1;
 	enum typec_accessory	accessory;
 	struct usb_pd_identity	*identity;
+	u16			pd_revision; /* 0300H = "3.0" */
 };
 
 /**