Hi all,

I see the following as a definitive improvement compared to the
previous situation. It's probably possible to improve it further and I
welcome comments in that direction. In general I would like to know how
other Zoran developers and users feel about this change, if there are
major objections, etc. And of course I welcome reports from testers :)

* * * * *

The memory allocation logic for the V4L buffers in the zr36067 driver
is a bit weird at the moment. It arbitrarily limits the size of
kmalloc'd buffers to 128 kB, and for larger buffers, it uses quirks
which are either marked as dangerous or require an external patch
(which I think is no longer maintained.) This basically limits
regular users to buffer sizes of 128 kB, which means a ridiculously
small resolution (320x200).

While it is true that buffers larger than 128 kB may be difficult to
obtain from kmalloc, on recent systems with a lot of memory it isn't
impossible. On my system I have setup the zr36067 driver to allocate
4 buffers of 1 MB each, and kmalloc managed to allocate them without
problems for months. I reduced the physical memory from 1 GB to 256 MB
to see how it would behave, and while the allocations start failing
when the system is short on memory, I can still get tvtime to work by
either running it early or by closing other applications before I
start it.

So I am proposing a rework of the V4L buffer allocation strategy:
* We drop the get_high_mem() alternative allocation method. Did this
  work for anyone in recent times? It never worked for me on x86-64.
  And if I read the code correctly, it also can't work if more than
  one Zoran adapter is installed.
* We suppress the arbitrary limit of 128 kB for kmalloc'd buffers. I
  see no reason to not take our chance. If the allocation succeeds
  then why not do it?

Note that this doesn't change the default behavior of the driver, as
the default buffer size is 128 kB, and for this size kmalloc was
already used so far.

Signed-off-by: Jean Delvare <[EMAIL PROTECTED]>
Cc: Trent Piepho <[EMAIL PROTECTED]>
Cc: Ronald S. Bultje <[EMAIL PROTECTED]>
Cc: Martin Samuelsson <[EMAIL PROTECTED]>
---
 drivers/media/video/zoran_driver.c |  146 +++---------------------------------
 1 file changed, 15 insertions(+), 131 deletions(-)

--- linux-2.6.27-rc5.orig/drivers/media/video/zoran_driver.c    2008-09-03 
13:23:18.000000000 +0200
+++ linux-2.6.27-rc5/drivers/media/video/zoran_driver.c 2008-09-03 
13:47:55.000000000 +0200
@@ -75,7 +75,6 @@
 #include "videocodec.h"
 
 #include <asm/byteorder.h>
-#include <asm/io.h>
 #include <asm/uaccess.h>
 #include <linux/proc_fs.h>
 
@@ -234,78 +233,9 @@ static void jpg_fbuffer_free(struct file
 /*
  *   Allocate the V4L grab buffers
  *
- *   These have to be pysically contiguous.
- *   If v4l_bufsize <= MAX_KMALLOC_MEM we use kmalloc
- *   else we try to allocate them with bigphysarea_alloc_pages
- *   if the bigphysarea patch is present in the kernel,
- *   else we try to use high memory (if the user has bootet
- *   Linux with the necessary memory left over).
+ *   These have to be physically contiguous.
  */
 
-static unsigned long
-get_high_mem (unsigned long size)
-{
-/*
- * Check if there is usable memory at the end of Linux memory
- * of at least size. Return the physical address of this memory,
- * return 0 on failure.
- *
- * The idea is from Alexandro Rubini's book "Linux device drivers".
- * The driver from him which is downloadable from O'Reilly's
- * web site misses the "virt_to_phys(high_memory)" part
- * (and therefore doesn't work at all - at least with 2.2.x kernels).
- *
- * It should be unnecessary to mention that THIS IS DANGEROUS,
- * if more than one driver at a time has the idea to use this memory!!!!
- */
-
-       volatile unsigned char __iomem *mem;
-       unsigned char c;
-       unsigned long hi_mem_ph;
-       unsigned long i;
-
-       /* Map the high memory to user space */
-
-       hi_mem_ph = virt_to_phys(high_memory);
-
-       mem = ioremap(hi_mem_ph, size);
-       if (!mem) {
-               dprintk(1,
-                       KERN_ERR "%s: get_high_mem() - ioremap failed\n",
-                       ZORAN_NAME);
-               return 0;
-       }
-
-       for (i = 0; i < size; i++) {
-               /* Check if it is memory */
-               c = i & 0xff;
-               writeb(c, mem + i);
-               if (readb(mem + i) != c)
-                       break;
-               c = 255 - c;
-               writeb(c, mem + i);
-               if (readb(mem + i) != c)
-                       break;
-               writeb(0, mem + i);     /* zero out memory */
-
-               /* give the kernel air to breath */
-               if ((i & 0x3ffff) == 0x3ffff)
-                       schedule();
-       }
-
-       iounmap(mem);
-
-       if (i != size) {
-               dprintk(1,
-                       KERN_ERR
-                       "%s: get_high_mem() - requested %lu, avail %lu\n",
-                       ZORAN_NAME, size, i);
-               return 0;
-       }
-
-       return hi_mem_ph;
-}
-
 static int
 v4l_fbuffer_alloc (struct file *file)
 {
@@ -313,7 +243,6 @@ v4l_fbuffer_alloc (struct file *file)
        struct zoran *zr = fh->zr;
        int i, off;
        unsigned char *mem;
-       unsigned long pmem = 0;
 
        /* we might have old buffers lying around... */
        if (fh->v4l_buffers.ready_to_be_freed) {
@@ -327,19 +256,9 @@ v4l_fbuffer_alloc (struct file *file)
                                "%s: v4l_fbuffer_alloc() - buffer %d allready 
allocated!?\n",
                                ZR_DEVNAME(zr), i);
 
-               //udelay(20);
-               if (fh->v4l_buffers.buffer_size <= MAX_KMALLOC_MEM) {
-                       /* Use kmalloc */
-
-                       mem = kmalloc(fh->v4l_buffers.buffer_size, GFP_KERNEL);
-                       if (!mem) {
-                               dprintk(1,
-                                       KERN_ERR
-                                       "%s: v4l_fbuffer_alloc() - kmalloc for 
V4L buf %d failed\n",
-                                       ZR_DEVNAME(zr), i);
-                               v4l_fbuffer_free(file);
-                               return -ENOBUFS;
-                       }
+               mem = kmalloc(fh->v4l_buffers.buffer_size,
+                             GFP_KERNEL | __GFP_NOWARN);
+               if (mem) {
                        fh->v4l_buffers.buffer[i].fbuffer = mem;
                        fh->v4l_buffers.buffer[i].fbuffer_phys =
                            virt_to_phys(mem);
@@ -354,45 +273,12 @@ v4l_fbuffer_alloc (struct file *file)
                                ZR_DEVNAME(zr), i, (unsigned long) mem,
                                virt_to_bus(mem));
                } else {
-
-                       /* Use high memory which has been left at boot time */
-
-                       /* Ok., Ok. this is an evil hack - we make
-                        * the assumption that physical addresses are
-                        * the same as bus addresses (true at least
-                        * for Intel processors). The whole method of
-                        * obtaining and using this memory is not very
-                        * nice - but I hope it saves some poor users
-                        * from kernel hacking, which might have even
-                        * more evil results */
-
-                       if (i == 0) {
-                               int size =
-                                   fh->v4l_buffers.num_buffers *
-                                   fh->v4l_buffers.buffer_size;
-
-                               pmem = get_high_mem(size);
-                               if (pmem == 0) {
-                                       dprintk(1,
-                                               KERN_ERR
-                                               "%s: v4l_fbuffer_alloc() - 
get_high_mem (size = %d KB) for V4L bufs failed\n",
-                                               ZR_DEVNAME(zr), size >> 10);
-                                       return -ENOBUFS;
-                               }
-                               fh->v4l_buffers.buffer[0].fbuffer = NULL;
-                               fh->v4l_buffers.buffer[0].fbuffer_phys = pmem;
-                               fh->v4l_buffers.buffer[0].fbuffer_bus = pmem;
-                               dprintk(4,
-                                       KERN_INFO
-                                       "%s: v4l_fbuffer_alloc() - using %d KB 
high memory\n",
-                                       ZR_DEVNAME(zr), size >> 10);
-                       } else {
-                               fh->v4l_buffers.buffer[i].fbuffer = NULL;
-                               fh->v4l_buffers.buffer[i].fbuffer_phys =
-                                   pmem + i * fh->v4l_buffers.buffer_size;
-                               fh->v4l_buffers.buffer[i].fbuffer_bus =
-                                   pmem + i * fh->v4l_buffers.buffer_size;
-                       }
+                       dprintk(1,
+                               KERN_ERR
+                               "%s: v4l_fbuffer_alloc() - kmalloc for V4L buf 
%d failed\n",
+                               ZR_DEVNAME(zr), i);
+                       v4l_fbuffer_free(file);
+                       return -ENOBUFS;
                }
        }
 
@@ -416,13 +302,11 @@ v4l_fbuffer_free (struct file *file)
                if (!fh->v4l_buffers.buffer[i].fbuffer)
                        continue;
 
-               if (fh->v4l_buffers.buffer_size <= MAX_KMALLOC_MEM) {
-                       mem = fh->v4l_buffers.buffer[i].fbuffer;
-                       for (off = 0; off < fh->v4l_buffers.buffer_size;
-                            off += PAGE_SIZE)
-                               ClearPageReserved(MAP_NR(mem + off));
-                       kfree((void *) fh->v4l_buffers.buffer[i].fbuffer);
-               }
+               mem = fh->v4l_buffers.buffer[i].fbuffer;
+               for (off = 0; off < fh->v4l_buffers.buffer_size;
+                    off += PAGE_SIZE)
+                       ClearPageReserved(MAP_NR(mem + off));
+               kfree((void *) fh->v4l_buffers.buffer[i].fbuffer);
                fh->v4l_buffers.buffer[i].fbuffer = NULL;
        }
 


-- 
Jean Delvare

-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
Mjpeg-users mailing list
Mjpeg-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/mjpeg-users

Reply via email to