Commit 6bbf87a1 authored by Pawel Laszczak's avatar Pawel Laszczak Committed by Felipe Balbi

usb:cdns3 Fix for stuck packets in on-chip OUT buffer.

Controller for OUT endpoints has shared on-chip buffers for all incoming
packets, including ep0out. It's FIFO buffer, so packets must be handled
by DMA in correct order. If the first packet in the buffer will not be
handled, then the following packets directed for other endpoints and
functions will be blocked.

Additionally the packets directed to one endpoint can block entire on-chip
buffers. In this case transfer to other endpoints also will blocked.

To resolve this issue after raising the descriptor missing interrupt
driver prepares internal usb_request object and use it to arm DMA
transfer.

The problematic situation was observed in case when endpoint has
been enabled but no usb_request were queued. Driver try detects
such endpoints and will use this workaround only for these endpoint.

Driver use limited number of buffer. This number can be set by macro
CDNS_WA2_NUM_BUFFERS.

Such blocking situation was observed on ACM gadget. For this function
host send OUT data packet but ACM function is not prepared for
this packet. It's cause that buffer placed in on chip memory block
transfer to other endpoints.

Issue has been fixed for DEV_VER_V2 version of controller.
Signed-off-by: default avatarPawel Laszczak <pawell@cadence.com>
Signed-off-by: default avatarFelipe Balbi <felipe.balbi@linux.intel.com>
parent 7733f6c3
This diff is collapsed.
...@@ -1083,6 +1083,7 @@ struct cdns3_trb { ...@@ -1083,6 +1083,7 @@ struct cdns3_trb {
#define CDNS3_EP_ISO_SS_BURST 3 #define CDNS3_EP_ISO_SS_BURST 3
#define CDNS3_MAX_NUM_DESCMISS_BUF 32 #define CDNS3_MAX_NUM_DESCMISS_BUF 32
#define CDNS3_DESCMIS_BUF_SIZE 2048 /* Bytes */ #define CDNS3_DESCMIS_BUF_SIZE 2048 /* Bytes */
#define CDNS3_WA2_NUM_BUFFERS 128
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
/* Used structs */ /* Used structs */
...@@ -1093,11 +1094,15 @@ struct cdns3_device; ...@@ -1093,11 +1094,15 @@ struct cdns3_device;
* @endpoint: usb endpoint * @endpoint: usb endpoint
* @pending_req_list: list of requests queuing on transfer ring. * @pending_req_list: list of requests queuing on transfer ring.
* @deferred_req_list: list of requests waiting for queuing on transfer ring. * @deferred_req_list: list of requests waiting for queuing on transfer ring.
* @wa2_descmiss_req_list: list of requests internally allocated by driver.
* @trb_pool: transfer ring - array of transaction buffers * @trb_pool: transfer ring - array of transaction buffers
* @trb_pool_dma: dma address of transfer ring * @trb_pool_dma: dma address of transfer ring
* @cdns3_dev: device associated with this endpoint * @cdns3_dev: device associated with this endpoint
* @name: a human readable name e.g. ep1out * @name: a human readable name e.g. ep1out
* @flags: specify the current state of endpoint * @flags: specify the current state of endpoint
* @descmis_req: internal transfer object used for getting data from on-chip
* buffer. It can happen only if function driver doesn't send usb_request
* object on time.
* @dir: endpoint direction * @dir: endpoint direction
* @num: endpoint number (1 - 15) * @num: endpoint number (1 - 15)
* @type: set to bmAttributes & USB_ENDPOINT_XFERTYPE_MASK * @type: set to bmAttributes & USB_ENDPOINT_XFERTYPE_MASK
...@@ -1114,6 +1119,8 @@ struct cdns3_endpoint { ...@@ -1114,6 +1119,8 @@ struct cdns3_endpoint {
struct usb_ep endpoint; struct usb_ep endpoint;
struct list_head pending_req_list; struct list_head pending_req_list;
struct list_head deferred_req_list; struct list_head deferred_req_list;
struct list_head wa2_descmiss_req_list;
int wa2_counter;
struct cdns3_trb *trb_pool; struct cdns3_trb *trb_pool;
dma_addr_t trb_pool_dma; dma_addr_t trb_pool_dma;
...@@ -1132,8 +1139,13 @@ struct cdns3_endpoint { ...@@ -1132,8 +1139,13 @@ struct cdns3_endpoint {
#define EP_CLAIMED BIT(8) #define EP_CLAIMED BIT(8)
#define EP_DEFERRED_DRDY BIT(9) #define EP_DEFERRED_DRDY BIT(9)
#define EP_QUIRK_ISO_OUT_EN BIT(10) #define EP_QUIRK_ISO_OUT_EN BIT(10)
#define EP_QUIRK_END_TRANSFER BIT(11)
#define EP_QUIRK_EXTRA_BUF_DET BIT(12)
#define EP_QUIRK_EXTRA_BUF_EN BIT(13)
u32 flags; u32 flags;
struct cdns3_request *descmis_req;
u8 dir; u8 dir;
u8 num; u8 num;
u8 type; u8 type;
...@@ -1181,6 +1193,7 @@ struct cdns3_aligned_buf { ...@@ -1181,6 +1193,7 @@ struct cdns3_aligned_buf {
* @aligned_buf: object holds information about aligned buffer associated whit * @aligned_buf: object holds information about aligned buffer associated whit
* this endpoint * this endpoint
* @flags: flag specifying special usage of request * @flags: flag specifying special usage of request
* @list: used by internally allocated request to add to wa2_descmiss_req_list.
*/ */
struct cdns3_request { struct cdns3_request {
struct usb_request request; struct usb_request request;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment