Re: Crash on unplug with the uvc driver in linuxtv/staging/for_v3.1

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

 



On Monday, June 13, 2011 11:41:42 Laurent Pinchart wrote:
> Hi Hans (and Hans),
> 
> On Saturday 11 June 2011 11:16:10 Laurent Pinchart wrote:
> > On Thursday 09 June 2011 13:22:03 Hans de Goede wrote:
> > > Hi,
> > > 
> > > When I unplug a uvc camera *while streaming* I get:
> > > 
> > > [15824.809741] BUG: unable to handle kernel NULL pointer dereference at
> > > (null)
> > 
> > [snip]
> > 
> > > I've not tested if this also impacts 3.0!!
> > 
> > It probably does. Thanks for the report. I'll fix it.
> 
> It does. Fixing the problem turns to be more complex than expected.
> 
> The crash is caused by media entities life time management issues.
> 
> Entities associated with video device nodes are unregistered in 
> video_unregister_device(). This removes the entity from its parent's entities 
> list, and sets the entity's parent to NULL.
> 
> Entities also get/put references to their parent's module through 
> media_entity_get() and media_entity_put(). Those functions are called in the 
> open and release handlers of video device nodes and subdev device nodes. The 
> reason behind this is to avoid a parent module from being removed while a 
> subdev is opened, as closing a subdev can call to the parent's module through 
> board code.
> 
> When a UVC device is unplugged while streaming, the uvcvideo driver will call 
> video_unregister_device() in the disconnect handler. This will in turn call 
> media_device_unregister_entity() which sets the entity's parent to NULL. When 
> the user then closes open video device nodes, v4l2_release() calls 
> media_entity_put() which tries to dereference entity->parent, and oopses.
> 
> I've tried to move the media_device_unregister_entity() call from 
> video_unregister_device() to v4l2_device_release() (called when the last 
> reference to the video device is released). media_entity_put() is then called 
> before the entity is unregistered, but that results in a different oops: as 
> this happens after the USB disconnect callback is called, entity->parent->dev-
> >driver is now NULL, and trying to access entity->parent->dev->driver->owner 
> to decrement the module use count oopses.
> 
> One possible workaround is to remove media_entity_get()/media_entity_put() 
> calls from v4l2-dev.c. As the original purpose of those functions was to avoid 
> a parent module from being removed while still accessible through board code, 
> and all existing MC-enabled drivers register video device nodes with the owner 
> equal to the entity's parent's module, we can safely do it.
> 
> I'd rather implement a proper solution though, but that's not straightforward. 
> We short-circuit the kernel reference management by going through board code. 
> There's something fundamentally wrong in the way we manage subdevs and 
> device/module reference counts. I'm not sure where the proper fix should go to 
> though.

Hmm. Tricky.

media_device_unregister_entity() is definitely called in the wrong place. It
should move to v4l2_device_release(). I wonder why media_entity_get/put are
called in v4l2_open and v4l2_release. That should be in __video_register_device
and v4l2_device_release as far as I can see.

Just closing a device node shouldn't be cause for changing the module's refcount,
that device node registration and the release after unregistration.

I also wonder whether instead of refcounting the module in media_entity_get/put
you should refcount the device (entity->parent->dev).

I have to admit that I don't quite understand why the USB disconnect zeroes
entity->parent->dev->driver.

I hope this gives some ideas...

Regards,

	Hans
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Input]     [Video for Linux]     [Gstreamer Embedded]     [Mplayer Users]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]
  Powered by Linux