Merge branch 'v4l_for_linus' of git://linuxtv.org/mchehab/for_linus
* 'v4l_for_linus' of git://linuxtv.org/mchehab/for_linus: [media] omap3isp: Fix build error in ispccdc.c [media] uvcvideo: Fix crash when linking entities [media] v4l: Make sure we hold a reference to the v4l2_device before using it [media] v4l: Fix use-after-free case in v4l2_device_release [media] uvcvideo: Set alternate setting 0 on resume if the bus has been reset [media] OMAP_VOUT: Fix build break caused by update_mode removal in DSS2
This commit is contained in:
@@ -2194,19 +2194,6 @@ static int __init omap_vout_probe(struct platform_device *pdev)
|
|||||||
"'%s' Display already enabled\n",
|
"'%s' Display already enabled\n",
|
||||||
def_display->name);
|
def_display->name);
|
||||||
}
|
}
|
||||||
/* set the update mode */
|
|
||||||
if (def_display->caps &
|
|
||||||
OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) {
|
|
||||||
if (dssdrv->enable_te)
|
|
||||||
dssdrv->enable_te(def_display, 0);
|
|
||||||
if (dssdrv->set_update_mode)
|
|
||||||
dssdrv->set_update_mode(def_display,
|
|
||||||
OMAP_DSS_UPDATE_MANUAL);
|
|
||||||
} else {
|
|
||||||
if (dssdrv->set_update_mode)
|
|
||||||
dssdrv->set_update_mode(def_display,
|
|
||||||
OMAP_DSS_UPDATE_AUTO);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -31,6 +31,7 @@
|
|||||||
#include <linux/dma-mapping.h>
|
#include <linux/dma-mapping.h>
|
||||||
#include <linux/mm.h>
|
#include <linux/mm.h>
|
||||||
#include <linux/sched.h>
|
#include <linux/sched.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
#include <media/v4l2-event.h>
|
#include <media/v4l2-event.h>
|
||||||
|
|
||||||
#include "isp.h"
|
#include "isp.h"
|
||||||
|
@@ -1961,7 +1961,7 @@ static int __uvc_resume(struct usb_interface *intf, int reset)
|
|||||||
|
|
||||||
list_for_each_entry(stream, &dev->streams, list) {
|
list_for_each_entry(stream, &dev->streams, list) {
|
||||||
if (stream->intf == intf)
|
if (stream->intf == intf)
|
||||||
return uvc_video_resume(stream);
|
return uvc_video_resume(stream, reset);
|
||||||
}
|
}
|
||||||
|
|
||||||
uvc_trace(UVC_TRACE_SUSPEND, "Resume: video streaming USB interface "
|
uvc_trace(UVC_TRACE_SUSPEND, "Resume: video streaming USB interface "
|
||||||
|
@@ -49,7 +49,7 @@ static int uvc_mc_register_entity(struct uvc_video_chain *chain,
|
|||||||
if (remote == NULL)
|
if (remote == NULL)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
source = (UVC_ENTITY_TYPE(remote) != UVC_TT_STREAMING)
|
source = (UVC_ENTITY_TYPE(remote) == UVC_TT_STREAMING)
|
||||||
? (remote->vdev ? &remote->vdev->entity : NULL)
|
? (remote->vdev ? &remote->vdev->entity : NULL)
|
||||||
: &remote->subdev.entity;
|
: &remote->subdev.entity;
|
||||||
if (source == NULL)
|
if (source == NULL)
|
||||||
|
@@ -1104,10 +1104,18 @@ int uvc_video_suspend(struct uvc_streaming *stream)
|
|||||||
* buffers, making sure userspace applications are notified of the problem
|
* buffers, making sure userspace applications are notified of the problem
|
||||||
* instead of waiting forever.
|
* instead of waiting forever.
|
||||||
*/
|
*/
|
||||||
int uvc_video_resume(struct uvc_streaming *stream)
|
int uvc_video_resume(struct uvc_streaming *stream, int reset)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
/* If the bus has been reset on resume, set the alternate setting to 0.
|
||||||
|
* This should be the default value, but some devices crash or otherwise
|
||||||
|
* misbehave if they don't receive a SET_INTERFACE request before any
|
||||||
|
* other video control request.
|
||||||
|
*/
|
||||||
|
if (reset)
|
||||||
|
usb_set_interface(stream->dev->udev, stream->intfnum, 0);
|
||||||
|
|
||||||
stream->frozen = 0;
|
stream->frozen = 0;
|
||||||
|
|
||||||
ret = uvc_commit_video(stream, &stream->ctrl);
|
ret = uvc_commit_video(stream, &stream->ctrl);
|
||||||
|
@@ -638,7 +638,7 @@ extern void uvc_mc_cleanup_entity(struct uvc_entity *entity);
|
|||||||
/* Video */
|
/* Video */
|
||||||
extern int uvc_video_init(struct uvc_streaming *stream);
|
extern int uvc_video_init(struct uvc_streaming *stream);
|
||||||
extern int uvc_video_suspend(struct uvc_streaming *stream);
|
extern int uvc_video_suspend(struct uvc_streaming *stream);
|
||||||
extern int uvc_video_resume(struct uvc_streaming *stream);
|
extern int uvc_video_resume(struct uvc_streaming *stream, int reset);
|
||||||
extern int uvc_video_enable(struct uvc_streaming *stream, int enable);
|
extern int uvc_video_enable(struct uvc_streaming *stream, int enable);
|
||||||
extern int uvc_probe_video(struct uvc_streaming *stream,
|
extern int uvc_probe_video(struct uvc_streaming *stream,
|
||||||
struct uvc_streaming_control *probe);
|
struct uvc_streaming_control *probe);
|
||||||
|
@@ -173,6 +173,17 @@ static void v4l2_device_release(struct device *cd)
|
|||||||
media_device_unregister_entity(&vdev->entity);
|
media_device_unregister_entity(&vdev->entity);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Do not call v4l2_device_put if there is no release callback set.
|
||||||
|
* Drivers that have no v4l2_device release callback might free the
|
||||||
|
* v4l2_dev instance in the video_device release callback below, so we
|
||||||
|
* must perform this check here.
|
||||||
|
*
|
||||||
|
* TODO: In the long run all drivers that use v4l2_device should use the
|
||||||
|
* v4l2_device release callback. This check will then be unnecessary.
|
||||||
|
*/
|
||||||
|
if (v4l2_dev->release == NULL)
|
||||||
|
v4l2_dev = NULL;
|
||||||
|
|
||||||
/* Release video_device and perform other
|
/* Release video_device and perform other
|
||||||
cleanups as needed. */
|
cleanups as needed. */
|
||||||
vdev->release(vdev);
|
vdev->release(vdev);
|
||||||
|
@@ -38,6 +38,7 @@ int v4l2_device_register(struct device *dev, struct v4l2_device *v4l2_dev)
|
|||||||
mutex_init(&v4l2_dev->ioctl_lock);
|
mutex_init(&v4l2_dev->ioctl_lock);
|
||||||
v4l2_prio_init(&v4l2_dev->prio);
|
v4l2_prio_init(&v4l2_dev->prio);
|
||||||
kref_init(&v4l2_dev->ref);
|
kref_init(&v4l2_dev->ref);
|
||||||
|
get_device(dev);
|
||||||
v4l2_dev->dev = dev;
|
v4l2_dev->dev = dev;
|
||||||
if (dev == NULL) {
|
if (dev == NULL) {
|
||||||
/* If dev == NULL, then name must be filled in by the caller */
|
/* If dev == NULL, then name must be filled in by the caller */
|
||||||
@@ -93,6 +94,7 @@ void v4l2_device_disconnect(struct v4l2_device *v4l2_dev)
|
|||||||
|
|
||||||
if (dev_get_drvdata(v4l2_dev->dev) == v4l2_dev)
|
if (dev_get_drvdata(v4l2_dev->dev) == v4l2_dev)
|
||||||
dev_set_drvdata(v4l2_dev->dev, NULL);
|
dev_set_drvdata(v4l2_dev->dev, NULL);
|
||||||
|
put_device(v4l2_dev->dev);
|
||||||
v4l2_dev->dev = NULL;
|
v4l2_dev->dev = NULL;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(v4l2_device_disconnect);
|
EXPORT_SYMBOL_GPL(v4l2_device_disconnect);
|
||||||
|
Reference in New Issue
Block a user