--- zzzz-none-000/linux-5.4.213/drivers/usb/core/generic.c 2022-09-15 10:04:56.000000000 +0000 +++ alder-5690pro-762/linux-5.4.213/drivers/usb/core/generic.c 2024-08-14 09:02:08.000000000 +0000 @@ -24,6 +24,82 @@ #include #include "usb.h" +/* == 20160301 AVM/VGJ - CHANGESET: AVM Power Meter == */ +#ifdef CONFIG_AVM_POWERMETER +#include +#include +#endif /*--- #ifdef CONFIG_AVM_POWERMETER ---*/ + +#if defined(CONFIG_AVM_USB_PM) +#include + +static struct avm_usb_pm_blacklist avm_usb_pm_blacklist_devs[AVM_USB_PM_MAX_BLACKLIST_SIZE]; + +static unsigned int avm_usb_pm_blacklist_size; +module_param_named(suspend_blacklist_size, avm_usb_pm_blacklist_size, int, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(suspend_blacklist_size, "Count of blacklisted devices"); + +int suspend_error_count; +module_param(suspend_error_count, int, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(suspend_error_count, "Count of failed suspends"); + + +/* == 20171115 AVM/VGJ - Checks whether a device is blacklisted for suspension == */ +int avm_usb_pm_is_blacklisted(struct usb_device *udev) +{ + int i; + + if (avm_usb_pm_blacklist_size > AVM_USB_PM_MAX_BLACKLIST_SIZE) { + avm_usb_pm_blacklist_size = 0; + return 0; + } + + for (i = 0; i < avm_usb_pm_blacklist_size; i++) { + if (udev->descriptor.idVendor != avm_usb_pm_blacklist_devs[i].idVendor) { + continue; + } + if (udev->descriptor.idProduct != avm_usb_pm_blacklist_devs[i].idProduct) { + continue; + } + if (udev->descriptor.bcdDevice != avm_usb_pm_blacklist_devs[i].bcdDevice) { + continue; + } + + return 1; + } + + return 0; +} + +/* == 20171115 AVM/VGJ - Adds a device to the suspension blacklist == */ +void avm_usb_pm_add_to_blacklist(struct usb_device *udev) +{ + // Check whether device is already blacklisted + if (avm_usb_pm_is_blacklisted(udev)) { + return; + } + + mutex_lock(&usb_bus_idr_lock); + + // Add device to blacklist + if (avm_usb_pm_blacklist_size < AVM_USB_PM_MAX_BLACKLIST_SIZE) { + avm_usb_pm_blacklist_devs[avm_usb_pm_blacklist_size].idVendor = udev->descriptor.idVendor; + avm_usb_pm_blacklist_devs[avm_usb_pm_blacklist_size].idProduct = udev->descriptor.idProduct; + avm_usb_pm_blacklist_devs[avm_usb_pm_blacklist_size].bcdDevice = udev->descriptor.bcdDevice; + + avm_usb_pm_blacklist_size++; + } + + mutex_unlock(&usb_bus_idr_lock); + + dev_info(&udev->dev, "USB device %04x:%04x:%04x added to suspend blacklist\n", + le16_to_cpu(udev->descriptor.idVendor), + le16_to_cpu(udev->descriptor.idProduct), + le16_to_cpu(udev->descriptor.bcdDevice)); +} +EXPORT_SYMBOL_GPL(avm_usb_pm_add_to_blacklist); +#endif + static inline const char *plural(int n) { return (n == 1 ? "" : "s"); @@ -118,6 +194,33 @@ continue; } +/* == 20160301 AVM/VGJ - CHANGESET: AVM Power Meter for DWC3 USB Controller == */ +#if defined(CONFIG_AVM_POWERMETER) && defined(CONFIG_USB_DWC3_HOST) + if (udev->level == 1) { + unsigned int nextmA; + unsigned int avm_powerdevice; + + if (udev->speed == USB_SPEED_SUPER) { + nextmA = (c->desc.bMaxPower * 8); + if (nextmA <= 150) { + nextmA = 150; + } + } else { + nextmA = (c->desc.bMaxPower * 2); + /* A device should display at least 100 mA in AVM_POWERMETER */ + if (nextmA < 100) { + nextmA = 100; + } + } + + // Buses 1 and 2 belong to one port and buses 3 and 4 to the other + avm_powerdevice = (udev->bus->busnum < 3) ? powerdevice_usb_host : powerdevice_usb_host2; + dev_info(&udev->dev, "Bus#%u disconnect: AVM Powermeter changed to %u mA\n", + udev->bus->busnum, nextmA); + PowerManagmentRessourceInfo(avm_powerdevice, nextmA); + } +#endif // CONFIG_AVM_POWERMETER + /* * Select first configuration as default for audio so that * devices that don't comply with UAC3 protocol are supported. @@ -204,6 +307,11 @@ */ if (udev->authorized == 0) dev_err(&udev->dev, "Device is not authorized for usage\n"); +#if defined(CONFIG_AVM_ENHANCED) + /* == 2016022 AVM/VGJ - CHANGESET: noprobe Extension for AURA == */ + else if (udev->noprobe) + dev_err(&udev->dev, "Probing is disabled for this device\n"); +#endif else { c = usb_choose_configuration(udev); if (c >= 0) { @@ -254,9 +362,18 @@ else if ((msg.event == PM_EVENT_FREEZE || msg.event == PM_EVENT_PRETHAW) && (udev->speed < USB_SPEED_SUPER)) rc = 0; - else + else { rc = usb_port_suspend(udev, msg); +/* == 20171115 AVM/VGJ Some devices are disconnected while suspending == */ +#if defined(CONFIG_AVM_USB_PM) + if (udev->state == USB_STATE_NOTATTACHED) { + suspend_error_count++; + avm_usb_pm_add_to_blacklist(udev); + } +#endif + } + if (rc == 0) usbfs_notify_suspend(udev); return rc;