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