public inbox for linux-acpi@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/5] ia64 ioremap, DMI, EFI system table
       [not found]   ` <20060118181116.GA5537@lists.us.dell.com>
@ 2006-01-19 20:10     ` Bjorn Helgaas
  2006-01-19 20:12       ` [PATCH 1/5] EFI, /dev/mem: simplify efi_mem_attribute_range() Bjorn Helgaas
                         ` (5 more replies)
  0 siblings, 6 replies; 7+ messages in thread
From: Bjorn Helgaas @ 2006-01-19 20:10 UTC (permalink / raw)
  To: Matt Domsch
  Cc: linux-ia64, ak, openipmi-developer, akpm, Tolentino, Matthew E,
	linux-kernel, linux-acpi

OK, here's a set of patches to (hopefully) clean up this area
a bit:

1  Simplify efi_mem_attribute_range() so I can use it both for
   /dev/mem validation and ioremap() attribute checking.

2  Make ia64 ioremap() check memory attributes, so it works for
   plain memory that only supports write-back access, as well as
   for MMIO space that only supports uncacheable access.

3  DMI ioremaps too much space, which makes it fail on machines
   where the SMBIOS table is near the end of a memory region.

4  Keep EFI table addresses as physical, not virtual.  The SMBIOS
   address was physical on x86 but virtual on ia64, which broke
   dmi_scan_machine().

5  Use smarter ioremap() implementation to remove some cruft in
   acpi_os_{read,write,map}_memory().  This one's just an optional
   cleanup; I don't think it fixes any bugs.


-------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc. Do you grep through log files
for problems?  Stop!  Download the new AJAX search engine that makes
searching your log files as easy as surfing the  web.  DOWNLOAD SPLUNK!
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=103432&bid=230486&dat=121642

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 1/5] EFI, /dev/mem: simplify efi_mem_attribute_range()
  2006-01-19 20:10     ` [PATCH 0/5] ia64 ioremap, DMI, EFI system table Bjorn Helgaas
@ 2006-01-19 20:12       ` Bjorn Helgaas
  2006-01-19 20:12       ` [PATCH 2/5] ia64: ioremap: check EFI for valid memory attributes Bjorn Helgaas
                         ` (4 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Bjorn Helgaas @ 2006-01-19 20:12 UTC (permalink / raw)
  To: Matt Domsch
  Cc: linux-ia64, ak, openipmi-developer, akpm, Tolentino, Matthew E,
	linux-kernel, linux-acpi

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>

Index: work-mm3/arch/ia64/kernel/efi.c
===================================================================
--- work-mm3.orig/arch/ia64/kernel/efi.c	2006-01-18 13:25:29.000000000 -0700
+++ work-mm3/arch/ia64/kernel/efi.c	2006-01-18 13:27:18.000000000 -0700
@@ -685,27 +685,34 @@
 /*
  * 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;
 }
@@ -716,7 +723,7 @@
  * 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);
 }
@@ -731,7 +738,7 @@
  * 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;
@@ -739,14 +746,6 @@
 	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: work-mm3/drivers/char/mem.c
===================================================================
--- work-mm3.orig/drivers/char/mem.c	2006-01-18 13:25:27.000000000 -0700
+++ work-mm3/drivers/char/mem.c	2006-01-18 13:27:18.000000000 -0700
@@ -88,21 +88,15 @@
 }
 
 #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 @@
 	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 @@
 	unsigned long copied;
 	void *ptr;
 
-	if (!valid_phys_addr_range(p, &count))
+	if (!valid_phys_addr_range(p, count))
 		return -EFAULT;
 
 	written = 0;
@@ -251,7 +245,7 @@
 {
 	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: work-mm3/include/asm-ia64/io.h
===================================================================
--- work-mm3.orig/include/asm-ia64/io.h	2006-01-18 13:25:27.000000000 -0700
+++ work-mm3/include/asm-ia64/io.h	2006-01-18 13:27:18.000000000 -0700
@@ -88,8 +88,8 @@
 }
 
 #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: work-mm3/include/linux/efi.h
===================================================================
--- work-mm3.orig/include/linux/efi.h	2006-01-18 13:25:27.000000000 -0700
+++ work-mm3/include/linux/efi.h	2006-01-18 13:27:18.000000000 -0700
@@ -292,6 +292,8 @@
 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);


-------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc. Do you grep through log files
for problems?  Stop!  Download the new AJAX search engine that makes
searching your log files as easy as surfing the  web.  DOWNLOAD SPLUNK!
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=103432&bid=230486&dat=121642

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 2/5] ia64: ioremap: check EFI for valid memory attributes
  2006-01-19 20:10     ` [PATCH 0/5] ia64 ioremap, DMI, EFI system table Bjorn Helgaas
  2006-01-19 20:12       ` [PATCH 1/5] EFI, /dev/mem: simplify efi_mem_attribute_range() Bjorn Helgaas
@ 2006-01-19 20:12       ` Bjorn Helgaas
  2006-01-19 20:13       ` [PATCH 3/5] DMI: only ioremap stuff we actually need Bjorn Helgaas
                         ` (3 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Bjorn Helgaas @ 2006-01-19 20:12 UTC (permalink / raw)
  To: Matt Domsch
  Cc: linux-ia64, ak, openipmi-developer, akpm, Tolentino, Matthew E,
	linux-kernel, linux-acpi

Check the EFI memory map so we can use the correct memory attributes
for ioremap().  Previously, we always used uncacheable access, which
blows up on some machines for regular system memory.

Depends on the previous efi_mem_attribute_range() patch.

Signed-off-by: Bjorn Helgaas <bjorn.helgaas@hp.com>

Index: work-mm3/arch/ia64/mm/ioremap.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ work-mm3/arch/ia64/mm/ioremap.c	2006-01-18 17:04:42.000000000 -0700
@@ -0,0 +1,40 @@
+/*
+ * (c) Copyright 2006 Hewlett-Packard Development Company, L.P.
+ *	Bjorn Helgaas <bjorn.helgaas@hp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/compiler.h>
+#include <linux/efi.h>
+#include <asm/io.h>
+
+static inline void __iomem *
+__ioremap (unsigned long offset, unsigned long size)
+{
+	return (void __iomem *) (__IA64_UNCACHED_OFFSET | offset);
+}
+
+void __iomem *
+ioremap (unsigned long offset, unsigned long size)
+{
+	if (efi_mem_attribute_range(offset, size, EFI_MEMORY_UC))
+		return __ioremap(offset, size);
+
+	if (efi_mem_attribute_range(offset, size, EFI_MEMORY_WB))
+		return phys_to_virt(offset);
+
+	/*
+	 * Someday this should check ACPI resources so we
+	 * can do the right thing for hot-plugged regions.
+	 */
+	return __ioremap(offset, size);
+}
+
+void __iomem *
+ioremap_nocache (unsigned long offset, unsigned long size)
+{
+	return __ioremap(offset, size);
+}
Index: work-mm3/include/asm-ia64/io.h
===================================================================
--- work-mm3.orig/include/asm-ia64/io.h	2006-01-18 13:33:06.000000000 -0700
+++ work-mm3/include/asm-ia64/io.h	2006-01-18 16:50:54.000000000 -0700
@@ -416,25 +416,14 @@
 # define outl_p		outl
 #endif
 
-/*
- * An "address" in IO memory space is not clearly either an integer or a pointer. We will
- * accept both, thus the casts.
- *
- * On ia-64, we access the physical I/O memory space through the uncached kernel region.
- */
-static inline void __iomem *
-ioremap (unsigned long offset, unsigned long size)
-{
-	return (void __iomem *) (__IA64_UNCACHED_OFFSET | (offset));
-}
+extern void __iomem * ioremap(unsigned long offset, unsigned long size);
+extern void __iomem * ioremap_nocache (unsigned long offset, unsigned long size);
 
 static inline void
 iounmap (volatile void __iomem *addr)
 {
 }
 
-#define ioremap_nocache(o,s)	ioremap(o,s)
-
 /* Use normal IO mappings for DMI */
 #define dmi_ioremap ioremap
 #define dmi_iounmap(x,l) iounmap(x)
Index: work-mm3/arch/ia64/mm/Makefile
===================================================================
--- work-mm3.orig/arch/ia64/mm/Makefile	2006-01-18 13:33:06.000000000 -0700
+++ work-mm3/arch/ia64/mm/Makefile	2006-01-18 13:33:34.000000000 -0700
@@ -2,7 +2,7 @@
 # Makefile for the ia64-specific parts of the memory manager.
 #
 
-obj-y := init.o fault.o tlb.o extable.o
+obj-y := init.o fault.o tlb.o extable.o ioremap.o
 
 obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
 obj-$(CONFIG_NUMA)	   += numa.o


-------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc. Do you grep through log files
for problems?  Stop!  Download the new AJAX search engine that makes
searching your log files as easy as surfing the  web.  DOWNLOAD SPLUNK!
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=103432&bid=230486&dat=121642

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 3/5] DMI: only ioremap stuff we actually need
  2006-01-19 20:10     ` [PATCH 0/5] ia64 ioremap, DMI, EFI system table Bjorn Helgaas
  2006-01-19 20:12       ` [PATCH 1/5] EFI, /dev/mem: simplify efi_mem_attribute_range() Bjorn Helgaas
  2006-01-19 20:12       ` [PATCH 2/5] ia64: ioremap: check EFI for valid memory attributes Bjorn Helgaas
@ 2006-01-19 20:13       ` Bjorn Helgaas
  2006-01-19 20:13       ` [PATCH 4/5] EFI: keep physical table addresses in efi structure Bjorn Helgaas
                         ` (2 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Bjorn Helgaas @ 2006-01-19 20:13 UTC (permalink / raw)
  To: Matt Domsch
  Cc: linux-ia64, ak, openipmi-developer, akpm, Tolentino, Matthew E,
	linux-kernel, linux-acpi

dmi_scan_machine() tries to ioremap 0x10000 (64K) bytes, even though
it only looks at the first 32 bytes or so.  If the SMBIOS table is
near the end of a memory region, the ioremap() may fail when it
shouldn't.

This is in the efi_enabled path, so it really only affects ia64 at
the moment.

Signed-off-by: Bjorn Helgaas <bjorn.helgaas@hp.com>

Index: work-mm3/arch/i386/kernel/dmi_scan.c
===================================================================
--- work-mm3.orig/arch/i386/kernel/dmi_scan.c	2006-01-19 11:26:17.000000000 -0700
+++ work-mm3/arch/i386/kernel/dmi_scan.c	2006-01-19 11:30:21.000000000 -0700
@@ -223,7 +223,7 @@
                 * needed during early boot.  This also means we can
                 * iounmap the space when we're done with it.
 		*/
-		p = ioremap((unsigned long)efi.smbios, 0x10000);
+		p = ioremap((unsigned long)efi.smbios, 32);
 		if (p == NULL)
 			goto out;
 

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 4/5] EFI: keep physical table addresses in efi structure
  2006-01-19 20:10     ` [PATCH 0/5] ia64 ioremap, DMI, EFI system table Bjorn Helgaas
                         ` (2 preceding siblings ...)
  2006-01-19 20:13       ` [PATCH 3/5] DMI: only ioremap stuff we actually need Bjorn Helgaas
@ 2006-01-19 20:13       ` Bjorn Helgaas
  2006-01-19 20:14       ` [PATCH 5/5] ACPI: clean up memory attribute checking for map/read/write Bjorn Helgaas
  2006-01-30 17:11       ` [Openipmi-developer] [PATCH 0/5] ia64 ioremap, DMI, EFI system table Matt Domsch
  5 siblings, 0 replies; 7+ messages in thread
From: Bjorn Helgaas @ 2006-01-19 20:13 UTC (permalink / raw)
  To: Matt Domsch
  Cc: linux-ia64, ak, openipmi-developer, akpm, Tolentino, Matthew E,
	linux-kernel, linux-acpi

Almost all users of the table addresses from the EFI system table
want physical addresses.  So rather than doing the pa->va->pa
conversion, just keep physical addresses in struct efi.

This fixes a DMI bug: the efi structure contained the physical SMBIOS
address on x86 but the virtual address on ia64, so dmi_scan_machine()
used ioremap() on a virtual address on ia64.

This is essentially the same as an earlier patch by Matt Tolentino:
    http://marc.theaimsgroup.com/?l=linux-kernel&m=112130292316281&w=2
except that this changes all table addresses, not just ACPI addresses.

Matt's original patch was backed out because it caused MCAs on HP sx1000
systems.  That problem is resolved by the ioremap() attribute checking
added for ia64.

Depends on the previous ia64 ioremap patch.

Signed-off-by: Bjorn Helgaas <bjorn.helgaas@hp.com>

Index: work-mm3/arch/i386/kernel/efi.c
===================================================================
--- work-mm3.orig/arch/i386/kernel/efi.c	2006-01-19 11:26:17.000000000 -0700
+++ work-mm3/arch/i386/kernel/efi.c	2006-01-19 11:37:23.000000000 -0700
@@ -377,29 +377,38 @@
 	if (config_tables == NULL)
 		printk(KERN_ERR PFX "Could not map EFI Configuration Table!\n");
 
+	efi.mps        = EFI_INVALID_TABLE_ADDR;
+	efi.acpi       = EFI_INVALID_TABLE_ADDR;
+	efi.acpi20     = EFI_INVALID_TABLE_ADDR;
+	efi.smbios     = EFI_INVALID_TABLE_ADDR;
+	efi.sal_systab = EFI_INVALID_TABLE_ADDR;
+	efi.boot_info  = EFI_INVALID_TABLE_ADDR;
+	efi.hcdp       = EFI_INVALID_TABLE_ADDR;
+	efi.uga        = EFI_INVALID_TABLE_ADDR;
+
 	for (i = 0; i < num_config_tables; i++) {
 		if (efi_guidcmp(config_tables[i].guid, MPS_TABLE_GUID) == 0) {
-			efi.mps = (void *)config_tables[i].table;
+			efi.mps = config_tables[i].table;
 			printk(KERN_INFO " MPS=0x%lx ", config_tables[i].table);
 		} else
 		    if (efi_guidcmp(config_tables[i].guid, ACPI_20_TABLE_GUID) == 0) {
-			efi.acpi20 = __va(config_tables[i].table);
+			efi.acpi20 = config_tables[i].table;
 			printk(KERN_INFO " ACPI 2.0=0x%lx ", config_tables[i].table);
 		} else
 		    if (efi_guidcmp(config_tables[i].guid, ACPI_TABLE_GUID) == 0) {
-			efi.acpi = __va(config_tables[i].table);
+			efi.acpi = config_tables[i].table;
 			printk(KERN_INFO " ACPI=0x%lx ", config_tables[i].table);
 		} else
 		    if (efi_guidcmp(config_tables[i].guid, SMBIOS_TABLE_GUID) == 0) {
-			efi.smbios = (void *) config_tables[i].table;
+			efi.smbios = config_tables[i].table;
 			printk(KERN_INFO " SMBIOS=0x%lx ", config_tables[i].table);
 		} else
 		    if (efi_guidcmp(config_tables[i].guid, HCDP_TABLE_GUID) == 0) {
-			efi.hcdp = (void *)config_tables[i].table;
+			efi.hcdp = config_tables[i].table;
 			printk(KERN_INFO " HCDP=0x%lx ", config_tables[i].table);
 		} else
 		    if (efi_guidcmp(config_tables[i].guid, UGA_IO_PROTOCOL_GUID) == 0) {
-			efi.uga = (void *)config_tables[i].table;
+			efi.uga = config_tables[i].table;
 			printk(KERN_INFO " UGA=0x%lx ", config_tables[i].table);
 		}
 	}
Index: work-mm3/arch/ia64/kernel/efi.c
===================================================================
--- work-mm3.orig/arch/ia64/kernel/efi.c	2006-01-19 11:36:52.000000000 -0700
+++ work-mm3/arch/ia64/kernel/efi.c	2006-01-19 11:37:23.000000000 -0700
@@ -466,24 +466,33 @@
 	printk(KERN_INFO "EFI v%u.%.02u by %s:",
 	       efi.systab->hdr.revision >> 16, efi.systab->hdr.revision & 0xffff, vendor);
 
+	efi.mps        = EFI_INVALID_TABLE_ADDR;
+	efi.acpi       = EFI_INVALID_TABLE_ADDR;
+	efi.acpi20     = EFI_INVALID_TABLE_ADDR;
+	efi.smbios     = EFI_INVALID_TABLE_ADDR;
+	efi.sal_systab = EFI_INVALID_TABLE_ADDR;
+	efi.boot_info  = EFI_INVALID_TABLE_ADDR;
+	efi.hcdp       = EFI_INVALID_TABLE_ADDR;
+	efi.uga        = EFI_INVALID_TABLE_ADDR;
+
 	for (i = 0; i < (int) efi.systab->nr_tables; i++) {
 		if (efi_guidcmp(config_tables[i].guid, MPS_TABLE_GUID) == 0) {
-			efi.mps = __va(config_tables[i].table);
+			efi.mps = config_tables[i].table;
 			printk(" MPS=0x%lx", config_tables[i].table);
 		} else if (efi_guidcmp(config_tables[i].guid, ACPI_20_TABLE_GUID) == 0) {
-			efi.acpi20 = __va(config_tables[i].table);
+			efi.acpi20 = config_tables[i].table;
 			printk(" ACPI 2.0=0x%lx", config_tables[i].table);
 		} else if (efi_guidcmp(config_tables[i].guid, ACPI_TABLE_GUID) == 0) {
-			efi.acpi = __va(config_tables[i].table);
+			efi.acpi = config_tables[i].table;
 			printk(" ACPI=0x%lx", config_tables[i].table);
 		} else if (efi_guidcmp(config_tables[i].guid, SMBIOS_TABLE_GUID) == 0) {
-			efi.smbios = __va(config_tables[i].table);
+			efi.smbios = config_tables[i].table;
 			printk(" SMBIOS=0x%lx", config_tables[i].table);
 		} else if (efi_guidcmp(config_tables[i].guid, SAL_SYSTEM_TABLE_GUID) == 0) {
-			efi.sal_systab = __va(config_tables[i].table);
+			efi.sal_systab = config_tables[i].table;
 			printk(" SALsystab=0x%lx", config_tables[i].table);
 		} else if (efi_guidcmp(config_tables[i].guid, HCDP_TABLE_GUID) == 0) {
-			efi.hcdp = __va(config_tables[i].table);
+			efi.hcdp = config_tables[i].table;
 			printk(" HCDP=0x%lx", config_tables[i].table);
 		}
 	}
Index: work-mm3/drivers/firmware/efivars.c
===================================================================
--- work-mm3.orig/drivers/firmware/efivars.c	2006-01-19 11:26:17.000000000 -0700
+++ work-mm3/drivers/firmware/efivars.c	2006-01-19 11:37:23.000000000 -0700
@@ -568,20 +568,20 @@
 	if (!entry || !buf)
 		return -EINVAL;
 
-	if (efi.mps)
-		str += sprintf(str, "MPS=0x%lx\n", __pa(efi.mps));
-	if (efi.acpi20)
-		str += sprintf(str, "ACPI20=0x%lx\n", __pa(efi.acpi20));
-	if (efi.acpi)
-		str += sprintf(str, "ACPI=0x%lx\n", __pa(efi.acpi));
-	if (efi.smbios)
-		str += sprintf(str, "SMBIOS=0x%lx\n", __pa(efi.smbios));
-	if (efi.hcdp)
-		str += sprintf(str, "HCDP=0x%lx\n", __pa(efi.hcdp));
-	if (efi.boot_info)
-		str += sprintf(str, "BOOTINFO=0x%lx\n", __pa(efi.boot_info));
-	if (efi.uga)
-		str += sprintf(str, "UGA=0x%lx\n", __pa(efi.uga));
+	if (efi.mps != EFI_INVALID_TABLE_ADDR)
+		str += sprintf(str, "MPS=0x%lx\n", efi.mps);
+	if (efi.acpi20 != EFI_INVALID_TABLE_ADDR)
+		str += sprintf(str, "ACPI20=0x%lx\n", efi.acpi20);
+	if (efi.acpi != EFI_INVALID_TABLE_ADDR)
+		str += sprintf(str, "ACPI=0x%lx\n", efi.acpi);
+	if (efi.smbios != EFI_INVALID_TABLE_ADDR)
+		str += sprintf(str, "SMBIOS=0x%lx\n", efi.smbios);
+	if (efi.hcdp != EFI_INVALID_TABLE_ADDR)
+		str += sprintf(str, "HCDP=0x%lx\n", efi.hcdp);
+	if (efi.boot_info != EFI_INVALID_TABLE_ADDR)
+		str += sprintf(str, "BOOTINFO=0x%lx\n", efi.boot_info);
+	if (efi.uga != EFI_INVALID_TABLE_ADDR)
+		str += sprintf(str, "UGA=0x%lx\n", efi.uga);
 
 	return str - buf;
 }
Index: work-mm3/include/linux/efi.h
===================================================================
--- work-mm3.orig/include/linux/efi.h	2006-01-19 11:28:43.000000000 -0700
+++ work-mm3/include/linux/efi.h	2006-01-19 11:37:23.000000000 -0700
@@ -240,19 +240,21 @@
 	unsigned long desc_size;
 };
 
+#define EFI_INVALID_TABLE_ADDR		(~0UL)
+
 /*
  * All runtime access to EFI goes through this structure:
  */
 extern struct efi {
 	efi_system_table_t *systab;	/* EFI system table */
-	void *mps;			/* MPS table */
-	void *acpi;			/* ACPI table  (IA64 ext 0.71) */
-	void *acpi20;			/* ACPI table  (ACPI 2.0) */
-	void *smbios;			/* SM BIOS table */
-	void *sal_systab;		/* SAL system table */
-	void *boot_info;		/* boot info table */
-	void *hcdp;			/* HCDP table */
-	void *uga;			/* UGA table */
+	unsigned long mps;		/* MPS table */
+	unsigned long acpi;		/* ACPI table  (IA64 ext 0.71) */
+	unsigned long acpi20;		/* ACPI table  (ACPI 2.0) */
+	unsigned long smbios;		/* SM BIOS table */
+	unsigned long sal_systab;	/* SAL system table */
+	unsigned long boot_info;	/* boot info table */
+	unsigned long hcdp;		/* HCDP table */
+	unsigned long uga;		/* UGA table */
 	efi_get_time_t *get_time;
 	efi_set_time_t *set_time;
 	efi_get_wakeup_time_t *get_wakeup_time;
Index: work-mm3/arch/i386/kernel/acpi/boot.c
===================================================================
--- work-mm3.orig/arch/i386/kernel/acpi/boot.c	2006-01-19 11:26:17.000000000 -0700
+++ work-mm3/arch/i386/kernel/acpi/boot.c	2006-01-19 11:37:23.000000000 -0700
@@ -659,10 +659,10 @@
 	unsigned long rsdp_phys = 0;
 
 	if (efi_enabled) {
-		if (efi.acpi20)
-			return __pa(efi.acpi20);
-		else if (efi.acpi)
-			return __pa(efi.acpi);
+		if (efi.acpi20 != EFI_INVALID_TABLE_ADDR)
+			return efi.acpi20;
+		else if (efi.acpi != EFI_INVALID_TABLE_ADDR)
+			return efi.acpi;
 	}
 	/*
 	 * Scan memory looking for the RSDP signature. First search EBDA (low
Index: work-mm3/arch/ia64/kernel/acpi.c
===================================================================
--- work-mm3.orig/arch/ia64/kernel/acpi.c	2006-01-19 11:26:17.000000000 -0700
+++ work-mm3/arch/ia64/kernel/acpi.c	2006-01-19 11:37:23.000000000 -0700
@@ -618,9 +618,9 @@
 {
 	unsigned long rsdp_phys = 0;
 
-	if (efi.acpi20)
-		rsdp_phys = __pa(efi.acpi20);
-	else if (efi.acpi)
+	if (efi.acpi20 != EFI_INVALID_TABLE_ADDR)
+		rsdp_phys = efi.acpi20;
+	else if (efi.acpi != EFI_INVALID_TABLE_ADDR)
 		printk(KERN_WARNING PREFIX
 		       "v1.0/r0.71 tables no longer supported\n");
 	return rsdp_phys;
Index: work-mm3/drivers/acpi/osl.c
===================================================================
--- work-mm3.orig/drivers/acpi/osl.c	2006-01-19 11:26:18.000000000 -0700
+++ work-mm3/drivers/acpi/osl.c	2006-01-19 11:37:23.000000000 -0700
@@ -156,12 +156,10 @@
 {
 	if (efi_enabled) {
 		addr->pointer_type = ACPI_PHYSICAL_POINTER;
-		if (efi.acpi20)
-			addr->pointer.physical =
-			    (acpi_physical_address) virt_to_phys(efi.acpi20);
-		else if (efi.acpi)
-			addr->pointer.physical =
-			    (acpi_physical_address) virt_to_phys(efi.acpi);
+		if (efi.acpi20 != EFI_INVALID_TABLE_ADDR)
+			addr->pointer.physical = efi.acpi20;
+		else if (efi.acpi != EFI_INVALID_TABLE_ADDR)
+			addr->pointer.physical = efi.acpi;
 		else {
 			printk(KERN_ERR PREFIX
 			       "System description tables not found\n");
Index: work-mm3/arch/i386/kernel/dmi_scan.c
===================================================================
--- work-mm3.orig/arch/i386/kernel/dmi_scan.c	2006-01-19 11:37:04.000000000 -0700
+++ work-mm3/arch/i386/kernel/dmi_scan.c	2006-01-19 11:37:58.000000000 -0700
@@ -216,14 +216,14 @@
 	int rc;
 
 	if (efi_enabled) {
-		if (!efi.smbios)
+		if (efi.smbios == EFI_INVALID_TABLE_ADDR)
 			goto out;
 
                /* This is called as a core_initcall() because it isn't
                 * needed during early boot.  This also means we can
                 * iounmap the space when we're done with it.
 		*/
-		p = ioremap((unsigned long)efi.smbios, 32);
+		p = ioremap(efi.smbios, 32);
 		if (p == NULL)
 			goto out;
 
Index: work-mm3/arch/ia64/kernel/setup.c
===================================================================
--- work-mm3.orig/arch/ia64/kernel/setup.c	2006-01-19 11:26:17.000000000 -0700
+++ work-mm3/arch/ia64/kernel/setup.c	2006-01-19 11:37:23.000000000 -0700
@@ -444,7 +444,7 @@
 	find_memory();
 
 	/* process SAL system table: */
-	ia64_sal_init(efi.sal_systab);
+	ia64_sal_init(__va(efi.sal_systab));
 
 #ifdef CONFIG_SMP
 	cpu_physical_id(0) = hard_smp_processor_id();
Index: work-mm3/arch/ia64/sn/kernel/setup.c
===================================================================
--- work-mm3.orig/arch/ia64/sn/kernel/setup.c	2006-01-19 11:26:17.000000000 -0700
+++ work-mm3/arch/ia64/sn/kernel/setup.c	2006-01-19 11:37:23.000000000 -0700
@@ -339,10 +339,11 @@
 	struct pcdp_interface_pci if_pci;
 	extern struct efi efi;
 
-	pcdp = efi.hcdp;
-	if (! pcdp)
+	if (efi.hcdp == EFI_INVALID_TABLE_ADDR)
 		return;		/* no hcdp/pcdp table */
 
+	pcdp = __va(efi.hcdp);
+
 	if (pcdp->rev < 3)
 		return;		/* only support PCDP (rev >= 3) */
 
Index: work-mm3/drivers/firmware/pcdp.c
===================================================================
--- work-mm3.orig/drivers/firmware/pcdp.c	2006-01-19 11:26:17.000000000 -0700
+++ work-mm3/drivers/firmware/pcdp.c	2006-01-19 11:37:23.000000000 -0700
@@ -89,19 +89,20 @@
 	struct pcdp_uart *uart;
 	struct pcdp_device *dev, *end;
 	int i, serial = 0;
+	int rc = -ENODEV;
 
-	pcdp = efi.hcdp;
-	if (!pcdp)
+	if (efi.hcdp == EFI_INVALID_TABLE_ADDR)
 		return -ENODEV;
 
-	printk(KERN_INFO "PCDP: v%d at 0x%lx\n", pcdp->rev, __pa(pcdp));
+	pcdp = ioremap(efi.hcdp, 4096);
+	printk(KERN_INFO "PCDP: v%d at 0x%lx\n", pcdp->rev, efi.hcdp);
 
 	if (strstr(cmdline, "console=hcdp")) {
 		if (pcdp->rev < 3)
 			serial = 1;
 	} else if (strstr(cmdline, "console=")) {
 		printk(KERN_INFO "Explicit \"console=\"; ignoring PCDP\n");
-		return -ENODEV;
+		goto out;
 	}
 
 	if (pcdp->rev < 3 && efi_uart_console_only())
@@ -110,7 +111,8 @@
 	for (i = 0, uart = pcdp->uart; i < pcdp->num_uarts; i++, uart++) {
 		if (uart->flags & PCDP_UART_PRIMARY_CONSOLE || serial) {
 			if (uart->type == PCDP_CONSOLE_UART) {
-				return setup_serial_console(uart);
+				rc = setup_serial_console(uart);
+				goto out;
 			}
 		}
 	}
@@ -121,10 +123,13 @@
 	     dev = (struct pcdp_device *) ((u8 *) dev + dev->length)) {
 		if (dev->flags & PCDP_PRIMARY_CONSOLE) {
 			if (dev->type == PCDP_CONSOLE_VGA) {
-				return setup_vga_console(dev);
+				rc = setup_vga_console(dev);
+				goto out;
 			}
 		}
 	}
 
-	return -ENODEV;
+out:
+	iounmap(pcdp);
+	return rc;
 }
Index: work-mm3/include/asm-ia64/sn/sn_sal.h
===================================================================
--- work-mm3.orig/include/asm-ia64/sn/sn_sal.h	2006-01-19 11:26:17.000000000 -0700
+++ work-mm3/include/asm-ia64/sn/sn_sal.h	2006-01-19 11:37:23.000000000 -0700
@@ -158,7 +158,7 @@
 static inline u32
 sn_sal_rev(void)
 {
-	struct ia64_sal_systab *systab = efi.sal_systab;
+	struct ia64_sal_systab *systab = __va(efi.sal_systab);
 
 	return (u32)(systab->sal_b_rev_major << 8 | systab->sal_b_rev_minor);
 }

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 5/5] ACPI: clean up memory attribute checking for map/read/write
  2006-01-19 20:10     ` [PATCH 0/5] ia64 ioremap, DMI, EFI system table Bjorn Helgaas
                         ` (3 preceding siblings ...)
  2006-01-19 20:13       ` [PATCH 4/5] EFI: keep physical table addresses in efi structure Bjorn Helgaas
@ 2006-01-19 20:14       ` Bjorn Helgaas
  2006-01-30 17:11       ` [Openipmi-developer] [PATCH 0/5] ia64 ioremap, DMI, EFI system table Matt Domsch
  5 siblings, 0 replies; 7+ messages in thread
From: Bjorn Helgaas @ 2006-01-19 20:14 UTC (permalink / raw)
  To: Matt Domsch
  Cc: linux-ia64, ak, openipmi-developer, akpm, Tolentino, Matthew E,
	linux-kernel, linux-acpi

ia64 ioremap is now smart enough to use the correct memory attributes,
so remove the EFI checks from osl.c.

Depends on the previous ia64 ioremap patch.

Signed-off-by: Bjorn Helgaas <bjorn.helgaas@hp.com>

Index: work-mm3/drivers/acpi/osl.c
===================================================================
--- work-mm3.orig/drivers/acpi/osl.c	2006-01-19 11:37:23.000000000 -0700
+++ work-mm3/drivers/acpi/osl.c	2006-01-19 11:38:05.000000000 -0700
@@ -180,22 +180,14 @@
 acpi_os_map_memory(acpi_physical_address phys, acpi_size size,
 		   void __iomem ** virt)
 {
-	if (efi_enabled) {
-		if (EFI_MEMORY_WB & efi_mem_attributes(phys)) {
-			*virt = (void __iomem *)phys_to_virt(phys);
-		} else {
-			*virt = ioremap(phys, size);
-		}
-	} else {
-		if (phys > ULONG_MAX) {
-			printk(KERN_ERR PREFIX "Cannot map memory that high\n");
-			return AE_BAD_PARAMETER;
-		}
-		/*
-		 * ioremap checks to ensure this is in reserved space
-		 */
-		*virt = ioremap((unsigned long)phys, size);
+	if (phys > ULONG_MAX) {
+		printk(KERN_ERR PREFIX "Cannot map memory that high\n");
+		return AE_BAD_PARAMETER;
 	}
+	/*
+	 * ioremap checks to ensure this is in reserved space
+	 */
+	*virt = ioremap((unsigned long)phys, size);
 
 	if (!*virt)
 		return AE_NO_MEMORY;
@@ -405,18 +397,8 @@
 {
 	u32 dummy;
 	void __iomem *virt_addr;
-	int iomem = 0;
 
-	if (efi_enabled) {
-		if (EFI_MEMORY_WB & efi_mem_attributes(phys_addr)) {
-			/* HACK ALERT! We can use readb/w/l on real memory too.. */
-			virt_addr = (void __iomem *)phys_to_virt(phys_addr);
-		} else {
-			iomem = 1;
-			virt_addr = ioremap(phys_addr, width);
-		}
-	} else
-		virt_addr = (void __iomem *)phys_to_virt(phys_addr);
+	virt_addr = ioremap(phys_addr, width);
 	if (!value)
 		value = &dummy;
 
@@ -434,10 +416,7 @@
 		BUG();
 	}
 
-	if (efi_enabled) {
-		if (iomem)
-			iounmap(virt_addr);
-	}
+	iounmap(virt_addr);
 
 	return AE_OK;
 }
@@ -446,18 +425,8 @@
 acpi_os_write_memory(acpi_physical_address phys_addr, u32 value, u32 width)
 {
 	void __iomem *virt_addr;
-	int iomem = 0;
 
-	if (efi_enabled) {
-		if (EFI_MEMORY_WB & efi_mem_attributes(phys_addr)) {
-			/* HACK ALERT! We can use writeb/w/l on real memory too */
-			virt_addr = (void __iomem *)phys_to_virt(phys_addr);
-		} else {
-			iomem = 1;
-			virt_addr = ioremap(phys_addr, width);
-		}
-	} else
-		virt_addr = (void __iomem *)phys_to_virt(phys_addr);
+	virt_addr = ioremap(phys_addr, width);
 
 	switch (width) {
 	case 8:
@@ -473,8 +442,7 @@
 		BUG();
 	}
 
-	if (iomem)
-		iounmap(virt_addr);
+	iounmap(virt_addr);
 
 	return AE_OK;
 }


-------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc. Do you grep through log files
for problems?  Stop!  Download the new AJAX search engine that makes
searching your log files as easy as surfing the  web.  DOWNLOAD SPLUNK!
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=103432&bid=230486&dat=121642

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [Openipmi-developer] [PATCH 0/5] ia64 ioremap, DMI, EFI system table
  2006-01-19 20:10     ` [PATCH 0/5] ia64 ioremap, DMI, EFI system table Bjorn Helgaas
                         ` (4 preceding siblings ...)
  2006-01-19 20:14       ` [PATCH 5/5] ACPI: clean up memory attribute checking for map/read/write Bjorn Helgaas
@ 2006-01-30 17:11       ` Matt Domsch
  5 siblings, 0 replies; 7+ messages in thread
From: Matt Domsch @ 2006-01-30 17:11 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: linux-ia64, ak, openipmi-developer, akpm, Tolentino, Matthew E,
	linux-kernel, linux-acpi

On Thu, Jan 19, 2006 at 01:10:57PM -0700, Bjorn Helgaas wrote:
> OK, here's a set of patches to (hopefully) clean up this area
> a bit:
> 
> 1  Simplify efi_mem_attribute_range() so I can use it both for
>    /dev/mem validation and ioremap() attribute checking.
> 
> 2  Make ia64 ioremap() check memory attributes, so it works for
>    plain memory that only supports write-back access, as well as
>    for MMIO space that only supports uncacheable access.
> 
> 3  DMI ioremaps too much space, which makes it fail on machines
>    where the SMBIOS table is near the end of a memory region.
> 
> 4  Keep EFI table addresses as physical, not virtual.  The SMBIOS
>    address was physical on x86 but virtual on ia64, which broke
>    dmi_scan_machine().
> 
> 5  Use smarter ioremap() implementation to remove some cruft in
>    acpi_os_{read,write,map}_memory().  This one's just an optional
>    cleanup; I don't think it fixes any bugs.


This set of patches works for me on my IA64 Tiger4 (Dell PowerEdge
7250) in kernel 2.6.16-rc1-mm4.  modprobe ipmi_si successfully
automatically finds the IPMI controller now.

Thanks Bjorn for doing a more complete cleanup in support of this!

Thanks,
Matt

-- 
Matt Domsch
Software Architect
Dell Linux Solutions linux.dell.com & www.dell.com/linux
Linux on Dell mailing lists @ http://lists.us.dell.com

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2006-01-30 17:11 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <20060104221627.GA26064@lists.us.dell.com>
     [not found] ` <200601181029.46352.bjorn.helgaas@hp.com>
     [not found]   ` <20060118181116.GA5537@lists.us.dell.com>
2006-01-19 20:10     ` [PATCH 0/5] ia64 ioremap, DMI, EFI system table Bjorn Helgaas
2006-01-19 20:12       ` [PATCH 1/5] EFI, /dev/mem: simplify efi_mem_attribute_range() Bjorn Helgaas
2006-01-19 20:12       ` [PATCH 2/5] ia64: ioremap: check EFI for valid memory attributes Bjorn Helgaas
2006-01-19 20:13       ` [PATCH 3/5] DMI: only ioremap stuff we actually need Bjorn Helgaas
2006-01-19 20:13       ` [PATCH 4/5] EFI: keep physical table addresses in efi structure Bjorn Helgaas
2006-01-19 20:14       ` [PATCH 5/5] ACPI: clean up memory attribute checking for map/read/write Bjorn Helgaas
2006-01-30 17:11       ` [Openipmi-developer] [PATCH 0/5] ia64 ioremap, DMI, EFI system table Matt Domsch

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox