18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * drivers/usb/driver.c - most of the driver model stuff for usb
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * (C) Copyright 2005 Greg Kroah-Hartman <gregkh@suse.de>
68c2ecf20Sopenharmony_ci *
78c2ecf20Sopenharmony_ci * based on drivers/usb/usb.c which had the following copyrights:
88c2ecf20Sopenharmony_ci *	(C) Copyright Linus Torvalds 1999
98c2ecf20Sopenharmony_ci *	(C) Copyright Johannes Erdfelt 1999-2001
108c2ecf20Sopenharmony_ci *	(C) Copyright Andreas Gal 1999
118c2ecf20Sopenharmony_ci *	(C) Copyright Gregory P. Smith 1999
128c2ecf20Sopenharmony_ci *	(C) Copyright Deti Fliegl 1999 (new USB architecture)
138c2ecf20Sopenharmony_ci *	(C) Copyright Randy Dunlap 2000
148c2ecf20Sopenharmony_ci *	(C) Copyright David Brownell 2000-2004
158c2ecf20Sopenharmony_ci *	(C) Copyright Yggdrasil Computing, Inc. 2000
168c2ecf20Sopenharmony_ci *		(usb_device_id matching changes by Adam J. Richter)
178c2ecf20Sopenharmony_ci *	(C) Copyright Greg Kroah-Hartman 2002-2003
188c2ecf20Sopenharmony_ci *
198c2ecf20Sopenharmony_ci * Released under the GPLv2 only.
208c2ecf20Sopenharmony_ci *
218c2ecf20Sopenharmony_ci * NOTE! This is not actually a driver at all, rather this is
228c2ecf20Sopenharmony_ci * just a collection of helper routines that implement the
238c2ecf20Sopenharmony_ci * matching, probing, releasing, suspending and resuming for
248c2ecf20Sopenharmony_ci * real drivers.
258c2ecf20Sopenharmony_ci *
268c2ecf20Sopenharmony_ci */
278c2ecf20Sopenharmony_ci
288c2ecf20Sopenharmony_ci#include <linux/device.h>
298c2ecf20Sopenharmony_ci#include <linux/slab.h>
308c2ecf20Sopenharmony_ci#include <linux/export.h>
318c2ecf20Sopenharmony_ci#include <linux/usb.h>
328c2ecf20Sopenharmony_ci#include <linux/usb/quirks.h>
338c2ecf20Sopenharmony_ci#include <linux/usb/hcd.h>
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_ci#include "usb.h"
368c2ecf20Sopenharmony_ci
378c2ecf20Sopenharmony_ci
388c2ecf20Sopenharmony_ci/*
398c2ecf20Sopenharmony_ci * Adds a new dynamic USBdevice ID to this driver,
408c2ecf20Sopenharmony_ci * and cause the driver to probe for all devices again.
418c2ecf20Sopenharmony_ci */
428c2ecf20Sopenharmony_cissize_t usb_store_new_id(struct usb_dynids *dynids,
438c2ecf20Sopenharmony_ci			 const struct usb_device_id *id_table,
448c2ecf20Sopenharmony_ci			 struct device_driver *driver,
458c2ecf20Sopenharmony_ci			 const char *buf, size_t count)
468c2ecf20Sopenharmony_ci{
478c2ecf20Sopenharmony_ci	struct usb_dynid *dynid;
488c2ecf20Sopenharmony_ci	u32 idVendor = 0;
498c2ecf20Sopenharmony_ci	u32 idProduct = 0;
508c2ecf20Sopenharmony_ci	unsigned int bInterfaceClass = 0;
518c2ecf20Sopenharmony_ci	u32 refVendor, refProduct;
528c2ecf20Sopenharmony_ci	int fields = 0;
538c2ecf20Sopenharmony_ci	int retval = 0;
548c2ecf20Sopenharmony_ci
558c2ecf20Sopenharmony_ci	fields = sscanf(buf, "%x %x %x %x %x", &idVendor, &idProduct,
568c2ecf20Sopenharmony_ci			&bInterfaceClass, &refVendor, &refProduct);
578c2ecf20Sopenharmony_ci	if (fields < 2)
588c2ecf20Sopenharmony_ci		return -EINVAL;
598c2ecf20Sopenharmony_ci
608c2ecf20Sopenharmony_ci	dynid = kzalloc(sizeof(*dynid), GFP_KERNEL);
618c2ecf20Sopenharmony_ci	if (!dynid)
628c2ecf20Sopenharmony_ci		return -ENOMEM;
638c2ecf20Sopenharmony_ci
648c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&dynid->node);
658c2ecf20Sopenharmony_ci	dynid->id.idVendor = idVendor;
668c2ecf20Sopenharmony_ci	dynid->id.idProduct = idProduct;
678c2ecf20Sopenharmony_ci	dynid->id.match_flags = USB_DEVICE_ID_MATCH_DEVICE;
688c2ecf20Sopenharmony_ci	if (fields > 2 && bInterfaceClass) {
698c2ecf20Sopenharmony_ci		if (bInterfaceClass > 255) {
708c2ecf20Sopenharmony_ci			retval = -EINVAL;
718c2ecf20Sopenharmony_ci			goto fail;
728c2ecf20Sopenharmony_ci		}
738c2ecf20Sopenharmony_ci
748c2ecf20Sopenharmony_ci		dynid->id.bInterfaceClass = (u8)bInterfaceClass;
758c2ecf20Sopenharmony_ci		dynid->id.match_flags |= USB_DEVICE_ID_MATCH_INT_CLASS;
768c2ecf20Sopenharmony_ci	}
778c2ecf20Sopenharmony_ci
788c2ecf20Sopenharmony_ci	if (fields > 4) {
798c2ecf20Sopenharmony_ci		const struct usb_device_id *id = id_table;
808c2ecf20Sopenharmony_ci
818c2ecf20Sopenharmony_ci		if (!id) {
828c2ecf20Sopenharmony_ci			retval = -ENODEV;
838c2ecf20Sopenharmony_ci			goto fail;
848c2ecf20Sopenharmony_ci		}
858c2ecf20Sopenharmony_ci
868c2ecf20Sopenharmony_ci		for (; id->match_flags; id++)
878c2ecf20Sopenharmony_ci			if (id->idVendor == refVendor && id->idProduct == refProduct)
888c2ecf20Sopenharmony_ci				break;
898c2ecf20Sopenharmony_ci
908c2ecf20Sopenharmony_ci		if (id->match_flags) {
918c2ecf20Sopenharmony_ci			dynid->id.driver_info = id->driver_info;
928c2ecf20Sopenharmony_ci		} else {
938c2ecf20Sopenharmony_ci			retval = -ENODEV;
948c2ecf20Sopenharmony_ci			goto fail;
958c2ecf20Sopenharmony_ci		}
968c2ecf20Sopenharmony_ci	}
978c2ecf20Sopenharmony_ci
988c2ecf20Sopenharmony_ci	spin_lock(&dynids->lock);
998c2ecf20Sopenharmony_ci	list_add_tail(&dynid->node, &dynids->list);
1008c2ecf20Sopenharmony_ci	spin_unlock(&dynids->lock);
1018c2ecf20Sopenharmony_ci
1028c2ecf20Sopenharmony_ci	retval = driver_attach(driver);
1038c2ecf20Sopenharmony_ci
1048c2ecf20Sopenharmony_ci	if (retval)
1058c2ecf20Sopenharmony_ci		return retval;
1068c2ecf20Sopenharmony_ci	return count;
1078c2ecf20Sopenharmony_ci
1088c2ecf20Sopenharmony_cifail:
1098c2ecf20Sopenharmony_ci	kfree(dynid);
1108c2ecf20Sopenharmony_ci	return retval;
1118c2ecf20Sopenharmony_ci}
1128c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(usb_store_new_id);
1138c2ecf20Sopenharmony_ci
1148c2ecf20Sopenharmony_cissize_t usb_show_dynids(struct usb_dynids *dynids, char *buf)
1158c2ecf20Sopenharmony_ci{
1168c2ecf20Sopenharmony_ci	struct usb_dynid *dynid;
1178c2ecf20Sopenharmony_ci	size_t count = 0;
1188c2ecf20Sopenharmony_ci
1198c2ecf20Sopenharmony_ci	list_for_each_entry(dynid, &dynids->list, node)
1208c2ecf20Sopenharmony_ci		if (dynid->id.bInterfaceClass != 0)
1218c2ecf20Sopenharmony_ci			count += scnprintf(&buf[count], PAGE_SIZE - count, "%04x %04x %02x\n",
1228c2ecf20Sopenharmony_ci					   dynid->id.idVendor, dynid->id.idProduct,
1238c2ecf20Sopenharmony_ci					   dynid->id.bInterfaceClass);
1248c2ecf20Sopenharmony_ci		else
1258c2ecf20Sopenharmony_ci			count += scnprintf(&buf[count], PAGE_SIZE - count, "%04x %04x\n",
1268c2ecf20Sopenharmony_ci					   dynid->id.idVendor, dynid->id.idProduct);
1278c2ecf20Sopenharmony_ci	return count;
1288c2ecf20Sopenharmony_ci}
1298c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(usb_show_dynids);
1308c2ecf20Sopenharmony_ci
1318c2ecf20Sopenharmony_cistatic ssize_t new_id_show(struct device_driver *driver, char *buf)
1328c2ecf20Sopenharmony_ci{
1338c2ecf20Sopenharmony_ci	struct usb_driver *usb_drv = to_usb_driver(driver);
1348c2ecf20Sopenharmony_ci
1358c2ecf20Sopenharmony_ci	return usb_show_dynids(&usb_drv->dynids, buf);
1368c2ecf20Sopenharmony_ci}
1378c2ecf20Sopenharmony_ci
1388c2ecf20Sopenharmony_cistatic ssize_t new_id_store(struct device_driver *driver,
1398c2ecf20Sopenharmony_ci			    const char *buf, size_t count)
1408c2ecf20Sopenharmony_ci{
1418c2ecf20Sopenharmony_ci	struct usb_driver *usb_drv = to_usb_driver(driver);
1428c2ecf20Sopenharmony_ci
1438c2ecf20Sopenharmony_ci	return usb_store_new_id(&usb_drv->dynids, usb_drv->id_table, driver, buf, count);
1448c2ecf20Sopenharmony_ci}
1458c2ecf20Sopenharmony_cistatic DRIVER_ATTR_RW(new_id);
1468c2ecf20Sopenharmony_ci
1478c2ecf20Sopenharmony_ci/*
1488c2ecf20Sopenharmony_ci * Remove a USB device ID from this driver
1498c2ecf20Sopenharmony_ci */
1508c2ecf20Sopenharmony_cistatic ssize_t remove_id_store(struct device_driver *driver, const char *buf,
1518c2ecf20Sopenharmony_ci			       size_t count)
1528c2ecf20Sopenharmony_ci{
1538c2ecf20Sopenharmony_ci	struct usb_dynid *dynid, *n;
1548c2ecf20Sopenharmony_ci	struct usb_driver *usb_driver = to_usb_driver(driver);
1558c2ecf20Sopenharmony_ci	u32 idVendor;
1568c2ecf20Sopenharmony_ci	u32 idProduct;
1578c2ecf20Sopenharmony_ci	int fields;
1588c2ecf20Sopenharmony_ci
1598c2ecf20Sopenharmony_ci	fields = sscanf(buf, "%x %x", &idVendor, &idProduct);
1608c2ecf20Sopenharmony_ci	if (fields < 2)
1618c2ecf20Sopenharmony_ci		return -EINVAL;
1628c2ecf20Sopenharmony_ci
1638c2ecf20Sopenharmony_ci	spin_lock(&usb_driver->dynids.lock);
1648c2ecf20Sopenharmony_ci	list_for_each_entry_safe(dynid, n, &usb_driver->dynids.list, node) {
1658c2ecf20Sopenharmony_ci		struct usb_device_id *id = &dynid->id;
1668c2ecf20Sopenharmony_ci
1678c2ecf20Sopenharmony_ci		if ((id->idVendor == idVendor) &&
1688c2ecf20Sopenharmony_ci		    (id->idProduct == idProduct)) {
1698c2ecf20Sopenharmony_ci			list_del(&dynid->node);
1708c2ecf20Sopenharmony_ci			kfree(dynid);
1718c2ecf20Sopenharmony_ci			break;
1728c2ecf20Sopenharmony_ci		}
1738c2ecf20Sopenharmony_ci	}
1748c2ecf20Sopenharmony_ci	spin_unlock(&usb_driver->dynids.lock);
1758c2ecf20Sopenharmony_ci	return count;
1768c2ecf20Sopenharmony_ci}
1778c2ecf20Sopenharmony_ci
1788c2ecf20Sopenharmony_cistatic ssize_t remove_id_show(struct device_driver *driver, char *buf)
1798c2ecf20Sopenharmony_ci{
1808c2ecf20Sopenharmony_ci	return new_id_show(driver, buf);
1818c2ecf20Sopenharmony_ci}
1828c2ecf20Sopenharmony_cistatic DRIVER_ATTR_RW(remove_id);
1838c2ecf20Sopenharmony_ci
1848c2ecf20Sopenharmony_cistatic int usb_create_newid_files(struct usb_driver *usb_drv)
1858c2ecf20Sopenharmony_ci{
1868c2ecf20Sopenharmony_ci	int error = 0;
1878c2ecf20Sopenharmony_ci
1888c2ecf20Sopenharmony_ci	if (usb_drv->no_dynamic_id)
1898c2ecf20Sopenharmony_ci		goto exit;
1908c2ecf20Sopenharmony_ci
1918c2ecf20Sopenharmony_ci	if (usb_drv->probe != NULL) {
1928c2ecf20Sopenharmony_ci		error = driver_create_file(&usb_drv->drvwrap.driver,
1938c2ecf20Sopenharmony_ci					   &driver_attr_new_id);
1948c2ecf20Sopenharmony_ci		if (error == 0) {
1958c2ecf20Sopenharmony_ci			error = driver_create_file(&usb_drv->drvwrap.driver,
1968c2ecf20Sopenharmony_ci					&driver_attr_remove_id);
1978c2ecf20Sopenharmony_ci			if (error)
1988c2ecf20Sopenharmony_ci				driver_remove_file(&usb_drv->drvwrap.driver,
1998c2ecf20Sopenharmony_ci						&driver_attr_new_id);
2008c2ecf20Sopenharmony_ci		}
2018c2ecf20Sopenharmony_ci	}
2028c2ecf20Sopenharmony_ciexit:
2038c2ecf20Sopenharmony_ci	return error;
2048c2ecf20Sopenharmony_ci}
2058c2ecf20Sopenharmony_ci
2068c2ecf20Sopenharmony_cistatic void usb_remove_newid_files(struct usb_driver *usb_drv)
2078c2ecf20Sopenharmony_ci{
2088c2ecf20Sopenharmony_ci	if (usb_drv->no_dynamic_id)
2098c2ecf20Sopenharmony_ci		return;
2108c2ecf20Sopenharmony_ci
2118c2ecf20Sopenharmony_ci	if (usb_drv->probe != NULL) {
2128c2ecf20Sopenharmony_ci		driver_remove_file(&usb_drv->drvwrap.driver,
2138c2ecf20Sopenharmony_ci				&driver_attr_remove_id);
2148c2ecf20Sopenharmony_ci		driver_remove_file(&usb_drv->drvwrap.driver,
2158c2ecf20Sopenharmony_ci				   &driver_attr_new_id);
2168c2ecf20Sopenharmony_ci	}
2178c2ecf20Sopenharmony_ci}
2188c2ecf20Sopenharmony_ci
2198c2ecf20Sopenharmony_cistatic void usb_free_dynids(struct usb_driver *usb_drv)
2208c2ecf20Sopenharmony_ci{
2218c2ecf20Sopenharmony_ci	struct usb_dynid *dynid, *n;
2228c2ecf20Sopenharmony_ci
2238c2ecf20Sopenharmony_ci	spin_lock(&usb_drv->dynids.lock);
2248c2ecf20Sopenharmony_ci	list_for_each_entry_safe(dynid, n, &usb_drv->dynids.list, node) {
2258c2ecf20Sopenharmony_ci		list_del(&dynid->node);
2268c2ecf20Sopenharmony_ci		kfree(dynid);
2278c2ecf20Sopenharmony_ci	}
2288c2ecf20Sopenharmony_ci	spin_unlock(&usb_drv->dynids.lock);
2298c2ecf20Sopenharmony_ci}
2308c2ecf20Sopenharmony_ci
2318c2ecf20Sopenharmony_cistatic const struct usb_device_id *usb_match_dynamic_id(struct usb_interface *intf,
2328c2ecf20Sopenharmony_ci							struct usb_driver *drv)
2338c2ecf20Sopenharmony_ci{
2348c2ecf20Sopenharmony_ci	struct usb_dynid *dynid;
2358c2ecf20Sopenharmony_ci
2368c2ecf20Sopenharmony_ci	spin_lock(&drv->dynids.lock);
2378c2ecf20Sopenharmony_ci	list_for_each_entry(dynid, &drv->dynids.list, node) {
2388c2ecf20Sopenharmony_ci		if (usb_match_one_id(intf, &dynid->id)) {
2398c2ecf20Sopenharmony_ci			spin_unlock(&drv->dynids.lock);
2408c2ecf20Sopenharmony_ci			return &dynid->id;
2418c2ecf20Sopenharmony_ci		}
2428c2ecf20Sopenharmony_ci	}
2438c2ecf20Sopenharmony_ci	spin_unlock(&drv->dynids.lock);
2448c2ecf20Sopenharmony_ci	return NULL;
2458c2ecf20Sopenharmony_ci}
2468c2ecf20Sopenharmony_ci
2478c2ecf20Sopenharmony_ci
2488c2ecf20Sopenharmony_ci/* called from driver core with dev locked */
2498c2ecf20Sopenharmony_cistatic int usb_probe_device(struct device *dev)
2508c2ecf20Sopenharmony_ci{
2518c2ecf20Sopenharmony_ci	struct usb_device_driver *udriver = to_usb_device_driver(dev->driver);
2528c2ecf20Sopenharmony_ci	struct usb_device *udev = to_usb_device(dev);
2538c2ecf20Sopenharmony_ci	int error = 0;
2548c2ecf20Sopenharmony_ci
2558c2ecf20Sopenharmony_ci	dev_dbg(dev, "%s\n", __func__);
2568c2ecf20Sopenharmony_ci
2578c2ecf20Sopenharmony_ci	/* TODO: Add real matching code */
2588c2ecf20Sopenharmony_ci
2598c2ecf20Sopenharmony_ci	/* The device should always appear to be in use
2608c2ecf20Sopenharmony_ci	 * unless the driver supports autosuspend.
2618c2ecf20Sopenharmony_ci	 */
2628c2ecf20Sopenharmony_ci	if (!udriver->supports_autosuspend)
2638c2ecf20Sopenharmony_ci		error = usb_autoresume_device(udev);
2648c2ecf20Sopenharmony_ci	if (error)
2658c2ecf20Sopenharmony_ci		return error;
2668c2ecf20Sopenharmony_ci
2678c2ecf20Sopenharmony_ci	if (udriver->generic_subclass)
2688c2ecf20Sopenharmony_ci		error = usb_generic_driver_probe(udev);
2698c2ecf20Sopenharmony_ci	if (error)
2708c2ecf20Sopenharmony_ci		return error;
2718c2ecf20Sopenharmony_ci
2728c2ecf20Sopenharmony_ci	/* Probe the USB device with the driver in hand, but only
2738c2ecf20Sopenharmony_ci	 * defer to a generic driver in case the current USB
2748c2ecf20Sopenharmony_ci	 * device driver has an id_table or a match function; i.e.,
2758c2ecf20Sopenharmony_ci	 * when the device driver was explicitly matched against
2768c2ecf20Sopenharmony_ci	 * a device.
2778c2ecf20Sopenharmony_ci	 *
2788c2ecf20Sopenharmony_ci	 * If the device driver does not have either of these,
2798c2ecf20Sopenharmony_ci	 * then we assume that it can bind to any device and is
2808c2ecf20Sopenharmony_ci	 * not truly a more specialized/non-generic driver, so a
2818c2ecf20Sopenharmony_ci	 * return value of -ENODEV should not force the device
2828c2ecf20Sopenharmony_ci	 * to be handled by the generic USB driver, as there
2838c2ecf20Sopenharmony_ci	 * can still be another, more specialized, device driver.
2848c2ecf20Sopenharmony_ci	 *
2858c2ecf20Sopenharmony_ci	 * This accommodates the usbip driver.
2868c2ecf20Sopenharmony_ci	 *
2878c2ecf20Sopenharmony_ci	 * TODO: What if, in the future, there are multiple
2888c2ecf20Sopenharmony_ci	 * specialized USB device drivers for a particular device?
2898c2ecf20Sopenharmony_ci	 * In such cases, there is a need to try all matching
2908c2ecf20Sopenharmony_ci	 * specialised device drivers prior to setting the
2918c2ecf20Sopenharmony_ci	 * use_generic_driver bit.
2928c2ecf20Sopenharmony_ci	 */
2938c2ecf20Sopenharmony_ci	error = udriver->probe(udev);
2948c2ecf20Sopenharmony_ci	if (error == -ENODEV && udriver != &usb_generic_driver &&
2958c2ecf20Sopenharmony_ci	    (udriver->id_table || udriver->match)) {
2968c2ecf20Sopenharmony_ci		udev->use_generic_driver = 1;
2978c2ecf20Sopenharmony_ci		return -EPROBE_DEFER;
2988c2ecf20Sopenharmony_ci	}
2998c2ecf20Sopenharmony_ci	return error;
3008c2ecf20Sopenharmony_ci}
3018c2ecf20Sopenharmony_ci
3028c2ecf20Sopenharmony_ci/* called from driver core with dev locked */
3038c2ecf20Sopenharmony_cistatic int usb_unbind_device(struct device *dev)
3048c2ecf20Sopenharmony_ci{
3058c2ecf20Sopenharmony_ci	struct usb_device *udev = to_usb_device(dev);
3068c2ecf20Sopenharmony_ci	struct usb_device_driver *udriver = to_usb_device_driver(dev->driver);
3078c2ecf20Sopenharmony_ci
3088c2ecf20Sopenharmony_ci	if (udriver->disconnect)
3098c2ecf20Sopenharmony_ci		udriver->disconnect(udev);
3108c2ecf20Sopenharmony_ci	if (udriver->generic_subclass)
3118c2ecf20Sopenharmony_ci		usb_generic_driver_disconnect(udev);
3128c2ecf20Sopenharmony_ci	if (!udriver->supports_autosuspend)
3138c2ecf20Sopenharmony_ci		usb_autosuspend_device(udev);
3148c2ecf20Sopenharmony_ci	return 0;
3158c2ecf20Sopenharmony_ci}
3168c2ecf20Sopenharmony_ci
3178c2ecf20Sopenharmony_ci/* called from driver core with dev locked */
3188c2ecf20Sopenharmony_cistatic int usb_probe_interface(struct device *dev)
3198c2ecf20Sopenharmony_ci{
3208c2ecf20Sopenharmony_ci	struct usb_driver *driver = to_usb_driver(dev->driver);
3218c2ecf20Sopenharmony_ci	struct usb_interface *intf = to_usb_interface(dev);
3228c2ecf20Sopenharmony_ci	struct usb_device *udev = interface_to_usbdev(intf);
3238c2ecf20Sopenharmony_ci	const struct usb_device_id *id;
3248c2ecf20Sopenharmony_ci	int error = -ENODEV;
3258c2ecf20Sopenharmony_ci	int lpm_disable_error = -ENODEV;
3268c2ecf20Sopenharmony_ci
3278c2ecf20Sopenharmony_ci	dev_dbg(dev, "%s\n", __func__);
3288c2ecf20Sopenharmony_ci
3298c2ecf20Sopenharmony_ci	intf->needs_binding = 0;
3308c2ecf20Sopenharmony_ci
3318c2ecf20Sopenharmony_ci	if (usb_device_is_owned(udev))
3328c2ecf20Sopenharmony_ci		return error;
3338c2ecf20Sopenharmony_ci
3348c2ecf20Sopenharmony_ci	if (udev->authorized == 0) {
3358c2ecf20Sopenharmony_ci		dev_err(&intf->dev, "Device is not authorized for usage\n");
3368c2ecf20Sopenharmony_ci		return error;
3378c2ecf20Sopenharmony_ci	} else if (intf->authorized == 0) {
3388c2ecf20Sopenharmony_ci		dev_err(&intf->dev, "Interface %d is not authorized for usage\n",
3398c2ecf20Sopenharmony_ci				intf->altsetting->desc.bInterfaceNumber);
3408c2ecf20Sopenharmony_ci		return error;
3418c2ecf20Sopenharmony_ci	}
3428c2ecf20Sopenharmony_ci
3438c2ecf20Sopenharmony_ci	id = usb_match_dynamic_id(intf, driver);
3448c2ecf20Sopenharmony_ci	if (!id)
3458c2ecf20Sopenharmony_ci		id = usb_match_id(intf, driver->id_table);
3468c2ecf20Sopenharmony_ci	if (!id)
3478c2ecf20Sopenharmony_ci		return error;
3488c2ecf20Sopenharmony_ci
3498c2ecf20Sopenharmony_ci	dev_dbg(dev, "%s - got id\n", __func__);
3508c2ecf20Sopenharmony_ci
3518c2ecf20Sopenharmony_ci	error = usb_autoresume_device(udev);
3528c2ecf20Sopenharmony_ci	if (error)
3538c2ecf20Sopenharmony_ci		return error;
3548c2ecf20Sopenharmony_ci
3558c2ecf20Sopenharmony_ci	intf->condition = USB_INTERFACE_BINDING;
3568c2ecf20Sopenharmony_ci
3578c2ecf20Sopenharmony_ci	/* Probed interfaces are initially active.  They are
3588c2ecf20Sopenharmony_ci	 * runtime-PM-enabled only if the driver has autosuspend support.
3598c2ecf20Sopenharmony_ci	 * They are sensitive to their children's power states.
3608c2ecf20Sopenharmony_ci	 */
3618c2ecf20Sopenharmony_ci	pm_runtime_set_active(dev);
3628c2ecf20Sopenharmony_ci	pm_suspend_ignore_children(dev, false);
3638c2ecf20Sopenharmony_ci	if (driver->supports_autosuspend)
3648c2ecf20Sopenharmony_ci		pm_runtime_enable(dev);
3658c2ecf20Sopenharmony_ci
3668c2ecf20Sopenharmony_ci	/* If the new driver doesn't allow hub-initiated LPM, and we can't
3678c2ecf20Sopenharmony_ci	 * disable hub-initiated LPM, then fail the probe.
3688c2ecf20Sopenharmony_ci	 *
3698c2ecf20Sopenharmony_ci	 * Otherwise, leaving LPM enabled should be harmless, because the
3708c2ecf20Sopenharmony_ci	 * endpoint intervals should remain the same, and the U1/U2 timeouts
3718c2ecf20Sopenharmony_ci	 * should remain the same.
3728c2ecf20Sopenharmony_ci	 *
3738c2ecf20Sopenharmony_ci	 * If we need to install alt setting 0 before probe, or another alt
3748c2ecf20Sopenharmony_ci	 * setting during probe, that should also be fine.  usb_set_interface()
3758c2ecf20Sopenharmony_ci	 * will attempt to disable LPM, and fail if it can't disable it.
3768c2ecf20Sopenharmony_ci	 */
3778c2ecf20Sopenharmony_ci	if (driver->disable_hub_initiated_lpm) {
3788c2ecf20Sopenharmony_ci		lpm_disable_error = usb_unlocked_disable_lpm(udev);
3798c2ecf20Sopenharmony_ci		if (lpm_disable_error) {
3808c2ecf20Sopenharmony_ci			dev_err(&intf->dev, "%s Failed to disable LPM for driver %s\n",
3818c2ecf20Sopenharmony_ci				__func__, driver->name);
3828c2ecf20Sopenharmony_ci			error = lpm_disable_error;
3838c2ecf20Sopenharmony_ci			goto err;
3848c2ecf20Sopenharmony_ci		}
3858c2ecf20Sopenharmony_ci	}
3868c2ecf20Sopenharmony_ci
3878c2ecf20Sopenharmony_ci	/* Carry out a deferred switch to altsetting 0 */
3888c2ecf20Sopenharmony_ci	if (intf->needs_altsetting0) {
3898c2ecf20Sopenharmony_ci		error = usb_set_interface(udev, intf->altsetting[0].
3908c2ecf20Sopenharmony_ci				desc.bInterfaceNumber, 0);
3918c2ecf20Sopenharmony_ci		if (error < 0)
3928c2ecf20Sopenharmony_ci			goto err;
3938c2ecf20Sopenharmony_ci		intf->needs_altsetting0 = 0;
3948c2ecf20Sopenharmony_ci	}
3958c2ecf20Sopenharmony_ci
3968c2ecf20Sopenharmony_ci	error = driver->probe(intf, id);
3978c2ecf20Sopenharmony_ci	if (error)
3988c2ecf20Sopenharmony_ci		goto err;
3998c2ecf20Sopenharmony_ci
4008c2ecf20Sopenharmony_ci	intf->condition = USB_INTERFACE_BOUND;
4018c2ecf20Sopenharmony_ci
4028c2ecf20Sopenharmony_ci	/* If the LPM disable succeeded, balance the ref counts. */
4038c2ecf20Sopenharmony_ci	if (!lpm_disable_error)
4048c2ecf20Sopenharmony_ci		usb_unlocked_enable_lpm(udev);
4058c2ecf20Sopenharmony_ci
4068c2ecf20Sopenharmony_ci	usb_autosuspend_device(udev);
4078c2ecf20Sopenharmony_ci	return error;
4088c2ecf20Sopenharmony_ci
4098c2ecf20Sopenharmony_ci err:
4108c2ecf20Sopenharmony_ci	usb_set_intfdata(intf, NULL);
4118c2ecf20Sopenharmony_ci	intf->needs_remote_wakeup = 0;
4128c2ecf20Sopenharmony_ci	intf->condition = USB_INTERFACE_UNBOUND;
4138c2ecf20Sopenharmony_ci
4148c2ecf20Sopenharmony_ci	/* If the LPM disable succeeded, balance the ref counts. */
4158c2ecf20Sopenharmony_ci	if (!lpm_disable_error)
4168c2ecf20Sopenharmony_ci		usb_unlocked_enable_lpm(udev);
4178c2ecf20Sopenharmony_ci
4188c2ecf20Sopenharmony_ci	/* Unbound interfaces are always runtime-PM-disabled and -suspended */
4198c2ecf20Sopenharmony_ci	if (driver->supports_autosuspend)
4208c2ecf20Sopenharmony_ci		pm_runtime_disable(dev);
4218c2ecf20Sopenharmony_ci	pm_runtime_set_suspended(dev);
4228c2ecf20Sopenharmony_ci
4238c2ecf20Sopenharmony_ci	usb_autosuspend_device(udev);
4248c2ecf20Sopenharmony_ci	return error;
4258c2ecf20Sopenharmony_ci}
4268c2ecf20Sopenharmony_ci
4278c2ecf20Sopenharmony_ci/* called from driver core with dev locked */
4288c2ecf20Sopenharmony_cistatic int usb_unbind_interface(struct device *dev)
4298c2ecf20Sopenharmony_ci{
4308c2ecf20Sopenharmony_ci	struct usb_driver *driver = to_usb_driver(dev->driver);
4318c2ecf20Sopenharmony_ci	struct usb_interface *intf = to_usb_interface(dev);
4328c2ecf20Sopenharmony_ci	struct usb_host_endpoint *ep, **eps = NULL;
4338c2ecf20Sopenharmony_ci	struct usb_device *udev;
4348c2ecf20Sopenharmony_ci	int i, j, error, r;
4358c2ecf20Sopenharmony_ci	int lpm_disable_error = -ENODEV;
4368c2ecf20Sopenharmony_ci
4378c2ecf20Sopenharmony_ci	intf->condition = USB_INTERFACE_UNBINDING;
4388c2ecf20Sopenharmony_ci
4398c2ecf20Sopenharmony_ci	/* Autoresume for set_interface call below */
4408c2ecf20Sopenharmony_ci	udev = interface_to_usbdev(intf);
4418c2ecf20Sopenharmony_ci	error = usb_autoresume_device(udev);
4428c2ecf20Sopenharmony_ci
4438c2ecf20Sopenharmony_ci	/* If hub-initiated LPM policy may change, attempt to disable LPM until
4448c2ecf20Sopenharmony_ci	 * the driver is unbound.  If LPM isn't disabled, that's fine because it
4458c2ecf20Sopenharmony_ci	 * wouldn't be enabled unless all the bound interfaces supported
4468c2ecf20Sopenharmony_ci	 * hub-initiated LPM.
4478c2ecf20Sopenharmony_ci	 */
4488c2ecf20Sopenharmony_ci	if (driver->disable_hub_initiated_lpm)
4498c2ecf20Sopenharmony_ci		lpm_disable_error = usb_unlocked_disable_lpm(udev);
4508c2ecf20Sopenharmony_ci
4518c2ecf20Sopenharmony_ci	/*
4528c2ecf20Sopenharmony_ci	 * Terminate all URBs for this interface unless the driver
4538c2ecf20Sopenharmony_ci	 * supports "soft" unbinding and the device is still present.
4548c2ecf20Sopenharmony_ci	 */
4558c2ecf20Sopenharmony_ci	if (!driver->soft_unbind || udev->state == USB_STATE_NOTATTACHED)
4568c2ecf20Sopenharmony_ci		usb_disable_interface(udev, intf, false);
4578c2ecf20Sopenharmony_ci
4588c2ecf20Sopenharmony_ci	driver->disconnect(intf);
4598c2ecf20Sopenharmony_ci
4608c2ecf20Sopenharmony_ci	/* Free streams */
4618c2ecf20Sopenharmony_ci	for (i = 0, j = 0; i < intf->cur_altsetting->desc.bNumEndpoints; i++) {
4628c2ecf20Sopenharmony_ci		ep = &intf->cur_altsetting->endpoint[i];
4638c2ecf20Sopenharmony_ci		if (ep->streams == 0)
4648c2ecf20Sopenharmony_ci			continue;
4658c2ecf20Sopenharmony_ci		if (j == 0) {
4668c2ecf20Sopenharmony_ci			eps = kmalloc_array(USB_MAXENDPOINTS, sizeof(void *),
4678c2ecf20Sopenharmony_ci				      GFP_KERNEL);
4688c2ecf20Sopenharmony_ci			if (!eps)
4698c2ecf20Sopenharmony_ci				break;
4708c2ecf20Sopenharmony_ci		}
4718c2ecf20Sopenharmony_ci		eps[j++] = ep;
4728c2ecf20Sopenharmony_ci	}
4738c2ecf20Sopenharmony_ci	if (j) {
4748c2ecf20Sopenharmony_ci		usb_free_streams(intf, eps, j, GFP_KERNEL);
4758c2ecf20Sopenharmony_ci		kfree(eps);
4768c2ecf20Sopenharmony_ci	}
4778c2ecf20Sopenharmony_ci
4788c2ecf20Sopenharmony_ci	/* Reset other interface state.
4798c2ecf20Sopenharmony_ci	 * We cannot do a Set-Interface if the device is suspended or
4808c2ecf20Sopenharmony_ci	 * if it is prepared for a system sleep (since installing a new
4818c2ecf20Sopenharmony_ci	 * altsetting means creating new endpoint device entries).
4828c2ecf20Sopenharmony_ci	 * When either of these happens, defer the Set-Interface.
4838c2ecf20Sopenharmony_ci	 */
4848c2ecf20Sopenharmony_ci	if (intf->cur_altsetting->desc.bAlternateSetting == 0) {
4858c2ecf20Sopenharmony_ci		/* Already in altsetting 0 so skip Set-Interface.
4868c2ecf20Sopenharmony_ci		 * Just re-enable it without affecting the endpoint toggles.
4878c2ecf20Sopenharmony_ci		 */
4888c2ecf20Sopenharmony_ci		usb_enable_interface(udev, intf, false);
4898c2ecf20Sopenharmony_ci	} else if (!error && !intf->dev.power.is_prepared) {
4908c2ecf20Sopenharmony_ci		r = usb_set_interface(udev, intf->altsetting[0].
4918c2ecf20Sopenharmony_ci				desc.bInterfaceNumber, 0);
4928c2ecf20Sopenharmony_ci		if (r < 0)
4938c2ecf20Sopenharmony_ci			intf->needs_altsetting0 = 1;
4948c2ecf20Sopenharmony_ci	} else {
4958c2ecf20Sopenharmony_ci		intf->needs_altsetting0 = 1;
4968c2ecf20Sopenharmony_ci	}
4978c2ecf20Sopenharmony_ci	usb_set_intfdata(intf, NULL);
4988c2ecf20Sopenharmony_ci
4998c2ecf20Sopenharmony_ci	intf->condition = USB_INTERFACE_UNBOUND;
5008c2ecf20Sopenharmony_ci	intf->needs_remote_wakeup = 0;
5018c2ecf20Sopenharmony_ci
5028c2ecf20Sopenharmony_ci	/* Attempt to re-enable USB3 LPM, if the disable succeeded. */
5038c2ecf20Sopenharmony_ci	if (!lpm_disable_error)
5048c2ecf20Sopenharmony_ci		usb_unlocked_enable_lpm(udev);
5058c2ecf20Sopenharmony_ci
5068c2ecf20Sopenharmony_ci	/* Unbound interfaces are always runtime-PM-disabled and -suspended */
5078c2ecf20Sopenharmony_ci	if (driver->supports_autosuspend)
5088c2ecf20Sopenharmony_ci		pm_runtime_disable(dev);
5098c2ecf20Sopenharmony_ci	pm_runtime_set_suspended(dev);
5108c2ecf20Sopenharmony_ci
5118c2ecf20Sopenharmony_ci	if (!error)
5128c2ecf20Sopenharmony_ci		usb_autosuspend_device(udev);
5138c2ecf20Sopenharmony_ci
5148c2ecf20Sopenharmony_ci	return 0;
5158c2ecf20Sopenharmony_ci}
5168c2ecf20Sopenharmony_ci
5178c2ecf20Sopenharmony_ci/**
5188c2ecf20Sopenharmony_ci * usb_driver_claim_interface - bind a driver to an interface
5198c2ecf20Sopenharmony_ci * @driver: the driver to be bound
5208c2ecf20Sopenharmony_ci * @iface: the interface to which it will be bound; must be in the
5218c2ecf20Sopenharmony_ci *	usb device's active configuration
5228c2ecf20Sopenharmony_ci * @priv: driver data associated with that interface
5238c2ecf20Sopenharmony_ci *
5248c2ecf20Sopenharmony_ci * This is used by usb device drivers that need to claim more than one
5258c2ecf20Sopenharmony_ci * interface on a device when probing (audio and acm are current examples).
5268c2ecf20Sopenharmony_ci * No device driver should directly modify internal usb_interface or
5278c2ecf20Sopenharmony_ci * usb_device structure members.
5288c2ecf20Sopenharmony_ci *
5298c2ecf20Sopenharmony_ci * Few drivers should need to use this routine, since the most natural
5308c2ecf20Sopenharmony_ci * way to bind to an interface is to return the private data from
5318c2ecf20Sopenharmony_ci * the driver's probe() method.
5328c2ecf20Sopenharmony_ci *
5338c2ecf20Sopenharmony_ci * Callers must own the device lock, so driver probe() entries don't need
5348c2ecf20Sopenharmony_ci * extra locking, but other call contexts may need to explicitly claim that
5358c2ecf20Sopenharmony_ci * lock.
5368c2ecf20Sopenharmony_ci *
5378c2ecf20Sopenharmony_ci * Return: 0 on success.
5388c2ecf20Sopenharmony_ci */
5398c2ecf20Sopenharmony_ciint usb_driver_claim_interface(struct usb_driver *driver,
5408c2ecf20Sopenharmony_ci				struct usb_interface *iface, void *priv)
5418c2ecf20Sopenharmony_ci{
5428c2ecf20Sopenharmony_ci	struct device *dev;
5438c2ecf20Sopenharmony_ci	int retval = 0;
5448c2ecf20Sopenharmony_ci
5458c2ecf20Sopenharmony_ci	if (!iface)
5468c2ecf20Sopenharmony_ci		return -ENODEV;
5478c2ecf20Sopenharmony_ci
5488c2ecf20Sopenharmony_ci	dev = &iface->dev;
5498c2ecf20Sopenharmony_ci	if (dev->driver)
5508c2ecf20Sopenharmony_ci		return -EBUSY;
5518c2ecf20Sopenharmony_ci
5528c2ecf20Sopenharmony_ci	/* reject claim if interface is not authorized */
5538c2ecf20Sopenharmony_ci	if (!iface->authorized)
5548c2ecf20Sopenharmony_ci		return -ENODEV;
5558c2ecf20Sopenharmony_ci
5568c2ecf20Sopenharmony_ci	dev->driver = &driver->drvwrap.driver;
5578c2ecf20Sopenharmony_ci	usb_set_intfdata(iface, priv);
5588c2ecf20Sopenharmony_ci	iface->needs_binding = 0;
5598c2ecf20Sopenharmony_ci
5608c2ecf20Sopenharmony_ci	iface->condition = USB_INTERFACE_BOUND;
5618c2ecf20Sopenharmony_ci
5628c2ecf20Sopenharmony_ci	/* Claimed interfaces are initially inactive (suspended) and
5638c2ecf20Sopenharmony_ci	 * runtime-PM-enabled, but only if the driver has autosuspend
5648c2ecf20Sopenharmony_ci	 * support.  Otherwise they are marked active, to prevent the
5658c2ecf20Sopenharmony_ci	 * device from being autosuspended, but left disabled.  In either
5668c2ecf20Sopenharmony_ci	 * case they are sensitive to their children's power states.
5678c2ecf20Sopenharmony_ci	 */
5688c2ecf20Sopenharmony_ci	pm_suspend_ignore_children(dev, false);
5698c2ecf20Sopenharmony_ci	if (driver->supports_autosuspend)
5708c2ecf20Sopenharmony_ci		pm_runtime_enable(dev);
5718c2ecf20Sopenharmony_ci	else
5728c2ecf20Sopenharmony_ci		pm_runtime_set_active(dev);
5738c2ecf20Sopenharmony_ci
5748c2ecf20Sopenharmony_ci	/* if interface was already added, bind now; else let
5758c2ecf20Sopenharmony_ci	 * the future device_add() bind it, bypassing probe()
5768c2ecf20Sopenharmony_ci	 */
5778c2ecf20Sopenharmony_ci	if (device_is_registered(dev))
5788c2ecf20Sopenharmony_ci		retval = device_bind_driver(dev);
5798c2ecf20Sopenharmony_ci
5808c2ecf20Sopenharmony_ci	if (retval) {
5818c2ecf20Sopenharmony_ci		dev->driver = NULL;
5828c2ecf20Sopenharmony_ci		usb_set_intfdata(iface, NULL);
5838c2ecf20Sopenharmony_ci		iface->needs_remote_wakeup = 0;
5848c2ecf20Sopenharmony_ci		iface->condition = USB_INTERFACE_UNBOUND;
5858c2ecf20Sopenharmony_ci
5868c2ecf20Sopenharmony_ci		/*
5878c2ecf20Sopenharmony_ci		 * Unbound interfaces are always runtime-PM-disabled
5888c2ecf20Sopenharmony_ci		 * and runtime-PM-suspended
5898c2ecf20Sopenharmony_ci		 */
5908c2ecf20Sopenharmony_ci		if (driver->supports_autosuspend)
5918c2ecf20Sopenharmony_ci			pm_runtime_disable(dev);
5928c2ecf20Sopenharmony_ci		pm_runtime_set_suspended(dev);
5938c2ecf20Sopenharmony_ci	}
5948c2ecf20Sopenharmony_ci
5958c2ecf20Sopenharmony_ci	return retval;
5968c2ecf20Sopenharmony_ci}
5978c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(usb_driver_claim_interface);
5988c2ecf20Sopenharmony_ci
5998c2ecf20Sopenharmony_ci/**
6008c2ecf20Sopenharmony_ci * usb_driver_release_interface - unbind a driver from an interface
6018c2ecf20Sopenharmony_ci * @driver: the driver to be unbound
6028c2ecf20Sopenharmony_ci * @iface: the interface from which it will be unbound
6038c2ecf20Sopenharmony_ci *
6048c2ecf20Sopenharmony_ci * This can be used by drivers to release an interface without waiting
6058c2ecf20Sopenharmony_ci * for their disconnect() methods to be called.  In typical cases this
6068c2ecf20Sopenharmony_ci * also causes the driver disconnect() method to be called.
6078c2ecf20Sopenharmony_ci *
6088c2ecf20Sopenharmony_ci * This call is synchronous, and may not be used in an interrupt context.
6098c2ecf20Sopenharmony_ci * Callers must own the device lock, so driver disconnect() entries don't
6108c2ecf20Sopenharmony_ci * need extra locking, but other call contexts may need to explicitly claim
6118c2ecf20Sopenharmony_ci * that lock.
6128c2ecf20Sopenharmony_ci */
6138c2ecf20Sopenharmony_civoid usb_driver_release_interface(struct usb_driver *driver,
6148c2ecf20Sopenharmony_ci					struct usb_interface *iface)
6158c2ecf20Sopenharmony_ci{
6168c2ecf20Sopenharmony_ci	struct device *dev = &iface->dev;
6178c2ecf20Sopenharmony_ci
6188c2ecf20Sopenharmony_ci	/* this should never happen, don't release something that's not ours */
6198c2ecf20Sopenharmony_ci	if (!dev->driver || dev->driver != &driver->drvwrap.driver)
6208c2ecf20Sopenharmony_ci		return;
6218c2ecf20Sopenharmony_ci
6228c2ecf20Sopenharmony_ci	/* don't release from within disconnect() */
6238c2ecf20Sopenharmony_ci	if (iface->condition != USB_INTERFACE_BOUND)
6248c2ecf20Sopenharmony_ci		return;
6258c2ecf20Sopenharmony_ci	iface->condition = USB_INTERFACE_UNBINDING;
6268c2ecf20Sopenharmony_ci
6278c2ecf20Sopenharmony_ci	/* Release via the driver core only if the interface
6288c2ecf20Sopenharmony_ci	 * has already been registered
6298c2ecf20Sopenharmony_ci	 */
6308c2ecf20Sopenharmony_ci	if (device_is_registered(dev)) {
6318c2ecf20Sopenharmony_ci		device_release_driver(dev);
6328c2ecf20Sopenharmony_ci	} else {
6338c2ecf20Sopenharmony_ci		device_lock(dev);
6348c2ecf20Sopenharmony_ci		usb_unbind_interface(dev);
6358c2ecf20Sopenharmony_ci		dev->driver = NULL;
6368c2ecf20Sopenharmony_ci		device_unlock(dev);
6378c2ecf20Sopenharmony_ci	}
6388c2ecf20Sopenharmony_ci}
6398c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(usb_driver_release_interface);
6408c2ecf20Sopenharmony_ci
6418c2ecf20Sopenharmony_ci/* returns 0 if no match, 1 if match */
6428c2ecf20Sopenharmony_ciint usb_match_device(struct usb_device *dev, const struct usb_device_id *id)
6438c2ecf20Sopenharmony_ci{
6448c2ecf20Sopenharmony_ci	if ((id->match_flags & USB_DEVICE_ID_MATCH_VENDOR) &&
6458c2ecf20Sopenharmony_ci	    id->idVendor != le16_to_cpu(dev->descriptor.idVendor))
6468c2ecf20Sopenharmony_ci		return 0;
6478c2ecf20Sopenharmony_ci
6488c2ecf20Sopenharmony_ci	if ((id->match_flags & USB_DEVICE_ID_MATCH_PRODUCT) &&
6498c2ecf20Sopenharmony_ci	    id->idProduct != le16_to_cpu(dev->descriptor.idProduct))
6508c2ecf20Sopenharmony_ci		return 0;
6518c2ecf20Sopenharmony_ci
6528c2ecf20Sopenharmony_ci	/* No need to test id->bcdDevice_lo != 0, since 0 is never
6538c2ecf20Sopenharmony_ci	   greater than any unsigned number. */
6548c2ecf20Sopenharmony_ci	if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_LO) &&
6558c2ecf20Sopenharmony_ci	    (id->bcdDevice_lo > le16_to_cpu(dev->descriptor.bcdDevice)))
6568c2ecf20Sopenharmony_ci		return 0;
6578c2ecf20Sopenharmony_ci
6588c2ecf20Sopenharmony_ci	if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_HI) &&
6598c2ecf20Sopenharmony_ci	    (id->bcdDevice_hi < le16_to_cpu(dev->descriptor.bcdDevice)))
6608c2ecf20Sopenharmony_ci		return 0;
6618c2ecf20Sopenharmony_ci
6628c2ecf20Sopenharmony_ci	if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_CLASS) &&
6638c2ecf20Sopenharmony_ci	    (id->bDeviceClass != dev->descriptor.bDeviceClass))
6648c2ecf20Sopenharmony_ci		return 0;
6658c2ecf20Sopenharmony_ci
6668c2ecf20Sopenharmony_ci	if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_SUBCLASS) &&
6678c2ecf20Sopenharmony_ci	    (id->bDeviceSubClass != dev->descriptor.bDeviceSubClass))
6688c2ecf20Sopenharmony_ci		return 0;
6698c2ecf20Sopenharmony_ci
6708c2ecf20Sopenharmony_ci	if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_PROTOCOL) &&
6718c2ecf20Sopenharmony_ci	    (id->bDeviceProtocol != dev->descriptor.bDeviceProtocol))
6728c2ecf20Sopenharmony_ci		return 0;
6738c2ecf20Sopenharmony_ci
6748c2ecf20Sopenharmony_ci	return 1;
6758c2ecf20Sopenharmony_ci}
6768c2ecf20Sopenharmony_ci
6778c2ecf20Sopenharmony_ci/* returns 0 if no match, 1 if match */
6788c2ecf20Sopenharmony_ciint usb_match_one_id_intf(struct usb_device *dev,
6798c2ecf20Sopenharmony_ci			  struct usb_host_interface *intf,
6808c2ecf20Sopenharmony_ci			  const struct usb_device_id *id)
6818c2ecf20Sopenharmony_ci{
6828c2ecf20Sopenharmony_ci	/* The interface class, subclass, protocol and number should never be
6838c2ecf20Sopenharmony_ci	 * checked for a match if the device class is Vendor Specific,
6848c2ecf20Sopenharmony_ci	 * unless the match record specifies the Vendor ID. */
6858c2ecf20Sopenharmony_ci	if (dev->descriptor.bDeviceClass == USB_CLASS_VENDOR_SPEC &&
6868c2ecf20Sopenharmony_ci			!(id->match_flags & USB_DEVICE_ID_MATCH_VENDOR) &&
6878c2ecf20Sopenharmony_ci			(id->match_flags & (USB_DEVICE_ID_MATCH_INT_CLASS |
6888c2ecf20Sopenharmony_ci				USB_DEVICE_ID_MATCH_INT_SUBCLASS |
6898c2ecf20Sopenharmony_ci				USB_DEVICE_ID_MATCH_INT_PROTOCOL |
6908c2ecf20Sopenharmony_ci				USB_DEVICE_ID_MATCH_INT_NUMBER)))
6918c2ecf20Sopenharmony_ci		return 0;
6928c2ecf20Sopenharmony_ci
6938c2ecf20Sopenharmony_ci	if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_CLASS) &&
6948c2ecf20Sopenharmony_ci	    (id->bInterfaceClass != intf->desc.bInterfaceClass))
6958c2ecf20Sopenharmony_ci		return 0;
6968c2ecf20Sopenharmony_ci
6978c2ecf20Sopenharmony_ci	if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_SUBCLASS) &&
6988c2ecf20Sopenharmony_ci	    (id->bInterfaceSubClass != intf->desc.bInterfaceSubClass))
6998c2ecf20Sopenharmony_ci		return 0;
7008c2ecf20Sopenharmony_ci
7018c2ecf20Sopenharmony_ci	if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_PROTOCOL) &&
7028c2ecf20Sopenharmony_ci	    (id->bInterfaceProtocol != intf->desc.bInterfaceProtocol))
7038c2ecf20Sopenharmony_ci		return 0;
7048c2ecf20Sopenharmony_ci
7058c2ecf20Sopenharmony_ci	if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_NUMBER) &&
7068c2ecf20Sopenharmony_ci	    (id->bInterfaceNumber != intf->desc.bInterfaceNumber))
7078c2ecf20Sopenharmony_ci		return 0;
7088c2ecf20Sopenharmony_ci
7098c2ecf20Sopenharmony_ci	return 1;
7108c2ecf20Sopenharmony_ci}
7118c2ecf20Sopenharmony_ci
7128c2ecf20Sopenharmony_ci/* returns 0 if no match, 1 if match */
7138c2ecf20Sopenharmony_ciint usb_match_one_id(struct usb_interface *interface,
7148c2ecf20Sopenharmony_ci		     const struct usb_device_id *id)
7158c2ecf20Sopenharmony_ci{
7168c2ecf20Sopenharmony_ci	struct usb_host_interface *intf;
7178c2ecf20Sopenharmony_ci	struct usb_device *dev;
7188c2ecf20Sopenharmony_ci
7198c2ecf20Sopenharmony_ci	/* proc_connectinfo in devio.c may call us with id == NULL. */
7208c2ecf20Sopenharmony_ci	if (id == NULL)
7218c2ecf20Sopenharmony_ci		return 0;
7228c2ecf20Sopenharmony_ci
7238c2ecf20Sopenharmony_ci	intf = interface->cur_altsetting;
7248c2ecf20Sopenharmony_ci	dev = interface_to_usbdev(interface);
7258c2ecf20Sopenharmony_ci
7268c2ecf20Sopenharmony_ci	if (!usb_match_device(dev, id))
7278c2ecf20Sopenharmony_ci		return 0;
7288c2ecf20Sopenharmony_ci
7298c2ecf20Sopenharmony_ci	return usb_match_one_id_intf(dev, intf, id);
7308c2ecf20Sopenharmony_ci}
7318c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(usb_match_one_id);
7328c2ecf20Sopenharmony_ci
7338c2ecf20Sopenharmony_ci/**
7348c2ecf20Sopenharmony_ci * usb_match_id - find first usb_device_id matching device or interface
7358c2ecf20Sopenharmony_ci * @interface: the interface of interest
7368c2ecf20Sopenharmony_ci * @id: array of usb_device_id structures, terminated by zero entry
7378c2ecf20Sopenharmony_ci *
7388c2ecf20Sopenharmony_ci * usb_match_id searches an array of usb_device_id's and returns
7398c2ecf20Sopenharmony_ci * the first one matching the device or interface, or null.
7408c2ecf20Sopenharmony_ci * This is used when binding (or rebinding) a driver to an interface.
7418c2ecf20Sopenharmony_ci * Most USB device drivers will use this indirectly, through the usb core,
7428c2ecf20Sopenharmony_ci * but some layered driver frameworks use it directly.
7438c2ecf20Sopenharmony_ci * These device tables are exported with MODULE_DEVICE_TABLE, through
7448c2ecf20Sopenharmony_ci * modutils, to support the driver loading functionality of USB hotplugging.
7458c2ecf20Sopenharmony_ci *
7468c2ecf20Sopenharmony_ci * Return: The first matching usb_device_id, or %NULL.
7478c2ecf20Sopenharmony_ci *
7488c2ecf20Sopenharmony_ci * What Matches:
7498c2ecf20Sopenharmony_ci *
7508c2ecf20Sopenharmony_ci * The "match_flags" element in a usb_device_id controls which
7518c2ecf20Sopenharmony_ci * members are used.  If the corresponding bit is set, the
7528c2ecf20Sopenharmony_ci * value in the device_id must match its corresponding member
7538c2ecf20Sopenharmony_ci * in the device or interface descriptor, or else the device_id
7548c2ecf20Sopenharmony_ci * does not match.
7558c2ecf20Sopenharmony_ci *
7568c2ecf20Sopenharmony_ci * "driver_info" is normally used only by device drivers,
7578c2ecf20Sopenharmony_ci * but you can create a wildcard "matches anything" usb_device_id
7588c2ecf20Sopenharmony_ci * as a driver's "modules.usbmap" entry if you provide an id with
7598c2ecf20Sopenharmony_ci * only a nonzero "driver_info" field.  If you do this, the USB device
7608c2ecf20Sopenharmony_ci * driver's probe() routine should use additional intelligence to
7618c2ecf20Sopenharmony_ci * decide whether to bind to the specified interface.
7628c2ecf20Sopenharmony_ci *
7638c2ecf20Sopenharmony_ci * What Makes Good usb_device_id Tables:
7648c2ecf20Sopenharmony_ci *
7658c2ecf20Sopenharmony_ci * The match algorithm is very simple, so that intelligence in
7668c2ecf20Sopenharmony_ci * driver selection must come from smart driver id records.
7678c2ecf20Sopenharmony_ci * Unless you have good reasons to use another selection policy,
7688c2ecf20Sopenharmony_ci * provide match elements only in related groups, and order match
7698c2ecf20Sopenharmony_ci * specifiers from specific to general.  Use the macros provided
7708c2ecf20Sopenharmony_ci * for that purpose if you can.
7718c2ecf20Sopenharmony_ci *
7728c2ecf20Sopenharmony_ci * The most specific match specifiers use device descriptor
7738c2ecf20Sopenharmony_ci * data.  These are commonly used with product-specific matches;
7748c2ecf20Sopenharmony_ci * the USB_DEVICE macro lets you provide vendor and product IDs,
7758c2ecf20Sopenharmony_ci * and you can also match against ranges of product revisions.
7768c2ecf20Sopenharmony_ci * These are widely used for devices with application or vendor
7778c2ecf20Sopenharmony_ci * specific bDeviceClass values.
7788c2ecf20Sopenharmony_ci *
7798c2ecf20Sopenharmony_ci * Matches based on device class/subclass/protocol specifications
7808c2ecf20Sopenharmony_ci * are slightly more general; use the USB_DEVICE_INFO macro, or
7818c2ecf20Sopenharmony_ci * its siblings.  These are used with single-function devices
7828c2ecf20Sopenharmony_ci * where bDeviceClass doesn't specify that each interface has
7838c2ecf20Sopenharmony_ci * its own class.
7848c2ecf20Sopenharmony_ci *
7858c2ecf20Sopenharmony_ci * Matches based on interface class/subclass/protocol are the
7868c2ecf20Sopenharmony_ci * most general; they let drivers bind to any interface on a
7878c2ecf20Sopenharmony_ci * multiple-function device.  Use the USB_INTERFACE_INFO
7888c2ecf20Sopenharmony_ci * macro, or its siblings, to match class-per-interface style
7898c2ecf20Sopenharmony_ci * devices (as recorded in bInterfaceClass).
7908c2ecf20Sopenharmony_ci *
7918c2ecf20Sopenharmony_ci * Note that an entry created by USB_INTERFACE_INFO won't match
7928c2ecf20Sopenharmony_ci * any interface if the device class is set to Vendor-Specific.
7938c2ecf20Sopenharmony_ci * This is deliberate; according to the USB spec the meanings of
7948c2ecf20Sopenharmony_ci * the interface class/subclass/protocol for these devices are also
7958c2ecf20Sopenharmony_ci * vendor-specific, and hence matching against a standard product
7968c2ecf20Sopenharmony_ci * class wouldn't work anyway.  If you really want to use an
7978c2ecf20Sopenharmony_ci * interface-based match for such a device, create a match record
7988c2ecf20Sopenharmony_ci * that also specifies the vendor ID.  (Unforunately there isn't a
7998c2ecf20Sopenharmony_ci * standard macro for creating records like this.)
8008c2ecf20Sopenharmony_ci *
8018c2ecf20Sopenharmony_ci * Within those groups, remember that not all combinations are
8028c2ecf20Sopenharmony_ci * meaningful.  For example, don't give a product version range
8038c2ecf20Sopenharmony_ci * without vendor and product IDs; or specify a protocol without
8048c2ecf20Sopenharmony_ci * its associated class and subclass.
8058c2ecf20Sopenharmony_ci */
8068c2ecf20Sopenharmony_ciconst struct usb_device_id *usb_match_id(struct usb_interface *interface,
8078c2ecf20Sopenharmony_ci					 const struct usb_device_id *id)
8088c2ecf20Sopenharmony_ci{
8098c2ecf20Sopenharmony_ci	/* proc_connectinfo in devio.c may call us with id == NULL. */
8108c2ecf20Sopenharmony_ci	if (id == NULL)
8118c2ecf20Sopenharmony_ci		return NULL;
8128c2ecf20Sopenharmony_ci
8138c2ecf20Sopenharmony_ci	/* It is important to check that id->driver_info is nonzero,
8148c2ecf20Sopenharmony_ci	   since an entry that is all zeroes except for a nonzero
8158c2ecf20Sopenharmony_ci	   id->driver_info is the way to create an entry that
8168c2ecf20Sopenharmony_ci	   indicates that the driver want to examine every
8178c2ecf20Sopenharmony_ci	   device and interface. */
8188c2ecf20Sopenharmony_ci	for (; id->idVendor || id->idProduct || id->bDeviceClass ||
8198c2ecf20Sopenharmony_ci	       id->bInterfaceClass || id->driver_info; id++) {
8208c2ecf20Sopenharmony_ci		if (usb_match_one_id(interface, id))
8218c2ecf20Sopenharmony_ci			return id;
8228c2ecf20Sopenharmony_ci	}
8238c2ecf20Sopenharmony_ci
8248c2ecf20Sopenharmony_ci	return NULL;
8258c2ecf20Sopenharmony_ci}
8268c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(usb_match_id);
8278c2ecf20Sopenharmony_ci
8288c2ecf20Sopenharmony_ciconst struct usb_device_id *usb_device_match_id(struct usb_device *udev,
8298c2ecf20Sopenharmony_ci				const struct usb_device_id *id)
8308c2ecf20Sopenharmony_ci{
8318c2ecf20Sopenharmony_ci	if (!id)
8328c2ecf20Sopenharmony_ci		return NULL;
8338c2ecf20Sopenharmony_ci
8348c2ecf20Sopenharmony_ci	for (; id->idVendor || id->idProduct ; id++) {
8358c2ecf20Sopenharmony_ci		if (usb_match_device(udev, id))
8368c2ecf20Sopenharmony_ci			return id;
8378c2ecf20Sopenharmony_ci	}
8388c2ecf20Sopenharmony_ci
8398c2ecf20Sopenharmony_ci	return NULL;
8408c2ecf20Sopenharmony_ci}
8418c2ecf20Sopenharmony_ci
8428c2ecf20Sopenharmony_cibool usb_driver_applicable(struct usb_device *udev,
8438c2ecf20Sopenharmony_ci			   struct usb_device_driver *udrv)
8448c2ecf20Sopenharmony_ci{
8458c2ecf20Sopenharmony_ci	if (udrv->id_table && udrv->match)
8468c2ecf20Sopenharmony_ci		return usb_device_match_id(udev, udrv->id_table) != NULL &&
8478c2ecf20Sopenharmony_ci		       udrv->match(udev);
8488c2ecf20Sopenharmony_ci
8498c2ecf20Sopenharmony_ci	if (udrv->id_table)
8508c2ecf20Sopenharmony_ci		return usb_device_match_id(udev, udrv->id_table) != NULL;
8518c2ecf20Sopenharmony_ci
8528c2ecf20Sopenharmony_ci	if (udrv->match)
8538c2ecf20Sopenharmony_ci		return udrv->match(udev);
8548c2ecf20Sopenharmony_ci
8558c2ecf20Sopenharmony_ci	return false;
8568c2ecf20Sopenharmony_ci}
8578c2ecf20Sopenharmony_ci
8588c2ecf20Sopenharmony_cistatic int usb_device_match(struct device *dev, struct device_driver *drv)
8598c2ecf20Sopenharmony_ci{
8608c2ecf20Sopenharmony_ci	/* devices and interfaces are handled separately */
8618c2ecf20Sopenharmony_ci	if (is_usb_device(dev)) {
8628c2ecf20Sopenharmony_ci		struct usb_device *udev;
8638c2ecf20Sopenharmony_ci		struct usb_device_driver *udrv;
8648c2ecf20Sopenharmony_ci
8658c2ecf20Sopenharmony_ci		/* interface drivers never match devices */
8668c2ecf20Sopenharmony_ci		if (!is_usb_device_driver(drv))
8678c2ecf20Sopenharmony_ci			return 0;
8688c2ecf20Sopenharmony_ci
8698c2ecf20Sopenharmony_ci		udev = to_usb_device(dev);
8708c2ecf20Sopenharmony_ci		udrv = to_usb_device_driver(drv);
8718c2ecf20Sopenharmony_ci
8728c2ecf20Sopenharmony_ci		/* If the device driver under consideration does not have a
8738c2ecf20Sopenharmony_ci		 * id_table or a match function, then let the driver's probe
8748c2ecf20Sopenharmony_ci		 * function decide.
8758c2ecf20Sopenharmony_ci		 */
8768c2ecf20Sopenharmony_ci		if (!udrv->id_table && !udrv->match)
8778c2ecf20Sopenharmony_ci			return 1;
8788c2ecf20Sopenharmony_ci
8798c2ecf20Sopenharmony_ci		return usb_driver_applicable(udev, udrv);
8808c2ecf20Sopenharmony_ci
8818c2ecf20Sopenharmony_ci	} else if (is_usb_interface(dev)) {
8828c2ecf20Sopenharmony_ci		struct usb_interface *intf;
8838c2ecf20Sopenharmony_ci		struct usb_driver *usb_drv;
8848c2ecf20Sopenharmony_ci		const struct usb_device_id *id;
8858c2ecf20Sopenharmony_ci
8868c2ecf20Sopenharmony_ci		/* device drivers never match interfaces */
8878c2ecf20Sopenharmony_ci		if (is_usb_device_driver(drv))
8888c2ecf20Sopenharmony_ci			return 0;
8898c2ecf20Sopenharmony_ci
8908c2ecf20Sopenharmony_ci		intf = to_usb_interface(dev);
8918c2ecf20Sopenharmony_ci		usb_drv = to_usb_driver(drv);
8928c2ecf20Sopenharmony_ci
8938c2ecf20Sopenharmony_ci		id = usb_match_id(intf, usb_drv->id_table);
8948c2ecf20Sopenharmony_ci		if (id)
8958c2ecf20Sopenharmony_ci			return 1;
8968c2ecf20Sopenharmony_ci
8978c2ecf20Sopenharmony_ci		id = usb_match_dynamic_id(intf, usb_drv);
8988c2ecf20Sopenharmony_ci		if (id)
8998c2ecf20Sopenharmony_ci			return 1;
9008c2ecf20Sopenharmony_ci	}
9018c2ecf20Sopenharmony_ci
9028c2ecf20Sopenharmony_ci	return 0;
9038c2ecf20Sopenharmony_ci}
9048c2ecf20Sopenharmony_ci
9058c2ecf20Sopenharmony_cistatic int usb_uevent(struct device *dev, struct kobj_uevent_env *env)
9068c2ecf20Sopenharmony_ci{
9078c2ecf20Sopenharmony_ci	struct usb_device *usb_dev;
9088c2ecf20Sopenharmony_ci
9098c2ecf20Sopenharmony_ci	if (is_usb_device(dev)) {
9108c2ecf20Sopenharmony_ci		usb_dev = to_usb_device(dev);
9118c2ecf20Sopenharmony_ci	} else if (is_usb_interface(dev)) {
9128c2ecf20Sopenharmony_ci		struct usb_interface *intf = to_usb_interface(dev);
9138c2ecf20Sopenharmony_ci
9148c2ecf20Sopenharmony_ci		usb_dev = interface_to_usbdev(intf);
9158c2ecf20Sopenharmony_ci	} else {
9168c2ecf20Sopenharmony_ci		return 0;
9178c2ecf20Sopenharmony_ci	}
9188c2ecf20Sopenharmony_ci
9198c2ecf20Sopenharmony_ci	if (usb_dev->devnum < 0) {
9208c2ecf20Sopenharmony_ci		/* driver is often null here; dev_dbg() would oops */
9218c2ecf20Sopenharmony_ci		pr_debug("usb %s: already deleted?\n", dev_name(dev));
9228c2ecf20Sopenharmony_ci		return -ENODEV;
9238c2ecf20Sopenharmony_ci	}
9248c2ecf20Sopenharmony_ci	if (!usb_dev->bus) {
9258c2ecf20Sopenharmony_ci		pr_debug("usb %s: bus removed?\n", dev_name(dev));
9268c2ecf20Sopenharmony_ci		return -ENODEV;
9278c2ecf20Sopenharmony_ci	}
9288c2ecf20Sopenharmony_ci
9298c2ecf20Sopenharmony_ci	/* per-device configurations are common */
9308c2ecf20Sopenharmony_ci	if (add_uevent_var(env, "PRODUCT=%x/%x/%x",
9318c2ecf20Sopenharmony_ci			   le16_to_cpu(usb_dev->descriptor.idVendor),
9328c2ecf20Sopenharmony_ci			   le16_to_cpu(usb_dev->descriptor.idProduct),
9338c2ecf20Sopenharmony_ci			   le16_to_cpu(usb_dev->descriptor.bcdDevice)))
9348c2ecf20Sopenharmony_ci		return -ENOMEM;
9358c2ecf20Sopenharmony_ci
9368c2ecf20Sopenharmony_ci	/* class-based driver binding models */
9378c2ecf20Sopenharmony_ci	if (add_uevent_var(env, "TYPE=%d/%d/%d",
9388c2ecf20Sopenharmony_ci			   usb_dev->descriptor.bDeviceClass,
9398c2ecf20Sopenharmony_ci			   usb_dev->descriptor.bDeviceSubClass,
9408c2ecf20Sopenharmony_ci			   usb_dev->descriptor.bDeviceProtocol))
9418c2ecf20Sopenharmony_ci		return -ENOMEM;
9428c2ecf20Sopenharmony_ci
9438c2ecf20Sopenharmony_ci	return 0;
9448c2ecf20Sopenharmony_ci}
9458c2ecf20Sopenharmony_ci
9468c2ecf20Sopenharmony_cistatic int __usb_bus_reprobe_drivers(struct device *dev, void *data)
9478c2ecf20Sopenharmony_ci{
9488c2ecf20Sopenharmony_ci	struct usb_device_driver *new_udriver = data;
9498c2ecf20Sopenharmony_ci	struct usb_device *udev;
9508c2ecf20Sopenharmony_ci	int ret;
9518c2ecf20Sopenharmony_ci
9528c2ecf20Sopenharmony_ci	/* Don't reprobe if current driver isn't usb_generic_driver */
9538c2ecf20Sopenharmony_ci	if (dev->driver != &usb_generic_driver.drvwrap.driver)
9548c2ecf20Sopenharmony_ci		return 0;
9558c2ecf20Sopenharmony_ci
9568c2ecf20Sopenharmony_ci	udev = to_usb_device(dev);
9578c2ecf20Sopenharmony_ci	if (!usb_driver_applicable(udev, new_udriver))
9588c2ecf20Sopenharmony_ci		return 0;
9598c2ecf20Sopenharmony_ci
9608c2ecf20Sopenharmony_ci	ret = device_reprobe(dev);
9618c2ecf20Sopenharmony_ci	if (ret && ret != -EPROBE_DEFER)
9628c2ecf20Sopenharmony_ci		dev_err(dev, "Failed to reprobe device (error %d)\n", ret);
9638c2ecf20Sopenharmony_ci
9648c2ecf20Sopenharmony_ci	return 0;
9658c2ecf20Sopenharmony_ci}
9668c2ecf20Sopenharmony_ci
9678c2ecf20Sopenharmony_ci/**
9688c2ecf20Sopenharmony_ci * usb_register_device_driver - register a USB device (not interface) driver
9698c2ecf20Sopenharmony_ci * @new_udriver: USB operations for the device driver
9708c2ecf20Sopenharmony_ci * @owner: module owner of this driver.
9718c2ecf20Sopenharmony_ci *
9728c2ecf20Sopenharmony_ci * Registers a USB device driver with the USB core.  The list of
9738c2ecf20Sopenharmony_ci * unattached devices will be rescanned whenever a new driver is
9748c2ecf20Sopenharmony_ci * added, allowing the new driver to attach to any recognized devices.
9758c2ecf20Sopenharmony_ci *
9768c2ecf20Sopenharmony_ci * Return: A negative error code on failure and 0 on success.
9778c2ecf20Sopenharmony_ci */
9788c2ecf20Sopenharmony_ciint usb_register_device_driver(struct usb_device_driver *new_udriver,
9798c2ecf20Sopenharmony_ci		struct module *owner)
9808c2ecf20Sopenharmony_ci{
9818c2ecf20Sopenharmony_ci	int retval = 0;
9828c2ecf20Sopenharmony_ci
9838c2ecf20Sopenharmony_ci	if (usb_disabled())
9848c2ecf20Sopenharmony_ci		return -ENODEV;
9858c2ecf20Sopenharmony_ci
9868c2ecf20Sopenharmony_ci	new_udriver->drvwrap.for_devices = 1;
9878c2ecf20Sopenharmony_ci	new_udriver->drvwrap.driver.name = new_udriver->name;
9888c2ecf20Sopenharmony_ci	new_udriver->drvwrap.driver.bus = &usb_bus_type;
9898c2ecf20Sopenharmony_ci	new_udriver->drvwrap.driver.probe = usb_probe_device;
9908c2ecf20Sopenharmony_ci	new_udriver->drvwrap.driver.remove = usb_unbind_device;
9918c2ecf20Sopenharmony_ci	new_udriver->drvwrap.driver.owner = owner;
9928c2ecf20Sopenharmony_ci	new_udriver->drvwrap.driver.dev_groups = new_udriver->dev_groups;
9938c2ecf20Sopenharmony_ci
9948c2ecf20Sopenharmony_ci	retval = driver_register(&new_udriver->drvwrap.driver);
9958c2ecf20Sopenharmony_ci
9968c2ecf20Sopenharmony_ci	if (!retval) {
9978c2ecf20Sopenharmony_ci		pr_info("%s: registered new device driver %s\n",
9988c2ecf20Sopenharmony_ci			usbcore_name, new_udriver->name);
9998c2ecf20Sopenharmony_ci		/*
10008c2ecf20Sopenharmony_ci		 * Check whether any device could be better served with
10018c2ecf20Sopenharmony_ci		 * this new driver
10028c2ecf20Sopenharmony_ci		 */
10038c2ecf20Sopenharmony_ci		bus_for_each_dev(&usb_bus_type, NULL, new_udriver,
10048c2ecf20Sopenharmony_ci				 __usb_bus_reprobe_drivers);
10058c2ecf20Sopenharmony_ci	} else {
10068c2ecf20Sopenharmony_ci		pr_err("%s: error %d registering device driver %s\n",
10078c2ecf20Sopenharmony_ci			usbcore_name, retval, new_udriver->name);
10088c2ecf20Sopenharmony_ci	}
10098c2ecf20Sopenharmony_ci
10108c2ecf20Sopenharmony_ci	return retval;
10118c2ecf20Sopenharmony_ci}
10128c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(usb_register_device_driver);
10138c2ecf20Sopenharmony_ci
10148c2ecf20Sopenharmony_ci/**
10158c2ecf20Sopenharmony_ci * usb_deregister_device_driver - unregister a USB device (not interface) driver
10168c2ecf20Sopenharmony_ci * @udriver: USB operations of the device driver to unregister
10178c2ecf20Sopenharmony_ci * Context: must be able to sleep
10188c2ecf20Sopenharmony_ci *
10198c2ecf20Sopenharmony_ci * Unlinks the specified driver from the internal USB driver list.
10208c2ecf20Sopenharmony_ci */
10218c2ecf20Sopenharmony_civoid usb_deregister_device_driver(struct usb_device_driver *udriver)
10228c2ecf20Sopenharmony_ci{
10238c2ecf20Sopenharmony_ci	pr_info("%s: deregistering device driver %s\n",
10248c2ecf20Sopenharmony_ci			usbcore_name, udriver->name);
10258c2ecf20Sopenharmony_ci
10268c2ecf20Sopenharmony_ci	driver_unregister(&udriver->drvwrap.driver);
10278c2ecf20Sopenharmony_ci}
10288c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(usb_deregister_device_driver);
10298c2ecf20Sopenharmony_ci
10308c2ecf20Sopenharmony_ci/**
10318c2ecf20Sopenharmony_ci * usb_register_driver - register a USB interface driver
10328c2ecf20Sopenharmony_ci * @new_driver: USB operations for the interface driver
10338c2ecf20Sopenharmony_ci * @owner: module owner of this driver.
10348c2ecf20Sopenharmony_ci * @mod_name: module name string
10358c2ecf20Sopenharmony_ci *
10368c2ecf20Sopenharmony_ci * Registers a USB interface driver with the USB core.  The list of
10378c2ecf20Sopenharmony_ci * unattached interfaces will be rescanned whenever a new driver is
10388c2ecf20Sopenharmony_ci * added, allowing the new driver to attach to any recognized interfaces.
10398c2ecf20Sopenharmony_ci *
10408c2ecf20Sopenharmony_ci * Return: A negative error code on failure and 0 on success.
10418c2ecf20Sopenharmony_ci *
10428c2ecf20Sopenharmony_ci * NOTE: if you want your driver to use the USB major number, you must call
10438c2ecf20Sopenharmony_ci * usb_register_dev() to enable that functionality.  This function no longer
10448c2ecf20Sopenharmony_ci * takes care of that.
10458c2ecf20Sopenharmony_ci */
10468c2ecf20Sopenharmony_ciint usb_register_driver(struct usb_driver *new_driver, struct module *owner,
10478c2ecf20Sopenharmony_ci			const char *mod_name)
10488c2ecf20Sopenharmony_ci{
10498c2ecf20Sopenharmony_ci	int retval = 0;
10508c2ecf20Sopenharmony_ci
10518c2ecf20Sopenharmony_ci	if (usb_disabled())
10528c2ecf20Sopenharmony_ci		return -ENODEV;
10538c2ecf20Sopenharmony_ci
10548c2ecf20Sopenharmony_ci	new_driver->drvwrap.for_devices = 0;
10558c2ecf20Sopenharmony_ci	new_driver->drvwrap.driver.name = new_driver->name;
10568c2ecf20Sopenharmony_ci	new_driver->drvwrap.driver.bus = &usb_bus_type;
10578c2ecf20Sopenharmony_ci	new_driver->drvwrap.driver.probe = usb_probe_interface;
10588c2ecf20Sopenharmony_ci	new_driver->drvwrap.driver.remove = usb_unbind_interface;
10598c2ecf20Sopenharmony_ci	new_driver->drvwrap.driver.owner = owner;
10608c2ecf20Sopenharmony_ci	new_driver->drvwrap.driver.mod_name = mod_name;
10618c2ecf20Sopenharmony_ci	new_driver->drvwrap.driver.dev_groups = new_driver->dev_groups;
10628c2ecf20Sopenharmony_ci	spin_lock_init(&new_driver->dynids.lock);
10638c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&new_driver->dynids.list);
10648c2ecf20Sopenharmony_ci
10658c2ecf20Sopenharmony_ci	retval = driver_register(&new_driver->drvwrap.driver);
10668c2ecf20Sopenharmony_ci	if (retval)
10678c2ecf20Sopenharmony_ci		goto out;
10688c2ecf20Sopenharmony_ci
10698c2ecf20Sopenharmony_ci	retval = usb_create_newid_files(new_driver);
10708c2ecf20Sopenharmony_ci	if (retval)
10718c2ecf20Sopenharmony_ci		goto out_newid;
10728c2ecf20Sopenharmony_ci
10738c2ecf20Sopenharmony_ci	pr_info("%s: registered new interface driver %s\n",
10748c2ecf20Sopenharmony_ci			usbcore_name, new_driver->name);
10758c2ecf20Sopenharmony_ci
10768c2ecf20Sopenharmony_ciout:
10778c2ecf20Sopenharmony_ci	return retval;
10788c2ecf20Sopenharmony_ci
10798c2ecf20Sopenharmony_ciout_newid:
10808c2ecf20Sopenharmony_ci	driver_unregister(&new_driver->drvwrap.driver);
10818c2ecf20Sopenharmony_ci
10828c2ecf20Sopenharmony_ci	pr_err("%s: error %d registering interface driver %s\n",
10838c2ecf20Sopenharmony_ci		usbcore_name, retval, new_driver->name);
10848c2ecf20Sopenharmony_ci	goto out;
10858c2ecf20Sopenharmony_ci}
10868c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(usb_register_driver);
10878c2ecf20Sopenharmony_ci
10888c2ecf20Sopenharmony_ci/**
10898c2ecf20Sopenharmony_ci * usb_deregister - unregister a USB interface driver
10908c2ecf20Sopenharmony_ci * @driver: USB operations of the interface driver to unregister
10918c2ecf20Sopenharmony_ci * Context: must be able to sleep
10928c2ecf20Sopenharmony_ci *
10938c2ecf20Sopenharmony_ci * Unlinks the specified driver from the internal USB driver list.
10948c2ecf20Sopenharmony_ci *
10958c2ecf20Sopenharmony_ci * NOTE: If you called usb_register_dev(), you still need to call
10968c2ecf20Sopenharmony_ci * usb_deregister_dev() to clean up your driver's allocated minor numbers,
10978c2ecf20Sopenharmony_ci * this * call will no longer do it for you.
10988c2ecf20Sopenharmony_ci */
10998c2ecf20Sopenharmony_civoid usb_deregister(struct usb_driver *driver)
11008c2ecf20Sopenharmony_ci{
11018c2ecf20Sopenharmony_ci	pr_info("%s: deregistering interface driver %s\n",
11028c2ecf20Sopenharmony_ci			usbcore_name, driver->name);
11038c2ecf20Sopenharmony_ci
11048c2ecf20Sopenharmony_ci	usb_remove_newid_files(driver);
11058c2ecf20Sopenharmony_ci	driver_unregister(&driver->drvwrap.driver);
11068c2ecf20Sopenharmony_ci	usb_free_dynids(driver);
11078c2ecf20Sopenharmony_ci}
11088c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(usb_deregister);
11098c2ecf20Sopenharmony_ci
11108c2ecf20Sopenharmony_ci/* Forced unbinding of a USB interface driver, either because
11118c2ecf20Sopenharmony_ci * it doesn't support pre_reset/post_reset/reset_resume or
11128c2ecf20Sopenharmony_ci * because it doesn't support suspend/resume.
11138c2ecf20Sopenharmony_ci *
11148c2ecf20Sopenharmony_ci * The caller must hold @intf's device's lock, but not @intf's lock.
11158c2ecf20Sopenharmony_ci */
11168c2ecf20Sopenharmony_civoid usb_forced_unbind_intf(struct usb_interface *intf)
11178c2ecf20Sopenharmony_ci{
11188c2ecf20Sopenharmony_ci	struct usb_driver *driver = to_usb_driver(intf->dev.driver);
11198c2ecf20Sopenharmony_ci
11208c2ecf20Sopenharmony_ci	dev_dbg(&intf->dev, "forced unbind\n");
11218c2ecf20Sopenharmony_ci	usb_driver_release_interface(driver, intf);
11228c2ecf20Sopenharmony_ci
11238c2ecf20Sopenharmony_ci	/* Mark the interface for later rebinding */
11248c2ecf20Sopenharmony_ci	intf->needs_binding = 1;
11258c2ecf20Sopenharmony_ci}
11268c2ecf20Sopenharmony_ci
11278c2ecf20Sopenharmony_ci/*
11288c2ecf20Sopenharmony_ci * Unbind drivers for @udev's marked interfaces.  These interfaces have
11298c2ecf20Sopenharmony_ci * the needs_binding flag set, for example by usb_resume_interface().
11308c2ecf20Sopenharmony_ci *
11318c2ecf20Sopenharmony_ci * The caller must hold @udev's device lock.
11328c2ecf20Sopenharmony_ci */
11338c2ecf20Sopenharmony_cistatic void unbind_marked_interfaces(struct usb_device *udev)
11348c2ecf20Sopenharmony_ci{
11358c2ecf20Sopenharmony_ci	struct usb_host_config	*config;
11368c2ecf20Sopenharmony_ci	int			i;
11378c2ecf20Sopenharmony_ci	struct usb_interface	*intf;
11388c2ecf20Sopenharmony_ci
11398c2ecf20Sopenharmony_ci	config = udev->actconfig;
11408c2ecf20Sopenharmony_ci	if (config) {
11418c2ecf20Sopenharmony_ci		for (i = 0; i < config->desc.bNumInterfaces; ++i) {
11428c2ecf20Sopenharmony_ci			intf = config->interface[i];
11438c2ecf20Sopenharmony_ci			if (intf->dev.driver && intf->needs_binding)
11448c2ecf20Sopenharmony_ci				usb_forced_unbind_intf(intf);
11458c2ecf20Sopenharmony_ci		}
11468c2ecf20Sopenharmony_ci	}
11478c2ecf20Sopenharmony_ci}
11488c2ecf20Sopenharmony_ci
11498c2ecf20Sopenharmony_ci/* Delayed forced unbinding of a USB interface driver and scan
11508c2ecf20Sopenharmony_ci * for rebinding.
11518c2ecf20Sopenharmony_ci *
11528c2ecf20Sopenharmony_ci * The caller must hold @intf's device's lock, but not @intf's lock.
11538c2ecf20Sopenharmony_ci *
11548c2ecf20Sopenharmony_ci * Note: Rebinds will be skipped if a system sleep transition is in
11558c2ecf20Sopenharmony_ci * progress and the PM "complete" callback hasn't occurred yet.
11568c2ecf20Sopenharmony_ci */
11578c2ecf20Sopenharmony_cistatic void usb_rebind_intf(struct usb_interface *intf)
11588c2ecf20Sopenharmony_ci{
11598c2ecf20Sopenharmony_ci	int rc;
11608c2ecf20Sopenharmony_ci
11618c2ecf20Sopenharmony_ci	/* Delayed unbind of an existing driver */
11628c2ecf20Sopenharmony_ci	if (intf->dev.driver)
11638c2ecf20Sopenharmony_ci		usb_forced_unbind_intf(intf);
11648c2ecf20Sopenharmony_ci
11658c2ecf20Sopenharmony_ci	/* Try to rebind the interface */
11668c2ecf20Sopenharmony_ci	if (!intf->dev.power.is_prepared) {
11678c2ecf20Sopenharmony_ci		intf->needs_binding = 0;
11688c2ecf20Sopenharmony_ci		rc = device_attach(&intf->dev);
11698c2ecf20Sopenharmony_ci		if (rc < 0 && rc != -EPROBE_DEFER)
11708c2ecf20Sopenharmony_ci			dev_warn(&intf->dev, "rebind failed: %d\n", rc);
11718c2ecf20Sopenharmony_ci	}
11728c2ecf20Sopenharmony_ci}
11738c2ecf20Sopenharmony_ci
11748c2ecf20Sopenharmony_ci/*
11758c2ecf20Sopenharmony_ci * Rebind drivers to @udev's marked interfaces.  These interfaces have
11768c2ecf20Sopenharmony_ci * the needs_binding flag set.
11778c2ecf20Sopenharmony_ci *
11788c2ecf20Sopenharmony_ci * The caller must hold @udev's device lock.
11798c2ecf20Sopenharmony_ci */
11808c2ecf20Sopenharmony_cistatic void rebind_marked_interfaces(struct usb_device *udev)
11818c2ecf20Sopenharmony_ci{
11828c2ecf20Sopenharmony_ci	struct usb_host_config	*config;
11838c2ecf20Sopenharmony_ci	int			i;
11848c2ecf20Sopenharmony_ci	struct usb_interface	*intf;
11858c2ecf20Sopenharmony_ci
11868c2ecf20Sopenharmony_ci	config = udev->actconfig;
11878c2ecf20Sopenharmony_ci	if (config) {
11888c2ecf20Sopenharmony_ci		for (i = 0; i < config->desc.bNumInterfaces; ++i) {
11898c2ecf20Sopenharmony_ci			intf = config->interface[i];
11908c2ecf20Sopenharmony_ci			if (intf->needs_binding)
11918c2ecf20Sopenharmony_ci				usb_rebind_intf(intf);
11928c2ecf20Sopenharmony_ci		}
11938c2ecf20Sopenharmony_ci	}
11948c2ecf20Sopenharmony_ci}
11958c2ecf20Sopenharmony_ci
11968c2ecf20Sopenharmony_ci/*
11978c2ecf20Sopenharmony_ci * Unbind all of @udev's marked interfaces and then rebind all of them.
11988c2ecf20Sopenharmony_ci * This ordering is necessary because some drivers claim several interfaces
11998c2ecf20Sopenharmony_ci * when they are first probed.
12008c2ecf20Sopenharmony_ci *
12018c2ecf20Sopenharmony_ci * The caller must hold @udev's device lock.
12028c2ecf20Sopenharmony_ci */
12038c2ecf20Sopenharmony_civoid usb_unbind_and_rebind_marked_interfaces(struct usb_device *udev)
12048c2ecf20Sopenharmony_ci{
12058c2ecf20Sopenharmony_ci	unbind_marked_interfaces(udev);
12068c2ecf20Sopenharmony_ci	rebind_marked_interfaces(udev);
12078c2ecf20Sopenharmony_ci}
12088c2ecf20Sopenharmony_ci
12098c2ecf20Sopenharmony_ci#ifdef CONFIG_PM
12108c2ecf20Sopenharmony_ci
12118c2ecf20Sopenharmony_ci/* Unbind drivers for @udev's interfaces that don't support suspend/resume
12128c2ecf20Sopenharmony_ci * There is no check for reset_resume here because it can be determined
12138c2ecf20Sopenharmony_ci * only during resume whether reset_resume is needed.
12148c2ecf20Sopenharmony_ci *
12158c2ecf20Sopenharmony_ci * The caller must hold @udev's device lock.
12168c2ecf20Sopenharmony_ci */
12178c2ecf20Sopenharmony_cistatic void unbind_no_pm_drivers_interfaces(struct usb_device *udev)
12188c2ecf20Sopenharmony_ci{
12198c2ecf20Sopenharmony_ci	struct usb_host_config	*config;
12208c2ecf20Sopenharmony_ci	int			i;
12218c2ecf20Sopenharmony_ci	struct usb_interface	*intf;
12228c2ecf20Sopenharmony_ci	struct usb_driver	*drv;
12238c2ecf20Sopenharmony_ci
12248c2ecf20Sopenharmony_ci	config = udev->actconfig;
12258c2ecf20Sopenharmony_ci	if (config) {
12268c2ecf20Sopenharmony_ci		for (i = 0; i < config->desc.bNumInterfaces; ++i) {
12278c2ecf20Sopenharmony_ci			intf = config->interface[i];
12288c2ecf20Sopenharmony_ci
12298c2ecf20Sopenharmony_ci			if (intf->dev.driver) {
12308c2ecf20Sopenharmony_ci				drv = to_usb_driver(intf->dev.driver);
12318c2ecf20Sopenharmony_ci				if (!drv->suspend || !drv->resume)
12328c2ecf20Sopenharmony_ci					usb_forced_unbind_intf(intf);
12338c2ecf20Sopenharmony_ci			}
12348c2ecf20Sopenharmony_ci		}
12358c2ecf20Sopenharmony_ci	}
12368c2ecf20Sopenharmony_ci}
12378c2ecf20Sopenharmony_ci
12388c2ecf20Sopenharmony_cistatic int usb_suspend_device(struct usb_device *udev, pm_message_t msg)
12398c2ecf20Sopenharmony_ci{
12408c2ecf20Sopenharmony_ci	struct usb_device_driver	*udriver;
12418c2ecf20Sopenharmony_ci	int				status = 0;
12428c2ecf20Sopenharmony_ci
12438c2ecf20Sopenharmony_ci	if (udev->state == USB_STATE_NOTATTACHED ||
12448c2ecf20Sopenharmony_ci			udev->state == USB_STATE_SUSPENDED)
12458c2ecf20Sopenharmony_ci		goto done;
12468c2ecf20Sopenharmony_ci
12478c2ecf20Sopenharmony_ci	/* For devices that don't have a driver, we do a generic suspend. */
12488c2ecf20Sopenharmony_ci	if (udev->dev.driver)
12498c2ecf20Sopenharmony_ci		udriver = to_usb_device_driver(udev->dev.driver);
12508c2ecf20Sopenharmony_ci	else {
12518c2ecf20Sopenharmony_ci		udev->do_remote_wakeup = 0;
12528c2ecf20Sopenharmony_ci		udriver = &usb_generic_driver;
12538c2ecf20Sopenharmony_ci	}
12548c2ecf20Sopenharmony_ci	if (udriver->suspend)
12558c2ecf20Sopenharmony_ci		status = udriver->suspend(udev, msg);
12568c2ecf20Sopenharmony_ci	if (status == 0 && udriver->generic_subclass)
12578c2ecf20Sopenharmony_ci		status = usb_generic_driver_suspend(udev, msg);
12588c2ecf20Sopenharmony_ci
12598c2ecf20Sopenharmony_ci done:
12608c2ecf20Sopenharmony_ci	dev_vdbg(&udev->dev, "%s: status %d\n", __func__, status);
12618c2ecf20Sopenharmony_ci	return status;
12628c2ecf20Sopenharmony_ci}
12638c2ecf20Sopenharmony_ci
12648c2ecf20Sopenharmony_cistatic int usb_resume_device(struct usb_device *udev, pm_message_t msg)
12658c2ecf20Sopenharmony_ci{
12668c2ecf20Sopenharmony_ci	struct usb_device_driver	*udriver;
12678c2ecf20Sopenharmony_ci	int				status = 0;
12688c2ecf20Sopenharmony_ci
12698c2ecf20Sopenharmony_ci	if (udev->state == USB_STATE_NOTATTACHED)
12708c2ecf20Sopenharmony_ci		goto done;
12718c2ecf20Sopenharmony_ci
12728c2ecf20Sopenharmony_ci	/* Can't resume it if it doesn't have a driver. */
12738c2ecf20Sopenharmony_ci	if (udev->dev.driver == NULL) {
12748c2ecf20Sopenharmony_ci		status = -ENOTCONN;
12758c2ecf20Sopenharmony_ci		goto done;
12768c2ecf20Sopenharmony_ci	}
12778c2ecf20Sopenharmony_ci
12788c2ecf20Sopenharmony_ci	/* Non-root devices on a full/low-speed bus must wait for their
12798c2ecf20Sopenharmony_ci	 * companion high-speed root hub, in case a handoff is needed.
12808c2ecf20Sopenharmony_ci	 */
12818c2ecf20Sopenharmony_ci	if (!PMSG_IS_AUTO(msg) && udev->parent && udev->bus->hs_companion)
12828c2ecf20Sopenharmony_ci		device_pm_wait_for_dev(&udev->dev,
12838c2ecf20Sopenharmony_ci				&udev->bus->hs_companion->root_hub->dev);
12848c2ecf20Sopenharmony_ci
12858c2ecf20Sopenharmony_ci	if (udev->quirks & USB_QUIRK_RESET_RESUME)
12868c2ecf20Sopenharmony_ci		udev->reset_resume = 1;
12878c2ecf20Sopenharmony_ci
12888c2ecf20Sopenharmony_ci	udriver = to_usb_device_driver(udev->dev.driver);
12898c2ecf20Sopenharmony_ci	if (udriver->generic_subclass)
12908c2ecf20Sopenharmony_ci		status = usb_generic_driver_resume(udev, msg);
12918c2ecf20Sopenharmony_ci	if (status == 0 && udriver->resume)
12928c2ecf20Sopenharmony_ci		status = udriver->resume(udev, msg);
12938c2ecf20Sopenharmony_ci
12948c2ecf20Sopenharmony_ci done:
12958c2ecf20Sopenharmony_ci	dev_vdbg(&udev->dev, "%s: status %d\n", __func__, status);
12968c2ecf20Sopenharmony_ci	return status;
12978c2ecf20Sopenharmony_ci}
12988c2ecf20Sopenharmony_ci
12998c2ecf20Sopenharmony_cistatic int usb_suspend_interface(struct usb_device *udev,
13008c2ecf20Sopenharmony_ci		struct usb_interface *intf, pm_message_t msg)
13018c2ecf20Sopenharmony_ci{
13028c2ecf20Sopenharmony_ci	struct usb_driver	*driver;
13038c2ecf20Sopenharmony_ci	int			status = 0;
13048c2ecf20Sopenharmony_ci
13058c2ecf20Sopenharmony_ci	if (udev->state == USB_STATE_NOTATTACHED ||
13068c2ecf20Sopenharmony_ci			intf->condition == USB_INTERFACE_UNBOUND)
13078c2ecf20Sopenharmony_ci		goto done;
13088c2ecf20Sopenharmony_ci	driver = to_usb_driver(intf->dev.driver);
13098c2ecf20Sopenharmony_ci
13108c2ecf20Sopenharmony_ci	/* at this time we know the driver supports suspend */
13118c2ecf20Sopenharmony_ci	status = driver->suspend(intf, msg);
13128c2ecf20Sopenharmony_ci	if (status && !PMSG_IS_AUTO(msg))
13138c2ecf20Sopenharmony_ci		dev_err(&intf->dev, "suspend error %d\n", status);
13148c2ecf20Sopenharmony_ci
13158c2ecf20Sopenharmony_ci done:
13168c2ecf20Sopenharmony_ci	dev_vdbg(&intf->dev, "%s: status %d\n", __func__, status);
13178c2ecf20Sopenharmony_ci	return status;
13188c2ecf20Sopenharmony_ci}
13198c2ecf20Sopenharmony_ci
13208c2ecf20Sopenharmony_cistatic int usb_resume_interface(struct usb_device *udev,
13218c2ecf20Sopenharmony_ci		struct usb_interface *intf, pm_message_t msg, int reset_resume)
13228c2ecf20Sopenharmony_ci{
13238c2ecf20Sopenharmony_ci	struct usb_driver	*driver;
13248c2ecf20Sopenharmony_ci	int			status = 0;
13258c2ecf20Sopenharmony_ci
13268c2ecf20Sopenharmony_ci	if (udev->state == USB_STATE_NOTATTACHED)
13278c2ecf20Sopenharmony_ci		goto done;
13288c2ecf20Sopenharmony_ci
13298c2ecf20Sopenharmony_ci	/* Don't let autoresume interfere with unbinding */
13308c2ecf20Sopenharmony_ci	if (intf->condition == USB_INTERFACE_UNBINDING)
13318c2ecf20Sopenharmony_ci		goto done;
13328c2ecf20Sopenharmony_ci
13338c2ecf20Sopenharmony_ci	/* Can't resume it if it doesn't have a driver. */
13348c2ecf20Sopenharmony_ci	if (intf->condition == USB_INTERFACE_UNBOUND) {
13358c2ecf20Sopenharmony_ci
13368c2ecf20Sopenharmony_ci		/* Carry out a deferred switch to altsetting 0 */
13378c2ecf20Sopenharmony_ci		if (intf->needs_altsetting0 && !intf->dev.power.is_prepared) {
13388c2ecf20Sopenharmony_ci			usb_set_interface(udev, intf->altsetting[0].
13398c2ecf20Sopenharmony_ci					desc.bInterfaceNumber, 0);
13408c2ecf20Sopenharmony_ci			intf->needs_altsetting0 = 0;
13418c2ecf20Sopenharmony_ci		}
13428c2ecf20Sopenharmony_ci		goto done;
13438c2ecf20Sopenharmony_ci	}
13448c2ecf20Sopenharmony_ci
13458c2ecf20Sopenharmony_ci	/* Don't resume if the interface is marked for rebinding */
13468c2ecf20Sopenharmony_ci	if (intf->needs_binding)
13478c2ecf20Sopenharmony_ci		goto done;
13488c2ecf20Sopenharmony_ci	driver = to_usb_driver(intf->dev.driver);
13498c2ecf20Sopenharmony_ci
13508c2ecf20Sopenharmony_ci	if (reset_resume) {
13518c2ecf20Sopenharmony_ci		if (driver->reset_resume) {
13528c2ecf20Sopenharmony_ci			status = driver->reset_resume(intf);
13538c2ecf20Sopenharmony_ci			if (status)
13548c2ecf20Sopenharmony_ci				dev_err(&intf->dev, "%s error %d\n",
13558c2ecf20Sopenharmony_ci						"reset_resume", status);
13568c2ecf20Sopenharmony_ci		} else {
13578c2ecf20Sopenharmony_ci			intf->needs_binding = 1;
13588c2ecf20Sopenharmony_ci			dev_dbg(&intf->dev, "no reset_resume for driver %s?\n",
13598c2ecf20Sopenharmony_ci					driver->name);
13608c2ecf20Sopenharmony_ci		}
13618c2ecf20Sopenharmony_ci	} else {
13628c2ecf20Sopenharmony_ci		status = driver->resume(intf);
13638c2ecf20Sopenharmony_ci		if (status)
13648c2ecf20Sopenharmony_ci			dev_err(&intf->dev, "resume error %d\n", status);
13658c2ecf20Sopenharmony_ci	}
13668c2ecf20Sopenharmony_ci
13678c2ecf20Sopenharmony_cidone:
13688c2ecf20Sopenharmony_ci	dev_vdbg(&intf->dev, "%s: status %d\n", __func__, status);
13698c2ecf20Sopenharmony_ci
13708c2ecf20Sopenharmony_ci	/* Later we will unbind the driver and/or reprobe, if necessary */
13718c2ecf20Sopenharmony_ci	return status;
13728c2ecf20Sopenharmony_ci}
13738c2ecf20Sopenharmony_ci
13748c2ecf20Sopenharmony_ci/**
13758c2ecf20Sopenharmony_ci * usb_suspend_both - suspend a USB device and its interfaces
13768c2ecf20Sopenharmony_ci * @udev: the usb_device to suspend
13778c2ecf20Sopenharmony_ci * @msg: Power Management message describing this state transition
13788c2ecf20Sopenharmony_ci *
13798c2ecf20Sopenharmony_ci * This is the central routine for suspending USB devices.  It calls the
13808c2ecf20Sopenharmony_ci * suspend methods for all the interface drivers in @udev and then calls
13818c2ecf20Sopenharmony_ci * the suspend method for @udev itself.  When the routine is called in
13828c2ecf20Sopenharmony_ci * autosuspend, if an error occurs at any stage, all the interfaces
13838c2ecf20Sopenharmony_ci * which were suspended are resumed so that they remain in the same
13848c2ecf20Sopenharmony_ci * state as the device, but when called from system sleep, all error
13858c2ecf20Sopenharmony_ci * from suspend methods of interfaces and the non-root-hub device itself
13868c2ecf20Sopenharmony_ci * are simply ignored, so all suspended interfaces are only resumed
13878c2ecf20Sopenharmony_ci * to the device's state when @udev is root-hub and its suspend method
13888c2ecf20Sopenharmony_ci * returns failure.
13898c2ecf20Sopenharmony_ci *
13908c2ecf20Sopenharmony_ci * Autosuspend requests originating from a child device or an interface
13918c2ecf20Sopenharmony_ci * driver may be made without the protection of @udev's device lock, but
13928c2ecf20Sopenharmony_ci * all other suspend calls will hold the lock.  Usbcore will insure that
13938c2ecf20Sopenharmony_ci * method calls do not arrive during bind, unbind, or reset operations.
13948c2ecf20Sopenharmony_ci * However drivers must be prepared to handle suspend calls arriving at
13958c2ecf20Sopenharmony_ci * unpredictable times.
13968c2ecf20Sopenharmony_ci *
13978c2ecf20Sopenharmony_ci * This routine can run only in process context.
13988c2ecf20Sopenharmony_ci *
13998c2ecf20Sopenharmony_ci * Return: 0 if the suspend succeeded.
14008c2ecf20Sopenharmony_ci */
14018c2ecf20Sopenharmony_cistatic int usb_suspend_both(struct usb_device *udev, pm_message_t msg)
14028c2ecf20Sopenharmony_ci{
14038c2ecf20Sopenharmony_ci	int			status = 0;
14048c2ecf20Sopenharmony_ci	int			i = 0, n = 0;
14058c2ecf20Sopenharmony_ci	struct usb_interface	*intf;
14068c2ecf20Sopenharmony_ci
14078c2ecf20Sopenharmony_ci	if (udev->state == USB_STATE_NOTATTACHED ||
14088c2ecf20Sopenharmony_ci			udev->state == USB_STATE_SUSPENDED)
14098c2ecf20Sopenharmony_ci		goto done;
14108c2ecf20Sopenharmony_ci
14118c2ecf20Sopenharmony_ci	/* Suspend all the interfaces and then udev itself */
14128c2ecf20Sopenharmony_ci	if (udev->actconfig) {
14138c2ecf20Sopenharmony_ci		n = udev->actconfig->desc.bNumInterfaces;
14148c2ecf20Sopenharmony_ci		for (i = n - 1; i >= 0; --i) {
14158c2ecf20Sopenharmony_ci			intf = udev->actconfig->interface[i];
14168c2ecf20Sopenharmony_ci			status = usb_suspend_interface(udev, intf, msg);
14178c2ecf20Sopenharmony_ci
14188c2ecf20Sopenharmony_ci			/* Ignore errors during system sleep transitions */
14198c2ecf20Sopenharmony_ci			if (!PMSG_IS_AUTO(msg))
14208c2ecf20Sopenharmony_ci				status = 0;
14218c2ecf20Sopenharmony_ci			if (status != 0)
14228c2ecf20Sopenharmony_ci				break;
14238c2ecf20Sopenharmony_ci		}
14248c2ecf20Sopenharmony_ci	}
14258c2ecf20Sopenharmony_ci	if (status == 0) {
14268c2ecf20Sopenharmony_ci		status = usb_suspend_device(udev, msg);
14278c2ecf20Sopenharmony_ci
14288c2ecf20Sopenharmony_ci		/*
14298c2ecf20Sopenharmony_ci		 * Ignore errors from non-root-hub devices during
14308c2ecf20Sopenharmony_ci		 * system sleep transitions.  For the most part,
14318c2ecf20Sopenharmony_ci		 * these devices should go to low power anyway when
14328c2ecf20Sopenharmony_ci		 * the entire bus is suspended.
14338c2ecf20Sopenharmony_ci		 */
14348c2ecf20Sopenharmony_ci		if (udev->parent && !PMSG_IS_AUTO(msg))
14358c2ecf20Sopenharmony_ci			status = 0;
14368c2ecf20Sopenharmony_ci
14378c2ecf20Sopenharmony_ci		/*
14388c2ecf20Sopenharmony_ci		 * If the device is inaccessible, don't try to resume
14398c2ecf20Sopenharmony_ci		 * suspended interfaces and just return the error.
14408c2ecf20Sopenharmony_ci		 */
14418c2ecf20Sopenharmony_ci		if (status && status != -EBUSY) {
14428c2ecf20Sopenharmony_ci			int err;
14438c2ecf20Sopenharmony_ci			u16 devstat;
14448c2ecf20Sopenharmony_ci
14458c2ecf20Sopenharmony_ci			err = usb_get_std_status(udev, USB_RECIP_DEVICE, 0,
14468c2ecf20Sopenharmony_ci						 &devstat);
14478c2ecf20Sopenharmony_ci			if (err) {
14488c2ecf20Sopenharmony_ci				dev_err(&udev->dev,
14498c2ecf20Sopenharmony_ci					"Failed to suspend device, error %d\n",
14508c2ecf20Sopenharmony_ci					status);
14518c2ecf20Sopenharmony_ci				goto done;
14528c2ecf20Sopenharmony_ci			}
14538c2ecf20Sopenharmony_ci		}
14548c2ecf20Sopenharmony_ci	}
14558c2ecf20Sopenharmony_ci
14568c2ecf20Sopenharmony_ci	/* If the suspend failed, resume interfaces that did get suspended */
14578c2ecf20Sopenharmony_ci	if (status != 0) {
14588c2ecf20Sopenharmony_ci		if (udev->actconfig) {
14598c2ecf20Sopenharmony_ci			msg.event ^= (PM_EVENT_SUSPEND | PM_EVENT_RESUME);
14608c2ecf20Sopenharmony_ci			while (++i < n) {
14618c2ecf20Sopenharmony_ci				intf = udev->actconfig->interface[i];
14628c2ecf20Sopenharmony_ci				usb_resume_interface(udev, intf, msg, 0);
14638c2ecf20Sopenharmony_ci			}
14648c2ecf20Sopenharmony_ci		}
14658c2ecf20Sopenharmony_ci
14668c2ecf20Sopenharmony_ci	/* If the suspend succeeded then prevent any more URB submissions
14678c2ecf20Sopenharmony_ci	 * and flush any outstanding URBs.
14688c2ecf20Sopenharmony_ci	 */
14698c2ecf20Sopenharmony_ci	} else {
14708c2ecf20Sopenharmony_ci		udev->can_submit = 0;
14718c2ecf20Sopenharmony_ci		for (i = 0; i < 16; ++i) {
14728c2ecf20Sopenharmony_ci			usb_hcd_flush_endpoint(udev, udev->ep_out[i]);
14738c2ecf20Sopenharmony_ci			usb_hcd_flush_endpoint(udev, udev->ep_in[i]);
14748c2ecf20Sopenharmony_ci		}
14758c2ecf20Sopenharmony_ci	}
14768c2ecf20Sopenharmony_ci
14778c2ecf20Sopenharmony_ci done:
14788c2ecf20Sopenharmony_ci	dev_vdbg(&udev->dev, "%s: status %d\n", __func__, status);
14798c2ecf20Sopenharmony_ci	return status;
14808c2ecf20Sopenharmony_ci}
14818c2ecf20Sopenharmony_ci
14828c2ecf20Sopenharmony_ci/**
14838c2ecf20Sopenharmony_ci * usb_resume_both - resume a USB device and its interfaces
14848c2ecf20Sopenharmony_ci * @udev: the usb_device to resume
14858c2ecf20Sopenharmony_ci * @msg: Power Management message describing this state transition
14868c2ecf20Sopenharmony_ci *
14878c2ecf20Sopenharmony_ci * This is the central routine for resuming USB devices.  It calls the
14888c2ecf20Sopenharmony_ci * the resume method for @udev and then calls the resume methods for all
14898c2ecf20Sopenharmony_ci * the interface drivers in @udev.
14908c2ecf20Sopenharmony_ci *
14918c2ecf20Sopenharmony_ci * Autoresume requests originating from a child device or an interface
14928c2ecf20Sopenharmony_ci * driver may be made without the protection of @udev's device lock, but
14938c2ecf20Sopenharmony_ci * all other resume calls will hold the lock.  Usbcore will insure that
14948c2ecf20Sopenharmony_ci * method calls do not arrive during bind, unbind, or reset operations.
14958c2ecf20Sopenharmony_ci * However drivers must be prepared to handle resume calls arriving at
14968c2ecf20Sopenharmony_ci * unpredictable times.
14978c2ecf20Sopenharmony_ci *
14988c2ecf20Sopenharmony_ci * This routine can run only in process context.
14998c2ecf20Sopenharmony_ci *
15008c2ecf20Sopenharmony_ci * Return: 0 on success.
15018c2ecf20Sopenharmony_ci */
15028c2ecf20Sopenharmony_cistatic int usb_resume_both(struct usb_device *udev, pm_message_t msg)
15038c2ecf20Sopenharmony_ci{
15048c2ecf20Sopenharmony_ci	int			status = 0;
15058c2ecf20Sopenharmony_ci	int			i;
15068c2ecf20Sopenharmony_ci	struct usb_interface	*intf;
15078c2ecf20Sopenharmony_ci
15088c2ecf20Sopenharmony_ci	if (udev->state == USB_STATE_NOTATTACHED) {
15098c2ecf20Sopenharmony_ci		status = -ENODEV;
15108c2ecf20Sopenharmony_ci		goto done;
15118c2ecf20Sopenharmony_ci	}
15128c2ecf20Sopenharmony_ci	udev->can_submit = 1;
15138c2ecf20Sopenharmony_ci
15148c2ecf20Sopenharmony_ci	/* Resume the device */
15158c2ecf20Sopenharmony_ci	if (udev->state == USB_STATE_SUSPENDED || udev->reset_resume)
15168c2ecf20Sopenharmony_ci		status = usb_resume_device(udev, msg);
15178c2ecf20Sopenharmony_ci
15188c2ecf20Sopenharmony_ci	/* Resume the interfaces */
15198c2ecf20Sopenharmony_ci	if (status == 0 && udev->actconfig) {
15208c2ecf20Sopenharmony_ci		for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {
15218c2ecf20Sopenharmony_ci			intf = udev->actconfig->interface[i];
15228c2ecf20Sopenharmony_ci			usb_resume_interface(udev, intf, msg,
15238c2ecf20Sopenharmony_ci					udev->reset_resume);
15248c2ecf20Sopenharmony_ci		}
15258c2ecf20Sopenharmony_ci	}
15268c2ecf20Sopenharmony_ci	usb_mark_last_busy(udev);
15278c2ecf20Sopenharmony_ci
15288c2ecf20Sopenharmony_ci done:
15298c2ecf20Sopenharmony_ci	dev_vdbg(&udev->dev, "%s: status %d\n", __func__, status);
15308c2ecf20Sopenharmony_ci	if (!status)
15318c2ecf20Sopenharmony_ci		udev->reset_resume = 0;
15328c2ecf20Sopenharmony_ci	return status;
15338c2ecf20Sopenharmony_ci}
15348c2ecf20Sopenharmony_ci
15358c2ecf20Sopenharmony_cistatic void choose_wakeup(struct usb_device *udev, pm_message_t msg)
15368c2ecf20Sopenharmony_ci{
15378c2ecf20Sopenharmony_ci	int	w;
15388c2ecf20Sopenharmony_ci
15398c2ecf20Sopenharmony_ci	/* Remote wakeup is needed only when we actually go to sleep.
15408c2ecf20Sopenharmony_ci	 * For things like FREEZE and QUIESCE, if the device is already
15418c2ecf20Sopenharmony_ci	 * autosuspended then its current wakeup setting is okay.
15428c2ecf20Sopenharmony_ci	 */
15438c2ecf20Sopenharmony_ci	if (msg.event == PM_EVENT_FREEZE || msg.event == PM_EVENT_QUIESCE) {
15448c2ecf20Sopenharmony_ci		if (udev->state != USB_STATE_SUSPENDED)
15458c2ecf20Sopenharmony_ci			udev->do_remote_wakeup = 0;
15468c2ecf20Sopenharmony_ci		return;
15478c2ecf20Sopenharmony_ci	}
15488c2ecf20Sopenharmony_ci
15498c2ecf20Sopenharmony_ci	/* Enable remote wakeup if it is allowed, even if no interface drivers
15508c2ecf20Sopenharmony_ci	 * actually want it.
15518c2ecf20Sopenharmony_ci	 */
15528c2ecf20Sopenharmony_ci	w = device_may_wakeup(&udev->dev);
15538c2ecf20Sopenharmony_ci
15548c2ecf20Sopenharmony_ci	/* If the device is autosuspended with the wrong wakeup setting,
15558c2ecf20Sopenharmony_ci	 * autoresume now so the setting can be changed.
15568c2ecf20Sopenharmony_ci	 */
15578c2ecf20Sopenharmony_ci	if (udev->state == USB_STATE_SUSPENDED && w != udev->do_remote_wakeup)
15588c2ecf20Sopenharmony_ci		pm_runtime_resume(&udev->dev);
15598c2ecf20Sopenharmony_ci	udev->do_remote_wakeup = w;
15608c2ecf20Sopenharmony_ci}
15618c2ecf20Sopenharmony_ci
15628c2ecf20Sopenharmony_ci/* The device lock is held by the PM core */
15638c2ecf20Sopenharmony_ciint usb_suspend(struct device *dev, pm_message_t msg)
15648c2ecf20Sopenharmony_ci{
15658c2ecf20Sopenharmony_ci	struct usb_device	*udev = to_usb_device(dev);
15668c2ecf20Sopenharmony_ci	int r;
15678c2ecf20Sopenharmony_ci
15688c2ecf20Sopenharmony_ci	unbind_no_pm_drivers_interfaces(udev);
15698c2ecf20Sopenharmony_ci
15708c2ecf20Sopenharmony_ci	/* From now on we are sure all drivers support suspend/resume
15718c2ecf20Sopenharmony_ci	 * but not necessarily reset_resume()
15728c2ecf20Sopenharmony_ci	 * so we may still need to unbind and rebind upon resume
15738c2ecf20Sopenharmony_ci	 */
15748c2ecf20Sopenharmony_ci	choose_wakeup(udev, msg);
15758c2ecf20Sopenharmony_ci	r = usb_suspend_both(udev, msg);
15768c2ecf20Sopenharmony_ci	if (r)
15778c2ecf20Sopenharmony_ci		return r;
15788c2ecf20Sopenharmony_ci
15798c2ecf20Sopenharmony_ci	if (udev->quirks & USB_QUIRK_DISCONNECT_SUSPEND)
15808c2ecf20Sopenharmony_ci		usb_port_disable(udev);
15818c2ecf20Sopenharmony_ci
15828c2ecf20Sopenharmony_ci	return 0;
15838c2ecf20Sopenharmony_ci}
15848c2ecf20Sopenharmony_ci
15858c2ecf20Sopenharmony_ci/* The device lock is held by the PM core */
15868c2ecf20Sopenharmony_ciint usb_resume_complete(struct device *dev)
15878c2ecf20Sopenharmony_ci{
15888c2ecf20Sopenharmony_ci	struct usb_device *udev = to_usb_device(dev);
15898c2ecf20Sopenharmony_ci
15908c2ecf20Sopenharmony_ci	/* For PM complete calls, all we do is rebind interfaces
15918c2ecf20Sopenharmony_ci	 * whose needs_binding flag is set
15928c2ecf20Sopenharmony_ci	 */
15938c2ecf20Sopenharmony_ci	if (udev->state != USB_STATE_NOTATTACHED)
15948c2ecf20Sopenharmony_ci		rebind_marked_interfaces(udev);
15958c2ecf20Sopenharmony_ci	return 0;
15968c2ecf20Sopenharmony_ci}
15978c2ecf20Sopenharmony_ci
15988c2ecf20Sopenharmony_ci/* The device lock is held by the PM core */
15998c2ecf20Sopenharmony_ciint usb_resume(struct device *dev, pm_message_t msg)
16008c2ecf20Sopenharmony_ci{
16018c2ecf20Sopenharmony_ci	struct usb_device	*udev = to_usb_device(dev);
16028c2ecf20Sopenharmony_ci	int			status;
16038c2ecf20Sopenharmony_ci
16048c2ecf20Sopenharmony_ci	/* For all calls, take the device back to full power and
16058c2ecf20Sopenharmony_ci	 * tell the PM core in case it was autosuspended previously.
16068c2ecf20Sopenharmony_ci	 * Unbind the interfaces that will need rebinding later,
16078c2ecf20Sopenharmony_ci	 * because they fail to support reset_resume.
16088c2ecf20Sopenharmony_ci	 * (This can't be done in usb_resume_interface()
16098c2ecf20Sopenharmony_ci	 * above because it doesn't own the right set of locks.)
16108c2ecf20Sopenharmony_ci	 */
16118c2ecf20Sopenharmony_ci	status = usb_resume_both(udev, msg);
16128c2ecf20Sopenharmony_ci	if (status == 0) {
16138c2ecf20Sopenharmony_ci		pm_runtime_disable(dev);
16148c2ecf20Sopenharmony_ci		pm_runtime_set_active(dev);
16158c2ecf20Sopenharmony_ci		pm_runtime_enable(dev);
16168c2ecf20Sopenharmony_ci		unbind_marked_interfaces(udev);
16178c2ecf20Sopenharmony_ci	}
16188c2ecf20Sopenharmony_ci
16198c2ecf20Sopenharmony_ci	/* Avoid PM error messages for devices disconnected while suspended
16208c2ecf20Sopenharmony_ci	 * as we'll display regular disconnect messages just a bit later.
16218c2ecf20Sopenharmony_ci	 */
16228c2ecf20Sopenharmony_ci	if (status == -ENODEV || status == -ESHUTDOWN)
16238c2ecf20Sopenharmony_ci		status = 0;
16248c2ecf20Sopenharmony_ci	return status;
16258c2ecf20Sopenharmony_ci}
16268c2ecf20Sopenharmony_ci
16278c2ecf20Sopenharmony_ci/**
16288c2ecf20Sopenharmony_ci * usb_enable_autosuspend - allow a USB device to be autosuspended
16298c2ecf20Sopenharmony_ci * @udev: the USB device which may be autosuspended
16308c2ecf20Sopenharmony_ci *
16318c2ecf20Sopenharmony_ci * This routine allows @udev to be autosuspended.  An autosuspend won't
16328c2ecf20Sopenharmony_ci * take place until the autosuspend_delay has elapsed and all the other
16338c2ecf20Sopenharmony_ci * necessary conditions are satisfied.
16348c2ecf20Sopenharmony_ci *
16358c2ecf20Sopenharmony_ci * The caller must hold @udev's device lock.
16368c2ecf20Sopenharmony_ci */
16378c2ecf20Sopenharmony_civoid usb_enable_autosuspend(struct usb_device *udev)
16388c2ecf20Sopenharmony_ci{
16398c2ecf20Sopenharmony_ci	pm_runtime_allow(&udev->dev);
16408c2ecf20Sopenharmony_ci}
16418c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(usb_enable_autosuspend);
16428c2ecf20Sopenharmony_ci
16438c2ecf20Sopenharmony_ci/**
16448c2ecf20Sopenharmony_ci * usb_disable_autosuspend - prevent a USB device from being autosuspended
16458c2ecf20Sopenharmony_ci * @udev: the USB device which may not be autosuspended
16468c2ecf20Sopenharmony_ci *
16478c2ecf20Sopenharmony_ci * This routine prevents @udev from being autosuspended and wakes it up
16488c2ecf20Sopenharmony_ci * if it is already autosuspended.
16498c2ecf20Sopenharmony_ci *
16508c2ecf20Sopenharmony_ci * The caller must hold @udev's device lock.
16518c2ecf20Sopenharmony_ci */
16528c2ecf20Sopenharmony_civoid usb_disable_autosuspend(struct usb_device *udev)
16538c2ecf20Sopenharmony_ci{
16548c2ecf20Sopenharmony_ci	pm_runtime_forbid(&udev->dev);
16558c2ecf20Sopenharmony_ci}
16568c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(usb_disable_autosuspend);
16578c2ecf20Sopenharmony_ci
16588c2ecf20Sopenharmony_ci/**
16598c2ecf20Sopenharmony_ci * usb_autosuspend_device - delayed autosuspend of a USB device and its interfaces
16608c2ecf20Sopenharmony_ci * @udev: the usb_device to autosuspend
16618c2ecf20Sopenharmony_ci *
16628c2ecf20Sopenharmony_ci * This routine should be called when a core subsystem is finished using
16638c2ecf20Sopenharmony_ci * @udev and wants to allow it to autosuspend.  Examples would be when
16648c2ecf20Sopenharmony_ci * @udev's device file in usbfs is closed or after a configuration change.
16658c2ecf20Sopenharmony_ci *
16668c2ecf20Sopenharmony_ci * @udev's usage counter is decremented; if it drops to 0 and all the
16678c2ecf20Sopenharmony_ci * interfaces are inactive then a delayed autosuspend will be attempted.
16688c2ecf20Sopenharmony_ci * The attempt may fail (see autosuspend_check()).
16698c2ecf20Sopenharmony_ci *
16708c2ecf20Sopenharmony_ci * The caller must hold @udev's device lock.
16718c2ecf20Sopenharmony_ci *
16728c2ecf20Sopenharmony_ci * This routine can run only in process context.
16738c2ecf20Sopenharmony_ci */
16748c2ecf20Sopenharmony_civoid usb_autosuspend_device(struct usb_device *udev)
16758c2ecf20Sopenharmony_ci{
16768c2ecf20Sopenharmony_ci	int	status;
16778c2ecf20Sopenharmony_ci
16788c2ecf20Sopenharmony_ci	usb_mark_last_busy(udev);
16798c2ecf20Sopenharmony_ci	status = pm_runtime_put_sync_autosuspend(&udev->dev);
16808c2ecf20Sopenharmony_ci	dev_vdbg(&udev->dev, "%s: cnt %d -> %d\n",
16818c2ecf20Sopenharmony_ci			__func__, atomic_read(&udev->dev.power.usage_count),
16828c2ecf20Sopenharmony_ci			status);
16838c2ecf20Sopenharmony_ci}
16848c2ecf20Sopenharmony_ci
16858c2ecf20Sopenharmony_ci/**
16868c2ecf20Sopenharmony_ci * usb_autoresume_device - immediately autoresume a USB device and its interfaces
16878c2ecf20Sopenharmony_ci * @udev: the usb_device to autoresume
16888c2ecf20Sopenharmony_ci *
16898c2ecf20Sopenharmony_ci * This routine should be called when a core subsystem wants to use @udev
16908c2ecf20Sopenharmony_ci * and needs to guarantee that it is not suspended.  No autosuspend will
16918c2ecf20Sopenharmony_ci * occur until usb_autosuspend_device() is called.  (Note that this will
16928c2ecf20Sopenharmony_ci * not prevent suspend events originating in the PM core.)  Examples would
16938c2ecf20Sopenharmony_ci * be when @udev's device file in usbfs is opened or when a remote-wakeup
16948c2ecf20Sopenharmony_ci * request is received.
16958c2ecf20Sopenharmony_ci *
16968c2ecf20Sopenharmony_ci * @udev's usage counter is incremented to prevent subsequent autosuspends.
16978c2ecf20Sopenharmony_ci * However if the autoresume fails then the usage counter is re-decremented.
16988c2ecf20Sopenharmony_ci *
16998c2ecf20Sopenharmony_ci * The caller must hold @udev's device lock.
17008c2ecf20Sopenharmony_ci *
17018c2ecf20Sopenharmony_ci * This routine can run only in process context.
17028c2ecf20Sopenharmony_ci *
17038c2ecf20Sopenharmony_ci * Return: 0 on success. A negative error code otherwise.
17048c2ecf20Sopenharmony_ci */
17058c2ecf20Sopenharmony_ciint usb_autoresume_device(struct usb_device *udev)
17068c2ecf20Sopenharmony_ci{
17078c2ecf20Sopenharmony_ci	int	status;
17088c2ecf20Sopenharmony_ci
17098c2ecf20Sopenharmony_ci	status = pm_runtime_get_sync(&udev->dev);
17108c2ecf20Sopenharmony_ci	if (status < 0)
17118c2ecf20Sopenharmony_ci		pm_runtime_put_sync(&udev->dev);
17128c2ecf20Sopenharmony_ci	dev_vdbg(&udev->dev, "%s: cnt %d -> %d\n",
17138c2ecf20Sopenharmony_ci			__func__, atomic_read(&udev->dev.power.usage_count),
17148c2ecf20Sopenharmony_ci			status);
17158c2ecf20Sopenharmony_ci	if (status > 0)
17168c2ecf20Sopenharmony_ci		status = 0;
17178c2ecf20Sopenharmony_ci	return status;
17188c2ecf20Sopenharmony_ci}
17198c2ecf20Sopenharmony_ci
17208c2ecf20Sopenharmony_ci/**
17218c2ecf20Sopenharmony_ci * usb_autopm_put_interface - decrement a USB interface's PM-usage counter
17228c2ecf20Sopenharmony_ci * @intf: the usb_interface whose counter should be decremented
17238c2ecf20Sopenharmony_ci *
17248c2ecf20Sopenharmony_ci * This routine should be called by an interface driver when it is
17258c2ecf20Sopenharmony_ci * finished using @intf and wants to allow it to autosuspend.  A typical
17268c2ecf20Sopenharmony_ci * example would be a character-device driver when its device file is
17278c2ecf20Sopenharmony_ci * closed.
17288c2ecf20Sopenharmony_ci *
17298c2ecf20Sopenharmony_ci * The routine decrements @intf's usage counter.  When the counter reaches
17308c2ecf20Sopenharmony_ci * 0, a delayed autosuspend request for @intf's device is attempted.  The
17318c2ecf20Sopenharmony_ci * attempt may fail (see autosuspend_check()).
17328c2ecf20Sopenharmony_ci *
17338c2ecf20Sopenharmony_ci * This routine can run only in process context.
17348c2ecf20Sopenharmony_ci */
17358c2ecf20Sopenharmony_civoid usb_autopm_put_interface(struct usb_interface *intf)
17368c2ecf20Sopenharmony_ci{
17378c2ecf20Sopenharmony_ci	struct usb_device	*udev = interface_to_usbdev(intf);
17388c2ecf20Sopenharmony_ci	int			status;
17398c2ecf20Sopenharmony_ci
17408c2ecf20Sopenharmony_ci	usb_mark_last_busy(udev);
17418c2ecf20Sopenharmony_ci	status = pm_runtime_put_sync(&intf->dev);
17428c2ecf20Sopenharmony_ci	dev_vdbg(&intf->dev, "%s: cnt %d -> %d\n",
17438c2ecf20Sopenharmony_ci			__func__, atomic_read(&intf->dev.power.usage_count),
17448c2ecf20Sopenharmony_ci			status);
17458c2ecf20Sopenharmony_ci}
17468c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(usb_autopm_put_interface);
17478c2ecf20Sopenharmony_ci
17488c2ecf20Sopenharmony_ci/**
17498c2ecf20Sopenharmony_ci * usb_autopm_put_interface_async - decrement a USB interface's PM-usage counter
17508c2ecf20Sopenharmony_ci * @intf: the usb_interface whose counter should be decremented
17518c2ecf20Sopenharmony_ci *
17528c2ecf20Sopenharmony_ci * This routine does much the same thing as usb_autopm_put_interface():
17538c2ecf20Sopenharmony_ci * It decrements @intf's usage counter and schedules a delayed
17548c2ecf20Sopenharmony_ci * autosuspend request if the counter is <= 0.  The difference is that it
17558c2ecf20Sopenharmony_ci * does not perform any synchronization; callers should hold a private
17568c2ecf20Sopenharmony_ci * lock and handle all synchronization issues themselves.
17578c2ecf20Sopenharmony_ci *
17588c2ecf20Sopenharmony_ci * Typically a driver would call this routine during an URB's completion
17598c2ecf20Sopenharmony_ci * handler, if no more URBs were pending.
17608c2ecf20Sopenharmony_ci *
17618c2ecf20Sopenharmony_ci * This routine can run in atomic context.
17628c2ecf20Sopenharmony_ci */
17638c2ecf20Sopenharmony_civoid usb_autopm_put_interface_async(struct usb_interface *intf)
17648c2ecf20Sopenharmony_ci{
17658c2ecf20Sopenharmony_ci	struct usb_device	*udev = interface_to_usbdev(intf);
17668c2ecf20Sopenharmony_ci	int			status;
17678c2ecf20Sopenharmony_ci
17688c2ecf20Sopenharmony_ci	usb_mark_last_busy(udev);
17698c2ecf20Sopenharmony_ci	status = pm_runtime_put(&intf->dev);
17708c2ecf20Sopenharmony_ci	dev_vdbg(&intf->dev, "%s: cnt %d -> %d\n",
17718c2ecf20Sopenharmony_ci			__func__, atomic_read(&intf->dev.power.usage_count),
17728c2ecf20Sopenharmony_ci			status);
17738c2ecf20Sopenharmony_ci}
17748c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(usb_autopm_put_interface_async);
17758c2ecf20Sopenharmony_ci
17768c2ecf20Sopenharmony_ci/**
17778c2ecf20Sopenharmony_ci * usb_autopm_put_interface_no_suspend - decrement a USB interface's PM-usage counter
17788c2ecf20Sopenharmony_ci * @intf: the usb_interface whose counter should be decremented
17798c2ecf20Sopenharmony_ci *
17808c2ecf20Sopenharmony_ci * This routine decrements @intf's usage counter but does not carry out an
17818c2ecf20Sopenharmony_ci * autosuspend.
17828c2ecf20Sopenharmony_ci *
17838c2ecf20Sopenharmony_ci * This routine can run in atomic context.
17848c2ecf20Sopenharmony_ci */
17858c2ecf20Sopenharmony_civoid usb_autopm_put_interface_no_suspend(struct usb_interface *intf)
17868c2ecf20Sopenharmony_ci{
17878c2ecf20Sopenharmony_ci	struct usb_device	*udev = interface_to_usbdev(intf);
17888c2ecf20Sopenharmony_ci
17898c2ecf20Sopenharmony_ci	usb_mark_last_busy(udev);
17908c2ecf20Sopenharmony_ci	pm_runtime_put_noidle(&intf->dev);
17918c2ecf20Sopenharmony_ci}
17928c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(usb_autopm_put_interface_no_suspend);
17938c2ecf20Sopenharmony_ci
17948c2ecf20Sopenharmony_ci/**
17958c2ecf20Sopenharmony_ci * usb_autopm_get_interface - increment a USB interface's PM-usage counter
17968c2ecf20Sopenharmony_ci * @intf: the usb_interface whose counter should be incremented
17978c2ecf20Sopenharmony_ci *
17988c2ecf20Sopenharmony_ci * This routine should be called by an interface driver when it wants to
17998c2ecf20Sopenharmony_ci * use @intf and needs to guarantee that it is not suspended.  In addition,
18008c2ecf20Sopenharmony_ci * the routine prevents @intf from being autosuspended subsequently.  (Note
18018c2ecf20Sopenharmony_ci * that this will not prevent suspend events originating in the PM core.)
18028c2ecf20Sopenharmony_ci * This prevention will persist until usb_autopm_put_interface() is called
18038c2ecf20Sopenharmony_ci * or @intf is unbound.  A typical example would be a character-device
18048c2ecf20Sopenharmony_ci * driver when its device file is opened.
18058c2ecf20Sopenharmony_ci *
18068c2ecf20Sopenharmony_ci * @intf's usage counter is incremented to prevent subsequent autosuspends.
18078c2ecf20Sopenharmony_ci * However if the autoresume fails then the counter is re-decremented.
18088c2ecf20Sopenharmony_ci *
18098c2ecf20Sopenharmony_ci * This routine can run only in process context.
18108c2ecf20Sopenharmony_ci *
18118c2ecf20Sopenharmony_ci * Return: 0 on success.
18128c2ecf20Sopenharmony_ci */
18138c2ecf20Sopenharmony_ciint usb_autopm_get_interface(struct usb_interface *intf)
18148c2ecf20Sopenharmony_ci{
18158c2ecf20Sopenharmony_ci	int	status;
18168c2ecf20Sopenharmony_ci
18178c2ecf20Sopenharmony_ci	status = pm_runtime_get_sync(&intf->dev);
18188c2ecf20Sopenharmony_ci	if (status < 0)
18198c2ecf20Sopenharmony_ci		pm_runtime_put_sync(&intf->dev);
18208c2ecf20Sopenharmony_ci	dev_vdbg(&intf->dev, "%s: cnt %d -> %d\n",
18218c2ecf20Sopenharmony_ci			__func__, atomic_read(&intf->dev.power.usage_count),
18228c2ecf20Sopenharmony_ci			status);
18238c2ecf20Sopenharmony_ci	if (status > 0)
18248c2ecf20Sopenharmony_ci		status = 0;
18258c2ecf20Sopenharmony_ci	return status;
18268c2ecf20Sopenharmony_ci}
18278c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(usb_autopm_get_interface);
18288c2ecf20Sopenharmony_ci
18298c2ecf20Sopenharmony_ci/**
18308c2ecf20Sopenharmony_ci * usb_autopm_get_interface_async - increment a USB interface's PM-usage counter
18318c2ecf20Sopenharmony_ci * @intf: the usb_interface whose counter should be incremented
18328c2ecf20Sopenharmony_ci *
18338c2ecf20Sopenharmony_ci * This routine does much the same thing as
18348c2ecf20Sopenharmony_ci * usb_autopm_get_interface(): It increments @intf's usage counter and
18358c2ecf20Sopenharmony_ci * queues an autoresume request if the device is suspended.  The
18368c2ecf20Sopenharmony_ci * differences are that it does not perform any synchronization (callers
18378c2ecf20Sopenharmony_ci * should hold a private lock and handle all synchronization issues
18388c2ecf20Sopenharmony_ci * themselves), and it does not autoresume the device directly (it only
18398c2ecf20Sopenharmony_ci * queues a request).  After a successful call, the device may not yet be
18408c2ecf20Sopenharmony_ci * resumed.
18418c2ecf20Sopenharmony_ci *
18428c2ecf20Sopenharmony_ci * This routine can run in atomic context.
18438c2ecf20Sopenharmony_ci *
18448c2ecf20Sopenharmony_ci * Return: 0 on success. A negative error code otherwise.
18458c2ecf20Sopenharmony_ci */
18468c2ecf20Sopenharmony_ciint usb_autopm_get_interface_async(struct usb_interface *intf)
18478c2ecf20Sopenharmony_ci{
18488c2ecf20Sopenharmony_ci	int	status;
18498c2ecf20Sopenharmony_ci
18508c2ecf20Sopenharmony_ci	status = pm_runtime_get(&intf->dev);
18518c2ecf20Sopenharmony_ci	if (status < 0 && status != -EINPROGRESS)
18528c2ecf20Sopenharmony_ci		pm_runtime_put_noidle(&intf->dev);
18538c2ecf20Sopenharmony_ci	dev_vdbg(&intf->dev, "%s: cnt %d -> %d\n",
18548c2ecf20Sopenharmony_ci			__func__, atomic_read(&intf->dev.power.usage_count),
18558c2ecf20Sopenharmony_ci			status);
18568c2ecf20Sopenharmony_ci	if (status > 0 || status == -EINPROGRESS)
18578c2ecf20Sopenharmony_ci		status = 0;
18588c2ecf20Sopenharmony_ci	return status;
18598c2ecf20Sopenharmony_ci}
18608c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(usb_autopm_get_interface_async);
18618c2ecf20Sopenharmony_ci
18628c2ecf20Sopenharmony_ci/**
18638c2ecf20Sopenharmony_ci * usb_autopm_get_interface_no_resume - increment a USB interface's PM-usage counter
18648c2ecf20Sopenharmony_ci * @intf: the usb_interface whose counter should be incremented
18658c2ecf20Sopenharmony_ci *
18668c2ecf20Sopenharmony_ci * This routine increments @intf's usage counter but does not carry out an
18678c2ecf20Sopenharmony_ci * autoresume.
18688c2ecf20Sopenharmony_ci *
18698c2ecf20Sopenharmony_ci * This routine can run in atomic context.
18708c2ecf20Sopenharmony_ci */
18718c2ecf20Sopenharmony_civoid usb_autopm_get_interface_no_resume(struct usb_interface *intf)
18728c2ecf20Sopenharmony_ci{
18738c2ecf20Sopenharmony_ci	struct usb_device	*udev = interface_to_usbdev(intf);
18748c2ecf20Sopenharmony_ci
18758c2ecf20Sopenharmony_ci	usb_mark_last_busy(udev);
18768c2ecf20Sopenharmony_ci	pm_runtime_get_noresume(&intf->dev);
18778c2ecf20Sopenharmony_ci}
18788c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(usb_autopm_get_interface_no_resume);
18798c2ecf20Sopenharmony_ci
18808c2ecf20Sopenharmony_ci/* Internal routine to check whether we may autosuspend a device. */
18818c2ecf20Sopenharmony_cistatic int autosuspend_check(struct usb_device *udev)
18828c2ecf20Sopenharmony_ci{
18838c2ecf20Sopenharmony_ci	int			w, i;
18848c2ecf20Sopenharmony_ci	struct usb_interface	*intf;
18858c2ecf20Sopenharmony_ci
18868c2ecf20Sopenharmony_ci	if (udev->state == USB_STATE_NOTATTACHED)
18878c2ecf20Sopenharmony_ci		return -ENODEV;
18888c2ecf20Sopenharmony_ci
18898c2ecf20Sopenharmony_ci	/* Fail if autosuspend is disabled, or any interfaces are in use, or
18908c2ecf20Sopenharmony_ci	 * any interface drivers require remote wakeup but it isn't available.
18918c2ecf20Sopenharmony_ci	 */
18928c2ecf20Sopenharmony_ci	w = 0;
18938c2ecf20Sopenharmony_ci	if (udev->actconfig) {
18948c2ecf20Sopenharmony_ci		for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {
18958c2ecf20Sopenharmony_ci			intf = udev->actconfig->interface[i];
18968c2ecf20Sopenharmony_ci
18978c2ecf20Sopenharmony_ci			/* We don't need to check interfaces that are
18988c2ecf20Sopenharmony_ci			 * disabled for runtime PM.  Either they are unbound
18998c2ecf20Sopenharmony_ci			 * or else their drivers don't support autosuspend
19008c2ecf20Sopenharmony_ci			 * and so they are permanently active.
19018c2ecf20Sopenharmony_ci			 */
19028c2ecf20Sopenharmony_ci			if (intf->dev.power.disable_depth)
19038c2ecf20Sopenharmony_ci				continue;
19048c2ecf20Sopenharmony_ci			if (atomic_read(&intf->dev.power.usage_count) > 0)
19058c2ecf20Sopenharmony_ci				return -EBUSY;
19068c2ecf20Sopenharmony_ci			w |= intf->needs_remote_wakeup;
19078c2ecf20Sopenharmony_ci
19088c2ecf20Sopenharmony_ci			/* Don't allow autosuspend if the device will need
19098c2ecf20Sopenharmony_ci			 * a reset-resume and any of its interface drivers
19108c2ecf20Sopenharmony_ci			 * doesn't include support or needs remote wakeup.
19118c2ecf20Sopenharmony_ci			 */
19128c2ecf20Sopenharmony_ci			if (udev->quirks & USB_QUIRK_RESET_RESUME) {
19138c2ecf20Sopenharmony_ci				struct usb_driver *driver;
19148c2ecf20Sopenharmony_ci
19158c2ecf20Sopenharmony_ci				driver = to_usb_driver(intf->dev.driver);
19168c2ecf20Sopenharmony_ci				if (!driver->reset_resume ||
19178c2ecf20Sopenharmony_ci						intf->needs_remote_wakeup)
19188c2ecf20Sopenharmony_ci					return -EOPNOTSUPP;
19198c2ecf20Sopenharmony_ci			}
19208c2ecf20Sopenharmony_ci		}
19218c2ecf20Sopenharmony_ci	}
19228c2ecf20Sopenharmony_ci	if (w && !device_can_wakeup(&udev->dev)) {
19238c2ecf20Sopenharmony_ci		dev_dbg(&udev->dev, "remote wakeup needed for autosuspend\n");
19248c2ecf20Sopenharmony_ci		return -EOPNOTSUPP;
19258c2ecf20Sopenharmony_ci	}
19268c2ecf20Sopenharmony_ci
19278c2ecf20Sopenharmony_ci	/*
19288c2ecf20Sopenharmony_ci	 * If the device is a direct child of the root hub and the HCD
19298c2ecf20Sopenharmony_ci	 * doesn't handle wakeup requests, don't allow autosuspend when
19308c2ecf20Sopenharmony_ci	 * wakeup is needed.
19318c2ecf20Sopenharmony_ci	 */
19328c2ecf20Sopenharmony_ci	if (w && udev->parent == udev->bus->root_hub &&
19338c2ecf20Sopenharmony_ci			bus_to_hcd(udev->bus)->cant_recv_wakeups) {
19348c2ecf20Sopenharmony_ci		dev_dbg(&udev->dev, "HCD doesn't handle wakeup requests\n");
19358c2ecf20Sopenharmony_ci		return -EOPNOTSUPP;
19368c2ecf20Sopenharmony_ci	}
19378c2ecf20Sopenharmony_ci
19388c2ecf20Sopenharmony_ci	udev->do_remote_wakeup = w;
19398c2ecf20Sopenharmony_ci	return 0;
19408c2ecf20Sopenharmony_ci}
19418c2ecf20Sopenharmony_ci
19428c2ecf20Sopenharmony_ciint usb_runtime_suspend(struct device *dev)
19438c2ecf20Sopenharmony_ci{
19448c2ecf20Sopenharmony_ci	struct usb_device	*udev = to_usb_device(dev);
19458c2ecf20Sopenharmony_ci	int			status;
19468c2ecf20Sopenharmony_ci
19478c2ecf20Sopenharmony_ci	/* A USB device can be suspended if it passes the various autosuspend
19488c2ecf20Sopenharmony_ci	 * checks.  Runtime suspend for a USB device means suspending all the
19498c2ecf20Sopenharmony_ci	 * interfaces and then the device itself.
19508c2ecf20Sopenharmony_ci	 */
19518c2ecf20Sopenharmony_ci	if (autosuspend_check(udev) != 0)
19528c2ecf20Sopenharmony_ci		return -EAGAIN;
19538c2ecf20Sopenharmony_ci
19548c2ecf20Sopenharmony_ci	status = usb_suspend_both(udev, PMSG_AUTO_SUSPEND);
19558c2ecf20Sopenharmony_ci
19568c2ecf20Sopenharmony_ci	/* Allow a retry if autosuspend failed temporarily */
19578c2ecf20Sopenharmony_ci	if (status == -EAGAIN || status == -EBUSY)
19588c2ecf20Sopenharmony_ci		usb_mark_last_busy(udev);
19598c2ecf20Sopenharmony_ci
19608c2ecf20Sopenharmony_ci	/*
19618c2ecf20Sopenharmony_ci	 * The PM core reacts badly unless the return code is 0,
19628c2ecf20Sopenharmony_ci	 * -EAGAIN, or -EBUSY, so always return -EBUSY on an error
19638c2ecf20Sopenharmony_ci	 * (except for root hubs, because they don't suspend through
19648c2ecf20Sopenharmony_ci	 * an upstream port like other USB devices).
19658c2ecf20Sopenharmony_ci	 */
19668c2ecf20Sopenharmony_ci	if (status != 0 && udev->parent)
19678c2ecf20Sopenharmony_ci		return -EBUSY;
19688c2ecf20Sopenharmony_ci	return status;
19698c2ecf20Sopenharmony_ci}
19708c2ecf20Sopenharmony_ci
19718c2ecf20Sopenharmony_ciint usb_runtime_resume(struct device *dev)
19728c2ecf20Sopenharmony_ci{
19738c2ecf20Sopenharmony_ci	struct usb_device	*udev = to_usb_device(dev);
19748c2ecf20Sopenharmony_ci	int			status;
19758c2ecf20Sopenharmony_ci
19768c2ecf20Sopenharmony_ci	/* Runtime resume for a USB device means resuming both the device
19778c2ecf20Sopenharmony_ci	 * and all its interfaces.
19788c2ecf20Sopenharmony_ci	 */
19798c2ecf20Sopenharmony_ci	status = usb_resume_both(udev, PMSG_AUTO_RESUME);
19808c2ecf20Sopenharmony_ci	return status;
19818c2ecf20Sopenharmony_ci}
19828c2ecf20Sopenharmony_ci
19838c2ecf20Sopenharmony_ciint usb_runtime_idle(struct device *dev)
19848c2ecf20Sopenharmony_ci{
19858c2ecf20Sopenharmony_ci	struct usb_device	*udev = to_usb_device(dev);
19868c2ecf20Sopenharmony_ci
19878c2ecf20Sopenharmony_ci	/* An idle USB device can be suspended if it passes the various
19888c2ecf20Sopenharmony_ci	 * autosuspend checks.
19898c2ecf20Sopenharmony_ci	 */
19908c2ecf20Sopenharmony_ci	if (autosuspend_check(udev) == 0)
19918c2ecf20Sopenharmony_ci		pm_runtime_autosuspend(dev);
19928c2ecf20Sopenharmony_ci	/* Tell the core not to suspend it, though. */
19938c2ecf20Sopenharmony_ci	return -EBUSY;
19948c2ecf20Sopenharmony_ci}
19958c2ecf20Sopenharmony_ci
19968c2ecf20Sopenharmony_cistatic int usb_set_usb2_hardware_lpm(struct usb_device *udev, int enable)
19978c2ecf20Sopenharmony_ci{
19988c2ecf20Sopenharmony_ci	struct usb_hcd *hcd = bus_to_hcd(udev->bus);
19998c2ecf20Sopenharmony_ci	int ret = -EPERM;
20008c2ecf20Sopenharmony_ci
20018c2ecf20Sopenharmony_ci	if (hcd->driver->set_usb2_hw_lpm) {
20028c2ecf20Sopenharmony_ci		ret = hcd->driver->set_usb2_hw_lpm(hcd, udev, enable);
20038c2ecf20Sopenharmony_ci		if (!ret)
20048c2ecf20Sopenharmony_ci			udev->usb2_hw_lpm_enabled = enable;
20058c2ecf20Sopenharmony_ci	}
20068c2ecf20Sopenharmony_ci
20078c2ecf20Sopenharmony_ci	return ret;
20088c2ecf20Sopenharmony_ci}
20098c2ecf20Sopenharmony_ci
20108c2ecf20Sopenharmony_ciint usb_enable_usb2_hardware_lpm(struct usb_device *udev)
20118c2ecf20Sopenharmony_ci{
20128c2ecf20Sopenharmony_ci	if (!udev->usb2_hw_lpm_capable ||
20138c2ecf20Sopenharmony_ci	    !udev->usb2_hw_lpm_allowed ||
20148c2ecf20Sopenharmony_ci	    udev->usb2_hw_lpm_enabled)
20158c2ecf20Sopenharmony_ci		return 0;
20168c2ecf20Sopenharmony_ci
20178c2ecf20Sopenharmony_ci	return usb_set_usb2_hardware_lpm(udev, 1);
20188c2ecf20Sopenharmony_ci}
20198c2ecf20Sopenharmony_ci
20208c2ecf20Sopenharmony_ciint usb_disable_usb2_hardware_lpm(struct usb_device *udev)
20218c2ecf20Sopenharmony_ci{
20228c2ecf20Sopenharmony_ci	if (!udev->usb2_hw_lpm_enabled)
20238c2ecf20Sopenharmony_ci		return 0;
20248c2ecf20Sopenharmony_ci
20258c2ecf20Sopenharmony_ci	return usb_set_usb2_hardware_lpm(udev, 0);
20268c2ecf20Sopenharmony_ci}
20278c2ecf20Sopenharmony_ci
20288c2ecf20Sopenharmony_ci#endif /* CONFIG_PM */
20298c2ecf20Sopenharmony_ci
20308c2ecf20Sopenharmony_cistruct bus_type usb_bus_type = {
20318c2ecf20Sopenharmony_ci	.name =		"usb",
20328c2ecf20Sopenharmony_ci	.match =	usb_device_match,
20338c2ecf20Sopenharmony_ci	.uevent =	usb_uevent,
20348c2ecf20Sopenharmony_ci	.need_parent_lock =	true,
20358c2ecf20Sopenharmony_ci};
2036