linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [RFC PATCHv2] usb: USB Type-C Connector Class
@ 2016-05-19 12:44 Heikki Krogerus
  2016-05-19 14:47 ` Oliver Neukum
                   ` (12 more replies)
  0 siblings, 13 replies; 98+ messages in thread
From: Heikki Krogerus @ 2016-05-19 12:44 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Greg KH, Mathias Nyman, Felipe Balbi, Oliver Neukum, Rajaram R,
	Andy Shevchenko, linux-kernel, linux-usb

The purpose of this class is to provide unified interface for user
space to get the status and basic information about USB Type-C
Connectors in the system, control data role swapping, and when USB PD
is available, also power role swapping and Alternate Modes.

Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
---
 drivers/usb/Kconfig         |   2 +
 drivers/usb/Makefile        |   2 +
 drivers/usb/type-c/Kconfig  |   7 +
 drivers/usb/type-c/Makefile |   1 +
 drivers/usb/type-c/typec.c  | 957 ++++++++++++++++++++++++++++++++++++++++++++
 include/linux/usb/typec.h   | 230 +++++++++++
 6 files changed, 1199 insertions(+)
 create mode 100644 drivers/usb/type-c/Kconfig
 create mode 100644 drivers/usb/type-c/Makefile
 create mode 100644 drivers/usb/type-c/typec.c
 create mode 100644 include/linux/usb/typec.h

Hi,

Like I've told some of you guys, I'm trying to implement a bus for
the Alternate Modes, but I'm still nowhere near finished with that
one, so let's just get the class ready now. The altmode bus should in
any case not affect the userspace interface proposed in this patch.

As you can see, the Alternate Modes are handled completely differently
compared to the original proposal. Every Alternate Mode will have
their own device instance (which will be then later bound to an
Alternate Mode specific driver once we have the bus), but also every
partner, cable and cable plug will have their own device instances
representing them.

An other change is that the data role is now handled in two ways.
The current_data_role file will represent static mode of the port, and
it will use the names for the roles as they are defined in the spec:
DFP, UFP and DRP. This file should be used if the port needs to be
fixed to one specific role with DRP ports. So this approach will
replace the suggestions for "preferred" data role we had. The
current_usb_data_role will use values "host" and "device" and it will
be used for data role swapping when already connected.

The tree of devices that will be populated when the cable is active
and when the cable has controller on both plug, will look as
following:

usbc0
|- usbc0-cable
|   |- usbc0-plug0
|   |   |- usbc0-plug.svid:xxx
|   |   |   |-mode0
|   |   |   |   |- vdo
|   |   |   |   |- desc
|   |   |   |   |- active
...
|   |- usbc0-plug1
|   |   |-usbc0-partner
|   |   |   |- usbc0-partner.svid:xxxx
|   |   |   |	|-mode0
|   |   |   |	|   |- vdo
|   |   |   |	|   |- desc
|   |   |   |	|   |- active
|   |   |   |	|-mode1
...
|   |   |- usbc0-plug1.svid:xxx
|   |   |   |-mode0
|   |   |   |   |- vdo
...

If there is no active cable, the partner will be directly attached to
the port, but symlink to the partner is now always added to the port
folder in any case. I'm not sure about this approach. There is a
question about it in the code. Please check it.

Just noticed that the "active" file is for now read only, but it needs
to be changed to writable. That file will of course provide means for
the userspace to Exit and Enter modes. But please note that the
responsibility of the dependencies between the modes, say, if a plug
needs to be in one mode or the other in order for the partner to enter
some specific mode, will fall on the Alternate Mode specific drivers
once we have the altmode bus. I remember there were concerns about
this in the original thread.

There were quite a few suggestions for the file names. I'm using the
most popular ones from the first thread now.

In case somebody is wondering, I'm not adding ABI documentation until
we know how the final version will look like.

I Hope I remembered to CC everybody interested.


Thanks,


diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig
index 8689dcb..4ef9b03 100644
--- a/drivers/usb/Kconfig
+++ b/drivers/usb/Kconfig
@@ -150,6 +150,8 @@ source "drivers/usb/phy/Kconfig"
 
 source "drivers/usb/gadget/Kconfig"
 
+source "drivers/usb/type-c/Kconfig"
+
 config USB_LED_TRIG
 	bool "USB LED Triggers"
 	depends on LEDS_CLASS && USB_COMMON && LEDS_TRIGGERS
diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile
index dca7856..02d26bf 100644
--- a/drivers/usb/Makefile
+++ b/drivers/usb/Makefile
@@ -61,3 +61,5 @@ obj-$(CONFIG_USB_GADGET)	+= gadget/
 obj-$(CONFIG_USB_COMMON)	+= common/
 
 obj-$(CONFIG_USBIP_CORE)	+= usbip/
+
+obj-$(CONFIG_TYPEC)		+= type-c/
diff --git a/drivers/usb/type-c/Kconfig b/drivers/usb/type-c/Kconfig
new file mode 100644
index 0000000..b229fb9
--- /dev/null
+++ b/drivers/usb/type-c/Kconfig
@@ -0,0 +1,7 @@
+
+menu "USB PD and Type-C drivers"
+
+config TYPEC
+	tristate
+
+endmenu
diff --git a/drivers/usb/type-c/Makefile b/drivers/usb/type-c/Makefile
new file mode 100644
index 0000000..1012a8b
--- /dev/null
+++ b/drivers/usb/type-c/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_TYPEC)		+= typec.o
diff --git a/drivers/usb/type-c/typec.c b/drivers/usb/type-c/typec.c
new file mode 100644
index 0000000..8028b7d
--- /dev/null
+++ b/drivers/usb/type-c/typec.c
@@ -0,0 +1,957 @@
+/*
+ * USB Type-C Connector Class
+ *
+ * Copyright (C) 2016, Intel Corporation
+ * Author: Heikki Krogerus <heikki.krogerus@linux.intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/usb/typec.h>
+
+struct typec_port {
+	unsigned int		id;
+	struct device		dev;
+	struct mutex		lock; /* FIXME: Not in use yet. */
+
+	enum typec_usb_role	usb_role;
+	enum typec_pwr_role	pwr_role;
+	enum typec_pwr_role	vconn_role;
+	enum typec_pwr_opmode	pwr_opmode;
+
+	struct typec_partner	*partner;
+	struct typec_cable	*cable;
+
+	unsigned int		connected:1;
+
+	int			n_altmode;
+
+	enum typec_data_role	fixed_role;
+	const struct typec_capability *cap;
+};
+
+#define to_typec_port(p) container_of(p, struct typec_port, dev)
+
+static DEFINE_IDA(typec_index_ida);
+
+static struct class typec_class = {
+	.name = "type-c",
+};
+
+/* -------------------------------- */
+/* Type-C Partners */
+
+static void typec_dev_release(struct device *dev)
+{
+}
+
+static const char * const typec_partner_types[] = {
+	[TYPEC_PARTNER_USB] = "USB",
+	[TYPEC_PARTNER_CHARGER] = "Charger",
+	[TYPEC_PARTNER_ALTMODE] = "Alternate Mode",
+	[TYPEC_PARTNER_AUDIO] = "Audio Accessory",
+	[TYPEC_PARTNER_DEBUG] = "Debug Accessory",
+};
+
+static ssize_t partner_type_show(struct device *dev,
+				 struct device_attribute *attr, char *buf)
+{
+	struct typec_partner *partner = container_of(dev, struct typec_partner,
+						     dev);
+
+	return sprintf(buf, "%s\n", typec_partner_types[partner->type]);
+}
+
+static struct device_attribute dev_attr_partner_type = {
+	.attr = {
+		.name = "type",
+		.mode = S_IRUGO,
+	},
+	.show = partner_type_show,
+};
+
+static struct attribute *typec_partner_attrs[] = {
+	&dev_attr_partner_type.attr,
+	NULL
+};
+
+static struct attribute_group typec_partner_group = {
+	.attrs = typec_partner_attrs,
+};
+
+static const struct attribute_group *typec_partner_groups[] = {
+	&typec_partner_group,
+	NULL
+};
+
+static struct device_type typec_partner_dev_type = {
+	.name = "typec_partner_device",
+	.groups = typec_partner_groups,
+	.release = typec_dev_release,
+};
+
+static int
+typec_add_partner(struct typec_port *port, struct typec_partner *partner)
+{
+	struct device *dev = &partner->dev;
+	struct device *parent;
+	int ret;
+
+	/*
+	 * REVISIT: Maybe it would be better to make the port always as the
+	 * parent of the partner? Or not even that. Would it be enough to just
+	 * create the symlink to the partner like we do below in any case?
+	 */
+	if (port->cable) {
+		if (port->cable->active) {
+			if (port->cable->sop_pp_controller)
+				parent = &port->cable->plug[1].dev;
+			else
+				parent = &port->cable->plug[0].dev;
+		} else {
+			parent = &port->cable->dev;
+		}
+	} else {
+		parent = &port->dev;
+	}
+
+	dev->class = &typec_class;
+	dev->parent = parent;
+	dev->type = &typec_partner_dev_type;
+	dev_set_name(dev, "%s-partner", dev_name(&port->dev));
+
+	ret = device_register(dev);
+	if (ret) {
+		put_device(dev);
+		return ret;
+	}
+
+	ret = typec_register_altmodes(dev, partner->alt_modes);
+	if (ret) {
+		device_unregister(dev);
+		return ret;
+	}
+
+	/* REVISIT: Creating symlink for the port device for now. */
+	ret = sysfs_create_link(&port->dev.kobj, &dev->kobj, "partner");
+	if (ret)
+		dev_WARN(&port->dev, "failed to create link to %s (%d)\n",
+			 dev_name(dev), ret);
+
+	port->partner = partner;
+	return 0;
+}
+
+static void typec_remove_partner(struct typec_port *port)
+{
+	sysfs_remove_link(&port->dev.kobj, "partner");
+	typec_unregister_altmodes(port->partner->alt_modes);
+	device_unregister(&port->partner->dev);
+}
+
+/* -------------------------------- */
+/* Type-C Cable Plugs */
+
+static struct device_type typec_plug_dev_type = {
+	.name = "type_plug_device",
+	.release = typec_dev_release,
+};
+
+static int
+typec_add_plug(struct typec_port *port, struct typec_plug *plug)
+{
+	struct device *dev = &plug->dev;
+	char name[6];
+	int ret;
+
+	sprintf(name, "plug%d", plug->index);
+
+	dev->class = &typec_class;
+	dev->parent = &port->cable->dev;
+	dev->type = &typec_plug_dev_type;
+	dev_set_name(dev, "%s-%s", dev_name(&port->dev), name);
+
+	ret = device_register(dev);
+	if (ret) {
+		put_device(dev);
+		return ret;
+	}
+
+	ret = typec_register_altmodes(dev, plug->alt_modes);
+	if (ret) {
+		device_unregister(dev);
+		return ret;
+	}
+
+	/* REVISIT: Is this useful? */
+	ret = sysfs_create_link(&port->dev.kobj, &dev->kobj, name);
+	if (ret)
+		dev_WARN(&port->dev, "failed to create link to %s (%d)\n",
+			 dev_name(dev), ret);
+
+	return 0;
+}
+
+static void typec_remove_plug(struct typec_plug *plug)
+{
+	struct typec_port *port = to_typec_port(plug->dev.parent->parent);
+	char name[6];
+
+	sprintf(name, "plug%d", plug->index);
+	sysfs_remove_link(&port->dev.kobj, name);
+	typec_unregister_altmodes(plug->alt_modes);
+	device_unregister(&plug->dev);
+}
+
+static ssize_t
+active_cable_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct typec_cable *cable = container_of(dev, struct typec_cable, dev);
+
+	return sprintf(buf, "%d\n", cable->active);
+}
+
+static struct device_attribute dev_attr_active_cable = {
+	.attr = {
+		.name = "active",
+		.mode = S_IRUGO,
+	},
+	.show = active_cable_show,
+};
+
+static const char * const typec_plug_types[] = {
+	[USB_PLUG_NONE] = "unknown",
+	[USB_PLUG_TYPE_A] = "Type-A",
+	[USB_PLUG_TYPE_B] = "Type-B",
+	[USB_PLUG_TYPE_C] = "Type-C",
+	[USB_PLUG_CAPTIVE] = "Captive",
+};
+
+static ssize_t
+cable_plug_type_show(struct device *dev, struct device_attribute *attr,
+		     char *buf)
+{
+	struct typec_cable *cable = container_of(dev, struct typec_cable, dev);
+
+	return sprintf(buf, "%s\n", typec_plug_types[cable->type]);
+}
+
+static struct device_attribute dev_attr_plug_type = {
+	.attr = {
+		.name = "plug_type",
+		.mode = S_IRUGO,
+	},
+	.show = cable_plug_type_show,
+};
+
+static struct attribute *typec_cable_attrs[] = {
+	&dev_attr_active_cable.attr,
+	&dev_attr_plug_type.attr,
+	NULL
+};
+
+static struct attribute_group typec_cable_group = {
+	.attrs = typec_cable_attrs,
+};
+
+static const struct attribute_group *typec_cable_groups[] = {
+	&typec_cable_group,
+	NULL
+};
+
+static struct device_type typec_cable_dev_type = {
+	.name = "typec_cable_device",
+	.groups = typec_cable_groups,
+	.release = typec_dev_release,
+};
+
+static int typec_add_cable(struct typec_port *port, struct typec_cable *cable)
+{
+	struct device *dev = &cable->dev;
+	int ret;
+
+	dev->class = &typec_class;
+	/* REVISIT: We could have just the symlink also for the cable. */
+	dev->parent = &port->dev;
+	dev->type = &typec_cable_dev_type;
+	dev_set_name(dev, "%s-cable", dev_name(&port->dev));
+
+	ret = device_register(dev);
+	if (ret) {
+		put_device(dev);
+		return ret;
+	}
+
+	/* Plug1 */
+	if (!cable->active)
+		return 0;
+
+	cable->plug[0].index = 1;
+	ret = typec_add_plug(port, &cable->plug[0]);
+	if (ret) {
+		device_unregister(dev);
+		return ret;
+	}
+
+	/* Plug2 */
+	if (!cable->sop_pp_controller)
+		return 0;
+
+	cable->plug[1].index = 2;
+	ret = typec_add_plug(port, &cable->plug[1]);
+	if (ret) {
+		typec_remove_plug(&cable->plug[0]);
+		device_unregister(dev);
+		return ret;
+	}
+
+	port->cable = cable;
+	return 0;
+}
+
+static void typec_remove_cable(struct typec_port *port)
+{
+	if (port->cable->active) {
+		typec_remove_plug(&port->cable->plug[0]);
+		if (port->cable->sop_pp_controller)
+			typec_remove_plug(&port->cable->plug[1]);
+	}
+	device_unregister(&port->cable->dev);
+}
+
+/* -------------------------------- */
+
+int typec_connect(struct typec_port *port, struct typec_connection *con)
+{
+	int ret;
+
+	/* FIXME: bus_type for typec? Note that we will in any case have bus for
+	 * the alternate modes. typec bus would be only dealing with the cable
+	 * and partner. */
+
+	if (!con->partner && !con->cable)
+		return -EINVAL;
+
+	port->connected = 1;
+	port->usb_role = con->usb_role;
+	port->pwr_role = con->pwr_role;
+	port->vconn_role = con->vconn_role;
+	port->pwr_opmode = con->pwr_opmode;
+
+	kobject_uevent(&port->dev.kobj, KOBJ_CHANGE);
+
+	if (con->cable) {
+		ret = typec_add_cable(port, con->cable);
+		if (ret)
+			return ret;
+	}
+
+	if (con->partner) {
+		ret = typec_add_partner(port, con->partner);
+		if (ret) {
+			if (con->cable)
+				typec_remove_cable(port);
+			return ret;
+		}
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(typec_connect);
+
+void typec_disconnect(struct typec_port *port)
+{
+	if (port->partner)
+		typec_remove_partner(port);
+
+	if (port->cable)
+		typec_remove_cable(port);
+
+	port->connected = 0;
+	port->partner = NULL;
+	port->cable = NULL;
+
+	port->pwr_opmode = TYPEC_PWR_MODE_USB;
+
+	if (port->fixed_role == TYPEC_PORT_DFP) {
+		port->usb_role = TYPEC_HOST;
+		port->pwr_role = TYPEC_PWR_SOURCE;
+		port->vconn_role = TYPEC_PWR_SOURCE;
+	} else {
+		/* Device mode as default also with DRP ports */
+		port->usb_role = TYPEC_DEVICE;
+		port->pwr_role = TYPEC_PWR_SINK;
+		port->vconn_role = TYPEC_PWR_SINK;
+	}
+
+	kobject_uevent(&port->dev.kobj, KOBJ_CHANGE);
+}
+EXPORT_SYMBOL_GPL(typec_disconnect);
+
+struct device *typec_port2dev(struct typec_port *port)
+{
+	return &port->dev;
+}
+EXPORT_SYMBOL_GPL(typec_port2dev);
+
+struct typec_port *typec_dev2port(struct device *dev)
+{
+	return to_typec_port(dev);
+}
+EXPORT_SYMBOL_GPL(typec_dev2port);
+
+/* -------------------------------- */
+/* Alternate Modes */
+
+/*
+ * typec_altmode2port - Alternate Mode to USB Type-C port
+ * @alt: The Alternate Mode
+ *
+ * Returns the port that the cable plug or partner with @alt is connected to.
+ * The function is helper only for cable plug and partner Alternate Modes. With
+ * Type-C port Alternate Modes the function returns NULL.
+ */
+struct typec_port *typec_altmode2port(struct typec_altmode *alt)
+{
+	if (alt->dev.parent->type == &typec_plug_dev_type)
+		return to_typec_port(alt->dev.parent->parent->parent);
+	if (alt->dev.parent->type == &typec_partner_dev_type)
+		return to_typec_port(alt->dev.parent->parent);
+
+	return NULL;
+}
+EXPORT_SYMBOL_GPL(typec_altmode2port);
+
+static void typec_altmode_release(struct device *dev)
+{
+	struct typec_altmode *alt = to_altmode(dev);
+
+	kfree(alt->mode_groups);
+}
+
+static ssize_t
+typec_altmode_vdo_show(struct device *dev, struct device_attribute *attr,
+		       char *buf)
+{
+	struct typec_mode *mode = container_of(attr, struct typec_mode,
+					       vdo_attr);
+
+	return sprintf(buf, "0x%08x\n", mode->vdo);
+}
+
+static ssize_t
+typec_altmode_desc_show(struct device *dev, struct device_attribute *attr,
+			char *buf)
+{
+	struct typec_mode *mode = container_of(attr, struct typec_mode,
+					       desc_attr);
+
+	return sprintf(buf, "%s\n", mode->desc);
+}
+
+static ssize_t
+typec_altmode_active_show(struct device *dev, struct device_attribute *attr,
+			  char *buf)
+{
+	struct typec_mode *mode = container_of(attr, struct typec_mode,
+					       active_attr);
+
+	return sprintf(buf, "%d\n", mode->active);
+}
+
+static void typec_init_modes(struct typec_altmode *alt)
+{
+	struct typec_mode *mode = alt->modes;
+	int i;
+
+	for (i = 0; i < alt->n_modes; i++, mode++) {
+		mode->index = i;
+		sprintf(mode->group_name, "mode%d", i);
+
+		sysfs_attr_init(&mode->vdo_attr.attr);
+		mode->vdo_attr.attr.name = "vdo";
+		mode->vdo_attr.attr.mode = S_IRUGO;
+		mode->vdo_attr.show = typec_altmode_vdo_show;
+
+		sysfs_attr_init(&mode->desc_attr.attr);
+		mode->desc_attr.attr.name = "description";
+		mode->desc_attr.attr.mode = S_IRUGO;
+		mode->desc_attr.show = typec_altmode_desc_show;
+
+		sysfs_attr_init(&mode->active_attr.attr);
+		mode->active_attr.attr.name = "active";
+		mode->active_attr.attr.mode = S_IRUGO;
+		mode->active_attr.show = typec_altmode_active_show;
+
+		mode->attrs[0] = &mode->vdo_attr.attr;
+		mode->attrs[1] = &mode->desc_attr.attr;
+		mode->attrs[2] = &mode->active_attr.attr;
+
+		mode->group.attrs = mode->attrs;
+		mode->group.name = mode->group_name;
+
+		alt->mode_groups[i] = &mode->group;
+	}
+}
+
+static int typec_add_altmode(struct device *parent, struct typec_altmode *alt)
+{
+	struct device *dev = &alt->dev;
+	int ret;
+
+	alt->mode_groups = kcalloc(alt->n_modes + 1,
+				   sizeof(struct attibute_group *), GFP_KERNEL);
+	if (!alt->mode_groups)
+		return -ENOMEM;
+
+	typec_init_modes(alt);
+
+	dev->groups = alt->mode_groups;
+	dev->release = typec_altmode_release;
+
+	dev->parent = parent;
+	/* TODO: dev->bus = &typec_altmode_bus; */
+
+	if (alt->name)
+		dev_set_name(dev, "%s.%s", dev_name(parent), alt->name);
+	else
+		dev_set_name(dev, "%s.svid:%04x", dev_name(parent), alt->svid);
+
+	ret = device_register(dev);
+	if (ret) {
+		put_device(dev);
+		kfree(alt->mode_groups);
+		return ret;
+	}
+
+	return 0;
+}
+
+int typec_register_altmodes(struct device *parent,
+			    struct typec_altmode *alt_modes)
+{
+	struct typec_altmode *alt;
+	int index;
+	int ret;
+
+	if (!alt_modes)
+		return 0;
+
+	for (alt = alt_modes, index = 0; alt->svid; alt++, index++) {
+		ret = typec_add_altmode(parent, alt);
+		if (ret)
+			goto err;
+	}
+
+	return 0;
+err:
+	for (alt = alt_modes + index; index; alt--, index--)
+		device_unregister(&alt->dev);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(typec_register_altmodes);
+
+void typec_unregister_altmodes(struct typec_altmode *alt_modes)
+{
+	struct typec_altmode *alt;
+
+	for (alt = alt_modes; alt->svid; alt++)
+		device_unregister(&alt->dev);
+}
+EXPORT_SYMBOL_GPL(typec_unregister_altmodes);
+
+/* -------------------------------- */
+
+static ssize_t
+current_usb_data_role_store(struct device *dev, struct device_attribute *attr,
+			    const char *buf, size_t size)
+{
+	struct typec_port *port = to_typec_port(dev);
+	enum typec_usb_role role;
+	int ret;
+
+	if (port->cap->role != TYPEC_PORT_DRP) {
+		dev_dbg(dev, "data role swap only supported with DRP ports\n");
+		return -EOPNOTSUPP;
+	}
+
+	if (!port->cap->dr_swap) {
+		dev_warn(dev, "data role swapping not supported\n");
+		return -EOPNOTSUPP;
+	}
+
+	if (!strncmp(buf, "host", 4))
+		role = TYPEC_HOST;
+	else if (!strncmp(buf, "device", 6))
+		role = TYPEC_DEVICE;
+	else
+		return -EINVAL;
+
+	if (port->usb_role == role || !port->partner)
+		return size;
+
+	ret = port->cap->dr_swap(port);
+	if (ret)
+		return ret;
+
+	return size;
+}
+
+static ssize_t
+current_usb_data_role_show(struct device *dev, struct device_attribute *attr,
+			   char *buf)
+{
+	struct typec_port *port = to_typec_port(dev);
+
+	if (port->usb_role == TYPEC_DEVICE)
+		return sprintf(buf, "device\n");
+
+	return sprintf(buf, "host\n");
+}
+static DEVICE_ATTR_RW(current_usb_data_role);
+
+static const char * const typec_data_roles[] = {
+	[TYPEC_PORT_DFP] = "DFP",
+	[TYPEC_PORT_UFP] = "UFP",
+	[TYPEC_PORT_DRP] = "DRP",
+};
+
+static ssize_t supported_data_roles_show(struct device *dev,
+					 struct device_attribute *attr,
+					 char *buf)
+{
+	struct typec_port *port = to_typec_port(dev);
+
+	return sprintf(buf, "%s\n", typec_data_roles[port->cap->role]);
+}
+static DEVICE_ATTR_RO(supported_data_roles);
+
+static ssize_t
+current_data_role_store(struct device *dev, struct device_attribute *attr,
+			const char *buf, size_t size)
+{
+	struct typec_port *port = to_typec_port(dev);
+	enum typec_data_role role;
+	int ret;
+
+	if (port->cap->role != TYPEC_PORT_DRP)
+		return -EOPNOTSUPP;
+
+	if (!port->cap->fix_role)
+		return -EOPNOTSUPP;
+
+	if (!strcmp(buf, "DFP"))
+		role = TYPEC_PORT_DFP;
+	else if (!strcmp(buf, "UFP"))
+		role = TYPEC_PORT_UFP;
+	else if (!strcmp(buf, "DRP"))
+		role = TYPEC_PORT_DRP;
+	else
+		return -EINVAL;
+
+	if (port->fixed_role == role)
+		return size;
+
+	ret = port->cap->fix_role(port, role);
+	if (ret)
+		return ret;
+
+	return size;
+}
+
+static ssize_t
+current_data_role_show(struct device *dev, struct device_attribute *attr,
+		       char *buf)
+{
+	struct typec_port *port = to_typec_port(dev);
+
+	return sprintf(buf, "%s\n", typec_data_roles[port->fixed_role]);
+}
+static DEVICE_ATTR_RW(current_data_role);
+
+static ssize_t current_power_role_store(struct device *dev,
+					struct device_attribute *attr,
+					const char *buf, size_t size)
+{
+	struct typec_port *port = to_typec_port(dev);
+	enum typec_pwr_role role;
+	int ret;
+
+	if (!port->cap->usb_pd) {
+		dev_dbg(dev, "power role swap only supported with USB PD\n");
+		return -EOPNOTSUPP;
+	}
+
+	if (!port->cap->pr_swap) {
+		dev_warn(dev, "power role swapping not supported\n");
+		return -EOPNOTSUPP;
+	}
+
+	if (port->pwr_opmode != TYPEC_PWR_MODE_PD) {
+		dev_dbg(dev, "partner unable to swap power role\n");
+		return -EIO;
+	}
+
+	if (!strncmp(buf, "source", 6))
+		role = TYPEC_PWR_SOURCE;
+	else if (!strncmp(buf, "sink", 4))
+		role = TYPEC_PWR_SINK;
+	else
+		return -EINVAL;
+
+	if (port->pwr_role == role || !port->partner)
+		return size;
+
+	ret = port->cap->pr_swap(port);
+	if (ret)
+		return ret;
+
+	return size;
+}
+
+static ssize_t current_power_role_show(struct device *dev,
+				       struct device_attribute *attr, char *buf)
+{
+	struct typec_port *port = to_typec_port(dev);
+
+	switch (port->pwr_role) {
+	case TYPEC_PWR_SOURCE:
+		return sprintf(buf, "source\n");
+	case TYPEC_PWR_SINK:
+		return sprintf(buf, "sink\n");
+	default:
+		return sprintf(buf, "unknown\n");
+	};
+}
+static DEVICE_ATTR_RW(current_power_role);
+
+static ssize_t supported_power_roles_show(struct device *dev,
+					  struct device_attribute *attr,
+					  char *buf)
+{
+	struct typec_port *port = to_typec_port(dev);
+
+	if (port->cap->usb_pd || port->cap->role == TYPEC_PORT_DRP)
+		return sprintf(buf, "source, sink\n");
+
+	return current_power_role_show(dev, attr, buf);
+}
+static DEVICE_ATTR_RO(supported_power_roles);
+
+static const char * const typec_pwr_opmodes[] = {
+	[TYPEC_PWR_MODE_USB] = "USB",
+	[TYPEC_PWR_MODE_BC1_2] = "BC1.2",
+	[TYPEC_PWR_MODE_1_5A] = "USB Type-C 1.5A",
+	[TYPEC_PWR_MODE_3_0A] = "USB Type-C 3.0A",
+	[TYPEC_PWR_MODE_PD] = "USB Power Delivery",
+};
+
+static ssize_t power_operation_mode_show(struct device *dev,
+					 struct device_attribute *attr,
+					 char *buf)
+{
+	struct typec_port *port = to_typec_port(dev);
+
+	return sprintf(buf, "%s\n", typec_pwr_opmodes[port->pwr_opmode]);
+}
+static DEVICE_ATTR_RO(power_operation_mode);
+
+static ssize_t supports_audio_accessory_show(struct device *dev,
+					     struct device_attribute *attr,
+					     char *buf)
+{
+	struct typec_port *port = to_typec_port(dev);
+
+	return sprintf(buf, "%d\n", port->cap->audio_accessory);
+}
+static DEVICE_ATTR_RO(supports_audio_accessory);
+
+static ssize_t supports_debug_accessory_show(struct device *dev,
+					     struct device_attribute *attr,
+					     char *buf)
+{
+	struct typec_port *port = to_typec_port(dev);
+
+	return sprintf(buf, "%d\n", port->cap->debug_accessory);
+}
+static DEVICE_ATTR_RO(supports_debug_accessory);
+
+static ssize_t supports_usb_power_delivery_show(struct device *dev,
+						struct device_attribute *attr,
+						char *buf)
+{
+	struct typec_port *port = to_typec_port(dev);
+
+	return sprintf(buf, "%d\n", port->cap->usb_pd);
+}
+static DEVICE_ATTR_RO(supports_usb_power_delivery);
+
+static struct attribute *typec_attrs[] = {
+	&dev_attr_current_data_role.attr,
+	&dev_attr_current_power_role.attr,
+	&dev_attr_current_usb_data_role.attr,
+	&dev_attr_power_operation_mode.attr,
+	&dev_attr_supported_data_roles.attr,
+	&dev_attr_supported_power_roles.attr,
+	&dev_attr_supports_audio_accessory.attr,
+	&dev_attr_supports_debug_accessory.attr,
+	&dev_attr_supports_usb_power_delivery.attr,
+	NULL,
+};
+
+static const struct attribute_group typec_group = {
+	.attrs = typec_attrs,
+};
+
+static ssize_t number_of_alternate_modes_show(struct device *dev,
+					      struct device_attribute *attr,
+					      char *buf)
+{
+	struct typec_port *port = to_typec_port(dev);
+
+	return sprintf(buf, "%d\n", port->n_altmode);
+}
+static DEVICE_ATTR_RO(number_of_alternate_modes);
+
+static struct attribute *altmode_attrs[] = {
+	&dev_attr_number_of_alternate_modes.attr,
+	NULL,
+};
+
+static const struct attribute_group altmode_group = {
+	.name = "supported_alternate_modes",
+	.attrs = altmode_attrs,
+};
+
+static const struct attribute_group *typec_groups[] = {
+	&typec_group,
+	&altmode_group,
+	NULL,
+};
+
+static int typec_uevent(struct device *dev, struct kobj_uevent_env *env)
+{
+	int ret;
+
+	ret = add_uevent_var(env, "TYPEC_PORT=%s", dev_name(dev));
+	if (ret)
+		dev_err(dev, "failed to add uevent TYPEC_PORT\n");
+
+	return ret;
+}
+
+static void typec_release(struct device *dev)
+{
+	struct typec_port *port = to_typec_port(dev);
+
+	ida_simple_remove(&typec_index_ida, port->id);
+	kfree(port);
+}
+
+static struct device_type typec_port_dev_type = {
+	.name = "typec_port",
+	.groups = typec_groups,
+	.uevent = typec_uevent,
+	.release = typec_release,
+};
+
+struct typec_port *typec_register_port(struct device *dev,
+				       struct typec_capability *cap)
+{
+	struct typec_port *port;
+	int ret;
+	int id;
+
+	port = kzalloc(sizeof(*port), GFP_KERNEL);
+	if (!port)
+		return ERR_PTR(-ENOMEM);
+
+	id = ida_simple_get(&typec_index_ida, 0, 0, GFP_KERNEL);
+	if (id < 0) {
+		kfree(port);
+		return ERR_PTR(id);
+	}
+
+	port->id = id;
+	port->cap = cap;
+	port->dev.type = &typec_port_dev_type;
+	port->dev.class = &typec_class;
+	port->dev.parent = dev;
+	dev_set_name(&port->dev, "usbc%d", id);
+	mutex_init(&port->lock);
+
+	port->fixed_role = port->cap->role;
+
+	ret = device_register(&port->dev);
+	if (ret) {
+		ida_simple_remove(&typec_index_ida, id);
+		put_device(&port->dev);
+		kfree(port);
+		return ERR_PTR(ret);
+	}
+
+	/*
+	 * The alternate modes that the port supports must be created before
+	 * registering the port. They are just linked to the port here.
+	 */
+	if (cap->alt_modes) {
+		struct typec_altmode *alt;
+
+		for (alt = cap->alt_modes; alt->svid; alt++) {
+			ret = sysfs_add_link_to_group(&port->dev.kobj,
+						"supported_alternate_modes",
+						&alt->dev.kobj,
+						alt->name ? alt->name :
+						dev_name(&alt->dev));
+			if (ret) {
+				dev_WARN(&port->dev,
+					 "failed to create sysfs symlink\n");
+			} else {
+				port->n_altmode++;
+			}
+		}
+	}
+
+	return port;
+}
+EXPORT_SYMBOL_GPL(typec_register_port);
+
+void typec_unregister_port(struct typec_port *port)
+{
+	if (port->connected)
+		typec_disconnect(port);
+
+	if (port->cap->alt_modes) {
+		struct typec_altmode *alt;
+
+		for (alt = port->cap->alt_modes; alt->svid; alt++)
+			sysfs_remove_link_from_group(&port->dev.kobj,
+						     "alternate_modes",
+						     alt->name ? alt->name :
+						     dev_name(&alt->dev));
+	}
+	device_unregister(&port->dev);
+}
+EXPORT_SYMBOL_GPL(typec_unregister_port);
+
+static int __init typec_init(void)
+{
+	return class_register(&typec_class);
+}
+subsys_initcall(typec_init);
+
+static void __exit typec_exit(void)
+{
+	class_unregister(&typec_class);
+}
+module_exit(typec_exit);
+
+MODULE_AUTHOR("Heikki Krogerus <heikki.krogerus@linux.intel.com>");
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("USB Type-C Connector Class");
diff --git a/include/linux/usb/typec.h b/include/linux/usb/typec.h
new file mode 100644
index 0000000..86e5c86
--- /dev/null
+++ b/include/linux/usb/typec.h
@@ -0,0 +1,230 @@
+
+#ifndef __LINUX_USB_TYPEC_H
+#define __LINUX_USB_TYPEC_H
+
+#include <linux/types.h>
+
+struct typec_port;
+
+enum typec_data_role {
+	TYPEC_PORT_DFP,
+	TYPEC_PORT_UFP,
+	TYPEC_PORT_DRP,
+};
+
+enum typec_partner_type {
+	TYPEC_PARTNER_USB,
+	TYPEC_PARTNER_CHARGER,
+	TYPEC_PARTNER_ALTMODE,
+	TYPEC_PARTNER_AUDIO,
+	TYPEC_PARTNER_DEBUG,
+};
+
+enum typec_plug_type {
+	USB_PLUG_NONE,
+	USB_PLUG_TYPE_A,
+	USB_PLUG_TYPE_B,
+	USB_PLUG_TYPE_C,
+	USB_PLUG_CAPTIVE,
+};
+
+enum typec_usb_role {
+	TYPEC_DEVICE,
+	TYPEC_HOST,
+};
+
+enum typec_pwr_role {
+	TYPEC_PWR_SINK,
+	TYPEC_PWR_SOURCE,
+};
+
+enum typec_pwr_opmode {
+	TYPEC_PWR_MODE_USB,
+	TYPEC_PWR_MODE_BC1_2,
+	TYPEC_PWR_MODE_1_5A,
+	TYPEC_PWR_MODE_3_0A,
+	TYPEC_PWR_MODE_PD,
+};
+
+/*
+ * struct typec_mode - Individual Mode of an Alternate Mode
+ * @vdo: VDO returned by Discover Modes USB PD command
+ * @desc: Mode description
+ * @active: Tells if the mode is currently entered or not
+ * @index: Index of the mode
+ * @group_name: Name for the sysfs folder in form "mode<index>"
+ * @group: The sysfs group (folder) for the mode
+ * @attrs: The attributes for the sysfs group
+ * @vdo_attr: Device attribute to expose the VDO of the mode
+ * @desc_attr: Device attribute to expose the description of the mode
+ * @acctive_attr: Device attribute to expose active of the mode
+ *
+ * Details about a mode of an Alternate Mode which a connector, cable plug or
+ * partner supports. Every mode will have it's own sysfs group. The details are
+ * the VDO returned by discover modes command, description for the mode and
+ * active flag telling is the mode currently active or not.
+ */
+struct typec_mode {
+	u32			vdo;
+	char			*desc;
+	unsigned int		active:1;
+
+	int			index;
+	char			group_name[8];
+	struct attribute_group	group;
+	struct attribute	*attrs[4];
+	struct device_attribute vdo_attr;
+	struct device_attribute desc_attr;
+	struct device_attribute active_attr;
+};
+
+/*
+ * struct typec_altmode - USB Type-C Alternate Mode
+ * @dev: struct device instance
+ * @name: Name for the Alternate Mode (optional)
+ * @svid: Standard or Vendor ID
+ * @n_modes: Number of modes
+ * @modes: Array of modes supported by the Alternat Mode
+ * @mode_groups: The modes as attribute groups to be exposed in sysfs
+ *
+ * Representation of an Alternate Mode that has SVID assigned by USB-IF. The
+ * array of modes will list the modes of a particular SVID that are supported by
+ * a connector, partner of a cable plug.
+ */
+struct typec_altmode {
+	struct device		dev;
+	char			*name;
+
+	u16			svid;
+	int			n_modes;
+	struct typec_mode	*modes;
+
+	const struct attribute_group **mode_groups;
+};
+
+#define to_altmode(d) container_of(d, struct typec_altmode, dev)
+
+struct typec_port *typec_altmode2port(struct typec_altmode *);
+
+int typec_register_altmodes(struct device *, struct typec_altmode *);
+void typec_unregister_altmodes(struct typec_altmode *);
+
+/*
+ * struct typec_plug - USB Type-C Cable Plug
+ * @dev: struct device instance
+ * @index: 1 for the plug connected to DFP and 2 for the plug connected to UFP
+ * @alt_modes: Alternate Modes the cable plug supports (null terminated)
+ *
+ * Represents USB Type-C Cable Plug.
+ */
+struct typec_plug {
+	struct device		dev;
+	int			index;
+	struct typec_altmode	*alt_modes;
+};
+
+/*
+ * struct typec_cable - USB Type-C Cable
+ * @dev: struct device instance
+ * @type: The plug type from USB PD Cable VDO
+ * @active: Is the cable active or passive
+ * @sop_pp_controller: Tells whether both cable plugs are configurable or not
+ * @plug: The two plugs in the cable.
+ *
+ * Represents USB Type-C Cable attached to USB Type-C port. Two plugs are
+ * created if the cable has SOP Double Prime controller as defined in USB PD
+ * specification. Otherwise only one will be created if the cable is active. For
+ * passive cables no plugs are created.
+ */
+struct typec_cable {
+	struct device		dev;
+	enum typec_plug_type	type;
+	unsigned int		active:1;
+	unsigned int		sop_pp_controller:1;
+	/* REVISIT: What else needed? */
+
+	struct typec_plug	plug[2];
+};
+
+/*
+ * struct typec_partner - USB Type-C Partner
+ * @dev: struct device instance
+ * @type: Normal USB device, charger, Alternate Mode or Accessory
+ * @alt_modes: Alternate Modes the partner supports (null terminated)
+ *
+ * Details about a partner that is attached to USB Type-C port.
+ */
+struct typec_partner {
+	struct device		dev;
+	enum typec_partner_type	type;
+	struct typec_altmode	*alt_modes;
+};
+
+/*
+ * struct typec_capability - USB Type-C Port Capabilities
+ * @role: DFP (Host-only), UFP (Device-only) or DRP (Dual Role)
+ * @usb_pd: USB Power Delivery support
+ * @alt_modes: Alternate Modes the connector supports (null terminated)
+ * @audio_accessory: Audio Accessory Adapter Mode support
+ * @debug_accessory: Debug Accessory Mode support
+ * @fix_role: Set a fixed data role for DRP port
+ * @dr_swap: Data Role Swap support
+ * @pr_swap: Power Role Swap support
+ * @vconn_swap: VCONN Swap support
+ * @activate_mode: Enter/exit given Alternate Mode
+ *
+ * Static capabilities of a single USB Type-C port.
+ */
+struct typec_capability {
+	enum typec_data_role	role;
+	unsigned int		usb_pd:1;
+	struct typec_altmode	*alt_modes;
+	unsigned int		audio_accessory:1;
+	unsigned int		debug_accessory:1;
+
+	int			(*fix_role)(struct typec_port *,
+					    enum typec_data_role);
+
+	int			(*dr_swap)(struct typec_port *);
+	int			(*pr_swap)(struct typec_port *);
+	int			(*vconn_swap)(struct typec_port *);
+
+	int			(*activate_mode)(struct typec_altmode *,
+						 int mode, int activate);
+};
+
+/*
+ * struct typec_connection - Details about USB Type-C port connection event
+ * @partner: The attached partner
+ * @cable: The attached cable
+ * @usb_role: Initial USB data role (host or device)
+ * @pwr_role: Initial Power role (source or sink)
+ * @vconn_role: Initial VCONN role (source or sink)
+ * @pwr_opmode: The power mode of the connection
+ *
+ * All the relevant details about a connection event. Wrapper that is passed to
+ * typec_connect(). The context is copied when typec_connect() is called and the
+ * structure is not used for anything else.
+ */
+struct typec_connection {
+	struct typec_partner	*partner;
+	struct typec_cable	*cable;
+
+	enum typec_usb_role	usb_role;
+	enum typec_pwr_role	pwr_role;
+	enum typec_pwr_role	vconn_role;
+	enum typec_pwr_opmode	pwr_opmode;
+};
+
+struct typec_port *typec_register_port(struct device *dev,
+				       struct typec_capability *cap);
+void typec_unregister_port(struct typec_port *port);
+
+int typec_connect(struct typec_port *port, struct typec_connection *con);
+void typec_disconnect(struct typec_port *port);
+
+/* REVISIT: are these needed? */
+struct device *typec_port2dev(struct typec_port *port);
+struct typec_port *typec_dev2port(struct device *dev);
+
+#endif /* __LINUX_USB_TYPEC_H */
-- 
2.8.1

^ permalink raw reply related	[flat|nested] 98+ messages in thread

* Re: [RFC PATCHv2] usb: USB Type-C Connector Class
  2016-05-19 12:44 [RFC PATCHv2] usb: USB Type-C Connector Class Heikki Krogerus
@ 2016-05-19 14:47 ` Oliver Neukum
  2016-05-20 11:24   ` Heikki Krogerus
  2016-05-19 14:48 ` Oliver Neukum
                   ` (11 subsequent siblings)
  12 siblings, 1 reply; 98+ messages in thread
From: Oliver Neukum @ 2016-05-19 14:47 UTC (permalink / raw)
  To: Heikki Krogerus
  Cc: Guenter Roeck, Andy Shevchenko, Rajaram R, Felipe Balbi,
	Mathias Nyman, Greg KH, linux-kernel, linux-usb

On Thu, 2016-05-19 at 15:44 +0300, Heikki Krogerus wrote:
> The purpose of this class is to provide unified interface for user
> space to get the status and basic information about USB Type-C
> Connectors in the system, control data role swapping, and when USB PD
> is available, also power role swapping and Alternate Modes.
> 
> Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
> ---
>  drivers/usb/Kconfig         |   2 +
>  drivers/usb/Makefile        |   2 +
>  drivers/usb/type-c/Kconfig  |   7 +
>  drivers/usb/type-c/Makefile |   1 +
>  drivers/usb/type-c/typec.c  | 957 ++++++++++++++++++++++++++++++++++++++++++++
>  include/linux/usb/typec.h   | 230 +++++++++++
>  6 files changed, 1199 insertions(+)
>  create mode 100644 drivers/usb/type-c/Kconfig
>  create mode 100644 drivers/usb/type-c/Makefile
>  create mode 100644 drivers/usb/type-c/typec.c
>  create mode 100644 include/linux/usb/typec.h
> 
> Hi,
> 
> Like I've told some of you guys, I'm trying to implement a bus for
> the Alternate Modes, but I'm still nowhere near finished with that
> one, so let's just get the class ready now. The altmode bus should in
> any case not affect the userspace interface proposed in this patch.
> 
> As you can see, the Alternate Modes are handled completely differently
> compared to the original proposal. Every Alternate Mode will have
> their own device instance (which will be then later bound to an
> Alternate Mode specific driver once we have the bus), but also every
> partner, cable and cable plug will have their own device instances
> representing them.

That raises a question. If I read the standard correctly, alternate
modes could be combinable. So how do you represent that.

> An other change is that the data role is now handled in two ways.
> The current_data_role file will represent static mode of the port, and
> it will use the names for the roles as they are defined in the spec:
> DFP, UFP and DRP. This file should be used if the port needs to be
> fixed to one specific role with DRP ports. So this approach will
> replace the suggestions for "preferred" data role we had. The
> current_usb_data_role will use values "host" and "device" and it will
> be used for data role swapping when already connected.

Please explain. How does that express DRP but prefered master?

> I Hope I remembered to CC everybody interested.

Alternate modes can be left involuntarily. So we need a method of
notification.

	Regards
		Oliver

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [RFC PATCHv2] usb: USB Type-C Connector Class
  2016-05-19 12:44 [RFC PATCHv2] usb: USB Type-C Connector Class Heikki Krogerus
  2016-05-19 14:47 ` Oliver Neukum
@ 2016-05-19 14:48 ` Oliver Neukum
  2016-05-19 15:43   ` Greg KH
  2016-05-19 17:53 ` Guenter Roeck
                   ` (10 subsequent siblings)
  12 siblings, 1 reply; 98+ messages in thread
From: Oliver Neukum @ 2016-05-19 14:48 UTC (permalink / raw)
  To: Heikki Krogerus
  Cc: Guenter Roeck, Andy Shevchenko, Rajaram R, Felipe Balbi,
	Mathias Nyman, Greg KH, linux-kernel, linux-usb

On Thu, 2016-05-19 at 15:44 +0300, Heikki Krogerus wrote:

> +	dev->class = &typec_class;
> +	dev->parent = parent;
> +	dev->type = &typec_partner_dev_type;
> +	dev_set_name(dev, "%s-partner", dev_name(&port->dev));
> +
> +	ret = device_register(dev);
> +	if (ret) {
> +		put_device(dev);
> +		return ret;
> +	}

This looks like a race condition.

> +	ret = typec_register_altmodes(dev, partner->alt_modes);
> +	if (ret) {
> +		device_unregister(dev);
> +		return ret;
> +	}
> +
> +	/* REVISIT: Creating symlink for the port device for now. */
> +	ret = sysfs_create_link(&port->dev.kobj, &dev->kobj, "partner");
> +	if (ret)
> +		dev_WARN(&port->dev, "failed to create link to %s (%d)\n",
> +			 dev_name(dev), ret);

The attributes should be present as soon as the device is announced.

	Regards
		Oliver

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [RFC PATCHv2] usb: USB Type-C Connector Class
  2016-05-19 14:48 ` Oliver Neukum
@ 2016-05-19 15:43   ` Greg KH
  2016-05-20 10:58     ` Heikki Krogerus
  0 siblings, 1 reply; 98+ messages in thread
From: Greg KH @ 2016-05-19 15:43 UTC (permalink / raw)
  To: Oliver Neukum
  Cc: Heikki Krogerus, Guenter Roeck, Andy Shevchenko, Rajaram R,
	Felipe Balbi, Mathias Nyman, linux-kernel, linux-usb

On Thu, May 19, 2016 at 04:48:46PM +0200, Oliver Neukum wrote:
> On Thu, 2016-05-19 at 15:44 +0300, Heikki Krogerus wrote:
> 
> > +	dev->class = &typec_class;
> > +	dev->parent = parent;
> > +	dev->type = &typec_partner_dev_type;
> > +	dev_set_name(dev, "%s-partner", dev_name(&port->dev));
> > +
> > +	ret = device_register(dev);
> > +	if (ret) {
> > +		put_device(dev);
> > +		return ret;
> > +	}
> 
> This looks like a race condition.

Really?  How?

> > +	ret = typec_register_altmodes(dev, partner->alt_modes);
> > +	if (ret) {
> > +		device_unregister(dev);
> > +		return ret;
> > +	}
> > +
> > +	/* REVISIT: Creating symlink for the port device for now. */
> > +	ret = sysfs_create_link(&port->dev.kobj, &dev->kobj, "partner");
> > +	if (ret)
> > +		dev_WARN(&port->dev, "failed to create link to %s (%d)\n",
> > +			 dev_name(dev), ret);
> 
> The attributes should be present as soon as the device is announced.

Yes, this is wrong and racy (hint, if you have to drop down to a sysfs
call within a driver, almost always something is wrong...)

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [RFC PATCHv2] usb: USB Type-C Connector Class
  2016-05-19 12:44 [RFC PATCHv2] usb: USB Type-C Connector Class Heikki Krogerus
  2016-05-19 14:47 ` Oliver Neukum
  2016-05-19 14:48 ` Oliver Neukum
@ 2016-05-19 17:53 ` Guenter Roeck
  2016-05-20 10:47   ` Heikki Krogerus
  2016-05-20 14:19 ` Oliver Neukum
                   ` (9 subsequent siblings)
  12 siblings, 1 reply; 98+ messages in thread
From: Guenter Roeck @ 2016-05-19 17:53 UTC (permalink / raw)
  To: Heikki Krogerus
  Cc: Greg KH, Mathias Nyman, Felipe Balbi, Oliver Neukum, Rajaram R,
	Andy Shevchenko, linux-kernel, linux-usb

Hello Heikki,

On Thu, May 19, 2016 at 03:44:54PM +0300, Heikki Krogerus wrote:
> The purpose of this class is to provide unified interface for user
> space to get the status and basic information about USB Type-C
> Connectors in the system, control data role swapping, and when USB PD
> is available, also power role swapping and Alternate Modes.
> 
> Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
> ---
>  drivers/usb/Kconfig         |   2 +
>  drivers/usb/Makefile        |   2 +
>  drivers/usb/type-c/Kconfig  |   7 +
>  drivers/usb/type-c/Makefile |   1 +
>  drivers/usb/type-c/typec.c  | 957 ++++++++++++++++++++++++++++++++++++++++++++
>  include/linux/usb/typec.h   | 230 +++++++++++
>  6 files changed, 1199 insertions(+)
>  create mode 100644 drivers/usb/type-c/Kconfig
>  create mode 100644 drivers/usb/type-c/Makefile
>  create mode 100644 drivers/usb/type-c/typec.c
>  create mode 100644 include/linux/usb/typec.h
> 
> Hi,
> 
> Like I've told some of you guys, I'm trying to implement a bus for
> the Alternate Modes, but I'm still nowhere near finished with that
> one, so let's just get the class ready now. The altmode bus should in
> any case not affect the userspace interface proposed in this patch.
> 
> As you can see, the Alternate Modes are handled completely differently
> compared to the original proposal. Every Alternate Mode will have
> their own device instance (which will be then later bound to an
> Alternate Mode specific driver once we have the bus), but also every
> partner, cable and cable plug will have their own device instances
> representing them.
> 
> An other change is that the data role is now handled in two ways.
> The current_data_role file will represent static mode of the port, and
> it will use the names for the roles as they are defined in the spec:
> DFP, UFP and DRP. This file should be used if the port needs to be
> fixed to one specific role with DRP ports. So this approach will
> replace the suggestions for "preferred" data role we had. The
> current_usb_data_role will use values "host" and "device" and it will
> be used for data role swapping when already connected.
> 

What I am missing completely is a means to handle role and alternate mode
changes triggered by the partner. The need for those should be obvious,
unless I am really missing something (just consider two devices supporting
this code connected to each other).

Also, I am not sure where the policy engine is supposed to reside.
I understand that some policy changes (eg unsolicited requests to switch roles)
can be triggered from user space. However, role change requests triggered from
the partner need to be evaluated quickly (typically within 15 ms), so user
space can not get involved. Maybe it would help to have some text describing
where the policy engine is expected to reside and how it is involved
in the decision making process. This includes the initial decision making
process, when it needs to be decided if role changes should be requested
or if one or multiple alternate modes should be entered after the initial
connection has been established.

On top of that, I am concerned about synchronization problems with role
changes triggered from user space. The driver is not told about the
desired role, only that it shall perform a role change. If a role change
triggered by the partner is ongoing at the time a role change request is
made from user space, it may well happen that the dual role change results
in a revert to the original role. Some synchronization primitives as well
as an API change might resolve that, but essentially it would mean that
drivers have to implement at least part of the policy engine. It might
make more sense to have that code in the infrastructure.

On disconnect, a port reverts to the default role. However, on port
registration, the port roles are left at 0, meaning they always
default to device/sink independent of the port's capabilities. Is this
on purpose ?

current_data_role_store() lets user space set a fixed port role. However,
the port role variables are not updated. How is this supposed to be handled ?
The same is true for other role change attributes - I don't see any code
to update the role variables. Presumably this would have to be done in the
class code, since the port data structure is private.

Overall, I am quite concerned by the lack of synchronization primitives
between the class code and port drivers, but also in the class code
itself. For example, nothing prevents multiple user space processes
from writing into the same (or different) attribute(s) repeatedly.

Thanks,
Guenter

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [RFC PATCHv2] usb: USB Type-C Connector Class
  2016-05-19 17:53 ` Guenter Roeck
@ 2016-05-20 10:47   ` Heikki Krogerus
  2016-05-20 17:02     ` Guenter Roeck
  0 siblings, 1 reply; 98+ messages in thread
From: Heikki Krogerus @ 2016-05-20 10:47 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Greg KH, Mathias Nyman, Felipe Balbi, Oliver Neukum, Rajaram R,
	Andy Shevchenko, linux-kernel, linux-usb

On Thu, May 19, 2016 at 10:53:04AM -0700, Guenter Roeck wrote:
> Hello Heikki,
> 
> On Thu, May 19, 2016 at 03:44:54PM +0300, Heikki Krogerus wrote:
> > The purpose of this class is to provide unified interface for user
> > space to get the status and basic information about USB Type-C
> > Connectors in the system, control data role swapping, and when USB PD
> > is available, also power role swapping and Alternate Modes.
> > 
> > Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
> > ---
> >  drivers/usb/Kconfig         |   2 +
> >  drivers/usb/Makefile        |   2 +
> >  drivers/usb/type-c/Kconfig  |   7 +
> >  drivers/usb/type-c/Makefile |   1 +
> >  drivers/usb/type-c/typec.c  | 957 ++++++++++++++++++++++++++++++++++++++++++++
> >  include/linux/usb/typec.h   | 230 +++++++++++
> >  6 files changed, 1199 insertions(+)
> >  create mode 100644 drivers/usb/type-c/Kconfig
> >  create mode 100644 drivers/usb/type-c/Makefile
> >  create mode 100644 drivers/usb/type-c/typec.c
> >  create mode 100644 include/linux/usb/typec.h
> > 
> > Hi,
> > 
> > Like I've told some of you guys, I'm trying to implement a bus for
> > the Alternate Modes, but I'm still nowhere near finished with that
> > one, so let's just get the class ready now. The altmode bus should in
> > any case not affect the userspace interface proposed in this patch.
> > 
> > As you can see, the Alternate Modes are handled completely differently
> > compared to the original proposal. Every Alternate Mode will have
> > their own device instance (which will be then later bound to an
> > Alternate Mode specific driver once we have the bus), but also every
> > partner, cable and cable plug will have their own device instances
> > representing them.
> > 
> > An other change is that the data role is now handled in two ways.
> > The current_data_role file will represent static mode of the port, and
> > it will use the names for the roles as they are defined in the spec:
> > DFP, UFP and DRP. This file should be used if the port needs to be
> > fixed to one specific role with DRP ports. So this approach will
> > replace the suggestions for "preferred" data role we had. The
> > current_usb_data_role will use values "host" and "device" and it will
> > be used for data role swapping when already connected.
> > 
> 
> What I am missing completely is a means to handle role and alternate mode
> changes triggered by the partner. The need for those should be obvious,
> unless I am really missing something (just consider two devices supporting
> this code connected to each other).

We are missing the notifications that are needed in these cases. But I
don't see much more we can do about those cases. We can not put any
policies in place at this level, because we have to be able to support
also things like USB PD and Type-C controllers that take care of all
that, leaving us to not be able to do anything else but to pass the
information forward. So the framework at this level has to be
"stupid", and if more infrastructure is needed, it has to be
introduced in an other layer.

> Also, I am not sure where the policy engine is supposed to reside.
> I understand that some policy changes (eg unsolicited requests to switch roles)
> can be triggered from user space. However, role change requests triggered from
> the partner need to be evaluated quickly (typically within 15 ms), so user
> space can not get involved. Maybe it would help to have some text describing
> where the policy engine is expected to reside and how it is involved
> in the decision making process. This includes the initial decision making
> process, when it needs to be decided if role changes should be requested
> or if one or multiple alternate modes should be entered after the initial
> connection has been established.

Well, yes we need to document these things, but you are now coupling
this framework with USB PD and we really should not do that.

The policy engine, and the whole USB PD stack, belongs inside the
kernel, and it will be completely separated from this framework. This
framework can not have any dependencies on the future USB PD stack.
This is not only because of the USB PD/Type-C controllers which handle
the policy engine on their own and only allow "unsolicited" requests
like "swap role" and "enter/exit mode", but also because this
framework must work smoothly on systems that don't want to use USB PD
and of course also with USB Type-C PHYs that simply don't include USB
PD transceiver.

The layer that joins these two parts together will be the port drivers
themselves, so the USB Type-C/PD PHYs and controllers, at least in the
beginning.

Any initial decisions about which role or which alternate mode to
select belongs to the stack. The userspace will need to be notified,
and the userspace can then attempt to request changes after that, but
if there is something that blocks the requests, the attempt has to
just fail. So we can't provide any knowledge for the userspace about
the requirements regarding the high level operations we allow the
userspace to request (so in practice swap role/power and enter/exit
mode). This information the userspace needs to get from somewhere else
just live without it. Nor do we expect the userspace to be aware of
the state of the system. So for example if the userspace attempts to
activate a mode, the framework will just pass it forward to the port
driver, which will then process it with the PD stack, and if for
example the state is not PE_SRC_Ready or PE_SNK_Ready or whatever, the
operation will just fail probable with -EBUSY in that case.

And the knowledge about dependencies related to the alternate modes
belong primarily to the alternate mode specific drivers in the end
(once we have the bus) like I said. We can't expect the USB PD stack
to be aware of those as they are alternate mode specific, and of
course we can not trust that the userspace will always do things the
right way. But the initial states after connection must be handle by
the policy engine of course.

> On top of that, I am concerned about synchronization problems with role
> changes triggered from user space. The driver is not told about the
> desired role, only that it shall perform a role change. If a role change
> triggered by the partner is ongoing at the time a role change request is
> made from user space, it may well happen that the dual role change results
> in a revert to the original role. Some synchronization primitives as well
> as an API change might resolve that, but essentially it would mean that
> drivers have to implement at least part of the policy engine. It might
> make more sense to have that code in the infrastructure.

Well, like I said above, this framework can not provide this
infrastructure. The framework at this level really has to be "stupid".
We simply can not do any decisions or have any expectations at this
level. If more infra is needed, it has to be provided in an other layer
on top of this bottom layer. So basically the driver have to implement
those things for now.

> On disconnect, a port reverts to the default role. However, on port
> registration, the port roles are left at 0, meaning they always
> default to device/sink independent of the port's capabilities. Is this
> on purpose ?

On disconnect, the port role is set according to the "fixed_role"? If
the port is DFP only, then the port will still be host/source after
disconnect. I don't see the problem here?

> current_data_role_store() lets user space set a fixed port role. However,
> the port role variables are not updated. How is this supposed to be handled ?
> The same is true for other role change attributes - I don't see any code
> to update the role variables. Presumably this would have to be done in the
> class code, since the port data structure is private.

This is a bug in the code indeed.

> Overall, I am quite concerned by the lack of synchronization primitives
> between the class code and port drivers, but also in the class code
> itself. For example, nothing prevents multiple user space processes
> from writing into the same (or different) attribute(s) repeatedly.

We clearly need consensus on what this class will be responsible of.
I've tried to explain how I see it above, hopefully with reasonable
explanations. So basically, USB PD for this class is just a external
feature that the alternate modes and power and vconn swapping depends
on, that the class can not take any responsibility of IMHO.

The UCSI spec defines an other layer on top of the USB PD stack that
basically describes what the userspace interface that I'm trying to
achieve with this class is. The "OS Policy".


Thanks,

-- 
heikki

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [RFC PATCHv2] usb: USB Type-C Connector Class
  2016-05-19 15:43   ` Greg KH
@ 2016-05-20 10:58     ` Heikki Krogerus
  0 siblings, 0 replies; 98+ messages in thread
From: Heikki Krogerus @ 2016-05-20 10:58 UTC (permalink / raw)
  To: Greg KH, Oliver Neukum
  Cc: Guenter Roeck, Andy Shevchenko, Rajaram R, Felipe Balbi,
	Mathias Nyman, linux-kernel, linux-usb

On Thu, May 19, 2016 at 08:43:27AM -0700, Greg KH wrote:
> On Thu, May 19, 2016 at 04:48:46PM +0200, Oliver Neukum wrote:
> > On Thu, 2016-05-19 at 15:44 +0300, Heikki Krogerus wrote:
> > > +	ret = typec_register_altmodes(dev, partner->alt_modes);
> > > +	if (ret) {
> > > +		device_unregister(dev);
> > > +		return ret;
> > > +	}
> > > +
> > > +	/* REVISIT: Creating symlink for the port device for now. */
> > > +	ret = sysfs_create_link(&port->dev.kobj, &dev->kobj, "partner");
> > > +	if (ret)
> > > +		dev_WARN(&port->dev, "failed to create link to %s (%d)\n",
> > > +			 dev_name(dev), ret);
> > 
> > The attributes should be present as soon as the device is announced.
> 
> Yes, this is wrong and racy (hint, if you have to drop down to a sysfs
> call within a driver, almost always something is wrong...)

I'll remove those links.

I'm hoping to get comments about the attributes in general. Do we
have everything needed to describe the state and capabilities of USB
Type-C ports with them, and are they in reasonable places. I'm playing
with these links in couple of places in the code, and I've put
questions in the comments on some of them. I'm really not planning on
leaving them as they are.

So if you guys could provide your opinions on those questions, I would
much appreciate.


Thanks a lot,

-- 
heikki

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [RFC PATCHv2] usb: USB Type-C Connector Class
  2016-05-19 14:47 ` Oliver Neukum
@ 2016-05-20 11:24   ` Heikki Krogerus
  2016-05-20 13:37     ` Oliver Neukum
  0 siblings, 1 reply; 98+ messages in thread
From: Heikki Krogerus @ 2016-05-20 11:24 UTC (permalink / raw)
  To: Oliver Neukum
  Cc: Guenter Roeck, Andy Shevchenko, Rajaram R, Felipe Balbi,
	Mathias Nyman, Greg KH, linux-kernel, linux-usb

On Thu, May 19, 2016 at 04:47:17PM +0200, Oliver Neukum wrote:
> On Thu, 2016-05-19 at 15:44 +0300, Heikki Krogerus wrote:
> > The purpose of this class is to provide unified interface for user
> > space to get the status and basic information about USB Type-C
> > Connectors in the system, control data role swapping, and when USB PD
> > is available, also power role swapping and Alternate Modes.
> > 
> > Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
> > ---
> >  drivers/usb/Kconfig         |   2 +
> >  drivers/usb/Makefile        |   2 +
> >  drivers/usb/type-c/Kconfig  |   7 +
> >  drivers/usb/type-c/Makefile |   1 +
> >  drivers/usb/type-c/typec.c  | 957 ++++++++++++++++++++++++++++++++++++++++++++
> >  include/linux/usb/typec.h   | 230 +++++++++++
> >  6 files changed, 1199 insertions(+)
> >  create mode 100644 drivers/usb/type-c/Kconfig
> >  create mode 100644 drivers/usb/type-c/Makefile
> >  create mode 100644 drivers/usb/type-c/typec.c
> >  create mode 100644 include/linux/usb/typec.h
> > 
> > Hi,
> > 
> > Like I've told some of you guys, I'm trying to implement a bus for
> > the Alternate Modes, but I'm still nowhere near finished with that
> > one, so let's just get the class ready now. The altmode bus should in
> > any case not affect the userspace interface proposed in this patch.
> > 
> > As you can see, the Alternate Modes are handled completely differently
> > compared to the original proposal. Every Alternate Mode will have
> > their own device instance (which will be then later bound to an
> > Alternate Mode specific driver once we have the bus), but also every
> > partner, cable and cable plug will have their own device instances
> > representing them.
> 
> That raises a question. If I read the standard correctly, alternate
> modes could be combinable. So how do you represent that.
> 
> > An other change is that the data role is now handled in two ways.
> > The current_data_role file will represent static mode of the port, and
> > it will use the names for the roles as they are defined in the spec:
> > DFP, UFP and DRP. This file should be used if the port needs to be
> > fixed to one specific role with DRP ports. So this approach will
> > replace the suggestions for "preferred" data role we had. The
> > current_usb_data_role will use values "host" and "device" and it will
> > be used for data role swapping when already connected.
> 
> Please explain. How does that express DRP but prefered master?

Sorry but I'm not sure what you mean here. If the port is capable of
being used as dual role port (DRP in the supported_data_roles file),
that is the only case where you can select the role with this file. So
I would imagine that in your case you want to make the port act as
DFP only, right? But if the port is capable of acting only as UFP, you
are stuck with that role.

> > I Hope I remembered to CC everybody interested.
> 
> Alternate modes can be left involuntarily. So we need a method of
> notification.

Yes, that is missing indeed.


Thanks,

-- 
heikki

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [RFC PATCHv2] usb: USB Type-C Connector Class
  2016-05-20 11:24   ` Heikki Krogerus
@ 2016-05-20 13:37     ` Oliver Neukum
  2016-05-21  5:51       ` Guenter Roeck
  0 siblings, 1 reply; 98+ messages in thread
From: Oliver Neukum @ 2016-05-20 13:37 UTC (permalink / raw)
  To: Heikki Krogerus
  Cc: Andy Shevchenko, Rajaram R, Felipe Balbi, Mathias Nyman, Greg KH,
	Guenter Roeck, linux-kernel, linux-usb

On Fri, 2016-05-20 at 14:24 +0300, Heikki Krogerus wrote:
> On Thu, May 19, 2016 at 04:47:17PM +0200, Oliver Neukum wrote:
> >
> > Please explain. How does that express DRP but prefered master?
> 
> Sorry but I'm not sure what you mean here. If the port is capable of
> being used as dual role port (DRP in the supported_data_roles file),
> that is the only case where you can select the role with this file. So
> I would imagine that in your case you want to make the port act as
> DFP only, right? But if the port is capable of acting only as UFP, you
> are stuck with that role.

How do I trigger that Try.SRC is to be used on a port?

	Regards
		Oliver

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [RFC PATCHv2] usb: USB Type-C Connector Class
  2016-05-19 12:44 [RFC PATCHv2] usb: USB Type-C Connector Class Heikki Krogerus
                   ` (2 preceding siblings ...)
  2016-05-19 17:53 ` Guenter Roeck
@ 2016-05-20 14:19 ` Oliver Neukum
  2016-05-23  9:57   ` Heikki Krogerus
  2016-05-24 12:51 ` Oliver Neukum
                   ` (8 subsequent siblings)
  12 siblings, 1 reply; 98+ messages in thread
From: Oliver Neukum @ 2016-05-20 14:19 UTC (permalink / raw)
  To: Heikki Krogerus
  Cc: Guenter Roeck, Andy Shevchenko, Rajaram R, Felipe Balbi,
	Mathias Nyman, Greg KH, linux-kernel, linux-usb

On Thu, 2016-05-19 at 15:44 +0300, Heikki Krogerus wrote:
> Like I've told some of you guys, I'm trying to implement a bus for
> the Alternate Modes, but I'm still nowhere near finished with that
> one, so let's just get the class ready now. The altmode bus should in
> any case not affect the userspace interface proposed in this patch.

Is this strictly divorced from USB PD?
How do you trigger a cable reset or a USB PD reset?

	Regards
		Oliver

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [RFC PATCHv2] usb: USB Type-C Connector Class
  2016-05-20 10:47   ` Heikki Krogerus
@ 2016-05-20 17:02     ` Guenter Roeck
  2016-05-23  9:23       ` Heikki Krogerus
  0 siblings, 1 reply; 98+ messages in thread
From: Guenter Roeck @ 2016-05-20 17:02 UTC (permalink / raw)
  To: Heikki Krogerus
  Cc: Greg KH, Mathias Nyman, Felipe Balbi, Oliver Neukum, Rajaram R,
	Andy Shevchenko, linux-kernel, linux-usb

On Fri, May 20, 2016 at 01:47:03PM +0300, Heikki Krogerus wrote:
> On Thu, May 19, 2016 at 10:53:04AM -0700, Guenter Roeck wrote:
> > Hello Heikki,
> > 
> > On Thu, May 19, 2016 at 03:44:54PM +0300, Heikki Krogerus wrote:
> > > The purpose of this class is to provide unified interface for user
> > > space to get the status and basic information about USB Type-C
> > > Connectors in the system, control data role swapping, and when USB PD
> > > is available, also power role swapping and Alternate Modes.
> > > 
> > > Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
> > > ---
> > >  drivers/usb/Kconfig         |   2 +
> > >  drivers/usb/Makefile        |   2 +
> > >  drivers/usb/type-c/Kconfig  |   7 +
> > >  drivers/usb/type-c/Makefile |   1 +
> > >  drivers/usb/type-c/typec.c  | 957 ++++++++++++++++++++++++++++++++++++++++++++
> > >  include/linux/usb/typec.h   | 230 +++++++++++
> > >  6 files changed, 1199 insertions(+)
> > >  create mode 100644 drivers/usb/type-c/Kconfig
> > >  create mode 100644 drivers/usb/type-c/Makefile
> > >  create mode 100644 drivers/usb/type-c/typec.c
> > >  create mode 100644 include/linux/usb/typec.h
> > > 
> > > Hi,
> > > 
> > > Like I've told some of you guys, I'm trying to implement a bus for
> > > the Alternate Modes, but I'm still nowhere near finished with that
> > > one, so let's just get the class ready now. The altmode bus should in
> > > any case not affect the userspace interface proposed in this patch.
> > > 
> > > As you can see, the Alternate Modes are handled completely differently
> > > compared to the original proposal. Every Alternate Mode will have
> > > their own device instance (which will be then later bound to an
> > > Alternate Mode specific driver once we have the bus), but also every
> > > partner, cable and cable plug will have their own device instances
> > > representing them.
> > > 
> > > An other change is that the data role is now handled in two ways.
> > > The current_data_role file will represent static mode of the port, and
> > > it will use the names for the roles as they are defined in the spec:
> > > DFP, UFP and DRP. This file should be used if the port needs to be
> > > fixed to one specific role with DRP ports. So this approach will
> > > replace the suggestions for "preferred" data role we had. The
> > > current_usb_data_role will use values "host" and "device" and it will
> > > be used for data role swapping when already connected.
> > > 
> > 
> > What I am missing completely is a means to handle role and alternate mode
> > changes triggered by the partner. The need for those should be obvious,
> > unless I am really missing something (just consider two devices supporting
> > this code connected to each other).
> 
> We are missing the notifications that are needed in these cases. But I
> don't see much more we can do about those cases. We can not put any
> policies in place at this level, because we have to be able to support
> also things like USB PD and Type-C controllers that take care of all
> that, leaving us to not be able to do anything else but to pass the
> information forward. So the framework at this level has to be
> "stupid", and if more infrastructure is needed, it has to be
> introduced in an other layer.
> 
Ok.

> > Also, I am not sure where the policy engine is supposed to reside.
> > I understand that some policy changes (eg unsolicited requests to switch roles)
> > can be triggered from user space. However, role change requests triggered from
> > the partner need to be evaluated quickly (typically within 15 ms), so user
> > space can not get involved. Maybe it would help to have some text describing
> > where the policy engine is expected to reside and how it is involved
> > in the decision making process. This includes the initial decision making
> > process, when it needs to be decided if role changes should be requested
> > or if one or multiple alternate modes should be entered after the initial
> > connection has been established.
> 
> Well, yes we need to document these things, but you are now coupling
> this framework with USB PD and we really should not do that.
> 
Not really. I was trying to understand where you would expect the policy engine
to reside, which you answered above.

> The policy engine, and the whole USB PD stack, belongs inside the
> kernel, and it will be completely separated from this framework. This
> framework can not have any dependencies on the future USB PD stack.
> This is not only because of the USB PD/Type-C controllers which handle
> the policy engine on their own and only allow "unsolicited" requests
> like "swap role" and "enter/exit mode", but also because this
> framework must work smoothly on systems that don't want to use USB PD
> and of course also with USB Type-C PHYs that simply don't include USB
> PD transceiver.
> 
> The layer that joins these two parts together will be the port drivers
> themselves, so the USB Type-C/PD PHYs and controllers, at least in the
> beginning.
> 
> Any initial decisions about which role or which alternate mode to
> select belongs to the stack. The userspace will need to be notified,
> and the userspace can then attempt to request changes after that, but
> if there is something that blocks the requests, the attempt has to
> just fail. So we can't provide any knowledge for the userspace about
> the requirements regarding the high level operations we allow the
> userspace to request (so in practice swap role/power and enter/exit
> mode). This information the userspace needs to get from somewhere else
> just live without it. Nor do we expect the userspace to be aware of
> the state of the system. So for example if the userspace attempts to
> activate a mode, the framework will just pass it forward to the port
> driver, which will then process it with the PD stack, and if for
> example the state is not PE_SRC_Ready or PE_SNK_Ready or whatever, the
> operation will just fail probable with -EBUSY in that case.
> 
Makes sense.

> And the knowledge about dependencies related to the alternate modes
> belong primarily to the alternate mode specific drivers in the end
> (once we have the bus) like I said. We can't expect the USB PD stack
> to be aware of those as they are alternate mode specific, and of
> course we can not trust that the userspace will always do things the
> right way. But the initial states after connection must be handle by
> the policy engine of course.
> 
> > On top of that, I am concerned about synchronization problems with role
> > changes triggered from user space. The driver is not told about the
> > desired role, only that it shall perform a role change. If a role change
> > triggered by the partner is ongoing at the time a role change request is
> > made from user space, it may well happen that the dual role change results
> > in a revert to the original role. Some synchronization primitives as well
> > as an API change might resolve that, but essentially it would mean that
> > drivers have to implement at least part of the policy engine. It might
> > make more sense to have that code in the infrastructure.
> 
> Well, like I said above, this framework can not provide this
> infrastructure. The framework at this level really has to be "stupid".

Ok.

> We simply can not do any decisions or have any expectations at this
> level. If more infra is needed, it has to be provided in an other layer
> on top of this bottom layer. So basically the driver have to implement
> those things for now.
> 
I still think that the lack of synchronization is inherently racy.
For example, on a power role swap request, port->pwr_role can change
(via the currently missing notification) after it was evaluated in
current_power_role_store(), but before port->cap->pr_swap() is called.
The lower level code has at this point no means to know which power role
change was requested, which may result in the power role being swapped
again even though it already is in the requested state.

> > On disconnect, a port reverts to the default role. However, on port
> > registration, the port roles are left at 0, meaning they always
> > default to device/sink independent of the port's capabilities. Is this
> > on purpose ?
> 
> On disconnect, the port role is set according to the "fixed_role"? If
> the port is DFP only, then the port will still be host/source after
> disconnect. I don't see the problem here?
> 
Roles are set differently on port registration vs. disconnect.
This means that roles (can) differ between "initial disconnect state"
and "disconnect state after connect". On port registration, usb_role,
pwr_role, and vconn_role are all set based on the current pwr_opmode.
During port registration, they are all initialized with 0.

> > current_data_role_store() lets user space set a fixed port role. However,
> > the port role variables are not updated. How is this supposed to be handled ?
> > The same is true for other role change attributes - I don't see any code
> > to update the role variables. Presumably this would have to be done in the
> > class code, since the port data structure is private.
> 
> This is a bug in the code indeed.
> 
> > Overall, I am quite concerned by the lack of synchronization primitives
> > between the class code and port drivers, but also in the class code
> > itself. For example, nothing prevents multiple user space processes
> > from writing into the same (or different) attribute(s) repeatedly.
> 
> We clearly need consensus on what this class will be responsible of.
> I've tried to explain how I see it above, hopefully with reasonable
> explanations. So basically, USB PD for this class is just a external
> feature that the alternate modes and power and vconn swapping depends
> on, that the class can not take any responsibility of IMHO.
> 
Sounds good to me, as long as the lower level code can inform the class
about state/role changes.

> The UCSI spec defines an other layer on top of the USB PD stack that
> basically describes what the userspace interface that I'm trying to
> achieve with this class is. The "OS Policy".
> 
Since you mention UCSI - in UCSI, the two API functions available to set
the power role (Set Power Direction Mode, Set Power Direction Mode)
both provide the desired role to the connector driver. How does this map
to the API in the class code, where a power swap is requested without
telling the low level code about the desired role ?

Personally I prefer the approach used in UCSI, or let's say what I perceive
the approach to be: Maybe the class code should just send a request to the
connector driver to change the role to X, independent of the current role.
This way, most if not all synchronization problems could be handled by the
lower level driver.

On a side note, I don't see how to request a vconn swap with UCSI.
Is that supported ?

Thanks,
Guenter

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [RFC PATCHv2] usb: USB Type-C Connector Class
  2016-05-20 13:37     ` Oliver Neukum
@ 2016-05-21  5:51       ` Guenter Roeck
  2016-05-21  6:43         ` Oliver Neukum
  0 siblings, 1 reply; 98+ messages in thread
From: Guenter Roeck @ 2016-05-21  5:51 UTC (permalink / raw)
  To: Oliver Neukum, Heikki Krogerus
  Cc: Andy Shevchenko, Rajaram R, Felipe Balbi, Mathias Nyman, Greg KH,
	linux-kernel, linux-usb

On 05/20/2016 06:37 AM, Oliver Neukum wrote:
> On Fri, 2016-05-20 at 14:24 +0300, Heikki Krogerus wrote:
>> On Thu, May 19, 2016 at 04:47:17PM +0200, Oliver Neukum wrote:
>>>
>>> Please explain. How does that express DRP but prefered master?
>>
>> Sorry but I'm not sure what you mean here. If the port is capable of
>> being used as dual role port (DRP in the supported_data_roles file),
>> that is the only case where you can select the role with this file. So
>> I would imagine that in your case you want to make the port act as
>> DFP only, right? But if the port is capable of acting only as UFP, you
>> are stuck with that role.
>
> How do I trigger that Try.SRC is to be used on a port?
>

This would be part of the USB PD protocol, ie probably outside the scope
of the class code. In my implementation, I enable Try.SRC or Try.SNK based
on the platform's preferred role.

Guenter

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [RFC PATCHv2] usb: USB Type-C Connector Class
  2016-05-21  5:51       ` Guenter Roeck
@ 2016-05-21  6:43         ` Oliver Neukum
  2016-05-22 15:54           ` Guenter Roeck
  0 siblings, 1 reply; 98+ messages in thread
From: Oliver Neukum @ 2016-05-21  6:43 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Heikki Krogerus, Andy Shevchenko, Rajaram R, Felipe Balbi,
	Mathias Nyman, Greg KH, linux-kernel, linux-usb

On Fri, 2016-05-20 at 22:51 -0700, Guenter Roeck wrote:
> On 05/20/2016 06:37 AM, Oliver Neukum wrote:
> > On Fri, 2016-05-20 at 14:24 +0300, Heikki Krogerus wrote:
> >> On Thu, May 19, 2016 at 04:47:17PM +0200, Oliver Neukum wrote:
> >>>
> >>> Please explain. How does that express DRP but prefered master?
> >>
> >> Sorry but I'm not sure what you mean here. If the port is capable of
> >> being used as dual role port (DRP in the supported_data_roles file),
> >> that is the only case where you can select the role with this file. So
> >> I would imagine that in your case you want to make the port act as
> >> DFP only, right? But if the port is capable of acting only as UFP, you
> >> are stuck with that role.
> >
> > How do I trigger that Try.SRC is to be used on a port?
> >
> 
> This would be part of the USB PD protocol, ie probably outside the scope
> of the class code. In my implementation, I enable Try.SRC or Try.SNK based
> on the platform's preferred role.

Hi,

from a purely formal point of view that makes sense.

>From a usability viewpoint I'd ideally want all controls
for role at one place. And possibly the controls for modes
at the same place.

I think part of the problem here is that we lack a statement
of mission. What are these controls for?
Merely for controlling modes and providing information
about modes? And to use neutral terms only for the "master"
side or both sides?

	Regards
		Oliver

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [RFC PATCHv2] usb: USB Type-C Connector Class
  2016-05-21  6:43         ` Oliver Neukum
@ 2016-05-22 15:54           ` Guenter Roeck
  2016-05-23  5:34             ` Oliver Neukum
  0 siblings, 1 reply; 98+ messages in thread
From: Guenter Roeck @ 2016-05-22 15:54 UTC (permalink / raw)
  To: Oliver Neukum
  Cc: Heikki Krogerus, Andy Shevchenko, Rajaram R, Felipe Balbi,
	Mathias Nyman, Greg KH, linux-kernel, linux-usb

Hi Oliver,

On 05/20/2016 11:43 PM, Oliver Neukum wrote:
> On Fri, 2016-05-20 at 22:51 -0700, Guenter Roeck wrote:
>> On 05/20/2016 06:37 AM, Oliver Neukum wrote:
>>> On Fri, 2016-05-20 at 14:24 +0300, Heikki Krogerus wrote:
>>>> On Thu, May 19, 2016 at 04:47:17PM +0200, Oliver Neukum wrote:
>>>>>
>>>>> Please explain. How does that express DRP but prefered master?
>>>>
>>>> Sorry but I'm not sure what you mean here. If the port is capable of
>>>> being used as dual role port (DRP in the supported_data_roles file),
>>>> that is the only case where you can select the role with this file. So
>>>> I would imagine that in your case you want to make the port act as
>>>> DFP only, right? But if the port is capable of acting only as UFP, you
>>>> are stuck with that role.
>>>
>>> How do I trigger that Try.SRC is to be used on a port?
>>>
>>
>> This would be part of the USB PD protocol, ie probably outside the scope
>> of the class code. In my implementation, I enable Try.SRC or Try.SNK based
>> on the platform's preferred role.
>
> Hi,
>
> from a purely formal point of view that makes sense.
>
>>From a usability viewpoint I'd ideally want all controls
> for role at one place. And possibly the controls for modes
> at the same place.
>
> I think part of the problem here is that we lack a statement
> of mission. What are these controls for?
> Merely for controlling modes and providing information
> about modes? And to use neutral terms only for the "master"
> side or both sides?
>

Good question. I originally added a sysfs attribute 'preferred-mode' to
my code, but then concluded that this is supposed to be provided
by the platform and added it as platform data instead, with (currently)
no means to report it to user space.

Heikki's current code doesn't really match the semantics of a 'preferred'
mode, at least not as I read it. In my understanding, 'preferred mode'
means "this is a DRP port which prefers to be a source/sink". In Heikki's
code, one can fix the mode to source or sink, but that doesn't support
situations such as "this port prefers to be a source, but is currently
a sink because the link partner happens to be a charger or refuses to act
as sink for some other reason".

Given that, my working assumption is that preferred mode handling is supposed
to be outside the scope of the infrastructure. I am happy to be corrected,
though.

On a side note, are you working on a USB-PD implementation as well ?

Thanks,
Guenter

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [RFC PATCHv2] usb: USB Type-C Connector Class
  2016-05-22 15:54           ` Guenter Roeck
@ 2016-05-23  5:34             ` Oliver Neukum
  2016-05-23 13:27               ` Guenter Roeck
  0 siblings, 1 reply; 98+ messages in thread
From: Oliver Neukum @ 2016-05-23  5:34 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Andy Shevchenko, Rajaram R, Felipe Balbi, Heikki Krogerus,
	Mathias Nyman, Greg KH, linux-kernel, linux-usb

On Sun, 2016-05-22 at 08:54 -0700, Guenter Roeck wrote:
> Hi Oliver,
> 
> On 05/20/2016 11:43 PM, Oliver Neukum wrote:
> > On Fri, 2016-05-20 at 22:51 -0700, Guenter Roeck wrote:
> >> On 05/20/2016 06:37 AM, Oliver Neukum wrote:
> >>> On Fri, 2016-05-20 at 14:24 +0300, Heikki Krogerus wrote:
> >>>> On Thu, May 19, 2016 at 04:47:17PM +0200, Oliver Neukum wrote:
> >>>>>
> >>>>> Please explain. How does that express DRP but prefered master?
> >>>>
> >>>> Sorry but I'm not sure what you mean here. If the port is capable of
> >>>> being used as dual role port (DRP in the supported_data_roles file),
> >>>> that is the only case where you can select the role with this file. So
> >>>> I would imagine that in your case you want to make the port act as
> >>>> DFP only, right? But if the port is capable of acting only as UFP, you
> >>>> are stuck with that role.
> >>>
> >>> How do I trigger that Try.SRC is to be used on a port?
> >>>
> >>
> >> This would be part of the USB PD protocol, ie probably outside the scope
> >> of the class code. In my implementation, I enable Try.SRC or Try.SNK based
> >> on the platform's preferred role.
> >
> > Hi,
> >
> > from a purely formal point of view that makes sense.
> >
> >>From a usability viewpoint I'd ideally want all controls
> > for role at one place. And possibly the controls for modes
> > at the same place.
> >
> > I think part of the problem here is that we lack a statement
> > of mission. What are these controls for?
> > Merely for controlling modes and providing information
> > about modes? And to use neutral terms only for the "master"
> > side or both sides?
> >
> 
> Good question. I originally added a sysfs attribute 'preferred-mode' to
> my code, but then concluded that this is supposed to be provided
> by the platform and added it as platform data instead, with (currently)
> no means to report it to user space.

Mode or role? I would say that the choice of alternate modes belongs to
user space. THere's no point in giving a preference to the kernel.
Role is different. Try.SRC is part of the standard (and Try.SNK has been
added). It needs to be in kernel space.

Now, if you say that this API is for selecting modes only, then I say it
lacks support for cable resets and notifications thereof. Yes, that is a
PD feature, but that doesn't help us. It changes the mode.

> Heikki's current code doesn't really match the semantics of a 'preferred'
> mode, at least not as I read it. In my understanding, 'preferred mode'
> means "this is a DRP port which prefers to be a source/sink". In Heikki's
> code, one can fix the mode to source or sink, but that doesn't support
> situations such as "this port prefers to be a source, but is currently
> a sink because the link partner happens to be a charger or refuses to act
> as sink for some other reason".

Yes. That is why we need a mission statement. We may be talking
a rice cooker not preparing tea here.

> Given that, my working assumption is that preferred mode handling is supposed
> to be outside the scope of the infrastructure. I am happy to be corrected,
> though.
> 
> On a side note, are you working on a USB-PD implementation as well ?

No, one of my task is to to make use of USB PD (and alternate modes)
in a distribution.

	Regards
		Oliver

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [RFC PATCHv2] usb: USB Type-C Connector Class
  2016-05-20 17:02     ` Guenter Roeck
@ 2016-05-23  9:23       ` Heikki Krogerus
  0 siblings, 0 replies; 98+ messages in thread
From: Heikki Krogerus @ 2016-05-23  9:23 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Greg KH, Mathias Nyman, Felipe Balbi, Oliver Neukum, Rajaram R,
	Andy Shevchenko, linux-kernel, linux-usb

On Fri, May 20, 2016 at 10:02:28AM -0700, Guenter Roeck wrote:
> On Fri, May 20, 2016 at 01:47:03PM +0300, Heikki Krogerus wrote:
> > On Thu, May 19, 2016 at 10:53:04AM -0700, Guenter Roeck wrote:
> > > Hello Heikki,
> > > 
> > > On Thu, May 19, 2016 at 03:44:54PM +0300, Heikki Krogerus wrote:
> > > > The purpose of this class is to provide unified interface for user
> > > > space to get the status and basic information about USB Type-C
> > > > Connectors in the system, control data role swapping, and when USB PD
> > > > is available, also power role swapping and Alternate Modes.
> > > > 
> > > > Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
> > > > ---
> > > >  drivers/usb/Kconfig         |   2 +
> > > >  drivers/usb/Makefile        |   2 +
> > > >  drivers/usb/type-c/Kconfig  |   7 +
> > > >  drivers/usb/type-c/Makefile |   1 +
> > > >  drivers/usb/type-c/typec.c  | 957 ++++++++++++++++++++++++++++++++++++++++++++
> > > >  include/linux/usb/typec.h   | 230 +++++++++++
> > > >  6 files changed, 1199 insertions(+)
> > > >  create mode 100644 drivers/usb/type-c/Kconfig
> > > >  create mode 100644 drivers/usb/type-c/Makefile
> > > >  create mode 100644 drivers/usb/type-c/typec.c
> > > >  create mode 100644 include/linux/usb/typec.h
> > > > 
> > > > Hi,
> > > > 
> > > > Like I've told some of you guys, I'm trying to implement a bus for
> > > > the Alternate Modes, but I'm still nowhere near finished with that
> > > > one, so let's just get the class ready now. The altmode bus should in
> > > > any case not affect the userspace interface proposed in this patch.
> > > > 
> > > > As you can see, the Alternate Modes are handled completely differently
> > > > compared to the original proposal. Every Alternate Mode will have
> > > > their own device instance (which will be then later bound to an
> > > > Alternate Mode specific driver once we have the bus), but also every
> > > > partner, cable and cable plug will have their own device instances
> > > > representing them.
> > > > 
> > > > An other change is that the data role is now handled in two ways.
> > > > The current_data_role file will represent static mode of the port, and
> > > > it will use the names for the roles as they are defined in the spec:
> > > > DFP, UFP and DRP. This file should be used if the port needs to be
> > > > fixed to one specific role with DRP ports. So this approach will
> > > > replace the suggestions for "preferred" data role we had. The
> > > > current_usb_data_role will use values "host" and "device" and it will
> > > > be used for data role swapping when already connected.
> > > > 
> > > 
> > > What I am missing completely is a means to handle role and alternate mode
> > > changes triggered by the partner. The need for those should be obvious,
> > > unless I am really missing something (just consider two devices supporting
> > > this code connected to each other).
> > 
> > We are missing the notifications that are needed in these cases. But I
> > don't see much more we can do about those cases. We can not put any
> > policies in place at this level, because we have to be able to support
> > also things like USB PD and Type-C controllers that take care of all
> > that, leaving us to not be able to do anything else but to pass the
> > information forward. So the framework at this level has to be
> > "stupid", and if more infrastructure is needed, it has to be
> > introduced in an other layer.
> > 
> Ok.
> 
> > > Also, I am not sure where the policy engine is supposed to reside.
> > > I understand that some policy changes (eg unsolicited requests to switch roles)
> > > can be triggered from user space. However, role change requests triggered from
> > > the partner need to be evaluated quickly (typically within 15 ms), so user
> > > space can not get involved. Maybe it would help to have some text describing
> > > where the policy engine is expected to reside and how it is involved
> > > in the decision making process. This includes the initial decision making
> > > process, when it needs to be decided if role changes should be requested
> > > or if one or multiple alternate modes should be entered after the initial
> > > connection has been established.
> > 
> > Well, yes we need to document these things, but you are now coupling
> > this framework with USB PD and we really should not do that.
> > 
> Not really. I was trying to understand where you would expect the policy engine
> to reside, which you answered above.

Ah OK, got it. Sorry.

> > The policy engine, and the whole USB PD stack, belongs inside the
> > kernel, and it will be completely separated from this framework. This
> > framework can not have any dependencies on the future USB PD stack.
> > This is not only because of the USB PD/Type-C controllers which handle
> > the policy engine on their own and only allow "unsolicited" requests
> > like "swap role" and "enter/exit mode", but also because this
> > framework must work smoothly on systems that don't want to use USB PD
> > and of course also with USB Type-C PHYs that simply don't include USB
> > PD transceiver.
> > 
> > The layer that joins these two parts together will be the port drivers
> > themselves, so the USB Type-C/PD PHYs and controllers, at least in the
> > beginning.
> > 
> > Any initial decisions about which role or which alternate mode to
> > select belongs to the stack. The userspace will need to be notified,
> > and the userspace can then attempt to request changes after that, but
> > if there is something that blocks the requests, the attempt has to
> > just fail. So we can't provide any knowledge for the userspace about
> > the requirements regarding the high level operations we allow the
> > userspace to request (so in practice swap role/power and enter/exit
> > mode). This information the userspace needs to get from somewhere else
> > just live without it. Nor do we expect the userspace to be aware of
> > the state of the system. So for example if the userspace attempts to
> > activate a mode, the framework will just pass it forward to the port
> > driver, which will then process it with the PD stack, and if for
> > example the state is not PE_SRC_Ready or PE_SNK_Ready or whatever, the
> > operation will just fail probable with -EBUSY in that case.
> > 
> Makes sense.
> 
> > And the knowledge about dependencies related to the alternate modes
> > belong primarily to the alternate mode specific drivers in the end
> > (once we have the bus) like I said. We can't expect the USB PD stack
> > to be aware of those as they are alternate mode specific, and of
> > course we can not trust that the userspace will always do things the
> > right way. But the initial states after connection must be handle by
> > the policy engine of course.
> > 
> > > On top of that, I am concerned about synchronization problems with role
> > > changes triggered from user space. The driver is not told about the
> > > desired role, only that it shall perform a role change. If a role change
> > > triggered by the partner is ongoing at the time a role change request is
> > > made from user space, it may well happen that the dual role change results
> > > in a revert to the original role. Some synchronization primitives as well
> > > as an API change might resolve that, but essentially it would mean that
> > > drivers have to implement at least part of the policy engine. It might
> > > make more sense to have that code in the infrastructure.
> > 
> > Well, like I said above, this framework can not provide this
> > infrastructure. The framework at this level really has to be "stupid".
> 
> Ok.
> 
> > We simply can not do any decisions or have any expectations at this
> > level. If more infra is needed, it has to be provided in an other layer
> > on top of this bottom layer. So basically the driver have to implement
> > those things for now.
> > 
> I still think that the lack of synchronization is inherently racy.
> For example, on a power role swap request, port->pwr_role can change
> (via the currently missing notification) after it was evaluated in
> current_power_role_store(), but before port->cap->pr_swap() is called.
> The lower level code has at this point no means to know which power role
> change was requested, which may result in the power role being swapped
> again even though it already is in the requested state.

You are correct. We need to pass the requested role to the drivers.

> > > On disconnect, a port reverts to the default role. However, on port
> > > registration, the port roles are left at 0, meaning they always
> > > default to device/sink independent of the port's capabilities. Is this
> > > on purpose ?
> > 
> > On disconnect, the port role is set according to the "fixed_role"? If
> > the port is DFP only, then the port will still be host/source after
> > disconnect. I don't see the problem here?
> > 
> Roles are set differently on port registration vs. disconnect.
> This means that roles (can) differ between "initial disconnect state"
> and "disconnect state after connect". On port registration, usb_role,
> pwr_role, and vconn_role are all set based on the current pwr_opmode.
> During port registration, they are all initialized with 0.

Got it. I'll fix that.

> > > current_data_role_store() lets user space set a fixed port role. However,
> > > the port role variables are not updated. How is this supposed to be handled ?
> > > The same is true for other role change attributes - I don't see any code
> > > to update the role variables. Presumably this would have to be done in the
> > > class code, since the port data structure is private.
> > 
> > This is a bug in the code indeed.
> > 
> > > Overall, I am quite concerned by the lack of synchronization primitives
> > > between the class code and port drivers, but also in the class code
> > > itself. For example, nothing prevents multiple user space processes
> > > from writing into the same (or different) attribute(s) repeatedly.
> > 
> > We clearly need consensus on what this class will be responsible of.
> > I've tried to explain how I see it above, hopefully with reasonable
> > explanations. So basically, USB PD for this class is just a external
> > feature that the alternate modes and power and vconn swapping depends
> > on, that the class can not take any responsibility of IMHO.
> > 
> Sounds good to me, as long as the lower level code can inform the class
> about state/role changes.
> 
> > The UCSI spec defines an other layer on top of the USB PD stack that
> > basically describes what the userspace interface that I'm trying to
> > achieve with this class is. The "OS Policy".
> > 
> Since you mention UCSI - in UCSI, the two API functions available to set
> the power role (Set Power Direction Mode, Set Power Direction Mode)
> both provide the desired role to the connector driver. How does this map
> to the API in the class code, where a power swap is requested without
> telling the low level code about the desired role ?
> 
> Personally I prefer the approach used in UCSI, or let's say what I perceive
> the approach to be: Maybe the class code should just send a request to the
> connector driver to change the role to X, independent of the current role.
> This way, most if not all synchronization problems could be handled by the
> lower level driver.

That sounds good to me. And it fits to the plan that the class does
not make any decisions.

> On a side note, I don't see how to request a vconn swap with UCSI.
> Is that supported ?

No, with UCSI we can not support vconn swap. Originally I was not even
proposing an attribute for vconn swap in v1, but there was demand for
it.


Thanks,

-- 
heikki

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [RFC PATCHv2] usb: USB Type-C Connector Class
  2016-05-20 14:19 ` Oliver Neukum
@ 2016-05-23  9:57   ` Heikki Krogerus
  2016-05-23 11:25     ` Oliver Neukum
  0 siblings, 1 reply; 98+ messages in thread
From: Heikki Krogerus @ 2016-05-23  9:57 UTC (permalink / raw)
  To: Oliver Neukum
  Cc: Guenter Roeck, Andy Shevchenko, Rajaram R, Felipe Balbi,
	Mathias Nyman, Greg KH, linux-kernel, linux-usb

Hi Oliver,

On Fri, May 20, 2016 at 04:19:59PM +0200, Oliver Neukum wrote:
> On Thu, 2016-05-19 at 15:44 +0300, Heikki Krogerus wrote:
> > Like I've told some of you guys, I'm trying to implement a bus for
> > the Alternate Modes, but I'm still nowhere near finished with that
> > one, so let's just get the class ready now. The altmode bus should in
> > any case not affect the userspace interface proposed in this patch.
> 
> Is this strictly divorced from USB PD?

The bus can not be tied to the USB PD stack we will have in the
kernel completely, or there is no change of using it with things like
UCSI. It's going to be difficult to achieve that in any case as we
simply won't be able to send and rescieve the VDMs with things like
UCSI, but let's see.

> How do you trigger a cable reset or a USB PD reset?

There needs to be an API, but I'm sure that's not going to be a
problem. The bus and the altmode specific drivers will reside inside
kernel.

But I'm getting the sense that you are thinking about having some
responsibility of USB PD in userspace. Please correct me if I'm wrong.
I don't think it will be possible. I think the role of userspace can
only be the source for high level requests via this interface, like
enter/exit mode and swap role, and receiving the status and details of
the ports, but any knowledge about the requirements regarding those
steps belongs to the kernel. This includes also the knowledge about
stuff like mode dependencies, for example if cable plug has to be in a
certain mode in order for the partner to be able to enter some
specific mode, etc.


Thanks.

-- 
heikki

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [RFC PATCHv2] usb: USB Type-C Connector Class
  2016-05-23  9:57   ` Heikki Krogerus
@ 2016-05-23 11:25     ` Oliver Neukum
  2016-05-23 17:09       ` Guenter Roeck
  2016-05-24  9:32       ` Heikki Krogerus
  0 siblings, 2 replies; 98+ messages in thread
From: Oliver Neukum @ 2016-05-23 11:25 UTC (permalink / raw)
  To: Heikki Krogerus
  Cc: Andy Shevchenko, Rajaram R, Felipe Balbi, Mathias Nyman, Greg KH,
	Guenter Roeck, linux-kernel, linux-usb

On Mon, 2016-05-23 at 12:57 +0300, Heikki Krogerus wrote:
> Hi Oliver,
> 
> On Fri, May 20, 2016 at 04:19:59PM +0200, Oliver Neukum wrote:
> > On Thu, 2016-05-19 at 15:44 +0300, Heikki Krogerus wrote:
> > > Like I've told some of you guys, I'm trying to implement a bus for
> > > the Alternate Modes, but I'm still nowhere near finished with that
> > > one, so let's just get the class ready now. The altmode bus should in
> > > any case not affect the userspace interface proposed in this patch.
> > 
> > Is this strictly divorced from USB PD?
> 
> The bus can not be tied to the USB PD stack we will have in the
> kernel completely, or there is no change of using it with things like
> UCSI. It's going to be difficult to achieve that in any case as we
> simply won't be able to send and rescieve the VDMs with things like
> UCSI, but let's see.
> 
> > How do you trigger a cable reset or a USB PD reset?
> 
> There needs to be an API, but I'm sure that's not going to be a
> problem. The bus and the altmode specific drivers will reside inside
> kernel.

Absolutely. But at some point we need to settle on an API.
If I am to tell you whether your proposed API leaves out
something that needs to be covered, I need to know what
is to go into the other APIs.

A reset is a generic function, so it does not belong to specific
drivers.

> But I'm getting the sense that you are thinking about having some
> responsibility of USB PD in userspace. Please correct me if I'm wrong.

Gods help us all if we are ready to do that.
It would fail.
Yet I think the idea that PD and Alternate Modes can be cleanly
divorced is wrong. The selection of Alternate Modes is done by
USB PD messages. We can encapsulate that, but we cannot leave it out,
especially in the area of resets.

> I don't think it will be possible. I think the role of userspace can
> only be the source for high level requests via this interface, like
> enter/exit mode and swap role, and receiving the status and details of
> the ports, but any knowledge about the requirements regarding those
> steps belongs to the kernel. This includes also the knowledge about

Yes.

> stuff like mode dependencies, for example if cable plug has to be in a
> certain mode in order for the partner to be able to enter some
> specific mode, etc.

Yes.

So for Alternate Modes we need on a high level the following features

1. discovery of available Alternate Modes
2. selection of an Alternate Mode
3. notification about entering an Alternate Mode
4. triggering a reset
5. notification about resets

6. discovery about the current role
7. switching roles
8. setting preferred roles (Try.SRC and Try.SNK)

You covered 1. and 2.
3. can be covered by specific drivers
4. and 5. are not covered (and it makes no sense to tie it
to specific drivers)

6. and 7. is covered
8. is not

And 8. needs to be covered. It affects who selects the Alternate Mode.
You cannot tie it to USB and it doesn't fit with pure PD stuff.

I like your API as it is now. But it is incomplete.

	Regards
		Oliver

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [RFC PATCHv2] usb: USB Type-C Connector Class
  2016-05-23  5:34             ` Oliver Neukum
@ 2016-05-23 13:27               ` Guenter Roeck
  2016-05-23 13:58                 ` Oliver Neukum
  0 siblings, 1 reply; 98+ messages in thread
From: Guenter Roeck @ 2016-05-23 13:27 UTC (permalink / raw)
  To: Oliver Neukum
  Cc: Andy Shevchenko, Rajaram R, Felipe Balbi, Heikki Krogerus,
	Mathias Nyman, Greg KH, linux-kernel, linux-usb

On 05/22/2016 10:34 PM, Oliver Neukum wrote:
> On Sun, 2016-05-22 at 08:54 -0700, Guenter Roeck wrote:
>> Hi Oliver,
>>
>> On 05/20/2016 11:43 PM, Oliver Neukum wrote:
>>> On Fri, 2016-05-20 at 22:51 -0700, Guenter Roeck wrote:
>>>> On 05/20/2016 06:37 AM, Oliver Neukum wrote:
>>>>> On Fri, 2016-05-20 at 14:24 +0300, Heikki Krogerus wrote:
>>>>>> On Thu, May 19, 2016 at 04:47:17PM +0200, Oliver Neukum wrote:
>>>>>>>
>>>>>>> Please explain. How does that express DRP but prefered master?
>>>>>>
>>>>>> Sorry but I'm not sure what you mean here. If the port is capable of
>>>>>> being used as dual role port (DRP in the supported_data_roles file),
>>>>>> that is the only case where you can select the role with this file. So
>>>>>> I would imagine that in your case you want to make the port act as
>>>>>> DFP only, right? But if the port is capable of acting only as UFP, you
>>>>>> are stuck with that role.
>>>>>
>>>>> How do I trigger that Try.SRC is to be used on a port?
>>>>>
>>>>
>>>> This would be part of the USB PD protocol, ie probably outside the scope
>>>> of the class code. In my implementation, I enable Try.SRC or Try.SNK based
>>>> on the platform's preferred role.
>>>
>>> Hi,
>>>
>>> from a purely formal point of view that makes sense.
>>>
>>> >From a usability viewpoint I'd ideally want all controls
>>> for role at one place. And possibly the controls for modes
>>> at the same place.
>>>
>>> I think part of the problem here is that we lack a statement
>>> of mission. What are these controls for?
>>> Merely for controlling modes and providing information
>>> about modes? And to use neutral terms only for the "master"
>>> side or both sides?
>>>
>>
>> Good question. I originally added a sysfs attribute 'preferred-mode' to
>> my code, but then concluded that this is supposed to be provided
>> by the platform and added it as platform data instead, with (currently)
>> no means to report it to user space.
>
> Mode or role? I would say that the choice of alternate modes belongs to

s/preferred mode/preferred role/g

> user space. THere's no point in giving a preference to the kernel.
> Role is different. Try.SRC is part of the standard (and Try.SNK has been
> added). It needs to be in kernel space.
>
> Now, if you say that this API is for selecting modes only, then I say it
> lacks support for cable resets and notifications thereof. Yes, that is a
> PD feature, but that doesn't help us. It changes the mode.
>
>> Heikki's current code doesn't really match the semantics of a 'preferred'
>> mode, at least not as I read it. In my understanding, 'preferred mode'
>> means "this is a DRP port which prefers to be a source/sink". In Heikki's
>> code, one can fix the mode to source or sink, but that doesn't support
>> situations such as "this port prefers to be a source, but is currently
>> a sink because the link partner happens to be a charger or refuses to act
>> as sink for some other reason".
>
> Yes. That is why we need a mission statement. We may be talking
> a rice cooker not preparing tea here.
>
>> Given that, my working assumption is that preferred mode handling is supposed
>> to be outside the scope of the infrastructure. I am happy to be corrected,
>> though.
>>
>> On a side note, are you working on a USB-PD implementation as well ?
>
> No, one of my task is to to make use of USB PD (and alternate modes)
> in a distribution.
>
> 	Regards
> 		Oliver
>
>
>

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [RFC PATCHv2] usb: USB Type-C Connector Class
  2016-05-23 13:27               ` Guenter Roeck
@ 2016-05-23 13:58                 ` Oliver Neukum
  2016-05-23 14:43                   ` Guenter Roeck
  0 siblings, 1 reply; 98+ messages in thread
From: Oliver Neukum @ 2016-05-23 13:58 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Andy Shevchenko, Rajaram R, Felipe Balbi, Heikki Krogerus,
	Mathias Nyman, Greg KH, linux-kernel, linux-usb

On Mon, 2016-05-23 at 06:27 -0700, Guenter Roeck wrote:
> >> Good question. I originally added a sysfs attribute
> 'preferred-mode' to
> >> my code, but then concluded that this is supposed to be provided
> >> by the platform and added it as platform data instead, with
> (currently)
> >> no means to report it to user space.
> >
> > Mode or role? I would say that the choice of alternate modes belongs
> to
> 
> s/preferred mode/preferred role/g

Now I am confused. Are you saying that the choice of Alternate Mode does
not belong into user space?

	Regards
		Oliver

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [RFC PATCHv2] usb: USB Type-C Connector Class
  2016-05-23 13:58                 ` Oliver Neukum
@ 2016-05-23 14:43                   ` Guenter Roeck
  2016-05-23 15:55                     ` Oliver Neukum
  0 siblings, 1 reply; 98+ messages in thread
From: Guenter Roeck @ 2016-05-23 14:43 UTC (permalink / raw)
  To: Oliver Neukum
  Cc: Andy Shevchenko, Rajaram R, Felipe Balbi, Heikki Krogerus,
	Mathias Nyman, Greg KH, linux-kernel, linux-usb

On 05/23/2016 06:58 AM, Oliver Neukum wrote:
> On Mon, 2016-05-23 at 06:27 -0700, Guenter Roeck wrote:
>>>> Good question. I originally added a sysfs attribute
>> 'preferred-mode' to
>>>> my code, but then concluded that this is supposed to be provided
>>>> by the platform and added it as platform data instead, with
>> (currently)
>>>> no means to report it to user space.
>>>
>>> Mode or role? I would say that the choice of alternate modes belongs
>> to
>>
>> s/preferred mode/preferred role/g
>
> Now I am confused. Are you saying that the choice of Alternate Mode does
> not belong into user space?
>

No; sorry for the confusion. The above was meant to apply to my use
of "preferred mode", not yours. I was trying to say that the choice of
preferred roles (which determines if Try.SRC or Try.SNK is enabled)
should belong primarily into the kernel, to be determined by the platform
(presumably via ACPI, devicetree data, or platform data). If it should
be possible to override it by user space is a different question. That
might be useful, at least for testing. If so, does such an override
belong into the class or into the PD driver ? Good question. I am fine
either way.

I don't really have a strong opinion about alternate mode selection. I would
think that there should be a kernel (platform) default, possibly determined
by the alternate mode itself, but I also think that it should be selectable
by user space. Question is if that should be done through the alternate mode
driver or through the class (example: alternate modes used for firmware
upgrades and other device specific functionality). I don't really have
an answer for that at this point. I'll probably have a better idea after
I implemented the alternate mode driver for Google devices.

Again, sorry for creating confusion between preferred role and preferred
(alternate) mode selection.

Thanks,
Guenter

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [RFC PATCHv2] usb: USB Type-C Connector Class
  2016-05-23 14:43                   ` Guenter Roeck
@ 2016-05-23 15:55                     ` Oliver Neukum
  2016-05-23 16:52                       ` Guenter Roeck
  0 siblings, 1 reply; 98+ messages in thread
From: Oliver Neukum @ 2016-05-23 15:55 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Andy Shevchenko, Rajaram R, Felipe Balbi, Heikki Krogerus,
	Mathias Nyman, Greg KH, linux-kernel, linux-usb

On Mon, 2016-05-23 at 07:43 -0700, Guenter Roeck wrote:
> On 05/23/2016 06:58 AM, Oliver Neukum wrote:

> > Now I am confused. Are you saying that the choice of Alternate Mode does
> > not belong into user space?
> >
> 
> No; sorry for the confusion. The above was meant to apply to my use
> of "preferred mode", not yours. I was trying to say that the choice of
> preferred roles (which determines if Try.SRC or Try.SNK is enabled)
> should belong primarily into the kernel, to be determined by the platform
> (presumably via ACPI, devicetree data, or platform data). If it should

Why on earth? That is most clearly a policy decision.

> be possible to override it by user space is a different question. That
> might be useful, at least for testing. If so, does such an override
> belong into the class or into the PD driver ? Good question. I am fine
> either way.

Well, if platform data has a default, I suppose we ought to use it.

> I don't really have a strong opinion about alternate mode selection. I would
> think that there should be a kernel (platform) default, possibly determined
> by the alternate mode itself, but I also think that it should be selectable
> by user space. Question is if that should be done through the alternate mode
> driver or through the class (example: alternate modes used for firmware

I would say that the ought to be a driver for type C which controls
alternate modes and roles.

	Regards
		Oliver

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [RFC PATCHv2] usb: USB Type-C Connector Class
  2016-05-23 15:55                     ` Oliver Neukum
@ 2016-05-23 16:52                       ` Guenter Roeck
  2016-05-24 10:08                         ` Heikki Krogerus
  0 siblings, 1 reply; 98+ messages in thread
From: Guenter Roeck @ 2016-05-23 16:52 UTC (permalink / raw)
  To: Oliver Neukum
  Cc: Andy Shevchenko, Rajaram R, Felipe Balbi, Heikki Krogerus,
	Mathias Nyman, Greg KH, linux-kernel, linux-usb

On Mon, May 23, 2016 at 05:55:04PM +0200, Oliver Neukum wrote:
> On Mon, 2016-05-23 at 07:43 -0700, Guenter Roeck wrote:
> > On 05/23/2016 06:58 AM, Oliver Neukum wrote:
> 
> > > Now I am confused. Are you saying that the choice of Alternate Mode does
> > > not belong into user space?
> > >
> > 
> > No; sorry for the confusion. The above was meant to apply to my use
> > of "preferred mode", not yours. I was trying to say that the choice of
> > preferred roles (which determines if Try.SRC or Try.SNK is enabled)
> > should belong primarily into the kernel, to be determined by the platform
> > (presumably via ACPI, devicetree data, or platform data). If it should
> 
> Why on earth? That is most clearly a policy decision.
> 

The question is not that much if it is policy (it is), but if the policy
should be driven by the platform or by user space. I think there needs
to be at least a default driven by the platform. As already mentioned,
I am ok with a means to override this platform default from user space.
But if user space doesn't say, there still needs to be a default.

Thanks,
Guenter

> > be possible to override it by user space is a different question. That
> > might be useful, at least for testing. If so, does such an override
> > belong into the class or into the PD driver ? Good question. I am fine
> > either way.
> 
> Well, if platform data has a default, I suppose we ought to use it.
> 
> > I don't really have a strong opinion about alternate mode selection. I would
> > think that there should be a kernel (platform) default, possibly determined
> > by the alternate mode itself, but I also think that it should be selectable
> > by user space. Question is if that should be done through the alternate mode
> > driver or through the class (example: alternate modes used for firmware
> 
> I would say that the ought to be a driver for type C which controls
> alternate modes and roles.
> 
> 	Regards
> 		Oliver
> 
> 

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [RFC PATCHv2] usb: USB Type-C Connector Class
  2016-05-23 11:25     ` Oliver Neukum
@ 2016-05-23 17:09       ` Guenter Roeck
  2016-05-24  9:06         ` Oliver Neukum
  2016-05-24  9:32       ` Heikki Krogerus
  1 sibling, 1 reply; 98+ messages in thread
From: Guenter Roeck @ 2016-05-23 17:09 UTC (permalink / raw)
  To: Oliver Neukum
  Cc: Heikki Krogerus, Andy Shevchenko, Rajaram R, Felipe Balbi,
	Mathias Nyman, Greg KH, linux-kernel, linux-usb

On Mon, May 23, 2016 at 01:25:19PM +0200, Oliver Neukum wrote:
> On Mon, 2016-05-23 at 12:57 +0300, Heikki Krogerus wrote:
> > Hi Oliver,
> > 
> > On Fri, May 20, 2016 at 04:19:59PM +0200, Oliver Neukum wrote:
> > > On Thu, 2016-05-19 at 15:44 +0300, Heikki Krogerus wrote:
> > > > Like I've told some of you guys, I'm trying to implement a bus for
> > > > the Alternate Modes, but I'm still nowhere near finished with that
> > > > one, so let's just get the class ready now. The altmode bus should in
> > > > any case not affect the userspace interface proposed in this patch.
> > > 
> > > Is this strictly divorced from USB PD?
> > 
> > The bus can not be tied to the USB PD stack we will have in the
> > kernel completely, or there is no change of using it with things like
> > UCSI. It's going to be difficult to achieve that in any case as we
> > simply won't be able to send and rescieve the VDMs with things like
> > UCSI, but let's see.
> > 
> > > How do you trigger a cable reset or a USB PD reset?
> > 
> > There needs to be an API, but I'm sure that's not going to be a
> > problem. The bus and the altmode specific drivers will reside inside
> > kernel.
> 
> Absolutely. But at some point we need to settle on an API.
> If I am to tell you whether your proposed API leaves out
> something that needs to be covered, I need to know what
> is to go into the other APIs.
> 
> A reset is a generic function, so it does not belong to specific
> drivers.
> 
A would expect the driver to execute the reset.

Maybe the question should be phrased differently: Even USCI (which
doesn't provide for everything) has commands to reset the policy
manager and to reset the connector. The class should provide a means
to execute those commands.

> > But I'm getting the sense that you are thinking about having some
> > responsibility of USB PD in userspace. Please correct me if I'm wrong.
> 
> Gods help us all if we are ready to do that.
> It would fail.
> Yet I think the idea that PD and Alternate Modes can be cleanly
> divorced is wrong. The selection of Alternate Modes is done by
> USB PD messages. We can encapsulate that, but we cannot leave it out,
> especially in the area of resets.
> 
> > I don't think it will be possible. I think the role of userspace can
> > only be the source for high level requests via this interface, like
> > enter/exit mode and swap role, and receiving the status and details of
> > the ports, but any knowledge about the requirements regarding those
> > steps belongs to the kernel. This includes also the knowledge about
> 
> Yes.
> 
> > stuff like mode dependencies, for example if cable plug has to be in a
> > certain mode in order for the partner to be able to enter some
> > specific mode, etc.
> 
> Yes.
> 
> So for Alternate Modes we need on a high level the following features
> 
> 1. discovery of available Alternate Modes
> 2. selection of an Alternate Mode
> 3. notification about entering an Alternate Mode
> 4. triggering a reset
> 5. notification about resets
> 
> 6. discovery about the current role
> 7. switching roles
> 8. setting preferred roles (Try.SRC and Try.SNK)
> 

Isn't reset and role handling orthogonal to alternate mode functionality ?
Both will still be needed even if alternate mode support is not implemented
at all.

> You covered 1. and 2.
> 3. can be covered by specific drivers
> 4. and 5. are not covered (and it makes no sense to tie it
> to specific drivers)
> 
> 6. and 7. is covered
> 8. is not
> 
> And 8. needs to be covered. It affects who selects the Alternate Mode.

Doesn't the actual role determine that ? A device which prefers to be
a DFP might still end up as UFP.

> You cannot tie it to USB and it doesn't fit with pure PD stuff.
> 
> I like your API as it is now. But it is incomplete.
> 

Same here.

Thanks,
Guenter

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [RFC PATCHv2] usb: USB Type-C Connector Class
  2016-05-23 17:09       ` Guenter Roeck
@ 2016-05-24  9:06         ` Oliver Neukum
  0 siblings, 0 replies; 98+ messages in thread
From: Oliver Neukum @ 2016-05-24  9:06 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Andy Shevchenko, Rajaram R, Felipe Balbi, Heikki Krogerus,
	Mathias Nyman, Greg KH, linux-kernel, linux-usb

On Mon, 2016-05-23 at 10:09 -0700, Guenter Roeck wrote:
> On Mon, May 23, 2016 at 01:25:19PM +0200, Oliver Neukum wrote:
> > On Mon, 2016-05-23 at 12:57 +0300, Heikki Krogerus wrote:
> >
> > A reset is a generic function, so it does not belong to specific
> > drivers.
> > 
> A would expect the driver to execute the reset.
> 
> Maybe the question should be phrased differently: Even USCI (which
> doesn't provide for everything) has commands to reset the policy
> manager and to reset the connector. The class should provide a means
> to execute those commands.

Yes.

> > So for Alternate Modes we need on a high level the following features
> > 
> > 1. discovery of available Alternate Modes
> > 2. selection of an Alternate Mode
> > 3. notification about entering an Alternate Mode
> > 4. triggering a reset
> > 5. notification about resets
> > 
> > 6. discovery about the current role
> > 7. switching roles
> > 8. setting preferred roles (Try.SRC and Try.SNK)
> > 
> 
> Isn't reset and role handling orthogonal to alternate mode functionality ?
> Both will still be needed even if alternate mode support is not implemented
> at all.

In part. A reset can cause the Alternate Mode to be left unexpectedly
and unintentionally.
So how many APIs do we want?
Three:

- Alternate Modes
- USB PD
- type C for roles and reset

Or another number?

> > I like your API as it is now. But it is incomplete.
> > 
> 
> Same here.

So what is to be done?

	Regards
		Oliver

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [RFC PATCHv2] usb: USB Type-C Connector Class
  2016-05-23 11:25     ` Oliver Neukum
  2016-05-23 17:09       ` Guenter Roeck
@ 2016-05-24  9:32       ` Heikki Krogerus
  1 sibling, 0 replies; 98+ messages in thread
From: Heikki Krogerus @ 2016-05-24  9:32 UTC (permalink / raw)
  To: Oliver Neukum
  Cc: Andy Shevchenko, Rajaram R, Felipe Balbi, Mathias Nyman, Greg KH,
	Guenter Roeck, linux-kernel, linux-usb

On Mon, May 23, 2016 at 01:25:19PM +0200, Oliver Neukum wrote:
> So for Alternate Modes we need on a high level the following features
> 
> 1. discovery of available Alternate Modes
> 2. selection of an Alternate Mode
> 3. notification about entering an Alternate Mode
> 4. triggering a reset
> 5. notification about resets
> 
> 6. discovery about the current role
> 7. switching roles
> 8. setting preferred roles (Try.SRC and Try.SNK)
> 
> You covered 1. and 2.
> 3. can be covered by specific drivers
> 4. and 5. are not covered (and it makes no sense to tie it
> to specific drivers)
> 
> 6. and 7. is covered
> 8. is not
> 
> And 8. needs to be covered. It affects who selects the Alternate Mode.
> You cannot tie it to USB and it doesn't fit with pure PD stuff.
> 
> I like your API as it is now. But it is incomplete.

OK, Got it.


Thanks Oliver,

-- 
heikki

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [RFC PATCHv2] usb: USB Type-C Connector Class
  2016-05-23 16:52                       ` Guenter Roeck
@ 2016-05-24 10:08                         ` Heikki Krogerus
  2016-05-24 10:18                           ` Oliver Neukum
  0 siblings, 1 reply; 98+ messages in thread
From: Heikki Krogerus @ 2016-05-24 10:08 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Oliver Neukum, Andy Shevchenko, Rajaram R, Felipe Balbi,
	Mathias Nyman, Greg KH, linux-kernel, linux-usb

Hi Guenter,

On Mon, May 23, 2016 at 09:52:12AM -0700, Guenter Roeck wrote:
> On Mon, May 23, 2016 at 05:55:04PM +0200, Oliver Neukum wrote:
> > On Mon, 2016-05-23 at 07:43 -0700, Guenter Roeck wrote:
> > > On 05/23/2016 06:58 AM, Oliver Neukum wrote:
> > 
> > > > Now I am confused. Are you saying that the choice of Alternate Mode does
> > > > not belong into user space?
> > > >
> > > 
> > > No; sorry for the confusion. The above was meant to apply to my use
> > > of "preferred mode", not yours. I was trying to say that the choice of
> > > preferred roles (which determines if Try.SRC or Try.SNK is enabled)
> > > should belong primarily into the kernel, to be determined by the platform
> > > (presumably via ACPI, devicetree data, or platform data). If it should
> > 
> > Why on earth? That is most clearly a policy decision.
> > 
> 
> The question is not that much if it is policy (it is), but if the policy
> should be driven by the platform or by user space. I think there needs
> to be at least a default driven by the platform. As already mentioned,
> I am ok with a means to override this platform default from user space.
> But if user space doesn't say, there still needs to be a default.

I don't completely agree with that. The platform should not, and
actually in most cases with ACPI AFAIK, will not provide any
"preferences" to the OS about anything. The platform should only
provide the OS the physical capabilities and nothing else. So if for
example the platform is capable of acting as only source with a Type-C
port, that is what it needs to tell to the OS so possibly the PHY can
be programmed accordingly, etc.

So IMO, just like with any decision related to what the system will
ultimately be used for, decision about the preferred role really
belongs to the userspace.


Thanks,

-- 
heikki

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [RFC PATCHv2] usb: USB Type-C Connector Class
  2016-05-24 10:08                         ` Heikki Krogerus
@ 2016-05-24 10:18                           ` Oliver Neukum
  2016-05-24 11:04                             ` Heikki Krogerus
  0 siblings, 1 reply; 98+ messages in thread
From: Oliver Neukum @ 2016-05-24 10:18 UTC (permalink / raw)
  To: Heikki Krogerus
  Cc: Guenter Roeck, Andy Shevchenko, Rajaram R, Felipe Balbi,
	Mathias Nyman, Greg KH, linux-kernel, linux-usb

On Tue, 2016-05-24 at 13:08 +0300, Heikki Krogerus wrote:
> Hi Guenter,
> 
> On Mon, May 23, 2016 at 09:52:12AM -0700, Guenter Roeck wrote:
> > On Mon, May 23, 2016 at 05:55:04PM +0200, Oliver Neukum wrote:
> > > On Mon, 2016-05-23 at 07:43 -0700, Guenter Roeck wrote:
> > > > On 05/23/2016 06:58 AM, Oliver Neukum wrote:
> > > 
> > > > > Now I am confused. Are you saying that the choice of Alternate Mode does
> > > > > not belong into user space?
> > > > >
> > > > 
> > > > No; sorry for the confusion. The above was meant to apply to my use
> > > > of "preferred mode", not yours. I was trying to say that the choice of
> > > > preferred roles (which determines if Try.SRC or Try.SNK is enabled)
> > > > should belong primarily into the kernel, to be determined by the platform
> > > > (presumably via ACPI, devicetree data, or platform data). If it should
> > > 
> > > Why on earth? That is most clearly a policy decision.
> > > 
> > 
> > The question is not that much if it is policy (it is), but if the policy
> > should be driven by the platform or by user space. I think there needs
> > to be at least a default driven by the platform. As already mentioned,
> > I am ok with a means to override this platform default from user space.
> > But if user space doesn't say, there still needs to be a default.
> 
> I don't completely agree with that. The platform should not, and
> actually in most cases with ACPI AFAIK, will not provide any
> "preferences" to the OS about anything. The platform should only
> provide the OS the physical capabilities and nothing else. So if for
> example the platform is capable of acting as only source with a Type-C
> port, that is what it needs to tell to the OS so possibly the PHY can
> be programmed accordingly, etc.

May I suggest that the point is moot as long as we agree that user space
needs to be able to set a policy? The OS cannot ignore the port before
user space tells it what to do. So a default will be needed.

The OS must act conservatively, which means it cannot deactivate
hardware. So if a port can do DRP, that must be the default.
I would go so far that I would suggest that we add a module parameter
for Try.SRC and Try.SNK to avoid trouble during boot.

> So IMO, just like with any decision related to what the system will
> ultimately be used for, decision about the preferred role really
> belongs to the userspace.

Yes, but ought the APIs for role, mode and PD be separate or not.
Sorry to sound like a broken record, but you need to provide some
higher level planning here.

	Regards
		Oliver

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [RFC PATCHv2] usb: USB Type-C Connector Class
  2016-05-24 10:18                           ` Oliver Neukum
@ 2016-05-24 11:04                             ` Heikki Krogerus
  0 siblings, 0 replies; 98+ messages in thread
From: Heikki Krogerus @ 2016-05-24 11:04 UTC (permalink / raw)
  To: Oliver Neukum
  Cc: Guenter Roeck, Andy Shevchenko, Rajaram R, Felipe Balbi,
	Mathias Nyman, Greg KH, linux-kernel, linux-usb

On Tue, May 24, 2016 at 12:18:38PM +0200, Oliver Neukum wrote:
> On Tue, 2016-05-24 at 13:08 +0300, Heikki Krogerus wrote:
> > Hi Guenter,
> > 
> > On Mon, May 23, 2016 at 09:52:12AM -0700, Guenter Roeck wrote:
> > > On Mon, May 23, 2016 at 05:55:04PM +0200, Oliver Neukum wrote:
> > > > On Mon, 2016-05-23 at 07:43 -0700, Guenter Roeck wrote:
> > > > > On 05/23/2016 06:58 AM, Oliver Neukum wrote:
> > > > 
> > > > > > Now I am confused. Are you saying that the choice of Alternate Mode does
> > > > > > not belong into user space?
> > > > > >
> > > > > 
> > > > > No; sorry for the confusion. The above was meant to apply to my use
> > > > > of "preferred mode", not yours. I was trying to say that the choice of
> > > > > preferred roles (which determines if Try.SRC or Try.SNK is enabled)
> > > > > should belong primarily into the kernel, to be determined by the platform
> > > > > (presumably via ACPI, devicetree data, or platform data). If it should
> > > > 
> > > > Why on earth? That is most clearly a policy decision.
> > > > 
> > > 
> > > The question is not that much if it is policy (it is), but if the policy
> > > should be driven by the platform or by user space. I think there needs
> > > to be at least a default driven by the platform. As already mentioned,
> > > I am ok with a means to override this platform default from user space.
> > > But if user space doesn't say, there still needs to be a default.
> > 
> > I don't completely agree with that. The platform should not, and
> > actually in most cases with ACPI AFAIK, will not provide any
> > "preferences" to the OS about anything. The platform should only
> > provide the OS the physical capabilities and nothing else. So if for
> > example the platform is capable of acting as only source with a Type-C
> > port, that is what it needs to tell to the OS so possibly the PHY can
> > be programmed accordingly, etc.
> 
> May I suggest that the point is moot as long as we agree that user space
> needs to be able to set a policy? The OS cannot ignore the port before
> user space tells it what to do. So a default will be needed.
> 
> The OS must act conservatively, which means it cannot deactivate
> hardware. So if a port can do DRP, that must be the default.

So exactly my point.

> I would go so far that I would suggest that we add a module parameter
> for Try.SRC and Try.SNK to avoid trouble during boot.

I would be fine with that, but apparently module parameters are so 90s
:(

> > So IMO, just like with any decision related to what the system will
> > ultimately be used for, decision about the preferred role really
> > belongs to the userspace.
> 
> Yes, but ought the APIs for role, mode and PD be separate or not.
> Sorry to sound like a broken record, but you need to provide some
> higher level planning here.

I was kinda hoping that we could formulate the plan together in this
thread.


Thanks,

-- 
heikki

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [RFC PATCHv2] usb: USB Type-C Connector Class
  2016-05-19 12:44 [RFC PATCHv2] usb: USB Type-C Connector Class Heikki Krogerus
                   ` (3 preceding siblings ...)
  2016-05-20 14:19 ` Oliver Neukum
@ 2016-05-24 12:51 ` Oliver Neukum
  2016-05-25 11:28   ` Heikki Krogerus
  2016-05-24 13:42 ` Guenter Roeck
                   ` (7 subsequent siblings)
  12 siblings, 1 reply; 98+ messages in thread
From: Oliver Neukum @ 2016-05-24 12:51 UTC (permalink / raw)
  To: Heikki Krogerus
  Cc: Guenter Roeck, Andy Shevchenko, Rajaram R, Felipe Balbi,
	Mathias Nyman, Greg KH, linux-kernel, linux-usb

On Thu, 2016-05-19 at 15:44 +0300, Heikki Krogerus wrote:

Hi,

as this discussion seems to go in circles, I am starting anew
at the top.

> Like I've told some of you guys, I'm trying to implement a bus for
> the Alternate Modes, but I'm still nowhere near finished with that
> one, so let's just get the class ready now. The altmode bus should in
> any case not affect the userspace interface proposed in this patch.
> 
> As you can see, the Alternate Modes are handled completely differently
> compared to the original proposal. Every Alternate Mode will have
> their own device instance (which will be then later bound to an
> Alternate Mode specific driver once we have the bus), but also every
> partner, cable and cable plug will have their own device instances
> representing them.

The API works for a DFP. I fail to see how the UFP learns about entering
an alternate mode.
Secondly, support to trigger a reset is missing

> An other change is that the data role is now handled in two ways.
> The current_data_role file will represent static mode of the port, and
> it will use the names for the roles as they are defined in the spec:
> DFP, UFP and DRP. This file should be used if the port needs to be

Good, but support for Try.SRC and Try.SNK is missing.
An additional problem with that is that it needs to work
without user space during boot. So I think module parameters
to set the default are necessary.

> fixed to one specific role with DRP ports. So this approach will
> replace the suggestions for "preferred" data role we had. The
> current_usb_data_role will use values "host" and "device" and it will
> be used for data role swapping when already connected.
> 
> The tree of devices that will be populated when the cable is active
> and when the cable has controller on both plug, will look as
> following:
> 
> usbc0
> |- usbc0-cable
> |   |- usbc0-plug0
> |   |   |- usbc0-plug.svid:xxx
> |   |   |   |-mode0
> |   |   |   |   |- vdo
> |   |   |   |   |- desc
> |   |   |   |   |- active
> ...
> |   |- usbc0-plug1
> |   |   |-usbc0-partner
> |   |   |   |- usbc0-partner.svid:xxxx
> |   |   |   |	|-mode0
> |   |   |   |	|   |- vdo
> |   |   |   |	|   |- desc
> |   |   |   |	|   |- active
> |   |   |   |	|-mode1
> ...
> |   |   |- usbc0-plug1.svid:xxx
> |   |   |   |-mode0
> |   |   |   |   |- vdo
> ...
> 
> If there is no active cable, the partner will be directly attached to
> the port, but symlink to the partner is now always added to the port
> folder in any case. I'm not sure about this approach. There is a
> question about it in the code. Please check it.

This approach looks workable.
An the whole the approach looks good, but needs to be extended.

	Regards
		Oliver

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [RFC PATCHv2] usb: USB Type-C Connector Class
  2016-05-19 12:44 [RFC PATCHv2] usb: USB Type-C Connector Class Heikki Krogerus
                   ` (4 preceding siblings ...)
  2016-05-24 12:51 ` Oliver Neukum
@ 2016-05-24 13:42 ` Guenter Roeck
  2016-05-25 11:30   ` Heikki Krogerus
  2016-05-24 19:28 ` Guenter Roeck
                   ` (6 subsequent siblings)
  12 siblings, 1 reply; 98+ messages in thread
From: Guenter Roeck @ 2016-05-24 13:42 UTC (permalink / raw)
  To: Heikki Krogerus
  Cc: Greg KH, Mathias Nyman, Felipe Balbi, Oliver Neukum, Rajaram R,
	Andy Shevchenko, linux-kernel, linux-usb

On 05/19/2016 05:44 AM, Heikki Krogerus wrote:
> The purpose of this class is to provide unified interface for user
> space to get the status and basic information about USB Type-C
> Connectors in the system, control data role swapping, and when USB PD
> is available, also power role swapping and Alternate Modes.
>
> Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
> ---
>   drivers/usb/Kconfig         |   2 +
>   drivers/usb/Makefile        |   2 +
>   drivers/usb/type-c/Kconfig  |   7 +
>   drivers/usb/type-c/Makefile |   1 +
>   drivers/usb/type-c/typec.c  | 957 ++++++++++++++++++++++++++++++++++++++++++++
>   include/linux/usb/typec.h   | 230 +++++++++++
>   6 files changed, 1199 insertions(+)
>   create mode 100644 drivers/usb/type-c/Kconfig
>   create mode 100644 drivers/usb/type-c/Makefile
>   create mode 100644 drivers/usb/type-c/typec.c
>   create mode 100644 include/linux/usb/typec.h
>

Hi,

> +/*
> + * struct typec_capability - USB Type-C Port Capabilities
> + * @role: DFP (Host-only), UFP (Device-only) or DRP (Dual Role)
> + * @usb_pd: USB Power Delivery support
> + * @alt_modes: Alternate Modes the connector supports (null terminated)
> + * @audio_accessory: Audio Accessory Adapter Mode support
> + * @debug_accessory: Debug Accessory Mode support
> + * @fix_role: Set a fixed data role for DRP port
> + * @dr_swap: Data Role Swap support
> + * @pr_swap: Power Role Swap support
> + * @vconn_swap: VCONN Swap support
> + * @activate_mode: Enter/exit given Alternate Mode
> + *
> + * Static capabilities of a single USB Type-C port.
> + */
> +struct typec_capability {
> +	enum typec_data_role	role;
> +	unsigned int		usb_pd:1;
> +	struct typec_altmode	*alt_modes;
> +	unsigned int		audio_accessory:1;
> +	unsigned int		debug_accessory:1;
> +
> +	int			(*fix_role)(struct typec_port *,
> +					    enum typec_data_role);
> +
> +	int			(*dr_swap)(struct typec_port *);
> +	int			(*pr_swap)(struct typec_port *);
> +	int			(*vconn_swap)(struct typec_port *);
> +

The function parameter in those calls is all but useless to the caller.
It needs to store the typec_port returned from typec_register(), create a
list of ports, and then search through this list each time one of the
functions is called. This is quite expensive for no good reason.

Previously, with typec_port exported, the called code could use the stored
caps pointer to map to its internal data structures. This is no longer
possible.

I think it would be useful to provide a better means for the called function
to identify its context. Maybe provide a pointer to the private data in
the registration function and use it as parameter in the callback functions ?

Thanks,
Guenter

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [RFC PATCHv2] usb: USB Type-C Connector Class
  2016-05-19 12:44 [RFC PATCHv2] usb: USB Type-C Connector Class Heikki Krogerus
                   ` (5 preceding siblings ...)
  2016-05-24 13:42 ` Guenter Roeck
@ 2016-05-24 19:28 ` Guenter Roeck
  2016-05-25 11:51   ` Heikki Krogerus
  2016-05-25 18:35 ` [RFC PATCH] usb: typec: Various API updates and fixes Guenter Roeck
                   ` (5 subsequent siblings)
  12 siblings, 1 reply; 98+ messages in thread
From: Guenter Roeck @ 2016-05-24 19:28 UTC (permalink / raw)
  To: Heikki Krogerus
  Cc: Greg KH, Mathias Nyman, Felipe Balbi, Oliver Neukum, Rajaram R,
	Andy Shevchenko, linux-kernel, linux-usb

On Thu, May 19, 2016 at 03:44:54PM +0300, Heikki Krogerus wrote:
> The purpose of this class is to provide unified interface for user
> space to get the status and basic information about USB Type-C
> Connectors in the system, control data role swapping, and when USB PD
> is available, also power role swapping and Alternate Modes.
> 
> Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>

[ ... ]

> +
> +static void typec_remove_partner(struct typec_port *port)
> +{
> +	sysfs_remove_link(&port->dev.kobj, "partner");
> +	typec_unregister_altmodes(port->partner->alt_modes);

This only unregisters alternate modes registered through typec_add_partner(),
but not alternate modes registered separately. Or is the calling code expected
to set port->partner->alt_modes when calling typec_register_altmodes()
directly ?

[ ... ]

> +
> +void typec_unregister_altmodes(struct typec_altmode *alt_modes)
> +{
> +	struct typec_altmode *alt;
> +
This will crash if alt_modes is NULL, which will happen if 
partner->alt_modes is NULL at connection time. Semantically
this is different to typec_register_altmodes(), which does
have a NULL check.

Guenter

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [RFC PATCHv2] usb: USB Type-C Connector Class
  2016-05-24 12:51 ` Oliver Neukum
@ 2016-05-25 11:28   ` Heikki Krogerus
  2016-05-25 15:19     ` Guenter Roeck
  0 siblings, 1 reply; 98+ messages in thread
From: Heikki Krogerus @ 2016-05-25 11:28 UTC (permalink / raw)
  To: Oliver Neukum
  Cc: Guenter Roeck, Andy Shevchenko, Rajaram R, Felipe Balbi,
	Mathias Nyman, Greg KH, linux-kernel, linux-usb

Hi,

On Tue, May 24, 2016 at 02:51:40PM +0200, Oliver Neukum wrote:
> On Thu, 2016-05-19 at 15:44 +0300, Heikki Krogerus wrote:
> 
> Hi,
> 
> as this discussion seems to go in circles, I am starting anew
> at the top.
> 
> > Like I've told some of you guys, I'm trying to implement a bus for
> > the Alternate Modes, but I'm still nowhere near finished with that
> > one, so let's just get the class ready now. The altmode bus should in
> > any case not affect the userspace interface proposed in this patch.
> > 
> > As you can see, the Alternate Modes are handled completely differently
> > compared to the original proposal. Every Alternate Mode will have
> > their own device instance (which will be then later bound to an
> > Alternate Mode specific driver once we have the bus), but also every
> > partner, cable and cable plug will have their own device instances
> > representing them.
> 
> The API works for a DFP. I fail to see how the UFP learns about entering
> an alternate mode.
> Secondly, support to trigger a reset is missing

I'm fine with adding an attribute for port and cable resets if it's
something that is needed. So do you want to be able to execute hard
reset on a port?

But could you please explain the case(s) where you need to tricker a
reset.

> > An other change is that the data role is now handled in two ways.
> > The current_data_role file will represent static mode of the port, and
> > it will use the names for the roles as they are defined in the spec:
> > DFP, UFP and DRP. This file should be used if the port needs to be
> 
> Good, but support for Try.SRC and Try.SNK is missing.

OK, but what is Try.SNK? It's not in the specs?

> An additional problem with that is that it needs to work
> without user space during boot. So I think module parameters
> to set the default are necessary.

I don't have a problem with that, but what does Greg say?

> > fixed to one specific role with DRP ports. So this approach will
> > replace the suggestions for "preferred" data role we had. The
> > current_usb_data_role will use values "host" and "device" and it will
> > be used for data role swapping when already connected.
> > 
> > The tree of devices that will be populated when the cable is active
> > and when the cable has controller on both plug, will look as
> > following:
> > 
> > usbc0
> > |- usbc0-cable
> > |   |- usbc0-plug0
> > |   |   |- usbc0-plug.svid:xxx
> > |   |   |   |-mode0
> > |   |   |   |   |- vdo
> > |   |   |   |   |- desc
> > |   |   |   |   |- active
> > ...
> > |   |- usbc0-plug1
> > |   |   |-usbc0-partner
> > |   |   |   |- usbc0-partner.svid:xxxx
> > |   |   |   |	|-mode0
> > |   |   |   |	|   |- vdo
> > |   |   |   |	|   |- desc
> > |   |   |   |	|   |- active
> > |   |   |   |	|-mode1
> > ...
> > |   |   |- usbc0-plug1.svid:xxx
> > |   |   |   |-mode0
> > |   |   |   |   |- vdo
> > ...
> > 
> > If there is no active cable, the partner will be directly attached to
> > the port, but symlink to the partner is now always added to the port
> > folder in any case. I'm not sure about this approach. There is a
> > question about it in the code. Please check it.
> 
> This approach looks workable.
> An the whole the approach looks good, but needs to be extended.


Thanks,

-- 
heikki

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [RFC PATCHv2] usb: USB Type-C Connector Class
  2016-05-24 13:42 ` Guenter Roeck
@ 2016-05-25 11:30   ` Heikki Krogerus
  2016-05-25 13:12     ` Guenter Roeck
  0 siblings, 1 reply; 98+ messages in thread
From: Heikki Krogerus @ 2016-05-25 11:30 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Greg KH, Mathias Nyman, Felipe Balbi, Oliver Neukum, Rajaram R,
	Andy Shevchenko, linux-kernel, linux-usb

Hi,

On Tue, May 24, 2016 at 06:42:09AM -0700, Guenter Roeck wrote:
> > +struct typec_capability {
> > +	enum typec_data_role	role;
> > +	unsigned int		usb_pd:1;
> > +	struct typec_altmode	*alt_modes;
> > +	unsigned int		audio_accessory:1;
> > +	unsigned int		debug_accessory:1;
> > +
> > +	int			(*fix_role)(struct typec_port *,
> > +					    enum typec_data_role);
> > +
> > +	int			(*dr_swap)(struct typec_port *);
> > +	int			(*pr_swap)(struct typec_port *);
> > +	int			(*vconn_swap)(struct typec_port *);
> > +
> 
> The function parameter in those calls is all but useless to the caller.
> It needs to store the typec_port returned from typec_register(), create a
> list of ports, and then search through this list each time one of the
> functions is called. This is quite expensive for no good reason.
> 
> Previously, with typec_port exported, the called code could use the stored
> caps pointer to map to its internal data structures. This is no longer
> possible.

True, the API now is in practice broken.

> I think it would be useful to provide a better means for the called function
> to identify its context. Maybe provide a pointer to the private data in
> the registration function and use it as parameter in the callback functions ?

Sounds reasonable.


Thanks,

-- 
heikki

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [RFC PATCHv2] usb: USB Type-C Connector Class
  2016-05-24 19:28 ` Guenter Roeck
@ 2016-05-25 11:51   ` Heikki Krogerus
  2016-05-25 13:21     ` Guenter Roeck
  0 siblings, 1 reply; 98+ messages in thread
From: Heikki Krogerus @ 2016-05-25 11:51 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Greg KH, Mathias Nyman, Felipe Balbi, Oliver Neukum, Rajaram R,
	Andy Shevchenko, linux-kernel, linux-usb

On Tue, May 24, 2016 at 12:28:26PM -0700, Guenter Roeck wrote:
> On Thu, May 19, 2016 at 03:44:54PM +0300, Heikki Krogerus wrote:
> > The purpose of this class is to provide unified interface for user
> > space to get the status and basic information about USB Type-C
> > Connectors in the system, control data role swapping, and when USB PD
> > is available, also power role swapping and Alternate Modes.
> > 
> > Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
> 
> [ ... ]
> 
> > +
> > +static void typec_remove_partner(struct typec_port *port)
> > +{
> > +	sysfs_remove_link(&port->dev.kobj, "partner");
> > +	typec_unregister_altmodes(port->partner->alt_modes);
> 
> This only unregisters alternate modes registered through typec_add_partner(),
> but not alternate modes registered separately. Or is the calling code expected
> to set port->partner->alt_modes when calling typec_register_altmodes()
> directly ?

The altmodes for the partner are not meant to be registered
separately. With the partners and also cable plugs the class is in
control of registering and unregistering of the altmode devices after
typec_connect() is called.

The idea was that only the ports will register the alternate modes
they support separately, but I think we have to change that too. So I
don't think we'll export the typec_un/register_altmodes() at all.

We will have to prevent any drivers from being bound to the port
alternate mode devices when we add the alternate mode bus, and I had
some idea where by making the port drivers themselves in charge of
registering the port alternate modes, we could prevent it easily. But
it's probable easier to just handle those in the class driver as well.

> > +
> > +void typec_unregister_altmodes(struct typec_altmode *alt_modes)
> > +{
> > +	struct typec_altmode *alt;
> > +
> This will crash if alt_modes is NULL, which will happen if 
> partner->alt_modes is NULL at connection time. Semantically
> this is different to typec_register_altmodes(), which does
> have a NULL check.

Yes, need to fix that.


Thanks Guenter,

-- 
heikki

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [RFC PATCHv2] usb: USB Type-C Connector Class
  2016-05-25 11:30   ` Heikki Krogerus
@ 2016-05-25 13:12     ` Guenter Roeck
  0 siblings, 0 replies; 98+ messages in thread
From: Guenter Roeck @ 2016-05-25 13:12 UTC (permalink / raw)
  To: Heikki Krogerus
  Cc: Greg KH, Mathias Nyman, Felipe Balbi, Oliver Neukum, Rajaram R,
	Andy Shevchenko, linux-kernel, linux-usb

On 05/25/2016 04:30 AM, Heikki Krogerus wrote:
> Hi,
>
> On Tue, May 24, 2016 at 06:42:09AM -0700, Guenter Roeck wrote:
>>> +struct typec_capability {
>>> +	enum typec_data_role	role;
>>> +	unsigned int		usb_pd:1;
>>> +	struct typec_altmode	*alt_modes;
>>> +	unsigned int		audio_accessory:1;
>>> +	unsigned int		debug_accessory:1;
>>> +
>>> +	int			(*fix_role)(struct typec_port *,
>>> +					    enum typec_data_role);
>>> +
>>> +	int			(*dr_swap)(struct typec_port *);
>>> +	int			(*pr_swap)(struct typec_port *);
>>> +	int			(*vconn_swap)(struct typec_port *);
>>> +
>>
>> The function parameter in those calls is all but useless to the caller.
>> It needs to store the typec_port returned from typec_register(), create a
>> list of ports, and then search through this list each time one of the
>> functions is called. This is quite expensive for no good reason.
>>
>> Previously, with typec_port exported, the called code could use the stored
>> caps pointer to map to its internal data structures. This is no longer
>> possible.
>
> True, the API now is in practice broken.
>
>> I think it would be useful to provide a better means for the called function
>> to identify its context. Maybe provide a pointer to the private data in
>> the registration function and use it as parameter in the callback functions ?
>
> Sounds reasonable.
>

I'll send a follow-up patch hopefully later today which fixes all the problems
I have found so far.

Guenter

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [RFC PATCHv2] usb: USB Type-C Connector Class
  2016-05-25 11:51   ` Heikki Krogerus
@ 2016-05-25 13:21     ` Guenter Roeck
  2016-05-25 14:04       ` Heikki Krogerus
  0 siblings, 1 reply; 98+ messages in thread
From: Guenter Roeck @ 2016-05-25 13:21 UTC (permalink / raw)
  To: Heikki Krogerus
  Cc: Greg KH, Mathias Nyman, Felipe Balbi, Oliver Neukum, Rajaram R,
	Andy Shevchenko, linux-kernel, linux-usb

On 05/25/2016 04:51 AM, Heikki Krogerus wrote:
> On Tue, May 24, 2016 at 12:28:26PM -0700, Guenter Roeck wrote:
>> On Thu, May 19, 2016 at 03:44:54PM +0300, Heikki Krogerus wrote:
>>> The purpose of this class is to provide unified interface for user
>>> space to get the status and basic information about USB Type-C
>>> Connectors in the system, control data role swapping, and when USB PD
>>> is available, also power role swapping and Alternate Modes.
>>>
>>> Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
>>
>> [ ... ]
>>
>>> +
>>> +static void typec_remove_partner(struct typec_port *port)
>>> +{
>>> +	sysfs_remove_link(&port->dev.kobj, "partner");
>>> +	typec_unregister_altmodes(port->partner->alt_modes);
>>
>> This only unregisters alternate modes registered through typec_add_partner(),
>> but not alternate modes registered separately. Or is the calling code expected
>> to set port->partner->alt_modes when calling typec_register_altmodes()
>> directly ?
>
> The altmodes for the partner are not meant to be registered
> separately. With the partners and also cable plugs the class is in
> control of registering and unregistering of the altmode devices after
> typec_connect() is called.
>
> The idea was that only the ports will register the alternate modes
> they support separately, but I think we have to change that too. So I
> don't think we'll export the typec_un/register_altmodes() at all.
>
> We will have to prevent any drivers from being bound to the port
> alternate mode devices when we add the alternate mode bus, and I had
> some idea where by making the port drivers themselves in charge of
> registering the port alternate modes, we could prevent it easily. But
> it's probable easier to just handle those in the class driver as well.
>

Alternate mode discovery is an orthogonal process to the connection
state machine, and may take a while to complete. Are you saying
that the call to typec_connect() should be delayed until after
alternate mode discovery completes or times out ?

So far I call typec_connect() in SRC.Ready and SNK.Ready, and
typec_register_altmodes() after mode discovery is complete.
It is also orthogonal, meaning it is only called if and when alternate
mode discovery completes, and the alternate mode discovery state machine
is separate to the port state machine.

No problem for me to change that, just making sure that the registration
delay is understood and accepted.

Thanks,
Guenter

>>> +
>>> +void typec_unregister_altmodes(struct typec_altmode *alt_modes)
>>> +{
>>> +	struct typec_altmode *alt;
>>> +
>> This will crash if alt_modes is NULL, which will happen if
>> partner->alt_modes is NULL at connection time. Semantically
>> this is different to typec_register_altmodes(), which does
>> have a NULL check.
>
> Yes, need to fix that.
>
>
> Thanks Guenter,
>

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [RFC PATCHv2] usb: USB Type-C Connector Class
  2016-05-25 13:21     ` Guenter Roeck
@ 2016-05-25 14:04       ` Heikki Krogerus
  2016-05-25 14:20         ` Oliver Neukum
  0 siblings, 1 reply; 98+ messages in thread
From: Heikki Krogerus @ 2016-05-25 14:04 UTC (permalink / raw)
  To: Guenter Roeck, Oliver Neukum
  Cc: Greg KH, Mathias Nyman, Felipe Balbi, Rajaram R, Andy Shevchenko,
	linux-kernel, linux-usb

On Wed, May 25, 2016 at 06:21:54AM -0700, Guenter Roeck wrote:
> On 05/25/2016 04:51 AM, Heikki Krogerus wrote:
> > On Tue, May 24, 2016 at 12:28:26PM -0700, Guenter Roeck wrote:
> > > On Thu, May 19, 2016 at 03:44:54PM +0300, Heikki Krogerus wrote:
> > > > The purpose of this class is to provide unified interface for user
> > > > space to get the status and basic information about USB Type-C
> > > > Connectors in the system, control data role swapping, and when USB PD
> > > > is available, also power role swapping and Alternate Modes.
> > > > 
> > > > Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
> > > 
> > > [ ... ]
> > > 
> > > > +
> > > > +static void typec_remove_partner(struct typec_port *port)
> > > > +{
> > > > +	sysfs_remove_link(&port->dev.kobj, "partner");
> > > > +	typec_unregister_altmodes(port->partner->alt_modes);
> > > 
> > > This only unregisters alternate modes registered through typec_add_partner(),
> > > but not alternate modes registered separately. Or is the calling code expected
> > > to set port->partner->alt_modes when calling typec_register_altmodes()
> > > directly ?
> > 
> > The altmodes for the partner are not meant to be registered
> > separately. With the partners and also cable plugs the class is in
> > control of registering and unregistering of the altmode devices after
> > typec_connect() is called.
> > 
> > The idea was that only the ports will register the alternate modes
> > they support separately, but I think we have to change that too. So I
> > don't think we'll export the typec_un/register_altmodes() at all.
> > 
> > We will have to prevent any drivers from being bound to the port
> > alternate mode devices when we add the alternate mode bus, and I had
> > some idea where by making the port drivers themselves in charge of
> > registering the port alternate modes, we could prevent it easily. But
> > it's probable easier to just handle those in the class driver as well.
> > 
> 
> Alternate mode discovery is an orthogonal process to the connection
> state machine, and may take a while to complete. Are you saying
> that the call to typec_connect() should be delayed until after
> alternate mode discovery completes or times out ?
> 
> So far I call typec_connect() in SRC.Ready and SNK.Ready, and
> typec_register_altmodes() after mode discovery is complete.
> It is also orthogonal, meaning it is only called if and when alternate
> mode discovery completes, and the alternate mode discovery state machine
> is separate to the port state machine.
> 
> No problem for me to change that, just making sure that the registration
> delay is understood and accepted.

I'm not against leaving the responsibility of registering the alternate
modes to the drivers. I'm a little bit worried about relying then on
the drivers to also handle the unregistering accordingly, but I can
live with that. But we just shouldn't share the responsibility of
un/registering them between the class and the drivers, so the driver
should then handle the registration always.

Oliver, what do you think?


Thanks,

-- 
heikki

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [RFC PATCHv2] usb: USB Type-C Connector Class
  2016-05-25 14:04       ` Heikki Krogerus
@ 2016-05-25 14:20         ` Oliver Neukum
  2016-05-25 14:59           ` Guenter Roeck
  0 siblings, 1 reply; 98+ messages in thread
From: Oliver Neukum @ 2016-05-25 14:20 UTC (permalink / raw)
  To: Heikki Krogerus
  Cc: Guenter Roeck, Andy Shevchenko, Rajaram R, Felipe Balbi,
	Mathias Nyman, Greg KH, linux-kernel, linux-usb

On Wed, 2016-05-25 at 17:04 +0300, Heikki Krogerus wrote:

> I'm not against leaving the responsibility of registering the alternate
> modes to the drivers. I'm a little bit worried about relying then on
> the drivers to also handle the unregistering accordingly, but I can
> live with that. But we just shouldn't share the responsibility of
> un/registering them between the class and the drivers, so the driver
> should then handle the registration always.
> 
> Oliver, what do you think?

Either will do for me. Registration by the drivers is a bit better.
But it has to be the one or the other. Mixing is indeed bad.

	Regards
		Oliver

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [RFC PATCHv2] usb: USB Type-C Connector Class
  2016-05-25 14:20         ` Oliver Neukum
@ 2016-05-25 14:59           ` Guenter Roeck
  2016-05-27  7:29             ` Heikki Krogerus
  0 siblings, 1 reply; 98+ messages in thread
From: Guenter Roeck @ 2016-05-25 14:59 UTC (permalink / raw)
  To: Oliver Neukum
  Cc: Heikki Krogerus, Andy Shevchenko, Rajaram R, Felipe Balbi,
	Mathias Nyman, Greg KH, linux-kernel, linux-usb

On Wed, May 25, 2016 at 04:20:56PM +0200, Oliver Neukum wrote:
> On Wed, 2016-05-25 at 17:04 +0300, Heikki Krogerus wrote:
> 
> > I'm not against leaving the responsibility of registering the alternate
> > modes to the drivers. I'm a little bit worried about relying then on
> > the drivers to also handle the unregistering accordingly, but I can
> > live with that. But we just shouldn't share the responsibility of
> > un/registering them between the class and the drivers, so the driver
> > should then handle the registration always.
> > 
> > Oliver, what do you think?
> 
> Either will do for me. Registration by the drivers is a bit better.
> But it has to be the one or the other. Mixing is indeed bad.
> 
Same here. I don't have any problems handling unregistering
from the driver. I just have to keep track of the state and call
typec_unregister_altmodes() before calling typec_disconnect().

Having to wait for mode discovery to complete before calling
typec_connect() is much more complicated, at least with my current
code.

Guenter

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [RFC PATCHv2] usb: USB Type-C Connector Class
  2016-05-25 11:28   ` Heikki Krogerus
@ 2016-05-25 15:19     ` Guenter Roeck
  2016-05-27  7:30       ` Heikki Krogerus
  0 siblings, 1 reply; 98+ messages in thread
From: Guenter Roeck @ 2016-05-25 15:19 UTC (permalink / raw)
  To: Heikki Krogerus
  Cc: Oliver Neukum, Andy Shevchenko, Rajaram R, Felipe Balbi,
	Mathias Nyman, Greg KH, linux-kernel, linux-usb

On Wed, May 25, 2016 at 02:28:46PM +0300, Heikki Krogerus wrote:
> Hi,
> 
> On Tue, May 24, 2016 at 02:51:40PM +0200, Oliver Neukum wrote:
> > On Thu, 2016-05-19 at 15:44 +0300, Heikki Krogerus wrote:
> > 
> > Hi,
> > 
> > as this discussion seems to go in circles, I am starting anew
> > at the top.
> > 
> > > Like I've told some of you guys, I'm trying to implement a bus for
> > > the Alternate Modes, but I'm still nowhere near finished with that
> > > one, so let's just get the class ready now. The altmode bus should in
> > > any case not affect the userspace interface proposed in this patch.
> > > 
> > > As you can see, the Alternate Modes are handled completely differently
> > > compared to the original proposal. Every Alternate Mode will have
> > > their own device instance (which will be then later bound to an
> > > Alternate Mode specific driver once we have the bus), but also every
> > > partner, cable and cable plug will have their own device instances
> > > representing them.
> > 
> > The API works for a DFP. I fail to see how the UFP learns about entering
> > an alternate mode.
> > Secondly, support to trigger a reset is missing
> 
> I'm fine with adding an attribute for port and cable resets if it's
> something that is needed. So do you want to be able to execute hard
> reset on a port?
> 
> But could you please explain the case(s) where you need to tricker a
> reset.
> 
> > > An other change is that the data role is now handled in two ways.
> > > The current_data_role file will represent static mode of the port, and
> > > it will use the names for the roles as they are defined in the spec:
> > > DFP, UFP and DRP. This file should be used if the port needs to be
> > 
> > Good, but support for Try.SRC and Try.SNK is missing.
> 
> OK, but what is Try.SNK? It's not in the specs?
> 

It is not in the USB PD specification, but in "USB Type-C Specification
Release 1.2 - Cable and Connector Specification".

Section 4.5.2.2.11, "Try.SNK State", says

"Note: if both Try.SRC and Try.SNK mechanisms are implemented, only one
 shall be enabled by the port at any given time. Deciding which of these
 two mechanisms is enabled is product design-specific."

... which is why I suggested earlier that there should be a platform
parameter to enable one or the other.

Guenter

^ permalink raw reply	[flat|nested] 98+ messages in thread

* [RFC PATCH] usb: typec: Various API updates and fixes
  2016-05-19 12:44 [RFC PATCHv2] usb: USB Type-C Connector Class Heikki Krogerus
                   ` (6 preceding siblings ...)
  2016-05-24 19:28 ` Guenter Roeck
@ 2016-05-25 18:35 ` Guenter Roeck
  2016-05-27  7:55   ` Heikki Krogerus
  2016-05-30 13:19 ` [RFC PATCHv2] usb: USB Type-C Connector Class Heikki Krogerus
                   ` (4 subsequent siblings)
  12 siblings, 1 reply; 98+ messages in thread
From: Guenter Roeck @ 2016-05-25 18:35 UTC (permalink / raw)
  To: Heikki Krogerus
  Cc: Greg KH, Mathias Nyman, Felipe Balbi, Oliver Neukum, Rajaram R,
	Andy Shevchenko, linux-kernel, linux-usb

From: Guenter Roeck <groeck@chromium.org>

New API functions (calls into class code)
	typec_set_usb_role()
	typec_set_pwr_role()
	typec_set_vconn_role()
	typec_set_pwr_opmode()

Modified API functions (calls into class code):
	typec_register_port(dev, cap) ->
			typec_register_port(dev, cap, driver_data)

Modified callback functions:
	dr_swap(port) -> dr_set(port, driver_data, role);
	pr_swap(port) -> pr_set(port, driver_data, role);
	vconn_swap(port) -> vconn_set(port, driver_data, role);
	fix_role(port) -> fix_role(port, driver_data, role);
	activate_mode(...) -> activate_mode(..., driver_data, ...);

New sysfs attribute:
	current_vconn_role

Other:
- Extract role initialization to new function typec_init_roles()
- Call driver code unconditionally on role changes
- Add NULL check in typec_unregister_altmodes()
- If an alternate mode description pointer is NULL, display
  an empty string.

Signed-off-by: Guenter Roeck <groeck@chromium.org>
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
---
This patch applies on top of '[RFC PATCHv2] usb: USB Type-C Connector Class'
from Heikki Krogerus. It provided the changes I made to get the code
operational.

 drivers/usb/type-c/typec.c | 134 ++++++++++++++++++++++++++++++++++++---------
 include/linux/usb/typec.h  |  26 ++++++---
 2 files changed, 125 insertions(+), 35 deletions(-)

diff --git a/drivers/usb/type-c/typec.c b/drivers/usb/type-c/typec.c
index 8028b7df0951..6836e972b681 100644
--- a/drivers/usb/type-c/typec.c
+++ b/drivers/usb/type-c/typec.c
@@ -27,6 +27,8 @@ struct typec_port {
 	struct typec_partner	*partner;
 	struct typec_cable	*cable;
 
+	void			*driver_data;
+
 	unsigned int		connected:1;
 
 	int			n_altmode;
@@ -324,6 +326,20 @@ static void typec_remove_cable(struct typec_port *port)
 	device_unregister(&port->cable->dev);
 }
 
+static void typec_init_roles(struct typec_port *port)
+{
+	if (port->fixed_role == TYPEC_PORT_DFP) {
+		port->usb_role = TYPEC_HOST;
+		port->pwr_role = TYPEC_PWR_SOURCE;
+		port->vconn_role = TYPEC_PWR_SOURCE;
+	} else {
+		/* Device mode as default also with DRP ports */
+		port->usb_role = TYPEC_DEVICE;
+		port->pwr_role = TYPEC_PWR_SINK;
+		port->vconn_role = TYPEC_PWR_SINK;
+	}
+}
+
 /* -------------------------------- */
 
 int typec_connect(struct typec_port *port, struct typec_connection *con)
@@ -378,16 +394,7 @@ void typec_disconnect(struct typec_port *port)
 
 	port->pwr_opmode = TYPEC_PWR_MODE_USB;
 
-	if (port->fixed_role == TYPEC_PORT_DFP) {
-		port->usb_role = TYPEC_HOST;
-		port->pwr_role = TYPEC_PWR_SOURCE;
-		port->vconn_role = TYPEC_PWR_SOURCE;
-	} else {
-		/* Device mode as default also with DRP ports */
-		port->usb_role = TYPEC_DEVICE;
-		port->pwr_role = TYPEC_PWR_SINK;
-		port->vconn_role = TYPEC_PWR_SINK;
-	}
+	typec_init_roles(port);
 
 	kobject_uevent(&port->dev.kobj, KOBJ_CHANGE);
 }
@@ -405,6 +412,34 @@ struct typec_port *typec_dev2port(struct device *dev)
 }
 EXPORT_SYMBOL_GPL(typec_dev2port);
 
+/* --------------------------------------- */
+/* Driver callbacks to report role updates */
+
+void typec_set_usb_role(struct typec_port *port, enum typec_usb_role role)
+{
+	port->usb_role = role;
+}
+EXPORT_SYMBOL(typec_set_usb_role);
+
+void typec_set_pwr_role(struct typec_port *port, enum typec_pwr_role role)
+{
+	port->pwr_role = role;
+}
+EXPORT_SYMBOL(typec_set_pwr_role);
+
+void typec_set_vconn_role(struct typec_port *port, enum typec_pwr_role role)
+{
+	port->vconn_role = role;
+}
+EXPORT_SYMBOL(typec_set_vconn_role);
+
+void typec_set_pwr_opmode(struct typec_port *port,
+			  enum typec_pwr_opmode opmode)
+{
+	port->pwr_opmode = opmode;
+}
+EXPORT_SYMBOL(typec_set_pwr_opmode);
+
 /* -------------------------------- */
 /* Alternate Modes */
 
@@ -451,7 +486,7 @@ typec_altmode_desc_show(struct device *dev, struct device_attribute *attr,
 	struct typec_mode *mode = container_of(attr, struct typec_mode,
 					       desc_attr);
 
-	return sprintf(buf, "%s\n", mode->desc);
+	return sprintf(buf, "%s\n", mode->desc ? mode->desc : "");
 }
 
 static ssize_t
@@ -561,6 +596,9 @@ void typec_unregister_altmodes(struct typec_altmode *alt_modes)
 {
 	struct typec_altmode *alt;
 
+	if (!alt_modes)
+		return;
+
 	for (alt = alt_modes; alt->svid; alt++)
 		device_unregister(&alt->dev);
 }
@@ -581,7 +619,7 @@ current_usb_data_role_store(struct device *dev, struct device_attribute *attr,
 		return -EOPNOTSUPP;
 	}
 
-	if (!port->cap->dr_swap) {
+	if (!port->cap->dr_set) {
 		dev_warn(dev, "data role swapping not supported\n");
 		return -EOPNOTSUPP;
 	}
@@ -593,10 +631,7 @@ current_usb_data_role_store(struct device *dev, struct device_attribute *attr,
 	else
 		return -EINVAL;
 
-	if (port->usb_role == role || !port->partner)
-		return size;
-
-	ret = port->cap->dr_swap(port);
+	ret = port->cap->dr_set(port, port->driver_data, role);
 	if (ret)
 		return ret;
 
@@ -655,10 +690,7 @@ current_data_role_store(struct device *dev, struct device_attribute *attr,
 	else
 		return -EINVAL;
 
-	if (port->fixed_role == role)
-		return size;
-
-	ret = port->cap->fix_role(port, role);
+	ret = port->cap->fix_role(port, port->driver_data, role);
 	if (ret)
 		return ret;
 
@@ -688,7 +720,7 @@ static ssize_t current_power_role_store(struct device *dev,
 		return -EOPNOTSUPP;
 	}
 
-	if (!port->cap->pr_swap) {
+	if (!port->cap->pr_set) {
 		dev_warn(dev, "power role swapping not supported\n");
 		return -EOPNOTSUPP;
 	}
@@ -705,10 +737,7 @@ static ssize_t current_power_role_store(struct device *dev,
 	else
 		return -EINVAL;
 
-	if (port->pwr_role == role || !port->partner)
-		return size;
-
-	ret = port->cap->pr_swap(port);
+	ret = port->cap->pr_set(port, port->driver_data, role);
 	if (ret)
 		return ret;
 
@@ -762,6 +791,54 @@ static ssize_t power_operation_mode_show(struct device *dev,
 }
 static DEVICE_ATTR_RO(power_operation_mode);
 
+static ssize_t current_vconn_role_store(struct device *dev,
+					struct device_attribute *attr,
+					const char *buf, size_t size)
+{
+	struct typec_port *port = to_typec_port(dev);
+	enum typec_pwr_role role;
+	int ret;
+
+	if (!port->cap->usb_pd) {
+		dev_dbg(dev, "vconn swap only supported with USB PD\n");
+		return -EOPNOTSUPP;
+	}
+
+	if (!port->cap->vconn_set) {
+		dev_warn(dev, "vconn swapping not supported\n");
+		return -EOPNOTSUPP;
+	}
+
+	if (!strncmp(buf, "source", 6))
+		role = TYPEC_PWR_SOURCE;
+	else if (!strncmp(buf, "sink", 4))
+		role = TYPEC_PWR_SINK;
+	else
+		return -EINVAL;
+
+	ret = port->cap->vconn_set(port, port->driver_data, role);
+	if (ret)
+		return ret;
+
+	return size;
+}
+
+static ssize_t current_vconn_role_show(struct device *dev,
+				       struct device_attribute *attr, char *buf)
+{
+	struct typec_port *port = to_typec_port(dev);
+
+	switch (port->vconn_role) {
+	case TYPEC_PWR_SOURCE:
+		return sprintf(buf, "source\n");
+	case TYPEC_PWR_SINK:
+		return sprintf(buf, "sink\n");
+	default:
+		return sprintf(buf, "unknown\n");
+	};
+}
+static DEVICE_ATTR_RW(current_vconn_role);
+
 static ssize_t supports_audio_accessory_show(struct device *dev,
 					     struct device_attribute *attr,
 					     char *buf)
@@ -795,6 +872,7 @@ static DEVICE_ATTR_RO(supports_usb_power_delivery);
 static struct attribute *typec_attrs[] = {
 	&dev_attr_current_data_role.attr,
 	&dev_attr_current_power_role.attr,
+	&dev_attr_current_vconn_role.attr,
 	&dev_attr_current_usb_data_role.attr,
 	&dev_attr_power_operation_mode.attr,
 	&dev_attr_supported_data_roles.attr,
@@ -862,7 +940,8 @@ static struct device_type typec_port_dev_type = {
 };
 
 struct typec_port *typec_register_port(struct device *dev,
-				       struct typec_capability *cap)
+				       struct typec_capability *cap,
+				       void *driver_data)
 {
 	struct typec_port *port;
 	int ret;
@@ -880,6 +959,7 @@ struct typec_port *typec_register_port(struct device *dev,
 
 	port->id = id;
 	port->cap = cap;
+	port->driver_data = driver_data;
 	port->dev.type = &typec_port_dev_type;
 	port->dev.class = &typec_class;
 	port->dev.parent = dev;
@@ -888,6 +968,8 @@ struct typec_port *typec_register_port(struct device *dev,
 
 	port->fixed_role = port->cap->role;
 
+	typec_init_roles(port);
+
 	ret = device_register(&port->dev);
 	if (ret) {
 		ida_simple_remove(&typec_index_ida, id);
diff --git a/include/linux/usb/typec.h b/include/linux/usb/typec.h
index 86e5c867800b..d16a38de57ac 100644
--- a/include/linux/usb/typec.h
+++ b/include/linux/usb/typec.h
@@ -168,9 +168,9 @@ struct typec_partner {
  * @audio_accessory: Audio Accessory Adapter Mode support
  * @debug_accessory: Debug Accessory Mode support
  * @fix_role: Set a fixed data role for DRP port
- * @dr_swap: Data Role Swap support
- * @pr_swap: Power Role Swap support
- * @vconn_swap: VCONN Swap support
+ * @dr_set: Set Data Role
+ * @pr_set: Set Power Role
+ * @vconn_set: Set VCONN Role
  * @activate_mode: Enter/exit given Alternate Mode
  *
  * Static capabilities of a single USB Type-C port.
@@ -182,14 +182,14 @@ struct typec_capability {
 	unsigned int		audio_accessory:1;
 	unsigned int		debug_accessory:1;
 
-	int			(*fix_role)(struct typec_port *,
+	int			(*fix_role)(struct typec_port *, void *,
 					    enum typec_data_role);
 
-	int			(*dr_swap)(struct typec_port *);
-	int			(*pr_swap)(struct typec_port *);
-	int			(*vconn_swap)(struct typec_port *);
+	int			(*dr_set)(struct typec_port *, void *, enum typec_usb_role);
+	int			(*pr_set)(struct typec_port *, void *, enum typec_pwr_role);
+	int			(*vconn_set)(struct typec_port *, void *, enum typec_pwr_role);
 
-	int			(*activate_mode)(struct typec_altmode *,
+	int			(*activate_mode)(struct typec_altmode *, void *,
 						 int mode, int activate);
 };
 
@@ -217,7 +217,8 @@ struct typec_connection {
 };
 
 struct typec_port *typec_register_port(struct device *dev,
-				       struct typec_capability *cap);
+				       struct typec_capability *cap,
+				       void *driver_data);
 void typec_unregister_port(struct typec_port *port);
 
 int typec_connect(struct typec_port *port, struct typec_connection *con);
@@ -227,4 +228,11 @@ void typec_disconnect(struct typec_port *port);
 struct device *typec_port2dev(struct typec_port *port);
 struct typec_port *typec_dev2port(struct device *dev);
 
+/* Callbacks from driver */
+
+void typec_set_usb_role(struct typec_port *, enum typec_usb_role);
+void typec_set_pwr_role(struct typec_port *, enum typec_pwr_role);
+void typec_set_vconn_role(struct typec_port *, enum typec_pwr_role);
+void typec_set_pwr_opmode(struct typec_port *, enum typec_pwr_opmode);
+
 #endif /* __LINUX_USB_TYPEC_H */
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 98+ messages in thread

* Re: [RFC PATCHv2] usb: USB Type-C Connector Class
  2016-05-25 14:59           ` Guenter Roeck
@ 2016-05-27  7:29             ` Heikki Krogerus
  0 siblings, 0 replies; 98+ messages in thread
From: Heikki Krogerus @ 2016-05-27  7:29 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Oliver Neukum, Andy Shevchenko, Rajaram R, Felipe Balbi,
	Mathias Nyman, Greg KH, linux-kernel, linux-usb

On Wed, May 25, 2016 at 07:59:57AM -0700, Guenter Roeck wrote:
> On Wed, May 25, 2016 at 04:20:56PM +0200, Oliver Neukum wrote:
> > On Wed, 2016-05-25 at 17:04 +0300, Heikki Krogerus wrote:
> > 
> > > I'm not against leaving the responsibility of registering the alternate
> > > modes to the drivers. I'm a little bit worried about relying then on
> > > the drivers to also handle the unregistering accordingly, but I can
> > > live with that. But we just shouldn't share the responsibility of
> > > un/registering them between the class and the drivers, so the driver
> > > should then handle the registration always.
> > > 
> > > Oliver, what do you think?
> > 
> > Either will do for me. Registration by the drivers is a bit better.
> > But it has to be the one or the other. Mixing is indeed bad.
> > 
> Same here. I don't have any problems handling unregistering
> from the driver. I just have to keep track of the state and call
> typec_unregister_altmodes() before calling typec_disconnect().
> 
> Having to wait for mode discovery to complete before calling
> typec_connect() is much more complicated, at least with my current
> code.

OK, so we'll change this and make the driver take care of the
registration.


-- 
heikki

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [RFC PATCHv2] usb: USB Type-C Connector Class
  2016-05-25 15:19     ` Guenter Roeck
@ 2016-05-27  7:30       ` Heikki Krogerus
  0 siblings, 0 replies; 98+ messages in thread
From: Heikki Krogerus @ 2016-05-27  7:30 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Oliver Neukum, Andy Shevchenko, Rajaram R, Felipe Balbi,
	Mathias Nyman, Greg KH, linux-kernel, linux-usb

On Wed, May 25, 2016 at 08:19:47AM -0700, Guenter Roeck wrote:
> On Wed, May 25, 2016 at 02:28:46PM +0300, Heikki Krogerus wrote:
> > Hi,
> > 
> > On Tue, May 24, 2016 at 02:51:40PM +0200, Oliver Neukum wrote:
> > > On Thu, 2016-05-19 at 15:44 +0300, Heikki Krogerus wrote:
> > > 
> > > Hi,
> > > 
> > > as this discussion seems to go in circles, I am starting anew
> > > at the top.
> > > 
> > > > Like I've told some of you guys, I'm trying to implement a bus for
> > > > the Alternate Modes, but I'm still nowhere near finished with that
> > > > one, so let's just get the class ready now. The altmode bus should in
> > > > any case not affect the userspace interface proposed in this patch.
> > > > 
> > > > As you can see, the Alternate Modes are handled completely differently
> > > > compared to the original proposal. Every Alternate Mode will have
> > > > their own device instance (which will be then later bound to an
> > > > Alternate Mode specific driver once we have the bus), but also every
> > > > partner, cable and cable plug will have their own device instances
> > > > representing them.
> > > 
> > > The API works for a DFP. I fail to see how the UFP learns about entering
> > > an alternate mode.
> > > Secondly, support to trigger a reset is missing
> > 
> > I'm fine with adding an attribute for port and cable resets if it's
> > something that is needed. So do you want to be able to execute hard
> > reset on a port?
> > 
> > But could you please explain the case(s) where you need to tricker a
> > reset.
> > 
> > > > An other change is that the data role is now handled in two ways.
> > > > The current_data_role file will represent static mode of the port, and
> > > > it will use the names for the roles as they are defined in the spec:
> > > > DFP, UFP and DRP. This file should be used if the port needs to be
> > > 
> > > Good, but support for Try.SRC and Try.SNK is missing.
> > 
> > OK, but what is Try.SNK? It's not in the specs?
> > 
> 
> It is not in the USB PD specification, but in "USB Type-C Specification
> Release 1.2 - Cable and Connector Specification".
> 
> Section 4.5.2.2.11, "Try.SNK State", says
> 
> "Note: if both Try.SRC and Try.SNK mechanisms are implemented, only one
>  shall be enabled by the port at any given time. Deciding which of these
>  two mechanisms is enabled is product design-specific."
> 
> ... which is why I suggested earlier that there should be a platform
> parameter to enable one or the other.

Heh, I'm still living the year 2015 :). I've missed the Type-C 1.2
spec.


Thanks guys,

-- 
heikki

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [RFC PATCH] usb: typec: Various API updates and fixes
  2016-05-25 18:35 ` [RFC PATCH] usb: typec: Various API updates and fixes Guenter Roeck
@ 2016-05-27  7:55   ` Heikki Krogerus
  2016-05-27 14:06     ` Guenter Roeck
  0 siblings, 1 reply; 98+ messages in thread
From: Heikki Krogerus @ 2016-05-27  7:55 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Greg KH, Mathias Nyman, Felipe Balbi, Oliver Neukum, Rajaram R,
	Andy Shevchenko, linux-kernel, linux-usb

Hi,

On Wed, May 25, 2016 at 11:35:07AM -0700, Guenter Roeck wrote:
> From: Guenter Roeck <groeck@chromium.org>
> 
> New API functions (calls into class code)
> 	typec_set_usb_role()
> 	typec_set_pwr_role()
> 	typec_set_vconn_role()
> 	typec_set_pwr_opmode()
> 
> Modified API functions (calls into class code):
> 	typec_register_port(dev, cap) ->
> 			typec_register_port(dev, cap, driver_data)
> 
> Modified callback functions:
> 	dr_swap(port) -> dr_set(port, driver_data, role);
> 	pr_swap(port) -> pr_set(port, driver_data, role);
> 	vconn_swap(port) -> vconn_set(port, driver_data, role);
> 	fix_role(port) -> fix_role(port, driver_data, role);
> 	activate_mode(...) -> activate_mode(..., driver_data, ...);
> 
> New sysfs attribute:
> 	current_vconn_role
> 
> Other:
> - Extract role initialization to new function typec_init_roles()
> - Call driver code unconditionally on role changes
> - Add NULL check in typec_unregister_altmodes()
> - If an alternate mode description pointer is NULL, display
>   an empty string.
> 
> Signed-off-by: Guenter Roeck <groeck@chromium.org>
> Signed-off-by: Guenter Roeck <linux@roeck-us.net>
> ---
> This patch applies on top of '[RFC PATCHv2] usb: USB Type-C Connector Class'
> from Heikki Krogerus. It provided the changes I made to get the code
> operational.
> 
>  drivers/usb/type-c/typec.c | 134 ++++++++++++++++++++++++++++++++++++---------
>  include/linux/usb/typec.h  |  26 ++++++---
>  2 files changed, 125 insertions(+), 35 deletions(-)

Thanks Guenter. After a quick glance looks good to me.

I think I'll create a development branch to my github tree for this
class and add this on top of the original v2 patch as is. Just to have
some history for as long we develop this thing. Though I'm not sure
how useful it is in this case. I think we need to put this together
fast. I'm thinking we need to target v4.8 with this.

I'll merge this into any case to v3, and I'll send on Monday.


> diff --git a/drivers/usb/type-c/typec.c b/drivers/usb/type-c/typec.c
> index 8028b7df0951..6836e972b681 100644
> --- a/drivers/usb/type-c/typec.c
> +++ b/drivers/usb/type-c/typec.c
> @@ -27,6 +27,8 @@ struct typec_port {
>  	struct typec_partner	*partner;
>  	struct typec_cable	*cable;
>  
> +	void			*driver_data;
> +
>  	unsigned int		connected:1;
>  
>  	int			n_altmode;
> @@ -324,6 +326,20 @@ static void typec_remove_cable(struct typec_port *port)
>  	device_unregister(&port->cable->dev);
>  }
>  
> +static void typec_init_roles(struct typec_port *port)
> +{
> +	if (port->fixed_role == TYPEC_PORT_DFP) {
> +		port->usb_role = TYPEC_HOST;
> +		port->pwr_role = TYPEC_PWR_SOURCE;
> +		port->vconn_role = TYPEC_PWR_SOURCE;
> +	} else {
> +		/* Device mode as default also with DRP ports */
> +		port->usb_role = TYPEC_DEVICE;
> +		port->pwr_role = TYPEC_PWR_SINK;
> +		port->vconn_role = TYPEC_PWR_SINK;
> +	}
> +}
> +
>  /* -------------------------------- */
>  
>  int typec_connect(struct typec_port *port, struct typec_connection *con)
> @@ -378,16 +394,7 @@ void typec_disconnect(struct typec_port *port)
>  
>  	port->pwr_opmode = TYPEC_PWR_MODE_USB;
>  
> -	if (port->fixed_role == TYPEC_PORT_DFP) {
> -		port->usb_role = TYPEC_HOST;
> -		port->pwr_role = TYPEC_PWR_SOURCE;
> -		port->vconn_role = TYPEC_PWR_SOURCE;
> -	} else {
> -		/* Device mode as default also with DRP ports */
> -		port->usb_role = TYPEC_DEVICE;
> -		port->pwr_role = TYPEC_PWR_SINK;
> -		port->vconn_role = TYPEC_PWR_SINK;
> -	}
> +	typec_init_roles(port);
>  
>  	kobject_uevent(&port->dev.kobj, KOBJ_CHANGE);
>  }
> @@ -405,6 +412,34 @@ struct typec_port *typec_dev2port(struct device *dev)
>  }
>  EXPORT_SYMBOL_GPL(typec_dev2port);
>  
> +/* --------------------------------------- */
> +/* Driver callbacks to report role updates */
> +
> +void typec_set_usb_role(struct typec_port *port, enum typec_usb_role role)
> +{
> +	port->usb_role = role;
> +}
> +EXPORT_SYMBOL(typec_set_usb_role);
> +
> +void typec_set_pwr_role(struct typec_port *port, enum typec_pwr_role role)
> +{
> +	port->pwr_role = role;
> +}
> +EXPORT_SYMBOL(typec_set_pwr_role);
> +
> +void typec_set_vconn_role(struct typec_port *port, enum typec_pwr_role role)
> +{
> +	port->vconn_role = role;
> +}
> +EXPORT_SYMBOL(typec_set_vconn_role);
> +
> +void typec_set_pwr_opmode(struct typec_port *port,
> +			  enum typec_pwr_opmode opmode)
> +{
> +	port->pwr_opmode = opmode;
> +}
> +EXPORT_SYMBOL(typec_set_pwr_opmode);
> +
>  /* -------------------------------- */
>  /* Alternate Modes */
>  
> @@ -451,7 +486,7 @@ typec_altmode_desc_show(struct device *dev, struct device_attribute *attr,
>  	struct typec_mode *mode = container_of(attr, struct typec_mode,
>  					       desc_attr);
>  
> -	return sprintf(buf, "%s\n", mode->desc);
> +	return sprintf(buf, "%s\n", mode->desc ? mode->desc : "");
>  }
>  
>  static ssize_t
> @@ -561,6 +596,9 @@ void typec_unregister_altmodes(struct typec_altmode *alt_modes)
>  {
>  	struct typec_altmode *alt;
>  
> +	if (!alt_modes)
> +		return;
> +
>  	for (alt = alt_modes; alt->svid; alt++)
>  		device_unregister(&alt->dev);
>  }
> @@ -581,7 +619,7 @@ current_usb_data_role_store(struct device *dev, struct device_attribute *attr,
>  		return -EOPNOTSUPP;
>  	}
>  
> -	if (!port->cap->dr_swap) {
> +	if (!port->cap->dr_set) {
>  		dev_warn(dev, "data role swapping not supported\n");
>  		return -EOPNOTSUPP;
>  	}
> @@ -593,10 +631,7 @@ current_usb_data_role_store(struct device *dev, struct device_attribute *attr,
>  	else
>  		return -EINVAL;
>  
> -	if (port->usb_role == role || !port->partner)
> -		return size;
> -
> -	ret = port->cap->dr_swap(port);
> +	ret = port->cap->dr_set(port, port->driver_data, role);
>  	if (ret)
>  		return ret;
>  
> @@ -655,10 +690,7 @@ current_data_role_store(struct device *dev, struct device_attribute *attr,
>  	else
>  		return -EINVAL;
>  
> -	if (port->fixed_role == role)
> -		return size;
> -
> -	ret = port->cap->fix_role(port, role);
> +	ret = port->cap->fix_role(port, port->driver_data, role);
>  	if (ret)
>  		return ret;
>  
> @@ -688,7 +720,7 @@ static ssize_t current_power_role_store(struct device *dev,
>  		return -EOPNOTSUPP;
>  	}
>  
> -	if (!port->cap->pr_swap) {
> +	if (!port->cap->pr_set) {
>  		dev_warn(dev, "power role swapping not supported\n");
>  		return -EOPNOTSUPP;
>  	}
> @@ -705,10 +737,7 @@ static ssize_t current_power_role_store(struct device *dev,
>  	else
>  		return -EINVAL;
>  
> -	if (port->pwr_role == role || !port->partner)
> -		return size;
> -
> -	ret = port->cap->pr_swap(port);
> +	ret = port->cap->pr_set(port, port->driver_data, role);
>  	if (ret)
>  		return ret;
>  
> @@ -762,6 +791,54 @@ static ssize_t power_operation_mode_show(struct device *dev,
>  }
>  static DEVICE_ATTR_RO(power_operation_mode);
>  
> +static ssize_t current_vconn_role_store(struct device *dev,
> +					struct device_attribute *attr,
> +					const char *buf, size_t size)
> +{
> +	struct typec_port *port = to_typec_port(dev);
> +	enum typec_pwr_role role;
> +	int ret;
> +
> +	if (!port->cap->usb_pd) {
> +		dev_dbg(dev, "vconn swap only supported with USB PD\n");
> +		return -EOPNOTSUPP;
> +	}
> +
> +	if (!port->cap->vconn_set) {
> +		dev_warn(dev, "vconn swapping not supported\n");
> +		return -EOPNOTSUPP;
> +	}
> +
> +	if (!strncmp(buf, "source", 6))
> +		role = TYPEC_PWR_SOURCE;
> +	else if (!strncmp(buf, "sink", 4))
> +		role = TYPEC_PWR_SINK;
> +	else
> +		return -EINVAL;
> +
> +	ret = port->cap->vconn_set(port, port->driver_data, role);
> +	if (ret)
> +		return ret;
> +
> +	return size;
> +}
> +
> +static ssize_t current_vconn_role_show(struct device *dev,
> +				       struct device_attribute *attr, char *buf)
> +{
> +	struct typec_port *port = to_typec_port(dev);
> +
> +	switch (port->vconn_role) {
> +	case TYPEC_PWR_SOURCE:
> +		return sprintf(buf, "source\n");
> +	case TYPEC_PWR_SINK:
> +		return sprintf(buf, "sink\n");
> +	default:
> +		return sprintf(buf, "unknown\n");
> +	};
> +}
> +static DEVICE_ATTR_RW(current_vconn_role);
> +
>  static ssize_t supports_audio_accessory_show(struct device *dev,
>  					     struct device_attribute *attr,
>  					     char *buf)
> @@ -795,6 +872,7 @@ static DEVICE_ATTR_RO(supports_usb_power_delivery);
>  static struct attribute *typec_attrs[] = {
>  	&dev_attr_current_data_role.attr,
>  	&dev_attr_current_power_role.attr,
> +	&dev_attr_current_vconn_role.attr,
>  	&dev_attr_current_usb_data_role.attr,
>  	&dev_attr_power_operation_mode.attr,
>  	&dev_attr_supported_data_roles.attr,
> @@ -862,7 +940,8 @@ static struct device_type typec_port_dev_type = {
>  };
>  
>  struct typec_port *typec_register_port(struct device *dev,
> -				       struct typec_capability *cap)
> +				       struct typec_capability *cap,
> +				       void *driver_data)
>  {
>  	struct typec_port *port;
>  	int ret;
> @@ -880,6 +959,7 @@ struct typec_port *typec_register_port(struct device *dev,
>  
>  	port->id = id;
>  	port->cap = cap;
> +	port->driver_data = driver_data;
>  	port->dev.type = &typec_port_dev_type;
>  	port->dev.class = &typec_class;
>  	port->dev.parent = dev;
> @@ -888,6 +968,8 @@ struct typec_port *typec_register_port(struct device *dev,
>  
>  	port->fixed_role = port->cap->role;
>  
> +	typec_init_roles(port);
> +
>  	ret = device_register(&port->dev);
>  	if (ret) {
>  		ida_simple_remove(&typec_index_ida, id);
> diff --git a/include/linux/usb/typec.h b/include/linux/usb/typec.h
> index 86e5c867800b..d16a38de57ac 100644
> --- a/include/linux/usb/typec.h
> +++ b/include/linux/usb/typec.h
> @@ -168,9 +168,9 @@ struct typec_partner {
>   * @audio_accessory: Audio Accessory Adapter Mode support
>   * @debug_accessory: Debug Accessory Mode support
>   * @fix_role: Set a fixed data role for DRP port
> - * @dr_swap: Data Role Swap support
> - * @pr_swap: Power Role Swap support
> - * @vconn_swap: VCONN Swap support
> + * @dr_set: Set Data Role
> + * @pr_set: Set Power Role
> + * @vconn_set: Set VCONN Role
>   * @activate_mode: Enter/exit given Alternate Mode
>   *
>   * Static capabilities of a single USB Type-C port.
> @@ -182,14 +182,14 @@ struct typec_capability {
>  	unsigned int		audio_accessory:1;
>  	unsigned int		debug_accessory:1;
>  
> -	int			(*fix_role)(struct typec_port *,
> +	int			(*fix_role)(struct typec_port *, void *,
>  					    enum typec_data_role);
>  
> -	int			(*dr_swap)(struct typec_port *);
> -	int			(*pr_swap)(struct typec_port *);
> -	int			(*vconn_swap)(struct typec_port *);
> +	int			(*dr_set)(struct typec_port *, void *, enum typec_usb_role);
> +	int			(*pr_set)(struct typec_port *, void *, enum typec_pwr_role);
> +	int			(*vconn_set)(struct typec_port *, void *, enum typec_pwr_role);
>  
> -	int			(*activate_mode)(struct typec_altmode *,
> +	int			(*activate_mode)(struct typec_altmode *, void *,
>  						 int mode, int activate);
>  };
>  
> @@ -217,7 +217,8 @@ struct typec_connection {
>  };
>  
>  struct typec_port *typec_register_port(struct device *dev,
> -				       struct typec_capability *cap);
> +				       struct typec_capability *cap,
> +				       void *driver_data);
>  void typec_unregister_port(struct typec_port *port);
>  
>  int typec_connect(struct typec_port *port, struct typec_connection *con);
> @@ -227,4 +228,11 @@ void typec_disconnect(struct typec_port *port);
>  struct device *typec_port2dev(struct typec_port *port);
>  struct typec_port *typec_dev2port(struct device *dev);
>  
> +/* Callbacks from driver */
> +
> +void typec_set_usb_role(struct typec_port *, enum typec_usb_role);
> +void typec_set_pwr_role(struct typec_port *, enum typec_pwr_role);
> +void typec_set_vconn_role(struct typec_port *, enum typec_pwr_role);
> +void typec_set_pwr_opmode(struct typec_port *, enum typec_pwr_opmode);
> +
>  #endif /* __LINUX_USB_TYPEC_H */
> -- 
> 2.5.0

-- 
heikki

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [RFC PATCH] usb: typec: Various API updates and fixes
  2016-05-27  7:55   ` Heikki Krogerus
@ 2016-05-27 14:06     ` Guenter Roeck
  2016-05-30 12:48       ` Heikki Krogerus
  0 siblings, 1 reply; 98+ messages in thread
From: Guenter Roeck @ 2016-05-27 14:06 UTC (permalink / raw)
  To: Heikki Krogerus
  Cc: Greg KH, Mathias Nyman, Felipe Balbi, Oliver Neukum, Rajaram R,
	Andy Shevchenko, linux-kernel, linux-usb

On 05/27/2016 12:55 AM, Heikki Krogerus wrote:
> Hi,
>

[ ... ]

>> ---
>> This patch applies on top of '[RFC PATCHv2] usb: USB Type-C Connector Class'
>> from Heikki Krogerus. It provided the changes I made to get the code
>> operational.
>>
>>   drivers/usb/type-c/typec.c | 134 ++++++++++++++++++++++++++++++++++++---------
>>   include/linux/usb/typec.h  |  26 ++++++---
>>   2 files changed, 125 insertions(+), 35 deletions(-)
>
> Thanks Guenter. After a quick glance looks good to me.
>
My pleasure.

> I think I'll create a development branch to my github tree for this
> class and add this on top of the original v2 patch as is. Just to have
> some history for as long we develop this thing. Though I'm not sure
> how useful it is in this case. I think we need to put this together
> fast. I'm thinking we need to target v4.8 with this.
>

Yes, agreed.

> I'll merge this into any case to v3, and I'll send on Monday.
>
Sounds good.

Couple of additional comments.

I don't really know what to do with the 'desc' field in struct typec_mode
for modes received from the partner. I wonder if it makes sense to display
it for partner modes.

Also, there is currently no attribute to show the partner identity (data
received from the Discover Identity command). Would it make sense to add
an 'identity' attribute to the partner device (plus an associated API
function to set it) ?

Thanks,
Guenter

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [RFC PATCH] usb: typec: Various API updates and fixes
  2016-05-27 14:06     ` Guenter Roeck
@ 2016-05-30 12:48       ` Heikki Krogerus
  0 siblings, 0 replies; 98+ messages in thread
From: Heikki Krogerus @ 2016-05-30 12:48 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Greg KH, Oliver Neukum, Mathias Nyman, Felipe Balbi, Rajaram R,
	Andy Shevchenko, linux-kernel, linux-usb

Hi guys,

On Fri, May 27, 2016 at 07:06:41AM -0700, Guenter Roeck wrote:
> On 05/27/2016 12:55 AM, Heikki Krogerus wrote:
> > I'll merge this into any case to v3, and I'll send on Monday.
> > 
> Sounds good.
> 
> Couple of additional comments.
> 
> I don't really know what to do with the 'desc' field in struct typec_mode
> for modes received from the partner. I wonder if it makes sense to display
> it for partner modes.

The idea comes straight from Billboard class where every mode has an
index to an _optional_ string. Those desc should ultimately come from
the altmode bus driver, and I think never from the port drivers.

> Also, there is currently no attribute to show the partner identity (data
> received from the Discover Identity command). Would it make sense to add
> an 'identity' attribute to the partner device (plus an associated API
> function to set it) ?

The problem is that we can only use it when the partner and our port
are both PD capable. Details about PDUSB devices that are attached are
out side the scope of this interface IMO, and need to be in any case
handled in USB core by using the PD Class specific descriptors etc.,
and possible with the help of the future PD stack that you are working
on. It's an other task. So this interface IMO should expose only the
Type-C specific details about the ports and partners. How about if we
just add an attribute "usb_communication_capable" for the partners?
That is something that we should be able to always determine, even
without USB PD.


Thanks,

-- 
heikki

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [RFC PATCHv2] usb: USB Type-C Connector Class
  2016-05-19 12:44 [RFC PATCHv2] usb: USB Type-C Connector Class Heikki Krogerus
                   ` (7 preceding siblings ...)
  2016-05-25 18:35 ` [RFC PATCH] usb: typec: Various API updates and fixes Guenter Roeck
@ 2016-05-30 13:19 ` Heikki Krogerus
  2016-05-30 13:59   ` Oliver Neukum
  2016-06-01  9:26 ` Oliver Neukum
                   ` (3 subsequent siblings)
  12 siblings, 1 reply; 98+ messages in thread
From: Heikki Krogerus @ 2016-05-30 13:19 UTC (permalink / raw)
  To: Guenter Roeck, Oliver Neukum
  Cc: Greg KH, Mathias Nyman, Felipe Balbi, Rajaram R, Andy Shevchenko,
	linux-kernel, linux-usb

[-- Attachment #1: Type: text/plain, Size: 2076 bytes --]

Hi guys,

I'm attaching a diff instead of full v3. I'm not yet adding attributes
for the reset and cable_reset. I still don't understand what is the
case where the userspace would need to be able to tricker reset? Why
isn't it enough for the userspace to be able to enter/exit modes?
Oliver! Can you please comment?

Guenter, I removed the driver_data you proposed and changed the API
so that the struct typec_capability is passed to the function pointers
instead of struct typec_port. The driver_data pointer felt a bit
clumsy to me, as it was something extra that always had to be passed
to every function. Let me know if it's not OK for you.

I also made a change to the partner devices so that they always have
the port as their parent. That will have an effect on the location
where the partner device is exposed in sysfs (so now always under the
port). And because of that, I would like to get an OK from you guys.

I'm a bit concerned about the current API for adding the alternate
modes. Since we are passing the parent for an alternate mode as
struct device, it makes it possible for the caller to place it into
some wrong place. But I guess we can change the API even later.

We also need to decide how the alternate modes a port support are
exposed to the userspace. Do we just assume the port drivers will
create them as devices under the port device itself, just like
alternate modes of partners and cable plugs are exposed under the
partners and cable plugs? That works for me, but again, the class does
not have any effect on that, and it will be just a guideline. Maybe
we can add some kind of helpers and force the port drivers to use
them.

And finally, mostly as a reminder for myself. I didn't yet add
attributes for Try.SRC/SNK. So can we make it something like
"preferred_role" like I think you proposed Guenter? The
"current_data_role" I'm dropping.

So to summarize. There are still open questions regarding the required
attributes and attribute names and locations. Let's agree on those
quickly and then we can polish the patch.


Thanks,

-- 
heikki

[-- Attachment #2: typec_update.diff --]
[-- Type: text/plain, Size: 8138 bytes --]

diff --git a/drivers/usb/type-c/typec.c b/drivers/usb/type-c/typec.c
index 6836e97..41ad955 100644
--- a/drivers/usb/type-c/typec.c
+++ b/drivers/usb/type-c/typec.c
@@ -27,8 +27,6 @@ struct typec_port {
 	struct typec_partner	*partner;
 	struct typec_cable	*cable;
 
-	void			*driver_data;
-
 	unsigned int		connected:1;
 
 	int			n_altmode;
@@ -101,29 +99,10 @@ static int
 typec_add_partner(struct typec_port *port, struct typec_partner *partner)
 {
 	struct device *dev = &partner->dev;
-	struct device *parent;
 	int ret;
 
-	/*
-	 * REVISIT: Maybe it would be better to make the port always as the
-	 * parent of the partner? Or not even that. Would it be enough to just
-	 * create the symlink to the partner like we do below in any case?
-	 */
-	if (port->cable) {
-		if (port->cable->active) {
-			if (port->cable->sop_pp_controller)
-				parent = &port->cable->plug[1].dev;
-			else
-				parent = &port->cable->plug[0].dev;
-		} else {
-			parent = &port->cable->dev;
-		}
-	} else {
-		parent = &port->dev;
-	}
-
 	dev->class = &typec_class;
-	dev->parent = parent;
+	dev->parent = &port->dev;
 	dev->type = &typec_partner_dev_type;
 	dev_set_name(dev, "%s-partner", dev_name(&port->dev));
 
@@ -133,18 +112,6 @@ typec_add_partner(struct typec_port *port, struct typec_partner *partner)
 		return ret;
 	}
 
-	ret = typec_register_altmodes(dev, partner->alt_modes);
-	if (ret) {
-		device_unregister(dev);
-		return ret;
-	}
-
-	/* REVISIT: Creating symlink for the port device for now. */
-	ret = sysfs_create_link(&port->dev.kobj, &dev->kobj, "partner");
-	if (ret)
-		dev_WARN(&port->dev, "failed to create link to %s (%d)\n",
-			 dev_name(dev), ret);
-
 	port->partner = partner;
 	return 0;
 }
@@ -184,12 +151,6 @@ typec_add_plug(struct typec_port *port, struct typec_plug *plug)
 		return ret;
 	}
 
-	ret = typec_register_altmodes(dev, plug->alt_modes);
-	if (ret) {
-		device_unregister(dev);
-		return ret;
-	}
-
 	/* REVISIT: Is this useful? */
 	ret = sysfs_create_link(&port->dev.kobj, &dev->kobj, name);
 	if (ret)
@@ -278,7 +239,6 @@ static int typec_add_cable(struct typec_port *port, struct typec_cable *cable)
 	int ret;
 
 	dev->class = &typec_class;
-	/* REVISIT: We could have just the symlink also for the cable. */
 	dev->parent = &port->dev;
 	dev->type = &typec_cable_dev_type;
 	dev_set_name(dev, "%s-cable", dev_name(&port->dev));
@@ -631,7 +591,7 @@ current_usb_data_role_store(struct device *dev, struct device_attribute *attr,
 	else
 		return -EINVAL;
 
-	ret = port->cap->dr_set(port, port->driver_data, role);
+	ret = port->cap->dr_set(port->cap, role);
 	if (ret)
 		return ret;
 
@@ -667,46 +627,6 @@ static ssize_t supported_data_roles_show(struct device *dev,
 }
 static DEVICE_ATTR_RO(supported_data_roles);
 
-static ssize_t
-current_data_role_store(struct device *dev, struct device_attribute *attr,
-			const char *buf, size_t size)
-{
-	struct typec_port *port = to_typec_port(dev);
-	enum typec_data_role role;
-	int ret;
-
-	if (port->cap->role != TYPEC_PORT_DRP)
-		return -EOPNOTSUPP;
-
-	if (!port->cap->fix_role)
-		return -EOPNOTSUPP;
-
-	if (!strcmp(buf, "DFP"))
-		role = TYPEC_PORT_DFP;
-	else if (!strcmp(buf, "UFP"))
-		role = TYPEC_PORT_UFP;
-	else if (!strcmp(buf, "DRP"))
-		role = TYPEC_PORT_DRP;
-	else
-		return -EINVAL;
-
-	ret = port->cap->fix_role(port, port->driver_data, role);
-	if (ret)
-		return ret;
-
-	return size;
-}
-
-static ssize_t
-current_data_role_show(struct device *dev, struct device_attribute *attr,
-		       char *buf)
-{
-	struct typec_port *port = to_typec_port(dev);
-
-	return sprintf(buf, "%s\n", typec_data_roles[port->fixed_role]);
-}
-static DEVICE_ATTR_RW(current_data_role);
-
 static ssize_t current_power_role_store(struct device *dev,
 					struct device_attribute *attr,
 					const char *buf, size_t size)
@@ -737,7 +657,7 @@ static ssize_t current_power_role_store(struct device *dev,
 	else
 		return -EINVAL;
 
-	ret = port->cap->pr_set(port, port->driver_data, role);
+	ret = port->cap->pr_set(port->cap, role);
 	if (ret)
 		return ret;
 
@@ -816,7 +736,7 @@ static ssize_t current_vconn_role_store(struct device *dev,
 	else
 		return -EINVAL;
 
-	ret = port->cap->vconn_set(port, port->driver_data, role);
+	ret = port->cap->vconn_set(port->cap, role);
 	if (ret)
 		return ret;
 
@@ -870,7 +790,6 @@ static ssize_t supports_usb_power_delivery_show(struct device *dev,
 static DEVICE_ATTR_RO(supports_usb_power_delivery);
 
 static struct attribute *typec_attrs[] = {
-	&dev_attr_current_data_role.attr,
 	&dev_attr_current_power_role.attr,
 	&dev_attr_current_vconn_role.attr,
 	&dev_attr_current_usb_data_role.attr,
@@ -902,6 +821,10 @@ static struct attribute *altmode_attrs[] = {
 	NULL,
 };
 
+/*
+ * FIXME: Now this group is useless, but is there any use for the
+ * number_of_alternate_modes attribute?
+ */
 static const struct attribute_group altmode_group = {
 	.name = "supported_alternate_modes",
 	.attrs = altmode_attrs,
@@ -940,8 +863,7 @@ static struct device_type typec_port_dev_type = {
 };
 
 struct typec_port *typec_register_port(struct device *dev,
-				       struct typec_capability *cap,
-				       void *driver_data)
+				       const struct typec_capability *cap)
 {
 	struct typec_port *port;
 	int ret;
@@ -959,7 +881,6 @@ struct typec_port *typec_register_port(struct device *dev,
 
 	port->id = id;
 	port->cap = cap;
-	port->driver_data = driver_data;
 	port->dev.type = &typec_port_dev_type;
 	port->dev.class = &typec_class;
 	port->dev.parent = dev;
@@ -978,28 +899,6 @@ struct typec_port *typec_register_port(struct device *dev,
 		return ERR_PTR(ret);
 	}
 
-	/*
-	 * The alternate modes that the port supports must be created before
-	 * registering the port. They are just linked to the port here.
-	 */
-	if (cap->alt_modes) {
-		struct typec_altmode *alt;
-
-		for (alt = cap->alt_modes; alt->svid; alt++) {
-			ret = sysfs_add_link_to_group(&port->dev.kobj,
-						"supported_alternate_modes",
-						&alt->dev.kobj,
-						alt->name ? alt->name :
-						dev_name(&alt->dev));
-			if (ret) {
-				dev_WARN(&port->dev,
-					 "failed to create sysfs symlink\n");
-			} else {
-				port->n_altmode++;
-			}
-		}
-	}
-
 	return port;
 }
 EXPORT_SYMBOL_GPL(typec_register_port);
@@ -1009,15 +908,6 @@ void typec_unregister_port(struct typec_port *port)
 	if (port->connected)
 		typec_disconnect(port);
 
-	if (port->cap->alt_modes) {
-		struct typec_altmode *alt;
-
-		for (alt = port->cap->alt_modes; alt->svid; alt++)
-			sysfs_remove_link_from_group(&port->dev.kobj,
-						     "alternate_modes",
-						     alt->name ? alt->name :
-						     dev_name(&alt->dev));
-	}
 	device_unregister(&port->dev);
 }
 EXPORT_SYMBOL_GPL(typec_unregister_port);
diff --git a/include/linux/usb/typec.h b/include/linux/usb/typec.h
index d16a38d..390e0e4 100644
--- a/include/linux/usb/typec.h
+++ b/include/linux/usb/typec.h
@@ -182,14 +182,18 @@ struct typec_capability {
 	unsigned int		audio_accessory:1;
 	unsigned int		debug_accessory:1;
 
-	int			(*fix_role)(struct typec_port *, void *,
+	/* FIXME: change to prefer_role? */
+	int			(*fix_role)(const struct typec_capability *,
 					    enum typec_data_role);
 
-	int			(*dr_set)(struct typec_port *, void *, enum typec_usb_role);
-	int			(*pr_set)(struct typec_port *, void *, enum typec_pwr_role);
-	int			(*vconn_set)(struct typec_port *, void *, enum typec_pwr_role);
+	int			(*dr_set)(const struct typec_capability *,
+					  enum typec_usb_role);
+	int			(*pr_set)(const struct typec_capability *,
+					  enum typec_pwr_role);
+	int			(*vconn_set)(const struct typec_capability *,
+					     enum typec_pwr_role);
 
-	int			(*activate_mode)(struct typec_altmode *, void *,
+	int			(*activate_mode)(struct typec_altmode *,
 						 int mode, int activate);
 };
 
@@ -217,8 +221,7 @@ struct typec_connection {
 };
 
 struct typec_port *typec_register_port(struct device *dev,
-				       struct typec_capability *cap,
-				       void *driver_data);
+				       const struct typec_capability *cap);
 void typec_unregister_port(struct typec_port *port);
 
 int typec_connect(struct typec_port *port, struct typec_connection *con);

^ permalink raw reply related	[flat|nested] 98+ messages in thread

* Re: [RFC PATCHv2] usb: USB Type-C Connector Class
  2016-05-30 13:19 ` [RFC PATCHv2] usb: USB Type-C Connector Class Heikki Krogerus
@ 2016-05-30 13:59   ` Oliver Neukum
  2016-05-31  8:31     ` Heikki Krogerus
  0 siblings, 1 reply; 98+ messages in thread
From: Oliver Neukum @ 2016-05-30 13:59 UTC (permalink / raw)
  To: Heikki Krogerus
  Cc: Guenter Roeck, Andy Shevchenko, Rajaram R, Felipe Balbi,
	Mathias Nyman, Greg KH, linux-kernel, linux-usb

On Mon, 2016-05-30 at 16:19 +0300, Heikki Krogerus wrote:
> Hi guys,
> 
> I'm attaching a diff instead of full v3. I'm not yet adding attributes
> for the reset and cable_reset. I still don't understand what is the
> case where the userspace would need to be able to tricker reset? Why
> isn't it enough for the userspace to be able to enter/exit modes?
> Oliver! Can you please comment?

1. Because we need error handling.
   Devices crash. Cables will crash. We will get out of sync.
   You never put yourself in a place where you cannot handle an
   IO error.
2. Because it is in the spec. We do not second guess the spec.
   We implement it.

> I also made a change to the partner devices so that they always have
> the port as their parent. That will have an effect on the location
> where the partner device is exposed in sysfs (so now always under the
> port). And because of that, I would like to get an OK from you guys.

It is not very important. i am fine with it.

> I'm a bit concerned about the current API for adding the alternate
> modes. Since we are passing the parent for an alternate mode as
> struct device, it makes it possible for the caller to place it into
> some wrong place. But I guess we can change the API even later.
> 
> We also need to decide how the alternate modes a port support are
> exposed to the userspace. Do we just assume the port drivers will
> create them as devices under the port device itself, just like
> alternate modes of partners and cable plugs are exposed under the
> partners and cable plugs? That works for me, but again, the class does
> not have any effect on that, and it will be just a guideline. Maybe
> we can add some kind of helpers and force the port drivers to use
> them.

What are the alternatives?

> And finally, mostly as a reminder for myself. I didn't yet add
> attributes for Try.SRC/SNK. So can we make it something like
> "preferred_role" like I think you proposed Guenter? The
> "current_data_role" I'm dropping.

That sounds good.

	Regards
		Oliver

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [RFC PATCHv2] usb: USB Type-C Connector Class
  2016-05-30 13:59   ` Oliver Neukum
@ 2016-05-31  8:31     ` Heikki Krogerus
  2016-05-31  8:48       ` Oliver Neukum
  2016-05-31 17:14       ` Guenter Roeck
  0 siblings, 2 replies; 98+ messages in thread
From: Heikki Krogerus @ 2016-05-31  8:31 UTC (permalink / raw)
  To: Oliver Neukum
  Cc: Guenter Roeck, Andy Shevchenko, Rajaram R, Felipe Balbi,
	Mathias Nyman, Greg KH, linux-kernel, linux-usb

Hi Oliver,

On Mon, May 30, 2016 at 03:59:27PM +0200, Oliver Neukum wrote:
> On Mon, 2016-05-30 at 16:19 +0300, Heikki Krogerus wrote:
> > Hi guys,
> > 
> > I'm attaching a diff instead of full v3. I'm not yet adding attributes
> > for the reset and cable_reset. I still don't understand what is the
> > case where the userspace would need to be able to tricker reset? Why
> > isn't it enough for the userspace to be able to enter/exit modes?
> > Oliver! Can you please comment?
> 
> 1. Because we need error handling.
>    Devices crash. Cables will crash. We will get out of sync.
>    You never put yourself in a place where you cannot handle an
>    IO error.
> 2. Because it is in the spec. We do not second guess the spec.
>    We implement it.

Error conditions and crashes are the responsibility of the USB PD
stack, not userspace. In those cases the stack can not wait for a
command from the userspace. So for example if a timer like
NoResponseTimer times out, the stack an its state machines will have
to take care of the reset quite independently.

If you get out of sync with an alternate mode, you reset that specific
alternate mode by exiting and re-entering it, and you do not reset the
entire PD connection, port, partner or cable.

The resets from userspace would be purely unsolicited. What would the
cases where we would need to tricker a reset like that?

I want to be careful with exposing reset to userspace. Reset in USB PD
is not just an IO related thing. When you tricker a reset with USB PD,
even if it's a soft reset, it may lead into hard reset, which may
potentially lead into sudden voltage and current drop, which may lead
into the entire system crashing. We really need to understand the
cases where it would be necessary to tricker a reset from userspace.
Right now I don't see any.

> > I also made a change to the partner devices so that they always have
> > the port as their parent. That will have an effect on the location
> > where the partner device is exposed in sysfs (so now always under the
> > port). And because of that, I would like to get an OK from you guys.
> 
> It is not very important. i am fine with it.
> 
> > I'm a bit concerned about the current API for adding the alternate
> > modes. Since we are passing the parent for an alternate mode as
> > struct device, it makes it possible for the caller to place it into
> > some wrong place. But I guess we can change the API even later.
> > 
> > We also need to decide how the alternate modes a port support are
> > exposed to the userspace. Do we just assume the port drivers will
> > create them as devices under the port device itself, just like
> > alternate modes of partners and cable plugs are exposed under the
> > partners and cable plugs? That works for me, but again, the class does
> > not have any effect on that, and it will be just a guideline. Maybe
> > we can add some kind of helpers and force the port drivers to use
> > them.
> 
> What are the alternatives?

Can we make a group for them under the port device somehow? Like the
supported_alternate_modes I proposed. I guess it's not possible to add
devices to a specific group in sysfs. And would it even be useful.


Thanks,

-- 
heikki

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [RFC PATCHv2] usb: USB Type-C Connector Class
  2016-05-31  8:31     ` Heikki Krogerus
@ 2016-05-31  8:48       ` Oliver Neukum
  2016-05-31 12:09         ` Heikki Krogerus
  2016-05-31 17:14       ` Guenter Roeck
  1 sibling, 1 reply; 98+ messages in thread
From: Oliver Neukum @ 2016-05-31  8:48 UTC (permalink / raw)
  To: Heikki Krogerus
  Cc: Andy Shevchenko, Rajaram R, Felipe Balbi, Mathias Nyman, Greg KH,
	Guenter Roeck, linux-kernel, linux-usb

On Tue, 2016-05-31 at 11:31 +0300, Heikki Krogerus wrote:
> Hi Oliver,
> 
> On Mon, May 30, 2016 at 03:59:27PM +0200, Oliver Neukum wrote:
> > On Mon, 2016-05-30 at 16:19 +0300, Heikki Krogerus wrote:
> > > Hi guys,
> > > 
> > > I'm attaching a diff instead of full v3. I'm not yet adding attributes
> > > for the reset and cable_reset. I still don't understand what is the
> > > case where the userspace would need to be able to tricker reset? Why
> > > isn't it enough for the userspace to be able to enter/exit modes?
> > > Oliver! Can you please comment?
> > 
> > 1. Because we need error handling.
> >    Devices crash. Cables will crash. We will get out of sync.
> >    You never put yourself in a place where you cannot handle an
> >    IO error.
> > 2. Because it is in the spec. We do not second guess the spec.
> >    We implement it.
> 
> Error conditions and crashes are the responsibility of the USB PD
> stack, not userspace. In those cases the stack can not wait for a

Those are not exclusive conditions.

> command from the userspace. So for example if a timer like
> NoResponseTimer times out, the stack an its state machines will have
> to take care of the reset quite independently.

Yes. But somebody needs to handle high level errors.

> If you get out of sync with an alternate mode, you reset that specific
> alternate mode by exiting and re-entering it, and you do not reset the
> entire PD connection, port, partner or cable.

That would be the first step. If that doesn't work you will at that
point either give up or use the next largest hammer.
In principle you could do that in kernel space, but that implies
that the kernel can detect all failures. That is unlikely.

> The resets from userspace would be purely unsolicited. What would the
> cases where we would need to tricker a reset like that?
> 
> I want to be careful with exposing reset to userspace. Reset in USB PD
> is not just an IO related thing. When you tricker a reset with USB PD,
> even if it's a soft reset, it may lead into hard reset, which may
> potentially lead into sudden voltage and current drop, which may lead
> into the entire system crashing. We really need to understand the
> cases where it would be necessary to tricker a reset from userspace.
> Right now I don't see any.

User space can call reboot. Actually that does not help.
Reset is an operation that is intended for error handling.
If all else fails, we will need to use it.
Its bad consequences apply whether you trigger this from kernel or
user space. In fact, an operation that may potentially crash the system
should involve user space.

[..]
> > > We also need to decide how the alternate modes a port support are
> > > exposed to the userspace. Do we just assume the port drivers will
> > > create them as devices under the port device itself, just like
> > > alternate modes of partners and cable plugs are exposed under the
> > > partners and cable plugs? That works for me, but again, the class does
> > > not have any effect on that, and it will be just a guideline. Maybe
> > > we can add some kind of helpers and force the port drivers to use
> > > them.
> > 
> > What are the alternatives?
> 
> Can we make a group for them under the port device somehow? Like the
> supported_alternate_modes I proposed. I guess it's not possible to add
> devices to a specific group in sysfs. And would it even be useful.

Please explain. It is not clear to me what you are proposing here.

	Regards
		Oliver

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [RFC PATCHv2] usb: USB Type-C Connector Class
  2016-05-31  8:48       ` Oliver Neukum
@ 2016-05-31 12:09         ` Heikki Krogerus
  2016-05-31 12:43           ` Heikki Krogerus
  0 siblings, 1 reply; 98+ messages in thread
From: Heikki Krogerus @ 2016-05-31 12:09 UTC (permalink / raw)
  To: Oliver Neukum
  Cc: Andy Shevchenko, Rajaram R, Felipe Balbi, Mathias Nyman, Greg KH,
	Guenter Roeck, linux-kernel, linux-usb

On Tue, May 31, 2016 at 10:48:29AM +0200, Oliver Neukum wrote:
> On Tue, 2016-05-31 at 11:31 +0300, Heikki Krogerus wrote:
> > Hi Oliver,
> > 
> > On Mon, May 30, 2016 at 03:59:27PM +0200, Oliver Neukum wrote:
> > > On Mon, 2016-05-30 at 16:19 +0300, Heikki Krogerus wrote:
> > > > Hi guys,
> > > > 
> > > > I'm attaching a diff instead of full v3. I'm not yet adding attributes
> > > > for the reset and cable_reset. I still don't understand what is the
> > > > case where the userspace would need to be able to tricker reset? Why
> > > > isn't it enough for the userspace to be able to enter/exit modes?
> > > > Oliver! Can you please comment?
> > > 
> > > 1. Because we need error handling.
> > >    Devices crash. Cables will crash. We will get out of sync.
> > >    You never put yourself in a place where you cannot handle an
> > >    IO error.
> > > 2. Because it is in the spec. We do not second guess the spec.
> > >    We implement it.
> > 
> > Error conditions and crashes are the responsibility of the USB PD
> > stack, not userspace. In those cases the stack can not wait for a
> 
> Those are not exclusive conditions.
> 
> > command from the userspace. So for example if a timer like
> > NoResponseTimer times out, the stack an its state machines will have
> > to take care of the reset quite independently.
> 
> Yes. But somebody needs to handle high level errors.
> 
> > If you get out of sync with an alternate mode, you reset that specific
> > alternate mode by exiting and re-entering it, and you do not reset the
> > entire PD connection, port, partner or cable.
> 
> That would be the first step. If that doesn't work you will at that
> point either give up or use the next largest hammer.
> In principle you could do that in kernel space, but that implies
> that the kernel can detect all failures. That is unlikely.

Any PD communication failures the kernel has to be able to detect, so
I guess you mean failures with the alternate modes themselves, right?

In that case, surely exiting the mode is enough to "reset" it? When it
is re-entered, it has to be completely re-configured in any case. I
don't see how resetting the whole port or cable would guarantee that a
mode would become any more functional in case of failures? It will
however make also the other active modes to de-activate even if they
are functioning fine.

> > The resets from userspace would be purely unsolicited. What would the
> > cases where we would need to tricker a reset like that?
> > 
> > I want to be careful with exposing reset to userspace. Reset in USB PD
> > is not just an IO related thing. When you tricker a reset with USB PD,
> > even if it's a soft reset, it may lead into hard reset, which may
> > potentially lead into sudden voltage and current drop, which may lead
> > into the entire system crashing. We really need to understand the
> > cases where it would be necessary to tricker a reset from userspace.
> > Right now I don't see any.
> 
> User space can call reboot. Actually that does not help.
> Reset is an operation that is intended for error handling.
> If all else fails, we will need to use it.
> Its bad consequences apply whether you trigger this from kernel or
> user space. In fact, an operation that may potentially crash the system
> should involve user space.
> 
> > > > We also need to decide how the alternate modes a port support are
> > > > exposed to the userspace. Do we just assume the port drivers will
> > > > create them as devices under the port device itself, just like
> > > > alternate modes of partners and cable plugs are exposed under the
> > > > partners and cable plugs? That works for me, but again, the class does
> > > > not have any effect on that, and it will be just a guideline. Maybe
> > > > we can add some kind of helpers and force the port drivers to use
> > > > them.
> > > 
> > > What are the alternatives?
> > 
> > Can we make a group for them under the port device somehow? Like the
> > supported_alternate_modes I proposed. I guess it's not possible to add
> > devices to a specific group in sysfs. And would it even be useful.
> 
> Please explain. It is not clear to me what you are proposing here.

So is it possible to have a folder in sysfs for the alternate modes
a port supports?

So instead of:

        /sysfs/class/type-c/usbc0/svid:xxx1/
        /sysfs/class/type-c/usbc0/svid:xxx2/
        /sysfs/class/type-c/usbc0/svid:xxx3/
        ...

We would have something like:

        /sysfs/class/type-c/usbc0/supported_alternate_modes/svid:xxx1/
        /sysfs/class/type-c/usbc0/supported_alternate_modes/svid:xxx2/
        /sysfs/class/type-c/usbc0/supported_alternate_modes/svid:xxx3/
        ...


Thanks,

-- 
heikki

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [RFC PATCHv2] usb: USB Type-C Connector Class
  2016-05-31 12:09         ` Heikki Krogerus
@ 2016-05-31 12:43           ` Heikki Krogerus
  2016-05-31 17:20             ` Guenter Roeck
  0 siblings, 1 reply; 98+ messages in thread
From: Heikki Krogerus @ 2016-05-31 12:43 UTC (permalink / raw)
  To: Oliver Neukum
  Cc: Andy Shevchenko, Rajaram R, Felipe Balbi, Mathias Nyman, Greg KH,
	Guenter Roeck, linux-kernel, linux-usb

On Tue, May 31, 2016 at 03:09:01PM +0300, Heikki Krogerus wrote:
> On Tue, May 31, 2016 at 10:48:29AM +0200, Oliver Neukum wrote:
> > On Tue, 2016-05-31 at 11:31 +0300, Heikki Krogerus wrote:
> > > Hi Oliver,
> > > 
> > > On Mon, May 30, 2016 at 03:59:27PM +0200, Oliver Neukum wrote:
> > > > On Mon, 2016-05-30 at 16:19 +0300, Heikki Krogerus wrote:
> > > > > Hi guys,
> > > > > 
> > > > > I'm attaching a diff instead of full v3. I'm not yet adding attributes
> > > > > for the reset and cable_reset. I still don't understand what is the
> > > > > case where the userspace would need to be able to tricker reset? Why
> > > > > isn't it enough for the userspace to be able to enter/exit modes?
> > > > > Oliver! Can you please comment?
> > > > 
> > > > 1. Because we need error handling.
> > > >    Devices crash. Cables will crash. We will get out of sync.
> > > >    You never put yourself in a place where you cannot handle an
> > > >    IO error.
> > > > 2. Because it is in the spec. We do not second guess the spec.
> > > >    We implement it.
> > > 
> > > Error conditions and crashes are the responsibility of the USB PD
> > > stack, not userspace. In those cases the stack can not wait for a
> > 
> > Those are not exclusive conditions.
> > 
> > > command from the userspace. So for example if a timer like
> > > NoResponseTimer times out, the stack an its state machines will have
> > > to take care of the reset quite independently.
> > 
> > Yes. But somebody needs to handle high level errors.
> > 
> > > If you get out of sync with an alternate mode, you reset that specific
> > > alternate mode by exiting and re-entering it, and you do not reset the
> > > entire PD connection, port, partner or cable.
> > 
> > That would be the first step. If that doesn't work you will at that
> > point either give up or use the next largest hammer.
> > In principle you could do that in kernel space, but that implies
> > that the kernel can detect all failures. That is unlikely.
> 
> Any PD communication failures the kernel has to be able to detect, so
> I guess you mean failures with the alternate modes themselves, right?
> 
> In that case, surely exiting the mode is enough to "reset" it? When it
> is re-entered, it has to be completely re-configured in any case. I
> don't see how resetting the whole port or cable would guarantee that a
> mode would become any more functional in case of failures? It will
> however make also the other active modes to de-activate even if they
> are functioning fine.

Forget about it, I'll just add the reset attributes. I'm still not
clear about their usefulness, but instead they will just create a small
risk, but I can live with that.


Cheers,

-- 
heikki

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [RFC PATCHv2] usb: USB Type-C Connector Class
  2016-05-31  8:31     ` Heikki Krogerus
  2016-05-31  8:48       ` Oliver Neukum
@ 2016-05-31 17:14       ` Guenter Roeck
  1 sibling, 0 replies; 98+ messages in thread
From: Guenter Roeck @ 2016-05-31 17:14 UTC (permalink / raw)
  To: Heikki Krogerus
  Cc: Oliver Neukum, Andy Shevchenko, Rajaram R, Felipe Balbi,
	Mathias Nyman, Greg KH, linux-kernel, linux-usb

On Tue, May 31, 2016 at 11:31:21AM +0300, Heikki Krogerus wrote:
> Hi Oliver,
> 
> On Mon, May 30, 2016 at 03:59:27PM +0200, Oliver Neukum wrote:
> > On Mon, 2016-05-30 at 16:19 +0300, Heikki Krogerus wrote:
> > > Hi guys,
> > > 
> > > I'm attaching a diff instead of full v3. I'm not yet adding attributes
> > > for the reset and cable_reset. I still don't understand what is the
> > > case where the userspace would need to be able to tricker reset? Why
> > > isn't it enough for the userspace to be able to enter/exit modes?
> > > Oliver! Can you please comment?
> > 
> > 1. Because we need error handling.
> >    Devices crash. Cables will crash. We will get out of sync.
> >    You never put yourself in a place where you cannot handle an
> >    IO error.
> > 2. Because it is in the spec. We do not second guess the spec.
> >    We implement it.
> 
> Error conditions and crashes are the responsibility of the USB PD
> stack, not userspace. In those cases the stack can not wait for a
> command from the userspace. So for example if a timer like
> NoResponseTimer times out, the stack an its state machines will have
> to take care of the reset quite independently.
> 
Agreed.

> If you get out of sync with an alternate mode, you reset that specific
> alternate mode by exiting and re-entering it, and you do not reset the
> entire PD connection, port, partner or cable.
> 
> The resets from userspace would be purely unsolicited. What would the
> cases where we would need to tricker a reset like that?
> 
> I want to be careful with exposing reset to userspace. Reset in USB PD
> is not just an IO related thing. When you tricker a reset with USB PD,
> even if it's a soft reset, it may lead into hard reset, which may

It may also lead to and trigger error recovery, which is pretty much
similar to physical disconnect and reconnect.

> potentially lead into sudden voltage and current drop, which may lead
> into the entire system crashing. We really need to understand the
> cases where it would be necessary to tricker a reset from userspace.
> Right now I don't see any.
> 
Me not either, really. Error conditions are notoriously difficult to handle.
I can get devices with external power into a state where even error recovery
doesn't bring the USB-PD connection back to operational mode - it is sometimes
necessary to disconnect power. With that in mind, not only is a reset from user
space risky, it may actually make the situation worse. That will hopefully
change over time, as the protocol implementations stabilize, but right now I am
very hesitant to add another variable into the picture - especially if the
benefits are not clear.

Thanks,
Guenter

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [RFC PATCHv2] usb: USB Type-C Connector Class
  2016-05-31 12:43           ` Heikki Krogerus
@ 2016-05-31 17:20             ` Guenter Roeck
  2016-06-01  8:23               ` Heikki Krogerus
  0 siblings, 1 reply; 98+ messages in thread
From: Guenter Roeck @ 2016-05-31 17:20 UTC (permalink / raw)
  To: Heikki Krogerus
  Cc: Oliver Neukum, Andy Shevchenko, Rajaram R, Felipe Balbi,
	Mathias Nyman, Greg KH, linux-kernel, linux-usb

On Tue, May 31, 2016 at 03:43:56PM +0300, Heikki Krogerus wrote:
> On Tue, May 31, 2016 at 03:09:01PM +0300, Heikki Krogerus wrote:
> > On Tue, May 31, 2016 at 10:48:29AM +0200, Oliver Neukum wrote:
> > > On Tue, 2016-05-31 at 11:31 +0300, Heikki Krogerus wrote:
> > > > Hi Oliver,
> > > > 
> > > > On Mon, May 30, 2016 at 03:59:27PM +0200, Oliver Neukum wrote:
> > > > > On Mon, 2016-05-30 at 16:19 +0300, Heikki Krogerus wrote:
> > > > > > Hi guys,
> > > > > > 
> > > > > > I'm attaching a diff instead of full v3. I'm not yet adding attributes
> > > > > > for the reset and cable_reset. I still don't understand what is the
> > > > > > case where the userspace would need to be able to tricker reset? Why
> > > > > > isn't it enough for the userspace to be able to enter/exit modes?
> > > > > > Oliver! Can you please comment?
> > > > > 
> > > > > 1. Because we need error handling.
> > > > >    Devices crash. Cables will crash. We will get out of sync.
> > > > >    You never put yourself in a place where you cannot handle an
> > > > >    IO error.
> > > > > 2. Because it is in the spec. We do not second guess the spec.
> > > > >    We implement it.
> > > > 
> > > > Error conditions and crashes are the responsibility of the USB PD
> > > > stack, not userspace. In those cases the stack can not wait for a
> > > 
> > > Those are not exclusive conditions.
> > > 
> > > > command from the userspace. So for example if a timer like
> > > > NoResponseTimer times out, the stack an its state machines will have
> > > > to take care of the reset quite independently.
> > > 
> > > Yes. But somebody needs to handle high level errors.
> > > 
> > > > If you get out of sync with an alternate mode, you reset that specific
> > > > alternate mode by exiting and re-entering it, and you do not reset the
> > > > entire PD connection, port, partner or cable.
> > > 
> > > That would be the first step. If that doesn't work you will at that
> > > point either give up or use the next largest hammer.
> > > In principle you could do that in kernel space, but that implies
> > > that the kernel can detect all failures. That is unlikely.
> > 
> > Any PD communication failures the kernel has to be able to detect, so
> > I guess you mean failures with the alternate modes themselves, right?
> > 
> > In that case, surely exiting the mode is enough to "reset" it? When it
> > is re-entered, it has to be completely re-configured in any case. I
> > don't see how resetting the whole port or cable would guarantee that a
> > mode would become any more functional in case of failures? It will
> > however make also the other active modes to de-activate even if they
> > are functioning fine.
> 
> Forget about it, I'll just add the reset attributes. I'm still not
> clear about their usefulness, but instead they will just create a small
> risk, but I can live with that.
> 

Given my experience over the last few weeks, I think the added risk
may not just be small, and I think the added benefit is questionable.
Reset handling is not well implemented in all devices, and manually
triggered resets in an unexpected state may make the situation worse.

Can you make it optional ? I may choose not to support it to avoid
the risk.

Thanks,
Guenter

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [RFC PATCHv2] usb: USB Type-C Connector Class
  2016-05-31 17:20             ` Guenter Roeck
@ 2016-06-01  8:23               ` Heikki Krogerus
  2016-06-01  8:31                 ` Oliver Neukum
  2016-06-01  9:04                 ` Oliver Neukum
  0 siblings, 2 replies; 98+ messages in thread
From: Heikki Krogerus @ 2016-06-01  8:23 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Oliver Neukum, Andy Shevchenko, Rajaram R, Felipe Balbi,
	Mathias Nyman, Greg KH, linux-kernel, linux-usb

On Tue, May 31, 2016 at 10:20:34AM -0700, Guenter Roeck wrote:
> On Tue, May 31, 2016 at 03:43:56PM +0300, Heikki Krogerus wrote:
> > On Tue, May 31, 2016 at 03:09:01PM +0300, Heikki Krogerus wrote:
> > > On Tue, May 31, 2016 at 10:48:29AM +0200, Oliver Neukum wrote:
> > > > On Tue, 2016-05-31 at 11:31 +0300, Heikki Krogerus wrote:
> > > > > Hi Oliver,
> > > > > 
> > > > > On Mon, May 30, 2016 at 03:59:27PM +0200, Oliver Neukum wrote:
> > > > > > On Mon, 2016-05-30 at 16:19 +0300, Heikki Krogerus wrote:
> > > > > > > Hi guys,
> > > > > > > 
> > > > > > > I'm attaching a diff instead of full v3. I'm not yet adding attributes
> > > > > > > for the reset and cable_reset. I still don't understand what is the
> > > > > > > case where the userspace would need to be able to tricker reset? Why
> > > > > > > isn't it enough for the userspace to be able to enter/exit modes?
> > > > > > > Oliver! Can you please comment?
> > > > > > 
> > > > > > 1. Because we need error handling.
> > > > > >    Devices crash. Cables will crash. We will get out of sync.
> > > > > >    You never put yourself in a place where you cannot handle an
> > > > > >    IO error.
> > > > > > 2. Because it is in the spec. We do not second guess the spec.
> > > > > >    We implement it.
> > > > > 
> > > > > Error conditions and crashes are the responsibility of the USB PD
> > > > > stack, not userspace. In those cases the stack can not wait for a
> > > > 
> > > > Those are not exclusive conditions.
> > > > 
> > > > > command from the userspace. So for example if a timer like
> > > > > NoResponseTimer times out, the stack an its state machines will have
> > > > > to take care of the reset quite independently.
> > > > 
> > > > Yes. But somebody needs to handle high level errors.
> > > > 
> > > > > If you get out of sync with an alternate mode, you reset that specific
> > > > > alternate mode by exiting and re-entering it, and you do not reset the
> > > > > entire PD connection, port, partner or cable.
> > > > 
> > > > That would be the first step. If that doesn't work you will at that
> > > > point either give up or use the next largest hammer.
> > > > In principle you could do that in kernel space, but that implies
> > > > that the kernel can detect all failures. That is unlikely.
> > > 
> > > Any PD communication failures the kernel has to be able to detect, so
> > > I guess you mean failures with the alternate modes themselves, right?
> > > 
> > > In that case, surely exiting the mode is enough to "reset" it? When it
> > > is re-entered, it has to be completely re-configured in any case. I
> > > don't see how resetting the whole port or cable would guarantee that a
> > > mode would become any more functional in case of failures? It will
> > > however make also the other active modes to de-activate even if they
> > > are functioning fine.
> > 
> > Forget about it, I'll just add the reset attributes. I'm still not
> > clear about their usefulness, but instead they will just create a small
> > risk, but I can live with that.
> > 
> 
> Given my experience over the last few weeks, I think the added risk
> may not just be small, and I think the added benefit is questionable.
> Reset handling is not well implemented in all devices, and manually
> triggered resets in an unexpected state may make the situation worse.
> 
> Can you make it optional ? I may choose not to support it to avoid
> the risk.

Maybe I gave up on this too hastily... I changing my mind about this,
I'm not going to add them. Having them optional is not enough. It
changes nothing when they are implemented. I think there is a change
that we would actually end up having to remove the attributes, which
would be really bad.

I think we can still add them later if they are still seen as
necessity later on, tough I seriously doubt it. It would not be
ideal, but adding an attribute should not really break anything,
right? Removing would.


Thanks,

-- 
heikki

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [RFC PATCHv2] usb: USB Type-C Connector Class
  2016-06-01  8:23               ` Heikki Krogerus
@ 2016-06-01  8:31                 ` Oliver Neukum
  2016-06-01  9:04                 ` Oliver Neukum
  1 sibling, 0 replies; 98+ messages in thread
From: Oliver Neukum @ 2016-06-01  8:31 UTC (permalink / raw)
  To: Heikki Krogerus
  Cc: Guenter Roeck, Andy Shevchenko, Rajaram R, Felipe Balbi,
	Mathias Nyman, Greg KH, linux-kernel, linux-usb

On Wed, 2016-06-01 at 11:23 +0300, Heikki Krogerus wrote:
> On Tue, May 31, 2016 at 10:20:34AM -0700, Guenter Roeck wrote:
> > On Tue, May 31, 2016 at 03:43:56PM +0300, Heikki Krogerus wrote:
> > > On Tue, May 31, 2016 at 03:09:01PM +0300, Heikki Krogerus wrote:
> > > > On Tue, May 31, 2016 at 10:48:29AM +0200, Oliver Neukum wrote:
> > > > > On Tue, 2016-05-31 at 11:31 +0300, Heikki Krogerus wrote:
> > > > > > Hi Oliver,
> > > > > > 
> > > > > > On Mon, May 30, 2016 at 03:59:27PM +0200, Oliver Neukum wrote:
> > > > > > > On Mon, 2016-05-30 at 16:19 +0300, Heikki Krogerus wrote:
> > > > > > > > Hi guys,
> > > > > > > > 
> > > > > > > > I'm attaching a diff instead of full v3. I'm not yet adding attributes
> > > > > > > > for the reset and cable_reset. I still don't understand what is the
> > > > > > > > case where the userspace would need to be able to tricker reset? Why
> > > > > > > > isn't it enough for the userspace to be able to enter/exit modes?
> > > > > > > > Oliver! Can you please comment?
> > > > > > > 
> > > > > > > 1. Because we need error handling.
> > > > > > >    Devices crash. Cables will crash. We will get out of sync.
> > > > > > >    You never put yourself in a place where you cannot handle an
> > > > > > >    IO error.
> > > > > > > 2. Because it is in the spec. We do not second guess the spec.
> > > > > > >    We implement it.
> > > > > > 
> > > > > > Error conditions and crashes are the responsibility of the USB PD
> > > > > > stack, not userspace. In those cases the stack can not wait for a
> > > > > 
> > > > > Those are not exclusive conditions.
> > > > > 
> > > > > > command from the userspace. So for example if a timer like
> > > > > > NoResponseTimer times out, the stack an its state machines will have
> > > > > > to take care of the reset quite independently.
> > > > > 
> > > > > Yes. But somebody needs to handle high level errors.
> > > > > 
> > > > > > If you get out of sync with an alternate mode, you reset that specific
> > > > > > alternate mode by exiting and re-entering it, and you do not reset the
> > > > > > entire PD connection, port, partner or cable.
> > > > > 
> > > > > That would be the first step. If that doesn't work you will at that
> > > > > point either give up or use the next largest hammer.
> > > > > In principle you could do that in kernel space, but that implies
> > > > > that the kernel can detect all failures. That is unlikely.
> > > > 
> > > > Any PD communication failures the kernel has to be able to detect, so
> > > > I guess you mean failures with the alternate modes themselves, right?
> > > > 
> > > > In that case, surely exiting the mode is enough to "reset" it? When it
> > > > is re-entered, it has to be completely re-configured in any case. I
> > > > don't see how resetting the whole port or cable would guarantee that a
> > > > mode would become any more functional in case of failures? It will
> > > > however make also the other active modes to de-activate even if they
> > > > are functioning fine.
> > > 
> > > Forget about it, I'll just add the reset attributes. I'm still not
> > > clear about their usefulness, but instead they will just create a small
> > > risk, but I can live with that.
> > > 
> > 
> > Given my experience over the last few weeks, I think the added risk
> > may not just be small, and I think the added benefit is questionable.
> > Reset handling is not well implemented in all devices, and manually
> > triggered resets in an unexpected state may make the situation worse.
> > 
> > Can you make it optional ? I may choose not to support it to avoid
> > the risk.
> 
> Maybe I gave up on this too hastily... I changing my mind about this,
> I'm not going to add them. Having them optional is not enough. It
> changes nothing when they are implemented. I think there is a change
> that we would actually end up having to remove the attributes, which
> would be really bad.
> 
> I think we can still add them later if they are still seen as
> necessity later on, tough I seriously doubt it. It would not be
> ideal, but adding an attribute should not really break anything,
> right? Removing would.

That is true. So let's leave it out for now. I still think sane
error handling will require it eventually, but that will be in the
future.

	Regards
		Oliver

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [RFC PATCHv2] usb: USB Type-C Connector Class
  2016-06-01  8:23               ` Heikki Krogerus
  2016-06-01  8:31                 ` Oliver Neukum
@ 2016-06-01  9:04                 ` Oliver Neukum
  2016-06-01 13:34                   ` Guenter Roeck
  1 sibling, 1 reply; 98+ messages in thread
From: Oliver Neukum @ 2016-06-01  9:04 UTC (permalink / raw)
  To: Heikki Krogerus
  Cc: Guenter Roeck, Andy Shevchenko, Rajaram R, Felipe Balbi,
	Mathias Nyman, Greg KH, linux-kernel, linux-usb

On Wed, 2016-06-01 at 11:23 +0300, Heikki Krogerus wrote:
> I think we can still add them later if they are still seen as
> necessity later on, tough I seriously doubt it. It would not be
> ideal, but adding an attribute should not really break anything,
> right? Removing would.

However, how do we learn that the other side has triggered a reset?

	Regards
		Oliver

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [RFC PATCHv2] usb: USB Type-C Connector Class
  2016-05-19 12:44 [RFC PATCHv2] usb: USB Type-C Connector Class Heikki Krogerus
                   ` (8 preceding siblings ...)
  2016-05-30 13:19 ` [RFC PATCHv2] usb: USB Type-C Connector Class Heikki Krogerus
@ 2016-06-01  9:26 ` Oliver Neukum
  2016-06-01 23:29   ` Guenter Roeck
  2016-06-02  8:02   ` Heikki Krogerus
  2016-06-03 20:20 ` Pavel Machek
                   ` (2 subsequent siblings)
  12 siblings, 2 replies; 98+ messages in thread
From: Oliver Neukum @ 2016-06-01  9:26 UTC (permalink / raw)
  To: Heikki Krogerus
  Cc: Guenter Roeck, Andy Shevchenko, Rajaram R, Felipe Balbi,
	Mathias Nyman, Greg KH, linux-kernel, linux-usb

On Thu, 2016-05-19 at 15:44 +0300, Heikki Krogerus wrote:
> Just noticed that the "active" file is for now read only, but it needs
> to be changed to writable. That file will of course provide means for
> the userspace to Exit and Enter modes. But please note that the
> responsibility of the dependencies between the modes, say, if a plug
> needs to be in one mode or the other in order for the partner to enter
> some specific mode, will fall on the Alternate Mode specific drivers
> once we have the altmode bus. I remember there were concerns about
> this in the original thread.

There's one thing we haven't touched upon yet. And I cannot really find
an answer in the spec.

What do we do if we return from S4 or S3? I think we need to restore
the ALternate Mode because our display may be running over that
Alternate Mode.
If we want to support USB persist we also need to restore data role
after S4.

	Regards
		Oliver

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [RFC PATCHv2] usb: USB Type-C Connector Class
  2016-06-01  9:04                 ` Oliver Neukum
@ 2016-06-01 13:34                   ` Guenter Roeck
  2016-06-02  6:24                     ` Oliver Neukum
  0 siblings, 1 reply; 98+ messages in thread
From: Guenter Roeck @ 2016-06-01 13:34 UTC (permalink / raw)
  To: Oliver Neukum, Heikki Krogerus
  Cc: Andy Shevchenko, Rajaram R, Felipe Balbi, Mathias Nyman, Greg KH,
	linux-kernel, linux-usb

On 06/01/2016 02:04 AM, Oliver Neukum wrote:
> On Wed, 2016-06-01 at 11:23 +0300, Heikki Krogerus wrote:
>> I think we can still add them later if they are still seen as
>> necessity later on, tough I seriously doubt it. It would not be
>> ideal, but adding an attribute should not really break anything,
>> right? Removing would.
>
> However, how do we learn that the other side has triggered a reset?
>

USB PD specification, section 6.8.2.2 (Modal Operation and Hard Reset):

A Hard Reset shall cause all Active Modes to be exited by both Port Partners
and any Cable Plugs (see Section 6.4.4.3.4).

Section 6.4.4.3.4 (Enter Mode Command):

The following events shall also cause the Port Partners and Cable Plug(s) to exit all Active Modes:
- A PD Hard Reset
- The Port Partners or Cable Plug(s) are Detached
- A Cable Reset (only exits the Cable Plug’s Active Modes)

The class code would not explicitly learn about the reset,
but it would be informed about the exited modes.

Guenter

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [RFC PATCHv2] usb: USB Type-C Connector Class
  2016-06-01  9:26 ` Oliver Neukum
@ 2016-06-01 23:29   ` Guenter Roeck
  2016-06-02  6:30     ` Oliver Neukum
  2016-06-02 10:18     ` Heikki Krogerus
  2016-06-02  8:02   ` Heikki Krogerus
  1 sibling, 2 replies; 98+ messages in thread
From: Guenter Roeck @ 2016-06-01 23:29 UTC (permalink / raw)
  To: Oliver Neukum
  Cc: Heikki Krogerus, Andy Shevchenko, Rajaram R, Felipe Balbi,
	Mathias Nyman, Greg KH, linux-kernel, linux-usb

On Wed, Jun 01, 2016 at 11:26:09AM +0200, Oliver Neukum wrote:
> On Thu, 2016-05-19 at 15:44 +0300, Heikki Krogerus wrote:
> > Just noticed that the "active" file is for now read only, but it needs
> > to be changed to writable. That file will of course provide means for
> > the userspace to Exit and Enter modes. But please note that the
> > responsibility of the dependencies between the modes, say, if a plug
> > needs to be in one mode or the other in order for the partner to enter
> > some specific mode, will fall on the Alternate Mode specific drivers
> > once we have the altmode bus. I remember there were concerns about
> > this in the original thread.
> 
> There's one thing we haven't touched upon yet. And I cannot really find
> an answer in the spec.
> 
> What do we do if we return from S4 or S3? I think we need to restore
> the ALternate Mode because our display may be running over that
> Alternate Mode.
> If we want to support USB persist we also need to restore data role
> after S4.
> 
I don't have an answer ... but another interesting question.

How do we distinguish between alternate modes supported by a host vs.
alternate modes supported by a sink ? typec_capability includes a pointer
to alternate modes supportedf by the connector, but it is not clear if
those are alternate modes supported as host, or alternate modes supported
as device, or alternate modes supported by both.

This doesn't matter much if only a fixed role is supported, but it does matter
for dual role ports. A laptop will typically only support DisplayPort as host,
for example.

Any idea ?

Thanks,
Guenter

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [RFC PATCHv2] usb: USB Type-C Connector Class
  2016-06-01 13:34                   ` Guenter Roeck
@ 2016-06-02  6:24                     ` Oliver Neukum
  2016-06-02  6:37                       ` Guenter Roeck
  0 siblings, 1 reply; 98+ messages in thread
From: Oliver Neukum @ 2016-06-02  6:24 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Heikki Krogerus, Andy Shevchenko, Rajaram R, Felipe Balbi,
	Mathias Nyman, Greg KH, linux-kernel, linux-usb

On Wed, 2016-06-01 at 06:34 -0700, Guenter Roeck wrote:
> The class code would not explicitly learn about the reset,
> but it would be informed about the exited modes.

That has drawbacks

- it doesn't tell you what caused the mode to be left (if you
  UFP, it may be the regular command)
- it is a race against your own command
- it does not work if you are in basic USB mode

	Regards
		Oliver

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [RFC PATCHv2] usb: USB Type-C Connector Class
  2016-06-01 23:29   ` Guenter Roeck
@ 2016-06-02  6:30     ` Oliver Neukum
  2016-06-02  8:27       ` Heikki Krogerus
  2016-06-02 10:18     ` Heikki Krogerus
  1 sibling, 1 reply; 98+ messages in thread
From: Oliver Neukum @ 2016-06-02  6:30 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Andy Shevchenko, Rajaram R, Felipe Balbi, Heikki Krogerus,
	Mathias Nyman, Greg KH, linux-kernel, linux-usb

On Wed, 2016-06-01 at 16:29 -0700, Guenter Roeck wrote:
> On Wed, Jun 01, 2016 at 11:26:09AM +0200, Oliver Neukum wrote:
> > On Thu, 2016-05-19 at 15:44 +0300, Heikki Krogerus wrote:
> > > Just noticed that the "active" file is for now read only, but it needs
> > > to be changed to writable. That file will of course provide means for
> > > the userspace to Exit and Enter modes. But please note that the
> > > responsibility of the dependencies between the modes, say, if a plug
> > > needs to be in one mode or the other in order for the partner to enter
> > > some specific mode, will fall on the Alternate Mode specific drivers
> > > once we have the altmode bus. I remember there were concerns about
> > > this in the original thread.
> > 
> > There's one thing we haven't touched upon yet. And I cannot really find
> > an answer in the spec.
> > 
> > What do we do if we return from S4 or S3? I think we need to restore
> > the ALternate Mode because our display may be running over that
> > Alternate Mode.
> > If we want to support USB persist we also need to restore data role
> > after S4.
> > 
> I don't have an answer ... but another interesting question.
> 
> How do we distinguish between alternate modes supported by a host vs.
> alternate modes supported by a sink ? typec_capability includes a pointer
> to alternate modes supportedf by the connector, but it is not clear if
> those are alternate modes supported as host, or alternate modes supported
> as device, or alternate modes supported by both.

I was under the impression that this applies to the current role.

> This doesn't matter much if only a fixed role is supported, but it does matter
> for dual role ports. A laptop will typically only support DisplayPort as host,
> for example.
> 
> Any idea ?

I would state the obvious that we need separate directories for that.
And how do we express captive cables?

	Regards
		Oliver

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [RFC PATCHv2] usb: USB Type-C Connector Class
  2016-06-02  6:24                     ` Oliver Neukum
@ 2016-06-02  6:37                       ` Guenter Roeck
  2016-06-02  7:43                         ` Oliver Neukum
  0 siblings, 1 reply; 98+ messages in thread
From: Guenter Roeck @ 2016-06-02  6:37 UTC (permalink / raw)
  To: Oliver Neukum
  Cc: Heikki Krogerus, Andy Shevchenko, Rajaram R, Felipe Balbi,
	Mathias Nyman, Greg KH, linux-kernel, linux-usb

On 06/01/2016 11:24 PM, Oliver Neukum wrote:
> On Wed, 2016-06-01 at 06:34 -0700, Guenter Roeck wrote:
>> The class code would not explicitly learn about the reset,
>> but it would be informed about the exited modes.
>
> That has drawbacks
>

Playing devils advocate a bit here

> - it doesn't tell you what caused the mode to be left (if you
>    UFP, it may be the regular command)

Does it matter ?

> - it is a race against your own command

It is my understanding that races have to be resolved by the drivers,
since the typec code does not do any locking. This is quite similar
to handling, say, a request to change the vconn source or to change
the power role. Am I missing something ?

> - it does not work if you are in basic USB mode
>
Would alternate modes be active in that case ?

Thanks,
Guenter

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [RFC PATCHv2] usb: USB Type-C Connector Class
  2016-06-02  6:37                       ` Guenter Roeck
@ 2016-06-02  7:43                         ` Oliver Neukum
  0 siblings, 0 replies; 98+ messages in thread
From: Oliver Neukum @ 2016-06-02  7:43 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Andy Shevchenko, Rajaram R, Felipe Balbi, Heikki Krogerus,
	Mathias Nyman, Greg KH, linux-kernel, linux-usb

On Wed, 2016-06-01 at 23:37 -0700, Guenter Roeck wrote:
> On 06/01/2016 11:24 PM, Oliver Neukum wrote:
> > On Wed, 2016-06-01 at 06:34 -0700, Guenter Roeck wrote:
> >> The class code would not explicitly learn about the reset,
> >> but it would be informed about the exited modes.
> >
> > That has drawbacks
> >
> 
> Playing devils advocate a bit here
> 
> > - it doesn't tell you what caused the mode to be left (if you
> >    UFP, it may be the regular command)
> 
> Does it matter ?

Potentially yes. Should you restore the last state when the mode
is reentered? If it caused the other side to reset, probably not.

> > - it is a race against your own command
> 
> It is my understanding that races have to be resolved by the drivers,
> since the typec code does not do any locking. This is quite similar
> to handling, say, a request to change the vconn source or to change
> the power role. Am I missing something ?

Yes. There is a fundamental race between Exit Mode and reset if you
only report leaving a mode. Drivers can do nothing to prevent it
unless reporting resets by themselves.

> > - it does not work if you are in basic USB mode
> >
> Would alternate modes be active in that case ?

No and that is the point. A reset happens, presumably because the
other side saw an error condition and we just blindly continue
because no Alternate Mode was left and our user space remains
uninformed.

	Regards
		Oliver

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [RFC PATCHv2] usb: USB Type-C Connector Class
  2016-06-01  9:26 ` Oliver Neukum
  2016-06-01 23:29   ` Guenter Roeck
@ 2016-06-02  8:02   ` Heikki Krogerus
  1 sibling, 0 replies; 98+ messages in thread
From: Heikki Krogerus @ 2016-06-02  8:02 UTC (permalink / raw)
  To: Oliver Neukum
  Cc: Guenter Roeck, Andy Shevchenko, Rajaram R, Felipe Balbi,
	Mathias Nyman, Greg KH, linux-kernel, linux-usb

On Wed, Jun 01, 2016 at 11:26:09AM +0200, Oliver Neukum wrote:
> On Thu, 2016-05-19 at 15:44 +0300, Heikki Krogerus wrote:
> > Just noticed that the "active" file is for now read only, but it needs
> > to be changed to writable. That file will of course provide means for
> > the userspace to Exit and Enter modes. But please note that the
> > responsibility of the dependencies between the modes, say, if a plug
> > needs to be in one mode or the other in order for the partner to enter
> > some specific mode, will fall on the Alternate Mode specific drivers
> > once we have the altmode bus. I remember there were concerns about
> > this in the original thread.
> 
> There's one thing we haven't touched upon yet. And I cannot really find
> an answer in the spec.
> 
> What do we do if we return from S4 or S3? I think we need to restore
> the ALternate Mode because our display may be running over that
> Alternate Mode.
> If we want to support USB persist we also need to restore data role
> after S4.

It would make sense.. What are all the things we need to consider with
that? An example, how do we know if the attached device has changed,
etc.

I'll try to put somekind of suspend and resume hooks to the API, but
this needs some thinking.

Does this have an effect on the interface, meaning would this be
something we could potentially add later? We need to document the
expected behaviour from the beginning, i.e. the roles and the modes
should be restored when resuming, in any case I think.


Thanks,

-- 
heikki

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [RFC PATCHv2] usb: USB Type-C Connector Class
  2016-06-02  6:30     ` Oliver Neukum
@ 2016-06-02  8:27       ` Heikki Krogerus
  0 siblings, 0 replies; 98+ messages in thread
From: Heikki Krogerus @ 2016-06-02  8:27 UTC (permalink / raw)
  To: Oliver Neukum
  Cc: Guenter Roeck, Andy Shevchenko, Rajaram R, Felipe Balbi,
	Mathias Nyman, Greg KH, linux-kernel, linux-usb

On Thu, Jun 02, 2016 at 08:30:57AM +0200, Oliver Neukum wrote:
> On Wed, 2016-06-01 at 16:29 -0700, Guenter Roeck wrote:
> > On Wed, Jun 01, 2016 at 11:26:09AM +0200, Oliver Neukum wrote:
> > > On Thu, 2016-05-19 at 15:44 +0300, Heikki Krogerus wrote:
> > > > Just noticed that the "active" file is for now read only, but it needs
> > > > to be changed to writable. That file will of course provide means for
> > > > the userspace to Exit and Enter modes. But please note that the
> > > > responsibility of the dependencies between the modes, say, if a plug
> > > > needs to be in one mode or the other in order for the partner to enter
> > > > some specific mode, will fall on the Alternate Mode specific drivers
> > > > once we have the altmode bus. I remember there were concerns about
> > > > this in the original thread.
> > > 
> > > There's one thing we haven't touched upon yet. And I cannot really find
> > > an answer in the spec.
> > > 
> > > What do we do if we return from S4 or S3? I think we need to restore
> > > the ALternate Mode because our display may be running over that
> > > Alternate Mode.
> > > If we want to support USB persist we also need to restore data role
> > > after S4.
> > > 
> > I don't have an answer ... but another interesting question.
> > 
> > How do we distinguish between alternate modes supported by a host vs.
> > alternate modes supported by a sink ? typec_capability includes a pointer
> > to alternate modes supportedf by the connector, but it is not clear if
> > those are alternate modes supported as host, or alternate modes supported
> > as device, or alternate modes supported by both.
> 
> I was under the impression that this applies to the current role.
> 
> > This doesn't matter much if only a fixed role is supported, but it does matter
> > for dual role ports. A laptop will typically only support DisplayPort as host,
> > for example.
> > 
> > Any idea ?
> 
> I would state the obvious that we need separate directories for that.
> And how do we express captive cables?

That means we can not present the alternate modes the ports support as
devices, as then we would have potentially two devices presenting the
same mode. Wish we could make those symlinks.. But perhaps we don't
need to present the port alternate modes as devices in any case.

But there is an other problem. The alternate modes a port can
support as host or device may be defined by the platform, but it can
also be dictated by the alternate mode spec itself. Knowing about the
platform is a problem for the port driver, but knowing about the
individual alternate modes is not. Those will be problems for the
alternate mode drivers in the end.

So the moment a port driver is expected to create the attributes (or
populate the devices) that will present the alternate modes it
supports, this thing will not always be clear to it.

I'm now wondering should we make it responsibility for the port
drivers to generate those attributes that present the alternate modes
they support after all?


Thanks,

-- 
heikki

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [RFC PATCHv2] usb: USB Type-C Connector Class
  2016-06-01 23:29   ` Guenter Roeck
  2016-06-02  6:30     ` Oliver Neukum
@ 2016-06-02 10:18     ` Heikki Krogerus
  2016-06-02 16:12       ` Guenter Roeck
  1 sibling, 1 reply; 98+ messages in thread
From: Heikki Krogerus @ 2016-06-02 10:18 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Oliver Neukum, Andy Shevchenko, Rajaram R, Felipe Balbi,
	Mathias Nyman, Greg KH, linux-kernel, linux-usb

On Wed, Jun 01, 2016 at 04:29:26PM -0700, Guenter Roeck wrote:
> On Wed, Jun 01, 2016 at 11:26:09AM +0200, Oliver Neukum wrote:
> > On Thu, 2016-05-19 at 15:44 +0300, Heikki Krogerus wrote:
> > > Just noticed that the "active" file is for now read only, but it needs
> > > to be changed to writable. That file will of course provide means for
> > > the userspace to Exit and Enter modes. But please note that the
> > > responsibility of the dependencies between the modes, say, if a plug
> > > needs to be in one mode or the other in order for the partner to enter
> > > some specific mode, will fall on the Alternate Mode specific drivers
> > > once we have the altmode bus. I remember there were concerns about
> > > this in the original thread.
> > 
> > There's one thing we haven't touched upon yet. And I cannot really find
> > an answer in the spec.
> > 
> > What do we do if we return from S4 or S3? I think we need to restore
> > the ALternate Mode because our display may be running over that
> > Alternate Mode.
> > If we want to support USB persist we also need to restore data role
> > after S4.
> > 
> I don't have an answer ... but another interesting question.
> 
> How do we distinguish between alternate modes supported by a host vs.
> alternate modes supported by a sink ? typec_capability includes a pointer
> to alternate modes supportedf by the connector, but it is not clear if
> those are alternate modes supported as host, or alternate modes supported
> as device, or alternate modes supported by both.
> 
> This doesn't matter much if only a fixed role is supported, but it does matter
> for dual role ports. A laptop will typically only support DisplayPort as host,
> for example.

The DP alternate mode spec actually separates the display role from
Type-C role. A laptop most likely would only support the modes for
display host roles, but if the port was DRP port then it would still
do so in both Type-C roles.

So basically, even if the display was Type-C host, it would still work
as a display when attached to the laptop.

> Any idea ?

I'm actually not sure this is a problem.


Thanks,

-- 
heikki

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [RFC PATCHv2] usb: USB Type-C Connector Class
  2016-06-02 10:18     ` Heikki Krogerus
@ 2016-06-02 16:12       ` Guenter Roeck
  2016-06-03 13:21         ` Heikki Krogerus
  0 siblings, 1 reply; 98+ messages in thread
From: Guenter Roeck @ 2016-06-02 16:12 UTC (permalink / raw)
  To: Heikki Krogerus
  Cc: Oliver Neukum, Andy Shevchenko, Rajaram R, Felipe Balbi,
	Mathias Nyman, Greg KH, linux-kernel, linux-usb

On Thu, Jun 02, 2016 at 01:18:53PM +0300, Heikki Krogerus wrote:
> On Wed, Jun 01, 2016 at 04:29:26PM -0700, Guenter Roeck wrote:
> > On Wed, Jun 01, 2016 at 11:26:09AM +0200, Oliver Neukum wrote:
> > > On Thu, 2016-05-19 at 15:44 +0300, Heikki Krogerus wrote:
> > > > Just noticed that the "active" file is for now read only, but it needs
> > > > to be changed to writable. That file will of course provide means for
> > > > the userspace to Exit and Enter modes. But please note that the
> > > > responsibility of the dependencies between the modes, say, if a plug
> > > > needs to be in one mode or the other in order for the partner to enter
> > > > some specific mode, will fall on the Alternate Mode specific drivers
> > > > once we have the altmode bus. I remember there were concerns about
> > > > this in the original thread.
> > > 
> > > There's one thing we haven't touched upon yet. And I cannot really find
> > > an answer in the spec.
> > > 
> > > What do we do if we return from S4 or S3? I think we need to restore
> > > the ALternate Mode because our display may be running over that
> > > Alternate Mode.
> > > If we want to support USB persist we also need to restore data role
> > > after S4.
> > > 
> > I don't have an answer ... but another interesting question.
> > 
> > How do we distinguish between alternate modes supported by a host vs.
> > alternate modes supported by a sink ? typec_capability includes a pointer
> > to alternate modes supportedf by the connector, but it is not clear if
> > those are alternate modes supported as host, or alternate modes supported
> > as device, or alternate modes supported by both.
> > 
> > This doesn't matter much if only a fixed role is supported, but it does matter
> > for dual role ports. A laptop will typically only support DisplayPort as host,
> > for example.
> 
> The DP alternate mode spec actually separates the display role from
> Type-C role. A laptop most likely would only support the modes for
> display host roles, but if the port was DRP port then it would still
> do so in both Type-C roles.
> 
> So basically, even if the display was Type-C host, it would still work
> as a display when attached to the laptop.
> 
> > Any idea ?
> 
> I'm actually not sure this is a problem.
> 
Yes, this was a bad example, since the DisplayPort mode vdo includes a flag
indicating if the port supports source, sink, or both.

Let's use a different example:
Google devices (such as power adapters) have mode '1' for firmware upgrades.
Obviously hosts will support that, but what should the host advertise if it
is configured as sink ?

Maybe this is just my personal confusion, and there is no real problem.
It might as well be that the Google mode VDO _should_ include a flag
indicating if the port supports updating the partner, and/or if it supports
being updated. For now I'll just assume that this is the case.

Something else, which goes back into the symlink question. If I create the
alternate mode devices before calling typec_register_port(), the devices won't
have a parent and don't show up in the class directory. You previously solved
that with the symlink. I am trying to solve it in my current code by calling
typec_register_altmodes() from typec_register_port() - primarily because I
don't really want to duplicate all the device creation code in my driver.

In my test case, this gives me
    /sys/class/type-c/usbc0/
	usbc0.svid:18d1
	usbc0.svid:18d1/mode0
	usbc0.svid:18d1/mode0/vdo
	usbc0.svid:18d1/mode0/description
	usbc0.svid:18d1/mode0/active
	...
	usbc0.svid:ff01
	usbc0.svid:ff01/mode0/vdo
	usbc0.svid:ff01/mode0/description
	usbc0.svid:ff01/mode0/active

in addition to
    /sys/class/type-c/usbc0/
	usbc0-partner/usbc0-partner.svid:05ac
	usbc0-partner/usbc0-partner.svid:05ac/mode0
	usbc0-partner/usbc0-partner.svid:05ac/mode0/vdo
	usbc0-partner/usbc0-partner.svid:05ac/mode0/description
	usbc0-partner/usbc0-partner.svid:05ac/mode0/active
	usbc0-partner/usbc0-partner.svid:05ac/mode1
	usbc0-partner/usbc0-partner.svid:05ac/mode1/vdo
	usbc0-partner/usbc0-partner.svid:05ac/mode1/description
	usbc0-partner/usbc0-partner.svid:05ac/mode1/active
	...
	usbc0-partner/usbc0-partner.svid:ff01
	usbc0-partner/usbc0-partner.svid:ff01/mode0
	usbc0-partner/usbc0-partner.svid:ff01/mode0/vdo
	usbc0-partner/usbc0-partner.svid:ff01/mode0/description
	usbc0-partner/usbc0-partner.svid:ff01/mode0/active

(when connecting the Apple adapter), which is exactly what I would expect to see.

Is this sensible ? Do we have a reason for expecting the alternate mode
_devices_ to be created (without parent) when calling typec_register_port() ?

Thanks,
Guenter

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [RFC PATCHv2] usb: USB Type-C Connector Class
  2016-06-02 16:12       ` Guenter Roeck
@ 2016-06-03 13:21         ` Heikki Krogerus
  2016-06-03 13:51           ` Guenter Roeck
  0 siblings, 1 reply; 98+ messages in thread
From: Heikki Krogerus @ 2016-06-03 13:21 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Oliver Neukum, Andy Shevchenko, Rajaram R, Felipe Balbi,
	Mathias Nyman, Greg KH, linux-kernel, linux-usb

Hi,

On Thu, Jun 02, 2016 at 09:12:19AM -0700, Guenter Roeck wrote:
> On Thu, Jun 02, 2016 at 01:18:53PM +0300, Heikki Krogerus wrote:
> > On Wed, Jun 01, 2016 at 04:29:26PM -0700, Guenter Roeck wrote:
> > > On Wed, Jun 01, 2016 at 11:26:09AM +0200, Oliver Neukum wrote:
> > > > On Thu, 2016-05-19 at 15:44 +0300, Heikki Krogerus wrote:
> > > > > Just noticed that the "active" file is for now read only, but it needs
> > > > > to be changed to writable. That file will of course provide means for
> > > > > the userspace to Exit and Enter modes. But please note that the
> > > > > responsibility of the dependencies between the modes, say, if a plug
> > > > > needs to be in one mode or the other in order for the partner to enter
> > > > > some specific mode, will fall on the Alternate Mode specific drivers
> > > > > once we have the altmode bus. I remember there were concerns about
> > > > > this in the original thread.
> > > > 
> > > > There's one thing we haven't touched upon yet. And I cannot really find
> > > > an answer in the spec.
> > > > 
> > > > What do we do if we return from S4 or S3? I think we need to restore
> > > > the ALternate Mode because our display may be running over that
> > > > Alternate Mode.
> > > > If we want to support USB persist we also need to restore data role
> > > > after S4.
> > > > 
> > > I don't have an answer ... but another interesting question.
> > > 
> > > How do we distinguish between alternate modes supported by a host vs.
> > > alternate modes supported by a sink ? typec_capability includes a pointer
> > > to alternate modes supportedf by the connector, but it is not clear if
> > > those are alternate modes supported as host, or alternate modes supported
> > > as device, or alternate modes supported by both.
> > > 
> > > This doesn't matter much if only a fixed role is supported, but it does matter
> > > for dual role ports. A laptop will typically only support DisplayPort as host,
> > > for example.
> > 
> > The DP alternate mode spec actually separates the display role from
> > Type-C role. A laptop most likely would only support the modes for
> > display host roles, but if the port was DRP port then it would still
> > do so in both Type-C roles.
> > 
> > So basically, even if the display was Type-C host, it would still work
> > as a display when attached to the laptop.
> > 
> > > Any idea ?
> > 
> > I'm actually not sure this is a problem.
> > 
> Yes, this was a bad example, since the DisplayPort mode vdo includes a flag
> indicating if the port supports source, sink, or both.

I meant that in case of DP alternate mode, there should not be a
problem.

> Let's use a different example:
> Google devices (such as power adapters) have mode '1' for firmware upgrades.
> Obviously hosts will support that, but what should the host advertise if it
> is configured as sink ?
> 
> Maybe this is just my personal confusion, and there is no real problem.
> It might as well be that the Google mode VDO _should_ include a flag
> indicating if the port supports updating the partner, and/or if it supports
> being updated. For now I'll just assume that this is the case.

Well, do you think we can rely on always being able to get this detail
from VDO?

> Something else, which goes back into the symlink question. If I create the
> alternate mode devices before calling typec_register_port(), the devices won't
> have a parent and don't show up in the class directory. You previously solved
> that with the symlink. I am trying to solve it in my current code by calling
> typec_register_altmodes() from typec_register_port() - primarily because I
> don't really want to duplicate all the device creation code in my driver.
> 
> In my test case, this gives me
>     /sys/class/type-c/usbc0/
> 	usbc0.svid:18d1
> 	usbc0.svid:18d1/mode0
> 	usbc0.svid:18d1/mode0/vdo
> 	usbc0.svid:18d1/mode0/description
> 	usbc0.svid:18d1/mode0/active
> 	...
> 	usbc0.svid:ff01
> 	usbc0.svid:ff01/mode0/vdo
> 	usbc0.svid:ff01/mode0/description
> 	usbc0.svid:ff01/mode0/active
> 
> in addition to
>     /sys/class/type-c/usbc0/
> 	usbc0-partner/usbc0-partner.svid:05ac
> 	usbc0-partner/usbc0-partner.svid:05ac/mode0
> 	usbc0-partner/usbc0-partner.svid:05ac/mode0/vdo
> 	usbc0-partner/usbc0-partner.svid:05ac/mode0/description
> 	usbc0-partner/usbc0-partner.svid:05ac/mode0/active
> 	usbc0-partner/usbc0-partner.svid:05ac/mode1
> 	usbc0-partner/usbc0-partner.svid:05ac/mode1/vdo
> 	usbc0-partner/usbc0-partner.svid:05ac/mode1/description
> 	usbc0-partner/usbc0-partner.svid:05ac/mode1/active
> 	...
> 	usbc0-partner/usbc0-partner.svid:ff01
> 	usbc0-partner/usbc0-partner.svid:ff01/mode0
> 	usbc0-partner/usbc0-partner.svid:ff01/mode0/vdo
> 	usbc0-partner/usbc0-partner.svid:ff01/mode0/description
> 	usbc0-partner/usbc0-partner.svid:ff01/mode0/active
> 
> (when connecting the Apple adapter), which is exactly what I would expect to see.
> 
> Is this sensible ? Do we have a reason for expecting the alternate mode
> _devices_ to be created (without parent) when calling typec_register_port() ?

So if you would prefer that the class code takes care of creating the
alternate modes when typec_register_port() is called, I'm fine with
that too. Let's make it so.


Thanks,

-- 
heikki

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [RFC PATCHv2] usb: USB Type-C Connector Class
  2016-06-03 13:21         ` Heikki Krogerus
@ 2016-06-03 13:51           ` Guenter Roeck
  2016-06-03 15:17             ` Heikki Krogerus
  0 siblings, 1 reply; 98+ messages in thread
From: Guenter Roeck @ 2016-06-03 13:51 UTC (permalink / raw)
  To: Heikki Krogerus
  Cc: Oliver Neukum, Andy Shevchenko, Rajaram R, Felipe Balbi,
	Mathias Nyman, Greg KH, linux-kernel, linux-usb

On 06/03/2016 06:21 AM, Heikki Krogerus wrote:
> Hi,
>
> On Thu, Jun 02, 2016 at 09:12:19AM -0700, Guenter Roeck wrote:
>> On Thu, Jun 02, 2016 at 01:18:53PM +0300, Heikki Krogerus wrote:
>>> On Wed, Jun 01, 2016 at 04:29:26PM -0700, Guenter Roeck wrote:
>>>> On Wed, Jun 01, 2016 at 11:26:09AM +0200, Oliver Neukum wrote:
>>>>> On Thu, 2016-05-19 at 15:44 +0300, Heikki Krogerus wrote:
>>>>>> Just noticed that the "active" file is for now read only, but it needs
>>>>>> to be changed to writable. That file will of course provide means for
>>>>>> the userspace to Exit and Enter modes. But please note that the
>>>>>> responsibility of the dependencies between the modes, say, if a plug
>>>>>> needs to be in one mode or the other in order for the partner to enter
>>>>>> some specific mode, will fall on the Alternate Mode specific drivers
>>>>>> once we have the altmode bus. I remember there were concerns about
>>>>>> this in the original thread.
>>>>>
>>>>> There's one thing we haven't touched upon yet. And I cannot really find
>>>>> an answer in the spec.
>>>>>
>>>>> What do we do if we return from S4 or S3? I think we need to restore
>>>>> the ALternate Mode because our display may be running over that
>>>>> Alternate Mode.
>>>>> If we want to support USB persist we also need to restore data role
>>>>> after S4.
>>>>>
>>>> I don't have an answer ... but another interesting question.
>>>>
>>>> How do we distinguish between alternate modes supported by a host vs.
>>>> alternate modes supported by a sink ? typec_capability includes a pointer
>>>> to alternate modes supportedf by the connector, but it is not clear if
>>>> those are alternate modes supported as host, or alternate modes supported
>>>> as device, or alternate modes supported by both.
>>>>
>>>> This doesn't matter much if only a fixed role is supported, but it does matter
>>>> for dual role ports. A laptop will typically only support DisplayPort as host,
>>>> for example.
>>>
>>> The DP alternate mode spec actually separates the display role from
>>> Type-C role. A laptop most likely would only support the modes for
>>> display host roles, but if the port was DRP port then it would still
>>> do so in both Type-C roles.
>>>
>>> So basically, even if the display was Type-C host, it would still work
>>> as a display when attached to the laptop.
>>>
>>>> Any idea ?
>>>
>>> I'm actually not sure this is a problem.
>>>
>> Yes, this was a bad example, since the DisplayPort mode vdo includes a flag
>> indicating if the port supports source, sink, or both.
>
> I meant that in case of DP alternate mode, there should not be a
> problem.
>
>> Let's use a different example:
>> Google devices (such as power adapters) have mode '1' for firmware upgrades.
>> Obviously hosts will support that, but what should the host advertise if it
>> is configured as sink ?
>>
>> Maybe this is just my personal confusion, and there is no real problem.
>> It might as well be that the Google mode VDO _should_ include a flag
>> indicating if the port supports updating the partner, and/or if it supports
>> being updated. For now I'll just assume that this is the case.
>
> Well, do you think we can rely on always being able to get this detail
> from VDO?
>

Not really. Like in the Google case, one end will implement sending the firmware,
the other end will implement receiving it and writing it to flash (or whatever).
Which is which isn't currently made visible to user space. I suspect that
other "intelligent" devices like Apple's multi-function adapter do the same,
though obviously I don't really know what the two VDO modes do on the apple
adapter.

I'll have to have some ABI to user space for the alternate mode, for example
to send the firmware file to the kernel. I am not there yet, though, so I
don't really know exactly how that will look like. Most likely it is going to be
added sysfs attributes in the mode device (eg usbc0.svid:18d1/mode0/firmware).

>> Something else, which goes back into the symlink question. If I create the
>> alternate mode devices before calling typec_register_port(), the devices won't
>> have a parent and don't show up in the class directory. You previously solved
>> that with the symlink. I am trying to solve it in my current code by calling
>> typec_register_altmodes() from typec_register_port() - primarily because I
>> don't really want to duplicate all the device creation code in my driver.
>>
>> In my test case, this gives me
>>      /sys/class/type-c/usbc0/
>> 	usbc0.svid:18d1
>> 	usbc0.svid:18d1/mode0
>> 	usbc0.svid:18d1/mode0/vdo
>> 	usbc0.svid:18d1/mode0/description
>> 	usbc0.svid:18d1/mode0/active
>> 	...
>> 	usbc0.svid:ff01
>> 	usbc0.svid:ff01/mode0/vdo
>> 	usbc0.svid:ff01/mode0/description
>> 	usbc0.svid:ff01/mode0/active

Side note: I didn't provide a description/name for the modes, because that
would result in something like usbc0.DisplayPort/ instead of usbc0.svid:ff01/,
and I prefer a consistent ABI. Since this _is_ part of the ABI, would it make
sense to standardize on names for modes in sysfs ? For example, how should
a "Display Port" mode directory be named ? It doesn't sound good if I
use "usbc0.svid:ff01", someone else uses "usbc0.DisplayPort", and yet
someone else uses "usbc0.displayport".

Also, do we at some point need to standardize the ABI for the standard
alternate modes such as DisplayPort (if there are any - again I am not
there yet) ?

>>
>> in addition to
>>      /sys/class/type-c/usbc0/
>> 	usbc0-partner/usbc0-partner.svid:05ac
>> 	usbc0-partner/usbc0-partner.svid:05ac/mode0
>> 	usbc0-partner/usbc0-partner.svid:05ac/mode0/vdo
>> 	usbc0-partner/usbc0-partner.svid:05ac/mode0/description
>> 	usbc0-partner/usbc0-partner.svid:05ac/mode0/active
>> 	usbc0-partner/usbc0-partner.svid:05ac/mode1
>> 	usbc0-partner/usbc0-partner.svid:05ac/mode1/vdo
>> 	usbc0-partner/usbc0-partner.svid:05ac/mode1/description
>> 	usbc0-partner/usbc0-partner.svid:05ac/mode1/active
>> 	...
>> 	usbc0-partner/usbc0-partner.svid:ff01
>> 	usbc0-partner/usbc0-partner.svid:ff01/mode0
>> 	usbc0-partner/usbc0-partner.svid:ff01/mode0/vdo
>> 	usbc0-partner/usbc0-partner.svid:ff01/mode0/description
>> 	usbc0-partner/usbc0-partner.svid:ff01/mode0/active
>>
>> (when connecting the Apple adapter), which is exactly what I would expect to see.
>>
>> Is this sensible ? Do we have a reason for expecting the alternate mode
>> _devices_ to be created (without parent) when calling typec_register_port() ?
>
> So if you would prefer that the class code takes care of creating the
> alternate modes when typec_register_port() is called, I'm fine with
> that too. Let's make it so.
>

Sounds good to me. Many other subsystems do the same, ie create the subsystem
device(s) during registration with the subsystem, so this is in line with other
kernel code.

Should I send you a follow-up patch on top of yours ?

Thanks,
Guenter

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [RFC PATCHv2] usb: USB Type-C Connector Class
  2016-06-03 13:51           ` Guenter Roeck
@ 2016-06-03 15:17             ` Heikki Krogerus
  2016-06-03 18:39               ` Guenter Roeck
  0 siblings, 1 reply; 98+ messages in thread
From: Heikki Krogerus @ 2016-06-03 15:17 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Oliver Neukum, Andy Shevchenko, Rajaram R, Felipe Balbi,
	Mathias Nyman, Greg KH, linux-kernel, linux-usb

On Fri, Jun 03, 2016 at 06:51:54AM -0700, Guenter Roeck wrote:
> On 06/03/2016 06:21 AM, Heikki Krogerus wrote:
> > Hi,
> > 
> > On Thu, Jun 02, 2016 at 09:12:19AM -0700, Guenter Roeck wrote:
> > > On Thu, Jun 02, 2016 at 01:18:53PM +0300, Heikki Krogerus wrote:
> > > > On Wed, Jun 01, 2016 at 04:29:26PM -0700, Guenter Roeck wrote:
> > > > > On Wed, Jun 01, 2016 at 11:26:09AM +0200, Oliver Neukum wrote:
> > > > > > On Thu, 2016-05-19 at 15:44 +0300, Heikki Krogerus wrote:
> > > > > > > Just noticed that the "active" file is for now read only, but it needs
> > > > > > > to be changed to writable. That file will of course provide means for
> > > > > > > the userspace to Exit and Enter modes. But please note that the
> > > > > > > responsibility of the dependencies between the modes, say, if a plug
> > > > > > > needs to be in one mode or the other in order for the partner to enter
> > > > > > > some specific mode, will fall on the Alternate Mode specific drivers
> > > > > > > once we have the altmode bus. I remember there were concerns about
> > > > > > > this in the original thread.
> > > > > > 
> > > > > > There's one thing we haven't touched upon yet. And I cannot really find
> > > > > > an answer in the spec.
> > > > > > 
> > > > > > What do we do if we return from S4 or S3? I think we need to restore
> > > > > > the ALternate Mode because our display may be running over that
> > > > > > Alternate Mode.
> > > > > > If we want to support USB persist we also need to restore data role
> > > > > > after S4.
> > > > > > 
> > > > > I don't have an answer ... but another interesting question.
> > > > > 
> > > > > How do we distinguish between alternate modes supported by a host vs.
> > > > > alternate modes supported by a sink ? typec_capability includes a pointer
> > > > > to alternate modes supportedf by the connector, but it is not clear if
> > > > > those are alternate modes supported as host, or alternate modes supported
> > > > > as device, or alternate modes supported by both.
> > > > > 
> > > > > This doesn't matter much if only a fixed role is supported, but it does matter
> > > > > for dual role ports. A laptop will typically only support DisplayPort as host,
> > > > > for example.
> > > > 
> > > > The DP alternate mode spec actually separates the display role from
> > > > Type-C role. A laptop most likely would only support the modes for
> > > > display host roles, but if the port was DRP port then it would still
> > > > do so in both Type-C roles.
> > > > 
> > > > So basically, even if the display was Type-C host, it would still work
> > > > as a display when attached to the laptop.
> > > > 
> > > > > Any idea ?
> > > > 
> > > > I'm actually not sure this is a problem.
> > > > 
> > > Yes, this was a bad example, since the DisplayPort mode vdo includes a flag
> > > indicating if the port supports source, sink, or both.
> > 
> > I meant that in case of DP alternate mode, there should not be a
> > problem.
> > 
> > > Let's use a different example:
> > > Google devices (such as power adapters) have mode '1' for firmware upgrades.
> > > Obviously hosts will support that, but what should the host advertise if it
> > > is configured as sink ?
> > > 
> > > Maybe this is just my personal confusion, and there is no real problem.
> > > It might as well be that the Google mode VDO _should_ include a flag
> > > indicating if the port supports updating the partner, and/or if it supports
> > > being updated. For now I'll just assume that this is the case.
> > 
> > Well, do you think we can rely on always being able to get this detail
> > from VDO?
> > 
> 
> Not really. Like in the Google case, one end will implement sending the firmware,
> the other end will implement receiving it and writing it to flash (or whatever).
> Which is which isn't currently made visible to user space. I suspect that
> other "intelligent" devices like Apple's multi-function adapter do the same,
> though obviously I don't really know what the two VDO modes do on the apple
> adapter.
> 
> I'll have to have some ABI to user space for the alternate mode, for example
> to send the firmware file to the kernel. I am not there yet, though, so I
> don't really know exactly how that will look like. Most likely it is going to be
> added sysfs attributes in the mode device (eg usbc0.svid:18d1/mode0/firmware).
> 
> > > Something else, which goes back into the symlink question. If I create the
> > > alternate mode devices before calling typec_register_port(), the devices won't
> > > have a parent and don't show up in the class directory. You previously solved
> > > that with the symlink. I am trying to solve it in my current code by calling
> > > typec_register_altmodes() from typec_register_port() - primarily because I
> > > don't really want to duplicate all the device creation code in my driver.
> > > 
> > > In my test case, this gives me
> > >      /sys/class/type-c/usbc0/
> > > 	usbc0.svid:18d1
> > > 	usbc0.svid:18d1/mode0
> > > 	usbc0.svid:18d1/mode0/vdo
> > > 	usbc0.svid:18d1/mode0/description
> > > 	usbc0.svid:18d1/mode0/active
> > > 	...
> > > 	usbc0.svid:ff01
> > > 	usbc0.svid:ff01/mode0/vdo
> > > 	usbc0.svid:ff01/mode0/description
> > > 	usbc0.svid:ff01/mode0/active
> 
> Side note: I didn't provide a description/name for the modes, because that
> would result in something like usbc0.DisplayPort/ instead of usbc0.svid:ff01/,
> and I prefer a consistent ABI. Since this _is_ part of the ABI, would it make
> sense to standardize on names for modes in sysfs ? For example, how should
> a "Display Port" mode directory be named ? It doesn't sound good if I
> use "usbc0.svid:ff01", someone else uses "usbc0.DisplayPort", and yet
> someone else uses "usbc0.displayport".

Yeah, let's make them standard.

> 
> Also, do we at some point need to standardize the ABI for the standard
> alternate modes such as DisplayPort (if there are any - again I am not
> there yet) ?

I don't have an answer to that.

> > > 
> > > in addition to
> > >      /sys/class/type-c/usbc0/
> > > 	usbc0-partner/usbc0-partner.svid:05ac
> > > 	usbc0-partner/usbc0-partner.svid:05ac/mode0
> > > 	usbc0-partner/usbc0-partner.svid:05ac/mode0/vdo
> > > 	usbc0-partner/usbc0-partner.svid:05ac/mode0/description
> > > 	usbc0-partner/usbc0-partner.svid:05ac/mode0/active
> > > 	usbc0-partner/usbc0-partner.svid:05ac/mode1
> > > 	usbc0-partner/usbc0-partner.svid:05ac/mode1/vdo
> > > 	usbc0-partner/usbc0-partner.svid:05ac/mode1/description
> > > 	usbc0-partner/usbc0-partner.svid:05ac/mode1/active
> > > 	...
> > > 	usbc0-partner/usbc0-partner.svid:ff01
> > > 	usbc0-partner/usbc0-partner.svid:ff01/mode0
> > > 	usbc0-partner/usbc0-partner.svid:ff01/mode0/vdo
> > > 	usbc0-partner/usbc0-partner.svid:ff01/mode0/description
> > > 	usbc0-partner/usbc0-partner.svid:ff01/mode0/active
> > > 
> > > (when connecting the Apple adapter), which is exactly what I would expect to see.
> > > 
> > > Is this sensible ? Do we have a reason for expecting the alternate mode
> > > _devices_ to be created (without parent) when calling typec_register_port() ?
> > 
> > So if you would prefer that the class code takes care of creating the
> > alternate modes when typec_register_port() is called, I'm fine with
> > that too. Let's make it so.
> > 
> 
> Sounds good to me. Many other subsystems do the same, ie create the subsystem
> device(s) during registration with the subsystem, so this is in line with other
> kernel code.
> 
> Should I send you a follow-up patch on top of yours ?

Sure. I'm a little bit stuck with an other tasks, so let's keep this
thing rolling.


Thanks,

-- 
heikki

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [RFC PATCHv2] usb: USB Type-C Connector Class
  2016-06-03 15:17             ` Heikki Krogerus
@ 2016-06-03 18:39               ` Guenter Roeck
  2016-06-06 13:28                 ` Heikki Krogerus
  0 siblings, 1 reply; 98+ messages in thread
From: Guenter Roeck @ 2016-06-03 18:39 UTC (permalink / raw)
  To: Heikki Krogerus
  Cc: Oliver Neukum, Andy Shevchenko, Rajaram R, Felipe Balbi,
	Mathias Nyman, Greg KH, linux-kernel, linux-usb

On Fri, Jun 03, 2016 at 06:17:46PM +0300, Heikki Krogerus wrote:
[ ... ]
> > > > 
> > > > In my test case, this gives me
> > > >      /sys/class/type-c/usbc0/
> > > > 	usbc0.svid:18d1
> > > > 	usbc0.svid:18d1/mode0
> > > > 	usbc0.svid:18d1/mode0/vdo
> > > > 	usbc0.svid:18d1/mode0/description
> > > > 	usbc0.svid:18d1/mode0/active
> > > > 	...
> > > > 	usbc0.svid:ff01
> > > > 	usbc0.svid:ff01/mode0/vdo
> > > > 	usbc0.svid:ff01/mode0/description
> > > > 	usbc0.svid:ff01/mode0/active
> > 
> > Side note: I didn't provide a description/name for the modes, because that
> > would result in something like usbc0.DisplayPort/ instead of usbc0.svid:ff01/,
> > and I prefer a consistent ABI. Since this _is_ part of the ABI, would it make
> > sense to standardize on names for modes in sysfs ? For example, how should
> > a "Display Port" mode directory be named ? It doesn't sound good if I
> > use "usbc0.svid:ff01", someone else uses "usbc0.DisplayPort", and yet
> > someone else uses "usbc0.displayport".
> 
> Yeah, let's make them standard.
> 
Any name preferences ?

> > 
> > Also, do we at some point need to standardize the ABI for the standard
> > alternate modes such as DisplayPort (if there are any - again I am not
> > there yet) ?
> 
> I don't have an answer to that.
> 
Ok, I'll look into it as I proceed with my implementation.

> > 
> > Sounds good to me. Many other subsystems do the same, ie create the subsystem
> > device(s) during registration with the subsystem, so this is in line with other
> > kernel code.
> > 
> > Should I send you a follow-up patch on top of yours ?
> 
> Sure. I'm a little bit stuck with an other tasks, so let's keep this
> thing rolling.
> 
See below.

Thanks,
Guenter

---
>From ab1f2d0671e3cda74b80c6d17d99cb3e386c0d08 Mon Sep 17 00:00:00 2001
From: Guenter Roeck <groeck@chromium.org>
Date: Thu, 2 Jun 2016 10:09:50 -0700
Subject: [PATCH] usb: typec: Register supported alternate modes in
 typec_register_port()

By registering supported alternate modes when registering the port, we
automatically get the correct directory hierarchie in the class device.

Change-Id: I543da5f4ce922ded0532e6b0a0fdb8bc55cb5a80
Signed-off-by: Guenter Roeck <groeck@chromium.org>
---
 drivers/usb/type-c/typec.c | 21 +++++++++++++++------
 1 file changed, 15 insertions(+), 6 deletions(-)

diff --git a/drivers/usb/type-c/typec.c b/drivers/usb/type-c/typec.c
index 41ad955..22ee7eb 100644
--- a/drivers/usb/type-c/typec.c
+++ b/drivers/usb/type-c/typec.c
@@ -892,14 +892,22 @@ struct typec_port *typec_register_port(struct device *dev,
 	typec_init_roles(port);
 
 	ret = device_register(&port->dev);
-	if (ret) {
-		ida_simple_remove(&typec_index_ida, id);
-		put_device(&port->dev);
-		kfree(port);
-		return ERR_PTR(ret);
-	}
+	if (ret)
+		goto reg_err;
+
+	ret = typec_register_altmodes(&port->dev, cap->alt_modes);
+	if (ret)
+		goto alt_err;
 
 	return port;
+
+alt_err:
+	device_unregister(&port->dev);
+reg_err:
+	ida_simple_remove(&typec_index_ida, id);
+	put_device(&port->dev);
+	kfree(port);
+	return ERR_PTR(ret);
 }
 EXPORT_SYMBOL_GPL(typec_register_port);
 
@@ -908,6 +916,7 @@ void typec_unregister_port(struct typec_port *port)
 	if (port->connected)
 		typec_disconnect(port);
 
+	typec_unregister_altmodes(port->cap->alt_modes);
 	device_unregister(&port->dev);
 }
 EXPORT_SYMBOL_GPL(typec_unregister_port);
-- 
2.1.2

^ permalink raw reply related	[flat|nested] 98+ messages in thread

* Re: [RFC PATCHv2] usb: USB Type-C Connector Class
  2016-05-19 12:44 [RFC PATCHv2] usb: USB Type-C Connector Class Heikki Krogerus
                   ` (9 preceding siblings ...)
  2016-06-01  9:26 ` Oliver Neukum
@ 2016-06-03 20:20 ` Pavel Machek
  2016-06-06 13:45   ` Heikki Krogerus
  2016-06-10 14:34 ` [RFC PATCHv3] " Heikki Krogerus
  2016-06-21 13:08 ` [RFC PATCHv2] " Oliver Neukum
  12 siblings, 1 reply; 98+ messages in thread
From: Pavel Machek @ 2016-06-03 20:20 UTC (permalink / raw)
  To: Heikki Krogerus
  Cc: Guenter Roeck, Greg KH, Mathias Nyman, Felipe Balbi,
	Oliver Neukum, Rajaram R, Andy Shevchenko, linux-kernel,
	linux-usb

On Thu 2016-05-19 15:44:54, Heikki Krogerus wrote:
> The purpose of this class is to provide unified interface for user
> space to get the status and basic information about USB Type-C
> Connectors in the system, control data role swapping, and when USB PD
> is available, also power role swapping and Alternate Modes.
> 
> Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
> ---
>  drivers/usb/Kconfig         |   2 +
>  drivers/usb/Makefile        |   2 +
>  drivers/usb/type-c/Kconfig  |   7 +
>  drivers/usb/type-c/Makefile |   1 +
>  drivers/usb/type-c/typec.c  | 957 ++++++++++++++++++++++++++++++++++++++++++++

For consistency, should this be either type-c/type-c.c or
typec/typec.c?

Best regards,
								Pavel

-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [RFC PATCHv2] usb: USB Type-C Connector Class
  2016-06-03 18:39               ` Guenter Roeck
@ 2016-06-06 13:28                 ` Heikki Krogerus
  2016-06-06 13:35                   ` Oliver Neukum
  2016-06-07 16:57                   ` Guenter Roeck
  0 siblings, 2 replies; 98+ messages in thread
From: Heikki Krogerus @ 2016-06-06 13:28 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Oliver Neukum, Andy Shevchenko, Rajaram R, Felipe Balbi,
	Mathias Nyman, Greg KH, linux-kernel, linux-usb

On Fri, Jun 03, 2016 at 11:39:27AM -0700, Guenter Roeck wrote:
> On Fri, Jun 03, 2016 at 06:17:46PM +0300, Heikki Krogerus wrote:
> [ ... ]
> > > > > 
> > > > > In my test case, this gives me
> > > > >      /sys/class/type-c/usbc0/
> > > > > 	usbc0.svid:18d1
> > > > > 	usbc0.svid:18d1/mode0
> > > > > 	usbc0.svid:18d1/mode0/vdo
> > > > > 	usbc0.svid:18d1/mode0/description
> > > > > 	usbc0.svid:18d1/mode0/active
> > > > > 	...
> > > > > 	usbc0.svid:ff01
> > > > > 	usbc0.svid:ff01/mode0/vdo
> > > > > 	usbc0.svid:ff01/mode0/description
> > > > > 	usbc0.svid:ff01/mode0/active
> > > 
> > > Side note: I didn't provide a description/name for the modes, because that
> > > would result in something like usbc0.DisplayPort/ instead of usbc0.svid:ff01/,
> > > and I prefer a consistent ABI. Since this _is_ part of the ABI, would it make
> > > sense to standardize on names for modes in sysfs ? For example, how should
> > > a "Display Port" mode directory be named ? It doesn't sound good if I
> > > use "usbc0.svid:ff01", someone else uses "usbc0.DisplayPort", and yet
> > > someone else uses "usbc0.displayport".
> > 
> > Yeah, let's make them standard.
> > 
> Any name preferences ?

I would prefer lower case letters. I don't know the SIDs there are at
them moment, other then Display Port. Do you know them?

I don't think we can ever guarantee that in every case we will be able
to provide a human readable name for the alternate modes if they are
vendor defined. We will then potentially still have the names in two
different forms: "usbc0.displayport" and "usbc0.svid:xxxx". Is that
something acceptable to everybody?

I guess if it's not, then to only way to go forward would be to always
just use the svid in the name.

> > > Also, do we at some point need to standardize the ABI for the standard
> > > alternate modes such as DisplayPort (if there are any - again I am not
> > > there yet) ?
> > 
> > I don't have an answer to that.
> > 
> Ok, I'll look into it as I proceed with my implementation.
> 
> > > 
> > > Sounds good to me. Many other subsystems do the same, ie create the subsystem
> > > device(s) during registration with the subsystem, so this is in line with other
> > > kernel code.
> > > 
> > > Should I send you a follow-up patch on top of yours ?
> > 
> > Sure. I'm a little bit stuck with an other tasks, so let's keep this
> > thing rolling.
> > 
> See below.

Thanks. I pushed it to my work branch for this class:

https://github.com/krohei/linux/commits/typec_class

There are still a few open questions, but I'm in any case going to
start polishing the driver. I think the other attributes are more or
less decided, excluding the alternate modes.


Cheers,

-- 
heikki

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [RFC PATCHv2] usb: USB Type-C Connector Class
  2016-06-06 13:28                 ` Heikki Krogerus
@ 2016-06-06 13:35                   ` Oliver Neukum
  2016-06-07  8:23                     ` Heikki Krogerus
  2016-06-07 16:57                   ` Guenter Roeck
  1 sibling, 1 reply; 98+ messages in thread
From: Oliver Neukum @ 2016-06-06 13:35 UTC (permalink / raw)
  To: Heikki Krogerus
  Cc: Guenter Roeck, Andy Shevchenko, Rajaram R, Felipe Balbi,
	Mathias Nyman, Greg KH, linux-kernel, linux-usb

On Mon, 2016-06-06 at 16:28 +0300, Heikki Krogerus wrote:

> I would prefer lower case letters. I don't know the SIDs there are at
> them moment, other then Display Port. Do you know them?
> 
> I don't think we can ever guarantee that in every case we will be able
> to provide a human readable name for the alternate modes if they are
> vendor defined. We will then potentially still have the names in two
> different forms: "usbc0.displayport" and "usbc0.svid:xxxx". Is that
> something acceptable to everybody?
> 
> I guess if it's not, then to only way to go forward would be to always
> just use the svid in the name.

Yes, that is better. It makes more sense to use the number.
We'd get into versioning problems if we use names.

	Regards
		Oliver

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [RFC PATCHv2] usb: USB Type-C Connector Class
  2016-06-03 20:20 ` Pavel Machek
@ 2016-06-06 13:45   ` Heikki Krogerus
  2016-06-06 14:41     ` Greg KH
  2016-06-06 16:02     ` Guenter Roeck
  0 siblings, 2 replies; 98+ messages in thread
From: Heikki Krogerus @ 2016-06-06 13:45 UTC (permalink / raw)
  To: Pavel Machek, Guenter Roeck
  Cc: Greg KH, Mathias Nyman, Felipe Balbi, Oliver Neukum, Rajaram R,
	Andy Shevchenko, linux-kernel, linux-usb

Hi,

On Fri, Jun 03, 2016 at 10:20:01PM +0200, Pavel Machek wrote:
> On Thu 2016-05-19 15:44:54, Heikki Krogerus wrote:
> > The purpose of this class is to provide unified interface for user
> > space to get the status and basic information about USB Type-C
> > Connectors in the system, control data role swapping, and when USB PD
> > is available, also power role swapping and Alternate Modes.
> > 
> > Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
> > ---
> >  drivers/usb/Kconfig         |   2 +
> >  drivers/usb/Makefile        |   2 +
> >  drivers/usb/type-c/Kconfig  |   7 +
> >  drivers/usb/type-c/Makefile |   1 +
> >  drivers/usb/type-c/typec.c  | 957 ++++++++++++++++++++++++++++++++++++++++++++
> 
> For consistency, should this be either type-c/type-c.c or
> typec/typec.c?

For some reason I like to have the dash in the folder name, but I
don't like the idea that the port driver would be in form
type-c_something. I would prefer them to be named typec_something. Or
maybe just "something" and also name the typec.c maybe class.c or
core.c.

Is this a big problem? I guess we could just name the folder "typec".
Guenter, whats your opinion?


Thanks,

-- 
heikki

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [RFC PATCHv2] usb: USB Type-C Connector Class
  2016-06-06 13:45   ` Heikki Krogerus
@ 2016-06-06 14:41     ` Greg KH
  2016-06-07  8:25       ` Heikki Krogerus
  2016-06-06 16:02     ` Guenter Roeck
  1 sibling, 1 reply; 98+ messages in thread
From: Greg KH @ 2016-06-06 14:41 UTC (permalink / raw)
  To: Heikki Krogerus
  Cc: Pavel Machek, Guenter Roeck, Mathias Nyman, Felipe Balbi,
	Oliver Neukum, Rajaram R, Andy Shevchenko, linux-kernel,
	linux-usb

On Mon, Jun 06, 2016 at 04:45:09PM +0300, Heikki Krogerus wrote:
> Hi,
> 
> On Fri, Jun 03, 2016 at 10:20:01PM +0200, Pavel Machek wrote:
> > On Thu 2016-05-19 15:44:54, Heikki Krogerus wrote:
> > > The purpose of this class is to provide unified interface for user
> > > space to get the status and basic information about USB Type-C
> > > Connectors in the system, control data role swapping, and when USB PD
> > > is available, also power role swapping and Alternate Modes.
> > > 
> > > Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
> > > ---
> > >  drivers/usb/Kconfig         |   2 +
> > >  drivers/usb/Makefile        |   2 +
> > >  drivers/usb/type-c/Kconfig  |   7 +
> > >  drivers/usb/type-c/Makefile |   1 +
> > >  drivers/usb/type-c/typec.c  | 957 ++++++++++++++++++++++++++++++++++++++++++++
> > 
> > For consistency, should this be either type-c/type-c.c or
> > typec/typec.c?
> 
> For some reason I like to have the dash in the folder name, but I
> don't like the idea that the port driver would be in form
> type-c_something. I would prefer them to be named typec_something. Or
> maybe just "something" and also name the typec.c maybe class.c or
> core.c.
> 
> Is this a big problem? I guess we could just name the folder "typec".
> Guenter, whats your opinion?

"typec" please.

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [RFC PATCHv2] usb: USB Type-C Connector Class
  2016-06-06 13:45   ` Heikki Krogerus
  2016-06-06 14:41     ` Greg KH
@ 2016-06-06 16:02     ` Guenter Roeck
  1 sibling, 0 replies; 98+ messages in thread
From: Guenter Roeck @ 2016-06-06 16:02 UTC (permalink / raw)
  To: Heikki Krogerus
  Cc: Pavel Machek, Greg KH, Mathias Nyman, Felipe Balbi,
	Oliver Neukum, Rajaram R, Andy Shevchenko, linux-kernel,
	linux-usb

On Mon, Jun 06, 2016 at 04:45:09PM +0300, Heikki Krogerus wrote:
> Hi,
> 
> On Fri, Jun 03, 2016 at 10:20:01PM +0200, Pavel Machek wrote:
> > On Thu 2016-05-19 15:44:54, Heikki Krogerus wrote:
> > > The purpose of this class is to provide unified interface for user
> > > space to get the status and basic information about USB Type-C
> > > Connectors in the system, control data role swapping, and when USB PD
> > > is available, also power role swapping and Alternate Modes.
> > > 
> > > Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
> > > ---
> > >  drivers/usb/Kconfig         |   2 +
> > >  drivers/usb/Makefile        |   2 +
> > >  drivers/usb/type-c/Kconfig  |   7 +
> > >  drivers/usb/type-c/Makefile |   1 +
> > >  drivers/usb/type-c/typec.c  | 957 ++++++++++++++++++++++++++++++++++++++++++++
> > 
> > For consistency, should this be either type-c/type-c.c or
> > typec/typec.c?
> 
> For some reason I like to have the dash in the folder name, but I
> don't like the idea that the port driver would be in form
> type-c_something. I would prefer them to be named typec_something. Or
> maybe just "something" and also name the typec.c maybe class.c or
> core.c.
> 
> Is this a big problem? I guess we could just name the folder "typec".
> Guenter, whats your opinion?
> 
I am fine either way.

Thanks,
Guenter

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [RFC PATCHv2] usb: USB Type-C Connector Class
  2016-06-06 13:35                   ` Oliver Neukum
@ 2016-06-07  8:23                     ` Heikki Krogerus
  0 siblings, 0 replies; 98+ messages in thread
From: Heikki Krogerus @ 2016-06-07  8:23 UTC (permalink / raw)
  To: Oliver Neukum
  Cc: Guenter Roeck, Andy Shevchenko, Rajaram R, Felipe Balbi,
	Mathias Nyman, Greg KH, linux-kernel, linux-usb

On Mon, Jun 06, 2016 at 03:35:35PM +0200, Oliver Neukum wrote:
> On Mon, 2016-06-06 at 16:28 +0300, Heikki Krogerus wrote:
> 
> > I would prefer lower case letters. I don't know the SIDs there are at
> > them moment, other then Display Port. Do you know them?
> > 
> > I don't think we can ever guarantee that in every case we will be able
> > to provide a human readable name for the alternate modes if they are
> > vendor defined. We will then potentially still have the names in two
> > different forms: "usbc0.displayport" and "usbc0.svid:xxxx". Is that
> > something acceptable to everybody?
> > 
> > I guess if it's not, then to only way to go forward would be to always
> > just use the svid in the name.
> 
> Yes, that is better. It makes more sense to use the number.
> We'd get into versioning problems if we use names.

OK, so we'll always use the svid in the name.

Thanks,

-- 
heikki

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [RFC PATCHv2] usb: USB Type-C Connector Class
  2016-06-06 14:41     ` Greg KH
@ 2016-06-07  8:25       ` Heikki Krogerus
  0 siblings, 0 replies; 98+ messages in thread
From: Heikki Krogerus @ 2016-06-07  8:25 UTC (permalink / raw)
  To: Greg KH
  Cc: Pavel Machek, Guenter Roeck, Mathias Nyman, Felipe Balbi,
	Oliver Neukum, Rajaram R, Andy Shevchenko, linux-kernel,
	linux-usb

On Mon, Jun 06, 2016 at 07:41:28AM -0700, Greg KH wrote:
> On Mon, Jun 06, 2016 at 04:45:09PM +0300, Heikki Krogerus wrote:
> > > For consistency, should this be either type-c/type-c.c or
> > > typec/typec.c?
> > 
> > For some reason I like to have the dash in the folder name, but I
> > don't like the idea that the port driver would be in form
> > type-c_something. I would prefer them to be named typec_something. Or
> > maybe just "something" and also name the typec.c maybe class.c or
> > core.c.
> > 
> > Is this a big problem? I guess we could just name the folder "typec".
> > Guenter, whats your opinion?
> 
> "typec" please.

OK, typec it is.


Thanks,

-- 
heikki

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [RFC PATCHv2] usb: USB Type-C Connector Class
  2016-06-06 13:28                 ` Heikki Krogerus
  2016-06-06 13:35                   ` Oliver Neukum
@ 2016-06-07 16:57                   ` Guenter Roeck
  1 sibling, 0 replies; 98+ messages in thread
From: Guenter Roeck @ 2016-06-07 16:57 UTC (permalink / raw)
  To: Heikki Krogerus
  Cc: Oliver Neukum, Andy Shevchenko, Rajaram R, Felipe Balbi,
	Mathias Nyman, Greg KH, linux-kernel, linux-usb

On Mon, Jun 06, 2016 at 04:28:08PM +0300, Heikki Krogerus wrote:
[ ... ]
> 
> I would prefer lower case letters. I don't know the SIDs there are at
> them moment, other then Display Port. Do you know them?
> 
SIDs:
	0xff00 - power delivery
	0xff01 - displayport
	0xff02 - MHL
	0xff03 - Thunderbolt 3 (if I recall correctly)

VIDs: Can obviously be anything. I have seen
	0x05ac - Apple
	0x18d1 - Google

> I don't think we can ever guarantee that in every case we will be able
> to provide a human readable name for the alternate modes if they are
> vendor defined. We will then potentially still have the names in two
> different forms: "usbc0.displayport" and "usbc0.svid:xxxx". Is that
> something acceptable to everybody?
> 
> I guess if it's not, then to only way to go forward would be to always
> just use the svid in the name.
> 
I think we should just use the svid.

> > > > Also, do we at some point need to standardize the ABI for the standard
> > > > alternate modes such as DisplayPort (if there are any - again I am not
> > > > there yet) ?
> > > 
> > > I don't have an answer to that.
> > > 
> > Ok, I'll look into it as I proceed with my implementation.
> > 
> > > > 
> > > > Sounds good to me. Many other subsystems do the same, ie create the subsystem
> > > > device(s) during registration with the subsystem, so this is in line with other
> > > > kernel code.
> > > > 
> > > > Should I send you a follow-up patch on top of yours ?
> > > 
> > > Sure. I'm a little bit stuck with an other tasks, so let's keep this
> > > thing rolling.
> > > 
> > See below.
> 
> Thanks. I pushed it to my work branch for this class:
> 
> https://github.com/krohei/linux/commits/typec_class
> 
> There are still a few open questions, but I'm in any case going to
> start polishing the driver. I think the other attributes are more or
> less decided, excluding the alternate modes.
> 
Sounds good.

Thanks,
Guenter

^ permalink raw reply	[flat|nested] 98+ messages in thread

* [RFC PATCHv3] usb: USB Type-C Connector Class
  2016-05-19 12:44 [RFC PATCHv2] usb: USB Type-C Connector Class Heikki Krogerus
                   ` (10 preceding siblings ...)
  2016-06-03 20:20 ` Pavel Machek
@ 2016-06-10 14:34 ` Heikki Krogerus
  2016-06-11  7:05   ` Oliver Neukum
  2016-06-21 13:08 ` [RFC PATCHv2] " Oliver Neukum
  12 siblings, 1 reply; 98+ messages in thread
From: Heikki Krogerus @ 2016-06-10 14:34 UTC (permalink / raw)
  To: Guenter Roeck, Oliver Neukum
  Cc: Felipe Balbi, Greg KH, Pavel Machek, linux-kernel, linux-usb

The purpose of this class is to provide unified interface for user
space to get the status and basic information about USB Type-C
Connectors in the system, control data role swapping, and when USB PD
is available, also power role swapping and Alternate Modes.

Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
---
 drivers/usb/Kconfig        |    2 +
 drivers/usb/Makefile       |    2 +
 drivers/usb/typec/Kconfig  |    7 +
 drivers/usb/typec/Makefile |    1 +
 drivers/usb/typec/typec.c  | 1077 ++++++++++++++++++++++++++++++++++++++++++++
 include/linux/usb/typec.h  |  252 +++++++++++
 6 files changed, 1341 insertions(+)
 create mode 100644 drivers/usb/typec/Kconfig
 create mode 100644 drivers/usb/typec/Makefile
 create mode 100644 drivers/usb/typec/typec.c
 create mode 100644 include/linux/usb/typec.h

Hi,

I'm sorry to send this on Friday evening, but next week I want to get
the alternate modes sorted out. Most of the remaining open questions
are related to those. But first I want confirmation from you guys that
the other attributes are OK.

The attributes for each type-c port under /sys/class/typec/usbc<x> are:

        current_data_role
        current_power_role
        current_vconn_role
        power_operation_mode
        preferred_role
        supported_accessory_modes
        supported_data_roles
        supported_power_roles
        supports_usb_power_delivery

I choose to not have separate attribute for every accessory mode, as
it seems we are getting more of them in the future type-c
specifications. Instead I added a single attribute,
supported_accessory_modes, to list all of them.

For the alternate modes I added an attribute, supported_roles, for the
modes. It is not available for the partners and plugs. It will list
the roles that particular mode supports on the port.

I have the following opens in my list:

- How do we restore the role and altmodes on resume?
- We are missing notification on alt_mode changes, resets from
  initiated by partner, etc.
- The supported_accessory_modes is not implemented yet.

What else?


Thanks,

diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig
index 8689dcb..f42a3d3 100644
--- a/drivers/usb/Kconfig
+++ b/drivers/usb/Kconfig
@@ -150,6 +150,8 @@ source "drivers/usb/phy/Kconfig"
 
 source "drivers/usb/gadget/Kconfig"
 
+source "drivers/usb/typec/Kconfig"
+
 config USB_LED_TRIG
 	bool "USB LED Triggers"
 	depends on LEDS_CLASS && USB_COMMON && LEDS_TRIGGERS
diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile
index dca7856..51e381e 100644
--- a/drivers/usb/Makefile
+++ b/drivers/usb/Makefile
@@ -61,3 +61,5 @@ obj-$(CONFIG_USB_GADGET)	+= gadget/
 obj-$(CONFIG_USB_COMMON)	+= common/
 
 obj-$(CONFIG_USBIP_CORE)	+= usbip/
+
+obj-$(CONFIG_TYPEC)		+= typec/
diff --git a/drivers/usb/typec/Kconfig b/drivers/usb/typec/Kconfig
new file mode 100644
index 0000000..b229fb9
--- /dev/null
+++ b/drivers/usb/typec/Kconfig
@@ -0,0 +1,7 @@
+
+menu "USB PD and Type-C drivers"
+
+config TYPEC
+	tristate
+
+endmenu
diff --git a/drivers/usb/typec/Makefile b/drivers/usb/typec/Makefile
new file mode 100644
index 0000000..1012a8b
--- /dev/null
+++ b/drivers/usb/typec/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_TYPEC)		+= typec.o
diff --git a/drivers/usb/typec/typec.c b/drivers/usb/typec/typec.c
new file mode 100644
index 0000000..f551de9
--- /dev/null
+++ b/drivers/usb/typec/typec.c
@@ -0,0 +1,1077 @@
+/*
+ * USB Type-C Connector Class
+ *
+ * Copyright (C) 2016, Intel Corporation
+ * Author: Heikki Krogerus <heikki.krogerus@linux.intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/usb/typec.h>
+
+struct typec_port {
+	unsigned int		id;
+	struct device		dev;
+	struct mutex		lock; /* device lock */
+
+	int			prefer_role;
+
+	enum typec_data_role	data_role;
+	enum typec_role		pwr_role;
+	enum typec_role		vconn_role;
+	enum typec_pwr_opmode	pwr_opmode;
+
+	struct typec_partner	*partner;
+	struct typec_cable	*cable;
+
+	unsigned int		connected:1;
+
+	const struct typec_capability *cap;
+};
+
+#define to_typec_port(p) container_of(p, struct typec_port, dev)
+
+static DEFINE_IDA(typec_index_ida);
+
+static struct class typec_class = {
+	.name = "typec",
+};
+
+static const char * const typec_accessory_modes[] = {
+	[TYPEC_ACCESSORY_NONE]		= "none",
+	[TYPEC_ACCESSORY_AUDIO]		= "Audio",
+	[TYPEC_ACCESSORY_DEBUG]		= "Debug",
+	[TYPEC_ACCESSORY_DAUDIO]	= "Digital Audio",
+};
+
+/* -------------------------------- */
+/* Type-C Partners */
+
+static void typec_dev_release(struct device *dev)
+{
+}
+
+static const char * const typec_partner_types[] = {
+	[TYPEC_PARTNER_USB]		= "USB",
+	[TYPEC_PARTNER_CHARGER]		= "Charger",
+	[TYPEC_PARTNER_ALTMODE]		= "Alternate Mode",
+	[TYPEC_PARTNER_ACCESSORY]	= "Accessory",
+};
+
+static ssize_t partner_type_show(struct device *dev,
+				 struct device_attribute *attr, char *buf)
+{
+	struct typec_partner *partner = container_of(dev, struct typec_partner,
+						     dev);
+
+	return sprintf(buf, "%s\n", typec_partner_types[partner->type]);
+}
+
+static struct device_attribute dev_attr_partner_type = {
+	.attr = {
+		.name = "type",
+		.mode = S_IRUGO,
+	},
+	.show = partner_type_show,
+};
+
+static ssize_t
+partner_accessory_mode_show(struct device *dev, struct device_attribute *attr,
+			    char *buf)
+{
+	struct typec_partner *partner = container_of(dev, struct typec_partner,
+						     dev);
+
+	return sprintf(buf, "%s\n", typec_accessory_modes[partner->accessory]);
+}
+
+static struct device_attribute dev_attr_partner_accessory = {
+	.attr = {
+		.name = "accessory",
+		.mode = S_IRUGO,
+	},
+	.show = partner_accessory_mode_show,
+};
+
+static struct attribute *typec_partner_attrs[] = {
+	&dev_attr_partner_type.attr,
+	&dev_attr_partner_accessory.attr,
+	NULL
+};
+
+static struct attribute_group typec_partner_group = {
+	.attrs = typec_partner_attrs,
+};
+
+static const struct attribute_group *typec_partner_groups[] = {
+	&typec_partner_group,
+	NULL
+};
+
+static struct device_type typec_partner_dev_type = {
+	.name = "typec_partner_device",
+	.groups = typec_partner_groups,
+	.release = typec_dev_release,
+};
+
+static int
+typec_add_partner(struct typec_port *port, struct typec_partner *partner)
+{
+	struct device *dev = &partner->dev;
+	int ret;
+
+	dev->class = &typec_class;
+	dev->parent = &port->dev;
+	dev->type = &typec_partner_dev_type;
+	dev_set_name(dev, "%s-partner", dev_name(&port->dev));
+
+	ret = device_register(dev);
+	if (ret) {
+		put_device(dev);
+		return ret;
+	}
+
+	port->partner = partner;
+	return 0;
+}
+
+static void typec_remove_partner(struct typec_port *port)
+{
+	typec_unregister_altmodes(port->partner->alt_modes);
+	device_unregister(&port->partner->dev);
+}
+
+/* -------------------------------- */
+/* Type-C Cable Plugs */
+
+static struct device_type typec_plug_dev_type = {
+	.name = "type_plug_device",
+	.release = typec_dev_release,
+};
+
+static int
+typec_add_plug(struct typec_port *port, struct typec_plug *plug)
+{
+	struct device *dev = &plug->dev;
+	char name[8];
+	int ret;
+
+	sprintf(name, "plug%d", plug->index);
+
+	dev->class = &typec_class;
+	dev->parent = &port->cable->dev;
+	dev->type = &typec_plug_dev_type;
+	dev_set_name(dev, "%s-%s", dev_name(&port->dev), name);
+
+	ret = device_register(dev);
+	if (ret) {
+		put_device(dev);
+		return ret;
+	}
+
+	return 0;
+}
+
+static void typec_remove_plug(struct typec_plug *plug)
+{
+	typec_unregister_altmodes(plug->alt_modes);
+	device_unregister(&plug->dev);
+}
+
+static ssize_t
+active_cable_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct typec_cable *cable = container_of(dev, struct typec_cable, dev);
+
+	return sprintf(buf, "%d\n", cable->active);
+}
+
+static struct device_attribute dev_attr_active_cable = {
+	.attr = {
+		.name = "active",
+		.mode = S_IRUGO,
+	},
+	.show = active_cable_show,
+};
+
+static const char * const typec_plug_types[] = {
+	[USB_PLUG_NONE]		= "unknown",
+	[USB_PLUG_TYPE_A]	= "Type-A",
+	[USB_PLUG_TYPE_B]	= "Type-B",
+	[USB_PLUG_TYPE_C]	= "Type-C",
+	[USB_PLUG_CAPTIVE]	= "Captive",
+};
+
+static ssize_t
+cable_plug_type_show(struct device *dev, struct device_attribute *attr,
+		     char *buf)
+{
+	struct typec_cable *cable = container_of(dev, struct typec_cable, dev);
+
+	return sprintf(buf, "%s\n", typec_plug_types[cable->type]);
+}
+
+static struct device_attribute dev_attr_plug_type = {
+	.attr = {
+		.name = "plug_type",
+		.mode = S_IRUGO,
+	},
+	.show = cable_plug_type_show,
+};
+
+static struct attribute *typec_cable_attrs[] = {
+	&dev_attr_active_cable.attr,
+	&dev_attr_plug_type.attr,
+	NULL
+};
+
+static struct attribute_group typec_cable_group = {
+	.attrs = typec_cable_attrs,
+};
+
+static const struct attribute_group *typec_cable_groups[] = {
+	&typec_cable_group,
+	NULL
+};
+
+static struct device_type typec_cable_dev_type = {
+	.name = "typec_cable_device",
+	.groups = typec_cable_groups,
+	.release = typec_dev_release,
+};
+
+static int typec_add_cable(struct typec_port *port, struct typec_cable *cable)
+{
+	struct device *dev = &cable->dev;
+	int ret;
+
+	dev->class = &typec_class;
+	dev->parent = &port->dev;
+	dev->type = &typec_cable_dev_type;
+	dev_set_name(dev, "%s-cable", dev_name(&port->dev));
+
+	ret = device_register(dev);
+	if (ret) {
+		put_device(dev);
+		return ret;
+	}
+
+	/* Plug1 */
+	if (!cable->active)
+		return 0;
+
+	cable->plug[0].index = 1;
+	ret = typec_add_plug(port, &cable->plug[0]);
+	if (ret) {
+		device_unregister(dev);
+		return ret;
+	}
+
+	/* Plug2 */
+	if (!cable->sop_pp_controller)
+		return 0;
+
+	cable->plug[1].index = 2;
+	ret = typec_add_plug(port, &cable->plug[1]);
+	if (ret) {
+		typec_remove_plug(&cable->plug[0]);
+		device_unregister(dev);
+		return ret;
+	}
+
+	port->cable = cable;
+	return 0;
+}
+
+static void typec_remove_cable(struct typec_port *port)
+{
+	if (port->cable->active) {
+		typec_remove_plug(&port->cable->plug[0]);
+		if (port->cable->sop_pp_controller)
+			typec_remove_plug(&port->cable->plug[1]);
+	}
+	device_unregister(&port->cable->dev);
+}
+
+static void typec_init_roles(struct typec_port *port)
+{
+	if (port->prefer_role < 0)
+		return;
+
+	if (port->prefer_role == TYPEC_SOURCE) {
+		port->data_role = TYPEC_HOST;
+		port->pwr_role = TYPEC_SOURCE;
+		port->vconn_role = TYPEC_SOURCE;
+	} else {
+		/* Device mode as default also by default with DRP ports */
+		port->data_role = TYPEC_DEVICE;
+		port->pwr_role = TYPEC_SINK;
+		port->vconn_role = TYPEC_SINK;
+	}
+}
+
+/* -------------------------------- */
+
+int typec_connect(struct typec_port *port, struct typec_connection *con)
+{
+	int ret;
+
+	dev_info(&port->dev, "%s\n", __func__);
+
+	if (!con->partner && !con->cable)
+		return -EINVAL;
+
+	port->connected = 1;
+	port->data_role = con->data_role;
+	port->pwr_role = con->pwr_role;
+	port->vconn_role = con->vconn_role;
+	port->pwr_opmode = con->pwr_opmode;
+
+	kobject_uevent(&port->dev.kobj, KOBJ_CHANGE);
+
+	if (con->cable) {
+		ret = typec_add_cable(port, con->cable);
+		if (ret)
+			return ret;
+	}
+
+	if (con->partner) {
+		ret = typec_add_partner(port, con->partner);
+		if (ret) {
+			if (con->cable)
+				typec_remove_cable(port);
+			return ret;
+		}
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(typec_connect);
+
+void typec_disconnect(struct typec_port *port)
+{
+	dev_info(&port->dev, "%s\n", __func__);
+
+	if (port->partner)
+		typec_remove_partner(port);
+
+	if (port->cable)
+		typec_remove_cable(port);
+
+	port->connected = 0;
+	port->partner = NULL;
+	port->cable = NULL;
+
+	port->pwr_opmode = TYPEC_PWR_MODE_USB;
+
+	typec_init_roles(port);
+
+	kobject_uevent(&port->dev.kobj, KOBJ_CHANGE);
+}
+EXPORT_SYMBOL_GPL(typec_disconnect);
+
+struct device *typec_port2dev(struct typec_port *port)
+{
+	return &port->dev;
+}
+EXPORT_SYMBOL_GPL(typec_port2dev);
+
+struct typec_port *typec_dev2port(struct device *dev)
+{
+	return to_typec_port(dev);
+}
+EXPORT_SYMBOL_GPL(typec_dev2port);
+
+/* --------------------------------------- */
+/* Driver callbacks to report role updates */
+
+void typec_set_data_role(struct typec_port *port, enum typec_data_role role)
+{
+	port->data_role = role;
+}
+EXPORT_SYMBOL(typec_set_data_role);
+
+void typec_set_pwr_role(struct typec_port *port, enum typec_role role)
+{
+	port->pwr_role = role;
+}
+EXPORT_SYMBOL(typec_set_pwr_role);
+
+void typec_set_vconn_role(struct typec_port *port, enum typec_role role)
+{
+	port->vconn_role = role;
+}
+EXPORT_SYMBOL(typec_set_vconn_role);
+
+void typec_set_pwr_opmode(struct typec_port *port,
+			  enum typec_pwr_opmode opmode)
+{
+	port->pwr_opmode = opmode;
+}
+EXPORT_SYMBOL(typec_set_pwr_opmode);
+
+/* -------------------------------- */
+/* Alternate Modes */
+
+static struct device_type typec_port_dev_type;
+
+/*
+ * typec_altmode2port - Alternate Mode to USB Type-C port
+ * @alt: The Alternate Mode
+ *
+ * Returns the port that the cable plug or partner with @alt is connected to.
+ */
+struct typec_port *typec_altmode2port(struct typec_altmode *alt)
+{
+	if (alt->dev.parent->type == &typec_plug_dev_type)
+		return to_typec_port(alt->dev.parent->parent->parent);
+	if (alt->dev.parent->type == &typec_partner_dev_type)
+		return to_typec_port(alt->dev.parent->parent);
+	if (alt->dev.parent->type == &typec_port_dev_type)
+		return to_typec_port(alt->dev.parent);
+
+	return NULL;
+}
+EXPORT_SYMBOL_GPL(typec_altmode2port);
+
+static void typec_altmode_release(struct device *dev)
+{
+	struct typec_altmode *alt = to_altmode(dev);
+
+	kfree(alt->mode_groups);
+}
+
+static ssize_t
+typec_altmode_vdo_show(struct device *dev, struct device_attribute *attr,
+		       char *buf)
+{
+	struct typec_mode *mode = container_of(attr, struct typec_mode,
+					       vdo_attr);
+
+	return sprintf(buf, "0x%08x\n", mode->vdo);
+}
+
+static ssize_t
+typec_altmode_desc_show(struct device *dev, struct device_attribute *attr,
+			char *buf)
+{
+	struct typec_mode *mode = container_of(attr, struct typec_mode,
+					       desc_attr);
+
+	return sprintf(buf, "%s\n", mode->desc ? mode->desc : "");
+}
+
+static ssize_t
+typec_altmode_active_show(struct device *dev, struct device_attribute *attr,
+			  char *buf)
+{
+	struct typec_mode *mode = container_of(attr, struct typec_mode,
+					       active_attr);
+
+	return sprintf(buf, "%d\n", mode->active);
+}
+
+static ssize_t
+typec_altmode_active_store(struct device *dev, struct device_attribute *attr,
+			   const char *buf, size_t size)
+{
+	struct typec_mode *mode = container_of(attr, struct typec_mode,
+					       active_attr);
+	struct typec_port *port = typec_altmode2port(mode->alt_mode);
+	bool activate;
+	int ret;
+
+	ret = kstrtobool(buf, &activate);
+	if (ret)
+		return ret;
+
+	if (activate > 1)
+		return -EINVAL;
+
+	ret = port->cap->activate_mode(mode->alt_mode, mode->index, activate);
+	if (ret)
+		return ret;
+
+	return size;
+}
+
+static ssize_t
+typec_altmode_roles_show(struct device *dev, struct device_attribute *attr,
+			 char *buf)
+{
+	struct typec_mode *mode = container_of(attr, struct typec_mode,
+					       roles_attr);
+
+	switch (mode->roles) {
+	case TYPEC_PORT_DFP:
+		return sprintf(buf, "source\n");
+	case TYPEC_PORT_UFP:
+		return sprintf(buf, "sink\n");
+	case TYPEC_PORT_DRP:
+	default:
+		return sprintf(buf, "source, sink\n");
+	}
+}
+
+static void typec_init_modes(struct typec_altmode *alt, int is_port)
+{
+	struct typec_mode *mode = alt->modes;
+	int i;
+
+	for (i = 0; i < alt->n_modes; i++, mode++) {
+		mode->alt_mode = alt;
+		mode->index = i;
+		sprintf(mode->group_name, "mode%d", i);
+
+		sysfs_attr_init(&mode->vdo_attr.attr);
+		mode->vdo_attr.attr.name = "vdo";
+		mode->vdo_attr.attr.mode = S_IRUGO;
+		mode->vdo_attr.show = typec_altmode_vdo_show;
+
+		sysfs_attr_init(&mode->desc_attr.attr);
+		mode->desc_attr.attr.name = "description";
+		mode->desc_attr.attr.mode = S_IRUGO;
+		mode->desc_attr.show = typec_altmode_desc_show;
+
+		sysfs_attr_init(&mode->active_attr.attr);
+		mode->active_attr.attr.name = "active";
+		mode->active_attr.attr.mode = S_IWUSR | S_IRUGO;
+		mode->active_attr.show = typec_altmode_active_show;
+		mode->active_attr.store = typec_altmode_active_store;
+
+		mode->attrs[0] = &mode->vdo_attr.attr;
+		mode->attrs[1] = &mode->desc_attr.attr;
+		mode->attrs[2] = &mode->active_attr.attr;
+
+		/* With ports, list the roles that the mode is supported with */
+		if (is_port) {
+			sysfs_attr_init(&mode->roles_attr.attr);
+			mode->roles_attr.attr.name = "supported_roles";
+			mode->roles_attr.attr.mode = S_IRUGO;
+			mode->roles_attr.show = typec_altmode_roles_show;
+
+			mode->attrs[3] = &mode->roles_attr.attr;
+		}
+
+		mode->group.attrs = mode->attrs;
+		mode->group.name = mode->group_name;
+
+		alt->mode_groups[i] = &mode->group;
+	}
+}
+
+static int
+typec_add_altmode(struct device *parent, struct typec_altmode *alt, int is_port)
+{
+	struct device *dev = &alt->dev;
+	int ret;
+
+	alt->mode_groups = kcalloc(alt->n_modes + 1,
+				   sizeof(struct attibute_group *), GFP_KERNEL);
+	if (!alt->mode_groups)
+		return -ENOMEM;
+
+	typec_init_modes(alt, is_port);
+
+	dev->groups = alt->mode_groups;
+	dev->release = typec_altmode_release;
+	dev->parent = parent;
+	/* TODO: if (!is_port) dev->bus = &typec_altmode_bus; */
+
+	dev_set_name(dev, "%s.svid:%04x", dev_name(parent), alt->svid);
+
+	dev_info(parent, "%s\n", __func__);
+
+	ret = device_register(dev);
+	if (ret) {
+		put_device(dev);
+		kfree(alt->mode_groups);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int __typec_register_altmodes(struct device *parent,
+				     struct typec_altmode *alt_modes,
+				     int is_port)
+{
+	struct typec_altmode *alt;
+	int index;
+	int ret;
+
+	if (!alt_modes)
+		return 0;
+
+	for (alt = alt_modes, index = 0; alt->svid; alt++, index++) {
+		dev_info(parent, "%s\n", __func__);
+
+		ret = typec_add_altmode(parent, alt, is_port);
+		if (ret)
+			goto err;
+	}
+
+	return 0;
+err:
+	for (alt = alt_modes + index; index; alt--, index--)
+		device_unregister(&alt->dev);
+
+	return ret;
+}
+
+int typec_register_altmodes(struct device *parent,
+			    struct typec_altmode *alt_modes)
+{
+	return __typec_register_altmodes(parent, alt_modes, false);
+}
+EXPORT_SYMBOL_GPL(typec_register_altmodes);
+
+void typec_unregister_altmodes(struct typec_altmode *alt_modes)
+{
+	struct typec_altmode *alt;
+
+	if (!alt_modes)
+		return;
+
+	for (alt = alt_modes; alt->svid; alt++)
+		device_unregister(&alt->dev);
+}
+EXPORT_SYMBOL_GPL(typec_unregister_altmodes);
+
+/* -------------------------------- */
+
+static const char * const typec_roles[] = {
+	[TYPEC_SINK]	= "sink",
+	[TYPEC_SOURCE]	= "source",
+};
+
+static const char * const typec_data_roles[] = {
+	[TYPEC_DEVICE]	= "device",
+	[TYPEC_HOST]	= "host",
+};
+
+static ssize_t
+preferred_role_store(struct device *dev, struct device_attribute *attr,
+		     const char *buf, size_t size)
+{
+	struct typec_port *port = to_typec_port(dev);
+	enum typec_role role;
+	int ret;
+
+	mutex_lock(&port->lock);
+
+	if (port->cap->type != TYPEC_PORT_DRP) {
+		dev_dbg(dev, "Try.SRC/SNK only supported with DRP ports\n");
+		ret = -EOPNOTSUPP;
+		goto out;
+	}
+
+	if (!port->cap->try_role) {
+		dev_warn(dev, "Try.SRC/SNK not supported\n");
+		ret = -EOPNOTSUPP;
+		goto out;
+	}
+
+	if (!strlen(buf)) {
+		port->prefer_role = -1;
+		ret = size;
+		goto out;
+	}
+
+	role = match_string(typec_roles, ARRAY_SIZE(typec_roles), buf);
+	if (role < 0) {
+		ret = role;
+		goto out;
+	}
+
+	ret = port->cap->try_role(port->cap, role);
+	if (ret)
+		goto out;
+
+	port->prefer_role = role;
+	ret = size;
+out:
+	mutex_unlock(&port->lock);
+	return ret;
+}
+
+static ssize_t
+preferred_role_show(struct device *dev, struct device_attribute *attr,
+		    char *buf)
+{
+	struct typec_port *port = to_typec_port(dev);
+	int ret = 0;
+
+	mutex_lock(&port->lock);
+
+	if (port->prefer_role < 0)
+		goto out;
+
+	ret = sprintf(buf, "%s\n", typec_roles[port->prefer_role]);
+out:
+	mutex_unlock(&port->lock);
+	return ret;
+}
+static DEVICE_ATTR_RW(preferred_role);
+
+static ssize_t
+current_data_role_store(struct device *dev, struct device_attribute *attr,
+			const char *buf, size_t size)
+{
+	struct typec_port *port = to_typec_port(dev);
+	int role;
+	int ret;
+
+	mutex_lock(&port->lock);
+
+	if (port->cap->type != TYPEC_PORT_DRP) {
+		dev_dbg(dev, "data role swap only supported with DRP ports\n");
+		ret = -EOPNOTSUPP;
+		goto out;
+	}
+
+	if (!port->cap->dr_set) {
+		dev_warn(dev, "data role swapping not supported\n");
+		ret = -EOPNOTSUPP;
+		goto out;
+	}
+
+	role = match_string(typec_data_roles, ARRAY_SIZE(typec_data_roles),
+			    buf);
+	if (role < 0) {
+		ret = role;
+		goto out;
+	}
+
+	ret = port->cap->dr_set(port->cap, role);
+	if (ret)
+		goto out;
+
+	ret = size;
+out:
+	mutex_unlock(&port->lock);
+	return ret;
+}
+
+static ssize_t
+current_data_role_show(struct device *dev, struct device_attribute *attr,
+		       char *buf)
+{
+	struct typec_port *port = to_typec_port(dev);
+
+	return sprintf(buf, "%s\n", typec_data_roles[port->data_role]);
+}
+static DEVICE_ATTR_RW(current_data_role);
+
+static ssize_t supported_data_roles_show(struct device *dev,
+					 struct device_attribute *attr,
+					 char *buf)
+{
+	struct typec_port *port = to_typec_port(dev);
+	size_t ret;
+
+	mutex_lock(&port->lock);
+
+	if (port->cap->type == TYPEC_PORT_DRP) {
+		ret = sprintf(buf, "host, device\n");
+		goto out;
+	}
+
+	ret = sprintf(buf, "%s\n", typec_data_roles[port->data_role]);
+out:
+	mutex_unlock(&port->lock);
+	return ret;
+}
+static DEVICE_ATTR_RO(supported_data_roles);
+
+static ssize_t current_power_role_store(struct device *dev,
+					struct device_attribute *attr,
+					const char *buf, size_t size)
+{
+	struct typec_port *port = to_typec_port(dev);
+	int role;
+	int ret;
+
+	mutex_lock(&port->lock);
+
+	if (!port->cap->usb_pd) {
+		dev_dbg(dev, "power role swap only supported with USB PD\n");
+		ret = -EOPNOTSUPP;
+		goto out;
+	}
+
+	if (!port->cap->pr_set) {
+		dev_warn(dev, "power role swapping not supported\n");
+		ret = -EOPNOTSUPP;
+		goto out;
+	}
+
+	if (port->pwr_opmode != TYPEC_PWR_MODE_PD) {
+		dev_dbg(dev, "partner unable to swap power role\n");
+		ret = -EIO;
+		goto out;
+	}
+
+	role = match_string(typec_roles, ARRAY_SIZE(typec_roles), buf);
+	if (role < 0) {
+		ret = role;
+		goto out;
+	}
+
+	ret = port->cap->pr_set(port->cap, role);
+	if (ret)
+		goto out;
+
+	ret = size;
+out:
+	mutex_unlock(&port->lock);
+	return ret;
+}
+
+static ssize_t current_power_role_show(struct device *dev,
+				       struct device_attribute *attr, char *buf)
+{
+	struct typec_port *port = to_typec_port(dev);
+
+	return sprintf(buf, "%s\n", typec_roles[port->pwr_role]);
+}
+static DEVICE_ATTR_RW(current_power_role);
+
+static ssize_t supported_power_roles_show(struct device *dev,
+					  struct device_attribute *attr,
+					  char *buf)
+{
+	struct typec_port *port = to_typec_port(dev);
+	size_t ret;
+
+	mutex_lock(&port->lock);
+
+	if (port->cap->usb_pd || port->cap->type == TYPEC_PORT_DRP) {
+		ret = sprintf(buf, "source, sink\n");
+		goto out;
+	}
+
+	ret = sprintf(buf, "%s\n", typec_roles[port->pwr_role]);
+out:
+	mutex_unlock(&port->lock);
+	return ret;
+}
+static DEVICE_ATTR_RO(supported_power_roles);
+
+static const char * const typec_pwr_opmodes[] = {
+	[TYPEC_PWR_MODE_USB]	= "USB",
+	[TYPEC_PWR_MODE_BC1_2]	= "BC1.2",
+	[TYPEC_PWR_MODE_1_5A]	= "USB Type-C 1.5A",
+	[TYPEC_PWR_MODE_3_0A]	= "USB Type-C 3.0A",
+	[TYPEC_PWR_MODE_PD]	= "USB Power Delivery",
+};
+
+static ssize_t power_operation_mode_show(struct device *dev,
+					 struct device_attribute *attr,
+					 char *buf)
+{
+	struct typec_port *port = to_typec_port(dev);
+
+	return sprintf(buf, "%s\n", typec_pwr_opmodes[port->pwr_opmode]);
+}
+static DEVICE_ATTR_RO(power_operation_mode);
+
+static ssize_t current_vconn_role_store(struct device *dev,
+					struct device_attribute *attr,
+					const char *buf, size_t size)
+{
+	struct typec_port *port = to_typec_port(dev);
+	int role;
+	int ret;
+
+	mutex_lock(&port->lock);
+
+	if (!port->cap->usb_pd) {
+		dev_dbg(dev, "vconn swap only supported with USB PD\n");
+		ret = -EOPNOTSUPP;
+		goto out;
+	}
+
+	if (!port->cap->vconn_set) {
+		dev_warn(dev, "vconn swapping not supported\n");
+		ret = -EOPNOTSUPP;
+		goto out;
+	}
+
+	role = match_string(typec_roles, ARRAY_SIZE(typec_roles), buf);
+	if (role < 0) {
+		ret = role;
+		goto out;
+	}
+
+	ret = port->cap->vconn_set(port->cap, role);
+	if (ret)
+		goto out;
+
+	ret = size;
+out:
+	mutex_unlock(&port->lock);
+	return ret;
+}
+
+static ssize_t current_vconn_role_show(struct device *dev,
+				       struct device_attribute *attr, char *buf)
+{
+	struct typec_port *port = to_typec_port(dev);
+
+	return sprintf(buf, "%s\n", typec_roles[port->vconn_role]);
+}
+static DEVICE_ATTR_RW(current_vconn_role);
+
+static ssize_t supported_accessory_modes_show(struct device *dev,
+					      struct device_attribute *attr,
+					      char *buf)
+{
+	/* FIXME!!! How do list the supported accessory modes? */
+	return 0;
+}
+static DEVICE_ATTR_RO(supported_accessory_modes);
+
+static ssize_t supports_usb_power_delivery_show(struct device *dev,
+						struct device_attribute *attr,
+						char *buf)
+{
+	struct typec_port *port = to_typec_port(dev);
+
+	return sprintf(buf, "%d\n", port->cap->usb_pd);
+}
+static DEVICE_ATTR_RO(supports_usb_power_delivery);
+
+static struct attribute *typec_attrs[] = {
+	&dev_attr_current_power_role.attr,
+	&dev_attr_current_vconn_role.attr,
+	&dev_attr_current_data_role.attr,
+	&dev_attr_power_operation_mode.attr,
+	&dev_attr_preferred_role.attr,
+	&dev_attr_supported_accessory_modes.attr,
+	&dev_attr_supported_data_roles.attr,
+	&dev_attr_supported_power_roles.attr,
+	&dev_attr_supports_usb_power_delivery.attr,
+	NULL,
+};
+
+static const struct attribute_group typec_group = {
+	.attrs = typec_attrs,
+};
+
+static const struct attribute_group *typec_groups[] = {
+	&typec_group,
+	NULL,
+};
+
+static int typec_uevent(struct device *dev, struct kobj_uevent_env *env)
+{
+	int ret;
+
+	ret = add_uevent_var(env, "TYPEC_PORT=%s", dev_name(dev));
+	if (ret)
+		dev_err(dev, "failed to add uevent TYPEC_PORT\n");
+
+	return ret;
+}
+
+static void typec_release(struct device *dev)
+{
+	struct typec_port *port = to_typec_port(dev);
+
+	ida_simple_remove(&typec_index_ida, port->id);
+	kfree(port);
+}
+
+static struct device_type typec_port_dev_type = {
+	.name = "typec_port",
+	.groups = typec_groups,
+	.uevent = typec_uevent,
+	.release = typec_release,
+};
+
+struct typec_port *typec_register_port(struct device *dev,
+				       const struct typec_capability *cap)
+{
+	struct typec_port *port;
+	int ret;
+	int id;
+
+	dev_info(dev, "%s\n", __func__);
+
+	port = kzalloc(sizeof(*port), GFP_KERNEL);
+	if (!port)
+		return ERR_PTR(-ENOMEM);
+
+	id = ida_simple_get(&typec_index_ida, 0, 0, GFP_KERNEL);
+	if (id < 0) {
+		kfree(port);
+		return ERR_PTR(id);
+	}
+
+	/* FIXME: a better approach for this */
+	port->prefer_role = -1;
+
+	port->id = id;
+	port->cap = cap;
+	port->dev.type = &typec_port_dev_type;
+	port->dev.class = &typec_class;
+	port->dev.parent = dev;
+	dev_set_name(&port->dev, "usbc%d", id);
+	mutex_init(&port->lock);
+
+	typec_init_roles(port);
+
+	ret = device_register(&port->dev);
+	if (ret)
+		goto reg_err;
+
+	dev_info(&port->dev, "%s\n", __func__);
+
+	ret = __typec_register_altmodes(&port->dev, cap->alt_modes, true);
+	if (ret)
+		goto alt_err;
+
+	return port;
+alt_err:
+	device_unregister(&port->dev);
+reg_err:
+	ida_simple_remove(&typec_index_ida, id);
+	put_device(&port->dev);
+	kfree(port);
+	return ERR_PTR(ret);
+}
+EXPORT_SYMBOL_GPL(typec_register_port);
+
+void typec_unregister_port(struct typec_port *port)
+{
+	if (port->connected)
+		typec_disconnect(port);
+
+	dev_info(&port->dev, "%s\n", __func__);
+
+	typec_unregister_altmodes(port->cap->alt_modes);
+	device_unregister(&port->dev);
+}
+EXPORT_SYMBOL_GPL(typec_unregister_port);
+
+static int __init typec_init(void)
+{
+	return class_register(&typec_class);
+}
+subsys_initcall(typec_init);
+
+static void __exit typec_exit(void)
+{
+	class_unregister(&typec_class);
+}
+module_exit(typec_exit);
+
+MODULE_AUTHOR("Heikki Krogerus <heikki.krogerus@linux.intel.com>");
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("USB Type-C Connector Class");
diff --git a/include/linux/usb/typec.h b/include/linux/usb/typec.h
new file mode 100644
index 0000000..1b91046
--- /dev/null
+++ b/include/linux/usb/typec.h
@@ -0,0 +1,252 @@
+
+#ifndef __LINUX_USB_TYPEC_H
+#define __LINUX_USB_TYPEC_H
+
+#include <linux/types.h>
+
+struct typec_port;
+
+enum typec_port_type {
+	TYPEC_PORT_DFP,
+	TYPEC_PORT_UFP,
+	TYPEC_PORT_DRP,
+};
+
+enum typec_partner_type {
+	TYPEC_PARTNER_USB,
+	TYPEC_PARTNER_CHARGER,
+	TYPEC_PARTNER_ALTMODE,
+	TYPEC_PARTNER_ACCESSORY,
+};
+
+enum typec_plug_type {
+	USB_PLUG_NONE,
+	USB_PLUG_TYPE_A,
+	USB_PLUG_TYPE_B,
+	USB_PLUG_TYPE_C,
+	USB_PLUG_CAPTIVE,
+};
+
+enum typec_data_role {
+	TYPEC_DEVICE,
+	TYPEC_HOST,
+};
+
+enum typec_role {
+	TYPEC_SINK,
+	TYPEC_SOURCE,
+};
+
+enum typec_pwr_opmode {
+	TYPEC_PWR_MODE_USB,
+	TYPEC_PWR_MODE_BC1_2,
+	TYPEC_PWR_MODE_1_5A,
+	TYPEC_PWR_MODE_3_0A,
+	TYPEC_PWR_MODE_PD,
+};
+
+enum typec_accessory {
+	TYPEC_ACCESSORY_NONE,
+	TYPEC_ACCESSORY_AUDIO,
+	TYPEC_ACCESSORY_DEBUG,
+	TYPEC_ACCESSORY_DAUDIO,
+};
+
+/*
+ * struct typec_mode - Individual Mode of an Alternate Mode
+ * @vdo: VDO returned by Discover Modes USB PD command
+ * @desc: Mode description
+ * @active: Tells if the mode is currently entered or not
+ * @index: Index of the mode
+ * @group_name: Name for the sysfs folder in form "mode<index>"
+ * @group: The sysfs group (folder) for the mode
+ * @attrs: The attributes for the sysfs group
+ * @vdo_attr: Device attribute to expose the VDO of the mode
+ * @desc_attr: Device attribute to expose the description of the mode
+ * @active_attr: Device attribute to expose active of the mode
+ * @roles: Only for ports. DRP if the mode is awailable in both roles
+ * @roles_attr: Device attribute, only for ports, to expose the supported roles
+ *
+ * Details about a mode of an Alternate Mode which a connector, cable plug or
+ * partner supports. Every mode will have it's own sysfs group. The details are
+ * the VDO returned by discover modes command, description for the mode and
+ * active flag telling is the mode currently active or not.
+ */
+struct typec_mode {
+	u32			vdo;
+	char			*desc;
+	unsigned int		active:1;
+	/* Only for ports */
+	enum typec_port_type	roles;
+
+	struct typec_altmode	*alt_mode;
+
+	int			index;
+	char			group_name[8];
+	struct attribute_group	group;
+	struct attribute	*attrs[5];
+	struct device_attribute vdo_attr;
+	struct device_attribute desc_attr;
+	struct device_attribute active_attr;
+	/* Only for ports */
+	struct device_attribute roles_attr;
+};
+
+/*
+ * struct typec_altmode - USB Type-C Alternate Mode
+ * @dev: struct device instance
+ * @name: Name for the Alternate Mode (optional)
+ * @svid: Standard or Vendor ID
+ * @n_modes: Number of modes
+ * @modes: Array of modes supported by the Alternat Mode
+ * @mode_groups: The modes as attribute groups to be exposed in sysfs
+ *
+ * Representation of an Alternate Mode that has SVID assigned by USB-IF. The
+ * array of modes will list the modes of a particular SVID that are supported by
+ * a connector, partner of a cable plug.
+ */
+struct typec_altmode {
+	struct device		dev;
+	char			*name;
+
+	u16			svid;
+	int			n_modes;
+	struct typec_mode	*modes;
+
+	const struct attribute_group **mode_groups;
+};
+
+#define to_altmode(d) container_of(d, struct typec_altmode, dev)
+
+struct typec_port *typec_altmode2port(struct typec_altmode *);
+
+int typec_register_altmodes(struct device *, struct typec_altmode *);
+void typec_unregister_altmodes(struct typec_altmode *);
+
+/*
+ * struct typec_plug - USB Type-C Cable Plug
+ * @dev: struct device instance
+ * @index: 1 for the plug connected to DFP and 2 for the plug connected to UFP
+ * @alt_modes: Alternate Modes the cable plug supports (null terminated)
+ *
+ * Represents USB Type-C Cable Plug.
+ */
+struct typec_plug {
+	struct device		dev;
+	int			index;
+	struct typec_altmode	*alt_modes;
+};
+
+/*
+ * struct typec_cable - USB Type-C Cable
+ * @dev: struct device instance
+ * @type: The plug type from USB PD Cable VDO
+ * @active: Is the cable active or passive
+ * @sop_pp_controller: Tells whether both cable plugs are configurable or not
+ * @plug: The two plugs in the cable.
+ *
+ * Represents USB Type-C Cable attached to USB Type-C port. Two plugs are
+ * created if the cable has SOP Double Prime controller as defined in USB PD
+ * specification. Otherwise only one will be created if the cable is active. For
+ * passive cables no plugs are created.
+ */
+struct typec_cable {
+	struct device		dev;
+	enum typec_plug_type	type;
+	unsigned int		active:1;
+	unsigned int		sop_pp_controller:1;
+	/* REVISIT: What else needed? */
+
+	struct typec_plug	plug[2];
+};
+
+/*
+ * struct typec_partner - USB Type-C Partner
+ * @dev: struct device instance
+ * @type: Normal USB device, charger, Alternate Mode or Accessory
+ * @alt_modes: Alternate Modes the partner supports (null terminated)
+ *
+ * Details about a partner that is attached to USB Type-C port.
+ */
+struct typec_partner {
+	struct device		dev;
+	enum typec_partner_type	type;
+	enum typec_accessory	accessory;
+	struct typec_altmode	*alt_modes;
+};
+
+/*
+ * struct typec_capability - USB Type-C Port Capabilities
+ * @role: DFP (Host-only), UFP (Device-only) or DRP (Dual Role)
+ * @usb_pd: USB Power Delivery support
+ * @alt_modes: Alternate Modes the connector supports (null terminated)
+ * @accessors: Supported Accessory Modes (null terminated)
+ * @try_role: Set a fixed data role for DRP port
+ * @dr_set: Set Data Role
+ * @pr_set: Set Power Role
+ * @vconn_set: Set VCONN Role
+ * @activate_mode: Enter/exit given Alternate Mode
+ *
+ * Static capabilities of a single USB Type-C port.
+ */
+struct typec_capability {
+	enum typec_port_type	type;
+	unsigned int		usb_pd:1;
+	struct typec_altmode	*alt_modes;
+
+	int			(*try_role)(const struct typec_capability *,
+					    enum typec_role);
+
+	int			(*dr_set)(const struct typec_capability *,
+					  enum typec_data_role);
+	int			(*pr_set)(const struct typec_capability *,
+					  enum typec_role);
+	int			(*vconn_set)(const struct typec_capability *,
+					     enum typec_role);
+
+	int			(*activate_mode)(struct typec_altmode *,
+						 int mode, int activate);
+};
+
+/*
+ * struct typec_connection - Details about USB Type-C port connection event
+ * @partner: The attached partner
+ * @cable: The attached cable
+ * @data_role: Initial USB data role (host or device)
+ * @pwr_role: Initial Power role (source or sink)
+ * @vconn_role: Initial VCONN role (source or sink)
+ * @pwr_opmode: The power mode of the connection
+ *
+ * All the relevant details about a connection event. Wrapper that is passed to
+ * typec_connect(). The context is copied when typec_connect() is called and the
+ * structure is not used for anything else.
+ */
+struct typec_connection {
+	struct typec_partner	*partner;
+	struct typec_cable	*cable;
+
+	enum typec_data_role	data_role;
+	enum typec_role		pwr_role;
+	enum typec_role		vconn_role;
+	enum typec_pwr_opmode	pwr_opmode;
+};
+
+struct typec_port *typec_register_port(struct device *dev,
+				       const struct typec_capability *cap);
+void typec_unregister_port(struct typec_port *port);
+
+int typec_connect(struct typec_port *port, struct typec_connection *con);
+void typec_disconnect(struct typec_port *port);
+
+/* REVISIT: are these needed? */
+struct device *typec_port2dev(struct typec_port *port);
+struct typec_port *typec_dev2port(struct device *dev);
+
+/* Callbacks from driver */
+
+void typec_set_data_role(struct typec_port *, enum typec_data_role);
+void typec_set_pwr_role(struct typec_port *, enum typec_role);
+void typec_set_vconn_role(struct typec_port *, enum typec_role);
+void typec_set_pwr_opmode(struct typec_port *, enum typec_pwr_opmode);
+
+#endif /* __LINUX_USB_TYPEC_H */
-- 
2.8.1

^ permalink raw reply related	[flat|nested] 98+ messages in thread

* Re: [RFC PATCHv3] usb: USB Type-C Connector Class
  2016-06-10 14:34 ` [RFC PATCHv3] " Heikki Krogerus
@ 2016-06-11  7:05   ` Oliver Neukum
  2016-06-11 18:03     ` Guenter Roeck
  2016-06-13  7:48     ` Heikki Krogerus
  0 siblings, 2 replies; 98+ messages in thread
From: Oliver Neukum @ 2016-06-11  7:05 UTC (permalink / raw)
  To: Heikki Krogerus
  Cc: Guenter Roeck, Felipe Balbi, Greg KH, Pavel Machek, linux-kernel,
	linux-usb

On Fri, 2016-06-10 at 17:34 +0300, Heikki Krogerus wrote:
> +static ssize_t
> +preferred_role_store(struct device *dev, struct device_attribute
> *attr,
> +                    const char *buf, size_t size)
> +{
> +       struct typec_port *port = to_typec_port(dev);
> +       enum typec_role role;
> +       int ret;
> +
> +       mutex_lock(&port->lock);
> +
> +       if (port->cap->type != TYPEC_PORT_DRP) {
> +               dev_dbg(dev, "Try.SRC/SNK only supported with DRP
> ports\n");
> +               ret = -EOPNOTSUPP;
> +               goto out;
> +       }

I think Try.SNK with an UFP should fail differently from
Try.SRC and vice versa.

And, even more importantly, this offeres no way to cancel
a preference.

	Regards
		Oliver

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [RFC PATCHv3] usb: USB Type-C Connector Class
  2016-06-11  7:05   ` Oliver Neukum
@ 2016-06-11 18:03     ` Guenter Roeck
  2016-06-13  7:49       ` Heikki Krogerus
  2016-06-13  7:48     ` Heikki Krogerus
  1 sibling, 1 reply; 98+ messages in thread
From: Guenter Roeck @ 2016-06-11 18:03 UTC (permalink / raw)
  To: Oliver Neukum, Heikki Krogerus
  Cc: Felipe Balbi, Greg KH, Pavel Machek, linux-kernel, linux-usb

On 06/11/2016 12:05 AM, Oliver Neukum wrote:
> On Fri, 2016-06-10 at 17:34 +0300, Heikki Krogerus wrote:
>> +static ssize_t
>> +preferred_role_store(struct device *dev, struct device_attribute
>> *attr,
>> +                    const char *buf, size_t size)
>> +{
>> +       struct typec_port *port = to_typec_port(dev);
>> +       enum typec_role role;
>> +       int ret;
>> +
>> +       mutex_lock(&port->lock);
>> +
>> +       if (port->cap->type != TYPEC_PORT_DRP) {
>> +               dev_dbg(dev, "Try.SRC/SNK only supported with DRP
>> ports\n");
>> +               ret = -EOPNOTSUPP;
>> +               goto out;
>> +       }
>
> I think Try.SNK with an UFP should fail differently from
> Try.SRC and vice versa.
>

I think the message should not even mention Try.src or Try.snk
in the first place, since both are optional and really orthogonal
to how the role is set (it can also be changed with pd messages).
On top of that, the specification states that Try.{src/snk} are
optional if there is no PD support, and NA if PD is supported
(see table 4.10). Kind of interesting, and I wonder how this
is supposed to be implemented in practice, since Try.{src/snk}
runs before it is established that/if the partner supports PD.

A better message would be something like "Setting preferred
role only supported with DRP ports", and leave implementation
details to the port driver.

Guenter

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [RFC PATCHv3] usb: USB Type-C Connector Class
  2016-06-11  7:05   ` Oliver Neukum
  2016-06-11 18:03     ` Guenter Roeck
@ 2016-06-13  7:48     ` Heikki Krogerus
  1 sibling, 0 replies; 98+ messages in thread
From: Heikki Krogerus @ 2016-06-13  7:48 UTC (permalink / raw)
  To: Oliver Neukum
  Cc: Guenter Roeck, Felipe Balbi, Greg KH, Pavel Machek, linux-kernel,
	linux-usb

On Sat, Jun 11, 2016 at 09:05:46AM +0200, Oliver Neukum wrote:
> On Fri, 2016-06-10 at 17:34 +0300, Heikki Krogerus wrote:
> > +static ssize_t
> > +preferred_role_store(struct device *dev, struct device_attribute
> > *attr,
> > +                    const char *buf, size_t size)
> > +{
> > +       struct typec_port *port = to_typec_port(dev);
> > +       enum typec_role role;
> > +       int ret;
> > +
> > +       mutex_lock(&port->lock);
> > +
> > +       if (port->cap->type != TYPEC_PORT_DRP) {
> > +               dev_dbg(dev, "Try.SRC/SNK only supported with DRP
> > ports\n");
> > +               ret = -EOPNOTSUPP;
> > +               goto out;
> > +       }
> 
> I think Try.SNK with an UFP should fail differently from
> Try.SRC and vice versa.
> 
> And, even more importantly, this offeres no way to cancel
> a preference.

Well, no way that would actually work. I'll fix that.

Thanks,

-- 
heikki

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [RFC PATCHv3] usb: USB Type-C Connector Class
  2016-06-11 18:03     ` Guenter Roeck
@ 2016-06-13  7:49       ` Heikki Krogerus
  0 siblings, 0 replies; 98+ messages in thread
From: Heikki Krogerus @ 2016-06-13  7:49 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Oliver Neukum, Felipe Balbi, Greg KH, Pavel Machek, linux-kernel,
	linux-usb

On Sat, Jun 11, 2016 at 11:03:53AM -0700, Guenter Roeck wrote:
> On 06/11/2016 12:05 AM, Oliver Neukum wrote:
> > On Fri, 2016-06-10 at 17:34 +0300, Heikki Krogerus wrote:
> > > +static ssize_t
> > > +preferred_role_store(struct device *dev, struct device_attribute
> > > *attr,
> > > +                    const char *buf, size_t size)
> > > +{
> > > +       struct typec_port *port = to_typec_port(dev);
> > > +       enum typec_role role;
> > > +       int ret;
> > > +
> > > +       mutex_lock(&port->lock);
> > > +
> > > +       if (port->cap->type != TYPEC_PORT_DRP) {
> > > +               dev_dbg(dev, "Try.SRC/SNK only supported with DRP
> > > ports\n");
> > > +               ret = -EOPNOTSUPP;
> > > +               goto out;
> > > +       }
> > 
> > I think Try.SNK with an UFP should fail differently from
> > Try.SRC and vice versa.
> > 
> 
> I think the message should not even mention Try.src or Try.snk
> in the first place, since both are optional and really orthogonal
> to how the role is set (it can also be changed with pd messages).
> On top of that, the specification states that Try.{src/snk} are
> optional if there is no PD support, and NA if PD is supported
> (see table 4.10). Kind of interesting, and I wonder how this
> is supposed to be implemented in practice, since Try.{src/snk}
> runs before it is established that/if the partner supports PD.
> 
> A better message would be something like "Setting preferred
> role only supported with DRP ports", and leave implementation
> details to the port driver.

Works for me.

Thanks,

-- 
heikki

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [RFC PATCHv2] usb: USB Type-C Connector Class
  2016-05-19 12:44 [RFC PATCHv2] usb: USB Type-C Connector Class Heikki Krogerus
                   ` (11 preceding siblings ...)
  2016-06-10 14:34 ` [RFC PATCHv3] " Heikki Krogerus
@ 2016-06-21 13:08 ` Oliver Neukum
  2016-06-21 13:24   ` Guenter Roeck
  2016-06-21 13:58   ` Heikki Krogerus
  12 siblings, 2 replies; 98+ messages in thread
From: Oliver Neukum @ 2016-06-21 13:08 UTC (permalink / raw)
  To: Heikki Krogerus
  Cc: Guenter Roeck, Andy Shevchenko, Rajaram R, Felipe Balbi,
	Mathias Nyman, Greg KH, linux-kernel, linux-usb

On Thu, 2016-05-19 at 15:44 +0300, Heikki Krogerus wrote:
> The purpose of this class is to provide unified interface for user
> space to get the status and basic information about USB Type-C
> Connectors in the system, control data role swapping, and when USB PD
> is available, also power role swapping and Alternate Modes.

This raises two more questions.

1. Booting

It is possible that our only display and, worse, our source
of power is a display that can be used only in an alternate mode
and is connected via a type C connector.

We need some kind of boot time support for alternate modes.

The firmware will surely want to display something. So it is possible
that we start the OS will a valid power contract. How do we deal
with that? Renegotiate?

2. Multiple GPUs

How do we know which GPU is connected to which port?

	Regards
		Oliver

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [RFC PATCHv2] usb: USB Type-C Connector Class
  2016-06-21 13:08 ` [RFC PATCHv2] " Oliver Neukum
@ 2016-06-21 13:24   ` Guenter Roeck
  2016-06-21 19:43     ` Oliver Neukum
  2016-06-21 13:58   ` Heikki Krogerus
  1 sibling, 1 reply; 98+ messages in thread
From: Guenter Roeck @ 2016-06-21 13:24 UTC (permalink / raw)
  To: Oliver Neukum, Heikki Krogerus
  Cc: Andy Shevchenko, Rajaram R, Felipe Balbi, Mathias Nyman, Greg KH,
	linux-kernel, linux-usb

On 06/21/2016 06:08 AM, Oliver Neukum wrote:
> On Thu, 2016-05-19 at 15:44 +0300, Heikki Krogerus wrote:
>> The purpose of this class is to provide unified interface for user
>> space to get the status and basic information about USB Type-C
>> Connectors in the system, control data role swapping, and when USB PD
>> is available, also power role swapping and Alternate Modes.
>
> This raises two more questions.
>
> 1. Booting
>
> It is possible that our only display and, worse, our source
> of power is a display that can be used only in an alternate mode
> and is connected via a type C connector.
>
> We need some kind of boot time support for alternate modes.
>
> The firmware will surely want to display something. So it is possible
> that we start the OS will a valid power contract. How do we deal
> with that? Renegotiate?
>

In one of my drivers, the PD protocol is running on an EC and the Linux
driver is just interfacing it to the typec class. I don't do any renegotiating
but just report the port state to the class. What is wrong with that, and why
would it not work ?

If the PD protocol runs in Linux (which I implement as well), I tried renegotiating,
ie assuming that a contract was already established, with several multi-function
adapters. Quite often those 'die' when trying tricks like that, and have to be manually
disconnected from power (on both ends) to get back to life. Granted, part of that
is that the firmware on those adapters is early and not as stable as I would like it
to be, but still that is a significant risk. I ended up always starting with error
recovery to avoid that kind of problem, at least for now. Even that doesn't always
help.

 > 2. Multiple GPUs
>
> How do we know which GPU is connected to which port?
>

Still working on it, but the basic idea (in my case) is to use devicetree data
or platform data if that is not available.

Guenter

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [RFC PATCHv2] usb: USB Type-C Connector Class
  2016-06-21 13:08 ` [RFC PATCHv2] " Oliver Neukum
  2016-06-21 13:24   ` Guenter Roeck
@ 2016-06-21 13:58   ` Heikki Krogerus
  2016-06-21 20:43     ` Oliver Neukum
  1 sibling, 1 reply; 98+ messages in thread
From: Heikki Krogerus @ 2016-06-21 13:58 UTC (permalink / raw)
  To: Oliver Neukum
  Cc: Guenter Roeck, Andy Shevchenko, Rajaram R, Felipe Balbi,
	Mathias Nyman, Greg KH, linux-kernel, linux-usb

On Tue, Jun 21, 2016 at 03:08:52PM +0200, Oliver Neukum wrote:
> On Thu, 2016-05-19 at 15:44 +0300, Heikki Krogerus wrote:
> > The purpose of this class is to provide unified interface for user
> > space to get the status and basic information about USB Type-C
> > Connectors in the system, control data role swapping, and when USB PD
> > is available, also power role swapping and Alternate Modes.
> 
> This raises two more questions.
> 
> 1. Booting
> 
> It is possible that our only display and, worse, our source
> of power is a display that can be used only in an alternate mode
> and is connected via a type C connector.
> 
> We need some kind of boot time support for alternate modes.
> 
> The firmware will surely want to display something. So it is possible
> that we start the OS will a valid power contract. How do we deal
> with that? Renegotiate?

Systems where the firmware has to negotiate PD will likely provide
firmware interface like UCSI, and where the OS has no direct
interaction with the USB PD transceiver. In these case there is no
need to renegotiate as we are just reporting in OS the initial state
after bootup.

We do have a system where the typec port is used to power the board.
On these systems the firmware does not communicate PD (so we will
never have the firmware displaying anything over Type-C on those
systems), but the USB PD chargers for example are detected as 3.0A
Type-C power supplies before any USB PD negotiation takes place, just
like the spec says, and that is more then enough to power these boards.

> 2. Multiple GPUs
> 
> How do we know which GPU is connected to which port?

With ACPI we will have to be able to bind the correct companion to the
device presenting the DP alternate mode under the port. Just like we
will have to bind the ACPI companion of the actual USB port to the
typec port device itself.


Cheers,

-- 
heikki

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [RFC PATCHv2] usb: USB Type-C Connector Class
  2016-06-21 13:24   ` Guenter Roeck
@ 2016-06-21 19:43     ` Oliver Neukum
  2016-06-21 21:37       ` Guenter Roeck
  0 siblings, 1 reply; 98+ messages in thread
From: Oliver Neukum @ 2016-06-21 19:43 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Heikki Krogerus, Andy Shevchenko, Rajaram R, Felipe Balbi,
	Mathias Nyman, Greg KH, linux-kernel, linux-usb

On Tue, 2016-06-21 at 06:24 -0700, Guenter Roeck wrote:
> On 06/21/2016 06:08 AM, Oliver Neukum wrote:
> > On Thu, 2016-05-19 at 15:44 +0300, Heikki Krogerus wrote:
> >> The purpose of this class is to provide unified interface for user
> >> space to get the status and basic information about USB Type-C
> >> Connectors in the system, control data role swapping, and when USB PD
> >> is available, also power role swapping and Alternate Modes.
> >
> > This raises two more questions.
> >
> > 1. Booting
> >
> > It is possible that our only display and, worse, our source
> > of power is a display that can be used only in an alternate mode
> > and is connected via a type C connector.
> >
> > We need some kind of boot time support for alternate modes.
> >
> > The firmware will surely want to display something. So it is possible
> > that we start the OS will a valid power contract. How do we deal
> > with that? Renegotiate?
> >
> 
> In one of my drivers, the PD protocol is running on an EC and the Linux

Is that code public?

> driver is just interfacing it to the typec class. I don't do any renegotiating
> but just report the port state to the class. What is wrong with that, and why
> would it not work ?

It is not wrong. But it is unclear how it would work if we pass control
between boot loader and OS. If I read the spec for TCPM and TCPC
correctly, we can read back the voltage, but not the agreed currents,
maximum currents and suspend rules. Yet we need those for power
budgeting.

We could reset, but then we leave the alternate mode.

	Regards
		Oliver

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [RFC PATCHv2] usb: USB Type-C Connector Class
  2016-06-21 13:58   ` Heikki Krogerus
@ 2016-06-21 20:43     ` Oliver Neukum
  2016-06-22  9:31       ` Heikki Krogerus
  0 siblings, 1 reply; 98+ messages in thread
From: Oliver Neukum @ 2016-06-21 20:43 UTC (permalink / raw)
  To: Heikki Krogerus
  Cc: Andy Shevchenko, Rajaram R, Felipe Balbi, Mathias Nyman, Greg KH,
	Guenter Roeck, linux-kernel, linux-usb

On Tue, 2016-06-21 at 16:58 +0300, Heikki Krogerus wrote:
> On Tue, Jun 21, 2016 at 03:08:52PM +0200, Oliver Neukum wrote:
>  
> > The firmware will surely want to display something. So it is possible
> > that we start the OS will a valid power contract. How do we deal
> > with that? Renegotiate?
> 
> Systems where the firmware has to negotiate PD will likely provide
> firmware interface like UCSI, and where the OS has no direct
> interaction with the USB PD transceiver. In these case there is no
> need to renegotiate as we are just reporting in OS the initial state
> after bootup.

How certain is that? I was under the impression that on many systems
the OS would speak to the TCPM directly.

> We do have a system where the typec port is used to power the board.
> On these systems the firmware does not communicate PD (so we will
> never have the firmware displaying anything over Type-C on those
> systems), but the USB PD chargers for example are detected as 3.0A
> Type-C power supplies before any USB PD negotiation takes place, just
> like the spec says, and that is more then enough to power these boards.

Now correct me, if I am misreading the spec. I am sure the system
will boot unless it needs ridiculous amounts of power, but
will we see anything on the screen? As far as I can tell the spec
actually says that you cannot enter an alternate mode without having
established a power contract.
If we really leave entering modes up to user space, we have lost
printk before getting into the initrd at the earliest.

	Regards
		Oliver

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [RFC PATCHv2] usb: USB Type-C Connector Class
  2016-06-21 19:43     ` Oliver Neukum
@ 2016-06-21 21:37       ` Guenter Roeck
  0 siblings, 0 replies; 98+ messages in thread
From: Guenter Roeck @ 2016-06-21 21:37 UTC (permalink / raw)
  To: Oliver Neukum
  Cc: Heikki Krogerus, Andy Shevchenko, Rajaram R, Felipe Balbi,
	Mathias Nyman, Greg KH, linux-kernel, linux-usb

On Tue, Jun 21, 2016 at 09:43:20PM +0200, Oliver Neukum wrote:
> On Tue, 2016-06-21 at 06:24 -0700, Guenter Roeck wrote:
> > On 06/21/2016 06:08 AM, Oliver Neukum wrote:
> > > On Thu, 2016-05-19 at 15:44 +0300, Heikki Krogerus wrote:
> > >> The purpose of this class is to provide unified interface for user
> > >> space to get the status and basic information about USB Type-C
> > >> Connectors in the system, control data role swapping, and when USB PD
> > >> is available, also power role swapping and Alternate Modes.
> > >
> > > This raises two more questions.
> > >
> > > 1. Booting
> > >
> > > It is possible that our only display and, worse, our source
> > > of power is a display that can be used only in an alternate mode
> > > and is connected via a type C connector.
> > >
> > > We need some kind of boot time support for alternate modes.
> > >
> > > The firmware will surely want to display something. So it is possible
> > > that we start the OS will a valid power contract. How do we deal
> > > with that? Renegotiate?
> > >
> > 
> > In one of my drivers, the PD protocol is running on an EC and the Linux
> 
> Is that code public?
> 
Pretty much, though it is not always up to date. It isn't pushed into an
official chromiumos kernel branch yet, but it is available in the repository
if one knows what to look for.

Unfortunately, it looks like I lost permission to create a sandbox in the
repository. I'll see what I can do to get that fixed.

> > driver is just interfacing it to the typec class. I don't do any renegotiating
> > but just report the port state to the class. What is wrong with that, and why
> > would it not work ?
> 
> It is not wrong. But it is unclear how it would work if we pass control
> between boot loader and OS. If I read the spec for TCPM and TCPC
> correctly, we can read back the voltage, but not the agreed currents,
> maximum currents and suspend rules. Yet we need those for power
> budgeting.
> 
The TCPC would not (necessarily) know that information, unfortunately.
I am not even sure about the negotiated voltage - are you sure the TCPC
would know it ?

> We could reset, but then we leave the alternate mode.
> 
Correct. I wasn't able to find a solution for that problem (yet). Going forward,
I can see that being an issue, for example if the BIOS/ROMMON negotiates a
contract but the TCPM running in the kernel doesn't know about it and thus has
to disconnect and reconnect the port.

Guenter

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [RFC PATCHv2] usb: USB Type-C Connector Class
  2016-06-21 20:43     ` Oliver Neukum
@ 2016-06-22  9:31       ` Heikki Krogerus
  2016-06-22 10:08         ` Oliver Neukum
  0 siblings, 1 reply; 98+ messages in thread
From: Heikki Krogerus @ 2016-06-22  9:31 UTC (permalink / raw)
  To: Oliver Neukum
  Cc: Andy Shevchenko, Rajaram R, Felipe Balbi, Mathias Nyman, Greg KH,
	Guenter Roeck, linux-kernel, linux-usb

Hi Oliver,

On Tue, Jun 21, 2016 at 10:43:05PM +0200, Oliver Neukum wrote:
> On Tue, 2016-06-21 at 16:58 +0300, Heikki Krogerus wrote:
> > On Tue, Jun 21, 2016 at 03:08:52PM +0200, Oliver Neukum wrote:
> >  
> > > The firmware will surely want to display something. So it is possible
> > > that we start the OS will a valid power contract. How do we deal
> > > with that? Renegotiate?
> > 
> > Systems where the firmware has to negotiate PD will likely provide
> > firmware interface like UCSI, and where the OS has no direct
> > interaction with the USB PD transceiver. In these case there is no
> > need to renegotiate as we are just reporting in OS the initial state
> > after bootup.
> 
> How certain is that? I was under the impression that on many systems
> the OS would speak to the TCPM directly.

I think we gonna see systems where the OS has access to TCPC and
where the TCPM is expected to be implemented in the OS, but we
will have quite a few systems where the TCPC/PD controller/non TCPC
compliant Type-C PHY is attached to a microcontroller like EC, and
where that microcontroller will implement TCPM and the OS is exposed
just a separate interface, most likely UCSI.

> > We do have a system where the typec port is used to power the board.
> > On these systems the firmware does not communicate PD (so we will
> > never have the firmware displaying anything over Type-C on those
> > systems), but the USB PD chargers for example are detected as 3.0A
> > Type-C power supplies before any USB PD negotiation takes place, just
> > like the spec says, and that is more then enough to power these boards.
> 
> Now correct me, if I am misreading the spec. I am sure the system
> will boot unless it needs ridiculous amounts of power, but
> will we see anything on the screen? As far as I can tell the spec
> actually says that you cannot enter an alternate mode without having
> established a power contract.
> If we really leave entering modes up to user space, we have lost
> printk before getting into the initrd at the earliest.

With these boards, you will not see anything on the screen that is
attached to a Type-C connector until the OS has booted to the point
where it has negotiated the power contract and entered a mode.

If the system has BIOS/FW/EC capable of negotiating the power contract
and enter a mode, but where we still are expected to take over the
whole TCPM in OS, I think the connection will be reset.


Thanks,

-- 
heikki

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [RFC PATCHv2] usb: USB Type-C Connector Class
  2016-06-22  9:31       ` Heikki Krogerus
@ 2016-06-22 10:08         ` Oliver Neukum
  2016-06-22 11:19           ` Heikki Krogerus
  2016-08-07 21:37           ` Pavel Machek
  0 siblings, 2 replies; 98+ messages in thread
From: Oliver Neukum @ 2016-06-22 10:08 UTC (permalink / raw)
  To: Heikki Krogerus
  Cc: Andy Shevchenko, Rajaram R, Felipe Balbi, Mathias Nyman, Greg KH,
	Guenter Roeck, linux-kernel, linux-usb

On Wed, 2016-06-22 at 12:31 +0300, Heikki Krogerus wrote:

Hi,

> > Now correct me, if I am misreading the spec. I am sure the system
> > will boot unless it needs ridiculous amounts of power, but
> > will we see anything on the screen? As far as I can tell the spec
> > actually says that you cannot enter an alternate mode without having
> > established a power contract.
> > If we really leave entering modes up to user space, we have lost
> > printk before getting into the initrd at the earliest.
> 
> With these boards, you will not see anything on the screen that is
> attached to a Type-C connector until the OS has booted to the point
> where it has negotiated the power contract and entered a mode.
> 
> If the system has BIOS/FW/EC capable of negotiating the power contract
> and enter a mode, but where we still are expected to take over the
> whole TCPM in OS, I think the connection will be reset.

Think about a DP over type C display with a USB PD power brick on a
daisy chain.
If the host needs more than 15W or more than 5V, a reset is suicide.

And losing earlyprintk hurts a lot.
This means we need USB PD statically in the kernel. And a kernel
based policy that brings up all displays.

	Regards
		Oliver

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [RFC PATCHv2] usb: USB Type-C Connector Class
  2016-06-22 10:08         ` Oliver Neukum
@ 2016-06-22 11:19           ` Heikki Krogerus
  2016-08-07 21:37           ` Pavel Machek
  1 sibling, 0 replies; 98+ messages in thread
From: Heikki Krogerus @ 2016-06-22 11:19 UTC (permalink / raw)
  To: Oliver Neukum
  Cc: Andy Shevchenko, Rajaram R, Felipe Balbi, Mathias Nyman, Greg KH,
	Guenter Roeck, linux-kernel, linux-usb

On Wed, Jun 22, 2016 at 12:08:57PM +0200, Oliver Neukum wrote:
> On Wed, 2016-06-22 at 12:31 +0300, Heikki Krogerus wrote:
> 
> Hi,
> 
> > > Now correct me, if I am misreading the spec. I am sure the system
> > > will boot unless it needs ridiculous amounts of power, but
> > > will we see anything on the screen? As far as I can tell the spec
> > > actually says that you cannot enter an alternate mode without having
> > > established a power contract.
> > > If we really leave entering modes up to user space, we have lost
> > > printk before getting into the initrd at the earliest.
> > 
> > With these boards, you will not see anything on the screen that is
> > attached to a Type-C connector until the OS has booted to the point
> > where it has negotiated the power contract and entered a mode.
> > 
> > If the system has BIOS/FW/EC capable of negotiating the power contract
> > and enter a mode, but where we still are expected to take over the
> > whole TCPM in OS, I think the connection will be reset.
> 
> Think about a DP over type C display with a USB PD power brick on a
> daisy chain.
> If the host needs more than 15W or more than 5V, a reset is suicide.

If the host needs more then 15W from Type-C to bootup, which does not
have enough capacitance the manage the renegotiation, I think will
always have only the FW interface (most likely UCSI) to deal with the
Type-C ports, if even that. The Thunderbolt3 controllers for example
don't give any details about or control over the Type-C ports to OS.
Though I think their firmwares may be made to support UCSI in the
future with some of them.

> And losing earlyprintk hurts a lot.
> This means we need USB PD statically in the kernel. And a kernel
> based policy that brings up all displays.

Yep.

I'm guessing these points are probable one of the major reason why the
control of the Type-C ports was made a responsibility of a discrete
microcontroller or the FW in general.


Thanks,

-- 
heikki

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [RFC PATCHv2] usb: USB Type-C Connector Class
  2016-06-22 10:08         ` Oliver Neukum
  2016-06-22 11:19           ` Heikki Krogerus
@ 2016-08-07 21:37           ` Pavel Machek
  2016-08-08  8:52             ` Oliver Neukum
  1 sibling, 1 reply; 98+ messages in thread
From: Pavel Machek @ 2016-08-07 21:37 UTC (permalink / raw)
  To: Oliver Neukum
  Cc: Heikki Krogerus, Andy Shevchenko, Rajaram R, Felipe Balbi,
	Mathias Nyman, Greg KH, Guenter Roeck, linux-kernel, linux-usb

Hi!

> > With these boards, you will not see anything on the screen that is
> > attached to a Type-C connector until the OS has booted to the point
> > where it has negotiated the power contract and entered a mode.
> > 
> > If the system has BIOS/FW/EC capable of negotiating the power contract
> > and enter a mode, but where we still are expected to take over the
> > whole TCPM in OS, I think the connection will be reset.
> 
> Think about a DP over type C display with a USB PD power brick on a
> daisy chain.
> If the host needs more than 15W or more than 5V, a reset is suicide.
> 
> And losing earlyprintk hurts a lot.
> This means we need USB PD statically in the kernel. And a kernel
> based policy that brings up all displays.

Yes please.

Of course, even that will hurt, because I guess that means printk()
after USB, and that means late in the boot process, but better late in
kernel than in initrd.

(And yes, N900 has display pretty late in the bootprocess, and yes, it
is very annoying.)

Best regards,
									Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [RFC PATCHv2] usb: USB Type-C Connector Class
  2016-08-07 21:37           ` Pavel Machek
@ 2016-08-08  8:52             ` Oliver Neukum
  0 siblings, 0 replies; 98+ messages in thread
From: Oliver Neukum @ 2016-08-08  8:52 UTC (permalink / raw)
  To: Pavel Machek
  Cc: Andy Shevchenko, Rajaram R, Felipe Balbi, Heikki Krogerus,
	Mathias Nyman, Greg KH, Guenter Roeck, linux-kernel, linux-usb

On Sun, 2016-08-07 at 23:37 +0200, Pavel Machek wrote:
> Hi!
> 
> > > With these boards, you will not see anything on the screen that is
> > > attached to a Type-C connector until the OS has booted to the point
> > > where it has negotiated the power contract and entered a mode.
> > > 
> > > If the system has BIOS/FW/EC capable of negotiating the power contract
> > > and enter a mode, but where we still are expected to take over the
> > > whole TCPM in OS, I think the connection will be reset.
> > 
> > Think about a DP over type C display with a USB PD power brick on a
> > daisy chain.
> > If the host needs more than 15W or more than 5V, a reset is suicide.
> > 
> > And losing earlyprintk hurts a lot.
> > This means we need USB PD statically in the kernel. And a kernel
> > based policy that brings up all displays.
> 
> Yes please.
> 
> Of course, even that will hurt, because I guess that means printk()
> after USB, and that means late in the boot process, but better late in
> kernel than in initrd.

i can confirm that in a laptop with a decent firmware a docking
station is switched into the mode that will make the display work.
In principle all is well if we can manage a handover.

	Regards
		Oliver

^ permalink raw reply	[flat|nested] 98+ messages in thread

end of thread, other threads:[~2016-08-08  8:57 UTC | newest]

Thread overview: 98+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-05-19 12:44 [RFC PATCHv2] usb: USB Type-C Connector Class Heikki Krogerus
2016-05-19 14:47 ` Oliver Neukum
2016-05-20 11:24   ` Heikki Krogerus
2016-05-20 13:37     ` Oliver Neukum
2016-05-21  5:51       ` Guenter Roeck
2016-05-21  6:43         ` Oliver Neukum
2016-05-22 15:54           ` Guenter Roeck
2016-05-23  5:34             ` Oliver Neukum
2016-05-23 13:27               ` Guenter Roeck
2016-05-23 13:58                 ` Oliver Neukum
2016-05-23 14:43                   ` Guenter Roeck
2016-05-23 15:55                     ` Oliver Neukum
2016-05-23 16:52                       ` Guenter Roeck
2016-05-24 10:08                         ` Heikki Krogerus
2016-05-24 10:18                           ` Oliver Neukum
2016-05-24 11:04                             ` Heikki Krogerus
2016-05-19 14:48 ` Oliver Neukum
2016-05-19 15:43   ` Greg KH
2016-05-20 10:58     ` Heikki Krogerus
2016-05-19 17:53 ` Guenter Roeck
2016-05-20 10:47   ` Heikki Krogerus
2016-05-20 17:02     ` Guenter Roeck
2016-05-23  9:23       ` Heikki Krogerus
2016-05-20 14:19 ` Oliver Neukum
2016-05-23  9:57   ` Heikki Krogerus
2016-05-23 11:25     ` Oliver Neukum
2016-05-23 17:09       ` Guenter Roeck
2016-05-24  9:06         ` Oliver Neukum
2016-05-24  9:32       ` Heikki Krogerus
2016-05-24 12:51 ` Oliver Neukum
2016-05-25 11:28   ` Heikki Krogerus
2016-05-25 15:19     ` Guenter Roeck
2016-05-27  7:30       ` Heikki Krogerus
2016-05-24 13:42 ` Guenter Roeck
2016-05-25 11:30   ` Heikki Krogerus
2016-05-25 13:12     ` Guenter Roeck
2016-05-24 19:28 ` Guenter Roeck
2016-05-25 11:51   ` Heikki Krogerus
2016-05-25 13:21     ` Guenter Roeck
2016-05-25 14:04       ` Heikki Krogerus
2016-05-25 14:20         ` Oliver Neukum
2016-05-25 14:59           ` Guenter Roeck
2016-05-27  7:29             ` Heikki Krogerus
2016-05-25 18:35 ` [RFC PATCH] usb: typec: Various API updates and fixes Guenter Roeck
2016-05-27  7:55   ` Heikki Krogerus
2016-05-27 14:06     ` Guenter Roeck
2016-05-30 12:48       ` Heikki Krogerus
2016-05-30 13:19 ` [RFC PATCHv2] usb: USB Type-C Connector Class Heikki Krogerus
2016-05-30 13:59   ` Oliver Neukum
2016-05-31  8:31     ` Heikki Krogerus
2016-05-31  8:48       ` Oliver Neukum
2016-05-31 12:09         ` Heikki Krogerus
2016-05-31 12:43           ` Heikki Krogerus
2016-05-31 17:20             ` Guenter Roeck
2016-06-01  8:23               ` Heikki Krogerus
2016-06-01  8:31                 ` Oliver Neukum
2016-06-01  9:04                 ` Oliver Neukum
2016-06-01 13:34                   ` Guenter Roeck
2016-06-02  6:24                     ` Oliver Neukum
2016-06-02  6:37                       ` Guenter Roeck
2016-06-02  7:43                         ` Oliver Neukum
2016-05-31 17:14       ` Guenter Roeck
2016-06-01  9:26 ` Oliver Neukum
2016-06-01 23:29   ` Guenter Roeck
2016-06-02  6:30     ` Oliver Neukum
2016-06-02  8:27       ` Heikki Krogerus
2016-06-02 10:18     ` Heikki Krogerus
2016-06-02 16:12       ` Guenter Roeck
2016-06-03 13:21         ` Heikki Krogerus
2016-06-03 13:51           ` Guenter Roeck
2016-06-03 15:17             ` Heikki Krogerus
2016-06-03 18:39               ` Guenter Roeck
2016-06-06 13:28                 ` Heikki Krogerus
2016-06-06 13:35                   ` Oliver Neukum
2016-06-07  8:23                     ` Heikki Krogerus
2016-06-07 16:57                   ` Guenter Roeck
2016-06-02  8:02   ` Heikki Krogerus
2016-06-03 20:20 ` Pavel Machek
2016-06-06 13:45   ` Heikki Krogerus
2016-06-06 14:41     ` Greg KH
2016-06-07  8:25       ` Heikki Krogerus
2016-06-06 16:02     ` Guenter Roeck
2016-06-10 14:34 ` [RFC PATCHv3] " Heikki Krogerus
2016-06-11  7:05   ` Oliver Neukum
2016-06-11 18:03     ` Guenter Roeck
2016-06-13  7:49       ` Heikki Krogerus
2016-06-13  7:48     ` Heikki Krogerus
2016-06-21 13:08 ` [RFC PATCHv2] " Oliver Neukum
2016-06-21 13:24   ` Guenter Roeck
2016-06-21 19:43     ` Oliver Neukum
2016-06-21 21:37       ` Guenter Roeck
2016-06-21 13:58   ` Heikki Krogerus
2016-06-21 20:43     ` Oliver Neukum
2016-06-22  9:31       ` Heikki Krogerus
2016-06-22 10:08         ` Oliver Neukum
2016-06-22 11:19           ` Heikki Krogerus
2016-08-07 21:37           ` Pavel Machek
2016-08-08  8:52             ` Oliver Neukum

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).