Skip to content

Commit

Permalink
[media] gspca_main: Set memory type to GSPCA_MEMORY_NO on buffer release
Browse files Browse the repository at this point in the history
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: Hans de Goede <hdegoede@redhat.com>
Acked-by: Jean-Francois Moine <moinejf@free.fr>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
  • Loading branch information
Hans de Goede authored and Mauro Carvalho Chehab committed Jan 19, 2011
1 parent 7f6eb11 commit d642de2
Showing 1 changed file with 11 additions and 12 deletions.
23 changes: 11 additions & 12 deletions drivers/media/video/gspca/gspca.c
Original file line number Diff line number Diff line change
Expand Up @@ -508,8 +508,8 @@ static int gspca_is_compressed(__u32 format)
return 0;
}

static int frame_alloc(struct gspca_dev *gspca_dev,
unsigned int count)
static int frame_alloc(struct gspca_dev *gspca_dev, struct file *file,
enum v4l2_memory memory, unsigned int count)
{
struct gspca_frame *frame;
unsigned int frsz;
Expand All @@ -519,14 +519,16 @@ static int frame_alloc(struct gspca_dev *gspca_dev,
frsz = gspca_dev->cam.cam_mode[i].sizeimage;
PDEBUG(D_STREAM, "frame alloc frsz: %d", frsz);
frsz = PAGE_ALIGN(frsz);
gspca_dev->frsz = frsz;
if (count >= GSPCA_MAX_FRAMES)
count = GSPCA_MAX_FRAMES - 1;
gspca_dev->frbuf = vmalloc_32(frsz * count);
if (!gspca_dev->frbuf) {
err("frame alloc failed");
return -ENOMEM;
}
gspca_dev->capt_file = file;
gspca_dev->memory = memory;
gspca_dev->frsz = frsz;
gspca_dev->nframes = count;
for (i = 0; i < count; i++) {
frame = &gspca_dev->frame[i];
Expand All @@ -535,7 +537,7 @@ static int frame_alloc(struct gspca_dev *gspca_dev,
frame->v4l2_buf.flags = 0;
frame->v4l2_buf.field = V4L2_FIELD_NONE;
frame->v4l2_buf.length = frsz;
frame->v4l2_buf.memory = gspca_dev->memory;
frame->v4l2_buf.memory = memory;
frame->v4l2_buf.sequence = 0;
frame->data = gspca_dev->frbuf + i * frsz;
frame->v4l2_buf.m.offset = i * frsz;
Expand All @@ -558,6 +560,9 @@ static void frame_free(struct gspca_dev *gspca_dev)
gspca_dev->frame[i].data = NULL;
}
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)
Expand Down Expand Up @@ -1250,8 +1255,6 @@ static int dev_close(struct file *file)
mutex_unlock(&gspca_dev->usb_lock);
}
frame_free(gspca_dev);
gspca_dev->capt_file = NULL;
gspca_dev->memory = GSPCA_MEMORY_NO;
}
file->private_data = NULL;
module_put(gspca_dev->module);
Expand Down Expand Up @@ -1524,17 +1527,13 @@ static int vidioc_reqbufs(struct file *file, void *priv,
}

/* free the previous allocated buffers, if any */
if (gspca_dev->nframes != 0) {
if (gspca_dev->nframes != 0)
frame_free(gspca_dev);
gspca_dev->capt_file = NULL;
}
if (rb->count == 0) /* unrequest */
goto out;
gspca_dev->memory = rb->memory;
ret = frame_alloc(gspca_dev, rb->count);
ret = frame_alloc(gspca_dev, file, rb->memory, rb->count);
if (ret == 0) {
rb->count = gspca_dev->nframes;
gspca_dev->capt_file = file;
if (streaming)
ret = gspca_init_transfer(gspca_dev);
}
Expand Down

0 comments on commit d642de2

Please sign in to comment.