aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYinghai Lu <yinghai@kernel.org>2009-06-16 18:31:16 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2009-06-16 22:47:28 -0400
commit3b0fde0fac19c180317eb0601b3504083f4b9bf5 (patch)
tree5458ec10f3c6759ec64c6fa27e12e692a575d07a
parent021415468c889979117b1a07b96f7e36de33e995 (diff)
firmware_map: fix hang with x86/32bit
Addresses http://bugzilla.kernel.org/show_bug.cgi?id=13484 Peer reported: | The bug is introduced from kernel 2.6.27, if E820 table reserve the memory | above 4G in 32bit OS(BIOS-e820: 00000000fff80000 - 0000000120000000 | (reserved)), system will report Int 6 error and hang up. The bug is caused by | the following code in drivers/firmware/memmap.c, the resource_size_t is 32bit | variable in 32bit OS, the BUG_ON() will be invoked to result in the Int 6 | error. I try the latest 32bit Ubuntu and Fedora distributions, all hit this | bug. |====== |static int firmware_map_add_entry(resource_size_t start, resource_size_t end, | const char *type, | struct firmware_map_entry *entry) and it only happen with CONFIG_PHYS_ADDR_T_64BIT is not set. it turns out we need to pass u64 instead of resource_size_t for that. [akpm@linux-foundation.org: add comment] Reported-and-tested-by: Peer Chen <pchen@nvidia.com> Signed-off-by: Yinghai Lu <yinghai@kernel.org> Cc: Ingo Molnar <mingo@elte.hu> Acked-by: H. Peter Anvin <hpa@zytor.com> Cc: Thomas Gleixner <tglx@linutronix.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/firmware/memmap.c16
-rw-r--r--include/linux/firmware-map.h12
2 files changed, 13 insertions, 15 deletions
diff --git a/drivers/firmware/memmap.c b/drivers/firmware/memmap.c
index 05aa2d406ac..d5ea8a68d33 100644
--- a/drivers/firmware/memmap.c
+++ b/drivers/firmware/memmap.c
@@ -31,8 +31,12 @@
31 * information is necessary as for the resource tree. 31 * information is necessary as for the resource tree.
32 */ 32 */
33struct firmware_map_entry { 33struct firmware_map_entry {
34 resource_size_t start; /* start of the memory range */ 34 /*
35 resource_size_t end; /* end of the memory range (incl.) */ 35 * start and end must be u64 rather than resource_size_t, because e820
36 * resources can lie at addresses above 4G.
37 */
38 u64 start; /* start of the memory range */
39 u64 end; /* end of the memory range (incl.) */
36 const char *type; /* type of the memory range */ 40 const char *type; /* type of the memory range */
37 struct list_head list; /* entry for the linked list */ 41 struct list_head list; /* entry for the linked list */
38 struct kobject kobj; /* kobject for each entry */ 42 struct kobject kobj; /* kobject for each entry */
@@ -101,7 +105,7 @@ static LIST_HEAD(map_entries);
101 * Common implementation of firmware_map_add() and firmware_map_add_early() 105 * Common implementation of firmware_map_add() and firmware_map_add_early()
102 * which expects a pre-allocated struct firmware_map_entry. 106 * which expects a pre-allocated struct firmware_map_entry.
103 **/ 107 **/
104static int firmware_map_add_entry(resource_size_t start, resource_size_t end, 108static int firmware_map_add_entry(u64 start, u64 end,
105 const char *type, 109 const char *type,
106 struct firmware_map_entry *entry) 110 struct firmware_map_entry *entry)
107{ 111{
@@ -132,8 +136,7 @@ static int firmware_map_add_entry(resource_size_t start, resource_size_t end,
132 * 136 *
133 * Returns 0 on success, or -ENOMEM if no memory could be allocated. 137 * Returns 0 on success, or -ENOMEM if no memory could be allocated.
134 **/ 138 **/
135int firmware_map_add(resource_size_t start, resource_size_t end, 139int firmware_map_add(u64 start, u64 end, const char *type)
136 const char *type)
137{ 140{
138 struct firmware_map_entry *entry; 141 struct firmware_map_entry *entry;
139 142
@@ -157,8 +160,7 @@ int firmware_map_add(resource_size_t start, resource_size_t end,
157 * 160 *
158 * Returns 0 on success, or -ENOMEM if no memory could be allocated. 161 * Returns 0 on success, or -ENOMEM if no memory could be allocated.
159 **/ 162 **/
160int __init firmware_map_add_early(resource_size_t start, resource_size_t end, 163int __init firmware_map_add_early(u64 start, u64 end, const char *type)
161 const char *type)
162{ 164{
163 struct firmware_map_entry *entry; 165 struct firmware_map_entry *entry;
164 166
diff --git a/include/linux/firmware-map.h b/include/linux/firmware-map.h
index cca686b3912..875451f1373 100644
--- a/include/linux/firmware-map.h
+++ b/include/linux/firmware-map.h
@@ -24,21 +24,17 @@
24 */ 24 */
25#ifdef CONFIG_FIRMWARE_MEMMAP 25#ifdef CONFIG_FIRMWARE_MEMMAP
26 26
27int firmware_map_add(resource_size_t start, resource_size_t end, 27int firmware_map_add(u64 start, u64 end, const char *type);
28 const char *type); 28int firmware_map_add_early(u64 start, u64 end, const char *type);
29int firmware_map_add_early(resource_size_t start, resource_size_t end,
30 const char *type);
31 29
32#else /* CONFIG_FIRMWARE_MEMMAP */ 30#else /* CONFIG_FIRMWARE_MEMMAP */
33 31
34static inline int firmware_map_add(resource_size_t start, resource_size_t end, 32static inline int firmware_map_add(u64 start, u64 end, const char *type)
35 const char *type)
36{ 33{
37 return 0; 34 return 0;
38} 35}
39 36
40static inline int firmware_map_add_early(resource_size_t start, 37static inline int firmware_map_add_early(u64 start, u64 end, const char *type)
41 resource_size_t end, const char *type)
42{ 38{
43 return 0; 39 return 0;
44} 40}