Commit 066cfd07 authored by Andrzej Pietrasiewicz's avatar Andrzej Pietrasiewicz Committed by Felipe Balbi

usb: gadget: dwc2: fix zlp handling

The patch 10209abe
usb: dwc2: gadget: Add scatter-gather mode

avoided a NULL pointer dereference (hs_ep->req == NULL) by
calling dwc2_gadget_fill_nonisoc_xfer_dma_one() directly instead of through
the dwc2_gadget_config_nonisoc_xfer_ddma() wrapper, which unconditionally
dereferenced the said pointer.

However, this was based on an incorrect assumption that in the context of
dwc2_hsotg_program_zlp() the pointer is always NULL, which is not the case.
The result were SB CV MSC tests failing starting from Test Case 6.

Instead, this patch reverts to calling the wrapper and adds a check for
the pointer being NULL inside the wrapper.

Fixes: 10209abe (usb: dwc2: gadget: Add scatter-gather mode)
Acked-by: default avatarMinas Harutyunyan <hminas@synopsys.com>
Signed-off-by: default avatarAndrzej Pietrasiewicz <andrzej.p@collabora.com>
Signed-off-by: default avatarFelipe Balbi <felipe.balbi@linux.intel.com>
parent 4faf3b36
...@@ -835,19 +835,22 @@ static void dwc2_gadget_fill_nonisoc_xfer_ddma_one(struct dwc2_hsotg_ep *hs_ep, ...@@ -835,19 +835,22 @@ static void dwc2_gadget_fill_nonisoc_xfer_ddma_one(struct dwc2_hsotg_ep *hs_ep,
* with corresponding information based on transfer data. * with corresponding information based on transfer data.
*/ */
static void dwc2_gadget_config_nonisoc_xfer_ddma(struct dwc2_hsotg_ep *hs_ep, static void dwc2_gadget_config_nonisoc_xfer_ddma(struct dwc2_hsotg_ep *hs_ep,
struct usb_request *ureq, dma_addr_t dma_buff,
unsigned int offset,
unsigned int len) unsigned int len)
{ {
struct usb_request *ureq = NULL;
struct dwc2_dma_desc *desc = hs_ep->desc_list; struct dwc2_dma_desc *desc = hs_ep->desc_list;
struct scatterlist *sg; struct scatterlist *sg;
int i; int i;
u8 desc_count = 0; u8 desc_count = 0;
if (hs_ep->req)
ureq = &hs_ep->req->req;
/* non-DMA sg buffer */ /* non-DMA sg buffer */
if (!ureq->num_sgs) { if (!ureq || !ureq->num_sgs) {
dwc2_gadget_fill_nonisoc_xfer_ddma_one(hs_ep, &desc, dwc2_gadget_fill_nonisoc_xfer_ddma_one(hs_ep, &desc,
ureq->dma + offset, len, true); dma_buff, len, true);
return; return;
} }
...@@ -1135,7 +1138,7 @@ static void dwc2_hsotg_start_req(struct dwc2_hsotg *hsotg, ...@@ -1135,7 +1138,7 @@ static void dwc2_hsotg_start_req(struct dwc2_hsotg *hsotg,
offset = ureq->actual; offset = ureq->actual;
/* Fill DDMA chain entries */ /* Fill DDMA chain entries */
dwc2_gadget_config_nonisoc_xfer_ddma(hs_ep, ureq, offset, dwc2_gadget_config_nonisoc_xfer_ddma(hs_ep, ureq->dma + offset,
length); length);
/* write descriptor chain address to control register */ /* write descriptor chain address to control register */
...@@ -2037,12 +2040,13 @@ static void dwc2_hsotg_program_zlp(struct dwc2_hsotg *hsotg, ...@@ -2037,12 +2040,13 @@ static void dwc2_hsotg_program_zlp(struct dwc2_hsotg *hsotg,
dev_dbg(hsotg->dev, "Receiving zero-length packet on ep%d\n", dev_dbg(hsotg->dev, "Receiving zero-length packet on ep%d\n",
index); index);
if (using_desc_dma(hsotg)) { if (using_desc_dma(hsotg)) {
/* Not specific buffer needed for ep0 ZLP */
dma_addr_t dma = hs_ep->desc_list_dma;
if (!index) if (!index)
dwc2_gadget_set_ep0_desc_chain(hsotg, hs_ep); dwc2_gadget_set_ep0_desc_chain(hsotg, hs_ep);
/* Not specific buffer needed for ep0 ZLP */ dwc2_gadget_config_nonisoc_xfer_ddma(hs_ep, dma, 0);
dwc2_gadget_fill_nonisoc_xfer_ddma_one(hs_ep, &hs_ep->desc_list,
hs_ep->desc_list_dma, 0, true);
} else { } else {
dwc2_writel(hsotg, DXEPTSIZ_MC(1) | DXEPTSIZ_PKTCNT(1) | dwc2_writel(hsotg, DXEPTSIZ_MC(1) | DXEPTSIZ_PKTCNT(1) |
DXEPTSIZ_XFERSIZE(0), DXEPTSIZ_XFERSIZE(0),
......
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