Re: [PATCH v6 3/7] HCD files for the DWC2 driver

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Tue, Mar 05, 2013 at 10:43:38PM +0000, Paul Zimmerman wrote:
> > From: Felipe Balbi [mailto:balbi@xxxxxx]
> > Sent: Tuesday, March 05, 2013 2:48 AM
> > 
> > On Mon, Mar 04, 2013 at 12:21:46PM -0800, Paul Zimmerman wrote:
> > > +#include "hcd.h"
> > > +
> > > +#ifdef VERBOSE_DEBUG
> > 
> > could move this inside the function body so you can call it
> > unconditionally.
> 
> Will do.
> 
> > Also, add a comment stating that this should be called with irqs
> > disabled and lock held.
> 
> Are you sure that is necessary? That means to be consistent, I would need
> to go through pretty much every function in the driver, and add a comment
> about whether it needs to be called with irqs disabled and the lock held. I
> don't think I have seen that level of detail in the comments of any other
> driver I have looked at.
> 
> If someone is modifying the driver, I would rather they follow the code
> to see whether the lock is required to be taken, instead of depending on
> the comment to be correct in every case.

fair enough.

> > Also, almost every single function related to qHs and qTDs is iterating
> > over those lists again and again and again. Eventually, if you have too
> > many of them, you will start to feel the pain :-p
> > 
> > I suggest going over this part of the code carefully and making sure you
> > can make the right assumptions (for example, assume that by the time
> > qh_remove_and_free() is called, you can assume all qHs to be empty or
> > something similar).
> 
> I think these functions are all in the abort/cleanup path. So in the normal
> case the lists would be empty, so the loop would break on the first
> iteration. Only in the abnormal case would there be anything in the list
> to be dealt with. So I think this is OK.

suit yourself, I still think your cleanup path is iterating far too much
;-)

> > > +static int dwc2_hcd_endpoint_disable(struct dwc2_hsotg *hsotg,
> > > +				     struct usb_host_endpoint *ep, int retry)
> > > +{
> > > +	struct dwc2_qh *qh;
> > > +	unsigned long flags;
> > > +
> > > +	spin_lock_irqsave(&hsotg->lock, flags);
> > > +
> > > +	qh = ep->hcpriv;
> > > +	if (!qh) {
> > > +		spin_unlock_irqrestore(&hsotg->lock, flags);
> > > +		return -EINVAL;
> > > +	}
> > > +
> > > +	while (!list_empty(&qh->qtd_list) && retry--) {
> > > +		if (retry == 0) {
> > > +			ep->hcpriv = NULL;
> > > +			spin_unlock_irqrestore(&hsotg->lock, flags);
> > > +			dev_err(hsotg->dev,
> > > +				"## timeout in dwc2_hcd_endpoint_disable() ##\n");
> > > +			return -EBUSY;
> > > +		}
> > > +		spin_unlock_irqrestore(&hsotg->lock, flags);
> > > +		usleep_range(20000, 40000);
> > > +		spin_lock_irqsave(&hsotg->lock, flags);
> > > +	}
> > > +
> > > +	dwc2_hcd_qh_remove(hsotg, qh);
> > > +	ep->hcpriv = NULL;
> > > +	spin_unlock_irqrestore(&hsotg->lock, flags);
> > 
> > locking here is getting convoluted already, you release the lock in
> > multiple places, it might be better to figure out you if you grab it in
> > one place and release it in one place. Also, releasing the lock for that
> > usleep_range() creates a race. What if the endpoint gets reenabled when
> > release that lock ?
> 
> I will fix it to use goto's and release the lock in a single place.

thanks

> > Perhaps using udelay() would be better in that case ?
> 
> That's not a good idea, because this can spin for quite a long time. Since
> this is the endpoint disable function, it is not possible for the endpoint
> to be re-enabled until this function has exited. So I don't think there's a
> race here, unless I'm missing something.

looking at that loop, is it really necessary ? I mean, what you do is:

spin_lock_irqsave();

while (!list_empty(list) && retry--) {
	if (!retry) {
		spin_unlock_irqrestore();
		boom();
	}

	spin_unlock_irqrestore();
	usleep_range();
	spin_lock_irqrestore();
}

are you really relying on that race to cleanup your qH list ? Doesn't
look to me that usleep is at all necessary here.

BTW, you _do_ have a race because you don't check ep->hcpriv when
->urb_enqueue() is called. This means that you could queue to an
endpoint which is in the process of getting disabled. The urb would
either be lost or completed before being started (if I read the code
correctly).

> > These comments summarize what needs to be changes all over the patch.
> 
> New patch coming in a day or so.

ok cool.

-- 
balbi

Attachment: signature.asc
Description: Digital signature


[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux