On Wed, Dec 14, 2022 at 3:07 PM Puma Hsu <pumahsu@xxxxxxxxxx> wrote: > > Add the hooks that vendor can design and bypass the suspend/resume. > When the handled is set, skip the original suspend/resume process. > > In mobile, a co-processor can be used for USB audio. When the co-processor > is working for USB audio, the co-processor is the user/owner of the USB > driver, and the ACPU is able to sleep in such condition to improve power > consumption. In original process, the ACPU will suspend/resume until the > USB suspend/resume. We add the hooks, so we can control USB suspend/resume > without affecting the ACPU. > > Signed-off-by: Puma Hsu <pumahsu@xxxxxxxxxx> > --- > drivers/usb/core/Makefile | 2 +- > drivers/usb/core/driver.c | 36 ++++++++++++++++++++++++++++++++++++ > drivers/usb/core/usb.h | 5 +++++ > 3 files changed, 42 insertions(+), 1 deletion(-) > > diff --git a/drivers/usb/core/Makefile b/drivers/usb/core/Makefile > index 7d338e9c0657..f48f646cd874 100644 > --- a/drivers/usb/core/Makefile > +++ b/drivers/usb/core/Makefile > @@ -3,7 +3,7 @@ > # Makefile for USB Core files and filesystem > # > > -usbcore-y := usb.o hub.o hcd.o urb.o message.o driver.o > +usbcore-y := usb.o hub.o hcd.o urb.o message.o driver.o usb-hooks-impl-goog.o > usbcore-y += config.o file.o buffer.o sysfs.o endpoint.o > usbcore-y += devio.o notify.o generic.o quirks.o devices.o > usbcore-y += phy.o port.o Sorry I should not add usb-hooks-impl-goog to the makefile. I will upload a version2 > diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c > index 7e7e119c253f..3d2cfb6c2277 100644 > --- a/drivers/usb/core/driver.c > +++ b/drivers/usb/core/driver.c > @@ -35,6 +35,25 @@ > #include "usb.h" > > > +static struct usb_device_vendor_ops *usb_dev_vendor_ops; > + > +int usb_dev_register_vendor_ops(struct usb_device_vendor_ops *vendor_ops) > +{ > + if (vendor_ops == NULL) > + return -EINVAL; > + > + usb_dev_vendor_ops = vendor_ops; > + return 0; > +} > +EXPORT_SYMBOL_GPL(usb_dev_register_vendor_ops); > + > +struct usb_device_vendor_ops *usb_vendor_get_ops(void) > +{ > + return usb_dev_vendor_ops; > +} > +EXPORT_SYMBOL_GPL(usb_vendor_get_ops); > + > + > /* > * Adds a new dynamic USBdevice ID to this driver, > * and cause the driver to probe for all devices again. > @@ -1400,11 +1419,19 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg) > int status = 0; > int i = 0, n = 0; > struct usb_interface *intf; > + bool handled; > + struct usb_device_vendor_ops *ops = usb_vendor_get_ops(); > > if (udev->state == USB_STATE_NOTATTACHED || > udev->state == USB_STATE_SUSPENDED) > goto done; > > + if (ops && ops->usb_dev_suspend) { > + handled = ops->usb_dev_suspend(udev, msg); > + if (handled) > + goto done; > + } > + > /* Suspend all the interfaces and then udev itself */ > if (udev->actconfig) { > n = udev->actconfig->desc.bNumInterfaces; > @@ -1501,11 +1528,20 @@ static int usb_resume_both(struct usb_device *udev, pm_message_t msg) > int status = 0; > int i; > struct usb_interface *intf; > + bool handled; > + struct usb_device_vendor_ops *ops = usb_vendor_get_ops(); > > if (udev->state == USB_STATE_NOTATTACHED) { > status = -ENODEV; > goto done; > } > + > + if (ops && ops->usb_dev_resume) { > + handled = ops->usb_dev_resume(udev, msg); > + if (handled) > + goto done; > + } > + > udev->can_submit = 1; > > /* Resume the device */ > diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h > index 82538daac8b8..9ccb8683071d 100644 > --- a/drivers/usb/core/usb.h > +++ b/drivers/usb/core/usb.h > @@ -220,3 +220,8 @@ extern acpi_handle usb_get_hub_port_acpi_handle(struct usb_device *hdev, > static inline int usb_acpi_register(void) { return 0; }; > static inline void usb_acpi_unregister(void) { }; > #endif > + > +struct usb_device_vendor_ops { > + bool (*usb_dev_suspend)(struct usb_device *udev, pm_message_t msg); > + bool (*usb_dev_resume)(struct usb_device *udev, pm_message_t msg); > +}; > -- > 2.39.0.rc1.256.g54fd8350bd-goog >