[PATCH] rvmalloc and rvfree

From: James Simmons (jsimmons@acsu.buffalo.edu)
Date: Thu Feb 10 2000 - 20:10:19 EST


 It was bothering me so much about the discussion we had about rvmalloc I
made a patch for it. This patch places the code inside vmalloc.c and I
changed vmalloc.h so drivers can use rvmalloc, rvfree, kvirt_to_bus, and
kvirt_to_pa. I removed the duplicated code out of bttv.c and the USB
drivers using it. I don't know if my solution is correct but its a start.
Modify it at will. It's against 2.3.43-8 and it compiles but I couldn't
test it. I don't have any drivers that use this code. So please test it as
well.

Codito, ergo sum - "I code, therefore I am"
James Simmons (o_
fbdev/gfx developer (o_ (o_ //\
http://www.linux-fbdev.org (/)_ (/)_ V_/_
http://linuxgfx.sourceforge.net

diff -urN linux-2.3.43-8/drivers/char/bttv.c linux/drivers/char/bttv.c
--- linux-2.3.43-8/drivers/char/bttv.c Thu Feb 10 15:07:18 2000
+++ linux/drivers/char/bttv.c Thu Feb 10 18:32:47 2000
@@ -99,124 +99,6 @@
 
 #define BURSTOFFSET 76
 
-
-/*******************************/
-/* 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.
- */
-
-/* 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 = (page_address(pte_page(pte))|(adr&(PAGE_SIZE-1)));
- }
- }
- MDEBUG(printk("uv2kva(%lx-->%lx)", adr, ret));
- 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);
- MDEBUG(printk("uv2b(%lx-->%lx)", adr, ret));
- 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);
- MDEBUG(printk("kv2b(%lx-->%lx)", adr, ret));
- 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);
- MDEBUG(printk("kv2pa(%lx-->%lx)", adr, ret));
- return ret;
-}
-
-static void * rvmalloc(unsigned long size)
-{
- void * mem;
- unsigned long adr, page;
-
- mem=vmalloc(size);
- if (mem)
- {
- 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(MAP_NR(__va(page)));
- adr+=PAGE_SIZE;
- size-=PAGE_SIZE;
- }
- }
- return mem;
-}
-
-static void rvfree(void * mem, unsigned long size)
-{
- unsigned long adr, page;
-
- if (mem)
- {
- adr=(unsigned long) mem;
- while (size > 0)
- {
- page = kvirt_to_pa(adr);
- mem_map_unreserve(MAP_NR(__va(page)));
- adr+=PAGE_SIZE;
- size-=PAGE_SIZE;
- }
- vfree(mem);
- }
-}
-
-
-
 /*
  * Create the giant waste of buffer space we need for now
  * until we get DMA to user space sorted out (probably 2.3.x)
diff -urN linux-2.3.43-8/drivers/usb/cpia.c linux/drivers/usb/cpia.c
--- linux-2.3.43-8/drivers/usb/cpia.c Thu Feb 10 15:07:20 2000
+++ linux/drivers/usb/cpia.c Thu Feb 10 18:36:08 2000
@@ -31,122 +31,7 @@
 /* 384 because xawtv tries to grab 384 even though we tell it 352 is our max */
 #define MAX_FRAME_SIZE (384 * 288 * 3)
 
-/*******************************/
-/* Memory management functions */
-/*******************************/
-
-#define MDEBUG(x) do { } while(0) /* Debug memory management */
-
 static struct usb_driver cpia_driver;
-
-/* 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 = page_address(pte_page(pte)) | (adr & (PAGE_SIZE-1));
- }
- }
- MDEBUG(printk("uv2kva(%lx-->%lx)", adr, ret));
- 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);
- MDEBUG(printk("uv2b(%lx-->%lx)", adr, ret));
- 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);
- MDEBUG(printk("kv2b(%lx-->%lx)", adr, ret));
- 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);
- MDEBUG(printk("kv2pa(%lx-->%lx)", adr, ret));
- 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(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(MAP_NR(__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(MAP_NR(__va(page)));
- adr += PAGE_SIZE;
- if (size > PAGE_SIZE)
- size -= PAGE_SIZE;
- else
- size = 0;
- }
- vfree(mem);
-}
 
 static int usb_cpia_get_version(struct usb_device *dev, void *buf)
 {
diff -urN linux-2.3.43-8/drivers/usb/ibmcam.c linux/drivers/usb/ibmcam.c
--- linux-2.3.43-8/drivers/usb/ibmcam.c Thu Feb 10 15:07:21 2000
+++ linux/drivers/usb/ibmcam.c Thu Feb 10 18:33:38 2000
@@ -143,124 +143,8 @@
 #define MAX_IBMCAM 4
 
 struct usb_ibmcam cams[MAX_IBMCAM];
-
-/*******************************/
-/* Memory management functions */
-/*******************************/
-
-#define MDEBUG(x) do { } while(0) /* Debug memory management */
-
 static struct usb_driver ibmcam_driver;
 static void usb_ibmcam_release(struct usb_ibmcam *ibmcam);
-
-/* 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 = page_address(pte_page(pte)) | (adr & (PAGE_SIZE-1));
- }
- }
- MDEBUG(printk("uv2kva(%lx-->%lx)", adr, ret));
- 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);
- MDEBUG(printk("uv2b(%lx-->%lx)", adr, ret));
- 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);
- MDEBUG(printk("kv2b(%lx-->%lx)", adr, ret));
- 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);
- MDEBUG(printk("kv2pa(%lx-->%lx)", adr, ret));
- 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(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(MAP_NR(__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(MAP_NR(__va(page)));
- adr += PAGE_SIZE;
- if (size > PAGE_SIZE)
- size -= PAGE_SIZE;
- else
- size = 0;
- }
- vfree(mem);
-}
 
 /*
  * usb_ibmcam_overlaychar()
diff -urN linux-2.3.43-8/drivers/usb/ov511.c linux/drivers/usb/ov511.c
--- linux-2.3.43-8/drivers/usb/ov511.c Thu Feb 10 15:07:21 2000
+++ linux/drivers/usb/ov511.c Thu Feb 10 18:37:11 2000
@@ -79,122 +79,7 @@
 
 char kernel_version[] = UTS_RELEASE;
 
-/*******************************/
-/* Memory management functions */
-/*******************************/
-
-#define MDEBUG(x) do { } while(0) /* Debug memory management */
-
 static struct usb_driver ov511_driver;
-
-/* 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 = page_address(pte_page(pte)) | (adr & (PAGE_SIZE-1));
- }
- }
- MDEBUG(printk("uv2kva(%lx-->%lx)", adr, ret));
- 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);
- MDEBUG(printk("uv2b(%lx-->%lx)", adr, ret));
- 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);
- MDEBUG(printk("kv2b(%lx-->%lx)", adr, ret));
- 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);
- MDEBUG(printk("kv2pa(%lx-->%lx)", adr, ret));
- 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(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(MAP_NR(__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(MAP_NR(__va(page)));
- adr += PAGE_SIZE;
- if (size > PAGE_SIZE)
- size -= PAGE_SIZE;
- else
- size = 0;
- }
- vfree(mem);
-}
 
 int ov511_reg_write(struct usb_device *dev, unsigned char reg, unsigned char value)
 {
diff -urN linux-2.3.43-8/include/linux/vmalloc.h linux/include/linux/vmalloc.h
--- linux-2.3.43-8/include/linux/vmalloc.h Wed Nov 24 11:04:30 1999
+++ linux/include/linux/vmalloc.h Thu Feb 10 19:03:23 2000
@@ -23,7 +23,10 @@
 long vread(char *buf, char *addr, unsigned long count);
 void vmfree_area_pages(unsigned long address, unsigned long size);
 int vmalloc_area_pages(unsigned long address, unsigned long size);
+inline unsigned long kvirt_to_bus(unsigned long adr);
+inline unsigned long kvirt_to_pa(unsigned long adr);
+void *rvmalloc(unsigned long size);
+void rvfree(void *mem, unsigned long size);
 
 extern struct vm_struct * vmlist;
 #endif
-
diff -urN linux-2.3.43-8/mm/vmalloc.c linux/mm/vmalloc.c
--- linux-2.3.43-8/mm/vmalloc.c Wed Nov 24 11:04:31 1999
+++ linux/mm/vmalloc.c Thu Feb 10 19:12:22 2000
@@ -7,9 +7,11 @@
 
 #include <linux/malloc.h>
 #include <linux/vmalloc.h>
+#include <linux/wrapper.h>
 
 #include <asm/uaccess.h>
 #include <asm/pgalloc.h>
+#include <asm/io.h>
 
 struct vm_struct * vmlist = NULL;
 
@@ -258,4 +260,127 @@
         }
 finished:
         return buf - buf_start;
+}
+
+/* [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.
+ */
+
+#define MDEBUG(x) do { } while(0) /* Debug memory management */
+
+/* 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 = page_address(pte_page(pte)) | (adr & (PAGE_SIZE-1));
+ }
+ }
+ MDEBUG(printk("uv2kva(%lx-->%lx)", adr, ret));
+ 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);
+ MDEBUG(printk("uv2b(%lx-->%lx)", adr, ret));
+ return ret;
+}
+
+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);
+ MDEBUG(printk("kv2b(%lx-->%lx)", adr, ret));
+ 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.
+ */
+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);
+ MDEBUG(printk("kv2pa(%lx-->%lx)", adr, ret));
+ return ret;
+}
+
+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(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(MAP_NR(__va(page)));
+ adr += PAGE_SIZE;
+ if (size > PAGE_SIZE)
+ size -= PAGE_SIZE;
+ else
+ size = 0;
+ }
+
+ return mem;
+}
+
+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(MAP_NR(__va(page)));
+ adr += PAGE_SIZE;
+ if (size > PAGE_SIZE)
+ size -= PAGE_SIZE;
+ else
+ size = 0;
+ }
+ vfree(mem);
 }

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Tue Feb 15 2000 - 21:00:18 EST