Commit d642de2e authored by Hans de Goede's avatar Hans de Goede Committed by Mauro Carvalho Chehab

[media] gspca_main: Set memory type to GSPCA_MEMORY_NO on buffer release

Before this patch we were not setting the memory type to GSPCA_MEMORY_NO
when the buffers were released by the app doing a reqbufs 0. Nor would
the memory type be set to GSPCA_MEMORY_NO on device close, as capture_file
already is NULL on device close because of the reqbufs 0. This caused the
following problem:
-app1 does reqbufs USERPTR for 4 buffers
-app1 does reqbufs USERPTR for 0 buffers
-app2 tries to do reqbufs MMAP for 4 buffers
 fails because gspca_dev->memory still is USERPTR

Fixing this also allows an app to switch memory type's by unrequesting
the buffers and re-requesting them of a different type.

This patch also moves the setting of gspca_dev->frsz and gscpa_dev->memory
to after alloc_frame succeeding, so that they are not changed when allocating
fails.
Signed-off-by: default avatarHans de Goede <hdegoede@redhat.com>
Acked-by: default avatarJean-Francois Moine <moinejf@free.fr>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent 7f6eb118
...@@ -508,8 +508,8 @@ static int gspca_is_compressed(__u32 format) ...@@ -508,8 +508,8 @@ static int gspca_is_compressed(__u32 format)
return 0; return 0;
} }
static int frame_alloc(struct gspca_dev *gspca_dev, static int frame_alloc(struct gspca_dev *gspca_dev, struct file *file,
unsigned int count) enum v4l2_memory memory, unsigned int count)
{ {
struct gspca_frame *frame; struct gspca_frame *frame;
unsigned int frsz; unsigned int frsz;
...@@ -519,7 +519,6 @@ static int frame_alloc(struct gspca_dev *gspca_dev, ...@@ -519,7 +519,6 @@ static int frame_alloc(struct gspca_dev *gspca_dev,
frsz = gspca_dev->cam.cam_mode[i].sizeimage; frsz = gspca_dev->cam.cam_mode[i].sizeimage;
PDEBUG(D_STREAM, "frame alloc frsz: %d", frsz); PDEBUG(D_STREAM, "frame alloc frsz: %d", frsz);
frsz = PAGE_ALIGN(frsz); frsz = PAGE_ALIGN(frsz);
gspca_dev->frsz = frsz;
if (count >= GSPCA_MAX_FRAMES) if (count >= GSPCA_MAX_FRAMES)
count = GSPCA_MAX_FRAMES - 1; count = GSPCA_MAX_FRAMES - 1;
gspca_dev->frbuf = vmalloc_32(frsz * count); gspca_dev->frbuf = vmalloc_32(frsz * count);
...@@ -527,6 +526,9 @@ static int frame_alloc(struct gspca_dev *gspca_dev, ...@@ -527,6 +526,9 @@ static int frame_alloc(struct gspca_dev *gspca_dev,
err("frame alloc failed"); err("frame alloc failed");
return -ENOMEM; return -ENOMEM;
} }
gspca_dev->capt_file = file;
gspca_dev->memory = memory;
gspca_dev->frsz = frsz;
gspca_dev->nframes = count; gspca_dev->nframes = count;
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
frame = &gspca_dev->frame[i]; frame = &gspca_dev->frame[i];
...@@ -535,7 +537,7 @@ static int frame_alloc(struct gspca_dev *gspca_dev, ...@@ -535,7 +537,7 @@ static int frame_alloc(struct gspca_dev *gspca_dev,
frame->v4l2_buf.flags = 0; frame->v4l2_buf.flags = 0;
frame->v4l2_buf.field = V4L2_FIELD_NONE; frame->v4l2_buf.field = V4L2_FIELD_NONE;
frame->v4l2_buf.length = frsz; frame->v4l2_buf.length = frsz;
frame->v4l2_buf.memory = gspca_dev->memory; frame->v4l2_buf.memory = memory;
frame->v4l2_buf.sequence = 0; frame->v4l2_buf.sequence = 0;
frame->data = gspca_dev->frbuf + i * frsz; frame->data = gspca_dev->frbuf + i * frsz;
frame->v4l2_buf.m.offset = i * frsz; frame->v4l2_buf.m.offset = i * frsz;
...@@ -558,6 +560,9 @@ static void frame_free(struct gspca_dev *gspca_dev) ...@@ -558,6 +560,9 @@ static void frame_free(struct gspca_dev *gspca_dev)
gspca_dev->frame[i].data = NULL; gspca_dev->frame[i].data = NULL;
} }
gspca_dev->nframes = 0; gspca_dev->nframes = 0;
gspca_dev->frsz = 0;
gspca_dev->capt_file = NULL;
gspca_dev->memory = GSPCA_MEMORY_NO;
} }
static void destroy_urbs(struct gspca_dev *gspca_dev) static void destroy_urbs(struct gspca_dev *gspca_dev)
...@@ -1250,8 +1255,6 @@ static int dev_close(struct file *file) ...@@ -1250,8 +1255,6 @@ static int dev_close(struct file *file)
mutex_unlock(&gspca_dev->usb_lock); mutex_unlock(&gspca_dev->usb_lock);
} }
frame_free(gspca_dev); frame_free(gspca_dev);
gspca_dev->capt_file = NULL;
gspca_dev->memory = GSPCA_MEMORY_NO;
} }
file->private_data = NULL; file->private_data = NULL;
module_put(gspca_dev->module); module_put(gspca_dev->module);
...@@ -1524,17 +1527,13 @@ static int vidioc_reqbufs(struct file *file, void *priv, ...@@ -1524,17 +1527,13 @@ static int vidioc_reqbufs(struct file *file, void *priv,
} }
/* free the previous allocated buffers, if any */ /* free the previous allocated buffers, if any */
if (gspca_dev->nframes != 0) { if (gspca_dev->nframes != 0)
frame_free(gspca_dev); frame_free(gspca_dev);
gspca_dev->capt_file = NULL;
}
if (rb->count == 0) /* unrequest */ if (rb->count == 0) /* unrequest */
goto out; goto out;
gspca_dev->memory = rb->memory; ret = frame_alloc(gspca_dev, file, rb->memory, rb->count);
ret = frame_alloc(gspca_dev, rb->count);
if (ret == 0) { if (ret == 0) {
rb->count = gspca_dev->nframes; rb->count = gspca_dev->nframes;
gspca_dev->capt_file = file;
if (streaming) if (streaming)
ret = gspca_init_transfer(gspca_dev); ret = gspca_init_transfer(gspca_dev);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment