Mark McClelland wrote:
> 
> 
> You can use the rvmalloc() function that is included in many V4L
> drivers. In ov511.c, I use it to allocate a few megs per camera. I never
> had any problem with it, except that in the 2.3.x kernels, some kernel
> resource would become exhausted after many allocate/free cycles. AFAIK,
> that is fixed now.
> 
> --

Well, apparently not in the version I have. I cut out the routines for
rvmalloc and rvfree from the se401.c code in the mandrake 2.4.8-26mdk
kernel source (see below). I changed the raw buffer allocation (~77KB)
from kmalloc to rvmalloc to test the rvmalloc code. I tested this with
code that worked fine with the kmalloc, and which would put the camera
into video mode for a few seconds and download the camera memory
contents (DL 1 picture 15 times); a small lcd display on the camera back
does a 'counter-rotation' of the segments of the 2 character 7 segment
display while the camera is in video mode and downloading. With the
rvmalloc version, the display segments never stop rotating, the driver
never finishes initialing (from lsmod), and I start getting "hda: lost
interrupt" messages. Now, this computer has an 800 MHz Duron, Gigabyte
GA-7IXE4 MB, AMD 750 chipset (751/756), usb-ochi, single WB 20GB hdd on
ide0 and DVD16x and Iomega 250MB zip on IDE1. 'Using dma' was enabled on
the hdd; when I turned it off, I get only a few messages about lost
interrupts but a lot about dma problems. According to the kernel log,
the AMD workaround for the ochi-Viper problem is enabled. The test does
work correctly the first time I try it after bringing the system up.
Here is the memory management code:

/**********************************************************************
 *
 * Memory management
 *
 * This is a shameless copy from the USB-cpia driver (linux kernel
 * version 2.3.29 or so, I have no idea what this code actually does ;).
 * Actually it seems to be a copy of a shameless copy of the
bttv-driver.
 * Or that is a copy of a shameless copy of ... (To the powers: is there
 * no generic kernel-function to do this sort of stuff?)
 *
 * Yes, it was a shameless copy from the bttv-driver. IIRC, Alan says
 * there will be one, but apparentely not yet -jerdfelt
 *
 * So I copied it again for the ov511 driver -claudio
 *
 * Same for the se401 driver -Jeroen
 *
 * And for the STV0680 driver - Kevin
 **********************************************************************/

/* Given PGD from the address space's page table, return the kernel
 * virtual mapping of the physical memory mapped at ADR.
 */
static inline unsigned long uvirt_to_kva(pgd_t *pgd, unsigned long adr)
{
        unsigned long ret = 0UL;
        pmd_t *pmd;
        pte_t *ptep, pte;

        if (!pgd_none(*pgd)) {
                pmd = pmd_offset(pgd, adr);
                if (!pmd_none(*pmd)) {
                        ptep = pte_offset(pmd, adr);
                        pte = *ptep;
                        if (pte_present(pte)) {
                                ret = (unsigned long)
page_address(pte_page(pte));
                                ret |= (adr & (PAGE_SIZE - 1));
                        }
                }
        }
        return ret;
}

/* Here we want the physical address of the memory. This is used when 
 * initializing the contents of the area and marking the pages as
reserved.
*/
static inline unsigned long kvirt_to_pa(unsigned long adr)
{
        unsigned long va, kva, ret;

        va = VMALLOC_VMADDR(adr);
        kva = uvirt_to_kva(pgd_offset_k(va), va);
        ret = __pa(kva);
        return ret;
}

static void *rvmalloc(unsigned long size)
{
        void *mem;
        unsigned long adr, page;

        /* Round it off to PAGE_SIZE */
        size += (PAGE_SIZE - 1);
        size &= ~(PAGE_SIZE - 1);

        mem = vmalloc_32(size);
        if (!mem)
                return NULL;

        memset(mem, 0, size); /* Clear the ram out, no junk to the user
*/
        adr = (unsigned long) mem;
        while (size > 0) {
                page = kvirt_to_pa(adr);
                mem_map_reserve(virt_to_page(__va(page)));
                adr += PAGE_SIZE;
                if (size > PAGE_SIZE)
                        size -= PAGE_SIZE;
                else
                        size = 0;
        }
        return mem;
}

static void rvfree(void *mem, unsigned long size)
{
        unsigned long adr, page;

        if (!mem)
                return;

        size += (PAGE_SIZE - 1);
        size &= ~(PAGE_SIZE - 1);

        adr=(unsigned long) mem;
        while (size > 0) {
                page = kvirt_to_pa(adr);
                mem_map_unreserve(virt_to_page(__va(page)));
                adr += PAGE_SIZE;
                if (size > PAGE_SIZE)
                        size -= PAGE_SIZE;
                else
                        size = 0;
        }
        vfree(mem);
}
/*****************   Mmeory Management  **********************/


and the raw buffer is allocated and used as
  
    raw = rvmalloc(bufsize);   ** ->  I get bufsize from the camera
    if (raw == NULL) {
        info("Out of memory for raw buffer");
        goto error;
    }

......
 The still picture  and video download both use bulk transfer, which I
set up using usb_bulk_get(dev, raw, bufsize). I essentially copied the
routine from the skel_read routine in usb-skeleton.c (version 0.4,
8/21/01). Remember, this stuff works if I use kmalloc instead of
rvmalloc (I also tried just vmalloc; same problem).

        Thinking that this was somehow related to the ochi controller, I went
to another computer (Asus MB, AMD K6-3-400, Intel 430TX chipset,
usb-uchi MB controller, running the same software). Both computers have
128MB memory; the slower machine has a WD 10GB hdd on IDE0, and has a
cdrw and 250 MB zip on IDE1. Now I have the original crash problem; any
call to usb_control_msg(dev, pipe,...) gives me a kernel oops (these
calls are used to initialize the camera, get the bufsize, etc). I
thought I had solved this problem when I went to the faster machine,
because I had to upgrade the kernel (AMD chipset problem) and I changed
the request type slightly (see previous post). Apparently, the problem
was solved because I went to an ochi controller. This doesn't make sense
to me, as the camera works with the Win98 drivers and with
usb-robot-slave commands determined from the Win sniff usb program, with
either usb controller. So, now I can't check out the rvmalloc problem on
an uchi computer because of the oops, and I can't get the buffer memory
I need (the processed picture buffer is 3x the raw (~77KB); kmalloc
limits me to 128KB) on the ochi, which doesn't have the oops. This is
getting very frustrating; any ideas would be greatly appreciated.

        Kevin


_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to