diff options
author | Heikki Krogerus <heikki.krogerus@linux.intel.com> | 2023-10-11 13:58:25 +0300 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2023-10-16 21:02:36 +0300 |
commit | 11110783f5ea866318831a56353c6f1c3fc0d8ed (patch) | |
tree | 4cd4afbf946dbcaab34e81c7366f941cd4124efd /drivers | |
parent | 59de2a56d127890cc610f3896d5fc31887c54ac2 (diff) | |
download | linux-11110783f5ea866318831a56353c6f1c3fc0d8ed.tar.xz |
usb: Inform the USB Type-C class about enumerated devices
The Type-C port drivers can make PM related decisions based
on is the device USB3 or USB2.
Suggested-by: Benson Leung <bleung@chromium.org>
Tested-by: Benson Leung <bleung@chromium.org>
Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Link: https://lore.kernel.org/r/20231011105825.320062-3-heikki.krogerus@linux.intel.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/usb/core/hub.c | 4 | ||||
-rw-r--r-- | drivers/usb/core/hub.h | 3 | ||||
-rw-r--r-- | drivers/usb/core/port.c | 19 |
3 files changed, 24 insertions, 2 deletions
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 0ff47eeffb49..b4584a0cd484 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -2274,6 +2274,8 @@ void usb_disconnect(struct usb_device **pdev) */ if (!test_and_set_bit(port1, hub->child_usage_bits)) pm_runtime_get_sync(&port_dev->dev); + + typec_deattach(port_dev->connector, &udev->dev); } usb_remove_ep_devs(&udev->ep0); @@ -2620,6 +2622,8 @@ int usb_new_device(struct usb_device *udev) if (!test_and_set_bit(port1, hub->child_usage_bits)) pm_runtime_get_sync(&port_dev->dev); + + typec_attach(port_dev->connector, &udev->dev); } (void) usb_create_ep_devs(&udev->dev, &udev->ep0, udev); diff --git a/drivers/usb/core/hub.h b/drivers/usb/core/hub.h index d44dd7f6623e..43ce21c96a51 100644 --- a/drivers/usb/core/hub.h +++ b/drivers/usb/core/hub.h @@ -14,6 +14,7 @@ #include <linux/usb.h> #include <linux/usb/ch11.h> #include <linux/usb/hcd.h> +#include <linux/usb/typec.h> #include "usb.h" struct usb_hub { @@ -82,6 +83,7 @@ struct usb_hub { * @dev: generic device interface * @port_owner: port's owner * @peer: related usb2 and usb3 ports (share the same connector) + * @connector: USB Type-C connector * @req: default pm qos request for hubs without port power control * @connect_type: port's connect type * @state: device state of the usb device attached to the port @@ -100,6 +102,7 @@ struct usb_port { struct device dev; struct usb_dev_state *port_owner; struct usb_port *peer; + struct typec_connector *connector; struct dev_pm_qos_request *req; enum usb_port_connect_type connect_type; enum usb_device_state state; diff --git a/drivers/usb/core/port.c b/drivers/usb/core/port.c index 77be0dc28da9..149bedb8e64f 100644 --- a/drivers/usb/core/port.c +++ b/drivers/usb/core/port.c @@ -653,6 +653,7 @@ static void find_and_link_peer(struct usb_hub *hub, int port1) static int connector_bind(struct device *dev, struct device *connector, void *data) { + struct usb_port *port_dev = to_usb_port(dev); int ret; ret = sysfs_create_link(&dev->kobj, &connector->kobj, "connector"); @@ -660,16 +661,30 @@ static int connector_bind(struct device *dev, struct device *connector, void *da return ret; ret = sysfs_create_link(&connector->kobj, &dev->kobj, dev_name(dev)); - if (ret) + if (ret) { sysfs_remove_link(&dev->kobj, "connector"); + return ret; + } + + port_dev->connector = data; + + /* + * If there is already USB device connected to the port, letting the + * Type-C connector know about it immediately. + */ + if (port_dev->child) + typec_attach(port_dev->connector, &port_dev->child->dev); - return ret; + return 0; } static void connector_unbind(struct device *dev, struct device *connector, void *data) { + struct usb_port *port_dev = to_usb_port(dev); + sysfs_remove_link(&connector->kobj, dev_name(dev)); sysfs_remove_link(&dev->kobj, "connector"); + port_dev->connector = NULL; } static const struct component_ops connector_ops = { |