@@ -3815,6 +3815,56 @@ int xhci_find_raw_port_number(struct usb_hcd *hcd, int port1)
38153815 return raw_port ;
38163816}
38173817
3818+ /*
3819+ * Issue an Evaluate Context command to change the Maximum Exit Latency in the
3820+ * slot context. If that succeeds, store the new MEL in the xhci_virt_device.
3821+ */
3822+ static int xhci_change_max_exit_latency (struct xhci_hcd * xhci ,
3823+ struct usb_device * udev , u16 max_exit_latency )
3824+ {
3825+ struct xhci_virt_device * virt_dev ;
3826+ struct xhci_command * command ;
3827+ struct xhci_input_control_ctx * ctrl_ctx ;
3828+ struct xhci_slot_ctx * slot_ctx ;
3829+ unsigned long flags ;
3830+ int ret ;
3831+
3832+ spin_lock_irqsave (& xhci -> lock , flags );
3833+ if (max_exit_latency == xhci -> devs [udev -> slot_id ]-> current_mel ) {
3834+ spin_unlock_irqrestore (& xhci -> lock , flags );
3835+ return 0 ;
3836+ }
3837+
3838+ /* Attempt to issue an Evaluate Context command to change the MEL. */
3839+ virt_dev = xhci -> devs [udev -> slot_id ];
3840+ command = xhci -> lpm_command ;
3841+ xhci_slot_copy (xhci , command -> in_ctx , virt_dev -> out_ctx );
3842+ spin_unlock_irqrestore (& xhci -> lock , flags );
3843+
3844+ ctrl_ctx = xhci_get_input_control_ctx (xhci , command -> in_ctx );
3845+ ctrl_ctx -> add_flags |= cpu_to_le32 (SLOT_FLAG );
3846+ slot_ctx = xhci_get_slot_ctx (xhci , command -> in_ctx );
3847+ slot_ctx -> dev_info2 &= cpu_to_le32 (~((u32 ) MAX_EXIT ));
3848+ slot_ctx -> dev_info2 |= cpu_to_le32 (max_exit_latency );
3849+
3850+ xhci_dbg (xhci , "Set up evaluate context for LPM MEL change.\n" );
3851+ xhci_dbg (xhci , "Slot %u Input Context:\n" , udev -> slot_id );
3852+ xhci_dbg_ctx (xhci , command -> in_ctx , 0 );
3853+
3854+ /* Issue and wait for the evaluate context command. */
3855+ ret = xhci_configure_endpoint (xhci , udev , command ,
3856+ true, true);
3857+ xhci_dbg (xhci , "Slot %u Output Context:\n" , udev -> slot_id );
3858+ xhci_dbg_ctx (xhci , virt_dev -> out_ctx , 0 );
3859+
3860+ if (!ret ) {
3861+ spin_lock_irqsave (& xhci -> lock , flags );
3862+ virt_dev -> current_mel = max_exit_latency ;
3863+ spin_unlock_irqrestore (& xhci -> lock , flags );
3864+ }
3865+ return ret ;
3866+ }
3867+
38183868#ifdef CONFIG_PM_RUNTIME
38193869
38203870/* BESL to HIRD Encoding array for USB2 LPM */
@@ -3856,6 +3906,28 @@ static int xhci_calculate_hird_besl(struct xhci_hcd *xhci,
38563906 return besl ;
38573907}
38583908
3909+ /* Calculate BESLD, L1 timeout and HIRDM for USB2 PORTHLPMC */
3910+ static int xhci_calculate_usb2_hw_lpm_params (struct usb_device * udev )
3911+ {
3912+ u32 field ;
3913+ int l1 ;
3914+ int besld = 0 ;
3915+ int hirdm = 0 ;
3916+
3917+ field = le32_to_cpu (udev -> bos -> ext_cap -> bmAttributes );
3918+
3919+ /* xHCI l1 is set in steps of 256us, xHCI 1.0 section 5.4.11.2 */
3920+ l1 = XHCI_L1_TIMEOUT / 256 ;
3921+
3922+ /* device has preferred BESLD */
3923+ if (field & USB_BESL_DEEP_VALID ) {
3924+ besld = USB_GET_BESL_DEEP (field );
3925+ hirdm = 1 ;
3926+ }
3927+
3928+ return PORT_BESLD (besld ) | PORT_L1_TIMEOUT (l1 ) | PORT_HIRDM (hirdm );
3929+ }
3930+
38593931static int xhci_usb2_software_lpm_test (struct usb_hcd * hcd ,
38603932 struct usb_device * udev )
38613933{
@@ -3988,11 +4060,12 @@ int xhci_set_usb2_hardware_lpm(struct usb_hcd *hcd,
39884060{
39894061 struct xhci_hcd * xhci = hcd_to_xhci (hcd );
39904062 __le32 __iomem * * port_array ;
3991- __le32 __iomem * pm_addr ;
3992- u32 temp ;
4063+ __le32 __iomem * pm_addr , * hlpm_addr ;
4064+ u32 pm_val , hlpm_val , field ;
39934065 unsigned int port_num ;
39944066 unsigned long flags ;
3995- int hird ;
4067+ int hird , exit_latency ;
4068+ int ret ;
39964069
39974070 if (hcd -> speed == HCD_USB3 || !xhci -> hw_lpm_support ||
39984071 !udev -> lpm_capable )
@@ -4010,23 +4083,73 @@ int xhci_set_usb2_hardware_lpm(struct usb_hcd *hcd,
40104083 port_array = xhci -> usb2_ports ;
40114084 port_num = udev -> portnum - 1 ;
40124085 pm_addr = port_array [port_num ] + PORTPMSC ;
4013- temp = xhci_readl (xhci , pm_addr );
4086+ pm_val = xhci_readl (xhci , pm_addr );
4087+ hlpm_addr = port_array [port_num ] + PORTHLPMC ;
4088+ field = le32_to_cpu (udev -> bos -> ext_cap -> bmAttributes );
40144089
40154090 xhci_dbg (xhci , "%s port %d USB2 hardware LPM\n" ,
40164091 enable ? "enable" : "disable" , port_num );
40174092
4018- hird = xhci_calculate_hird_besl (xhci , udev );
4019-
40204093 if (enable ) {
4021- temp &= ~PORT_HIRD_MASK ;
4022- temp |= PORT_HIRD (hird ) | PORT_RWE ;
4023- xhci_writel (xhci , temp , pm_addr );
4024- temp = xhci_readl (xhci , pm_addr );
4025- temp |= PORT_HLE ;
4026- xhci_writel (xhci , temp , pm_addr );
4094+ /* Host supports BESL timeout instead of HIRD */
4095+ if (udev -> usb2_hw_lpm_besl_capable ) {
4096+ /* if device doesn't have a preferred BESL value use a
4097+ * default one which works with mixed HIRD and BESL
4098+ * systems. See XHCI_DEFAULT_BESL definition in xhci.h
4099+ */
4100+ if ((field & USB_BESL_SUPPORT ) &&
4101+ (field & USB_BESL_BASELINE_VALID ))
4102+ hird = USB_GET_BESL_BASELINE (field );
4103+ else
4104+ hird = XHCI_DEFAULT_BESL ;
4105+
4106+ exit_latency = xhci_besl_encoding [hird ];
4107+ spin_unlock_irqrestore (& xhci -> lock , flags );
4108+
4109+ /* USB 3.0 code dedicate one xhci->lpm_command->in_ctx
4110+ * input context for link powermanagement evaluate
4111+ * context commands. It is protected by hcd->bandwidth
4112+ * mutex and is shared by all devices. We need to set
4113+ * the max ext latency in USB 2 BESL LPM as well, so
4114+ * use the same mutex and xhci_change_max_exit_latency()
4115+ */
4116+ mutex_lock (hcd -> bandwidth_mutex );
4117+ ret = xhci_change_max_exit_latency (xhci , udev ,
4118+ exit_latency );
4119+ mutex_unlock (hcd -> bandwidth_mutex );
4120+
4121+ if (ret < 0 )
4122+ return ret ;
4123+ spin_lock_irqsave (& xhci -> lock , flags );
4124+
4125+ hlpm_val = xhci_calculate_usb2_hw_lpm_params (udev );
4126+ xhci_writel (xhci , hlpm_val , hlpm_addr );
4127+ /* flush write */
4128+ xhci_readl (xhci , hlpm_addr );
4129+ } else {
4130+ hird = xhci_calculate_hird_besl (xhci , udev );
4131+ }
4132+
4133+ pm_val &= ~PORT_HIRD_MASK ;
4134+ pm_val |= PORT_HIRD (hird ) | PORT_RWE ;
4135+ xhci_writel (xhci , pm_val , pm_addr );
4136+ pm_val = xhci_readl (xhci , pm_addr );
4137+ pm_val |= PORT_HLE ;
4138+ xhci_writel (xhci , pm_val , pm_addr );
4139+ /* flush write */
4140+ xhci_readl (xhci , pm_addr );
40274141 } else {
4028- temp &= ~(PORT_HLE | PORT_RWE | PORT_HIRD_MASK );
4029- xhci_writel (xhci , temp , pm_addr );
4142+ pm_val &= ~(PORT_HLE | PORT_RWE | PORT_HIRD_MASK );
4143+ xhci_writel (xhci , pm_val , pm_addr );
4144+ /* flush write */
4145+ xhci_readl (xhci , pm_addr );
4146+ if (udev -> usb2_hw_lpm_besl_capable ) {
4147+ spin_unlock_irqrestore (& xhci -> lock , flags );
4148+ mutex_lock (hcd -> bandwidth_mutex );
4149+ xhci_change_max_exit_latency (xhci , udev , 0 );
4150+ mutex_unlock (hcd -> bandwidth_mutex );
4151+ return 0 ;
4152+ }
40304153 }
40314154
40324155 spin_unlock_irqrestore (& xhci -> lock , flags );
@@ -4068,6 +4191,9 @@ int xhci_update_device(struct usb_hcd *hcd, struct usb_device *udev)
40684191 if (xhci -> hw_lpm_support == 1 &&
40694192 xhci_check_usb2_port_capability (xhci , portnum , XHCI_HLC )) {
40704193 udev -> usb2_hw_lpm_capable = 1 ;
4194+ if (xhci_check_usb2_port_capability (xhci , portnum ,
4195+ XHCI_BLC ))
4196+ udev -> usb2_hw_lpm_besl_capable = 1 ;
40714197 ret = xhci_set_usb2_hardware_lpm (hcd , udev , 1 );
40724198 if (!ret )
40734199 udev -> usb2_hw_lpm_enabled = 1 ;
@@ -4398,56 +4524,6 @@ static u16 xhci_calculate_lpm_timeout(struct usb_hcd *hcd,
43984524 return timeout ;
43994525}
44004526
4401- /*
4402- * Issue an Evaluate Context command to change the Maximum Exit Latency in the
4403- * slot context. If that succeeds, store the new MEL in the xhci_virt_device.
4404- */
4405- static int xhci_change_max_exit_latency (struct xhci_hcd * xhci ,
4406- struct usb_device * udev , u16 max_exit_latency )
4407- {
4408- struct xhci_virt_device * virt_dev ;
4409- struct xhci_command * command ;
4410- struct xhci_input_control_ctx * ctrl_ctx ;
4411- struct xhci_slot_ctx * slot_ctx ;
4412- unsigned long flags ;
4413- int ret ;
4414-
4415- spin_lock_irqsave (& xhci -> lock , flags );
4416- if (max_exit_latency == xhci -> devs [udev -> slot_id ]-> current_mel ) {
4417- spin_unlock_irqrestore (& xhci -> lock , flags );
4418- return 0 ;
4419- }
4420-
4421- /* Attempt to issue an Evaluate Context command to change the MEL. */
4422- virt_dev = xhci -> devs [udev -> slot_id ];
4423- command = xhci -> lpm_command ;
4424- xhci_slot_copy (xhci , command -> in_ctx , virt_dev -> out_ctx );
4425- spin_unlock_irqrestore (& xhci -> lock , flags );
4426-
4427- ctrl_ctx = xhci_get_input_control_ctx (xhci , command -> in_ctx );
4428- ctrl_ctx -> add_flags |= cpu_to_le32 (SLOT_FLAG );
4429- slot_ctx = xhci_get_slot_ctx (xhci , command -> in_ctx );
4430- slot_ctx -> dev_info2 &= cpu_to_le32 (~((u32 ) MAX_EXIT ));
4431- slot_ctx -> dev_info2 |= cpu_to_le32 (max_exit_latency );
4432-
4433- xhci_dbg (xhci , "Set up evaluate context for LPM MEL change.\n" );
4434- xhci_dbg (xhci , "Slot %u Input Context:\n" , udev -> slot_id );
4435- xhci_dbg_ctx (xhci , command -> in_ctx , 0 );
4436-
4437- /* Issue and wait for the evaluate context command. */
4438- ret = xhci_configure_endpoint (xhci , udev , command ,
4439- true, true);
4440- xhci_dbg (xhci , "Slot %u Output Context:\n" , udev -> slot_id );
4441- xhci_dbg_ctx (xhci , virt_dev -> out_ctx , 0 );
4442-
4443- if (!ret ) {
4444- spin_lock_irqsave (& xhci -> lock , flags );
4445- virt_dev -> current_mel = max_exit_latency ;
4446- spin_unlock_irqrestore (& xhci -> lock , flags );
4447- }
4448- return ret ;
4449- }
4450-
44514527static int calculate_max_exit_latency (struct usb_device * udev ,
44524528 enum usb3_link_state state_changed ,
44534529 u16 hub_encoded_timeout )
0 commit comments