xHCI: test USB2 software LPM

This patch tests USB2 software LPM for a USB2 LPM-capable device.

When a lpm-capable device is addressed, if the host also supports software
LPM, apply a test by putting the device into L1 state and resume it to see
if the device can do L1 suspend/resume successfully.

If the device fails to enter L1 or resume from L1 state, it may not
function normally and usbcore may disconnect and re-enumerate it. In this
case, store the device's Vid and Pid information, make sure the host will
not test LPM for it twice.

The test result is per device/host. Some devices claim to be lpm-capable,
but fail to enter L1 or resume. So the test is necessary.

The xHCI 1.0 errata has modified the USB2.0 LPM implementation. It redefines
the HIRD field to BESL, and adds another register Port Hardware LPM Control
(PORTHLPMC). However, this should not affect the LPM behavior on xHC which
does not implement 1.0 errata.

USB2.0 LPM errata defines a new bit BESL in the device's USB 2.0 extension
descriptor. If the device reports it uses BESL, driver should use BESL
instead of HIRD for it.

Signed-off-by: Andiry Xu <andiry.xu@amd.com>
Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index 8673f98..b24c4fc 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -272,6 +272,7 @@
  */
 #define PORT_PLS_MASK	(0xf << 5)
 #define XDEV_U0		(0x0 << 5)
+#define XDEV_U2		(0x2 << 5)
 #define XDEV_U3		(0x3 << 5)
 #define XDEV_RESUME	(0xf << 5)
 /* true: port has power (see HCC_PPC) */
@@ -362,7 +363,11 @@
 /* Bits 24:31 for port testing */
 
 /* USB2 Protocol PORTSPMSC */
-#define PORT_RWE	(1 << 0x3)
+#define	PORT_L1S_MASK		7
+#define	PORT_L1S_SUCCESS	1
+#define	PORT_RWE		(1 << 3)
+#define	PORT_HIRD(p)		(((p) & 0xf) << 4)
+#define	PORT_L1DS(p)		(((p) & 0xff) << 8)
 
 /**
  * struct xhci_intr_reg - Interrupt Register Set
@@ -1324,6 +1329,12 @@
 	u64	erst_dequeue;
 };
 
+/* Use for lpm */
+struct dev_info {
+	u32			dev_id;
+	struct	list_head	list;
+};
+
 struct xhci_bus_state {
 	unsigned long		bus_suspended;
 	unsigned long		next_statechange;
@@ -1387,6 +1398,8 @@
 	struct xhci_erst	erst;
 	/* Scratchpad */
 	struct xhci_scratchpad  *scratchpad;
+	/* Store LPM test failed devices' information */
+	struct list_head	lpm_failed_devs;
 
 	/* slot enabling and address device helpers */
 	struct completion	addr_dev;
@@ -1663,6 +1676,7 @@
 		struct usb_host_endpoint **eps, unsigned int num_eps,
 		gfp_t mem_flags);
 int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev);
+int xhci_update_device(struct usb_hcd *hcd, struct usb_device *udev);
 int xhci_update_hub_device(struct usb_hcd *hcd, struct usb_device *hdev,
 			struct usb_tt *tt, gfp_t mem_flags);
 int xhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags);