diff options
Diffstat (limited to 'drivers/firmware/memmap.c')
| -rw-r--r-- | drivers/firmware/memmap.c | 61 |
1 files changed, 43 insertions, 18 deletions
diff --git a/drivers/firmware/memmap.c b/drivers/firmware/memmap.c index 001622eb86f9..3bf8ee120d42 100644 --- a/drivers/firmware/memmap.c +++ b/drivers/firmware/memmap.c | |||
| @@ -84,20 +84,23 @@ static struct kobj_type memmap_ktype = { | |||
| 84 | */ | 84 | */ |
| 85 | 85 | ||
| 86 | /* | 86 | /* |
| 87 | * Firmware memory map entries | 87 | * Firmware memory map entries. No locking is needed because the |
| 88 | * firmware_map_add() and firmware_map_add_early() functions are called | ||
| 89 | * in firmware initialisation code in one single thread of execution. | ||
| 88 | */ | 90 | */ |
| 89 | static LIST_HEAD(map_entries); | 91 | static LIST_HEAD(map_entries); |
| 90 | 92 | ||
| 91 | /** | 93 | /** |
| 92 | * Common implementation of firmware_map_add() and firmware_map_add_early() | 94 | * firmware_map_add_entry() - Does the real work to add a firmware memmap entry. |
| 93 | * which expects a pre-allocated struct firmware_map_entry. | ||
| 94 | * | ||
| 95 | * @start: Start of the memory range. | 95 | * @start: Start of the memory range. |
| 96 | * @end: End of the memory range (inclusive). | 96 | * @end: End of the memory range (inclusive). |
| 97 | * @type: Type of the memory range. | 97 | * @type: Type of the memory range. |
| 98 | * @entry: Pre-allocated (either kmalloc() or bootmem allocator), uninitialised | 98 | * @entry: Pre-allocated (either kmalloc() or bootmem allocator), uninitialised |
| 99 | * entry. | 99 | * entry. |
| 100 | */ | 100 | * |
| 101 | * Common implementation of firmware_map_add() and firmware_map_add_early() | ||
| 102 | * which expects a pre-allocated struct firmware_map_entry. | ||
| 103 | **/ | ||
| 101 | static int firmware_map_add_entry(resource_size_t start, resource_size_t end, | 104 | static int firmware_map_add_entry(resource_size_t start, resource_size_t end, |
| 102 | const char *type, | 105 | const char *type, |
| 103 | struct firmware_map_entry *entry) | 106 | struct firmware_map_entry *entry) |
| @@ -115,33 +118,52 @@ static int firmware_map_add_entry(resource_size_t start, resource_size_t end, | |||
| 115 | return 0; | 118 | return 0; |
| 116 | } | 119 | } |
| 117 | 120 | ||
| 118 | /* | 121 | /** |
| 119 | * See <linux/firmware-map.h> for documentation. | 122 | * firmware_map_add() - Adds a firmware mapping entry. |
| 120 | */ | 123 | * @start: Start of the memory range. |
| 124 | * @end: End of the memory range (inclusive). | ||
| 125 | * @type: Type of the memory range. | ||
| 126 | * | ||
| 127 | * This function uses kmalloc() for memory | ||
| 128 | * allocation. Use firmware_map_add_early() if you want to use the bootmem | ||
| 129 | * allocator. | ||
| 130 | * | ||
| 131 | * That function must be called before late_initcall. | ||
| 132 | * | ||
| 133 | * Returns 0 on success, or -ENOMEM if no memory could be allocated. | ||
| 134 | **/ | ||
| 121 | int firmware_map_add(resource_size_t start, resource_size_t end, | 135 | int firmware_map_add(resource_size_t start, resource_size_t end, |
| 122 | const char *type) | 136 | const char *type) |
| 123 | { | 137 | { |
| 124 | struct firmware_map_entry *entry; | 138 | struct firmware_map_entry *entry; |
| 125 | 139 | ||
| 126 | entry = kmalloc(sizeof(struct firmware_map_entry), GFP_ATOMIC); | 140 | entry = kmalloc(sizeof(struct firmware_map_entry), GFP_ATOMIC); |
| 127 | WARN_ON(!entry); | ||
| 128 | if (!entry) | 141 | if (!entry) |
| 129 | return -ENOMEM; | 142 | return -ENOMEM; |
| 130 | 143 | ||
| 131 | return firmware_map_add_entry(start, end, type, entry); | 144 | return firmware_map_add_entry(start, end, type, entry); |
| 132 | } | 145 | } |
| 133 | 146 | ||
| 134 | /* | 147 | /** |
| 135 | * See <linux/firmware-map.h> for documentation. | 148 | * firmware_map_add_early() - Adds a firmware mapping entry. |
| 136 | */ | 149 | * @start: Start of the memory range. |
| 150 | * @end: End of the memory range (inclusive). | ||
| 151 | * @type: Type of the memory range. | ||
| 152 | * | ||
| 153 | * Adds a firmware mapping entry. This function uses the bootmem allocator | ||
| 154 | * for memory allocation. Use firmware_map_add() if you want to use kmalloc(). | ||
| 155 | * | ||
| 156 | * That function must be called before late_initcall. | ||
| 157 | * | ||
| 158 | * Returns 0 on success, or -ENOMEM if no memory could be allocated. | ||
| 159 | **/ | ||
| 137 | int __init firmware_map_add_early(resource_size_t start, resource_size_t end, | 160 | int __init firmware_map_add_early(resource_size_t start, resource_size_t end, |
| 138 | const char *type) | 161 | const char *type) |
| 139 | { | 162 | { |
| 140 | struct firmware_map_entry *entry; | 163 | struct firmware_map_entry *entry; |
| 141 | 164 | ||
| 142 | entry = alloc_bootmem_low(sizeof(struct firmware_map_entry)); | 165 | entry = alloc_bootmem_low(sizeof(struct firmware_map_entry)); |
| 143 | WARN_ON(!entry); | 166 | if (WARN_ON(!entry)) |
| 144 | if (!entry) | ||
| 145 | return -ENOMEM; | 167 | return -ENOMEM; |
| 146 | 168 | ||
| 147 | return firmware_map_add_entry(start, end, type, entry); | 169 | return firmware_map_add_entry(start, end, type, entry); |
| @@ -183,7 +205,10 @@ static ssize_t memmap_attr_show(struct kobject *kobj, | |||
| 183 | /* | 205 | /* |
| 184 | * Initialises stuff and adds the entries in the map_entries list to | 206 | * Initialises stuff and adds the entries in the map_entries list to |
| 185 | * sysfs. Important is that firmware_map_add() and firmware_map_add_early() | 207 | * sysfs. Important is that firmware_map_add() and firmware_map_add_early() |
| 186 | * must be called before late_initcall. | 208 | * must be called before late_initcall. That's just because that function |
| 209 | * is called as late_initcall() function, which means that if you call | ||
| 210 | * firmware_map_add() or firmware_map_add_early() afterwards, the entries | ||
| 211 | * are not added to sysfs. | ||
| 187 | */ | 212 | */ |
| 188 | static int __init memmap_init(void) | 213 | static int __init memmap_init(void) |
| 189 | { | 214 | { |
| @@ -192,13 +217,13 @@ static int __init memmap_init(void) | |||
| 192 | struct kset *memmap_kset; | 217 | struct kset *memmap_kset; |
| 193 | 218 | ||
| 194 | memmap_kset = kset_create_and_add("memmap", NULL, firmware_kobj); | 219 | memmap_kset = kset_create_and_add("memmap", NULL, firmware_kobj); |
| 195 | WARN_ON(!memmap_kset); | 220 | if (WARN_ON(!memmap_kset)) |
| 196 | if (!memmap_kset) | ||
| 197 | return -ENOMEM; | 221 | return -ENOMEM; |
| 198 | 222 | ||
| 199 | list_for_each_entry(entry, &map_entries, list) { | 223 | list_for_each_entry(entry, &map_entries, list) { |
| 200 | entry->kobj.kset = memmap_kset; | 224 | entry->kobj.kset = memmap_kset; |
| 201 | kobject_add(&entry->kobj, NULL, "%d", i++); | 225 | if (kobject_add(&entry->kobj, NULL, "%d", i++)) |
| 226 | kobject_put(&entry->kobj); | ||
| 202 | } | 227 | } |
| 203 | 228 | ||
| 204 | return 0; | 229 | return 0; |
