[pvrusb2] pvrusb2 driver lock in 2.6.27: workaround

Mike Isely isely at isely.net
Sat Oct 18 21:38:05 CDT 2008


On Sat, 18 Oct 2008, Mike Isely wrote:

> 
> Finally got a good 2.6.27.2 kernel build here and I tried the included 
> pvrusb2 driver.  Complete failure, very early in initialization.  Same 
> problem with the standalone driver, and I'm sure that v4l-dvb resident 
> version is going to have the same issue.
> 
> I've got a bunch of clues to chase down; stay tuned.  Looks like I'll be 
> rebooting a lot :-(

Holy crap.  This one is very interesting.  The good news is that I have 
an easy workaround - no code changes needed:  Turn off the pvrusb2 
module parameter "initusbreset".  This is defaulted to on and it's part 
of the problem.

Said another way, just do this before you plug in the device for the 
first time:

  modprobe pvrusb2 initusbreset=0

Alternatively, putting the following into a file anywhere under 
/etc/modprobe.d/ should work even better:

  options pvrusb2 initusbreset=0

That causes udev to set this parameter for you whenever the driver gets 
loaded.


Here is the sequence of events, when the device is plugged in:

1. Driver is called to associate the new device.

2. Driver creates an internal context, and passes it off to its internal 
worker thread.

3. Driver worker thread "enters" the new context and starts initializing 
the device.  Entry into the context causes the instance's mutex to be 
entered.

4. Driver notices that initusbreset is true and first kicks a USB reset 
to the device.

5. The USB reset action causes the USB core to disconnect the device.

6. The disconnect action triggers another call into the pvrusb2 driver 
to disconnect.

7. The disconnect call "enters" that same context - and grabs the 
instance's mutex again.  *DEADLOCK*

Because the USB core is calling back into the driver right on top of the 
reset call into the core, the second grab of the driver's instance mutex 
therefore happens in the same thread context and that causes the thread 
to deadlock.  The deadlocked thread is completely jammed - there's 
simply no way out.  This stuck thread prevents removal of the pvrusb2.ko 
module, which is why a modprobe -r gets stuck.  The only escape is a 
reboot.

So for now the workaround is easy; set initusbreset to zero; this 
prevents the USB reset attempt and avoids the recursive lock.  As for 
why that initusbreset business is there at all - this dates quite a ways 
back when I was doing tricks to better stabilize the hardware.  At the 
time I found that the reset never "hurt" and that it seem to sometimes 
clear any previous jammed condition in the device hardware (if the 
device had been jammed mid-transfer from a previous bad hotplug 
removal).  So omitting the usb reset there is not really a big problem.

I need to go back and study older kernels to see why this wasn't a 
problem before 2.6.27.  Once I have a better handle on this, I'll 
concoct a patch to fix it permanently.

  -Mike

-- 

Mike Isely
isely @ pobox (dot) com
PGP: 03 54 43 4D 75 E5 CC 92 71 16 01 E2 B5 F5 C1 E8


More information about the pvrusb2 mailing list