Initial Contribution

msm-2.6.38: tag AU_LINUX_ANDROID_GINGERBREAD.02.03.04.00.142

Signed-off-by: Bryan Huntsman <bryanh@codeaurora.org>
diff --git a/drivers/base/memory.c b/drivers/base/memory.c
index 45d7c8f..42befd1 100644
--- a/drivers/base/memory.c
+++ b/drivers/base/memory.c
@@ -62,6 +62,9 @@
 
 static BLOCKING_NOTIFIER_HEAD(memory_chain);
 
+unsigned long movable_reserved_start, movable_reserved_size;
+unsigned long low_power_memory_start, low_power_memory_size;
+
 int register_memory_notifier(struct notifier_block *nb)
 {
         return blocking_notifier_chain_register(&memory_chain, nb);
@@ -366,6 +369,64 @@
 				&attr_block_size_bytes.attr);
 }
 
+static ssize_t
+print_movable_size(struct class *class, struct class_attribute *attr, char *buf)
+{
+	return sprintf(buf, "%lx\n", movable_reserved_size);
+}
+
+static CLASS_ATTR(movable_size_bytes, 0444, print_movable_size, NULL);
+
+static int movable_size_init(void)
+{
+	return sysfs_create_file(&memory_sysdev_class.kset.kobj,
+				&class_attr_movable_size_bytes.attr);
+}
+
+static ssize_t
+print_movable_start(struct class *class, struct class_attribute *attr, char *buf)
+{
+	return sprintf(buf, "%lx\n", movable_reserved_start);
+}
+
+static CLASS_ATTR(movable_start_bytes, 0444, print_movable_start, NULL);
+
+static int movable_start_init(void)
+{
+	return sysfs_create_file(&memory_sysdev_class.kset.kobj,
+				&class_attr_movable_start_bytes.attr);
+}
+
+static ssize_t
+print_low_power_memory_size(struct class *class, struct class_attribute *attr, char *buf)
+{
+	return sprintf(buf, "%lx\n", low_power_memory_size);
+}
+
+static CLASS_ATTR(low_power_memory_size_bytes, 0444,
+	print_low_power_memory_size, NULL);
+
+static int low_power_memory_size_init(void)
+{
+	return sysfs_create_file(&memory_sysdev_class.kset.kobj,
+				&class_attr_low_power_memory_size_bytes.attr);
+}
+
+static ssize_t
+print_low_power_memory_start(struct class *class, struct class_attribute *attr, char *buf)
+{
+	return sprintf(buf, "%lx\n", low_power_memory_start);
+}
+
+static CLASS_ATTR(low_power_memory_start_bytes, 0444,
+	print_low_power_memory_start, NULL);
+
+static int low_power_memory_start_init(void)
+{
+	return sysfs_create_file(&memory_sysdev_class.kset.kobj,
+				&class_attr_low_power_memory_start_bytes.attr);
+}
+
 /*
  * Some architectures will have custom drivers to do this, and
  * will not need to do it from userspace.  The fake hot-add code
@@ -473,6 +534,96 @@
 }
 #endif
 
+#ifdef CONFIG_ARCH_MEMORY_REMOVE
+static ssize_t
+memory_remove_store(struct class *class, struct class_attribute *attr,
+		    const char *buf, size_t count)
+{
+	u64 phys_addr;
+	int ret;
+
+	phys_addr = simple_strtoull(buf, NULL, 0);
+
+	ret = physical_remove_memory(phys_addr,
+		PAGES_PER_SECTION << PAGE_SHIFT);
+
+	if (ret)
+		count = ret;
+
+	return count;
+}
+static CLASS_ATTR(remove, S_IWUSR, NULL, memory_remove_store);
+
+static int memory_remove_init(void)
+{
+	return sysfs_create_file(&memory_sysdev_class.kset.kobj,
+				&class_attr_remove.attr);
+}
+
+static ssize_t
+memory_active_store(struct class *class, struct class_attribute *attr,
+		    const char *buf, size_t count)
+{
+	u64 phys_addr;
+	int ret;
+
+	phys_addr = simple_strtoull(buf, NULL, 0);
+
+	ret = physical_active_memory(phys_addr,
+		PAGES_PER_SECTION << PAGE_SHIFT);
+
+	if (ret)
+		count = ret;
+
+	return count;
+}
+static CLASS_ATTR(active, S_IWUSR, NULL, memory_active_store);
+
+static int memory_active_init(void)
+{
+	return sysfs_create_file(&memory_sysdev_class.kset.kobj,
+				&class_attr_active.attr);
+}
+
+static ssize_t
+memory_low_power_store(struct class *class, struct class_attribute *attr,
+		       const char *buf, size_t count)
+{
+	u64 phys_addr;
+	int ret;
+
+	phys_addr = simple_strtoull(buf, NULL, 0);
+
+	ret = physical_low_power_memory(phys_addr,
+		PAGES_PER_SECTION << PAGE_SHIFT);
+
+	if (ret)
+		count = ret;
+
+	return count;
+}
+static CLASS_ATTR(low_power, S_IWUSR, NULL, memory_low_power_store);
+
+static int memory_low_power_init(void)
+{
+	return sysfs_create_file(&memory_sysdev_class.kset.kobj,
+				&class_attr_low_power.attr);
+}
+#else
+static inline int memory_remove_init(void)
+{
+	return 0;
+}
+static inline int memory_active_init(void)
+{
+	return 0;
+}
+static inline int memory_low_power_init(void)
+{
+	return 0;
+}
+#endif
+
 /*
  * Note that phys_device is optional.  It is here to allow for
  * differentiation between which *physical* devices each
@@ -665,9 +816,30 @@
 	err = memory_fail_init();
 	if (!ret)
 		ret = err;
+	err = memory_remove_init();
+	if (!ret)
+		ret = err;
+	err = memory_active_init();
+	if (!ret)
+		ret = err;
+	err = memory_low_power_init();
+	if (!ret)
+		ret = err;
 	err = block_size_init();
 	if (!ret)
 		ret = err;
+	err = movable_size_init();
+	if (!ret)
+		ret = err;
+	err = movable_start_init();
+	if (!ret)
+		ret = err;
+	err = low_power_memory_size_init();
+	if (!ret)
+		ret = err;
+	err = low_power_memory_start_init();
+	if (!ret)
+		ret = err;
 out:
 	if (ret)
 		printk(KERN_ERR "%s() failed: %d\n", __func__, ret);