Re: [PATCH v3 1/2] usb: dwc3: refactor gadget endpoint count calculation

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

 



On 06/04/17 11:59, Roger Quadros wrote:
> Hi,
> 
> On 31/01/17 22:58, Bryan O'Donoghue wrote:
>> - DWC_USB3_NUM indicates the number of Device mode single directional
>>   endpoints, including OUT and IN endpoint 0.
>>
>> - DWC_USB3_NUM_IN_EPS indicates the maximum number of Device mode IN
>>   endpoints active at any time, including control endpoint 0.
>>
>> It's possible to configure RTL such that DWC_USB3_NUM_EPS is equal to
>> DWC_USB3_NUM_IN_EPS.
>>
>> dwc3-core calculates the number of OUT endpoints as DWC_USB3_NUM minus
>> DWC_USB3_NUM_IN_EPS. If RTL has been configured with DWC_USB3_NUM_IN_EPS
>> equal to DWC_USB3_NUM then dwc3-core will calculate the number of OUT
>> endpoints as zero.
>>
>> For example a from dwc3_core_num_eps() shows:
>> [    1.565000]  /usb0@f01d0000: found 8 IN and 0 OUT endpoints
>>
>> This patch refactors the endpoint calculation down to one variable
>> dwc->num_eps taking care to maintain the current mapping of endpoints for
>> fixed FPGA configurations as described in Table 4-7 of version 2.60a of the
>> DWC USB3 databook.
>>
>> The endpoint mapping will then be EP-OUT, EP-IN etc, up to DWC_USB3_NUM.
>> If DWC_USB3_NUM is odd then OUT will take the extra endpoint.
>>
>> Suggested-by: Felipe Balbi <balbi@xxxxxxxxxx>
>> Signed-off-by: Bryan O'Donoghue <pure.logic@xxxxxxxxxxxxxxxxx>
> 
> This patch breaks gadget mode on dra7-evm that uses dwc3 core v2.02a.
> 
> Apparently on dra7, DWC3_NUM_EPS(parms) returns 32 (IN+OUT) and that's
> why things break as below
> 
> 
> [    8.973915] ------------[ cut here ]------------
> [    8.978779] WARNING: CPU: 0 PID: 84 at drivers/bus/omap_l3_noc.c:147 l3_interrupt_handler+0x220/0x34c
> [    8.988457] 44000000.ocp:L3 Custom Error: MASTER MPU TARGET L4_PER3_P3 (Read): Data Access in User mode during Functional access
> [    9.000587] Modules linked in: dwc3 snd_soc_simple_card udc_core snd_soc_davinci_mcasp snd_soc_simple_card_utils snd_soc_tlv320aic3x m25p80 evdev usb_common snd_soc_edma snd_soc_omap spi_nor snd_soc_core snde
> [    9.041924] CPU: 0 PID: 84 Comm: kworker/0:2 Not tainted 4.11.0-rc4-00049-g4b31421 #1327
> [    9.050426] Hardware name: Generic DRA74X (Flattened Device Tree)
> [    9.056848] Workqueue: events_power_efficient __dwc3_set_mode [dwc3]
> [    9.063537] [<c01101ec>] (unwind_backtrace) from [<c010c328>] (show_stack+0x10/0x14)
> [    9.071672] [<c010c328>] (show_stack) from [<c04b46b8>] (dump_stack+0xac/0xe0)
> [    9.079258] [<c04b46b8>] (dump_stack) from [<c0136cf0>] (__warn+0xd8/0x104)
> [    9.086574] [<c0136cf0>] (__warn) from [<c0136d50>] (warn_slowpath_fmt+0x34/0x44)
> [    9.094438] [<c0136d50>] (warn_slowpath_fmt) from [<c04eb228>] (l3_interrupt_handler+0x220/0x34c)
> [    9.103760] [<c04eb228>] (l3_interrupt_handler) from [<c01a9438>] (__handle_irq_event_percpu+0x48/0x3b4)
> [    9.113714] [<c01a9438>] (__handle_irq_event_percpu) from [<c01a97c0>] (handle_irq_event_percpu+0x1c/0x58)
> [    9.123857] [<c01a97c0>] (handle_irq_event_percpu) from [<c01a9834>] (handle_irq_event+0x38/0x5c)
> [    9.133170] [<c01a9834>] (handle_irq_event) from [<c01acc94>] (handle_fasteoi_irq+0xcc/0x1ac)
> [    9.142120] [<c01acc94>] (handle_fasteoi_irq) from [<c01a874c>] (generic_handle_irq+0x20/0x34)
> [    9.151165] [<c01a874c>] (generic_handle_irq) from [<c01a8ca0>] (__handle_domain_irq+0x64/0xe0)
> [    9.160306] [<c01a8ca0>] (__handle_domain_irq) from [<c0101550>] (gic_handle_irq+0x54/0xb8)
> [    9.169087] [<c0101550>] (gic_handle_irq) from [<c080d1f0>] (__irq_svc+0x70/0x98)
> [    9.176942] Exception stack(0xed095df0 to 0xed095e38)
> [    9.182241] 5de0:                                     00000000 00000000 01000000 e5935000
> [    9.190821] 5e00: bf2fc85c 20000013 ffffffff ed095e74 00000001 ed094000 00000011 ed14a810
> [    9.199407] 5e20: 00000005 ed095e40 00000000 c080d144 60000113 ffffffff
> [    9.206350] [<c080d1f0>] (__irq_svc) from [<c080d144>] (__dabt_svc+0x64/0xa0)
> [    9.213861] [<c080d144>] (__dabt_svc) from [<bf2fc860>] (dwc3_gadget_init+0x2a0/0xacc [dwc3])
> [    9.222881] [<bf2fc860>] (dwc3_gadget_init [dwc3]) from [<bf2ee574>] (__dwc3_set_mode+0xa8/0xe8 [dwc3])
> [    9.232762] [<bf2ee574>] (__dwc3_set_mode [dwc3]) from [<c0154f44>] (process_one_work+0x1fc/0x76c)
> [    9.242173] [<c0154f44>] (process_one_work) from [<c01554f0>] (worker_thread+0x3c/0x540)
> [    9.250671] [<c01554f0>] (worker_thread) from [<c015ba40>] (kthread+0xf8/0x138)
> [    9.258361] [<c015ba40>] (kthread) from [<c0107910>] (ret_from_fork+0x14/0x24)
> [    9.265941] ---[ end trace 82ed288046388a02 ]---
> [    9.271148] Unhandled fault: imprecise external abort (0x1406) at 0x00000000
> [    9.278547] pgd = c0004000
> [    9.281391] [00000000] *pgd=00000000
> [    9.285160] Internal error: : 1406 [#1] SMP ARM
> [    9.289914] Modules linked in: dwc3 snd_soc_simple_card udc_core snd_soc_davinci_mcasp snd_soc_simple_card_utils snd_soc_tlv320aic3x m25p80 evdev usb_common snd_soc_edma snd_soc_omap spi_nor snd_soc_core snde
> [    9.331160] CPU: 0 PID: 84 Comm: kworker/0:2 Tainted: G        W       4.11.0-rc4-00049-g4b31421 #1327
> [    9.340923] Hardware name: Generic DRA74X (Flattened Device Tree)
> [    9.347352] Workqueue: events_power_efficient __dwc3_set_mode [dwc3]
> [    9.354020] task: ed0931c0 task.stack: ed094000
> [    9.358796] PC is at dwc3_gadget_init+0x2a0/0xacc [dwc3]
> [    9.364371] LR is at 0xd8
> [    9.367122] pc : [<bf2fc860>]    lr : [<000000d8>]    psr: 20000013
> [    9.367122] sp : ed095e90  ip : 00000000  fp : ed14a810
> [    9.379162] r10: 00000011  r9 : 00000001  r8 : 00000001
> [    9.384638] r7 : 000001c5  r6 : fa89c100  r5 : 00000000  r4 : ec915300
> [    9.391475] r3 : fa89c301  r2 : 00000008  r1 : 00000000  r0 : 00000040
> [    9.398322] Flags: nzCv  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment none
> [    9.405809] Control: 10c5387d  Table: ad38c06a  DAC: 00000051
> [    9.411843] Process kworker/0:2 (pid: 84, stack limit = 0xed094218)
> [    9.418420] Stack: (0xed095e90 to 0xed096000)
> [    9.422990] 5e80:                                     bf303350 00000110 00000001 0000c910
> [    9.431567] 5ea0: 00000008 ed14a99c c0d0796c ed14aa04 00000020 0000c301 00000000 c01b4bb0
> [    9.440146] 5ec0: bf306e60 bf2eb754 00000002 ed14a810 ed14a8e8 80000113 ed095f20 eedb1200
> [    9.448730] 5ee0: c0d0796c c0dc2fd4 c0d4fbbe bf2ee574 ed14a810 ed073080 eedada80 c0154f44
> [    9.457311] 5f00: 00000001 00000000 c0154e8c 00000002 00000000 00000000 c0155564 00000008
> [    9.465902] 5f20: bf307380 c0f33a74 00000000 bf302574 ed073080 eedada80 ed073098 00000008
> [    9.474477] 5f40: eedadab4 ed094000 c0d04900 eedada80 ed073080 c01554f0 00000000 ffffe000
> [    9.483055] 5f60: ed09e240 ee136680 00000000 ffffe000 ed09e240 ed073080 c01554b4 ee1366b8
> [    9.491639] 5f80: ee0c5e90 c015ba40 ed094000 ed09e240 c015b948 00000000 00000000 00000000
> [    9.500223] 5fa0: 00000000 00000000 00000000 c0107910 00000000 00000000 00000000 00000000
> [    9.508801] 5fc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
> [    9.517387] 5fe0: 00000000 00000000 00000000 00000000 00000013 00000000 8a0400c5 20808032
> [    9.525999] [<bf2fc860>] (dwc3_gadget_init [dwc3]) from [<bf2ee574>] (__dwc3_set_mode+0xa8/0xe8 [dwc3])
> [    9.535871] [<bf2ee574>] (__dwc3_set_mode [dwc3]) from [<c0154f44>] (process_one_work+0x1fc/0x76c)
> [    9.545276] [<c0154f44>] (process_one_work) from [<c01554f0>] (worker_thread+0x3c/0x540)
> [    9.553777] [<c01554f0>] (worker_thread) from [<c015ba40>] (kthread+0xf8/0x138)
> [    9.561459] [<c015ba40>] (kthread) from [<c0107910>] (ret_from_fork+0x14/0x24)
> [    9.569042] Code: e1a021c0 e0863003 e58d2010 e5935000 (e3a03000) 
> [    9.575433] ---[ end trace 82ed288046388a03 ]---
> 
> cheers,
> -roger
> 
>> ---
>>  drivers/usb/dwc3/core.c    |  3 +--
>>  drivers/usb/dwc3/core.h    |  6 ++----
>>  drivers/usb/dwc3/debugfs.c | 15 ++-------------
>>  drivers/usb/dwc3/gadget.c  | 36 +++++++++++-------------------------
>>  4 files changed, 16 insertions(+), 44 deletions(-)
>>
>> diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
>> index 369bab1..68c9c84 100644
>> --- a/drivers/usb/dwc3/core.c
>> +++ b/drivers/usb/dwc3/core.c
>> @@ -397,8 +397,7 @@ static void dwc3_core_num_eps(struct dwc3 *dwc)
>>  {
>>  	struct dwc3_hwparams	*parms = &dwc->hwparams;
>>  
>> -	dwc->num_in_eps = DWC3_NUM_IN_EPS(parms);
>> -	dwc->num_out_eps = DWC3_NUM_EPS(parms) - dwc->num_in_eps;
>> +	dwc->num_eps = DWC3_NUM_EPS(parms);
>>  }
>>  
>>  static void dwc3_cache_hwparams(struct dwc3 *dwc)
>> diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
>> index 2b9e4ca..d496ddc 100644
>> --- a/drivers/usb/dwc3/core.h
>> +++ b/drivers/usb/dwc3/core.h
>> @@ -799,8 +799,7 @@ struct dwc3_scratchpad_array {
>>   * @u2pel: parameter from Set SEL request.
>>   * @u1sel: parameter from Set SEL request.
>>   * @u1pel: parameter from Set SEL request.
>> - * @num_out_eps: number of out endpoints
>> - * @num_in_eps: number of in endpoints
>> + * @num_eps: number of endpoints
>>   * @ep0_next_event: hold the next expected event
>>   * @ep0state: state of endpoint zero
>>   * @link_state: link state
>> @@ -960,8 +959,7 @@ struct dwc3 {
>>  
>>  	u8			speed;
>>  
>> -	u8			num_out_eps;
>> -	u8			num_in_eps;
>> +	u8			num_eps;
>>  
>>  	struct dwc3_hwparams	hwparams;
>>  	struct dentry		*root;
>> diff --git a/drivers/usb/dwc3/debugfs.c b/drivers/usb/dwc3/debugfs.c
>> index 31926dd..7df4541 100644
>> --- a/drivers/usb/dwc3/debugfs.c
>> +++ b/drivers/usb/dwc3/debugfs.c
>> @@ -822,19 +822,8 @@ static void dwc3_debugfs_create_endpoint_dirs(struct dwc3 *dwc,
>>  {
>>  	int			i;
>>  
>> -	for (i = 0; i < dwc->num_in_eps; i++) {
>> -		u8		epnum = (i << 1) | 1;
>> -		struct dwc3_ep	*dep = dwc->eps[epnum];
>> -
>> -		if (!dep)
>> -			continue;
>> -
>> -		dwc3_debugfs_create_endpoint_dir(dep, parent);
>> -	}
>> -
>> -	for (i = 0; i < dwc->num_out_eps; i++) {
>> -		u8		epnum = (i << 1);
>> -		struct dwc3_ep	*dep = dwc->eps[epnum];
>> +	for (i = 0; i < dwc->num_eps; i++) {
>> +		struct dwc3_ep	*dep = dwc->eps[i];
>>  
>>  		if (!dep)
>>  			continue;
>> diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
>> index 4db97ec..ef86ab6 100644
>> --- a/drivers/usb/dwc3/gadget.c
>> +++ b/drivers/usb/dwc3/gadget.c
>> @@ -1930,14 +1930,13 @@ static const struct usb_gadget_ops dwc3_gadget_ops = {
>>  
>>  /* -------------------------------------------------------------------------- */
>>  
>> -static int dwc3_gadget_init_hw_endpoints(struct dwc3 *dwc,
>> -		u8 num, u32 direction)
>> +static int dwc3_gadget_init_hw_endpoints(struct dwc3 *dwc, u8 num)
>>  {
>>  	struct dwc3_ep			*dep;
>> -	u8				i;
>> +	u8				epnum;
>> +	bool				direction = false;
>>  
>> -	for (i = 0; i < num; i++) {
>> -		u8 epnum = (i << 1) | (direction ? 1 : 0);
>> +	for (epnum = 0; epnum < num; epnum++) {
>>  
>>  		dep = kzalloc(sizeof(*dep), GFP_KERNEL);
>>  		if (!dep)
>> @@ -1945,12 +1944,12 @@ static int dwc3_gadget_init_hw_endpoints(struct dwc3 *dwc,
>>  
>>  		dep->dwc = dwc;
>>  		dep->number = epnum;
>> -		dep->direction = !!direction;
>> +		dep->direction = direction;
>>  		dep->regs = dwc->regs + DWC3_DEP_BASE(epnum);
>>  		dwc->eps[epnum] = dep;
>>  
>> -		snprintf(dep->name, sizeof(dep->name), "ep%d%s", epnum >> 1,
>> -				(epnum & 1) ? "in" : "out");
>> +		snprintf(dep->name, sizeof(dep->name), "ep%d%s", epnum / 2,
>> +			 direction ? "in" : "out");
>>  
>>  		dep->endpoint.name = dep->name;
>>  
>> @@ -1977,7 +1976,7 @@ static int dwc3_gadget_init_hw_endpoints(struct dwc3 *dwc,
>>  			/* MDWIDTH is represented in bits, we need it in bytes */
>>  			mdwidth /= 8;
>>  
>> -			size = dwc3_readl(dwc->regs, DWC3_GTXFIFOSIZ(i));
>> +			size = dwc3_readl(dwc->regs, DWC3_GTXFIFOSIZ(epnum));

Just to shed some more light here. I was testing on Felipe's testing/next where
this line has been fixed to

size = dwc3_readl(dwc->regs, DWC3_GTXFIFOSIZ(epnum >> 1));

But as the macro DWC3_GTXFIFOSIZ isn't defined correctly it
results in a wrong address thus causing the fault.

Proper fix should be

-#define DWC3_GTXFIFOSIZ(n)     (0xc300 + (n * 0x04))
+#define DWC3_GTXFIFOSIZ(n)     (0xc300 + ((n) * 0x04))

for all the macros. And that fix should come by a separate patch.


>>  			size = DWC3_GTXFIFOSIZ_TXFDEF(size);
>>  
>>  			/* FIFO Depth is in MDWDITH bytes. Multiply */
>> @@ -2027,11 +2026,12 @@ static int dwc3_gadget_init_hw_endpoints(struct dwc3 *dwc,
>>  			dep->endpoint.caps.type_int = true;
>>  		}
>>  
>> -		dep->endpoint.caps.dir_in = !!direction;
>> +		dep->endpoint.caps.dir_in = direction;
>>  		dep->endpoint.caps.dir_out = !direction;
>>  
>>  		INIT_LIST_HEAD(&dep->pending_list);
>>  		INIT_LIST_HEAD(&dep->started_list);
>> +		direction = !direction;
>>  	}
>>  
>>  	return 0;
>> @@ -2039,23 +2039,9 @@ static int dwc3_gadget_init_hw_endpoints(struct dwc3 *dwc,
>>  
>>  static int dwc3_gadget_init_endpoints(struct dwc3 *dwc)
>>  {
>> -	int				ret;
>> -
>>  	INIT_LIST_HEAD(&dwc->gadget.ep_list);
>>  
>> -	ret = dwc3_gadget_init_hw_endpoints(dwc, dwc->num_out_eps, 0);
>> -	if (ret < 0) {
>> -		dev_err(dwc->dev, "failed to initialize OUT endpoints\n");
>> -		return ret;
>> -	}
>> -
>> -	ret = dwc3_gadget_init_hw_endpoints(dwc, dwc->num_in_eps, 1);
>> -	if (ret < 0) {
>> -		dev_err(dwc->dev, "failed to initialize IN endpoints\n");
>> -		return ret;
>> -	}
>> -
>> -	return 0;
>> +	return dwc3_gadget_init_hw_endpoints(dwc, dwc->num_eps);
>>  }
>>  
>>  static void dwc3_gadget_free_endpoints(struct dwc3 *dwc)
>>
> --
> 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
> 


cheers,
-roger
--
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