Commit 33110a83 authored by Ingo Molnar's avatar Ingo Molnar

- cleanup patch from Hugh Dickins, fix up drivers to use vmalloc_to_page()...

- cleanup patch from Hugh Dickins, fix up drivers to use vmalloc_to_page() instead of local hacks of uvirt_to_kva(). (and related fixes.)
parent 38432d05
...@@ -332,35 +332,8 @@ perfmon_get_stamp(void) ...@@ -332,35 +332,8 @@ perfmon_get_stamp(void)
return ia64_get_itc(); return ia64_get_itc();
} }
/* 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));
}
}
}
DBprintk(("uv2kva(%lx-->%lx)\n", adr, ret));
return ret;
}
/* Here we want the physical address of the memory. /* Here we want the physical address of the memory.
* This is used when initializing the contents of the * This is used when initializing the contents of the area.
* area and marking the pages as reserved.
*/ */
static inline unsigned long static inline unsigned long
kvirt_to_pa(unsigned long adr) kvirt_to_pa(unsigned long adr)
...@@ -374,19 +347,15 @@ static void * ...@@ -374,19 +347,15 @@ static void *
rvmalloc(unsigned long size) rvmalloc(unsigned long size)
{ {
void *mem; void *mem;
unsigned long adr, page; unsigned long adr;
/* XXX: may have to revisit this part because size=PAGE_ALIGN(size);
* vmalloc() does not necessarily return a page-aligned buffer.
* This maybe a security problem when mapped at user level
*/
mem=vmalloc(size); mem=vmalloc(size);
if (mem) { if (mem) {
memset(mem, 0, size); /* Clear the ram out, no junk to the user */ memset(mem, 0, size); /* Clear the ram out, no junk to the user */
adr=(unsigned long) mem; adr=(unsigned long) mem;
while (size > 0) { while (size > 0) {
page = kvirt_to_pa(adr); mem_map_reserve(vmalloc_to_page((void *)adr));
mem_map_reserve(virt_to_page(__va(page)));
adr+=PAGE_SIZE; adr+=PAGE_SIZE;
size-=PAGE_SIZE; size-=PAGE_SIZE;
} }
...@@ -397,13 +366,12 @@ rvmalloc(unsigned long size) ...@@ -397,13 +366,12 @@ rvmalloc(unsigned long size)
static void static void
rvfree(void *mem, unsigned long size) rvfree(void *mem, unsigned long size)
{ {
unsigned long adr, page; unsigned long adr;
if (mem) { if (mem) {
adr=(unsigned long) mem; adr=(unsigned long) mem;
while (size > 0) { while ((long) size > 0) {
page = kvirt_to_pa(adr); mem_map_unreserve(vmalloc_to_page((void *)adr));
mem_map_unreserve(virt_to_page(__va(page)));
adr+=PAGE_SIZE; adr+=PAGE_SIZE;
size-=PAGE_SIZE; size-=PAGE_SIZE;
} }
...@@ -515,7 +483,6 @@ pfm_smpl_buffer_alloc(pfm_context_t *ctx, unsigned long which_pmds, unsigned lon ...@@ -515,7 +483,6 @@ pfm_smpl_buffer_alloc(pfm_context_t *ctx, unsigned long which_pmds, unsigned lon
vma->vm_file = NULL; vma->vm_file = NULL;
vma->vm_raend = 0; vma->vm_raend = 0;
/* XXX: see rvmalloc() for page alignment problem */
smpl_buf = rvmalloc(size); smpl_buf = rvmalloc(size);
if (smpl_buf == NULL) goto no_buffer; if (smpl_buf == NULL) goto no_buffer;
......
...@@ -66,9 +66,6 @@ int DRM(sg_alloc)( struct inode *inode, struct file *filp, ...@@ -66,9 +66,6 @@ int DRM(sg_alloc)( struct inode *inode, struct file *filp,
drm_scatter_gather_t request; drm_scatter_gather_t request;
drm_sg_mem_t *entry; drm_sg_mem_t *entry;
unsigned long pages, i, j; unsigned long pages, i, j;
pgd_t *pgd;
pmd_t *pmd;
pte_t *pte, pte_entry;
DRM_DEBUG( "%s\n", __FUNCTION__ ); DRM_DEBUG( "%s\n", __FUNCTION__ );
...@@ -135,25 +132,9 @@ int DRM(sg_alloc)( struct inode *inode, struct file *filp, ...@@ -135,25 +132,9 @@ int DRM(sg_alloc)( struct inode *inode, struct file *filp,
DRM_DEBUG( "sg alloc virtual = %p\n", entry->virtual ); DRM_DEBUG( "sg alloc virtual = %p\n", entry->virtual );
for ( i = entry->handle, j = 0 ; j < pages ; i += PAGE_SIZE, j++ ) { for ( i = entry->handle, j = 0 ; j < pages ; i += PAGE_SIZE, j++ ) {
pgd = pgd_offset_k( i ); entry->pagelist[j] = vmalloc_to_page((void *)i);
if ( !pgd_present( *pgd ) ) if (!entry->pagelist[j])
goto failed; goto failed;
pmd = pmd_offset( pgd, i );
if ( !pmd_present( *pmd ) )
goto failed;
preempt_disable();
pte = pte_offset_map(pmd, i);
pte_entry = *pte;
pte_unmap(pte);
preempt_enable();
if (!pte_present(pte_entry))
goto failed;
entry->pagelist[j] = pte_page(pte_entry);
SetPageReserved(entry->pagelist[j]); SetPageReserved(entry->pagelist[j]);
} }
......
...@@ -152,9 +152,6 @@ struct page *DRM(vm_shm_nopage)(struct vm_area_struct *vma, ...@@ -152,9 +152,6 @@ struct page *DRM(vm_shm_nopage)(struct vm_area_struct *vma,
#endif #endif
unsigned long offset; unsigned long offset;
unsigned long i; unsigned long i;
pgd_t *pgd;
pmd_t *pmd;
pte_t *pte, entry;
struct page *page; struct page *page;
if (address > vma->vm_end) return NOPAGE_SIGBUS; /* Disallow mremap */ if (address > vma->vm_end) return NOPAGE_SIGBUS; /* Disallow mremap */
...@@ -162,26 +159,9 @@ struct page *DRM(vm_shm_nopage)(struct vm_area_struct *vma, ...@@ -162,26 +159,9 @@ struct page *DRM(vm_shm_nopage)(struct vm_area_struct *vma,
offset = address - vma->vm_start; offset = address - vma->vm_start;
i = (unsigned long)map->handle + offset; i = (unsigned long)map->handle + offset;
/* We have to walk page tables here because we need large SAREA's, and page = vmalloc_to_page((void *)i);
* they need to be virtually contiguous in kernel space. if (!page)
*/ return NOPAGE_OOM;
pgd = pgd_offset_k( i );
if (!pgd_present(*pgd))
goto oom;
pmd = pmd_offset( pgd, i );
if (!pmd_present(*pmd))
goto oom;
preempt_disable();
pte = pte_offset_map(pmd, i);
entry = *pte;
pte_unmap(pte);
preempt_enable();
if (!pte_present(entry))
goto oom;
page = pte_page(entry);
get_page(page); get_page(page);
DRM_DEBUG("shm_nopage 0x%lx\n", address); DRM_DEBUG("shm_nopage 0x%lx\n", address);
...@@ -190,8 +170,6 @@ struct page *DRM(vm_shm_nopage)(struct vm_area_struct *vma, ...@@ -190,8 +170,6 @@ struct page *DRM(vm_shm_nopage)(struct vm_area_struct *vma,
#else #else
return page; return page;
#endif #endif
oom:
return NOPAGE_OOM;
} }
/* Special close routine which deletes map information if we are the last /* Special close routine which deletes map information if we are the last
......
...@@ -185,78 +185,19 @@ static inline struct video_card* file_to_video_card(struct file *file) ...@@ -185,78 +185,19 @@ static inline struct video_card* file_to_video_card(struct file *file)
/* Memory management functions */ /* Memory management functions */
/*******************************/ /*******************************/
#define MDEBUG(x) do { } while(0) /* Debug memory management */
/* [DaveM] I've recoded most of this so that:
* 1) It's easier to tell what is happening
* 2) It's more portable, especially for translating things
* out of vmalloc mapped areas in the kernel.
* 3) Less unnecessary translations happen.
*
* The code used to assume that the kernel vmalloc mappings
* existed in the page tables of every process, this is simply
* not guarenteed. We now use pgd_offset_k which is the
* defined way to get at the kernel page tables.
*/
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0)
#define page_address(x) (x)
#endif
/* Given PGD from the address space's page table, return the kernel
* virtual mapping of the physical memory mapped at ADR.
*/
static inline struct page *uvirt_to_page(pgd_t *pgd, unsigned long adr)
{
pmd_t *pmd;
pte_t *ptep, pte;
struct page *ret = NULL;
if (!pgd_none(*pgd)) {
pmd = pmd_offset(pgd, adr);
if (!pmd_none(*pmd)) {
preempt_disable();
ptep = pte_offset_map(pmd, adr);
pte = *ptep;
pte_unmap(pte);
preempt_enable();
if(pte_present(pte))
ret = pte_page(pte);
}
}
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, and for
* handling page faults on the rvmalloc()ed buffer
*/
static inline unsigned long kvirt_to_pa(unsigned long adr)
{
unsigned long va, kva, ret;
va = VMALLOC_VMADDR(adr);
kva = (unsigned long) page_address(uvirt_to_page(pgd_offset_k(va), va));
kva |= adr & (PAGE_SIZE-1); /* restore the offset */
ret = __pa(kva);
MDEBUG(printk("kv2pa(%lx-->%lx)", adr, ret));
return ret;
}
static void * rvmalloc(unsigned long size) static void * rvmalloc(unsigned long size)
{ {
void * mem; void * mem;
unsigned long adr, page; unsigned long adr;
size=PAGE_ALIGN(size);
mem=vmalloc_32(size); mem=vmalloc_32(size);
if (mem) { if (mem) {
memset(mem, 0, size); /* Clear the ram out, memset(mem, 0, size); /* Clear the ram out,
no junk to the user */ no junk to the user */
adr=(unsigned long) mem; adr=(unsigned long) mem;
while (size > 0) { while (size > 0) {
page = kvirt_to_pa(adr); mem_map_reserve(vmalloc_to_page((void *)adr));
mem_map_reserve(virt_to_page(__va(page)));
adr+=PAGE_SIZE; adr+=PAGE_SIZE;
size-=PAGE_SIZE; size-=PAGE_SIZE;
} }
...@@ -266,13 +207,12 @@ static void * rvmalloc(unsigned long size) ...@@ -266,13 +207,12 @@ static void * rvmalloc(unsigned long size)
static void rvfree(void * mem, unsigned long size) static void rvfree(void * mem, unsigned long size)
{ {
unsigned long adr, page; unsigned long adr;
if (mem) { if (mem) {
adr=(unsigned long) mem; adr=(unsigned long) mem;
while (size > 0) { while ((long) size > 0) {
page = kvirt_to_pa(adr); mem_map_unreserve(vmalloc_to_page((void *)adr));
mem_map_unreserve(virt_to_page(__va(page)));
adr+=PAGE_SIZE; adr+=PAGE_SIZE;
size-=PAGE_SIZE; size-=PAGE_SIZE;
} }
...@@ -1166,9 +1106,9 @@ static int do_dv1394_init(struct video_card *video, struct dv1394_init *init) ...@@ -1166,9 +1106,9 @@ static int do_dv1394_init(struct video_card *video, struct dv1394_init *init)
/* fill the sglist with the kernel addresses of pages in the non-contiguous buffer */ /* fill the sglist with the kernel addresses of pages in the non-contiguous buffer */
for(i = 0; i < video->user_dma.n_pages; i++) { for(i = 0; i < video->user_dma.n_pages; i++) {
unsigned long va = VMALLOC_VMADDR( (unsigned long) video->user_buf + i * PAGE_SIZE ); unsigned long va = (unsigned long) video->user_buf + i * PAGE_SIZE;
video->user_dma.sglist[i].page = uvirt_to_page(pgd_offset_k(va), va); video->user_dma.sglist[i].page = vmalloc_to_page((void *)va);
video->user_dma.sglist[i].length = PAGE_SIZE; video->user_dma.sglist[i].length = PAGE_SIZE;
} }
...@@ -1492,7 +1432,7 @@ static int do_dv1394_shutdown(struct video_card *video, int free_user_buf) ...@@ -1492,7 +1432,7 @@ static int do_dv1394_shutdown(struct video_card *video, int free_user_buf)
static struct page * dv1394_nopage(struct vm_area_struct * area, unsigned long address, int write_access) static struct page * dv1394_nopage(struct vm_area_struct * area, unsigned long address, int write_access)
{ {
unsigned long offset; unsigned long offset;
unsigned long page, kernel_virt_addr; unsigned long kernel_virt_addr;
struct page *ret = NOPAGE_SIGBUS; struct page *ret = NOPAGE_SIGBUS;
struct video_card *video = (struct video_card*) area->vm_private_data; struct video_card *video = (struct video_card*) area->vm_private_data;
...@@ -1510,10 +1450,7 @@ static struct page * dv1394_nopage(struct vm_area_struct * area, unsigned long a ...@@ -1510,10 +1450,7 @@ static struct page * dv1394_nopage(struct vm_area_struct * area, unsigned long a
offset = address - area->vm_start; offset = address - area->vm_start;
kernel_virt_addr = (unsigned long) video->user_buf + offset; kernel_virt_addr = (unsigned long) video->user_buf + offset;
ret = vmalloc_to_page((void *)kernel_virt_addr);
page = kvirt_to_pa(kernel_virt_addr);
ret = virt_to_page(__va(page));
get_page(ret); get_page(ret);
out: out:
......
...@@ -159,49 +159,35 @@ static struct hpsb_highlevel *hl_handle = NULL; ...@@ -159,49 +159,35 @@ static struct hpsb_highlevel *hl_handle = NULL;
/* Memory management functions */ /* Memory management functions */
/*******************************/ /*******************************/
#define MDEBUG(x) do { } while(0) /* Debug memory management */
/* [DaveM] I've recoded most of this so that:
* 1) It's easier to tell what is happening
* 2) It's more portable, especially for translating things
* out of vmalloc mapped areas in the kernel.
* 3) Less unnecessary translations happen.
*
* The code used to assume that the kernel vmalloc mappings
* existed in the page tables of every process, this is simply
* not guaranteed. We now use pgd_offset_k which is the
* defined way to get at the kernel page tables.
*/
static inline unsigned long kvirt_to_bus(unsigned long adr) static inline unsigned long kvirt_to_bus(unsigned long adr)
{ {
unsigned long kva, ret; unsigned long kva, ret;
kva = page_address(vmalloc_to_page((void *)adr)); kva = (unsigned long) page_address(vmalloc_to_page((void *)adr));
kva |= adr & (PAGE_SIZE-1); /* restore the offset */
ret = virt_to_bus((void *)kva); ret = virt_to_bus((void *)kva);
MDEBUG(printk("kv2b(%lx-->%lx)", adr, ret));
return ret; return ret;
} }
/* Here we want the physical address of the memory. /* Here we want the physical address of the memory.
* This is used when initializing the contents of the * This is used when initializing the contents of the area.
* area and marking the pages as reserved.
*/ */
static inline unsigned long kvirt_to_pa(unsigned long adr) static inline unsigned long kvirt_to_pa(unsigned long adr)
{ {
unsigned long kva, ret; unsigned long kva, ret;
kva = page_address(vmalloc_to_page((void *)adr)); kva = (unsigned long) page_address(vmalloc_to_page((void *)adr));
kva |= adr & (PAGE_SIZE-1); /* restore the offset */
ret = __pa(kva); ret = __pa(kva);
MDEBUG(printk("kv2pa(%lx-->%lx)", adr, ret));
return ret; return ret;
} }
static void * rvmalloc(unsigned long size) static void * rvmalloc(unsigned long size)
{ {
void * mem; void * mem;
unsigned long adr, page; unsigned long adr;
size=PAGE_ALIGN(size);
mem=vmalloc_32(size); mem=vmalloc_32(size);
if (mem) if (mem)
{ {
...@@ -210,8 +196,7 @@ static void * rvmalloc(unsigned long size) ...@@ -210,8 +196,7 @@ static void * rvmalloc(unsigned long size)
adr=(unsigned long) mem; adr=(unsigned long) mem;
while (size > 0) while (size > 0)
{ {
page = kvirt_to_pa(adr); mem_map_reserve(vmalloc_to_page((void *)adr));
mem_map_reserve(virt_to_page(__va(page)));
adr+=PAGE_SIZE; adr+=PAGE_SIZE;
size-=PAGE_SIZE; size-=PAGE_SIZE;
} }
...@@ -221,15 +206,14 @@ static void * rvmalloc(unsigned long size) ...@@ -221,15 +206,14 @@ static void * rvmalloc(unsigned long size)
static void rvfree(void * mem, unsigned long size) static void rvfree(void * mem, unsigned long size)
{ {
unsigned long adr, page; unsigned long adr;
if (mem) if (mem)
{ {
adr=(unsigned long) mem; adr=(unsigned long) mem;
while (size > 0) while ((long) size > 0)
{ {
page = kvirt_to_pa(adr); mem_map_unreserve(vmalloc_to_page((void *)adr));
mem_map_unreserve(virt_to_page(__va(page)));
adr+=PAGE_SIZE; adr+=PAGE_SIZE;
size-=PAGE_SIZE; size-=PAGE_SIZE;
} }
...@@ -1369,7 +1353,7 @@ int video1394_mmap(struct file *file, struct vm_area_struct *vma) ...@@ -1369,7 +1353,7 @@ int video1394_mmap(struct file *file, struct vm_area_struct *vma)
if (video->current_ctx == NULL) { if (video->current_ctx == NULL) {
PRINT(KERN_ERR, ohci->id, "Current iso context not set"); PRINT(KERN_ERR, ohci->id, "Current iso context not set");
} else } else
res = do_iso_mmap(ohci, video->current_ctx, res = do_iso_mmap(vma, ohci, video->current_ctx,
(char *)vma->vm_start, (char *)vma->vm_start,
(unsigned long)(vma->vm_end-vma->vm_start)); (unsigned long)(vma->vm_end-vma->vm_start));
unlock_kernel(); unlock_kernel();
......
...@@ -172,8 +172,7 @@ static inline unsigned long kvirt_to_bus(unsigned long addr) ...@@ -172,8 +172,7 @@ static inline unsigned long kvirt_to_bus(unsigned long addr)
} }
/* Here we want the physical address of the memory. /* Here we want the physical address of the memory.
* This is used when initializing the contents of the * This is used when initializing the contents of the area.
* area and marking the pages as reserved.
*/ */
static inline unsigned long kvirt_to_pa(unsigned long addr) static inline unsigned long kvirt_to_pa(unsigned long addr)
{ {
...@@ -183,14 +182,15 @@ static inline unsigned long kvirt_to_pa(unsigned long addr) ...@@ -183,14 +182,15 @@ static inline unsigned long kvirt_to_pa(unsigned long addr)
return ret; return ret;
} }
static void * rvmalloc(signed long size) static void * rvmalloc(unsigned long size)
{ {
void * mem; void * mem;
unsigned long adr; unsigned long adr;
size=PAGE_ALIGN(size);
mem=vmalloc_32(size); mem=vmalloc_32(size);
if (NULL == mem) if (NULL == mem)
printk(KERN_INFO "bttv: vmalloc_32(%ld) failed\n",size); printk(KERN_INFO "bttv: vmalloc_32(%lu) failed\n",size);
else { else {
/* Clear the ram out, no junk to the user */ /* Clear the ram out, no junk to the user */
memset(mem, 0, size); memset(mem, 0, size);
...@@ -205,14 +205,14 @@ static void * rvmalloc(signed long size) ...@@ -205,14 +205,14 @@ static void * rvmalloc(signed long size)
return mem; return mem;
} }
static void rvfree(void * mem, signed long size) static void rvfree(void * mem, unsigned long size)
{ {
unsigned long adr; unsigned long adr;
if (mem) if (mem)
{ {
adr=(unsigned long) mem; adr=(unsigned long) mem;
while (size > 0) while ((long) size > 0)
{ {
mem_map_unreserve(vmalloc_to_page((void *)adr)); mem_map_unreserve(vmalloc_to_page((void *)adr));
adr+=PAGE_SIZE; adr+=PAGE_SIZE;
......
...@@ -181,14 +181,14 @@ static void reset_camera_struct(struct cam_data *cam); ...@@ -181,14 +181,14 @@ static void reset_camera_struct(struct cam_data *cam);
**********************************************************************/ **********************************************************************/
/* Here we want the physical address of the memory. /* Here we want the physical address of the memory.
* This is used when initializing the contents of the * This is used when initializing the contents of the area.
* area and marking the pages as reserved.
*/ */
static inline unsigned long kvirt_to_pa(unsigned long adr) static inline unsigned long kvirt_to_pa(unsigned long adr)
{ {
unsigned long kva, ret; unsigned long kva, ret;
kva = page_address(vmalloc_to_page((void *)adr)); kva = (unsigned long) page_address(vmalloc_to_page((void *)adr));
kva |= adr & (PAGE_SIZE-1); /* restore the offset */
ret = __pa(kva); ret = __pa(kva);
return ret; return ret;
} }
...@@ -196,12 +196,9 @@ static inline unsigned long kvirt_to_pa(unsigned long adr) ...@@ -196,12 +196,9 @@ static inline unsigned long kvirt_to_pa(unsigned long adr)
static void *rvmalloc(unsigned long size) static void *rvmalloc(unsigned long size)
{ {
void *mem; void *mem;
unsigned long adr, page; unsigned long adr;
/* Round it off to PAGE_SIZE */
size += (PAGE_SIZE - 1);
size &= ~(PAGE_SIZE - 1);
size = PAGE_ALIGN(size);
mem = vmalloc_32(size); mem = vmalloc_32(size);
if (!mem) if (!mem)
return NULL; return NULL;
...@@ -209,13 +206,9 @@ static void *rvmalloc(unsigned long size) ...@@ -209,13 +206,9 @@ static void *rvmalloc(unsigned long size)
memset(mem, 0, size); /* Clear the ram out, no junk to the user */ memset(mem, 0, size); /* Clear the ram out, no junk to the user */
adr = (unsigned long) mem; adr = (unsigned long) mem;
while (size > 0) { while (size > 0) {
page = kvirt_to_pa(adr); mem_map_reserve(vmalloc_to_page((void *)adr));
mem_map_reserve(virt_to_page(__va(page)));
adr += PAGE_SIZE; adr += PAGE_SIZE;
if (size > PAGE_SIZE) size -= PAGE_SIZE;
size -= PAGE_SIZE;
else
size = 0;
} }
return mem; return mem;
...@@ -223,23 +216,16 @@ static void *rvmalloc(unsigned long size) ...@@ -223,23 +216,16 @@ static void *rvmalloc(unsigned long size)
static void rvfree(void *mem, unsigned long size) static void rvfree(void *mem, unsigned long size)
{ {
unsigned long adr, page; unsigned long adr;
if (!mem) if (!mem)
return; return;
size += (PAGE_SIZE - 1);
size &= ~(PAGE_SIZE - 1);
adr = (unsigned long) mem; adr = (unsigned long) mem;
while (size > 0) { while ((long) size > 0) {
page = kvirt_to_pa(adr); mem_map_unreserve(vmalloc_to_page((void *)adr));
mem_map_unreserve(virt_to_page(__va(page)));
adr += PAGE_SIZE; adr += PAGE_SIZE;
if (size > PAGE_SIZE) size -= PAGE_SIZE;
size -= PAGE_SIZE;
else
size = 0;
} }
vfree(mem); vfree(mem);
} }
......
...@@ -115,33 +115,29 @@ static inline int meye_emptyq(struct meye_queue *queue, int *elem) { ...@@ -115,33 +115,29 @@ static inline int meye_emptyq(struct meye_queue *queue, int *elem) {
/* Memory allocation routines (stolen from bttv-driver.c) */ /* Memory allocation routines (stolen from bttv-driver.c) */
/****************************************************************************/ /****************************************************************************/
#define MDEBUG(x) do {} while (0)
/* #define MDEBUG(x) x */
/* Here we want the physical address of the memory. /* Here we want the physical address of the memory.
* This is used when initializing the contents of the * This is used when initializing the contents of the area.
* area and marking the pages as reserved.
*/ */
static inline unsigned long kvirt_to_pa(unsigned long adr) { static inline unsigned long kvirt_to_pa(unsigned long adr) {
unsigned long kva, ret; unsigned long kva, ret;
kva = page_address(vmalloc_to_page((void *) adr)); kva = (unsigned long) page_address(vmalloc_to_page((void *)adr));
kva |= adr & (PAGE_SIZE-1); /* restore the offset */
ret = __pa(kva); ret = __pa(kva);
MDEBUG(printk("kv2pa(%lx-->%lx)\n", adr, ret));
return ret; return ret;
} }
static void *rvmalloc(signed long size) { static void *rvmalloc(unsigned long size) {
void *mem; void *mem;
unsigned long adr, page; unsigned long adr;
size = PAGE_ALIGN(size);
mem = vmalloc_32(size); mem = vmalloc_32(size);
if (mem) { if (mem) {
memset(mem, 0, size); /* Clear the ram out, no junk to the user */ memset(mem, 0, size); /* Clear the ram out, no junk to the user */
adr = (unsigned long)mem; adr = (unsigned long)mem;
while (size > 0) { while (size > 0) {
page = kvirt_to_pa(adr); mem_map_reserve(vmalloc_to_page((void *)adr));
mem_map_reserve(virt_to_page(__va(page)));
adr += PAGE_SIZE; adr += PAGE_SIZE;
size -= PAGE_SIZE; size -= PAGE_SIZE;
} }
...@@ -149,14 +145,13 @@ static void *rvmalloc(signed long size) { ...@@ -149,14 +145,13 @@ static void *rvmalloc(signed long size) {
return mem; return mem;
} }
static void rvfree(void * mem, signed long size) { static void rvfree(void * mem, unsigned long size) {
unsigned long adr, page; unsigned long adr;
if (mem) { if (mem) {
adr = (unsigned long) mem; adr = (unsigned long) mem;
while (size > 0) { while ((long) size > 0) {
page = kvirt_to_pa(adr); mem_map_unreserve(vmalloc_to_page((void *)adr));
mem_map_unreserve(virt_to_page(__va(page)));
adr += PAGE_SIZE; adr += PAGE_SIZE;
size -= PAGE_SIZE; size -= PAGE_SIZE;
} }
......
...@@ -379,15 +379,15 @@ static unsigned char uvQuanTable518[] = OV518_UVQUANTABLE; ...@@ -379,15 +379,15 @@ static unsigned char uvQuanTable518[] = OV518_UVQUANTABLE;
**********************************************************************/ **********************************************************************/
/* Here we want the physical address of the memory. /* Here we want the physical address of the memory.
* This is used when initializing the contents of the * This is used when initializing the contents of the area.
* area and marking the pages as reserved.
*/ */
static inline unsigned long static inline unsigned long
kvirt_to_pa(unsigned long adr) kvirt_to_pa(unsigned long adr)
{ {
unsigned long kva, ret; unsigned long kva, ret;
kva = page_address(vmalloc_to_page((void *)adr)); kva = (unsigned long) page_address(vmalloc_to_page((void *)adr));
kva |= adr & (PAGE_SIZE-1); /* restore the offset */
ret = __pa(kva); ret = __pa(kva);
return ret; return ret;
} }
...@@ -396,12 +396,9 @@ static void * ...@@ -396,12 +396,9 @@ static void *
rvmalloc(unsigned long size) rvmalloc(unsigned long size)
{ {
void *mem; void *mem;
unsigned long adr, page; unsigned long adr;
/* Round it off to PAGE_SIZE */
size += (PAGE_SIZE - 1);
size &= ~(PAGE_SIZE - 1);
size = PAGE_ALIGN(size);
mem = vmalloc_32(size); mem = vmalloc_32(size);
if (!mem) if (!mem)
return NULL; return NULL;
...@@ -409,13 +406,9 @@ rvmalloc(unsigned long size) ...@@ -409,13 +406,9 @@ rvmalloc(unsigned long size)
memset(mem, 0, size); /* Clear the ram out, no junk to the user */ memset(mem, 0, size); /* Clear the ram out, no junk to the user */
adr = (unsigned long) mem; adr = (unsigned long) mem;
while (size > 0) { while (size > 0) {
page = kvirt_to_pa(adr); mem_map_reserve(vmalloc_to_page((void *)adr));
mem_map_reserve(virt_to_page(__va(page)));
adr += PAGE_SIZE; adr += PAGE_SIZE;
if (size > PAGE_SIZE) size -= PAGE_SIZE;
size -= PAGE_SIZE;
else
size = 0;
} }
return mem; return mem;
...@@ -424,23 +417,16 @@ rvmalloc(unsigned long size) ...@@ -424,23 +417,16 @@ rvmalloc(unsigned long size)
static void static void
rvfree(void *mem, unsigned long size) rvfree(void *mem, unsigned long size)
{ {
unsigned long adr, page; unsigned long adr;
if (!mem) if (!mem)
return; return;
size += (PAGE_SIZE - 1); adr = (unsigned long) mem;
size &= ~(PAGE_SIZE - 1); while ((long) size > 0) {
mem_map_unreserve(vmalloc_to_page((void *)adr));
adr=(unsigned long) mem;
while (size > 0) {
page = kvirt_to_pa(adr);
mem_map_unreserve(virt_to_page(__va(page)));
adr += PAGE_SIZE; adr += PAGE_SIZE;
if (size > PAGE_SIZE) size -= PAGE_SIZE;
size -= PAGE_SIZE;
else
size = 0;
} }
vfree(mem); vfree(mem);
} }
......
...@@ -179,27 +179,24 @@ static struct video_device pwc_template = { ...@@ -179,27 +179,24 @@ static struct video_device pwc_template = {
/* Private functions */ /* Private functions */
/* Here we want the physical address of the memory. /* Here we want the physical address of the memory.
* This is used when initializing the contents of the * This is used when initializing the contents of the area.
* area and marking the pages as reserved.
*/ */
static inline unsigned long kvirt_to_pa(unsigned long adr) static inline unsigned long kvirt_to_pa(unsigned long adr)
{ {
unsigned long kva, ret; unsigned long kva, ret;
kva = page_address(vmalloc_to_page((void *)adr)); kva = (unsigned long) page_address(vmalloc_to_page((void *)adr));
kva |= adr & (PAGE_SIZE-1); /* restore the offset */
ret = __pa(kva); ret = __pa(kva);
return ret; return ret;
} }
static void * rvmalloc(signed long size) static void * rvmalloc(unsigned long size)
{ {
void * mem; void * mem;
unsigned long adr, page; unsigned long adr;
/* Round it off to PAGE_SIZE */ size=PAGE_ALIGN(size);
size += (PAGE_SIZE - 1);
size &= ~(PAGE_SIZE - 1);
mem=vmalloc_32(size); mem=vmalloc_32(size);
if (mem) if (mem)
{ {
...@@ -207,8 +204,7 @@ static void * rvmalloc(signed long size) ...@@ -207,8 +204,7 @@ static void * rvmalloc(signed long size)
adr=(unsigned long) mem; adr=(unsigned long) mem;
while (size > 0) while (size > 0)
{ {
page = kvirt_to_pa(adr); mem_map_reserve(vmalloc_to_page((void *)adr));
mem_map_reserve(virt_to_page(__va(page)));
adr+=PAGE_SIZE; adr+=PAGE_SIZE;
size-=PAGE_SIZE; size-=PAGE_SIZE;
} }
...@@ -216,20 +212,16 @@ static void * rvmalloc(signed long size) ...@@ -216,20 +212,16 @@ static void * rvmalloc(signed long size)
return mem; return mem;
} }
static void rvfree(void * mem, signed long size) static void rvfree(void * mem, unsigned long size)
{ {
unsigned long adr, page; unsigned long adr;
/* Round it off to PAGE_SIZE */
size += (PAGE_SIZE - 1);
size &= ~(PAGE_SIZE - 1);
if (mem) if (mem)
{ {
adr=(unsigned long) mem; adr=(unsigned long) mem;
while (size > 0) while ((long) size > 0)
{ {
page = kvirt_to_pa(adr); mem_map_unreserve(vmalloc_to_page((void *)adr));
mem_map_unreserve(virt_to_page(__va(page)));
adr+=PAGE_SIZE; adr+=PAGE_SIZE;
size-=PAGE_SIZE; size-=PAGE_SIZE;
} }
......
...@@ -84,14 +84,14 @@ static struct usb_driver se401_driver; ...@@ -84,14 +84,14 @@ static struct usb_driver se401_driver;
**********************************************************************/ **********************************************************************/
/* Here we want the physical address of the memory. /* Here we want the physical address of the memory.
* This is used when initializing the contents of the * This is used when initializing the contents of the area.
* area and marking the pages as reserved.
*/ */
static inline unsigned long kvirt_to_pa(unsigned long adr) static inline unsigned long kvirt_to_pa(unsigned long adr)
{ {
unsigned long kva, ret; unsigned long kva, ret;
kva = page_address(vmalloc_to_page((void *)adr)); kva = (unsigned long) page_address(vmalloc_to_page((void *)adr));
kva |= adr & (PAGE_SIZE-1); /* restore the offset */
ret = __pa(kva); ret = __pa(kva);
return ret; return ret;
} }
...@@ -99,12 +99,9 @@ static inline unsigned long kvirt_to_pa(unsigned long adr) ...@@ -99,12 +99,9 @@ static inline unsigned long kvirt_to_pa(unsigned long adr)
static void *rvmalloc(unsigned long size) static void *rvmalloc(unsigned long size)
{ {
void *mem; void *mem;
unsigned long adr, page; unsigned long adr;
/* Round it off to PAGE_SIZE */
size += (PAGE_SIZE - 1);
size &= ~(PAGE_SIZE - 1);
size = PAGE_ALIGN(size);
mem = vmalloc_32(size); mem = vmalloc_32(size);
if (!mem) if (!mem)
return NULL; return NULL;
...@@ -112,13 +109,9 @@ static void *rvmalloc(unsigned long size) ...@@ -112,13 +109,9 @@ static void *rvmalloc(unsigned long size)
memset(mem, 0, size); /* Clear the ram out, no junk to the user */ memset(mem, 0, size); /* Clear the ram out, no junk to the user */
adr = (unsigned long) mem; adr = (unsigned long) mem;
while (size > 0) { while (size > 0) {
page = kvirt_to_pa(adr); mem_map_reserve(vmalloc_to_page((void *)adr));
mem_map_reserve(virt_to_page(__va(page)));
adr += PAGE_SIZE; adr += PAGE_SIZE;
if (size > PAGE_SIZE) size -= PAGE_SIZE;
size -= PAGE_SIZE;
else
size = 0;
} }
return mem; return mem;
...@@ -126,23 +119,16 @@ static void *rvmalloc(unsigned long size) ...@@ -126,23 +119,16 @@ static void *rvmalloc(unsigned long size)
static void rvfree(void *mem, unsigned long size) static void rvfree(void *mem, unsigned long size)
{ {
unsigned long adr, page; unsigned long adr;
if (!mem) if (!mem)
return; return;
size += (PAGE_SIZE - 1); adr = (unsigned long) mem;
size &= ~(PAGE_SIZE - 1); while ((long) size > 0) {
mem_map_unreserve(vmalloc_to_page((void *)adr));
adr=(unsigned long) mem;
while (size > 0) {
page = kvirt_to_pa(adr);
mem_map_unreserve(virt_to_page(__va(page)));
adr += PAGE_SIZE; adr += PAGE_SIZE;
if (size > PAGE_SIZE) size -= PAGE_SIZE;
size -= PAGE_SIZE;
else
size = 0;
} }
vfree(mem); vfree(mem);
} }
......
...@@ -127,54 +127,25 @@ EXPORT_NO_SYMBOLS; ...@@ -127,54 +127,25 @@ EXPORT_NO_SYMBOLS;
* And the STV0680 driver - Kevin * And the STV0680 driver - Kevin
********************************************************************/ ********************************************************************/
/* Given PGD from the address space's page table, return the kernel /* Here we want the physical address of the memory.
* virtual mapping of the physical memory mapped at ADR. * This is used when initializing the contents of the area.
*/
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)) {
preempt_disable();
ptep = pte_offset_map (pmd, adr);
pte = *ptep;
pte_unmap(pte);
preempt_enable();
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) static inline unsigned long kvirt_to_pa (unsigned long adr)
{ {
unsigned long va, kva, ret; unsigned long kva, ret;
va = VMALLOC_VMADDR (adr); kva = (unsigned long) page_address(vmalloc_to_page((void *)adr));
kva = uvirt_to_kva (pgd_offset_k (va), va); kva |= adr & (PAGE_SIZE-1); /* restore the offset */
ret = __pa (kva); ret = __pa(kva);
return ret; return ret;
} }
static void *rvmalloc (unsigned long size) static void *rvmalloc (unsigned long size)
{ {
void *mem; void *mem;
unsigned long adr, page; unsigned long adr;
/* Round it off to PAGE_SIZE */
size += (PAGE_SIZE - 1);
size &= ~(PAGE_SIZE - 1);
size = PAGE_ALIGN(size);
mem = vmalloc_32 (size); mem = vmalloc_32 (size);
if (!mem) if (!mem)
return NULL; return NULL;
...@@ -182,36 +153,25 @@ static void *rvmalloc (unsigned long size) ...@@ -182,36 +153,25 @@ static void *rvmalloc (unsigned long size)
memset (mem, 0, size); /* Clear the ram out, no junk to the user */ memset (mem, 0, size); /* Clear the ram out, no junk to the user */
adr = (unsigned long) mem; adr = (unsigned long) mem;
while (size > 0) { while (size > 0) {
page = kvirt_to_pa (adr); mem_map_reserve(vmalloc_to_page((void *)adr));
mem_map_reserve (virt_to_page (__va (page)));
adr += PAGE_SIZE; adr += PAGE_SIZE;
if (size > PAGE_SIZE) size -= PAGE_SIZE;
size -= PAGE_SIZE;
else
size = 0;
} }
return mem; return mem;
} }
static void rvfree (void *mem, unsigned long size) static void rvfree (void *mem, unsigned long size)
{ {
unsigned long adr, page; unsigned long adr;
if (!mem) if (!mem)
return; return;
size += (PAGE_SIZE - 1);
size &= ~(PAGE_SIZE - 1);
adr = (unsigned long) mem; adr = (unsigned long) mem;
while (size > 0) { while ((long) size > 0) {
page = kvirt_to_pa (adr); mem_map_unreserve(vmalloc_to_page((void *)adr));
mem_map_unreserve (virt_to_page (__va (page)));
adr += PAGE_SIZE; adr += PAGE_SIZE;
if (size > PAGE_SIZE) size -= PAGE_SIZE;
size -= PAGE_SIZE;
else
size = 0;
} }
vfree (mem); vfree (mem);
} }
......
...@@ -59,32 +59,26 @@ static int usbvideo_default_procfs_write_proc( ...@@ -59,32 +59,26 @@ static int usbvideo_default_procfs_write_proc(
/* Memory management functions */ /* Memory management functions */
/*******************************/ /*******************************/
#define MDEBUG(x) do { } while(0) /* Debug memory management */
/* /*
* Here we want the physical address of the memory. * Here we want the physical address of the memory.
* This is used when initializing the contents of the * This is used when initializing the contents of the area.
* area and marking the pages as reserved.
*/ */
unsigned long usbvideo_kvirt_to_pa(unsigned long adr) unsigned long usbvideo_kvirt_to_pa(unsigned long adr)
{ {
unsigned long kva, ret; unsigned long kva, ret;
kva = page_address(vmalloc_to_page((void *)adr)); kva = (unsigned long) page_address(vmalloc_to_page((void *)adr));
kva |= adr & (PAGE_SIZE-1); /* restore the offset */
ret = __pa(kva); ret = __pa(kva);
MDEBUG(printk("kv2pa(%lx-->%lx)", adr, ret));
return ret; return ret;
} }
void *usbvideo_rvmalloc(unsigned long size) void *usbvideo_rvmalloc(unsigned long size)
{ {
void *mem; void *mem;
unsigned long adr, page; unsigned long adr;
/* Round it off to PAGE_SIZE */
size += (PAGE_SIZE - 1);
size &= ~(PAGE_SIZE - 1);
size = PAGE_ALIGN(size);
mem = vmalloc_32(size); mem = vmalloc_32(size);
if (!mem) if (!mem)
return NULL; return NULL;
...@@ -92,13 +86,9 @@ void *usbvideo_rvmalloc(unsigned long size) ...@@ -92,13 +86,9 @@ void *usbvideo_rvmalloc(unsigned long size)
memset(mem, 0, size); /* Clear the ram out, no junk to the user */ memset(mem, 0, size); /* Clear the ram out, no junk to the user */
adr = (unsigned long) mem; adr = (unsigned long) mem;
while (size > 0) { while (size > 0) {
page = usbvideo_kvirt_to_pa(adr); mem_map_reserve(vmalloc_to_page((void *)adr));
mem_map_reserve(virt_to_page(__va(page)));
adr += PAGE_SIZE; adr += PAGE_SIZE;
if (size > PAGE_SIZE) size -= PAGE_SIZE;
size -= PAGE_SIZE;
else
size = 0;
} }
return mem; return mem;
...@@ -106,23 +96,16 @@ void *usbvideo_rvmalloc(unsigned long size) ...@@ -106,23 +96,16 @@ void *usbvideo_rvmalloc(unsigned long size)
void usbvideo_rvfree(void *mem, unsigned long size) void usbvideo_rvfree(void *mem, unsigned long size)
{ {
unsigned long adr, page; unsigned long adr;
if (!mem) if (!mem)
return; return;
size += (PAGE_SIZE - 1); adr = (unsigned long) mem;
size &= ~(PAGE_SIZE - 1); while ((long) size > 0) {
mem_map_unreserve(vmalloc_to_page((void *)adr));
adr=(unsigned long) mem;
while (size > 0) {
page = usbvideo_kvirt_to_pa(adr);
mem_map_unreserve(virt_to_page(__va(page)));
adr += PAGE_SIZE; adr += PAGE_SIZE;
if (size > PAGE_SIZE) size -= PAGE_SIZE;
size -= PAGE_SIZE;
else
size = 0;
} }
vfree(mem); vfree(mem);
} }
......
...@@ -93,83 +93,25 @@ static int vicam_parameters(struct usb_vicam *vicam); ...@@ -93,83 +93,25 @@ static int vicam_parameters(struct usb_vicam *vicam);
* *
******************************************************************************/ ******************************************************************************/
/* [DaveM] I've recoded most of this so that:
* 1) It's easier to tell what is happening
* 2) It's more portable, especially for translating things
* out of vmalloc mapped areas in the kernel.
* 3) Less unnecessary translations happen.
*
* The code used to assume that the kernel vmalloc mappings
* existed in the page tables of every process, this is simply
* not guarenteed. We now use pgd_offset_k which is the
* defined way to get at the kernel page tables.
*/
/* 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)) {
preempt_disable();
ptep = pte_offset_map(pmd, adr);
pte = *ptep;
pte_unmap(pte);
preempt_enable();
if(pte_present(pte)) {
ret = (unsigned long) page_address(pte_page(pte));
ret |= (adr & (PAGE_SIZE - 1));
}
}
}
return ret;
}
static inline unsigned long uvirt_to_bus(unsigned long adr)
{
unsigned long kva, ret;
kva = uvirt_to_kva(pgd_offset(current->mm, adr), adr);
ret = virt_to_bus((void *)kva);
return ret;
}
static inline unsigned long kvirt_to_bus(unsigned long adr)
{
unsigned long va, kva, ret;
va = VMALLOC_VMADDR(adr);
kva = uvirt_to_kva(pgd_offset_k(va), va);
ret = virt_to_bus((void *)kva);
return ret;
}
/* Here we want the physical address of the memory. /* Here we want the physical address of the memory.
* This is used when initializing the contents of the * This is used when initializing the contents of the area.
* area and marking the pages as reserved.
*/ */
static inline unsigned long kvirt_to_pa(unsigned long adr) static inline unsigned long kvirt_to_pa(unsigned long adr)
{ {
unsigned long va, kva, ret; unsigned long kva, ret;
va = VMALLOC_VMADDR(adr); kva = (unsigned long) page_address(vmalloc_to_page((void *)adr));
kva = uvirt_to_kva(pgd_offset_k(va), va); kva |= adr & (PAGE_SIZE-1); /* restore the offset */
ret = __pa(kva); ret = __pa(kva);
return ret; return ret;
} }
static void * rvmalloc(signed long size) static void * rvmalloc(unsigned long size)
{ {
void * mem; void * mem;
unsigned long adr, page; unsigned long adr;
size=PAGE_ALIGN(size);
mem=vmalloc_32(size); mem=vmalloc_32(size);
if (mem) if (mem)
{ {
...@@ -177,8 +119,7 @@ static void * rvmalloc(signed long size) ...@@ -177,8 +119,7 @@ static void * rvmalloc(signed long size)
adr=(unsigned long) mem; adr=(unsigned long) mem;
while (size > 0) while (size > 0)
{ {
page = kvirt_to_pa(adr); mem_map_reserve(vmalloc_to_page((void *)adr));
mem_map_reserve(virt_to_page(__va(page)));
adr+=PAGE_SIZE; adr+=PAGE_SIZE;
size-=PAGE_SIZE; size-=PAGE_SIZE;
} }
...@@ -186,17 +127,16 @@ static void * rvmalloc(signed long size) ...@@ -186,17 +127,16 @@ static void * rvmalloc(signed long size)
return mem; return mem;
} }
static void rvfree(void * mem, signed long size) static void rvfree(void * mem, unsigned long size)
{ {
unsigned long adr, page; unsigned long adr;
if (mem) if (mem)
{ {
adr=(unsigned long) mem; adr=(unsigned long) mem;
while (size > 0) while ((long) size > 0)
{ {
page = kvirt_to_pa(adr); mem_map_unreserve(vmalloc_to_page((void *)adr));
mem_map_unreserve(virt_to_page(__va(page)));
adr+=PAGE_SIZE; adr+=PAGE_SIZE;
size-=PAGE_SIZE; size-=PAGE_SIZE;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment