@@ -1608,6 +1608,109 @@ static int xhci_check_ep0_maxpacket(struct xhci_hcd *xhci, struct xhci_virt_devi
16081608 return ret ;
16091609}
16101610
1611+ /*
1612+ * RPI: Fixup endpoint intervals when requested
1613+ * - Check interval versus the (cached) endpoint context
1614+ * - set the endpoint interval to the new value
1615+ * - force an endpoint configure command
1616+ * XXX: bandwidth is not recalculated. We should probably do that.
1617+ */
1618+
1619+ static unsigned int xhci_get_endpoint_flag_from_index (unsigned int ep_index )
1620+ {
1621+ return 1 << (ep_index + 1 );
1622+ }
1623+
1624+ static void xhci_fixup_endpoint (struct usb_hcd * hcd , struct usb_device * udev ,
1625+ struct usb_host_endpoint * ep , int interval )
1626+ {
1627+ struct xhci_hcd * xhci ;
1628+ struct xhci_ep_ctx * ep_ctx_out , * ep_ctx_in ;
1629+ struct xhci_command * command ;
1630+ struct xhci_input_control_ctx * ctrl_ctx ;
1631+ struct xhci_virt_device * vdev ;
1632+ int xhci_interval ;
1633+ int ret ;
1634+ int ep_index ;
1635+ unsigned long flags ;
1636+ u32 ep_info_tmp ;
1637+
1638+ xhci = hcd_to_xhci (hcd );
1639+ ep_index = xhci_get_endpoint_index (& ep -> desc );
1640+
1641+ /* FS/LS interval translations */
1642+ if ((udev -> speed == USB_SPEED_FULL ||
1643+ udev -> speed == USB_SPEED_LOW ))
1644+ interval *= 8 ;
1645+
1646+ mutex_lock (& xhci -> mutex );
1647+
1648+ spin_lock_irqsave (& xhci -> lock , flags );
1649+
1650+ vdev = xhci -> devs [udev -> slot_id ];
1651+ /* Get context-derived endpoint interval */
1652+ ep_ctx_out = xhci_get_ep_ctx (xhci , vdev -> out_ctx , ep_index );
1653+ ep_ctx_in = xhci_get_ep_ctx (xhci , vdev -> in_ctx , ep_index );
1654+ xhci_interval = EP_INTERVAL_TO_UFRAMES (le32_to_cpu (ep_ctx_out -> ep_info ));
1655+
1656+ if (interval == xhci_interval ) {
1657+ spin_unlock_irqrestore (& xhci -> lock , flags );
1658+ mutex_unlock (& xhci -> mutex );
1659+ return ;
1660+ }
1661+
1662+ xhci_dbg (xhci , "Fixup interval=%d xhci_interval=%d\n" ,
1663+ interval , xhci_interval );
1664+ command = xhci_alloc_command_with_ctx (xhci , true, GFP_ATOMIC );
1665+ if (!command ) {
1666+ /* Failure here is benign, poll at the original rate */
1667+ spin_unlock_irqrestore (& xhci -> lock , flags );
1668+ mutex_unlock (& xhci -> mutex );
1669+ return ;
1670+ }
1671+
1672+ /* xHCI uses exponents for intervals... */
1673+ xhci_interval = fls (interval ) - 1 ;
1674+ xhci_interval = clamp_val (xhci_interval , 3 , 10 );
1675+ ep_info_tmp = le32_to_cpu (ep_ctx_out -> ep_info );
1676+ ep_info_tmp &= ~EP_INTERVAL (255 );
1677+ ep_info_tmp |= EP_INTERVAL (xhci_interval );
1678+
1679+ /* Keep the endpoint context up-to-date while issuing the command. */
1680+ xhci_endpoint_copy (xhci , vdev -> in_ctx ,
1681+ vdev -> out_ctx , ep_index );
1682+ ep_ctx_in -> ep_info = cpu_to_le32 (ep_info_tmp );
1683+
1684+ /*
1685+ * We need to drop the lock, so take an explicit copy
1686+ * of the ep context.
1687+ */
1688+ xhci_endpoint_copy (xhci , command -> in_ctx , vdev -> in_ctx , ep_index );
1689+
1690+ ctrl_ctx = xhci_get_input_control_ctx (command -> in_ctx );
1691+ if (!ctrl_ctx ) {
1692+ xhci_warn (xhci ,
1693+ "%s: Could not get input context, bad type.\n" ,
1694+ __func__ );
1695+ spin_unlock_irqrestore (& xhci -> lock , flags );
1696+ xhci_free_command (xhci , command );
1697+ mutex_unlock (& xhci -> mutex );
1698+ return ;
1699+ }
1700+ ctrl_ctx -> add_flags = xhci_get_endpoint_flag_from_index (ep_index );
1701+ ctrl_ctx -> drop_flags = 0 ;
1702+
1703+ spin_unlock_irqrestore (& xhci -> lock , flags );
1704+
1705+ ret = xhci_configure_endpoint (xhci , udev , command ,
1706+ false, false);
1707+ if (ret )
1708+ xhci_warn (xhci , "%s: Configure endpoint failed: %d\n" ,
1709+ __func__ , ret );
1710+ xhci_free_command (xhci , command );
1711+ mutex_unlock (& xhci -> mutex );
1712+ }
1713+
16111714/*
16121715 * non-error returns are a promise to giveback() the urb later
16131716 * we drop ownership so next owner (or urb unlink) can get it
@@ -5568,6 +5671,7 @@ static const struct hc_driver xhci_hc_driver = {
55685671 .endpoint_reset = xhci_endpoint_reset ,
55695672 .check_bandwidth = xhci_check_bandwidth ,
55705673 .reset_bandwidth = xhci_reset_bandwidth ,
5674+ .fixup_endpoint = xhci_fixup_endpoint ,
55715675 .address_device = xhci_address_device ,
55725676 .enable_device = xhci_enable_device ,
55735677 .update_hub_device = xhci_update_hub_device ,
0 commit comments