Hello Paul and Alan,
21.01.2012 1:17, Paul Zimmerman:
On Fri, 20 Jan 2012, Alan Stern wrote:
This is a serious problem. The gadget API does not specify whether
usb_ep_enable and usb_ep_disable should be able to run in interrupt
context. Consequently we end up with UDC drivers like your DWC thing
in which the routines cannot run in interrupt context, together with
gadget drivers like g_serial which do call them in interrupt context.
It may be that the best solution is for the composite.c driver to
implement Set-Config and Set-Interface requests in a workqueue, so that
the calls could be made in process context. For now, you can avoid the
problem by not calling dma_alloc_coherent in your endpoint-setup
routine.
g_file_storage doesn't have this problem because it uses its own kernel
thread for handling these requests.
Actually, dma_alloc_coherent() takes a gfp_t parameter, so you should be
able to set GFP_ATOMIC and do the allocation from interrupt context.
The problem comes from dma_free_coherent(). It unconditionally checks for
being called in process context, and gives a warning if not. This check was
added a year or two ago, for something in the ARM architecture IIRC. I keep
expecting that this will get fixed at some point, but so far it hasn't.
Based on your comments I decided to move some preparations to a
workqueue and there are no issues with those allocations anymore.
I've now finally got g_serial fully recognised on another side (by host
PC) and was even able to open the respective serial device there, but
unfortunately for that to succeed I had to also disable (just throw
away) all requests for EPs != 0 (I did this in ep_queue in dwc driver,
if matters). Without that, controller starts raising "IN Token Received
with EP mismatch" instead of normal "Transfer complete" bit. If I
understand it correctly, this means that Tx FIFO happened to be filled
in some particular order that controller disliked (and refused). I've
also found a fragment of code with possibly relevant comment (quoted
below). Indeed, apparently this "EP mismatch" event is not handled
anywhere in the driver (other than providing a line for dmesg). If it
should, then I'd guess it means the driver is just plain unfininshed and
I have no idea if it can even be fixed with a reasonable effort. Not
sure what was meant exactly by "one endpoint at once" though.. Of course
usefull gadget drivers would probably employ > 1 EPs, even
g_file_storage does so? Strange thing.
Thank you.
Nikolai
/* Reactive the EP */
dwc_otg_ep_activate(GET_CORE_IF(pcd), &ep->dwc_ep);
if (ep->stopped) {
ep->stopped = 0;
/* If there is a request in the EP queue start it */
/** @todo FIXME: this causes an EP mismatch in DMA mode.
* epmismatch not yet implemented. */
/*
* Above fixme is solved by implmenting a tasklet to call the
* start_next_request(), outside of interrupt context at some
* time after the current time, after a clear-halt setup packet.
* Still need to implement ep mismatch in the future if a gadget
* ever uses more than one endpoint at once
*/
ep->queue_sof = 1;
tasklet_schedule (pcd->start_xfer_tasklet);
}
/* Start Control Status Phase */
do_setup_in_status_phase(pcd);
--
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