|
@@ -13,6 +13,7 @@
|
|
|
|
|
|
#include <linux/usb.h>
|
|
|
#include <linux/usb/quirks.h>
|
|
|
+#include <linux/usb/hcd.h>
|
|
|
#include "usb.h"
|
|
|
|
|
|
/* Lists of quirky USB devices, split in device quirks and interface quirks.
|
|
@@ -155,6 +156,21 @@ static const struct usb_device_id usb_interface_quirk_list[] = {
|
|
|
{ } /* terminating entry must be last */
|
|
|
};
|
|
|
|
|
|
+static const struct usb_device_id usb_amd_resume_quirk_list[] = {
|
|
|
+ /* Lenovo Mouse with Pixart controller */
|
|
|
+ { USB_DEVICE(0x17ef, 0x602e), .driver_info = USB_QUIRK_RESET_RESUME },
|
|
|
+
|
|
|
+ /* Pixart Mouse */
|
|
|
+ { USB_DEVICE(0x093a, 0x2500), .driver_info = USB_QUIRK_RESET_RESUME },
|
|
|
+ { USB_DEVICE(0x093a, 0x2510), .driver_info = USB_QUIRK_RESET_RESUME },
|
|
|
+ { USB_DEVICE(0x093a, 0x2521), .driver_info = USB_QUIRK_RESET_RESUME },
|
|
|
+
|
|
|
+ /* Logitech Optical Mouse M90/M100 */
|
|
|
+ { USB_DEVICE(0x046d, 0xc05a), .driver_info = USB_QUIRK_RESET_RESUME },
|
|
|
+
|
|
|
+ { } /* terminating entry must be last */
|
|
|
+};
|
|
|
+
|
|
|
static bool usb_match_any_interface(struct usb_device *udev,
|
|
|
const struct usb_device_id *id)
|
|
|
{
|
|
@@ -181,6 +197,18 @@ static bool usb_match_any_interface(struct usb_device *udev,
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
+int usb_amd_resume_quirk(struct usb_device *udev)
|
|
|
+{
|
|
|
+ struct usb_hcd *hcd;
|
|
|
+
|
|
|
+ hcd = bus_to_hcd(udev->bus);
|
|
|
+ /* The device should be attached directly to root hub */
|
|
|
+ if (udev->level == 1 && hcd->amd_resume_bug == 1)
|
|
|
+ return 1;
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
static u32 __usb_detect_quirks(struct usb_device *udev,
|
|
|
const struct usb_device_id *id)
|
|
|
{
|
|
@@ -206,6 +234,15 @@ static u32 __usb_detect_quirks(struct usb_device *udev,
|
|
|
void usb_detect_quirks(struct usb_device *udev)
|
|
|
{
|
|
|
udev->quirks = __usb_detect_quirks(udev, usb_quirk_list);
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Pixart-based mice would trigger remote wakeup issue on AMD
|
|
|
+ * Yangtze chipset, so set them as RESET_RESUME flag.
|
|
|
+ */
|
|
|
+ if (usb_amd_resume_quirk(udev))
|
|
|
+ udev->quirks |= __usb_detect_quirks(udev,
|
|
|
+ usb_amd_resume_quirk_list);
|
|
|
+
|
|
|
if (udev->quirks)
|
|
|
dev_dbg(&udev->dev, "USB quirks for this device: %x\n",
|
|
|
udev->quirks);
|