Skip to contentSkip to conversation

usb: dwc3: gadget: giveback request if start transfer fail

PATCH In review Zhuang Jin Can 2 participants 6 messages Apr 30, 2014 – May 2, 2014

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 usb: dwc3: gadget: giveback request if start transfer fail

At least we should giveback the current request to the gadget. Otherwise, the gadget will be stuck without knowing anything.

It was oberved that the failure can happen if the request is queued when the run/stop bit of controller is not set.

---
 drivers/usb/dwc3/gadget.c |    4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)
drivers/usb/dwc3/gadget.c +1 -3
index 70715ee..8d0c3c7 100644
@@ -1000,9 +1000,7 @@ static int __dwc3_gadget_kick_transfer(struct dwc3_ep *dep, u16 cmd_param,
 		 * here and stop, unmap, free and del each of the linked
 		 * requests instead of what we do now.
 		 */
-		usb_gadget_unmap_request(&dwc->gadget, &req->request,
-				req->direction);
-		list_del(&req->list);
+		dwc3_gadget_giveback(dep, req, -ESHUTDOWN);
 		return ret;
 	}
 
Signature · 1 line
1.7.9.5
#1 lore raw

Hi,

Quoted 6 lines · Zhuang Jin Can

At least we should giveback the current request to the gadget. Otherwise, the gadget will be stuck without knowing anything.

It was oberved that the failure can happen if the request is queued when the run/stop bit of controller is not set.

why is your gadget queueing any requests before calling ->udc_start() ?

A better question, what modification have you done to udc-core.c which broke this ? udc-core *always* calls ->udc_start() by the time you load a gadget driver so this case will *never* happen. Whatever modification you did, broke this assumption and I will *not* accept this patch because the bug is elsewhere and *not* in mainline kernel.

Quoted 23 lines
---
 drivers/usb/dwc3/gadget.c |    4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)
drivers/usb/dwc3/gadget.c +1 -3
index 70715ee..8d0c3c7 100644
@@ -1000,9 +1000,7 @@ static int __dwc3_gadget_kick_transfer(struct dwc3_ep *dep, u16 cmd_param,
 		 * here and stop, unmap, free and del each of the linked
 		 * requests instead of what we do now.
 		 */
-		usb_gadget_unmap_request(&dwc->gadget, &req->request,
-				req->direction);
-		list_del(&req->list);
+		dwc3_gadget_giveback(dep, req, -ESHUTDOWN);
 		return ret;
 	}
 
Signature · 1 line
1.7.9.5
Signature · 1 line
balbi
#2 lore raw

Hi Balbi,

Quoted 8 lines · Felipe Balbi
Quoted 6 lines · Zhuang Jin Can

At least we should giveback the current request to the gadget. Otherwise, the gadget will be stuck without knowing anything.

It was oberved that the failure can happen if the request is queued when the run/stop bit of controller is not set.

Quoted 8 lines

why is your gadget queueing any requests before calling ->udc_start() ?

A better question, what modification have you done to udc-core.c which broke this ? udc-core *always* calls ->udc_start() by the time you load a gadget driver so this case will *never* happen. Whatever modification you did, broke this assumption and I will *not* accept this patch because the bug is elsewhere and *not* in mainline kernel.

It's found in Android using kernel 3.10.20. Android has its own usb_composite_driver usb/gadget/android.c (not in mainline), and it allows userspace to disconnect the pullup (i.e clear run/stop bit in dwc3) and remove the gadget functions like adb, mtp and then add new functions like rndis, acm. The problem is when you disconnect the pullup, a gadget maybe in the middle of queuing a request, and result in the "start transfer cmd failure". I think this is also a common issue for other usb_composite_drivers too. Normally, if one of the gadget deactivate its own function, the pullup will be disconnected, other gadgets won't get notified until their requests are failed. So it makes dwc3 more robust to deal with these situations.

Quoted 20 lines
Quoted 20 lines
---
 drivers/usb/dwc3/gadget.c |    4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)
drivers/usb/dwc3/gadget.c +1 -3
index 70715ee..8d0c3c7 100644
@@ -1000,9 +1000,7 @@ static int __dwc3_gadget_kick_transfer(struct dwc3_ep *dep, u16 cmd_param,
 		 * here and stop, unmap, free and del each of the linked
 		 * requests instead of what we do now.
 		 */
-		usb_gadget_unmap_request(&dwc->gadget, &req->request,
-				req->direction);
-		list_del(&req->list);
+		dwc3_gadget_giveback(dep, req, -ESHUTDOWN);
 		return ret;
 	}
 
Quoted 3 lines
Quoted 3 lines
Signature · 1 line
1.7.9.5

Jincan

#3 lore raw

Hi,

Quoted 11 lines · Zhuang Jin Can
Quoted 10 lines · Felipe Balbi
Quoted 6 lines · Zhuang Jin Can

At least we should giveback the current request to the gadget. Otherwise, the gadget will be stuck without knowing anything.

It was oberved that the failure can happen if the request is queued when the run/stop bit of controller is not set.

why is your gadget queueing any requests before calling ->udc_start() ?

Quoted 8 lines
Quoted 6 lines

A better question, what modification have you done to udc-core.c which broke this ? udc-core *always* calls ->udc_start() by the time you load a gadget driver so this case will *never* happen. Whatever modification you did, broke this assumption and I will *not* accept this patch because the bug is elsewhere and *not* in mainline kernel.

It's found in Android using kernel 3.10.20. Android has its own usb_composite_driver usb/gadget/android.c (not in mainline), and it

so you found something on an old kernel using an out-of-tree gadget driver.

Quoted 5 lines

allows userspace to disconnect the pullup (i.e clear run/stop bit in dwc3) and remove the gadget functions like adb, mtp and then add new functions like rndis, acm. The problem is when you disconnect the pullup, a gadget maybe in the middle of queuing a request, and result in the "start transfer cmd failure". I think this is also a common issue for other

Android gadget needs to learn how to cope with that.

Quoted 4 lines

usb_composite_drivers too. Normally, if one of the gadget deactivate its own function, the pullup will be disconnected, other gadgets won't get notified until their requests are failed. So it makes dwc3 more robust to deal with these situations.

Right, but Android gadget can run on top of several other UDCs and you want to have a single one of them cope with android's bug ?

You'd be better off getting google to accept a bugfix to the android gadget, since that's where the problem lies.

Signature · 1 line
balbi
#4 lore raw

Hi,

Quoted 24 lines · Felipe Balbi
Quoted 11 lines · Zhuang Jin Can
Quoted 10 lines · Felipe Balbi
Quoted 6 lines · Zhuang Jin Can

At least we should giveback the current request to the gadget. Otherwise, the gadget will be stuck without knowing anything.

It was oberved that the failure can happen if the request is queued when the run/stop bit of controller is not set.

why is your gadget queueing any requests before calling ->udc_start() ?

Quoted 8 lines
Quoted 6 lines

A better question, what modification have you done to udc-core.c which broke this ? udc-core *always* calls ->udc_start() by the time you load a gadget driver so this case will *never* happen. Whatever modification you did, broke this assumption and I will *not* accept this patch because the bug is elsewhere and *not* in mainline kernel.

It's found in Android using kernel 3.10.20. Android has its own usb_composite_driver usb/gadget/android.c (not in mainline), and it

so you found something on an old kernel using an out-of-tree gadget driver.

Quoted 8 lines
Quoted 5 lines

allows userspace to disconnect the pullup (i.e clear run/stop bit in dwc3) and remove the gadget functions like adb, mtp and then add new functions like rndis, acm. The problem is when you disconnect the pullup, a gadget maybe in the middle of queuing a request, and result in the "start transfer cmd failure". I think this is also a common issue for other

Android gadget needs to learn how to cope with that.

Agree.

Quoted 11 lines
Quoted 4 lines

usb_composite_drivers too. Normally, if one of the gadget deactivate its own function, the pullup will be disconnected, other gadgets won't get notified until their requests are failed. So it makes dwc3 more robust to deal with these situations.

Right, but Android gadget can run on top of several other UDCs and you want to have a single one of them cope with android's bug ?

You'd be better off getting google to accept a bugfix to the android gadget, since that's where the problem lies.

I agree. I'll try to push the fix to google.
It's really hard to fix the race condition (for me), as any gadget or /sys/class/udc/soft_connect can just disconnect the pullup anytime they want. The only thing I can do is giving back the request to the gadget if the condition happens.

Jincan

#5 lore raw

Hi,

Quoted 40 lines · Zhuang Jin Can
Quoted 24 lines · Felipe Balbi
Quoted 11 lines · Zhuang Jin Can
Quoted 10 lines · Felipe Balbi
Quoted 6 lines · Zhuang Jin Can

At least we should giveback the current request to the gadget. Otherwise, the gadget will be stuck without knowing anything.

It was oberved that the failure can happen if the request is queued when the run/stop bit of controller is not set.

why is your gadget queueing any requests before calling ->udc_start() ?

Quoted 8 lines
Quoted 6 lines

A better question, what modification have you done to udc-core.c which broke this ? udc-core *always* calls ->udc_start() by the time you load a gadget driver so this case will *never* happen. Whatever modification you did, broke this assumption and I will *not* accept this patch because the bug is elsewhere and *not* in mainline kernel.

It's found in Android using kernel 3.10.20. Android has its own usb_composite_driver usb/gadget/android.c (not in mainline), and it

so you found something on an old kernel using an out-of-tree gadget driver.

Quoted 8 lines
Quoted 5 lines

allows userspace to disconnect the pullup (i.e clear run/stop bit in dwc3) and remove the gadget functions like adb, mtp and then add new functions like rndis, acm. The problem is when you disconnect the pullup, a gadget maybe in the middle of queuing a request, and result in the "start transfer cmd failure". I think this is also a common issue for other

Android gadget needs to learn how to cope with that.

Agree.

Quoted 5 lines
Quoted 4 lines

usb_composite_drivers too. Normally, if one of the gadget deactivate its own function, the pullup will be disconnected, other gadgets won't get notified until their requests are failed. So it makes dwc3 more robust to deal with these situations.

Quoted 7 lines
Quoted 6 lines

Right, but Android gadget can run on top of several other UDCs and you want to have a single one of them cope with android's bug ?

You'd be better off getting google to accept a bugfix to the android gadget, since that's where the problem lies.

I agree. I'll try to push the fix to google.

alright, thanks

Quoted 4 lines

It's really hard to fix the race condition (for me), as any gadget or /sys/class/udc/soft_connect can just disconnect the pullup anytime they want. The only thing I can do is giving back the request to the gadget if the condition happens.

even in that case, gadget driver's ->disconnect() will be called and that should be enough to tell the gadget driver 'hey, don't queue anything right now because you're not talking to any host'.

cheers

Signature · 1 line
balbi