Re: [PATCH 8/9 v2] xHCI: test USB2 software LPM

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



* Andiry Xu | 2011-08-17 18:01:42 [+0800]:

>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. The behavior is also different on different
>IP-vendor hosts: one device passes the test on a host but fails to resume
>on another with different IP vendor.

The one IPcore that fails on one device, does it also fail on other
devices or does it pass on other devices? So pattern is something like:

 IP Core     A      B        C
 device A   ok     ok     fail
 device B   fail fail       ok
 device C   fail   ok     fail

i.e. totally random but reproducible mapping between IP core and device?
Do you see any difference with a USB sniffer?

>diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
>index 3a0f695..fce413a 100644
>--- a/drivers/usb/host/xhci.c
>+++ b/drivers/usb/host/xhci.c
>@@ -37,6 +37,10 @@ static int link_quirk;
> module_param(link_quirk, int, S_IRUGO | S_IWUSR);
> MODULE_PARM_DESC(link_quirk, "Don't clear the chain bit on a link TRB");
> 
>+/* BESL to HIRD Encoding array for USB2 LPM */
>+static int xhci_besl_encoding[16] = {125, 150, 200, 300, 400, 500, 1000, 2000,
>+	3000, 4000, 5000, 6000, 7000, 8000, 9000, 10000};
>+
> /* TODO: copied from ehci-hcd.c - can this be refactored? */
> /*
>  * handshake - spin reading hc until handshake completes or fails
>@@ -2957,6 +2961,166 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev)
> 	return 0;
> }
> 
>+/* Calculate HIRD/BESL for USB2 PORTPMSC*/
>+static int xhci_calculate_hird_besl(int u2del, bool use_besl)
>+{
>+	int hird;
>+
>+	if (use_besl) {
>+		for (hird = 0; hird < 16; hird++) {

ARRAY_SIZE_OF

>+			if (xhci_besl_encoding[hird] >= u2del)
>+				break;
>+		}
>+	} else {
>+		if (u2del <= 50)
>+			hird = 0;
>+		else
>+			hird = (u2del - 51) / 75 + 1;
>+
>+		if (hird > 15)
>+			hird = 15;
>+	}
>+
>+	return hird;
>+}
>+
>+static int xhci_usb2_software_lpm_test(struct xhci_hcd *xhci,
>+		  struct usb_device *udev, unsigned long flags)
>+{
>+	struct usb_hcd	*hcd = xhci_to_hcd(xhci);
>+	struct dev_info	*dev_info;
>+	__le32 __iomem	**port_array;
>+	__le32 __iomem	*addr, *pm_addr;
>+	u32		temp, dev_id;
>+	unsigned int	port_num;
>+	int		u2del, hird;
>+	int		ret;
>+
>+	if (hcd->speed == HCD_USB3 || !xhci->sw_lpm_support ||
>+			!udev->lpm_capable)
>+		return -EINVAL;
>+
>+	/* we only support lpm for non-hub device connected to root hub yet */
>+	if (!udev->parent || udev->parent->parent ||
>+			udev->descriptor.bDeviceClass == USB_CLASS_HUB)
>+		return -EINVAL;
>+
>+	/* Look for devices in lpm_failed_devs list */
>+	dev_id = le16_to_cpu(udev->descriptor.idVendor) << 16 |
>+			le16_to_cpu(udev->descriptor.idProduct);
>+	list_for_each_entry(dev_info, &xhci->lpm_failed_devs, list) {
>+		if (dev_info->dev_id == dev_id)
>+			return -EINVAL;
>+	}

I'm still not really convinced about the list for each device. If the
device passes the test you re-test it on the next plug-in. So why not
re-test it in the fail case if your static array is full?
Can you quote some numbers about the time a successfull and a failed
test needs? According to the code would say about 20ms in both cases
(unless it is already in the list).

Sebastian
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux