Message ID | 1380119260-29231-3-git-send-email-gavin.guo@canonical.com |
---|---|
State | New |
Headers | show |
On 09/25/2013 07:27 AM, Gavin Guo wrote: > From: Mathias Nyman <mathias.nyman@linux.intel.com> > > BugLink: https://bugs.launchpad.net/bugs/1229576 > > usb 2.0 devices with link power managment (LPM) can describe their idle link > timeouts either in BESL or HIRD format, so far xHCI has only supported HIRD but > later xHCI errata add BESL support as well > > BESL timeouts need to inform exit latency changes with an evaluate > context command the same way USB 3.0 link PM code does. > The same xhci_change_max_exit_latency() function is used as with USB3 > but code is pulled out from #ifdef CONFIG_PM as USB2.0 BESL LPM > funcionality does not depend on CONFIG_PM. > > Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com> > Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com> > (backported from commit a558ccdcc71c7770c5e80c926a31cfe8a3892a09) > > Signed-off-by: Shawn Wang <shawn.wang@canonical.com> > Signed-off-by: Gavin Guo <gavin.guo@canonical.com> > > Conflicts: > drivers/usb/host/xhci.c > --- > drivers/usb/host/xhci.c | 201 ++++++++++++++++++++++++++++++++--------------- > drivers/usb/host/xhci.h | 21 +++++ > 2 files changed, 158 insertions(+), 64 deletions(-) > > diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c > index c3b0f2d..fb2aaaf 100644 > --- a/drivers/usb/host/xhci.c > +++ b/drivers/usb/host/xhci.c > @@ -3783,6 +3783,56 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev) > return 0; > } > > +/* > + * Issue an Evaluate Context command to change the Maximum Exit Latency in the > + * slot context. If that succeeds, store the new MEL in the xhci_virt_device. > + */ > +static int xhci_change_max_exit_latency(struct xhci_hcd *xhci, > + struct usb_device *udev, u16 max_exit_latency) > +{ > + struct xhci_virt_device *virt_dev; > + struct xhci_command *command; > + struct xhci_input_control_ctx *ctrl_ctx; > + struct xhci_slot_ctx *slot_ctx; > + unsigned long flags; > + int ret; > + > + spin_lock_irqsave(&xhci->lock, flags); > + if (max_exit_latency == xhci->devs[udev->slot_id]->current_mel) { > + spin_unlock_irqrestore(&xhci->lock, flags); > + return 0; > + } > + > + /* Attempt to issue an Evaluate Context command to change the MEL. */ > + virt_dev = xhci->devs[udev->slot_id]; > + command = xhci->lpm_command; > + xhci_slot_copy(xhci, command->in_ctx, virt_dev->out_ctx); > + spin_unlock_irqrestore(&xhci->lock, flags); > + > + ctrl_ctx = xhci_get_input_control_ctx(xhci, command->in_ctx); > + ctrl_ctx->add_flags |= cpu_to_le32(SLOT_FLAG); > + slot_ctx = xhci_get_slot_ctx(xhci, command->in_ctx); > + slot_ctx->dev_info2 &= cpu_to_le32(~((u32) MAX_EXIT)); > + slot_ctx->dev_info2 |= cpu_to_le32(max_exit_latency); > + > + xhci_dbg(xhci, "Set up evaluate context for LPM MEL change.\n"); > + xhci_dbg(xhci, "Slot %u Input Context:\n", udev->slot_id); > + xhci_dbg_ctx(xhci, command->in_ctx, 0); > + > + /* Issue and wait for the evaluate context command. */ > + ret = xhci_configure_endpoint(xhci, udev, command, > + true, true); > + xhci_dbg(xhci, "Slot %u Output Context:\n", udev->slot_id); > + xhci_dbg_ctx(xhci, virt_dev->out_ctx, 0); > + > + if (!ret) { > + spin_lock_irqsave(&xhci->lock, flags); > + virt_dev->current_mel = max_exit_latency; > + spin_unlock_irqrestore(&xhci->lock, flags); > + } > + return ret; > +} > + > #ifdef CONFIG_USB_SUSPEND > > /* BESL to HIRD Encoding array for USB2 LPM */ > @@ -3824,6 +3874,28 @@ static int xhci_calculate_hird_besl(struct xhci_hcd *xhci, > return besl; > } > > +/* Calculate BESLD, L1 timeout and HIRDM for USB2 PORTHLPMC */ > +static int xhci_calculate_usb2_hw_lpm_params(struct usb_device *udev) > +{ > + u32 field; > + int l1; > + int besld = 0; > + int hirdm = 0; > + > + field = le32_to_cpu(udev->bos->ext_cap->bmAttributes); > + > + /* xHCI l1 is set in steps of 256us, xHCI 1.0 section 5.4.11.2 */ > + l1 = XHCI_L1_TIMEOUT / 256; > + > + /* device has preferred BESLD */ > + if (field & USB_BESL_DEEP_VALID) { > + besld = USB_GET_BESL_DEEP(field); > + hirdm = 1; > + } > + > + return PORT_BESLD(besld) | PORT_L1_TIMEOUT(l1) | PORT_HIRDM(hirdm); > +} > + > static int xhci_usb2_software_lpm_test(struct usb_hcd *hcd, > struct usb_device *udev) > { > @@ -3955,11 +4027,12 @@ int xhci_set_usb2_hardware_lpm(struct usb_hcd *hcd, > { > struct xhci_hcd *xhci = hcd_to_xhci(hcd); > __le32 __iomem **port_array; > - __le32 __iomem *pm_addr; > - u32 temp; > + __le32 __iomem *pm_addr, *hlpm_addr; > + u32 pm_val, hlpm_val, field; > unsigned int port_num; > unsigned long flags; > - int hird; > + int hird, exit_latency; > + int ret; > > if (hcd->speed == HCD_USB3 || !xhci->hw_lpm_support || > !udev->lpm_capable) > @@ -3977,23 +4050,73 @@ int xhci_set_usb2_hardware_lpm(struct usb_hcd *hcd, > port_array = xhci->usb2_ports; > port_num = udev->portnum - 1; > pm_addr = port_array[port_num] + PORTPMSC; > - temp = xhci_readl(xhci, pm_addr); > + pm_val = xhci_readl(xhci, pm_addr); > + hlpm_addr = port_array[port_num] + PORTHLPMC; > + field = le32_to_cpu(udev->bos->ext_cap->bmAttributes); > > xhci_dbg(xhci, "%s port %d USB2 hardware LPM\n", > enable ? "enable" : "disable", port_num); > > - hird = xhci_calculate_hird_besl(xhci, udev); > - > if (enable) { > - temp &= ~PORT_HIRD_MASK; > - temp |= PORT_HIRD(hird) | PORT_RWE; > - xhci_writel(xhci, temp, pm_addr); > - temp = xhci_readl(xhci, pm_addr); > - temp |= PORT_HLE; > - xhci_writel(xhci, temp, pm_addr); > + /* Host supports BESL timeout instead of HIRD */ > + if (udev->usb2_hw_lpm_capable) { > + /* if device doesn't have a preferred BESL value use a > + * default one which works with mixed HIRD and BESL > + * systems. See XHCI_DEFAULT_BESL definition in xhci.h > + */ > + if ((field & USB_BESL_SUPPORT) && > + (field & USB_BESL_BASELINE_VALID)) > + hird = USB_GET_BESL_BASELINE(field); > + else > + hird = XHCI_DEFAULT_BESL; > + > + exit_latency = xhci_besl_encoding[hird]; > + spin_unlock_irqrestore(&xhci->lock, flags); > + > + /* USB 3.0 code dedicate one xhci->lpm_command->in_ctx > + * input context for link powermanagement evaluate > + * context commands. It is protected by hcd->bandwidth > + * mutex and is shared by all devices. We need to set > + * the max ext latency in USB 2 BESL LPM as well, so > + * use the same mutex and xhci_change_max_exit_latency() > + */ > + mutex_lock(hcd->bandwidth_mutex); > + ret = xhci_change_max_exit_latency(xhci, udev, > + exit_latency); > + mutex_unlock(hcd->bandwidth_mutex); > + > + if (ret < 0) > + return ret; > + spin_lock_irqsave(&xhci->lock, flags); > + > + hlpm_val = xhci_calculate_usb2_hw_lpm_params(udev); > + xhci_writel(xhci, hlpm_val, hlpm_addr); > + /* flush write */ > + xhci_readl(xhci, hlpm_addr); > + } else { > + hird = xhci_calculate_hird_besl(xhci, udev); > + } > + > + pm_val &= ~PORT_HIRD_MASK; > + pm_val |= PORT_HIRD(hird) | PORT_RWE; > + xhci_writel(xhci, pm_val, pm_addr); > + pm_val = xhci_readl(xhci, pm_addr); > + pm_val |= PORT_HLE; > + xhci_writel(xhci, pm_val, pm_addr); > + /* flush write */ > + xhci_readl(xhci, pm_addr); > } else { > - temp &= ~(PORT_HLE | PORT_RWE | PORT_HIRD_MASK); > - xhci_writel(xhci, temp, pm_addr); > + pm_val &= ~(PORT_HLE | PORT_RWE | PORT_HIRD_MASK); > + xhci_writel(xhci, pm_val, pm_addr); > + /* flush write */ > + xhci_readl(xhci, pm_addr); > + if (udev->usb2_hw_lpm_capable) { > + spin_unlock_irqrestore(&xhci->lock, flags); > + mutex_lock(hcd->bandwidth_mutex); > + xhci_change_max_exit_latency(xhci, udev, 0); > + mutex_unlock(hcd->bandwidth_mutex); > + return 0; > + } > } > > spin_unlock_irqrestore(&xhci->lock, flags); > @@ -4340,56 +4463,6 @@ static u16 xhci_calculate_lpm_timeout(struct usb_hcd *hcd, > return timeout; > } > > -/* > - * Issue an Evaluate Context command to change the Maximum Exit Latency in the > - * slot context. If that succeeds, store the new MEL in the xhci_virt_device. > - */ > -static int xhci_change_max_exit_latency(struct xhci_hcd *xhci, > - struct usb_device *udev, u16 max_exit_latency) > -{ > - struct xhci_virt_device *virt_dev; > - struct xhci_command *command; > - struct xhci_input_control_ctx *ctrl_ctx; > - struct xhci_slot_ctx *slot_ctx; > - unsigned long flags; > - int ret; > - > - spin_lock_irqsave(&xhci->lock, flags); > - if (max_exit_latency == xhci->devs[udev->slot_id]->current_mel) { > - spin_unlock_irqrestore(&xhci->lock, flags); > - return 0; > - } > - > - /* Attempt to issue an Evaluate Context command to change the MEL. */ > - virt_dev = xhci->devs[udev->slot_id]; > - command = xhci->lpm_command; > - xhci_slot_copy(xhci, command->in_ctx, virt_dev->out_ctx); > - spin_unlock_irqrestore(&xhci->lock, flags); > - > - ctrl_ctx = xhci_get_input_control_ctx(xhci, command->in_ctx); > - ctrl_ctx->add_flags |= cpu_to_le32(SLOT_FLAG); > - slot_ctx = xhci_get_slot_ctx(xhci, command->in_ctx); > - slot_ctx->dev_info2 &= cpu_to_le32(~((u32) MAX_EXIT)); > - slot_ctx->dev_info2 |= cpu_to_le32(max_exit_latency); > - > - xhci_dbg(xhci, "Set up evaluate context for LPM MEL change.\n"); > - xhci_dbg(xhci, "Slot %u Input Context:\n", udev->slot_id); > - xhci_dbg_ctx(xhci, command->in_ctx, 0); > - > - /* Issue and wait for the evaluate context command. */ > - ret = xhci_configure_endpoint(xhci, udev, command, > - true, true); > - xhci_dbg(xhci, "Slot %u Output Context:\n", udev->slot_id); > - xhci_dbg_ctx(xhci, virt_dev->out_ctx, 0); > - > - if (!ret) { > - spin_lock_irqsave(&xhci->lock, flags); > - virt_dev->current_mel = max_exit_latency; > - spin_unlock_irqrestore(&xhci->lock, flags); > - } > - return ret; > -} > - > static int calculate_max_exit_latency(struct usb_device *udev, > enum usb3_link_state state_changed, > u16 hub_encoded_timeout) > diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h > index 79c324a..5897c13 100644 > --- a/drivers/usb/host/xhci.h > +++ b/drivers/usb/host/xhci.h > @@ -386,6 +386,27 @@ struct xhci_op_regs { > #define PORT_L1DS(p) (((p) & 0xff) << 8) > #define PORT_HLE (1 << 16) > > + > +/* USB2 Protocol PORTHLPMC */ > +#define PORT_HIRDM(p)((p) & 3) > +#define PORT_L1_TIMEOUT(p)(((p) & 0xff) << 2) > +#define PORT_BESLD(p)(((p) & 0xf) << 10) > + > +/* use 512 microseconds as USB2 LPM L1 default timeout. */ > +#define XHCI_L1_TIMEOUT 512 > + > +/* Set default HIRD/BESL value to 4 (350/400us) for USB2 L1 LPM resume latency. > + * Safe to use with mixed HIRD and BESL systems (host and device) and is used > + * by other operating systems. > + * > + * XHCI 1.0 errata 8/14/12 Table 13 notes: > + * "Software should choose xHC BESL/BESLD field values that do not violate a > + * device's resume latency requirements, > + * e.g. not program values > '4' if BLC = '1' and a HIRD device is attached, > + * or not program values < '4' if BLC = '0' and a BESL device is attached. > + */ > +#define XHCI_DEFAULT_BESL 4 > + > /** > * struct xhci_intr_reg - Interrupt Register Set > * @irq_pending: IMAN - Interrupt Management Register. Used to enable > Hmm, might you also need dcf06a036848b4e8e6c8220f2e00b9adf6f84918 ?
Hi Tim, The original commit a558ccdcc71c7770c5e80c926a31cfe8a3892a09 add usb2_hw_lpm_besl_capable in struct usb3_lpm_parameters. (include/linux/usb.h) However, the XHCI_HLC and XHCI_BLC are the same. We skip the below change, use usb2_hw_lpm_capable to instead of usb2_hw_lpm_besl_capable. If add dcf06a036848b4e8e6c8220f2e00b9adf6f84918, should we change the struct usb3_lpm_parameters? Some realtek webcam modules need the backport to fix preview issues. a558ccdcc71c7770c5e80c926a31cfe8a3892a09 +++ b/drivers/usb/host/xhci-ext-caps.h @@ -71,6 +71,7 @@ /* USB 2.0 xHCI 1.0 hardware LMP capability - section 7.2.2.1.3.2 */ #define XHCI_HLC (1 << 19) +#define XHCI_BLC (1 << 19) @@ -4068,6 +4191,9 @@ int xhci_update_device(struct usb_hcd *hcd, struct usb_device *udev) if (xhci->hw_lpm_support == 1 && xhci_check_usb2_port_capability(xhci, portnum, XHCI_HLC)) { udev->usb2_hw_lpm_capable = 1; + if (xhci_check_usb2_port_capability(xhci, portnum, + XHCI_BLC)) + udev->usb2_hw_lpm_besl_capable = 1; dcf06a036848b4e8e6c8220f2e00b9adf6f84918 /* USB 2.0 xHCI 1.0 hardware LMP capability - section 7.2.2.1.3.2 */ #define XHCI_HLC (1 << 19) -#define XHCI_BLC (1 << 19) +#define XHCI_BLC (1 << 20) Regards, Shawn On Wed, Sep 25, 2013 at 10:52 PM, Tim Gardner <tim.gardner@canonical.com>wrote: > On 09/25/2013 07:27 AM, Gavin Guo wrote: > > From: Mathias Nyman <mathias.nyman@linux.intel.com> > > > > BugLink: https://bugs.launchpad.net/bugs/1229576 > > > > usb 2.0 devices with link power managment (LPM) can describe their idle > link > > timeouts either in BESL or HIRD format, so far xHCI has only supported > HIRD but > > later xHCI errata add BESL support as well > > > > BESL timeouts need to inform exit latency changes with an evaluate > > context command the same way USB 3.0 link PM code does. > > The same xhci_change_max_exit_latency() function is used as with USB3 > > but code is pulled out from #ifdef CONFIG_PM as USB2.0 BESL LPM > > funcionality does not depend on CONFIG_PM. > > > > Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com> > > Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com> > > (backported from commit a558ccdcc71c7770c5e80c926a31cfe8a3892a09) > > > > Signed-off-by: Shawn Wang <shawn.wang@canonical.com> > > Signed-off-by: Gavin Guo <gavin.guo@canonical.com> > > > > Conflicts: > > drivers/usb/host/xhci.c > > --- > > drivers/usb/host/xhci.c | 201 > ++++++++++++++++++++++++++++++++--------------- > > drivers/usb/host/xhci.h | 21 +++++ > > 2 files changed, 158 insertions(+), 64 deletions(-) > > > > diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c > > index c3b0f2d..fb2aaaf 100644 > > --- a/drivers/usb/host/xhci.c > > +++ b/drivers/usb/host/xhci.c > > @@ -3783,6 +3783,56 @@ int xhci_address_device(struct usb_hcd *hcd, > struct usb_device *udev) > > return 0; > > } > > > > +/* > > + * Issue an Evaluate Context command to change the Maximum Exit Latency > in the > > + * slot context. If that succeeds, store the new MEL in the > xhci_virt_device. > > + */ > > +static int xhci_change_max_exit_latency(struct xhci_hcd *xhci, > > + struct usb_device *udev, u16 max_exit_latency) > > +{ > > + struct xhci_virt_device *virt_dev; > > + struct xhci_command *command; > > + struct xhci_input_control_ctx *ctrl_ctx; > > + struct xhci_slot_ctx *slot_ctx; > > + unsigned long flags; > > + int ret; > > + > > + spin_lock_irqsave(&xhci->lock, flags); > > + if (max_exit_latency == xhci->devs[udev->slot_id]->current_mel) { > > + spin_unlock_irqrestore(&xhci->lock, flags); > > + return 0; > > + } > > + > > + /* Attempt to issue an Evaluate Context command to change the MEL. > */ > > + virt_dev = xhci->devs[udev->slot_id]; > > + command = xhci->lpm_command; > > + xhci_slot_copy(xhci, command->in_ctx, virt_dev->out_ctx); > > + spin_unlock_irqrestore(&xhci->lock, flags); > > + > > + ctrl_ctx = xhci_get_input_control_ctx(xhci, command->in_ctx); > > + ctrl_ctx->add_flags |= cpu_to_le32(SLOT_FLAG); > > + slot_ctx = xhci_get_slot_ctx(xhci, command->in_ctx); > > + slot_ctx->dev_info2 &= cpu_to_le32(~((u32) MAX_EXIT)); > > + slot_ctx->dev_info2 |= cpu_to_le32(max_exit_latency); > > + > > + xhci_dbg(xhci, "Set up evaluate context for LPM MEL change.\n"); > > + xhci_dbg(xhci, "Slot %u Input Context:\n", udev->slot_id); > > + xhci_dbg_ctx(xhci, command->in_ctx, 0); > > + > > + /* Issue and wait for the evaluate context command. */ > > + ret = xhci_configure_endpoint(xhci, udev, command, > > + true, true); > > + xhci_dbg(xhci, "Slot %u Output Context:\n", udev->slot_id); > > + xhci_dbg_ctx(xhci, virt_dev->out_ctx, 0); > > + > > + if (!ret) { > > + spin_lock_irqsave(&xhci->lock, flags); > > + virt_dev->current_mel = max_exit_latency; > > + spin_unlock_irqrestore(&xhci->lock, flags); > > + } > > + return ret; > > +} > > + > > #ifdef CONFIG_USB_SUSPEND > > > > /* BESL to HIRD Encoding array for USB2 LPM */ > > @@ -3824,6 +3874,28 @@ static int xhci_calculate_hird_besl(struct > xhci_hcd *xhci, > > return besl; > > } > > > > +/* Calculate BESLD, L1 timeout and HIRDM for USB2 PORTHLPMC */ > > +static int xhci_calculate_usb2_hw_lpm_params(struct usb_device *udev) > > +{ > > + u32 field; > > + int l1; > > + int besld = 0; > > + int hirdm = 0; > > + > > + field = le32_to_cpu(udev->bos->ext_cap->bmAttributes); > > + > > + /* xHCI l1 is set in steps of 256us, xHCI 1.0 section 5.4.11.2 */ > > + l1 = XHCI_L1_TIMEOUT / 256; > > + > > + /* device has preferred BESLD */ > > + if (field & USB_BESL_DEEP_VALID) { > > + besld = USB_GET_BESL_DEEP(field); > > + hirdm = 1; > > + } > > + > > + return PORT_BESLD(besld) | PORT_L1_TIMEOUT(l1) | PORT_HIRDM(hirdm); > > +} > > + > > static int xhci_usb2_software_lpm_test(struct usb_hcd *hcd, > > struct usb_device *udev) > > { > > @@ -3955,11 +4027,12 @@ int xhci_set_usb2_hardware_lpm(struct usb_hcd > *hcd, > > { > > struct xhci_hcd *xhci = hcd_to_xhci(hcd); > > __le32 __iomem **port_array; > > - __le32 __iomem *pm_addr; > > - u32 temp; > > + __le32 __iomem *pm_addr, *hlpm_addr; > > + u32 pm_val, hlpm_val, field; > > unsigned int port_num; > > unsigned long flags; > > - int hird; > > + int hird, exit_latency; > > + int ret; > > > > if (hcd->speed == HCD_USB3 || !xhci->hw_lpm_support || > > !udev->lpm_capable) > > @@ -3977,23 +4050,73 @@ int xhci_set_usb2_hardware_lpm(struct usb_hcd > *hcd, > > port_array = xhci->usb2_ports; > > port_num = udev->portnum - 1; > > pm_addr = port_array[port_num] + PORTPMSC; > > - temp = xhci_readl(xhci, pm_addr); > > + pm_val = xhci_readl(xhci, pm_addr); > > + hlpm_addr = port_array[port_num] + PORTHLPMC; > > + field = le32_to_cpu(udev->bos->ext_cap->bmAttributes); > > > > xhci_dbg(xhci, "%s port %d USB2 hardware LPM\n", > > enable ? "enable" : "disable", port_num); > > > > - hird = xhci_calculate_hird_besl(xhci, udev); > > - > > if (enable) { > > - temp &= ~PORT_HIRD_MASK; > > - temp |= PORT_HIRD(hird) | PORT_RWE; > > - xhci_writel(xhci, temp, pm_addr); > > - temp = xhci_readl(xhci, pm_addr); > > - temp |= PORT_HLE; > > - xhci_writel(xhci, temp, pm_addr); > > + /* Host supports BESL timeout instead of HIRD */ > > + if (udev->usb2_hw_lpm_capable) { > > + /* if device doesn't have a preferred BESL value > use a > > + * default one which works with mixed HIRD and BESL > > + * systems. See XHCI_DEFAULT_BESL definition in > xhci.h > > + */ > > + if ((field & USB_BESL_SUPPORT) && > > + (field & USB_BESL_BASELINE_VALID)) > > + hird = USB_GET_BESL_BASELINE(field); > > + else > > + hird = XHCI_DEFAULT_BESL; > > + > > + exit_latency = xhci_besl_encoding[hird]; > > + spin_unlock_irqrestore(&xhci->lock, flags); > > + > > + /* USB 3.0 code dedicate one > xhci->lpm_command->in_ctx > > + * input context for link powermanagement evaluate > > + * context commands. It is protected by > hcd->bandwidth > > + * mutex and is shared by all devices. We need to > set > > + * the max ext latency in USB 2 BESL LPM as well, > so > > + * use the same mutex and > xhci_change_max_exit_latency() > > + */ > > + mutex_lock(hcd->bandwidth_mutex); > > + ret = xhci_change_max_exit_latency(xhci, udev, > > + exit_latency); > > + mutex_unlock(hcd->bandwidth_mutex); > > + > > + if (ret < 0) > > + return ret; > > + spin_lock_irqsave(&xhci->lock, flags); > > + > > + hlpm_val = xhci_calculate_usb2_hw_lpm_params(udev); > > + xhci_writel(xhci, hlpm_val, hlpm_addr); > > + /* flush write */ > > + xhci_readl(xhci, hlpm_addr); > > + } else { > > + hird = xhci_calculate_hird_besl(xhci, udev); > > + } > > + > > + pm_val &= ~PORT_HIRD_MASK; > > + pm_val |= PORT_HIRD(hird) | PORT_RWE; > > + xhci_writel(xhci, pm_val, pm_addr); > > + pm_val = xhci_readl(xhci, pm_addr); > > + pm_val |= PORT_HLE; > > + xhci_writel(xhci, pm_val, pm_addr); > > + /* flush write */ > > + xhci_readl(xhci, pm_addr); > > } else { > > - temp &= ~(PORT_HLE | PORT_RWE | PORT_HIRD_MASK); > > - xhci_writel(xhci, temp, pm_addr); > > + pm_val &= ~(PORT_HLE | PORT_RWE | PORT_HIRD_MASK); > > + xhci_writel(xhci, pm_val, pm_addr); > > + /* flush write */ > > + xhci_readl(xhci, pm_addr); > > + if (udev->usb2_hw_lpm_capable) { > > + spin_unlock_irqrestore(&xhci->lock, flags); > > + mutex_lock(hcd->bandwidth_mutex); > > + xhci_change_max_exit_latency(xhci, udev, 0); > > + mutex_unlock(hcd->bandwidth_mutex); > > + return 0; > > + } > > } > > > > spin_unlock_irqrestore(&xhci->lock, flags); > > @@ -4340,56 +4463,6 @@ static u16 xhci_calculate_lpm_timeout(struct > usb_hcd *hcd, > > return timeout; > > } > > > > -/* > > - * Issue an Evaluate Context command to change the Maximum Exit Latency > in the > > - * slot context. If that succeeds, store the new MEL in the > xhci_virt_device. > > - */ > > -static int xhci_change_max_exit_latency(struct xhci_hcd *xhci, > > - struct usb_device *udev, u16 max_exit_latency) > > -{ > > - struct xhci_virt_device *virt_dev; > > - struct xhci_command *command; > > - struct xhci_input_control_ctx *ctrl_ctx; > > - struct xhci_slot_ctx *slot_ctx; > > - unsigned long flags; > > - int ret; > > - > > - spin_lock_irqsave(&xhci->lock, flags); > > - if (max_exit_latency == xhci->devs[udev->slot_id]->current_mel) { > > - spin_unlock_irqrestore(&xhci->lock, flags); > > - return 0; > > - } > > - > > - /* Attempt to issue an Evaluate Context command to change the MEL. > */ > > - virt_dev = xhci->devs[udev->slot_id]; > > - command = xhci->lpm_command; > > - xhci_slot_copy(xhci, command->in_ctx, virt_dev->out_ctx); > > - spin_unlock_irqrestore(&xhci->lock, flags); > > - > > - ctrl_ctx = xhci_get_input_control_ctx(xhci, command->in_ctx); > > - ctrl_ctx->add_flags |= cpu_to_le32(SLOT_FLAG); > > - slot_ctx = xhci_get_slot_ctx(xhci, command->in_ctx); > > - slot_ctx->dev_info2 &= cpu_to_le32(~((u32) MAX_EXIT)); > > - slot_ctx->dev_info2 |= cpu_to_le32(max_exit_latency); > > - > > - xhci_dbg(xhci, "Set up evaluate context for LPM MEL change.\n"); > > - xhci_dbg(xhci, "Slot %u Input Context:\n", udev->slot_id); > > - xhci_dbg_ctx(xhci, command->in_ctx, 0); > > - > > - /* Issue and wait for the evaluate context command. */ > > - ret = xhci_configure_endpoint(xhci, udev, command, > > - true, true); > > - xhci_dbg(xhci, "Slot %u Output Context:\n", udev->slot_id); > > - xhci_dbg_ctx(xhci, virt_dev->out_ctx, 0); > > - > > - if (!ret) { > > - spin_lock_irqsave(&xhci->lock, flags); > > - virt_dev->current_mel = max_exit_latency; > > - spin_unlock_irqrestore(&xhci->lock, flags); > > - } > > - return ret; > > -} > > - > > static int calculate_max_exit_latency(struct usb_device *udev, > > enum usb3_link_state state_changed, > > u16 hub_encoded_timeout) > > diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h > > index 79c324a..5897c13 100644 > > --- a/drivers/usb/host/xhci.h > > +++ b/drivers/usb/host/xhci.h > > @@ -386,6 +386,27 @@ struct xhci_op_regs { > > #define PORT_L1DS(p) (((p) & 0xff) << 8) > > #define PORT_HLE (1 << 16) > > > > + > > +/* USB2 Protocol PORTHLPMC */ > > +#define PORT_HIRDM(p)((p) & 3) > > +#define PORT_L1_TIMEOUT(p)(((p) & 0xff) << 2) > > +#define PORT_BESLD(p)(((p) & 0xf) << 10) > > + > > +/* use 512 microseconds as USB2 LPM L1 default timeout. */ > > +#define XHCI_L1_TIMEOUT 512 > > + > > +/* Set default HIRD/BESL value to 4 (350/400us) for USB2 L1 LPM resume > latency. > > + * Safe to use with mixed HIRD and BESL systems (host and device) and > is used > > + * by other operating systems. > > + * > > + * XHCI 1.0 errata 8/14/12 Table 13 notes: > > + * "Software should choose xHC BESL/BESLD field values that do not > violate a > > + * device's resume latency requirements, > > + * e.g. not program values > '4' if BLC = '1' and a HIRD device is > attached, > > + * or not program values < '4' if BLC = '0' and a BESL device is > attached. > > + */ > > +#define XHCI_DEFAULT_BESL 4 > > + > > /** > > * struct xhci_intr_reg - Interrupt Register Set > > * @irq_pending: IMAN - Interrupt Management Register. Used to > enable > > > > Hmm, might you also need dcf06a036848b4e8e6c8220f2e00b9adf6f84918 ? > > -- > Tim Gardner tim.gardner@canonical.com > > -- > kernel-team mailing list > kernel-team@lists.ubuntu.com > https://lists.ubuntu.com/mailman/listinfo/kernel-team >
On 09/26/2013 02:32 AM, Shawn Wang wrote: > Hi Tim, > The original commit a558ccdcc71c7770c5e80c926a31cfe8a3892a09 > add usb2_hw_lpm_besl_capable in struct > usb3_lpm_parameters. (include/linux/usb.h) > However, the XHCI_HLC and XHCI_BLC are the same. > We skip the below change, use usb2_hw_lpm_capable to instead of > usb2_hw_lpm_besl_capable. > If add dcf06a036848b4e8e6c8220f2e00b9adf6f84918, should we change the > struct usb3_lpm_parameters? > > Some realtek webcam modules need the backport to fix preview issues. > > a558ccdcc71c7770c5e80c926a31cfe8a3892a09 > > +++ b/drivers/usb/host/xhci-ext-caps.h > @@ -71,6 +71,7 @@ > > /* USB 2.0 xHCI 1.0 hardware LMP capability - section 7.2.2.1.3.2 */ > #define XHCI_HLC (1 << 19) > +#define XHCI_BLC (1 << 19) > > @@ -4068,6 +4191,9 @@ int xhci_update_device(struct usb_hcd *hcd, > struct usb_device *udev) > if (xhci->hw_lpm_support == 1 && > xhci_check_usb2_port_capability(xhci, portnum, XHCI_HLC)) { > udev->usb2_hw_lpm_capable = 1; > + if (xhci_check_usb2_port_capability(xhci, portnum, > + XHCI_BLC)) > + udev->usb2_hw_lpm_besl_capable = 1; > > > dcf06a036848b4e8e6c8220f2e00b9adf6f84918 > > /* USB 2.0 xHCI 1.0 hardware LMP capability - section 7.2.2.1.3.2 */ > #define XHCI_HLC (1 << 19) > -#define XHCI_BLC (1 << 19) > +#define XHCI_BLC (1 << 20) > > Regards, > Shawn > Ah, never mind. The back port of a558ccdcc71c7770c5e80c926a31cfe8a3892a09 looks OK. However, there is no mention in the bug report of any kind of regression tests having been performed. This looks like a code path that will affect a lot of devices. rtg
Hi Tim, I did some regression tests and posted it on https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1229576. Webcam test: preview with resolution change (cheese/guvcview) Take photos. S3 stress 30 times than preview and take photos. Other usb device test: USB mouse (8564:1000) usb disk (0781:5571 SanDisk Corp.) usb bt (8087:07dc) Regards, Shawn On Thu, Sep 26, 2013 at 11:07 PM, Tim Gardner <tim.gardner@canonical.com>wrote: > On 09/26/2013 02:32 AM, Shawn Wang wrote: > > Hi Tim, > > The original commit a558ccdcc71c7770c5e80c926a31cfe8a3892a09 > > add usb2_hw_lpm_besl_capable in struct > > usb3_lpm_parameters. (include/linux/usb.h) > > However, the XHCI_HLC and XHCI_BLC are the same. > > We skip the below change, use usb2_hw_lpm_capable to instead of > > usb2_hw_lpm_besl_capable. > > If add dcf06a036848b4e8e6c8220f2e00b9adf6f84918, should we change the > > struct usb3_lpm_parameters? > > > > Some realtek webcam modules need the backport to fix preview issues. > > > > a558ccdcc71c7770c5e80c926a31cfe8a3892a09 > > > > +++ b/drivers/usb/host/xhci-ext-caps.h > > @@ -71,6 +71,7 @@ > > > > /* USB 2.0 xHCI 1.0 hardware LMP capability - section 7.2.2.1.3.2 */ > > #define XHCI_HLC (1 << 19) > > +#define XHCI_BLC (1 << 19) > > > > @@ -4068,6 +4191,9 @@ int xhci_update_device(struct usb_hcd *hcd, > > struct usb_device *udev) > > if (xhci->hw_lpm_support == 1 && > > xhci_check_usb2_port_capability(xhci, portnum, XHCI_HLC)) { > > udev->usb2_hw_lpm_capable = 1; > > + if (xhci_check_usb2_port_capability(xhci, portnum, > > + XHCI_BLC)) > > + udev->usb2_hw_lpm_besl_capable = 1; > > > > > > dcf06a036848b4e8e6c8220f2e00b9adf6f84918 > > > > /* USB 2.0 xHCI 1.0 hardware LMP capability - section 7.2.2.1.3.2 */ > > #define XHCI_HLC (1 << 19) > > -#define XHCI_BLC (1 << 19) > > +#define XHCI_BLC (1 << 20) > > > > Regards, > > Shawn > > > > Ah, never mind. The back port of > a558ccdcc71c7770c5e80c926a31cfe8a3892a09 looks OK. However, there is no > mention in the bug report of any kind of regression tests having been > performed. This looks like a code path that will affect a lot of devices. > > rtg > -- > Tim Gardner tim.gardner@canonical.com >
On 09/30/2013 02:14 AM, Shawn Wang wrote: > Hi Tim, > I did some regression tests and posted it > on https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1229576. > > Webcam test: > preview with resolution change (cheese/guvcview) > Take photos. > S3 stress 30 times than preview and take photos. > > Other usb device test: > USB mouse (8564:1000) > usb disk (0781:5571 SanDisk Corp.) > usb bt (8087:07dc) > > Regards, > Shawn > It is not clear from your test results that you have regression tested other platforms. I'm reasonably sure you would have noticed regressions with other USB devices on the _same_ platform as the camera under test. rtg
On 10/08/2013 11:20 PM, Shawn Wang wrote: > Hi Tim, > > Sorry about the late reply. > I tested the other three platforms for the BESL patch. > Is the coverage good enough? > > https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1229576/comments/7 > Test 3 other usb chipsets, all of the usb functions are good. > > ==> amz-pst-c2/lspci <== > 00:00.0 Host bridge: Intel Corporation Haswell DRAM Controller (rev 06) > ==> me5-e3-i1/lspci <== > 00:00.0 Host bridge: Intel Corporation Ivy Bridge DRAM Controller (rev 08) > ==> osaka8/lspci <== > 00:00.0 Host bridge: Advanced Micro Devices [AMD] Family 14h Processor > Root Complex > > Regards, > Shawn > > > On Wed, Oct 9, 2013 at 12:50 PM, Anthony Wong > <anthony.wong@canonical.com <mailto:anthony.wong@canonical.com>> wrote: > > Hi Shawn -- I think we have a good coverage here and you can ping > Tim again to let him know. > > Thanks, > Anthony > > -- > Anthony Wong <anthony.wong@canonical.com > <mailto:anthony.wong@canonical.com>> > Project Manager, Hardware Enablement > Mobile: +86 1860-8989-064 <tel:%2B86%201860-8989-064> > Canonical Ltd. www.canonical.com <http://www.canonical.com/> > > > On 9 October 2013 10:55, Shawn Wang <shawn.wang@canonical.com > <mailto:shawn.wang@canonical.com>> wrote: > > Hi Anthony, > I'm not sure about the regression test. > Could you help about it? > > I test the other three platforms. > > https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1229576/comments/7 > Test 3 other usb chipsets, all of the usb functions are good. > > ==> amz-pst-c2/lspci <== > 00:00.0 Host bridge: Intel Corporation Haswell DRAM Controller > (rev 06) > ==> me5-e3-i1/lspci <== > 00:00.0 Host bridge: Intel Corporation Ivy Bridge DRAM > Controller (rev 08) > ==> osaka8/lspci <== > 00:00.0 Host bridge: Advanced Micro Devices [AMD] Family 14h > Processor Root Complex > > Regards, > Shawn > ---------- Forwarded message ---------- > From: *Tim Gardner* <tim.gardner@canonical.com > <mailto:tim.gardner@canonical.com>> > Date: Mon, Sep 30, 2013 at 10:25 PM > Subject: Re: [Quantal][SRU][PATCH 2/2] usb: xhci: add USB2 Link > power management BESL support > To: Shawn Wang <shawn.wang@canonical.com > <mailto:shawn.wang@canonical.com>> > Cc: Gavin Guo <gavin.guo@canonical.com > <mailto:gavin.guo@canonical.com>>, kernel-team@lists.ubuntu.com > <mailto:kernel-team@lists.ubuntu.com>, Anthony Wong > <anthony.wong@canonical.com <mailto:anthony.wong@canonical.com>> > > > On 09/30/2013 02:14 AM, Shawn Wang wrote: > > Hi Tim, > > I did some regression tests and posted it > > on https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1229576. > > > > Webcam test: > > preview with resolution change (cheese/guvcview) > > Take photos. > > S3 stress 30 times than preview and take photos. > > > > Other usb device test: > > USB mouse (8564:1000) > > usb disk (0781:5571 SanDisk Corp.) > > usb bt (8087:07dc) > > > > Regards, > > Shawn > > > > It is not clear from your test results that you have regression > tested > other platforms. I'm reasonably sure you would have noticed > regressions > with other USB devices on the _same_ platform as the camera > under test. > > rtg > -- > Tim Gardner tim.gardner@canonical.com > <mailto:tim.gardner@canonical.com> > > >
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index c3b0f2d..fb2aaaf 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -3783,6 +3783,56 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev) return 0; } +/* + * Issue an Evaluate Context command to change the Maximum Exit Latency in the + * slot context. If that succeeds, store the new MEL in the xhci_virt_device. + */ +static int xhci_change_max_exit_latency(struct xhci_hcd *xhci, + struct usb_device *udev, u16 max_exit_latency) +{ + struct xhci_virt_device *virt_dev; + struct xhci_command *command; + struct xhci_input_control_ctx *ctrl_ctx; + struct xhci_slot_ctx *slot_ctx; + unsigned long flags; + int ret; + + spin_lock_irqsave(&xhci->lock, flags); + if (max_exit_latency == xhci->devs[udev->slot_id]->current_mel) { + spin_unlock_irqrestore(&xhci->lock, flags); + return 0; + } + + /* Attempt to issue an Evaluate Context command to change the MEL. */ + virt_dev = xhci->devs[udev->slot_id]; + command = xhci->lpm_command; + xhci_slot_copy(xhci, command->in_ctx, virt_dev->out_ctx); + spin_unlock_irqrestore(&xhci->lock, flags); + + ctrl_ctx = xhci_get_input_control_ctx(xhci, command->in_ctx); + ctrl_ctx->add_flags |= cpu_to_le32(SLOT_FLAG); + slot_ctx = xhci_get_slot_ctx(xhci, command->in_ctx); + slot_ctx->dev_info2 &= cpu_to_le32(~((u32) MAX_EXIT)); + slot_ctx->dev_info2 |= cpu_to_le32(max_exit_latency); + + xhci_dbg(xhci, "Set up evaluate context for LPM MEL change.\n"); + xhci_dbg(xhci, "Slot %u Input Context:\n", udev->slot_id); + xhci_dbg_ctx(xhci, command->in_ctx, 0); + + /* Issue and wait for the evaluate context command. */ + ret = xhci_configure_endpoint(xhci, udev, command, + true, true); + xhci_dbg(xhci, "Slot %u Output Context:\n", udev->slot_id); + xhci_dbg_ctx(xhci, virt_dev->out_ctx, 0); + + if (!ret) { + spin_lock_irqsave(&xhci->lock, flags); + virt_dev->current_mel = max_exit_latency; + spin_unlock_irqrestore(&xhci->lock, flags); + } + return ret; +} + #ifdef CONFIG_USB_SUSPEND /* BESL to HIRD Encoding array for USB2 LPM */ @@ -3824,6 +3874,28 @@ static int xhci_calculate_hird_besl(struct xhci_hcd *xhci, return besl; } +/* Calculate BESLD, L1 timeout and HIRDM for USB2 PORTHLPMC */ +static int xhci_calculate_usb2_hw_lpm_params(struct usb_device *udev) +{ + u32 field; + int l1; + int besld = 0; + int hirdm = 0; + + field = le32_to_cpu(udev->bos->ext_cap->bmAttributes); + + /* xHCI l1 is set in steps of 256us, xHCI 1.0 section 5.4.11.2 */ + l1 = XHCI_L1_TIMEOUT / 256; + + /* device has preferred BESLD */ + if (field & USB_BESL_DEEP_VALID) { + besld = USB_GET_BESL_DEEP(field); + hirdm = 1; + } + + return PORT_BESLD(besld) | PORT_L1_TIMEOUT(l1) | PORT_HIRDM(hirdm); +} + static int xhci_usb2_software_lpm_test(struct usb_hcd *hcd, struct usb_device *udev) { @@ -3955,11 +4027,12 @@ int xhci_set_usb2_hardware_lpm(struct usb_hcd *hcd, { struct xhci_hcd *xhci = hcd_to_xhci(hcd); __le32 __iomem **port_array; - __le32 __iomem *pm_addr; - u32 temp; + __le32 __iomem *pm_addr, *hlpm_addr; + u32 pm_val, hlpm_val, field; unsigned int port_num; unsigned long flags; - int hird; + int hird, exit_latency; + int ret; if (hcd->speed == HCD_USB3 || !xhci->hw_lpm_support || !udev->lpm_capable) @@ -3977,23 +4050,73 @@ int xhci_set_usb2_hardware_lpm(struct usb_hcd *hcd, port_array = xhci->usb2_ports; port_num = udev->portnum - 1; pm_addr = port_array[port_num] + PORTPMSC; - temp = xhci_readl(xhci, pm_addr); + pm_val = xhci_readl(xhci, pm_addr); + hlpm_addr = port_array[port_num] + PORTHLPMC; + field = le32_to_cpu(udev->bos->ext_cap->bmAttributes); xhci_dbg(xhci, "%s port %d USB2 hardware LPM\n", enable ? "enable" : "disable", port_num); - hird = xhci_calculate_hird_besl(xhci, udev); - if (enable) { - temp &= ~PORT_HIRD_MASK; - temp |= PORT_HIRD(hird) | PORT_RWE; - xhci_writel(xhci, temp, pm_addr); - temp = xhci_readl(xhci, pm_addr); - temp |= PORT_HLE; - xhci_writel(xhci, temp, pm_addr); + /* Host supports BESL timeout instead of HIRD */ + if (udev->usb2_hw_lpm_capable) { + /* if device doesn't have a preferred BESL value use a + * default one which works with mixed HIRD and BESL + * systems. See XHCI_DEFAULT_BESL definition in xhci.h + */ + if ((field & USB_BESL_SUPPORT) && + (field & USB_BESL_BASELINE_VALID)) + hird = USB_GET_BESL_BASELINE(field); + else + hird = XHCI_DEFAULT_BESL; + + exit_latency = xhci_besl_encoding[hird]; + spin_unlock_irqrestore(&xhci->lock, flags); + + /* USB 3.0 code dedicate one xhci->lpm_command->in_ctx + * input context for link powermanagement evaluate + * context commands. It is protected by hcd->bandwidth + * mutex and is shared by all devices. We need to set + * the max ext latency in USB 2 BESL LPM as well, so + * use the same mutex and xhci_change_max_exit_latency() + */ + mutex_lock(hcd->bandwidth_mutex); + ret = xhci_change_max_exit_latency(xhci, udev, + exit_latency); + mutex_unlock(hcd->bandwidth_mutex); + + if (ret < 0) + return ret; + spin_lock_irqsave(&xhci->lock, flags); + + hlpm_val = xhci_calculate_usb2_hw_lpm_params(udev); + xhci_writel(xhci, hlpm_val, hlpm_addr); + /* flush write */ + xhci_readl(xhci, hlpm_addr); + } else { + hird = xhci_calculate_hird_besl(xhci, udev); + } + + pm_val &= ~PORT_HIRD_MASK; + pm_val |= PORT_HIRD(hird) | PORT_RWE; + xhci_writel(xhci, pm_val, pm_addr); + pm_val = xhci_readl(xhci, pm_addr); + pm_val |= PORT_HLE; + xhci_writel(xhci, pm_val, pm_addr); + /* flush write */ + xhci_readl(xhci, pm_addr); } else { - temp &= ~(PORT_HLE | PORT_RWE | PORT_HIRD_MASK); - xhci_writel(xhci, temp, pm_addr); + pm_val &= ~(PORT_HLE | PORT_RWE | PORT_HIRD_MASK); + xhci_writel(xhci, pm_val, pm_addr); + /* flush write */ + xhci_readl(xhci, pm_addr); + if (udev->usb2_hw_lpm_capable) { + spin_unlock_irqrestore(&xhci->lock, flags); + mutex_lock(hcd->bandwidth_mutex); + xhci_change_max_exit_latency(xhci, udev, 0); + mutex_unlock(hcd->bandwidth_mutex); + return 0; + } } spin_unlock_irqrestore(&xhci->lock, flags); @@ -4340,56 +4463,6 @@ static u16 xhci_calculate_lpm_timeout(struct usb_hcd *hcd, return timeout; } -/* - * Issue an Evaluate Context command to change the Maximum Exit Latency in the - * slot context. If that succeeds, store the new MEL in the xhci_virt_device. - */ -static int xhci_change_max_exit_latency(struct xhci_hcd *xhci, - struct usb_device *udev, u16 max_exit_latency) -{ - struct xhci_virt_device *virt_dev; - struct xhci_command *command; - struct xhci_input_control_ctx *ctrl_ctx; - struct xhci_slot_ctx *slot_ctx; - unsigned long flags; - int ret; - - spin_lock_irqsave(&xhci->lock, flags); - if (max_exit_latency == xhci->devs[udev->slot_id]->current_mel) { - spin_unlock_irqrestore(&xhci->lock, flags); - return 0; - } - - /* Attempt to issue an Evaluate Context command to change the MEL. */ - virt_dev = xhci->devs[udev->slot_id]; - command = xhci->lpm_command; - xhci_slot_copy(xhci, command->in_ctx, virt_dev->out_ctx); - spin_unlock_irqrestore(&xhci->lock, flags); - - ctrl_ctx = xhci_get_input_control_ctx(xhci, command->in_ctx); - ctrl_ctx->add_flags |= cpu_to_le32(SLOT_FLAG); - slot_ctx = xhci_get_slot_ctx(xhci, command->in_ctx); - slot_ctx->dev_info2 &= cpu_to_le32(~((u32) MAX_EXIT)); - slot_ctx->dev_info2 |= cpu_to_le32(max_exit_latency); - - xhci_dbg(xhci, "Set up evaluate context for LPM MEL change.\n"); - xhci_dbg(xhci, "Slot %u Input Context:\n", udev->slot_id); - xhci_dbg_ctx(xhci, command->in_ctx, 0); - - /* Issue and wait for the evaluate context command. */ - ret = xhci_configure_endpoint(xhci, udev, command, - true, true); - xhci_dbg(xhci, "Slot %u Output Context:\n", udev->slot_id); - xhci_dbg_ctx(xhci, virt_dev->out_ctx, 0); - - if (!ret) { - spin_lock_irqsave(&xhci->lock, flags); - virt_dev->current_mel = max_exit_latency; - spin_unlock_irqrestore(&xhci->lock, flags); - } - return ret; -} - static int calculate_max_exit_latency(struct usb_device *udev, enum usb3_link_state state_changed, u16 hub_encoded_timeout) diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 79c324a..5897c13 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -386,6 +386,27 @@ struct xhci_op_regs { #define PORT_L1DS(p) (((p) & 0xff) << 8) #define PORT_HLE (1 << 16) + +/* USB2 Protocol PORTHLPMC */ +#define PORT_HIRDM(p)((p) & 3) +#define PORT_L1_TIMEOUT(p)(((p) & 0xff) << 2) +#define PORT_BESLD(p)(((p) & 0xf) << 10) + +/* use 512 microseconds as USB2 LPM L1 default timeout. */ +#define XHCI_L1_TIMEOUT 512 + +/* Set default HIRD/BESL value to 4 (350/400us) for USB2 L1 LPM resume latency. + * Safe to use with mixed HIRD and BESL systems (host and device) and is used + * by other operating systems. + * + * XHCI 1.0 errata 8/14/12 Table 13 notes: + * "Software should choose xHC BESL/BESLD field values that do not violate a + * device's resume latency requirements, + * e.g. not program values > '4' if BLC = '1' and a HIRD device is attached, + * or not program values < '4' if BLC = '0' and a BESL device is attached. + */ +#define XHCI_DEFAULT_BESL 4 + /** * struct xhci_intr_reg - Interrupt Register Set * @irq_pending: IMAN - Interrupt Management Register. Used to enable