All of lore.kernel.org
 help / color / mirror / Atom feed
From: Peter Chen <peter.chen@freescale.com>
To: Li Yang <leoli@freescale.com>
Cc: gregkh@suse.de, linuxppc-dev@lists.ozlabs.org,
	linux-usb@vger.kernel.org, balbi@ti.com
Subject: Re: [PATCH] usb/fsl_udc: fix dequeuing a request in progress
Date: Tue, 22 Nov 2011 17:34:39 +0800	[thread overview]
Message-ID: <20111122093437.GA18543@nchen-desktop> (raw)
In-Reply-To: <1321015093-13715-1-git-send-email-leoli@freescale.com>

On Fri, Nov 11, 2011 at 08:38:13PM +0800, Li Yang wrote:
> The original implementation of dequeuing a request in progress
> is not correct.  Change to use a correct process and also clean
> up the related functions a little bit.
> 
> Signed-off-by: Li Yang <leoli@freescale.com>
> ---
>  drivers/usb/gadget/fsl_udc_core.c |   62 +++++++++++++++++-------------------
>  1 files changed, 29 insertions(+), 33 deletions(-)
> 
> diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/fsl_udc_core.c
> index b2c44e1..beef9b7 100644
> --- a/drivers/usb/gadget/fsl_udc_core.c
> +++ b/drivers/usb/gadget/fsl_udc_core.c
> @@ -696,12 +696,31 @@ static void fsl_free_request(struct usb_ep *_ep, struct usb_request *_req)
>  		kfree(req);
>  }
>  
> -/*-------------------------------------------------------------------------*/
> +/* Actually add a dTD chain to an empty dQH and let go */
> +static void fsl_prime_ep(struct fsl_ep *ep, struct ep_td_struct *td)
> +{
> +	struct ep_queue_head *qh = ep->qh;
It seems to can't get the correct qh pointer, you may still need to
use below code to get it
 	int i = ep_index(ep) * 2 + ep_is_in(ep);
 	struct ep_queue_head *dQH = &ep->udc->ep_qh[i];
> +
> +	/* Write dQH next pointer and terminate bit to 0 */
> +	qh->next_dtd_ptr = cpu_to_hc32(td->td_dma
> +			& EP_QUEUE_HEAD_NEXT_POINTER_MASK);
> +
> +	/* Clear active and halt bit */
> +	qh->size_ioc_int_sts &= cpu_to_hc32(~(EP_QUEUE_HEAD_STATUS_ACTIVE
> +					| EP_QUEUE_HEAD_STATUS_HALT));
> +
> +	/* Ensure that updates to the QH will occur before priming. */
> +	wmb();
> +
> +	/* Prime endpoint by writing correct bit to ENDPTPRIME */
> +	fsl_writel(ep_is_in(ep) ? (1 << (ep_index(ep) + 16))
> +			: (1 << (ep_index(ep))), &dr_regs->endpointprime);
> +}
> +
> +/* Add dTD chain to the dQH of an EP */
>  static void fsl_queue_td(struct fsl_ep *ep, struct fsl_req *req)
>  {
> -	int i = ep_index(ep) * 2 + ep_is_in(ep);
>  	u32 temp, bitmask, tmp_stat;
> -	struct ep_queue_head *dQH = &ep->udc->ep_qh[i];
>  
>  	/* VDBG("QH addr Register 0x%8x", dr_regs->endpointlistaddr);
>  	VDBG("ep_qh[%d] addr is 0x%8x", i, (u32)&(ep->udc->ep_qh[i])); */
> @@ -719,7 +738,7 @@ static void fsl_queue_td(struct fsl_ep *ep, struct fsl_req *req)
>  			cpu_to_hc32(req->head->td_dma & DTD_ADDR_MASK);
>  		/* Read prime bit, if 1 goto done */
>  		if (fsl_readl(&dr_regs->endpointprime) & bitmask)
> -			goto out;
> +			return;
>  
>  		do {
>  			/* Set ATDTW bit in USBCMD */
> @@ -736,28 +755,10 @@ static void fsl_queue_td(struct fsl_ep *ep, struct fsl_req *req)
>  		fsl_writel(temp & ~USB_CMD_ATDTW, &dr_regs->usbcmd);
>  
>  		if (tmp_stat)
> -			goto out;
> +			return;
>  	}
>  
> -	/* Write dQH next pointer and terminate bit to 0 */
> -	temp = req->head->td_dma & EP_QUEUE_HEAD_NEXT_POINTER_MASK;
> -	dQH->next_dtd_ptr = cpu_to_hc32(temp);
> -
> -	/* Clear active and halt bit */
> -	temp = cpu_to_hc32(~(EP_QUEUE_HEAD_STATUS_ACTIVE
> -			| EP_QUEUE_HEAD_STATUS_HALT));
> -	dQH->size_ioc_int_sts &= temp;
> -
> -	/* Ensure that updates to the QH will occur before priming. */
> -	wmb();
> -
> -	/* Prime endpoint by writing 1 to ENDPTPRIME */
> -	temp = ep_is_in(ep)
> -		? (1 << (ep_index(ep) + 16))
> -		: (1 << (ep_index(ep)));
> -	fsl_writel(temp, &dr_regs->endpointprime);
> -out:
> -	return;
> +	fsl_prime_ep(ep, req->head);
>  }
>  
>  /* Fill in the dTD structure
> @@ -973,25 +974,20 @@ static int fsl_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req)
>  
>  		/* The request isn't the last request in this ep queue */
>  		if (req->queue.next != &ep->queue) {
> -			struct ep_queue_head *qh;
>  			struct fsl_req *next_req;
>  
> -			qh = ep->qh;
>  			next_req = list_entry(req->queue.next, struct fsl_req,
>  					queue);
>  
> -			/* Point the QH to the first TD of next request */
> -			fsl_writel((u32) next_req->head, &qh->curr_dtd_ptr);
> +			/* prime with dTD of next request */
> +			fsl_prime_ep(ep, next_req->head);
>  		}
> -
> -		/* The request hasn't been processed, patch up the TD chain */
> +	/* The request hasn't been processed, patch up the TD chain */
>  	} else {
>  		struct fsl_req *prev_req;
>  
>  		prev_req = list_entry(req->queue.prev, struct fsl_req, queue);
> -		fsl_writel(fsl_readl(&req->tail->next_td_ptr),
> -				&prev_req->tail->next_td_ptr);
> -
> +		prev_req->tail->next_td_ptr = req->tail->next_td_ptr;
>  	}
>  
>  	done(ep, req, -ECONNRESET);

After fixing above error, others are ok. I have tested it at i.mx51 bbg board
using 3.2.0-rc2+.
> -- 
> 1.5.4.3
> 
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-usb" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

-- 

Best Regards,
Peter Chen

  reply	other threads:[~2011-11-22  9:34 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-11-11 12:38 [PATCH] usb/fsl_udc: fix dequeuing a request in progress Li Yang
2011-11-22  9:34 ` Peter Chen [this message]
2011-11-22  9:49   ` Li Yang-R58472
2011-11-22 11:48     ` Peter Chen
2011-11-23  3:02       ` Peter Chen
2011-11-23  8:20         ` Li Yang-R58472
2011-11-24  9:32           ` Felipe Balbi

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20111122093437.GA18543@nchen-desktop \
    --to=peter.chen@freescale.com \
    --cc=balbi@ti.com \
    --cc=gregkh@suse.de \
    --cc=leoli@freescale.com \
    --cc=linux-usb@vger.kernel.org \
    --cc=linuxppc-dev@lists.ozlabs.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.