mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-30 22:26:55 +00:00
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>
This commit is contained in:
parent
59de2a56d1
commit
11110783f5
3 changed files with 24 additions and 2 deletions
|
@ -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)
|
||||||
|
|
||||||
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 @@
|
||||||
#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 {
|
||||||
* @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 {
|
||||||
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)
|
||||||
|
|
||||||
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
|
||||||
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;
|
||||||
|
}
|
||||||
|
|
||||||
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 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 = {
|
||||||
|
|
Loading…
Reference in a new issue