powerpc/pseries: CMO unused page hinting
[pandora-kernel.git] / arch / powerpc / platforms / pseries / lpar.c
index 52a80e5..e3139fa 100644 (file)
@@ -609,3 +609,55 @@ void __init hpte_init_lpar(void)
        ppc_md.flush_hash_range = pSeries_lpar_flush_hash_range;
        ppc_md.hpte_clear_all   = pSeries_lpar_hptab_clear;
 }
+
+#ifdef CONFIG_PPC_SMLPAR
+#define CMO_FREE_HINT_DEFAULT 1
+static int cmo_free_hint_flag = CMO_FREE_HINT_DEFAULT;
+
+static int __init cmo_free_hint(char *str)
+{
+       char *parm;
+       parm = strstrip(str);
+
+       if (strcasecmp(parm, "no") == 0 || strcasecmp(parm, "off") == 0) {
+               printk(KERN_INFO "cmo_free_hint: CMO free page hinting is not active.\n");
+               cmo_free_hint_flag = 0;
+               return 1;
+       }
+
+       cmo_free_hint_flag = 1;
+       printk(KERN_INFO "cmo_free_hint: CMO free page hinting is active.\n");
+
+       if (strcasecmp(parm, "yes") == 0 || strcasecmp(parm, "on") == 0)
+               return 1;
+
+       return 0;
+}
+
+__setup("cmo_free_hint=", cmo_free_hint);
+
+static void pSeries_set_page_state(struct page *page, int order,
+                                  unsigned long state)
+{
+       int i, j;
+       unsigned long cmo_page_sz, addr;
+
+       cmo_page_sz = cmo_get_page_size();
+       addr = __pa((unsigned long)page_address(page));
+
+       for (i = 0; i < (1 << order); i++, addr += PAGE_SIZE) {
+               for (j = 0; j < PAGE_SIZE; j += cmo_page_sz)
+                       plpar_hcall_norets(H_PAGE_INIT, state, addr + j, 0);
+       }
+}
+
+void arch_free_page(struct page *page, int order)
+{
+       if (!cmo_free_hint_flag || !firmware_has_feature(FW_FEATURE_CMO))
+               return;
+
+       pSeries_set_page_state(page, order, H_PAGE_SET_UNUSED);
+}
+EXPORT_SYMBOL(arch_free_page);
+
+#endif