aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrzej Pietrasiewicz <andrzej.p@collabora.com>2019-04-01 06:50:45 -0400
committerFelipe Balbi <felipe.balbi@linux.intel.com>2019-06-06 06:51:57 -0400
commit066cfd0770aba8a9ac79b59d99530653885d919d (patch)
tree5aaba57969f52b5424fb50db399615b99bb59bc6
parent4faf3b36553a0a5304f58ee3a620e659739a2e20 (diff)
usb: gadget: dwc2: fix zlp handling
The patch 10209abe87f5ebfd482a00323f5236d6094d0865 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: 10209abe87f5 (usb: dwc2: gadget: Add scatter-gather mode) Acked-by: Minas Harutyunyan <hminas@synopsys.com> Signed-off-by: Andrzej Pietrasiewicz <andrzej.p@collabora.com> Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
-rw-r--r--drivers/usb/dwc2/gadget.c20
1 files changed, 12 insertions, 8 deletions
diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
index 1d4aef8d4137..bff48a8a1984 100644
--- a/drivers/usb/dwc2/gadget.c
+++ b/drivers/usb/dwc2/gadget.c
@@ -835,19 +835,22 @@ static void dwc2_gadget_fill_nonisoc_xfer_ddma_one(struct dwc2_hsotg_ep *hs_ep,
835 * with corresponding information based on transfer data. 835 * with corresponding information based on transfer data.
836 */ 836 */
837static void dwc2_gadget_config_nonisoc_xfer_ddma(struct dwc2_hsotg_ep *hs_ep, 837static void dwc2_gadget_config_nonisoc_xfer_ddma(struct dwc2_hsotg_ep *hs_ep,
838 struct usb_request *ureq, 838 dma_addr_t dma_buff,
839 unsigned int offset,
840 unsigned int len) 839 unsigned int len)
841{ 840{
841 struct usb_request *ureq = NULL;
842 struct dwc2_dma_desc *desc = hs_ep->desc_list; 842 struct dwc2_dma_desc *desc = hs_ep->desc_list;
843 struct scatterlist *sg; 843 struct scatterlist *sg;
844 int i; 844 int i;
845 u8 desc_count = 0; 845 u8 desc_count = 0;
846 846
847 if (hs_ep->req)
848 ureq = &hs_ep->req->req;
849
847 /* non-DMA sg buffer */ 850 /* non-DMA sg buffer */
848 if (!ureq->num_sgs) { 851 if (!ureq || !ureq->num_sgs) {
849 dwc2_gadget_fill_nonisoc_xfer_ddma_one(hs_ep, &desc, 852 dwc2_gadget_fill_nonisoc_xfer_ddma_one(hs_ep, &desc,
850 ureq->dma + offset, len, true); 853 dma_buff, len, true);
851 return; 854 return;
852 } 855 }
853 856
@@ -1135,7 +1138,7 @@ static void dwc2_hsotg_start_req(struct dwc2_hsotg *hsotg,
1135 offset = ureq->actual; 1138 offset = ureq->actual;
1136 1139
1137 /* Fill DDMA chain entries */ 1140 /* Fill DDMA chain entries */
1138 dwc2_gadget_config_nonisoc_xfer_ddma(hs_ep, ureq, offset, 1141 dwc2_gadget_config_nonisoc_xfer_ddma(hs_ep, ureq->dma + offset,
1139 length); 1142 length);
1140 1143
1141 /* write descriptor chain address to control register */ 1144 /* write descriptor chain address to control register */
@@ -2037,12 +2040,13 @@ static void dwc2_hsotg_program_zlp(struct dwc2_hsotg *hsotg,
2037 dev_dbg(hsotg->dev, "Receiving zero-length packet on ep%d\n", 2040 dev_dbg(hsotg->dev, "Receiving zero-length packet on ep%d\n",
2038 index); 2041 index);
2039 if (using_desc_dma(hsotg)) { 2042 if (using_desc_dma(hsotg)) {
2043 /* Not specific buffer needed for ep0 ZLP */
2044 dma_addr_t dma = hs_ep->desc_list_dma;
2045
2040 if (!index) 2046 if (!index)
2041 dwc2_gadget_set_ep0_desc_chain(hsotg, hs_ep); 2047 dwc2_gadget_set_ep0_desc_chain(hsotg, hs_ep);
2042 2048
2043 /* Not specific buffer needed for ep0 ZLP */ 2049 dwc2_gadget_config_nonisoc_xfer_ddma(hs_ep, dma, 0);
2044 dwc2_gadget_fill_nonisoc_xfer_ddma_one(hs_ep, &hs_ep->desc_list,
2045 hs_ep->desc_list_dma, 0, true);
2046 } else { 2050 } else {
2047 dwc2_writel(hsotg, DXEPTSIZ_MC(1) | DXEPTSIZ_PKTCNT(1) | 2051 dwc2_writel(hsotg, DXEPTSIZ_MC(1) | DXEPTSIZ_PKTCNT(1) |
2048 DXEPTSIZ_XFERSIZE(0), 2052 DXEPTSIZ_XFERSIZE(0),