]> git.karo-electronics.de Git - mv-sheeva.git/commitdiff
[media] gspca_main: Set memory type to GSPCA_MEMORY_NO on buffer release
authorHans de Goede <hdegoede@redhat.com>
Fri, 31 Dec 2010 07:51:36 +0000 (04:51 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Wed, 19 Jan 2011 13:44:57 +0000 (11:44 -0200)
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>
drivers/media/video/gspca/gspca.c

index 0ba42dd4b99b466068e1706c0ee1789f04d3b361..adab34f91a68323dbf99d1531edbe34bb2d64016 100644 (file)
@@ -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;
@@ -519,7 +519,6 @@ 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);
@@ -527,6 +526,9 @@ static int frame_alloc(struct gspca_dev *gspca_dev,
                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];
@@ -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;
@@ -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)
@@ -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);
@@ -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);
        }