summaryrefslogtreecommitdiff
path: root/drivers/usb/dwc3/gadget.c
AgeCommit message (Collapse)Author
2018-05-21usb: dwc3: gadget: Fix list_del corruption in dwc3_ep_dequeueMayank Rana
dwc3_ep_dequeue() waits for completion of End Transfer command using wait_event_lock_irq(), which will release the dwc3->lock while waiting and reacquire after completion. This allows a potential race condition with ep_disable() which also removes all requests from started_list and pending_list. The check for NULL r->trb should catch this but currently it exits to the wrong 'out1' label which calls dwc3_gadget_giveback(). Since its list entry was already removed, if CONFIG_DEBUG_LIST is enabled a 'list_del corruption' bug is thrown since its next/prev pointers are already LIST_POISON1/2. If r->trb is NULL it should simply exit to 'out0'. Fixes: cf3113d893d4 ("usb: dwc3: gadget: properly increment dequeue pointer on ep_dequeue") Cc: stable@vger.kernel.org # v4.12+ Signed-off-by: Mayank Rana <mrana@codeaurora.org> Signed-off-by: Jack Pham <jackp@codeaurora.org> Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
2018-05-21usb: dwc3: gadget: dwc3_gadget_del_and_unmap_request() can be staticWei Yongjun
Fixes the following sparse warning: drivers/usb/dwc3/gadget.c:169:6: warning: symbol 'dwc3_gadget_del_and_unmap_request' was not declared. Should it be static? Signed-off-by: Wei Yongjun <weiyongjun1@huawei.com> Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
2018-05-21usb: dwc3: gadget: init req->{direction,epnum} from alloc_request()Felipe Balbi
We dont' need to touch req->direction or req->epnum from ep_queue(). It's enough that we initialize both fields from alloc_request() and just keep them for the entire lifetime of the request. No functional changes. Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
2018-05-21usb: dwc3: gadget: initialize transfer index from send_gadget_ep_cmd()Felipe Balbi
Instead of *always* calling dwc3_gadget_ep_get_transfer_index() after sending a Start Transfer command, we can call it once from dwc3_send_gadget_ep_cmd() itself. Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
2018-05-21usb: dwc3: gadget: assign resource_index inside get_transfer_index()Felipe Balbi
Instead of returning resource index number just to assign it to a field inside 'dep' which was passed as argument, we can assing dep->resource_index from inside dwc3_gadget_ep_get_transfer_index() itself. Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
2018-05-21usb: dwc3: gadget: always start isochronous aligned to dep->intervalFelipe Balbi
We will *always* start transfer to the next uFrame number aligned to dep->interval. Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
2018-05-21usb: dwc3: gadget: don't issue End Transfer if we have started reqsFelipe Balbi
In case we have many started requests and one of them in the middle is completed with Missed Isoc, let's not End Transfer as that would result in us loosing (possibly) many more intervals. Instead, let's allow the controller to go through its list of started requests. Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
2018-05-21usb: dwc3: gadget: move dwc3_calc_trbs_left() in place of prototypeFelipe Balbi
Avoid a prototype when the function can be defined earlier. No functional changes, cleanup only. Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
2018-05-21usb: dwc3: gadget: move set_xfer_resource() in place of prototypeFelipe Balbi
Instead of having a prototype for a function that's defined a few lines down, let's just move definition to the place where prototype was. No functional changes, cleanup only. Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
2018-05-21usb: dwc3: gadget: remove a few more dwc argumentsFelipe Balbi
In a few places, the argument is completely unnecessary. On places where it's needed, we can get it from dep->dwc. Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
2018-05-21usb: dwc3: gadget: combine modify & restore into single argumentFelipe Balbi
Those two arguments refer to a single bitfield in the register. In order to simplify the code, we can combine them into a single argument and expect caller to pass the correct action argument at all times. Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
2018-05-21usb: dwc3: gadget: refactor dwc3_gadget_init_endpoints()Felipe Balbi
This just makes it slightly easier to read. No functional changes. Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
2018-05-21usb: dwc3: gadget: split dwc3_gadget_ep_cleanup_completed_requests()Felipe Balbi
No functional changes, it just makes the code slightly easier to read. Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
2018-05-21usb: dwc3: gadget: get rid of the length variableFelipe Balbi
Code is just as readable without it. Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
2018-05-21usb: dwc3: gadget: reduce scope of ret variableFelipe Balbi
We can declare it inside list_for_each_entry_safe() loop and reduce its scope. Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
2018-05-21usb: dwc3: gadget: one declaration per lineFelipe Balbi
Misc cleanup. No functional changes. Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
2018-05-21usb: dwc3: gadget: simplify IOC handlingFelipe Balbi
We will only have event status of IOC when IOC bit is set in TRB. There's no need to check both bits. Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
2018-05-21usb: dwc3: gadget: simplify short packet eventFelipe Balbi
We know that only OUT endpoints can trigger SHORT. We also know that count MUST be > 0 whenever SHORT triggers. Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
2018-05-21usb: dwc3: gadget: simplify unaligned and zlp handlingFelipe Balbi
We can just call reclaim_trb_linear instead of reimplementing it. Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
2018-05-21usb: dwc3: gadget: remove unnecessary 'chain' variableFelipe Balbi
Minor cleanup, no functional changes. Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
2018-05-21usb: dwc3: gadget: remove PENDING handling from cleanup_completedFelipe Balbi
We are trying to kick transfers on Isochronous endpoints in a more controlled manner now. And this ended up rendering this piece of code unnecessary. Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
2018-05-21usb: dwc3: gadget: split scatterlist and linear handlersFelipe Balbi
instead of having one big loop, let's split it down into two smaller handlers: one for linear buffers and one for scatterlist. Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
2018-05-21usb: dwc3: gadget: simplify isoc case on cleanup_completed_requestsFelipe Balbi
Just a minor simplification, no functional changes. Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
2018-05-21usb: dwc3: gadget: simplify queueing of isoc transfersFelipe Balbi
After all the previous changes, it's now a lot clearer how isoc transfers should be managed. We don't need to try to End Transfers from ep_queue since that's already done by cleanup_requests. Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
2018-05-21usb: dwc3: gadget: remove duplicated missed isoc handlingFelipe Balbi
Now, this part of the code is duplicated and brings no extra value to the driver. Let's remove it. Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
2018-05-21usb: dwc3: gadget: check for Missed Isoc from event statusFelipe Balbi
In case we get an event with status set to Missed Isoc, this means we have missed an isochronous interval and should issue End Transfer command and wait for the following XferNotReady. Let's do that early, rather than late. Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
2018-05-21usb: dwc3: gadget: remove unnecessary 'ioc' variableFelipe Balbi
It's only written to, never read. We can remove it now. Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
2018-05-21usb: dwc3: gadget: make cleanup_completed_requests() return nothingFelipe Balbi
We don't need to return a value anymore here. Let's remove it. Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
2018-05-21usb: dwc3: gadget: remove DWC3_EP_BUSY flagFelipe Balbi
It has no use anymore. Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
2018-05-21usb: dwc3: gadget: start removing BUSY flagFelipe Balbi
By now, it has the same semantics as DWC3_EP_TRANSFER_STARTED, but that has a much more descriptive name. Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
2018-05-21usb: dwc3: gadget: update dep->frame_number from XferInprogress tooFelipe Balbi
We will need an up-to-date frame_number from XferInProgress too when future patches improve our handling of Isoc endpoints. Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
2018-05-21usb: dwc3: gadget: always use frame number from XferNotReadyFelipe Balbi
The core requires the extra two bits of information for properly scheduling Isochronous transfers. This means that we can't rely on __dwc3_gadget_get_frame(). Let's always cache uFrame number from XferNotReady instead. Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
2018-05-21usb: dwc3: gadget: remove unnecessary 'dwc' parameterFelipe Balbi
Endpoint handlers need to know about endpoints, not dwc. If they really need access to dwc (e.g. for printing error messages) we have a reference to it tucked inside the endpoint. This patch has no functional changes, it's simply moving things around. Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
2018-05-21usb: dwc3: gadget: move handler closer to calling siteFelipe Balbi
Cleanup only, no functional changes. Just making code easier to follow. Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
2018-05-21usb: dwc3: gadget: rename dwc3_gadget_start_isoc()Felipe Balbi
Cleanup only, no functional changes. This just matches the event name with its handler. Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
2018-05-21usb: dwc3: gadget: remove some pointless checksFelipe Balbi
We *KNOW* which events we enable for which endpoint types and we *KNOW* when they'll trigger. The endpoint type checks are pointless. Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
2018-05-21usb: dwc3: gadget: remove allocated/queued request trackingFelipe Balbi
That has never proven useful in any way. Just remove it. Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
2018-05-21usb: dwc3: gadget: rename done_trbs and done_reqsFelipe Balbi
This patch simply renames two functions to more descriptive names so that it's easier to understand what they're doing. Cleanup only, no functional changes. Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
2018-05-21usb: dwc3: gadget: don't kick transfer all the timeFelipe Balbi
Instead of constantly calling kick transfer everything some event shows up, let's just rely on the fact that we send Update Transfer every time a new request is queued. Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
2018-05-21usb: dwc3: gadget: rename dwc3_endpoint_transfer_complete()Felipe Balbi
Now that we're making sure we don't have XferComplete events, we can rename this function to what it actually handles: dwc3_gadget_endpoint_transfer_in_progress() Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
2018-05-21usb: dwc3: gadget: XferComplete only for EP0Felipe Balbi
XferComplete is enabled only for the default control pipe, let's make that clear in the code. Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
2018-05-21usb: dwc3: gadget: XferNotReady is Isoc-onlyFelipe Balbi
We don't use XferNotReady for anything other than Default Control Pipe, which is handled in ep0.c, and Isochronous endpoints. Let's make that clear in the code. Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
2018-05-21usb: dwc3: gadget: pre-issue Start Transfer for Interrupt EPs tooFelipe Balbi
Interrupt endpoints behave much like Bulk endpoints with the exception that they are periodic. We can pre-issue Start Transfer exactly as we do for Bulk endpoints. While at that, remove one trailing blank line which is unnecessary. Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
2018-05-21usb: dwc3: gadget: Correct the logic for queuing sgsAnurag Kumar Vulisha
The present code correctly fetches the req which were previously not queued from the started_list but fails to continue queuing from the sg where it previously stopped queuing (because of the unavailable TRB's). This patch correct's the code to continue queuing from the correct sg present in the sglist. For example, consider 5 sgs in req. Because of limited TRB's among the 5 sgs only 3 got queued. This patch corrects the code to start queuing from correct sg i.e 4th sg when the TRBs are available. Signed-off-by: Anurag Kumar Vulisha <anuragku@xilinx.com> Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
2018-05-21usb: dwc3: gadget: Correct handling of scattergather listsAnurag Kumar Vulisha
The code logic in dwc3_prepare_one_trb() incorrectly uses the address and length fields present in req packet for mapping TRB's instead of using the address and length fields of scattergather lists. This patch correct's the code to use sg->address and sg->length when scattergather lists are present. Signed-off-by: Anurag Kumar Vulisha <anuragku@xilinx.com> Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
2018-03-26usb: dwc3: gadget: never call ->complete() from ->ep_queue()Felipe Balbi
This is a requirement which has always existed but, somehow, wasn't reflected in the documentation and problems weren't found until now when Tuba Yavuz found a possible deadlock happening between dwc3 and f_hid. She described the situation as follows: spin_lock_irqsave(&hidg->write_spinlock, flags); // first acquire /* we our function has been disabled by host */ if (!hidg->req) { free_ep_req(hidg->in_ep, hidg->req); goto try_again; } [...] status = usb_ep_queue(hidg->in_ep, hidg->req, GFP_ATOMIC); => [...] => usb_gadget_giveback_request => f_hidg_req_complete => spin_lock_irqsave(&hidg->write_spinlock, flags); // second acquire Note that this happens because dwc3 would call ->complete() on a failed usb_ep_queue() due to failed Start Transfer command. This is, anyway, a theoretical situation because dwc3 currently uses "No Response Update Transfer" command for Bulk and Interrupt endpoints. It's still good to make this case impossible to happen even if the "No Reponse Update Transfer" command is changed. Reported-by: Tuba Yavuz <tuba@ece.ufl.edu> Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com> Cc: stable <stable@vger.kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2018-03-22usb: dwc3: Check controller type before setting speedThinh Nguyen
DWC_usb3 speed can only be set up to SuperSpeed. Limit the setting to SuperSpeed only should the value be higher. Otherwise, the controller will read an invalid speed value and set the device to an incorrect speed. Signed-off-by: Thinh Nguyen <thinhn@synopsys.com> Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
2018-03-22usb: dwc3: gadget: Check IP revision for GRXTHRCFGThinh Nguyen
DWC_usb31 controller has a different UsbRxPktCnt bit fields from GRXTHRCFG register. Check for DWC_usb31 IP revision to read the appropriate value. Signed-off-by: Thinh Nguyen <thinhn@synopsys.com> Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
2018-03-22usb: dwc3: Check IP revision for GTXFIFOSIZThinh Nguyen
DWC_usb31 controller has different GTXFIFOSIZE bit field for TXFDEF. Check for DWC_usb31 IP revision to read the appropriate bit fields. Signed-off-by: Thinh Nguyen <thinhn@synopsys.com> Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
2018-03-13usb: dwc3: Prevent indefinite sleep in _dwc3_set_mode during suspend/resumeRoger Quadros
In the following test we get stuck by sleeping forever in _dwc3_set_mode() after which dual-role switching doesn't work. On dra7-evm's dual-role port, - Load g_zero gadget driver and enumerate to host - suspend to mem - disconnect USB cable to host and connect otg cable with Pen drive in it. - resume system - we sleep indefinitely in _dwc3_set_mode due to. dwc3_gadget_exit()->usb_del_gadget_udc()->udc_stop()-> dwc3_gadget_stop()->wait_event_lock_irq() To fix this instead of waiting indefinitely with wait_event_lock_irq() we use wait_event_interruptible_lock_irq_timeout() and print and error message if there was a timeout. Signed-off-by: Roger Quadros <rogerq@ti.com> Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>