Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Heikki Krogerus and committed by
Greg Kroah-Hartman
11110783 59de2a56

+24 -2
+4
drivers/usb/core/hub.c
··· 2274 2274 */ 2275 2275 if (!test_and_set_bit(port1, hub->child_usage_bits)) 2276 2276 pm_runtime_get_sync(&port_dev->dev); 2277 + 2278 + typec_deattach(port_dev->connector, &udev->dev); 2277 2279 } 2278 2280 2279 2281 usb_remove_ep_devs(&udev->ep0); ··· 2622 2620 2623 2621 if (!test_and_set_bit(port1, hub->child_usage_bits)) 2624 2622 pm_runtime_get_sync(&port_dev->dev); 2623 + 2624 + typec_attach(port_dev->connector, &udev->dev); 2625 2625 } 2626 2626 2627 2627 (void) usb_create_ep_devs(&udev->dev, &udev->ep0, udev);
+3
drivers/usb/core/hub.h
··· 14 14 #include <linux/usb.h> 15 15 #include <linux/usb/ch11.h> 16 16 #include <linux/usb/hcd.h> 17 + #include <linux/usb/typec.h> 17 18 #include "usb.h" 18 19 19 20 struct usb_hub { ··· 83 82 * @dev: generic device interface 84 83 * @port_owner: port's owner 85 84 * @peer: related usb2 and usb3 ports (share the same connector) 85 + * @connector: USB Type-C connector 86 86 * @req: default pm qos request for hubs without port power control 87 87 * @connect_type: port's connect type 88 88 * @state: device state of the usb device attached to the port ··· 102 100 struct device dev; 103 101 struct usb_dev_state *port_owner; 104 102 struct usb_port *peer; 103 + struct typec_connector *connector; 105 104 struct dev_pm_qos_request *req; 106 105 enum usb_port_connect_type connect_type; 107 106 enum usb_device_state state;
+17 -2
drivers/usb/core/port.c
··· 653 653 654 654 static int connector_bind(struct device *dev, struct device *connector, void *data) 655 655 { 656 + struct usb_port *port_dev = to_usb_port(dev); 656 657 int ret; 657 658 658 659 ret = sysfs_create_link(&dev->kobj, &connector->kobj, "connector"); ··· 661 660 return ret; 662 661 663 662 ret = sysfs_create_link(&connector->kobj, &dev->kobj, dev_name(dev)); 664 - if (ret) 663 + if (ret) { 665 664 sysfs_remove_link(&dev->kobj, "connector"); 665 + return ret; 666 + } 666 667 667 - return ret; 668 + port_dev->connector = data; 669 + 670 + /* 671 + * If there is already USB device connected to the port, letting the 672 + * Type-C connector know about it immediately. 673 + */ 674 + if (port_dev->child) 675 + typec_attach(port_dev->connector, &port_dev->child->dev); 676 + 677 + return 0; 668 678 } 669 679 670 680 static void connector_unbind(struct device *dev, struct device *connector, void *data) 671 681 { 682 + struct usb_port *port_dev = to_usb_port(dev); 683 + 672 684 sysfs_remove_link(&connector->kobj, dev_name(dev)); 673 685 sysfs_remove_link(&dev->kobj, "connector"); 686 + port_dev->connector = NULL; 674 687 } 675 688 676 689 static const struct component_ops connector_ops = {