linux-mips.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH -v1] MIPS: fix pfn_valid() for FLATMEM
@ 2009-10-09 16:15 Wu Zhangjin
  2009-10-09 16:20 ` Wu Zhangjin
  2009-10-10 14:38 ` Wu Zhangjin
  0 siblings, 2 replies; 11+ messages in thread
From: Wu Zhangjin @ 2009-10-09 16:15 UTC (permalink / raw)
  To: linux-mips
  Cc: Atsushi Nemoto, ralf, rjw, Sergei Shtylyov, Pavel Machek,
	Wu Zhangjin

When CONFIG_FLATMEM enabled, STD/Hiberation will fail on YeeLoong
laptop, This patch fixes it:

if pfn is between min_low_pfn and max_mapnr, the old pfn_valid() will
return TRUE, but if the memory is not continuous, for example:

$ cat /proc/iomem | grep "System RAM"
00000000-0fffffff : System RAM
90000000-bfffffff : System RAM

as we can see, it is not continuous, so, some of the memory is not
valid, and at last make STD/Hibernate fail when shrinking a too large
number of invalid memory.

the "invalid" memory here include the memory space we never used.

10000000-3fffffff
80000000-8fffffff

and also include the meory space we have mapped into pci space.

40000000-7fffffff : pci memory space

Here, we fix it via checking pfn is in the "System RAM" or not. and
Seems pfn_valid() is not called in assembly code, we move it to
"!__ASSEMBLY__" to ensure we can simply declare it via "extern int
pfn_valid(unsigned long)" without Compiling Error.

(This -v1 version incorporates feedback from Pavel Machek <pavel@ucw.cz>
 and Sergei Shtylyov <sshtylyov@ru.mvista.com> and Ralf)

Signed-off-by: Wu Zhangjin <wuzhangjin@gmail.com>
---
 arch/mips/include/asm/page.h |   50 ++++++++++++++++++-----------------------
 arch/mips/mm/page.c          |   18 +++++++++++++++
 2 files changed, 40 insertions(+), 28 deletions(-)

diff --git a/arch/mips/include/asm/page.h b/arch/mips/include/asm/page.h
index f266295..dc28d0a 100644
--- a/arch/mips/include/asm/page.h
+++ b/arch/mips/include/asm/page.h
@@ -146,36 +146,9 @@ typedef struct { unsigned long pgprot; } pgprot_t;
  */
 #define ptep_buddy(x)	((pte_t *)((unsigned long)(x) ^ sizeof(pte_t)))
 
-#endif /* !__ASSEMBLY__ */
-
-/*
- * __pa()/__va() should be used only during mem init.
- */
-#ifdef CONFIG_64BIT
-#define __pa(x)								\
-({									\
-    unsigned long __x = (unsigned long)(x);				\
-    __x < CKSEG0 ? XPHYSADDR(__x) : CPHYSADDR(__x);			\
-})
-#else
-#define __pa(x)								\
-    ((unsigned long)(x) - PAGE_OFFSET + PHYS_OFFSET)
-#endif
-#define __va(x)		((void *)((unsigned long)(x) + PAGE_OFFSET - PHYS_OFFSET))
-#define __pa_symbol(x)	__pa(RELOC_HIDE((unsigned long)(x), 0))
-
-#define pfn_to_kaddr(pfn)	__va((pfn) << PAGE_SHIFT)
-
 #ifdef CONFIG_FLATMEM
 
-#define pfn_valid(pfn)							\
-({									\
-	unsigned long __pfn = (pfn);					\
-	/* avoid <linux/bootmem.h> include hell */			\
-	extern unsigned long min_low_pfn;				\
-									\
-	__pfn >= min_low_pfn && __pfn < max_mapnr;			\
-})
+extern int pfn_valid(unsigned long);
 
 #elif defined(CONFIG_SPARSEMEM)
 
@@ -194,6 +167,27 @@ typedef struct { unsigned long pgprot; } pgprot_t;
 
 #endif
 
+
+#endif /* !__ASSEMBLY__ */
+
+/*
+ * __pa()/__va() should be used only during mem init.
+ */
+#ifdef CONFIG_64BIT
+#define __pa(x)								\
+({									\
+    unsigned long __x = (unsigned long)(x);				\
+    __x < CKSEG0 ? XPHYSADDR(__x) : CPHYSADDR(__x);			\
+})
+#else
+#define __pa(x)								\
+    ((unsigned long)(x) - PAGE_OFFSET + PHYS_OFFSET)
+#endif
+#define __va(x)		((void *)((unsigned long)(x) + PAGE_OFFSET - PHYS_OFFSET))
+#define __pa_symbol(x)	__pa(RELOC_HIDE((unsigned long)(x), 0))
+
+#define pfn_to_kaddr(pfn)	__va((pfn) << PAGE_SHIFT)
+
 #define virt_to_page(kaddr)	pfn_to_page(PFN_DOWN(virt_to_phys(kaddr)))
 #define virt_addr_valid(kaddr)	pfn_valid(PFN_DOWN(virt_to_phys(kaddr)))
 
diff --git a/arch/mips/mm/page.c b/arch/mips/mm/page.c
index f5c7375..203d805 100644
--- a/arch/mips/mm/page.c
+++ b/arch/mips/mm/page.c
@@ -689,3 +689,21 @@ void copy_page(void *to, void *from)
 }
 
 #endif /* CONFIG_SIBYTE_DMA_PAGEOPS */
+
+#ifdef CONFIG_FLATMEM
+int pfn_valid(unsigned long pfn)
+{
+	int i;
+
+	for (i = 0; i < boot_mem_map.nr_map; i++) {
+		if ((boot_mem_map.map[i].type == BOOT_MEM_RAM) ||
+			(boot_mem_map.map[i].type == BOOT_MEM_ROM_DATA)) {
+			if ((pfn >= PFN_DOWN(boot_mem_map.map[i].addr)) &&
+				(pfn < PFN_UP(boot_mem_map.map[i].addr +
+					boot_mem_map.map[i].size)))
+				return 1;
+		}
+	}
+	return 0;
+}
+#endif
-- 
1.6.2.1

^ permalink raw reply related	[flat|nested] 11+ messages in thread
* [PATCH -v1] MIPS: fix pfn_valid() for FLATMEM
@ 2009-10-08 11:32 Wu Zhangjin
  2009-10-08 20:21 ` Rafael J. Wysocki
  0 siblings, 1 reply; 11+ messages in thread
From: Wu Zhangjin @ 2009-10-08 11:32 UTC (permalink / raw)
  To: linux-mips
  Cc: Ralf Baechle, Rafael J. Wysocki, Sergei Shtylyov, Pavel Machek,
	Wu Zhangjin

When CONFIG_FLATMEM enabled, STD/Hiberation will fail on YeeLoong
laptop, This patch fixes it:

if pfn is between min_low_pfn and max_mapnr, the old pfn_valid() will
return TRUE, but in reality, if the memory is not continuous, it should
be false. for example:

$ cat /proc/iomem | grep "System RAM"
00000000-0fffffff : System RAM
90000000-bfffffff : System RAM

as we can see, it is not continuous, so, some of the memory is not valid
but regarded as valid by pfn_valid(), and at last make STD/Hibernate
fail when shrinking a too large number of invalid memory.

Here, we fix it via checking pfn is in the "System RAM" or not. and
Seems pfn_valid() is not called in assembly code, we move it to
"!__ASSEMBLY__" to ensure we can simply declare it via "extern int
pfn_valid(unsigned long)" without Compiling Error.

(This -v1 version incorporates feedback from Pavel Machek <pavel@ucw.cz>
 and Sergei Shtylyov <sshtylyov@ru.mvista.com>)

Signed-off-by: Wu Zhangjin <wuzhangjin@gmail.com>
---
 arch/mips/include/asm/page.h |   50 ++++++++++++++++++-----------------------
 arch/mips/mm/page.c          |   17 ++++++++++++++
 2 files changed, 39 insertions(+), 28 deletions(-)

diff --git a/arch/mips/include/asm/page.h b/arch/mips/include/asm/page.h
index 4320239..ef43905 100644
--- a/arch/mips/include/asm/page.h
+++ b/arch/mips/include/asm/page.h
@@ -145,36 +145,9 @@ typedef struct { unsigned long pgprot; } pgprot_t;
  */
 #define ptep_buddy(x)	((pte_t *)((unsigned long)(x) ^ sizeof(pte_t)))
 
-#endif /* !__ASSEMBLY__ */
-
-/*
- * __pa()/__va() should be used only during mem init.
- */
-#ifdef CONFIG_64BIT
-#define __pa(x)								\
-({									\
-    unsigned long __x = (unsigned long)(x);				\
-    __x < CKSEG0 ? XPHYSADDR(__x) : CPHYSADDR(__x);			\
-})
-#else
-#define __pa(x)								\
-    ((unsigned long)(x) - PAGE_OFFSET + PHYS_OFFSET)
-#endif
-#define __va(x)		((void *)((unsigned long)(x) + PAGE_OFFSET - PHYS_OFFSET))
-#define __pa_symbol(x)	__pa(RELOC_HIDE((unsigned long)(x), 0))
-
-#define pfn_to_kaddr(pfn)	__va((pfn) << PAGE_SHIFT)
-
 #ifdef CONFIG_FLATMEM
 
-#define pfn_valid(pfn)							\
-({									\
-	unsigned long __pfn = (pfn);					\
-	/* avoid <linux/bootmem.h> include hell */			\
-	extern unsigned long min_low_pfn;				\
-									\
-	__pfn >= min_low_pfn && __pfn < max_mapnr;			\
-})
+extern int pfn_valid(unsigned long);
 
 #elif defined(CONFIG_SPARSEMEM)
 
@@ -193,6 +166,27 @@ typedef struct { unsigned long pgprot; } pgprot_t;
 
 #endif
 
+
+#endif /* !__ASSEMBLY__ */
+
+/*
+ * __pa()/__va() should be used only during mem init.
+ */
+#ifdef CONFIG_64BIT
+#define __pa(x)								\
+({									\
+    unsigned long __x = (unsigned long)(x);				\
+    __x < CKSEG0 ? XPHYSADDR(__x) : CPHYSADDR(__x);			\
+})
+#else
+#define __pa(x)								\
+    ((unsigned long)(x) - PAGE_OFFSET + PHYS_OFFSET)
+#endif
+#define __va(x)		((void *)((unsigned long)(x) + PAGE_OFFSET - PHYS_OFFSET))
+#define __pa_symbol(x)	__pa(RELOC_HIDE((unsigned long)(x), 0))
+
+#define pfn_to_kaddr(pfn)	__va((pfn) << PAGE_SHIFT)
+
 #define virt_to_page(kaddr)	pfn_to_page(PFN_DOWN(virt_to_phys(kaddr)))
 #define virt_addr_valid(kaddr)	pfn_valid(PFN_DOWN(virt_to_phys(kaddr)))
 
diff --git a/arch/mips/mm/page.c b/arch/mips/mm/page.c
index f5c7375..e0a3f72 100644
--- a/arch/mips/mm/page.c
+++ b/arch/mips/mm/page.c
@@ -689,3 +689,20 @@ void copy_page(void *to, void *from)
 }
 
 #endif /* CONFIG_SIBYTE_DMA_PAGEOPS */
+
+#ifdef CONFIG_FLATMEM
+int pfn_valid(unsigned long pfn)
+{
+	int i;
+
+	for (i = 0; i < boot_mem_map.nr_map; i++) {
+		if (boot_mem_map.map[i].type == BOOT_MEM_RAM) {
+			if ((pfn >= PFN_DOWN(boot_mem_map.map[i].addr)) &&
+				(pfn < PFN_UP(boot_mem_map.map[i].addr +
+					boot_mem_map.map[i].size)))
+				return 1;
+		}
+	}
+	return 0;
+}
+#endif
-- 
1.6.2.1

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

end of thread, other threads:[~2009-10-14  1:06 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-10-09 16:15 [PATCH -v1] MIPS: fix pfn_valid() for FLATMEM Wu Zhangjin
2009-10-09 16:20 ` Wu Zhangjin
2009-10-10 14:38 ` Wu Zhangjin
2009-10-10 19:19   ` Wu Zhangjin
  -- strict thread matches above, loose matches on Subject: below --
2009-10-08 11:32 Wu Zhangjin
2009-10-08 20:21 ` Rafael J. Wysocki
2009-10-08 20:44   ` Ralf Baechle
2009-10-09  2:08     ` Wu Zhangjin
2009-10-09 16:02       ` Wu Zhangjin
2009-10-13 22:04         ` Ralf Baechle
2009-10-14  1:06           ` Wu Zhangjin

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).