@@ -1537,6 +1537,109 @@ static int xhci_check_ep0_maxpacket(struct xhci_hcd *xhci, struct xhci_virt_devi
15371537 return ret ;
15381538}
15391539
1540+ /*
1541+ * RPI: Fixup endpoint intervals when requested
1542+ * - Check interval versus the (cached) endpoint context
1543+ * - set the endpoint interval to the new value
1544+ * - force an endpoint configure command
1545+ * XXX: bandwidth is not recalculated. We should probably do that.
1546+ */
1547+
1548+ static unsigned int xhci_get_endpoint_flag_from_index (unsigned int ep_index )
1549+ {
1550+ return 1 << (ep_index + 1 );
1551+ }
1552+
1553+ static void xhci_fixup_endpoint (struct usb_hcd * hcd , struct usb_device * udev ,
1554+ struct usb_host_endpoint * ep , int interval )
1555+ {
1556+ struct xhci_hcd * xhci ;
1557+ struct xhci_ep_ctx * ep_ctx_out , * ep_ctx_in ;
1558+ struct xhci_command * command ;
1559+ struct xhci_input_control_ctx * ctrl_ctx ;
1560+ struct xhci_virt_device * vdev ;
1561+ int xhci_interval ;
1562+ int ret ;
1563+ int ep_index ;
1564+ unsigned long flags ;
1565+ u32 ep_info_tmp ;
1566+
1567+ xhci = hcd_to_xhci (hcd );
1568+ ep_index = xhci_get_endpoint_index (& ep -> desc );
1569+
1570+ /* FS/LS interval translations */
1571+ if ((udev -> speed == USB_SPEED_FULL ||
1572+ udev -> speed == USB_SPEED_LOW ))
1573+ interval *= 8 ;
1574+
1575+ mutex_lock (& xhci -> mutex );
1576+
1577+ spin_lock_irqsave (& xhci -> lock , flags );
1578+
1579+ vdev = xhci -> devs [udev -> slot_id ];
1580+ /* Get context-derived endpoint interval */
1581+ ep_ctx_out = xhci_get_ep_ctx (xhci , vdev -> out_ctx , ep_index );
1582+ ep_ctx_in = xhci_get_ep_ctx (xhci , vdev -> in_ctx , ep_index );
1583+ xhci_interval = EP_INTERVAL_TO_UFRAMES (le32_to_cpu (ep_ctx_out -> ep_info ));
1584+
1585+ if (interval == xhci_interval ) {
1586+ spin_unlock_irqrestore (& xhci -> lock , flags );
1587+ mutex_unlock (& xhci -> mutex );
1588+ return ;
1589+ }
1590+
1591+ xhci_dbg (xhci , "Fixup interval=%d xhci_interval=%d\n" ,
1592+ interval , xhci_interval );
1593+ command = xhci_alloc_command_with_ctx (xhci , true, GFP_ATOMIC );
1594+ if (!command ) {
1595+ /* Failure here is benign, poll at the original rate */
1596+ spin_unlock_irqrestore (& xhci -> lock , flags );
1597+ mutex_unlock (& xhci -> mutex );
1598+ return ;
1599+ }
1600+
1601+ /* xHCI uses exponents for intervals... */
1602+ xhci_interval = fls (interval ) - 1 ;
1603+ xhci_interval = clamp_val (xhci_interval , 3 , 10 );
1604+ ep_info_tmp = le32_to_cpu (ep_ctx_out -> ep_info );
1605+ ep_info_tmp &= ~EP_INTERVAL (255 );
1606+ ep_info_tmp |= EP_INTERVAL (xhci_interval );
1607+
1608+ /* Keep the endpoint context up-to-date while issuing the command. */
1609+ xhci_endpoint_copy (xhci , vdev -> in_ctx ,
1610+ vdev -> out_ctx , ep_index );
1611+ ep_ctx_in -> ep_info = cpu_to_le32 (ep_info_tmp );
1612+
1613+ /*
1614+ * We need to drop the lock, so take an explicit copy
1615+ * of the ep context.
1616+ */
1617+ xhci_endpoint_copy (xhci , command -> in_ctx , vdev -> in_ctx , ep_index );
1618+
1619+ ctrl_ctx = xhci_get_input_control_ctx (command -> in_ctx );
1620+ if (!ctrl_ctx ) {
1621+ xhci_warn (xhci ,
1622+ "%s: Could not get input context, bad type.\n" ,
1623+ __func__ );
1624+ spin_unlock_irqrestore (& xhci -> lock , flags );
1625+ xhci_free_command (xhci , command );
1626+ mutex_unlock (& xhci -> mutex );
1627+ return ;
1628+ }
1629+ ctrl_ctx -> add_flags = xhci_get_endpoint_flag_from_index (ep_index );
1630+ ctrl_ctx -> drop_flags = 0 ;
1631+
1632+ spin_unlock_irqrestore (& xhci -> lock , flags );
1633+
1634+ ret = xhci_configure_endpoint (xhci , udev , command ,
1635+ false, false);
1636+ if (ret )
1637+ xhci_warn (xhci , "%s: Configure endpoint failed: %d\n" ,
1638+ __func__ , ret );
1639+ xhci_free_command (xhci , command );
1640+ mutex_unlock (& xhci -> mutex );
1641+ }
1642+
15401643/*
15411644 * non-error returns are a promise to giveback() the urb later
15421645 * we drop ownership so next owner (or urb unlink) can get it
@@ -5402,6 +5505,7 @@ static const struct hc_driver xhci_hc_driver = {
54025505 .endpoint_reset = xhci_endpoint_reset ,
54035506 .check_bandwidth = xhci_check_bandwidth ,
54045507 .reset_bandwidth = xhci_reset_bandwidth ,
5508+ .fixup_endpoint = xhci_fixup_endpoint ,
54055509 .address_device = xhci_address_device ,
54065510 .enable_device = xhci_enable_device ,
54075511 .update_hub_device = xhci_update_hub_device ,
0 commit comments