diff mbox series

usb: gadget: dwc2: fix zlp handling

Message ID 20190401105045.6527-1-andrzej.p@collabora.com (mailing list archive)
State Mainlined
Commit 066cfd0770aba8a9ac79b59d99530653885d919d
Headers show
Series usb: gadget: dwc2: fix zlp handling | expand

Commit Message

Andrzej Pietrasiewicz April 1, 2019, 10:50 a.m. UTC
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)
Signed-off-by: Andrzej Pietrasiewicz <andrzej.p@collabora.com>
---
 drivers/usb/dwc2/gadget.c | 20 ++++++++++++--------
 1 file changed, 12 insertions(+), 8 deletions(-)

Comments

Minas Harutyunyan April 1, 2019, 11:33 a.m. UTC | #1
On 4/1/2019 2:51 PM, Andrzej Pietrasiewicz wrote:
> 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)
> Signed-off-by: Andrzej Pietrasiewicz <andrzej.p@collabora.com>

Acked-by: Minas Harutyunyan <hminas@synopsys.com>

> ---
>   drivers/usb/dwc2/gadget.c | 20 ++++++++++++--------
>   1 file changed, 12 insertions(+), 8 deletions(-)
> 
> diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
> index 6812a8a3a98b..e76b2e040b4c 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,
>    * with corresponding information based on transfer data.
>    */
>   static void dwc2_gadget_config_nonisoc_xfer_ddma(struct dwc2_hsotg_ep *hs_ep,
> -						 struct usb_request *ureq,
> -						 unsigned int offset,
> +						 dma_addr_t dma_buff,
>   						 unsigned int len)
>   {
> +	struct usb_request *ureq = NULL;
>   	struct dwc2_dma_desc *desc = hs_ep->desc_list;
>   	struct scatterlist *sg;
>   	int i;
>   	u8 desc_count = 0;
>   
> +	if (hs_ep->req)
> +		ureq = &hs_ep->req->req;
> +
>   	/* non-DMA sg buffer */
> -	if (!ureq->num_sgs) {
> +	if (!ureq || !ureq->num_sgs) {
>   		dwc2_gadget_fill_nonisoc_xfer_ddma_one(hs_ep, &desc,
> -			ureq->dma + offset, len, true);
> +			dma_buff, len, true);
>   		return;
>   	}
>   
> @@ -1135,7 +1138,7 @@ static void dwc2_hsotg_start_req(struct dwc2_hsotg *hsotg,
>   			offset = ureq->actual;
>   
>   		/* 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);
>   
>   		/* write descriptor chain address to control register */
> @@ -2028,12 +2031,13 @@ static void dwc2_hsotg_program_zlp(struct dwc2_hsotg *hsotg,
>   		dev_dbg(hsotg->dev, "Receiving zero-length packet on ep%d\n",
>   			index);
>   	if (using_desc_dma(hsotg)) {
> +		/* Not specific buffer needed for ep0 ZLP */
> +		dma_addr_t dma = hs_ep->desc_list_dma;
> +
>   		if (!index)
>   			dwc2_gadget_set_ep0_desc_chain(hsotg, hs_ep);
>   
> -		/* Not specific buffer needed for ep0 ZLP */
> -		dwc2_gadget_fill_nonisoc_xfer_ddma_one(hs_ep, &hs_ep->desc_list,
> -			hs_ep->desc_list_dma, 0, true);
> +		dwc2_gadget_config_nonisoc_xfer_ddma(hs_ep, dma, 0);
>   	} else {
>   		dwc2_writel(hsotg, DXEPTSIZ_MC(1) | DXEPTSIZ_PKTCNT(1) |
>   			    DXEPTSIZ_XFERSIZE(0),
>
Minas Harutyunyan April 30, 2019, 6:39 a.m. UTC | #2
Hi Felipe,

On 4/1/2019 3:33 PM, Minas Harutyunyan wrote:
> On 4/1/2019 2:51 PM, Andrzej Pietrasiewicz wrote:
>> 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)
>> Signed-off-by: Andrzej Pietrasiewicz <andrzej.p@collabora.com>
> 
> Acked-by: Minas Harutyunyan <hminas@synopsys.com>
> 
>> ---
>>    drivers/usb/dwc2/gadget.c | 20 ++++++++++++--------
>>    1 file changed, 12 insertions(+), 8 deletions(-)
>>
>> diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
>> index 6812a8a3a98b..e76b2e040b4c 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,
>>     * with corresponding information based on transfer data.
>>     */
>>    static void dwc2_gadget_config_nonisoc_xfer_ddma(struct dwc2_hsotg_ep *hs_ep,
>> -						 struct usb_request *ureq,
>> -						 unsigned int offset,
>> +						 dma_addr_t dma_buff,
>>    						 unsigned int len)
>>    {
>> +	struct usb_request *ureq = NULL;
>>    	struct dwc2_dma_desc *desc = hs_ep->desc_list;
>>    	struct scatterlist *sg;
>>    	int i;
>>    	u8 desc_count = 0;
>>    
>> +	if (hs_ep->req)
>> +		ureq = &hs_ep->req->req;
>> +
>>    	/* non-DMA sg buffer */
>> -	if (!ureq->num_sgs) {
>> +	if (!ureq || !ureq->num_sgs) {
>>    		dwc2_gadget_fill_nonisoc_xfer_ddma_one(hs_ep, &desc,
>> -			ureq->dma + offset, len, true);
>> +			dma_buff, len, true);
>>    		return;
>>    	}
>>    
>> @@ -1135,7 +1138,7 @@ static void dwc2_hsotg_start_req(struct dwc2_hsotg *hsotg,
>>    			offset = ureq->actual;
>>    
>>    		/* 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);
>>    
>>    		/* write descriptor chain address to control register */
>> @@ -2028,12 +2031,13 @@ static void dwc2_hsotg_program_zlp(struct dwc2_hsotg *hsotg,
>>    		dev_dbg(hsotg->dev, "Receiving zero-length packet on ep%d\n",
>>    			index);
>>    	if (using_desc_dma(hsotg)) {
>> +		/* Not specific buffer needed for ep0 ZLP */
>> +		dma_addr_t dma = hs_ep->desc_list_dma;
>> +
>>    		if (!index)
>>    			dwc2_gadget_set_ep0_desc_chain(hsotg, hs_ep);
>>    
>> -		/* Not specific buffer needed for ep0 ZLP */
>> -		dwc2_gadget_fill_nonisoc_xfer_ddma_one(hs_ep, &hs_ep->desc_list,
>> -			hs_ep->desc_list_dma, 0, true);
>> +		dwc2_gadget_config_nonisoc_xfer_ddma(hs_ep, dma, 0);
>>    	} else {
>>    		dwc2_writel(hsotg, DXEPTSIZ_MC(1) | DXEPTSIZ_PKTCNT(1) |
>>    			    DXEPTSIZ_XFERSIZE(0),
>>
> 
> 

This patch is fix for "usb: dwc2: gadget: Add scatter-gather mode" patch 
to allow pass USB CV.
Could you please merge to your testing/next this patch also.

Thanks,
Minas
diff mbox series

Patch

diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
index 6812a8a3a98b..e76b2e040b4c 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,
  * with corresponding information based on transfer data.
  */
 static void dwc2_gadget_config_nonisoc_xfer_ddma(struct dwc2_hsotg_ep *hs_ep,
-						 struct usb_request *ureq,
-						 unsigned int offset,
+						 dma_addr_t dma_buff,
 						 unsigned int len)
 {
+	struct usb_request *ureq = NULL;
 	struct dwc2_dma_desc *desc = hs_ep->desc_list;
 	struct scatterlist *sg;
 	int i;
 	u8 desc_count = 0;
 
+	if (hs_ep->req)
+		ureq = &hs_ep->req->req;
+
 	/* non-DMA sg buffer */
-	if (!ureq->num_sgs) {
+	if (!ureq || !ureq->num_sgs) {
 		dwc2_gadget_fill_nonisoc_xfer_ddma_one(hs_ep, &desc,
-			ureq->dma + offset, len, true);
+			dma_buff, len, true);
 		return;
 	}
 
@@ -1135,7 +1138,7 @@  static void dwc2_hsotg_start_req(struct dwc2_hsotg *hsotg,
 			offset = ureq->actual;
 
 		/* 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);
 
 		/* write descriptor chain address to control register */
@@ -2028,12 +2031,13 @@  static void dwc2_hsotg_program_zlp(struct dwc2_hsotg *hsotg,
 		dev_dbg(hsotg->dev, "Receiving zero-length packet on ep%d\n",
 			index);
 	if (using_desc_dma(hsotg)) {
+		/* Not specific buffer needed for ep0 ZLP */
+		dma_addr_t dma = hs_ep->desc_list_dma;
+
 		if (!index)
 			dwc2_gadget_set_ep0_desc_chain(hsotg, hs_ep);
 
-		/* Not specific buffer needed for ep0 ZLP */
-		dwc2_gadget_fill_nonisoc_xfer_ddma_one(hs_ep, &hs_ep->desc_list,
-			hs_ep->desc_list_dma, 0, true);
+		dwc2_gadget_config_nonisoc_xfer_ddma(hs_ep, dma, 0);
 	} else {
 		dwc2_writel(hsotg, DXEPTSIZ_MC(1) | DXEPTSIZ_PKTCNT(1) |
 			    DXEPTSIZ_XFERSIZE(0),