drm/radeon/kms/pm: resurrect printing power states
[safe/jmp/linux-2.6] / drivers / firmware / memmap.c
index 3bf8ee1..adc0710 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * linux/drivers/firmware/memmap.c
  *  Copyright (C) 2008 SUSE LINUX Products GmbH
- *  by Bernhard Walle <bwalle@suse.de>
+ *  by Bernhard Walle <bernhard.walle@gmx.de>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License v2.0 as published by
@@ -20,6 +20,7 @@
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/bootmem.h>
+#include <linux/slab.h>
 
 /*
  * Data types ------------------------------------------------------------------
  * information is necessary as for the resource tree.
  */
 struct firmware_map_entry {
-       resource_size_t         start;  /* start of the memory range */
-       resource_size_t         end;    /* end of the memory range (incl.) */
+       /*
+        * start and end must be u64 rather than resource_size_t, because e820
+        * resources can lie at addresses above 4G.
+        */
+       u64                     start;  /* start of the memory range */
+       u64                     end;    /* end of the memory range (incl.) */
        const char              *type;  /* type of the memory range */
        struct list_head        list;   /* entry for the linked list */
        struct kobject          kobj;   /* kobject for each entry */
@@ -56,9 +61,9 @@ struct memmap_attribute {
        ssize_t (*show)(struct firmware_map_entry *entry, char *buf);
 };
 
-struct memmap_attribute memmap_start_attr = __ATTR_RO(start);
-struct memmap_attribute memmap_end_attr   = __ATTR_RO(end);
-struct memmap_attribute memmap_type_attr  = __ATTR_RO(type);
+static struct memmap_attribute memmap_start_attr = __ATTR_RO(start);
+static struct memmap_attribute memmap_end_attr   = __ATTR_RO(end);
+static struct memmap_attribute memmap_type_attr  = __ATTR_RO(type);
 
 /*
  * These are default attributes that are added for every memmap entry.
@@ -70,7 +75,7 @@ static struct attribute *def_attrs[] = {
        NULL
 };
 
-static struct sysfs_ops memmap_attr_ops = {
+static const struct sysfs_ops memmap_attr_ops = {
        .show = memmap_attr_show,
 };
 
@@ -101,7 +106,7 @@ static LIST_HEAD(map_entries);
  * Common implementation of firmware_map_add() and firmware_map_add_early()
  * which expects a pre-allocated struct firmware_map_entry.
  **/
-static int firmware_map_add_entry(resource_size_t start, resource_size_t end,
+static int firmware_map_add_entry(u64 start, u64 end,
                                  const char *type,
                                  struct firmware_map_entry *entry)
 {
@@ -118,30 +123,53 @@ static int firmware_map_add_entry(resource_size_t start, resource_size_t end,
        return 0;
 }
 
+/*
+ * Add memmap entry on sysfs
+ */
+static int add_sysfs_fw_map_entry(struct firmware_map_entry *entry)
+{
+       static int map_entries_nr;
+       static struct kset *mmap_kset;
+
+       if (!mmap_kset) {
+               mmap_kset = kset_create_and_add("memmap", NULL, firmware_kobj);
+               if (!mmap_kset)
+                       return -ENOMEM;
+       }
+
+       entry->kobj.kset = mmap_kset;
+       if (kobject_add(&entry->kobj, NULL, "%d", map_entries_nr++))
+               kobject_put(&entry->kobj);
+
+       return 0;
+}
+
 /**
- * firmware_map_add() - Adds a firmware mapping entry.
+ * firmware_map_add_hotplug() - Adds a firmware mapping entry when we do
+ * memory hotplug.
  * @start: Start of the memory range.
  * @end:   End of the memory range (inclusive).
  * @type:  Type of the memory range.
  *
- * This function uses kmalloc() for memory
- * allocation. Use firmware_map_add_early() if you want to use the bootmem
- * allocator.
- *
- * That function must be called before late_initcall.
+ * Adds a firmware mapping entry. This function is for memory hotplug, it is
+ * similar to function firmware_map_add_early(). The only difference is that
+ * it will create the syfs entry dynamically.
  *
  * Returns 0 on success, or -ENOMEM if no memory could be allocated.
  **/
-int firmware_map_add(resource_size_t start, resource_size_t end,
-                    const char *type)
+int __meminit firmware_map_add_hotplug(u64 start, u64 end, const char *type)
 {
        struct firmware_map_entry *entry;
 
-       entry = kmalloc(sizeof(struct firmware_map_entry), GFP_ATOMIC);
+       entry = kzalloc(sizeof(struct firmware_map_entry), GFP_ATOMIC);
        if (!entry)
                return -ENOMEM;
 
-       return firmware_map_add_entry(start, end, type, entry);
+       firmware_map_add_entry(start, end, type, entry);
+       /* create the memmap entry */
+       add_sysfs_fw_map_entry(entry);
+
+       return 0;
 }
 
 /**
@@ -151,18 +179,17 @@ int firmware_map_add(resource_size_t start, resource_size_t end,
  * @type:  Type of the memory range.
  *
  * Adds a firmware mapping entry. This function uses the bootmem allocator
- * for memory allocation. Use firmware_map_add() if you want to use kmalloc().
+ * for memory allocation.
  *
  * That function must be called before late_initcall.
  *
  * Returns 0 on success, or -ENOMEM if no memory could be allocated.
  **/
-int __init firmware_map_add_early(resource_size_t start, resource_size_t end,
-                                 const char *type)
+int __init firmware_map_add_early(u64 start, u64 end, const char *type)
 {
        struct firmware_map_entry *entry;
 
-       entry = alloc_bootmem_low(sizeof(struct firmware_map_entry));
+       entry = alloc_bootmem(sizeof(struct firmware_map_entry));
        if (WARN_ON(!entry))
                return -ENOMEM;
 
@@ -212,19 +239,10 @@ static ssize_t memmap_attr_show(struct kobject *kobj,
  */
 static int __init memmap_init(void)
 {
-       int i = 0;
        struct firmware_map_entry *entry;
-       struct kset *memmap_kset;
-
-       memmap_kset = kset_create_and_add("memmap", NULL, firmware_kobj);
-       if (WARN_ON(!memmap_kset))
-               return -ENOMEM;
 
-       list_for_each_entry(entry, &map_entries, list) {
-               entry->kobj.kset = memmap_kset;
-               if (kobject_add(&entry->kobj, NULL, "%d", i++))
-                       kobject_put(&entry->kobj);
-       }
+       list_for_each_entry(entry, &map_entries, list)
+               add_sysfs_fw_map_entry(entry);
 
        return 0;
 }