aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJiri Slaby <jslaby@suse.cz>2010-10-26 17:22:11 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2010-10-26 19:52:11 -0400
commita56d5318716d120e040294bb258901ba89fb9c90 (patch)
tree107c4ffcccecc99cee94c118650e32dfe192e57d
parentf3ab2636c5c1dd9ab0ff53a46d8354d5769ffdd4 (diff)
hpet: unmap unused I/O space
When the initialization code in hpet finds a memory resource and does not find an IRQ, it does not unmap the memory resource previously mapped. There are buggy BIOSes which report resources exactly like this and what is worse the memory region bases point to normal RAM. This normally would not matter since the space is not touched. But when PAT is turned on, ioremap causes the page to be uncached and sets this bit in page->flags. Then when the page is about to be used by the allocator, it is reported as: BUG: Bad page state in process md5sum pfn:3ed00 page:ffffea0000dbd800 count:0 mapcount:0 mapping:(null) index:0x0 page flags: 0x20000001000000(uncached) Pid: 7956, comm: md5sum Not tainted 2.6.34-12-desktop #1 Call Trace: [<ffffffff810df851>] bad_page+0xb1/0x100 [<ffffffff810dfa45>] prep_new_page+0x1a5/0x1c0 [<ffffffff810dfe01>] get_page_from_freelist+0x3a1/0x640 [<ffffffff810e01af>] __alloc_pages_nodemask+0x10f/0x6b0 ... In this particular case: 1) HPET returns 3ed00000 as memory region base, but it is not in reserved ranges reported by the BIOS (excerpt): BIOS-e820: 0000000000100000 - 00000000af6cf000 (usable) BIOS-e820: 00000000af6cf000 - 00000000afdcf000 (reserved) 2) there is no IRQ resource reported by HPET method. On the other hand, the Intel HPET specs (1.0a) says (3.2.5.1): _CRS ( // Report 1K of memory consumed by this Timer Block memory range consumed // Optional: only used if BIOS allocates Interrupts [1] IRQs consumed ) [1] For case where Timer Block is configured to consume IRQ0/IRQ8 AND Legacy 8254/Legacy RTC hardware still exists, the device objects associated with 8254 & RTC devices should not report IRQ0/IRQ8 as "consumed resources". So in theory we should check whether if it is the case and use those interrupts instead. Anyway the address reported by the BIOS here is bogus, so non-presence of IRQ doesn't mean the "optional" part in point 2). Since I got no reply previously, fix this by simply unmapping the space when IRQ is not found and memory region was mapped previously. It would be probably more safe to walk the resources again and unmap appropriately depending on type. But as we now use only ioremap for both 2 memory resource types, it is not necessarily needed right now. Addresses https://bugzilla.novell.com/show_bug.cgi?id=629908 Reported-by: Olaf Hering <olaf@aepfle.de> Signed-off-by: Jiri Slaby <jslaby@suse.cz> Acked-by: Clemens Ladisch <clemens@ladisch.de> Cc: <stable@kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--drivers/char/hpet.c2
1 files changed, 2 insertions, 0 deletions
diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c
index a4eee324eb1e..84e6a7e673b7 100644
--- a/drivers/char/hpet.c
+++ b/drivers/char/hpet.c
@@ -1000,6 +1000,8 @@ static int hpet_acpi_add(struct acpi_device *device)
1000 return -ENODEV; 1000 return -ENODEV;
1001 1001
1002 if (!data.hd_address || !data.hd_nirqs) { 1002 if (!data.hd_address || !data.hd_nirqs) {
1003 if (data.hd_address)
1004 iounmap(data.hd_address);
1003 printk("%s: no address or irqs in _CRS\n", __func__); 1005 printk("%s: no address or irqs in _CRS\n", __func__);
1004 return -ENODEV; 1006 return -ENODEV;
1005 } 1007 }