Message ID | 20220412130023.83927-3-heikki.krogerus@linux.intel.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | usb: typec: Separate sysfs directory for all USB PD objects | expand |
Hi Heikki, I love your patch! Perhaps something to improve: [auto build test WARNING on usb/usb-testing] [also build test WARNING on chrome-platform/for-next v5.18-rc2 next-20220412] [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/intel-lab-lkp/linux/commits/Heikki-Krogerus/usb-typec-Separate-sysfs-directory-for-all-USB-PD-objects/20220412-211628 base: https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb.git usb-testing config: alpha-allyesconfig (https://download.01.org/0day-ci/archive/20220412/202204122323.iqiRhgAI-lkp@intel.com/config) compiler: alpha-linux-gcc (GCC) 11.2.0 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 # https://github.com/intel-lab-lkp/linux/commit/98fece77872792e49f1005617761a533089f319d git remote add linux-review https://github.com/intel-lab-lkp/linux git fetch --no-tags linux-review Heikki-Krogerus/usb-typec-Separate-sysfs-directory-for-all-USB-PD-objects/20220412-211628 git checkout 98fece77872792e49f1005617761a533089f319d # save the config file to linux build tree mkdir build_dir COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-11.2.0 make.cross O=build_dir ARCH=alpha SHELL=/bin/bash drivers/usb/typec/ If you fix the issue, kindly add following tag as appropriate Reported-by: kernel test robot <lkp@intel.com> All warnings (new ones prefixed by >>): >> drivers/usb/typec/pd.c:669: warning: expecting prototype for pd_register(). Prototype was for pd_unregister() instead >> drivers/usb/typec/pd.c:717: warning: expecting prototype for pd_link_device(). Prototype was for pd_unlink_device() instead -- >> drivers/usb/typec/class.c:1222: warning: expecting prototype for typec_port_set_pd_capabilities(). Prototype was for typec_port_set_pd() instead vim +717 drivers/usb/typec/pd.c c99df888db9e4c Heikki Krogerus 2022-04-12 663 c99df888db9e4c Heikki Krogerus 2022-04-12 664 /** c99df888db9e4c Heikki Krogerus 2022-04-12 665 * pd_register - Unregister USB Power Delivery Support. c99df888db9e4c Heikki Krogerus 2022-04-12 666 * @pd: The USB PD contract. c99df888db9e4c Heikki Krogerus 2022-04-12 667 */ c99df888db9e4c Heikki Krogerus 2022-04-12 668 void pd_unregister(struct pd *pd) c99df888db9e4c Heikki Krogerus 2022-04-12 @669 { c99df888db9e4c Heikki Krogerus 2022-04-12 670 if (IS_ERR_OR_NULL(pd)) c99df888db9e4c Heikki Krogerus 2022-04-12 671 return; c99df888db9e4c Heikki Krogerus 2022-04-12 672 c99df888db9e4c Heikki Krogerus 2022-04-12 673 kobject_put(&pd->kobj); c99df888db9e4c Heikki Krogerus 2022-04-12 674 } c99df888db9e4c Heikki Krogerus 2022-04-12 675 EXPORT_SYMBOL_GPL(pd_unregister); c99df888db9e4c Heikki Krogerus 2022-04-12 676 c99df888db9e4c Heikki Krogerus 2022-04-12 677 /** c99df888db9e4c Heikki Krogerus 2022-04-12 678 * pd_link_device - Link device to its USB PD object. c99df888db9e4c Heikki Krogerus 2022-04-12 679 * @pd: The USB PD instance. c99df888db9e4c Heikki Krogerus 2022-04-12 680 * @dev: The device. c99df888db9e4c Heikki Krogerus 2022-04-12 681 * c99df888db9e4c Heikki Krogerus 2022-04-12 682 * This function can be used to create a symlink named "usb_power_delivery" for c99df888db9e4c Heikki Krogerus 2022-04-12 683 * @dev that points to @pd. c99df888db9e4c Heikki Krogerus 2022-04-12 684 */ c99df888db9e4c Heikki Krogerus 2022-04-12 685 int pd_link_device(struct pd *pd, struct device *dev) c99df888db9e4c Heikki Krogerus 2022-04-12 686 { c99df888db9e4c Heikki Krogerus 2022-04-12 687 int ret; c99df888db9e4c Heikki Krogerus 2022-04-12 688 c99df888db9e4c Heikki Krogerus 2022-04-12 689 if (IS_ERR_OR_NULL(pd) || !dev) c99df888db9e4c Heikki Krogerus 2022-04-12 690 return 0; c99df888db9e4c Heikki Krogerus 2022-04-12 691 c99df888db9e4c Heikki Krogerus 2022-04-12 692 ret = sysfs_create_link(&dev->kobj, &pd->kobj, "usb_power_delivery"); c99df888db9e4c Heikki Krogerus 2022-04-12 693 if (ret) c99df888db9e4c Heikki Krogerus 2022-04-12 694 return ret; c99df888db9e4c Heikki Krogerus 2022-04-12 695 c99df888db9e4c Heikki Krogerus 2022-04-12 696 ret = sysfs_create_link(&pd->kobj, &dev->kobj, dev_name(dev)); c99df888db9e4c Heikki Krogerus 2022-04-12 697 if (ret) { c99df888db9e4c Heikki Krogerus 2022-04-12 698 sysfs_remove_link(&dev->kobj, "usb_power_delivery"); c99df888db9e4c Heikki Krogerus 2022-04-12 699 return ret; c99df888db9e4c Heikki Krogerus 2022-04-12 700 } c99df888db9e4c Heikki Krogerus 2022-04-12 701 c99df888db9e4c Heikki Krogerus 2022-04-12 702 kobject_get(&pd->kobj); c99df888db9e4c Heikki Krogerus 2022-04-12 703 get_device(dev); c99df888db9e4c Heikki Krogerus 2022-04-12 704 c99df888db9e4c Heikki Krogerus 2022-04-12 705 return 0; c99df888db9e4c Heikki Krogerus 2022-04-12 706 } c99df888db9e4c Heikki Krogerus 2022-04-12 707 EXPORT_SYMBOL_GPL(pd_link_device); c99df888db9e4c Heikki Krogerus 2022-04-12 708 c99df888db9e4c Heikki Krogerus 2022-04-12 709 /** c99df888db9e4c Heikki Krogerus 2022-04-12 710 * pd_link_device - Unlink device from its USB PD object. c99df888db9e4c Heikki Krogerus 2022-04-12 711 * @pd: The USB PD instance. c99df888db9e4c Heikki Krogerus 2022-04-12 712 * @dev: The device. c99df888db9e4c Heikki Krogerus 2022-04-12 713 * c99df888db9e4c Heikki Krogerus 2022-04-12 714 * Remove the symlink that was previously created with pd_link_device(). c99df888db9e4c Heikki Krogerus 2022-04-12 715 */ c99df888db9e4c Heikki Krogerus 2022-04-12 716 void pd_unlink_device(struct pd *pd, struct device *dev) c99df888db9e4c Heikki Krogerus 2022-04-12 @717 { c99df888db9e4c Heikki Krogerus 2022-04-12 718 if (IS_ERR_OR_NULL(pd) || !dev) c99df888db9e4c Heikki Krogerus 2022-04-12 719 return; c99df888db9e4c Heikki Krogerus 2022-04-12 720 c99df888db9e4c Heikki Krogerus 2022-04-12 721 sysfs_remove_link(&dev->kobj, "usb_power_delivery"); c99df888db9e4c Heikki Krogerus 2022-04-12 722 sysfs_remove_link(&pd->kobj, dev_name(dev)); c99df888db9e4c Heikki Krogerus 2022-04-12 723 kobject_put(&pd->kobj); c99df888db9e4c Heikki Krogerus 2022-04-12 724 put_device(dev); c99df888db9e4c Heikki Krogerus 2022-04-12 725 } c99df888db9e4c Heikki Krogerus 2022-04-12 726 EXPORT_SYMBOL_GPL(pd_unlink_device); c99df888db9e4c Heikki Krogerus 2022-04-12 727
Hi Heikki, I love your patch! Perhaps something to improve: [auto build test WARNING on usb/usb-testing] [also build test WARNING on chrome-platform/for-next v5.18-rc2 next-20220412] [cannot apply to balbi-usb/testing/next peter-chen-usb/for-usb-next] [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/intel-lab-lkp/linux/commits/Heikki-Krogerus/usb-typec-Separate-sysfs-directory-for-all-USB-PD-objects/20220412-211628 base: https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb.git usb-testing config: hexagon-buildonly-randconfig-r005-20220412 (https://download.01.org/0day-ci/archive/20220413/202204130028.O6wRGxzY-lkp@intel.com/config) compiler: clang version 15.0.0 (https://github.com/llvm/llvm-project fe2478d44e4f7f191c43fef629ac7a23d0251e72) 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 # https://github.com/intel-lab-lkp/linux/commit/98fece77872792e49f1005617761a533089f319d git remote add linux-review https://github.com/intel-lab-lkp/linux git fetch --no-tags linux-review Heikki-Krogerus/usb-typec-Separate-sysfs-directory-for-all-USB-PD-objects/20220412-211628 git checkout 98fece77872792e49f1005617761a533089f319d # save the config file to linux build tree mkdir build_dir COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=hexagon SHELL=/bin/bash drivers/usb/typec/ If you fix the issue, kindly add following tag as appropriate Reported-by: kernel test robot <lkp@intel.com> All warnings (new ones prefixed by >>): >> drivers/usb/typec/class.c:30:27: warning: unused variable 'cap_name' [-Wunused-const-variable] static const char * const cap_name[] = { ^ 1 warning generated. vim +/cap_name +30 drivers/usb/typec/class.c 29 > 30 static const char * const cap_name[] = { 31 [TYPEC_SINK] = "sink-capabilities", 32 [TYPEC_SOURCE] = "source-capabilities", 33 }; 34
Hi Heikki, I love your patch! Perhaps something to improve: [auto build test WARNING on usb/usb-testing] [also build test WARNING on chrome-platform/for-next v5.18-rc2 next-20220412] [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/intel-lab-lkp/linux/commits/Heikki-Krogerus/usb-typec-Separate-sysfs-directory-for-all-USB-PD-objects/20220412-211628 base: https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb.git usb-testing config: i386-randconfig-a004-20220411 (https://download.01.org/0day-ci/archive/20220413/202204130102.YjEnm3E0-lkp@intel.com/config) compiler: clang version 15.0.0 (https://github.com/llvm/llvm-project fe2478d44e4f7f191c43fef629ac7a23d0251e72) 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 # https://github.com/intel-lab-lkp/linux/commit/98fece77872792e49f1005617761a533089f319d git remote add linux-review https://github.com/intel-lab-lkp/linux git fetch --no-tags linux-review Heikki-Krogerus/usb-typec-Separate-sysfs-directory-for-all-USB-PD-objects/20220412-211628 git checkout 98fece77872792e49f1005617761a533089f319d # save the config file to linux build tree mkdir build_dir COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=i386 SHELL=/bin/bash drivers/usb/typec/ If you fix the issue, kindly add following tag as appropriate Reported-by: kernel test robot <lkp@intel.com> All warnings (new ones prefixed by >>): >> drivers/usb/typec/class.c:30:27: warning: unused variable 'cap_name' [-Wunused-const-variable] static const char * const cap_name[] = { ^ 1 warning generated. -- >> drivers/usb/typec/pd.c:669: warning: expecting prototype for pd_register(). Prototype was for pd_unregister() instead >> drivers/usb/typec/pd.c:717: warning: expecting prototype for pd_link_device(). Prototype was for pd_unlink_device() instead -- >> drivers/usb/typec/class.c:1222: warning: expecting prototype for typec_port_set_pd_capabilities(). Prototype was for typec_port_set_pd() instead vim +/cap_name +30 drivers/usb/typec/class.c 29 > 30 static const char * const cap_name[] = { 31 [TYPEC_SINK] = "sink-capabilities", 32 [TYPEC_SOURCE] = "source-capabilities", 33 }; 34
diff --git a/Documentation/ABI/testing/sysfs-class-typec b/Documentation/ABI/testing/sysfs-class-typec index 75088ecad2029..6c528f87ecaf0 100644 --- a/Documentation/ABI/testing/sysfs-class-typec +++ b/Documentation/ABI/testing/sysfs-class-typec @@ -141,6 +141,14 @@ Description: - "reverse": CC2 orientation - "unknown": Orientation cannot be determined. +What: /sys/class/typec/<port>/select_usb_power_delivery +Date: February 2022 +Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com> +Description: + Lists the USB Power Delivery Capabilities that the port can + advertise to the partner. The currently used capabilities are in + brackets. Selection happens by writing to the file. + USB Type-C partner devices (eg. /sys/class/typec/port0-partner/) What: /sys/class/typec/<port>-partner/accessory_mode diff --git a/drivers/usb/typec/class.c b/drivers/usb/typec/class.c index ee0e520707dd7..770d7d38c9b57 100644 --- a/drivers/usb/typec/class.c +++ b/drivers/usb/typec/class.c @@ -15,6 +15,7 @@ #include "bus.h" #include "class.h" +#include "pd.h" static DEFINE_IDA(typec_index_ida); @@ -26,6 +27,11 @@ struct class typec_class = { /* ------------------------------------------------------------------------- */ /* Common attributes */ +static const char * const cap_name[] = { + [TYPEC_SINK] = "sink-capabilities", + [TYPEC_SOURCE] = "source-capabilities", +}; + static const char * const typec_accessory_modes[] = { [TYPEC_ACCESSORY_NONE] = "none", [TYPEC_ACCESSORY_AUDIO] = "analog_audio", @@ -720,6 +726,38 @@ void typec_partner_set_pd_revision(struct typec_partner *partner, u16 pd_revisio } EXPORT_SYMBOL_GPL(typec_partner_set_pd_revision); +/** + * typec_partner_set_pd - Declare USB Power Delivery Contract. + * @partner: The partner device. + * @pd: The USB PD instance. + * + * This routine can be used to declare USB Power Delivery Contract with @partner + * by linking @partner to @pd which contains the objects that were used during the + * negotiation of the contract. + * + * If @pd is NULL, the link is removed and the contract with @partner has ended. + */ +int typec_partner_set_pd(struct typec_partner *partner, struct pd *pd) +{ + int ret; + + if (IS_ERR_OR_NULL(partner) || partner->pd == pd) + return 0; + + if (pd) { + ret = pd_link_device(pd, &partner->dev); + if (ret) + return ret; + } else { + pd_unlink_device(partner->pd, &partner->dev); + } + + partner->pd = pd; + + return 0; +} +EXPORT_SYMBOL_GPL(typec_partner_set_pd); + /** * typec_partner_set_num_altmodes - Set the number of available partner altmodes * @partner: The partner to be updated. @@ -1170,6 +1208,104 @@ EXPORT_SYMBOL_GPL(typec_unregister_cable); /* ------------------------------------------------------------------------- */ /* USB Type-C ports */ +/** + * typec_port_set_pd_capabilities - Assign USB PD for port. + * @port: USB Type-C port. + * @pd: USB PD instance. + * + * This routine can be used to set the USB Power Delivery Capabilities for @port + * that it will advertise to the partner. + * + * If @pd is NULL, the assignment is removed. + */ +int typec_port_set_pd(struct typec_port *port, struct pd *pd) +{ + int ret; + + if (IS_ERR_OR_NULL(port) || port->pd == pd) + return 0; + + if (pd) { + ret = pd_link_device(pd, &port->dev); + if (ret) + return ret; + } else { + pd_unlink_device(port->pd, &port->dev); + } + + port->pd = pd; + + return 0; +} +EXPORT_SYMBOL_GPL(typec_port_set_pd); + +static ssize_t select_usb_power_delivery_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + struct typec_port *port = to_typec_port(dev); + struct pd *pd; + + if (!port->ops || !port->ops->pd_set) + return -EOPNOTSUPP; + + pd = pd_find(buf); + if (!pd) + return -EINVAL; + + return port->ops->pd_set(port, pd); +} + +static ssize_t select_usb_power_delivery_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct typec_port *port = to_typec_port(dev); + struct pd **pds; + struct pd *pd; + int ret = 0; + + if (!port->ops || !port->ops->pd_get) + return -EOPNOTSUPP; + + pds = port->ops->pd_get(port); + if (!pds) + return 0; + + for (pd = pds[0]; pd; pd++) { + if (pd == port->pd) + ret += sysfs_emit(buf + ret, "[%s] ", kobject_name(&pd->kobj)); + else + ret += sysfs_emit(buf + ret, "%s ", kobject_name(&pd->kobj)); + } + + buf[ret - 1] = '\n'; + + return ret; +} +static DEVICE_ATTR_RW(select_usb_power_delivery); + +static struct attribute *port_attrs[] = { + &dev_attr_select_usb_power_delivery.attr, + NULL +}; + +static umode_t port_attr_is_visible(struct kobject *kobj, struct attribute *attr, int n) +{ + struct typec_port *port = to_typec_port(kobj_to_dev(kobj)); + + if (!port->pd || !port->ops || !port->ops->pd_get) + return 0; + if (!port->ops->pd_set) + return 0444; + + return attr->mode; +} + +static const struct attribute_group pd_group = { + .is_visible = port_attr_is_visible, + .attrs = port_attrs, +}; + static const char * const typec_orientations[] = { [TYPEC_ORIENTATION_NONE] = "unknown", [TYPEC_ORIENTATION_NORMAL] = "normal", @@ -1581,6 +1717,7 @@ static const struct attribute_group typec_group = { static const struct attribute_group *typec_groups[] = { &typec_group, + &pd_group, NULL }; @@ -2123,6 +2260,13 @@ struct typec_port *typec_register_port(struct device *parent, return ERR_PTR(ret); } + ret = typec_port_set_pd(port, cap->pd); + if (ret) { + dev_err(&port->dev, "failed to link pd\n"); + device_unregister(&port->dev); + return ERR_PTR(ret); + } + ret = typec_link_ports(port); if (ret) dev_warn(&port->dev, "failed to create symlinks (%d)\n", ret); @@ -2141,6 +2285,7 @@ void typec_unregister_port(struct typec_port *port) { if (!IS_ERR_OR_NULL(port)) { typec_unlink_ports(port); + typec_port_set_pd(port, NULL); device_unregister(&port->dev); } } @@ -2162,8 +2307,15 @@ static int __init typec_init(void) if (ret) goto err_unregister_mux_class; + ret = pd_init(); + if (ret) + goto err_unregister_class; + return 0; +err_unregister_class: + class_unregister(&typec_class); + err_unregister_mux_class: class_unregister(&typec_mux_class); @@ -2176,6 +2328,7 @@ subsys_initcall(typec_init); static void __exit typec_exit(void) { + pd_exit(); class_unregister(&typec_class); ida_destroy(&typec_index_ida); bus_unregister(&typec_bus); diff --git a/drivers/usb/typec/class.h b/drivers/usb/typec/class.h index 0f1bd6d19d67e..6c638fd8d85cb 100644 --- a/drivers/usb/typec/class.h +++ b/drivers/usb/typec/class.h @@ -33,6 +33,8 @@ struct typec_partner { int num_altmodes; u16 pd_revision; /* 0300H = "3.0" */ enum usb_pd_svdm_ver svdm_version; + + struct pd *pd; }; struct typec_port { @@ -40,6 +42,8 @@ struct typec_port { struct device dev; struct ida mode_ids; + struct pd *pd; + int prefer_role; enum typec_data_role data_role; enum typec_role pwr_role; diff --git a/include/linux/usb/typec.h b/include/linux/usb/typec.h index 45e28d14ae56e..3855cd07925d3 100644 --- a/include/linux/usb/typec.h +++ b/include/linux/usb/typec.h @@ -22,6 +22,8 @@ struct typec_altmode_ops; struct fwnode_handle; struct device; +struct pd; + enum typec_port_type { TYPEC_PORT_SRC, TYPEC_PORT_SNK, @@ -223,6 +225,8 @@ struct typec_partner_desc { * @pr_set: Set Power Role * @vconn_set: Source VCONN * @port_type_set: Set port type + * @pd_get: Get available USB Power Delivery Capabilities. + * @pd_set: Set USB Power Delivery Capabilities. */ struct typec_operations { int (*try_role)(struct typec_port *port, int role); @@ -231,6 +235,8 @@ struct typec_operations { int (*vconn_set)(struct typec_port *port, enum typec_role role); int (*port_type_set)(struct typec_port *port, enum typec_port_type type); + struct pd **(*pd_get)(struct typec_port *port); + int (*pd_set)(struct typec_port *port, struct pd *pd); }; enum usb_pd_svdm_ver { @@ -250,6 +256,7 @@ enum usb_pd_svdm_ver { * @accessory: Supported Accessory Modes * @fwnode: Optional fwnode of the port * @driver_data: Private pointer for driver specific info + * @pd: Optional USB Power Delivery Support * @ops: Port operations vector * * Static capabilities of a single USB Type-C port. @@ -267,6 +274,8 @@ struct typec_capability { struct fwnode_handle *fwnode; void *driver_data; + struct pd *pd; + const struct typec_operations *ops; }; @@ -318,4 +327,7 @@ void typec_partner_set_svdm_version(struct typec_partner *partner, enum usb_pd_svdm_ver svdm_version); int typec_get_negotiated_svdm_version(struct typec_port *port); +int typec_port_set_pd(struct typec_port *port, struct pd *pd); +int typec_partner_set_pd(struct typec_partner *partner, struct pd *pd); + #endif /* __LINUX_USB_TYPEC_H */
All the USB Type-C Connector Class devices are protected, so the drivers can not directly access them. This will adds a few helpers that can be used to link the ports and partners to the correct USB Power Delivery objects. For ports a new optional sysfs attribute file is also added that can be used to select the USB Power Delivery capabilities that the port will advertise to the partner. Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com> --- Documentation/ABI/testing/sysfs-class-typec | 8 + drivers/usb/typec/class.c | 153 ++++++++++++++++++++ drivers/usb/typec/class.h | 4 + include/linux/usb/typec.h | 12 ++ 4 files changed, 177 insertions(+)