[PATCH] EFI, /dev/mem: simplify efi_mem_attribute_range()
Bjorn Helgaas [Sun, 26 Mar 2006 09:37:05 +0000 (01:37 -0800)]
Pass the size, not a pointer to the size, to efi_mem_attribute_range().

This function validates memory regions for the /dev/mem read/write/mmap paths.
The pointer allows arches to reduce the size of the range, but I think that's
unnecessary complexity.  Simplifying it will let me use
efi_mem_attribute_range() to improve the ia64 ioremap() implementation.

Signed-off-by: Bjorn Helgaas <bjorn.helgaas@hp.com>
Cc: Matt Domsch <Matt_Domsch@dell.com>
Cc: "Tolentino, Matthew E" <matthew.e.tolentino@intel.com>
Cc: "Brown, Len" <len.brown@intel.com>
Cc: Andi Kleen <ak@muc.de>
Acked-by: "Luck, Tony" <tony.luck@intel.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

arch/ia64/kernel/efi.c
drivers/char/mem.c
include/asm-ia64/io.h
include/linux/efi.h

index 9990320..2993748 100644 (file)
@@ -677,27 +677,34 @@ EXPORT_SYMBOL(efi_mem_attributes);
 /*
  * Determines whether the memory at phys_addr supports the desired
  * attribute (WB, UC, etc).  If this returns 1, the caller can safely
- * access *size bytes at phys_addr with the specified attribute.
+ * access size bytes at phys_addr with the specified attribute.
  */
-static int
-efi_mem_attribute_range (unsigned long phys_addr, unsigned long *size, u64 attr)
+int
+efi_mem_attribute_range (unsigned long phys_addr, unsigned long size, u64 attr)
 {
+       unsigned long end = phys_addr + size;
        efi_memory_desc_t *md = efi_memory_descriptor(phys_addr);
-       unsigned long md_end;
 
-       if (!md || (md->attribute & attr) != attr)
+       /*
+        * Some firmware doesn't report MMIO regions in the EFI memory
+        * map.  The Intel BigSur (a.k.a. HP i2000) has this problem.
+        * On those platforms, we have to assume UC is valid everywhere.
+        */
+       if (!md || (md->attribute & attr) != attr) {
+               if (attr == EFI_MEMORY_UC && !efi_memmap_has_mmio())
+                       return 1;
                return 0;
+       }
 
        do {
-               md_end = efi_md_end(md);
-               if (phys_addr + *size <= md_end)
+               unsigned long md_end = efi_md_end(md);
+
+               if (end <= md_end)
                        return 1;
 
                md = efi_memory_descriptor(md_end);
-               if (!md || (md->attribute & attr) != attr) {
-                       *size = md_end - phys_addr;
-                       return 1;
-               }
+               if (!md || (md->attribute & attr) != attr)
+                       return 0;
        } while (md);
        return 0;
 }
@@ -708,7 +715,7 @@ efi_mem_attribute_range (unsigned long phys_addr, unsigned long *size, u64 attr)
  * control access size.
  */
 int
-valid_phys_addr_range (unsigned long phys_addr, unsigned long *size)
+valid_phys_addr_range (unsigned long phys_addr, unsigned long size)
 {
        return efi_mem_attribute_range(phys_addr, size, EFI_MEMORY_WB);
 }
@@ -723,7 +730,7 @@ valid_phys_addr_range (unsigned long phys_addr, unsigned long *size)
  * because that doesn't appear in the boot-time EFI memory map.
  */
 int
-valid_mmap_phys_addr_range (unsigned long phys_addr, unsigned long *size)
+valid_mmap_phys_addr_range (unsigned long phys_addr, unsigned long size)
 {
        if (efi_mem_attribute_range(phys_addr, size, EFI_MEMORY_WB))
                return 1;
@@ -731,14 +738,6 @@ valid_mmap_phys_addr_range (unsigned long phys_addr, unsigned long *size)
        if (efi_mem_attribute_range(phys_addr, size, EFI_MEMORY_UC))
                return 1;
 
-       /*
-        * Some firmware doesn't report MMIO regions in the EFI memory map.
-        * The Intel BigSur (a.k.a. HP i2000) has this problem.  In this
-        * case, we can't use the EFI memory map to validate mmap requests.
-        */
-       if (!efi_memmap_has_mmio())
-               return 1;
-
        return 0;
 }
 
index 26d0116..5245ba1 100644 (file)
@@ -88,21 +88,15 @@ static inline int uncached_access(struct file *file, unsigned long addr)
 }
 
 #ifndef ARCH_HAS_VALID_PHYS_ADDR_RANGE
-static inline int valid_phys_addr_range(unsigned long addr, size_t *count)
+static inline int valid_phys_addr_range(unsigned long addr, size_t count)
 {
-       unsigned long end_mem;
-
-       end_mem = __pa(high_memory);
-       if (addr >= end_mem)
+       if (addr + count > __pa(high_memory))
                return 0;
 
-       if (*count > end_mem - addr)
-               *count = end_mem - addr;
-
        return 1;
 }
 
-static inline int valid_mmap_phys_addr_range(unsigned long addr, size_t *size)
+static inline int valid_mmap_phys_addr_range(unsigned long addr, size_t size)
 {
        return 1;
 }
@@ -119,7 +113,7 @@ static ssize_t read_mem(struct file * file, char __user * buf,
        ssize_t read, sz;
        char *ptr;
 
-       if (!valid_phys_addr_range(p, &count))
+       if (!valid_phys_addr_range(p, count))
                return -EFAULT;
        read = 0;
 #ifdef __ARCH_HAS_NO_PAGE_ZERO_MAPPED
@@ -177,7 +171,7 @@ static ssize_t write_mem(struct file * file, const char __user * buf,
        unsigned long copied;
        void *ptr;
 
-       if (!valid_phys_addr_range(p, &count))
+       if (!valid_phys_addr_range(p, count))
                return -EFAULT;
 
        written = 0;
@@ -249,7 +243,7 @@ static int mmap_mem(struct file * file, struct vm_area_struct * vma)
 {
        size_t size = vma->vm_end - vma->vm_start;
 
-       if (!valid_mmap_phys_addr_range(vma->vm_pgoff << PAGE_SHIFT, &size))
+       if (!valid_mmap_phys_addr_range(vma->vm_pgoff << PAGE_SHIFT, size))
                return -EINVAL;
 
        vma->vm_page_prot = phys_mem_access_prot(file, vma->vm_pgoff,
index 0d9bcc3..acba019 100644 (file)
@@ -88,8 +88,8 @@ phys_to_virt (unsigned long address)
 }
 
 #define ARCH_HAS_VALID_PHYS_ADDR_RANGE
-extern int valid_phys_addr_range (unsigned long addr, size_t *count); /* efi.c */
-extern int valid_mmap_phys_addr_range (unsigned long addr, size_t *count);
+extern int valid_phys_addr_range (unsigned long addr, size_t count); /* efi.c */
+extern int valid_mmap_phys_addr_range (unsigned long addr, size_t count);
 
 /*
  * The following two macros are deprecated and scheduled for removal.
index c7c5dd3..d157254 100644 (file)
@@ -292,6 +292,8 @@ extern void efi_enter_virtual_mode (void);  /* switch EFI to virtual mode, if pos
 extern u64 efi_get_iobase (void);
 extern u32 efi_mem_type (unsigned long phys_addr);
 extern u64 efi_mem_attributes (unsigned long phys_addr);
+extern int efi_mem_attribute_range (unsigned long phys_addr, unsigned long size,
+                                   u64 attr);
 extern int __init efi_uart_console_only (void);
 extern void efi_initialize_iomem_resources(struct resource *code_resource,
                                        struct resource *data_resource);