aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/firmware
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/firmware')
-rw-r--r--drivers/firmware/memmap.c61
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 */
89static LIST_HEAD(map_entries); 91static 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 **/
101static int firmware_map_add_entry(resource_size_t start, resource_size_t end, 104static 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 **/
121int firmware_map_add(resource_size_t start, resource_size_t end, 135int 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 **/
137int __init firmware_map_add_early(resource_size_t start, resource_size_t end, 160int __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 */
188static int __init memmap_init(void) 213static 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;