Re: [PATCH v4 2/3] usb: dwc3: Implement interrupt moderation

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 11/15/2016 3:16 AM, Felipe Balbi wrote:
> 
> Hi,
> 
> John Youn <johnyoun@xxxxxxxxxxxx> writes:
>> Implement interrupt moderation which allows the interrupt rate to be
>> throttled. To enable this feature the dwc->imod_interval must be set to
>> 1 or greater. This value specifies the minimum inter-interrupt interval,
>> in 250 ns increments. A value of 0 disables interrupt moderation.
>>
>> This applies for DWC_usb3 version 3.00a and higher and for DWC_usb31
>> version 1.20a and higher.
>>
>> Signed-off-by: John Youn <johnyoun@xxxxxxxxxxxx>
>> ---
>>  drivers/usb/dwc3/core.c   | 16 ++++++++++++++++
>>  drivers/usb/dwc3/core.h   | 15 +++++++++++++++
>>  drivers/usb/dwc3/gadget.c | 16 ++++++++++++++++
>>  3 files changed, 47 insertions(+)
>>
>> diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
>> index 87d0cfb..889dbab 100644
>> --- a/drivers/usb/dwc3/core.c
>> +++ b/drivers/usb/dwc3/core.c
>> @@ -982,12 +982,28 @@ static void dwc3_get_properties(struct dwc3 *dwc)
>>  	dwc->hird_threshold = hird_threshold
>>  		| (dwc->is_utmi_l1_suspend << 4);
>>  
>> +	dwc->imod_interval = 0;
>> +}
>> +
>> +/* check whether the core supports IMOD */
>> +bool dwc3_has_imod(struct dwc3 *dwc)
>> +{
>> +	return ((dwc3_is_usb3(dwc) &&
>> +		 dwc->revision >= DWC3_REVISION_300A) ||
>> +		(dwc3_is_usb31(dwc) &&
>> +		 dwc->revision >= DWC3_USB31_REVISION_120A));
>>  }
>>  
>>  static void dwc3_check_params(struct dwc3 *dwc)
>>  {
>>  	struct device *dev = dwc->dev;
>>  
>> +	/* Check for proper value of imod_interval */
>> +	if (dwc->imod_interval && !dwc3_has_imod(dwc)) {
>> +		dev_warn(dwc->dev, "Interrupt moderation not supported\n");
>> +		dwc->imod_interval = 0;
>> +	}
>> +
>>  	/* Check the maximum_speed parameter */
>>  	switch (dwc->maximum_speed) {
>>  	case USB_SPEED_LOW:
>> diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
>> index bf63756..ef81fa5 100644
>> --- a/drivers/usb/dwc3/core.h
>> +++ b/drivers/usb/dwc3/core.h
>> @@ -67,6 +67,7 @@
>>  #define DWC3_DEVICE_EVENT_OVERFLOW		11
>>  
>>  #define DWC3_GEVNTCOUNT_MASK	0xfffc
>> +#define DWC3_GEVNTCOUNT_EHB	(1 << 31)
>>  #define DWC3_GSNPSID_MASK	0xffff0000
>>  #define DWC3_GSNPSREV_MASK	0xffff
>>  
>> @@ -149,6 +150,8 @@
>>  #define DWC3_DEPCMDPAR0		0x08
>>  #define DWC3_DEPCMD		0x0c
>>  
>> +#define DWC3_DEV_IMOD(n)	(0xca00 + (n * 0x4))
>> +
>>  /* OTG Registers */
>>  #define DWC3_OCFG		0xcc00
>>  #define DWC3_OCTL		0xcc04
>> @@ -465,6 +468,11 @@
>>  #define DWC3_DEPCMD_TYPE_BULK		2
>>  #define DWC3_DEPCMD_TYPE_INTR		3
>>  
>> +#define DWC3_DEV_IMOD_COUNT_SHIFT	16
>> +#define DWC3_DEV_IMOD_COUNT_MASK	(0xffff << 16)
>> +#define DWC3_DEV_IMOD_INTERVAL_SHIFT	0
>> +#define DWC3_DEV_IMOD_INTERVAL_MASK	(0xffff << 0)
>> +
>>  /* Structures */
>>  
>>  struct dwc3_trb;
>> @@ -846,6 +854,8 @@ struct dwc3_scratchpad_array {
>>   * 	1	- -3.5dB de-emphasis
>>   * 	2	- No de-emphasis
>>   * 	3	- Reserved
>> + * @imod_interval: set the interrupt moderation interval in 250ns
>> + *                 increments or 0 to disable.
>>   */
>>  struct dwc3 {
>>  	struct usb_ctrlrequest	*ctrl_req;
>> @@ -933,6 +943,7 @@ struct dwc3 {
>>   */
>>  #define DWC3_REVISION_IS_DWC31		0x80000000
>>  #define DWC3_USB31_REVISION_110A	(0x3131302a | DWC3_REVISION_IS_DWC31)
>> +#define DWC3_USB31_REVISION_120A	(0x3132302a | DWC3_REVISION_IS_DWC31)
>>  
>>  	enum dwc3_ep0_next	ep0_next_event;
>>  	enum dwc3_ep0_state	ep0state;
>> @@ -991,6 +1002,8 @@ struct dwc3 {
>>  
>>  	unsigned		tx_de_emphasis_quirk:1;
>>  	unsigned		tx_de_emphasis:2;
>> +
>> +	u16			imod_interval;
>>  };
>>  
>>  /* -------------------------------------------------------------------------- */
>> @@ -1162,6 +1175,8 @@ static inline bool dwc3_is_usb31(struct dwc3 *dwc)
>>  	return !!(dwc->revision & DWC3_REVISION_IS_DWC31);
>>  }
>>  
>> +bool dwc3_has_imod(struct dwc3 *dwc);
>> +
>>  #if IS_ENABLED(CONFIG_USB_DWC3_HOST) || IS_ENABLED(CONFIG_USB_DWC3_DUAL_ROLE)
>>  int dwc3_host_init(struct dwc3 *dwc);
>>  void dwc3_host_exit(struct dwc3 *dwc);
>> diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
>> index baa2c64..0973167 100644
>> --- a/drivers/usb/dwc3/gadget.c
>> +++ b/drivers/usb/dwc3/gadget.c
>> @@ -1685,6 +1685,17 @@ static int __dwc3_gadget_start(struct dwc3 *dwc)
>>  	int			ret = 0;
>>  	u32			reg;
>>  
>> +	/*
>> +	 * Use IMOD if enabled via dwc->imod_interval. Otherwise, if
>> +	 * the core supports IMOD, disable it.
>> +	 */
>> +	if (dwc->imod_interval) {
>> +		dwc3_writel(dwc->regs, DWC3_DEV_IMOD(0), dwc->imod_interval);
>> +		dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(0), DWC3_GEVNTCOUNT_EHB);
> 
> is this safe? You're doing this after request_threaded_irq(). Sure, IRQs
> are still masked, but couldn't clear events that would get fired as soon
> as we unmask events?

With an IMOD-capable IP, if zero is written to the GEVNTCOUNT.count
field, it has no effect, as long as the whole GEVNTCOUNT is not 0. If
the whole GEVNTCOUNT is zero that means to initialize. So this should
be safe. This is just clearing the EHB in case it is set.

> 
>> +	} else if (dwc3_has_imod(dwc)) {
>> +		dwc3_writel(dwc->regs, DWC3_DEV_IMOD(0), 0);
>> +	}
>> +
>>  	reg = dwc3_readl(dwc->regs, DWC3_DCFG);
>>  	reg &= ~(DWC3_DCFG_SPEED_MASK);
>>  
>> @@ -2847,6 +2858,11 @@ static irqreturn_t dwc3_process_event_buf(struct dwc3_event_buffer *evt)
>>  	reg &= ~DWC3_GEVNTSIZ_INTMASK;
>>  	dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(0), reg);
>>  
>> +	if (dwc->imod_interval) {
>> +		dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(0), DWC3_GEVNTCOUNT_EHB);
> 
> is this really safe? Aren't you forcefully clearing GEVNTCOUNT back to
> zero here?  Why couldn't you do a single write to GEVNTCOUNT?
> 

Same as above. This is clearing EHB, telling the core that we're
finished handling the interrupts and it can now reassert the interrupt
line when needed.

> Waiting for you reply before applying. BTW, I've applied patch 1, but
> broke it down into smaller patches. I'll send them to linux-usb shortly.
> 

Ok thanks.

Regards,
John
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux