From 6a919d906e49fd2cfc2b7d813818cf493d1c4315 Mon Sep 17 00:00:00 2001 From: P33M Date: Mon, 12 Jun 2017 16:10:03 +0100 Subject: [PATCH] dwc_otg: add module parameter int_ep_interval_min Add a module parameter (defaulting to ignored) that clamps the polling rate of high-speed Interrupt endpoints to a minimum microframe interval. The parameter is modifiable at runtime as it is used when activating new endpoints (such as on device connect). --- drivers/usb/host/dwc_otg/dwc_otg_driver.c | 6 ++++- drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c | 25 ++++++++++---------- 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/drivers/usb/host/dwc_otg/dwc_otg_driver.c b/drivers/usb/host/dwc_otg/dwc_otg_driver.c index cb060a7179a3ee..95943e07528276 100644 --- a/drivers/usb/host/dwc_otg/dwc_otg_driver.c +++ b/drivers/usb/host/dwc_otg/dwc_otg_driver.c @@ -249,6 +249,7 @@ uint16_t nak_holdoff = 8; unsigned short fiq_fsm_mask = 0x0F; +unsigned short int_ep_interval_min = 0; /** * This function shows the Driver Version. */ @@ -1398,7 +1399,10 @@ MODULE_PARM_DESC(fiq_fsm_mask, "Bitmask of transactions to perform in the FIQ.\n "Bit 1 : Periodic split transactions\n" "Bit 2 : High-speed multi-transfer isochronous\n" "All other bits should be set 0."); - +module_param(int_ep_interval_min, ushort, 0644); +MODULE_PARM_DESC(int_ep_interval_min, "Clamp high-speed Interrupt endpoints to a minimum polling interval.\n" + "0..1 = Use endpoint default\n" + "2..n = Minimum interval n microframes. Use powers of 2.\n"); /** @page "Module Parameters" * diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c index 4b1dd9de99e9e0..fe8e8f841f0366 100644 --- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c @@ -43,6 +43,7 @@ #include "dwc_otg_regs.h" extern bool microframe_schedule; +extern unsigned short int_ep_interval_min; /** * Free each QTD in the QH's QTD-list then free the QH. QH should already be @@ -218,21 +219,19 @@ void qh_init(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh, dwc_otg_hcd_urb_t * urb) SCHEDULE_SLOP); qh->interval = urb->interval; -#if 0 - /* Increase interrupt polling rate for debugging. */ - if (qh->ep_type == UE_INTERRUPT) { - qh->interval = 8; - } -#endif hprt.d32 = DWC_READ_REG32(hcd->core_if->host_if->hprt0); - if ((hprt.b.prtspd == DWC_HPRT0_PRTSPD_HIGH_SPEED) && - ((dev_speed == USB_SPEED_LOW) || - (dev_speed == USB_SPEED_FULL))) { - qh->interval *= 8; - qh->sched_frame |= 0x7; - qh->start_split_frame = qh->sched_frame; + if (hprt.b.prtspd == DWC_HPRT0_PRTSPD_HIGH_SPEED) { + if (dev_speed == USB_SPEED_LOW || + dev_speed == USB_SPEED_FULL) { + qh->interval *= 8; + qh->sched_frame |= 0x7; + qh->start_split_frame = qh->sched_frame; + } else if (int_ep_interval_min >= 2 && + qh->interval < int_ep_interval_min && + qh->ep_type == UE_INTERRUPT) { + qh->interval = int_ep_interval_min; + } } - } DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD QH Initialized\n");