diff options
Diffstat (limited to 'drivers/firmware')
-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; |