svn commit: r246614 - head/sys/dev/usb/wlan

John Baldwin jhb at freebsd.org
Wed Feb 13 16:00:06 UTC 2013


On Tuesday, February 12, 2013 2:43:32 am Hans Petter Selasky wrote:
> On Monday 11 February 2013 17:33:02 John Baldwin wrote:
> > On Sunday, February 10, 2013 5:36:17 am Hans Petter Selasky wrote:
> > > Author: hselasky
> > > Date: Sun Feb 10 10:36:16 2013
> > > New Revision: 246614
> > > URL: http://svnweb.freebsd.org/changeset/base/246614
> > > 
> > > Log:
> > >   - Streamline detach logic in wlan drivers, so that
> > >   
> > >     freed memory cannot be used during detach.
> > >   
> > >   - Remove all panic() calls from the urtw driver because
> > >   
> > >     panic() is not appropriate here.
> > >   
> > >   - Remove redundant checks for device detached in
> > >   
> > >     device detach callbacks.
> > >   
> > >   - Use DEVMETHOD_END to mark end of device methods.
> > 
> > Using a detached flag to bail from ioctl generally means you are doing
> > things wrong in detach.  The correct solution is to always detach your
> > ifnet first, then start tearing down other state.  In general with device
> > detach routines the first order of business is removing external
> > references such as character devices, ifnets, etc. and only start shutting
> > down the hardware and releasing state once those steps have completed.
> 
> Hi,
> 
> What I can do to solve the problem is to lock a mutex while detaching. Is 
the 
> ifnet detach routine non-blocking?
> 
> Why do I say that? It is because we are in a chicken-egg situation. USB is 
> feeding data into ifnet and ifnet is feeding data into USB. Each stack is 
> running under its own lock. The current approach is:
> 
> 1) Stop data traffic in both directions
> 2) Make sure no more init happens (ioctl fix)
> 3) Free USB and IFNET.
> 
> I see currently no way I can atomically stop all traffic and prevent futher 
> init at the same time, while holding a single mutex. Do you?

You shouldn't call routines that can drain like if_detach() or destroy_dev() 
or the like while holding any mutexes period.  I think you need a 0) step 
which is "detach external consumers" including cdev's (destroy_dev()) and 
ifnet's (if_detach).  Once both of those routines have finished, you can then
proceed with actually stopping device operation, and 2) is not needed as it 
can't happen once 0) has finished.

When a device has both an ifnet and a cdev you may need something to handle 
the case of one part being dead but not the other.  For now you can call
if_detach() first as it doesn't sleep (though that is a bug).  The real fix 
for this case (and things like tun(4) can need this as well) is to have a way 
to call just the non-blocking parts of things like if_detach() and 
destroy_dev() first to mark the relevant portions as dead and then follow 
those with blocking calls that do the drain.  This is all part of step 0 
though.

-- 
John Baldwin


More information about the svn-src-head mailing list