Commit 11110783 authored by Heikki Krogerus's avatar Heikki Krogerus Committed by Greg Kroah-Hartman

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: default avatarBenson Leung <bleung@chromium.org>
Tested-by: default avatarBenson Leung <bleung@chromium.org>
Signed-off-by: default avatarHeikki Krogerus <heikki.krogerus@linux.intel.com>
Link: https://lore.kernel.org/r/20231011105825.320062-3-heikki.krogerus@linux.intel.comSigned-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 59de2a56
...@@ -2274,6 +2274,8 @@ void usb_disconnect(struct usb_device **pdev) ...@@ -2274,6 +2274,8 @@ void usb_disconnect(struct usb_device **pdev)
*/ */
if (!test_and_set_bit(port1, hub->child_usage_bits)) if (!test_and_set_bit(port1, hub->child_usage_bits))
pm_runtime_get_sync(&port_dev->dev); pm_runtime_get_sync(&port_dev->dev);
typec_deattach(port_dev->connector, &udev->dev);
} }
usb_remove_ep_devs(&udev->ep0); usb_remove_ep_devs(&udev->ep0);
...@@ -2620,6 +2622,8 @@ int usb_new_device(struct usb_device *udev) ...@@ -2620,6 +2622,8 @@ int usb_new_device(struct usb_device *udev)
if (!test_and_set_bit(port1, hub->child_usage_bits)) if (!test_and_set_bit(port1, hub->child_usage_bits))
pm_runtime_get_sync(&port_dev->dev); pm_runtime_get_sync(&port_dev->dev);
typec_attach(port_dev->connector, &udev->dev);
} }
(void) usb_create_ep_devs(&udev->dev, &udev->ep0, udev); (void) usb_create_ep_devs(&udev->dev, &udev->ep0, udev);
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include <linux/usb.h> #include <linux/usb.h>
#include <linux/usb/ch11.h> #include <linux/usb/ch11.h>
#include <linux/usb/hcd.h> #include <linux/usb/hcd.h>
#include <linux/usb/typec.h>
#include "usb.h" #include "usb.h"
struct usb_hub { struct usb_hub {
...@@ -82,6 +83,7 @@ struct usb_hub { ...@@ -82,6 +83,7 @@ struct usb_hub {
* @dev: generic device interface * @dev: generic device interface
* @port_owner: port's owner * @port_owner: port's owner
* @peer: related usb2 and usb3 ports (share the same connector) * @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 * @req: default pm qos request for hubs without port power control
* @connect_type: port's connect type * @connect_type: port's connect type
* @state: device state of the usb device attached to the port * @state: device state of the usb device attached to the port
...@@ -100,6 +102,7 @@ struct usb_port { ...@@ -100,6 +102,7 @@ struct usb_port {
struct device dev; struct device dev;
struct usb_dev_state *port_owner; struct usb_dev_state *port_owner;
struct usb_port *peer; struct usb_port *peer;
struct typec_connector *connector;
struct dev_pm_qos_request *req; struct dev_pm_qos_request *req;
enum usb_port_connect_type connect_type; enum usb_port_connect_type connect_type;
enum usb_device_state state; enum usb_device_state state;
......
...@@ -653,6 +653,7 @@ static void find_and_link_peer(struct usb_hub *hub, int port1) ...@@ -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) static int connector_bind(struct device *dev, struct device *connector, void *data)
{ {
struct usb_port *port_dev = to_usb_port(dev);
int ret; int ret;
ret = sysfs_create_link(&dev->kobj, &connector->kobj, "connector"); 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 ...@@ -660,16 +661,30 @@ static int connector_bind(struct device *dev, struct device *connector, void *da
return ret; return ret;
ret = sysfs_create_link(&connector->kobj, &dev->kobj, dev_name(dev)); ret = sysfs_create_link(&connector->kobj, &dev->kobj, dev_name(dev));
if (ret) if (ret) {
sysfs_remove_link(&dev->kobj, "connector"); 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) 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(&connector->kobj, dev_name(dev));
sysfs_remove_link(&dev->kobj, "connector"); sysfs_remove_link(&dev->kobj, "connector");
port_dev->connector = NULL;
} }
static const struct component_ops connector_ops = { static const struct component_ops connector_ops = {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment