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