Commit b520e412faaaad35641aeedd6059179f9f1b393c
Committed by
David Woodhouse
1 parent
4d1ee80f3a
Exists in
master
and in
20 other branches
mtd: Replace static array of devices with an idr structure
Signed-off-by: Ben Hutchings <bhutchings@solarflare.com> Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com> Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
Showing 3 changed files with 81 additions and 83 deletions Side-by-side Diff
drivers/mtd/mtdcore.c
... | ... | @@ -17,6 +17,7 @@ |
17 | 17 | #include <linux/init.h> |
18 | 18 | #include <linux/mtd/compatmac.h> |
19 | 19 | #include <linux/proc_fs.h> |
20 | +#include <linux/idr.h> | |
20 | 21 | |
21 | 22 | #include <linux/mtd/mtd.h> |
22 | 23 | #include "internal.h" |
23 | 24 | |
24 | 25 | |
25 | 26 | |
... | ... | @@ -33,14 +34,19 @@ |
33 | 34 | .resume = mtd_cls_resume, |
34 | 35 | }; |
35 | 36 | |
37 | +static DEFINE_IDR(mtd_idr); | |
38 | + | |
36 | 39 | /* These are exported solely for the purpose of mtd_blkdevs.c. You |
37 | 40 | should not use them for _anything_ else */ |
38 | 41 | DEFINE_MUTEX(mtd_table_mutex); |
39 | -struct mtd_info *mtd_table[MAX_MTD_DEVICES]; | |
40 | - | |
41 | 42 | EXPORT_SYMBOL_GPL(mtd_table_mutex); |
42 | -EXPORT_SYMBOL_GPL(mtd_table); | |
43 | 43 | |
44 | +struct mtd_info *__mtd_next_device(int i) | |
45 | +{ | |
46 | + return idr_get_next(&mtd_idr, &i); | |
47 | +} | |
48 | +EXPORT_SYMBOL_GPL(__mtd_next_device); | |
49 | + | |
44 | 50 | static LIST_HEAD(mtd_notifiers); |
45 | 51 | |
46 | 52 | |
47 | 53 | |
... | ... | @@ -235,13 +241,13 @@ |
235 | 241 | * Add a device to the list of MTD devices present in the system, and |
236 | 242 | * notify each currently active MTD 'user' of its arrival. Returns |
237 | 243 | * zero on success or 1 on failure, which currently will only happen |
238 | - * if the number of present devices exceeds MAX_MTD_DEVICES (i.e. 16) | |
239 | - * or there's a sysfs error. | |
244 | + * if there is insufficient memory or a sysfs error. | |
240 | 245 | */ |
241 | 246 | |
242 | 247 | int add_mtd_device(struct mtd_info *mtd) |
243 | 248 | { |
244 | - int i; | |
249 | + struct mtd_notifier *not; | |
250 | + int i, error; | |
245 | 251 | |
246 | 252 | if (!mtd->backing_dev_info) { |
247 | 253 | switch (mtd->type) { |
248 | 254 | |
249 | 255 | |
250 | 256 | |
251 | 257 | |
252 | 258 | |
253 | 259 | |
254 | 260 | |
255 | 261 | |
256 | 262 | |
257 | 263 | |
... | ... | @@ -260,71 +266,74 @@ |
260 | 266 | BUG_ON(mtd->writesize == 0); |
261 | 267 | mutex_lock(&mtd_table_mutex); |
262 | 268 | |
263 | - for (i=0; i < MAX_MTD_DEVICES; i++) | |
264 | - if (!mtd_table[i]) { | |
265 | - struct mtd_notifier *not; | |
269 | + do { | |
270 | + if (!idr_pre_get(&mtd_idr, GFP_KERNEL)) | |
271 | + goto fail_locked; | |
272 | + error = idr_get_new(&mtd_idr, mtd, &i); | |
273 | + } while (error == -EAGAIN); | |
266 | 274 | |
267 | - mtd_table[i] = mtd; | |
268 | - mtd->index = i; | |
269 | - mtd->usecount = 0; | |
275 | + if (error) | |
276 | + goto fail_locked; | |
270 | 277 | |
271 | - if (is_power_of_2(mtd->erasesize)) | |
272 | - mtd->erasesize_shift = ffs(mtd->erasesize) - 1; | |
273 | - else | |
274 | - mtd->erasesize_shift = 0; | |
278 | + mtd->index = i; | |
279 | + mtd->usecount = 0; | |
275 | 280 | |
276 | - if (is_power_of_2(mtd->writesize)) | |
277 | - mtd->writesize_shift = ffs(mtd->writesize) - 1; | |
278 | - else | |
279 | - mtd->writesize_shift = 0; | |
281 | + if (is_power_of_2(mtd->erasesize)) | |
282 | + mtd->erasesize_shift = ffs(mtd->erasesize) - 1; | |
283 | + else | |
284 | + mtd->erasesize_shift = 0; | |
280 | 285 | |
281 | - mtd->erasesize_mask = (1 << mtd->erasesize_shift) - 1; | |
282 | - mtd->writesize_mask = (1 << mtd->writesize_shift) - 1; | |
286 | + if (is_power_of_2(mtd->writesize)) | |
287 | + mtd->writesize_shift = ffs(mtd->writesize) - 1; | |
288 | + else | |
289 | + mtd->writesize_shift = 0; | |
283 | 290 | |
284 | - /* Some chips always power up locked. Unlock them now */ | |
285 | - if ((mtd->flags & MTD_WRITEABLE) | |
286 | - && (mtd->flags & MTD_POWERUP_LOCK) && mtd->unlock) { | |
287 | - if (mtd->unlock(mtd, 0, mtd->size)) | |
288 | - printk(KERN_WARNING | |
289 | - "%s: unlock failed, " | |
290 | - "writes may not work\n", | |
291 | - mtd->name); | |
292 | - } | |
291 | + mtd->erasesize_mask = (1 << mtd->erasesize_shift) - 1; | |
292 | + mtd->writesize_mask = (1 << mtd->writesize_shift) - 1; | |
293 | 293 | |
294 | - /* Caller should have set dev.parent to match the | |
295 | - * physical device. | |
296 | - */ | |
297 | - mtd->dev.type = &mtd_devtype; | |
298 | - mtd->dev.class = &mtd_class; | |
299 | - mtd->dev.devt = MTD_DEVT(i); | |
300 | - dev_set_name(&mtd->dev, "mtd%d", i); | |
301 | - dev_set_drvdata(&mtd->dev, mtd); | |
302 | - if (device_register(&mtd->dev) != 0) { | |
303 | - mtd_table[i] = NULL; | |
304 | - break; | |
305 | - } | |
294 | + /* Some chips always power up locked. Unlock them now */ | |
295 | + if ((mtd->flags & MTD_WRITEABLE) | |
296 | + && (mtd->flags & MTD_POWERUP_LOCK) && mtd->unlock) { | |
297 | + if (mtd->unlock(mtd, 0, mtd->size)) | |
298 | + printk(KERN_WARNING | |
299 | + "%s: unlock failed, writes may not work\n", | |
300 | + mtd->name); | |
301 | + } | |
306 | 302 | |
307 | - if (MTD_DEVT(i)) | |
308 | - device_create(&mtd_class, mtd->dev.parent, | |
309 | - MTD_DEVT(i) + 1, | |
310 | - NULL, "mtd%dro", i); | |
303 | + /* Caller should have set dev.parent to match the | |
304 | + * physical device. | |
305 | + */ | |
306 | + mtd->dev.type = &mtd_devtype; | |
307 | + mtd->dev.class = &mtd_class; | |
308 | + mtd->dev.devt = MTD_DEVT(i); | |
309 | + dev_set_name(&mtd->dev, "mtd%d", i); | |
310 | + dev_set_drvdata(&mtd->dev, mtd); | |
311 | + if (device_register(&mtd->dev) != 0) | |
312 | + goto fail_added; | |
311 | 313 | |
312 | - DEBUG(0, "mtd: Giving out device %d to %s\n",i, mtd->name); | |
313 | - /* No need to get a refcount on the module containing | |
314 | - the notifier, since we hold the mtd_table_mutex */ | |
315 | - list_for_each_entry(not, &mtd_notifiers, list) | |
316 | - not->add(mtd); | |
314 | + if (MTD_DEVT(i)) | |
315 | + device_create(&mtd_class, mtd->dev.parent, | |
316 | + MTD_DEVT(i) + 1, | |
317 | + NULL, "mtd%dro", i); | |
317 | 318 | |
318 | - mutex_unlock(&mtd_table_mutex); | |
319 | - /* We _know_ we aren't being removed, because | |
320 | - our caller is still holding us here. So none | |
321 | - of this try_ nonsense, and no bitching about it | |
322 | - either. :) */ | |
323 | - __module_get(THIS_MODULE); | |
324 | - return 0; | |
325 | - } | |
319 | + DEBUG(0, "mtd: Giving out device %d to %s\n", i, mtd->name); | |
320 | + /* No need to get a refcount on the module containing | |
321 | + the notifier, since we hold the mtd_table_mutex */ | |
322 | + list_for_each_entry(not, &mtd_notifiers, list) | |
323 | + not->add(mtd); | |
326 | 324 | |
327 | 325 | mutex_unlock(&mtd_table_mutex); |
326 | + /* We _know_ we aren't being removed, because | |
327 | + our caller is still holding us here. So none | |
328 | + of this try_ nonsense, and no bitching about it | |
329 | + either. :) */ | |
330 | + __module_get(THIS_MODULE); | |
331 | + return 0; | |
332 | + | |
333 | +fail_added: | |
334 | + idr_remove(&mtd_idr, i); | |
335 | +fail_locked: | |
336 | + mutex_unlock(&mtd_table_mutex); | |
328 | 337 | return 1; |
329 | 338 | } |
330 | 339 | |
... | ... | @@ -344,7 +353,7 @@ |
344 | 353 | |
345 | 354 | mutex_lock(&mtd_table_mutex); |
346 | 355 | |
347 | - if (mtd_table[mtd->index] != mtd) { | |
356 | + if (idr_find(&mtd_idr, mtd->index) != mtd) { | |
348 | 357 | ret = -ENODEV; |
349 | 358 | } else if (mtd->usecount) { |
350 | 359 | printk(KERN_NOTICE "Removing MTD device #%d (%s) with use count %d\n", |
... | ... | @@ -360,7 +369,7 @@ |
360 | 369 | list_for_each_entry(not, &mtd_notifiers, list) |
361 | 370 | not->remove(mtd); |
362 | 371 | |
363 | - mtd_table[mtd->index] = NULL; | |
372 | + idr_remove(&mtd_idr, mtd->index); | |
364 | 373 | |
365 | 374 | module_put(THIS_MODULE); |
366 | 375 | ret = 0; |
... | ... | @@ -448,8 +457,8 @@ |
448 | 457 | break; |
449 | 458 | } |
450 | 459 | } |
451 | - } else if (num >= 0 && num < MAX_MTD_DEVICES) { | |
452 | - ret = mtd_table[num]; | |
460 | + } else if (num >= 0) { | |
461 | + ret = idr_find(&mtd_idr, num); | |
453 | 462 | if (mtd && mtd != ret) |
454 | 463 | ret = NULL; |
455 | 464 | } |
drivers/mtd/mtdcore.h
... | ... | @@ -8,17 +8,7 @@ |
8 | 8 | should not use them for _anything_ else */ |
9 | 9 | |
10 | 10 | extern struct mutex mtd_table_mutex; |
11 | -extern struct mtd_info *mtd_table[MAX_MTD_DEVICES]; | |
12 | - | |
13 | -static inline struct mtd_info *__mtd_next_device(int i) | |
14 | -{ | |
15 | - while (i < MAX_MTD_DEVICES) { | |
16 | - if (mtd_table[i]) | |
17 | - return mtd_table[i]; | |
18 | - i++; | |
19 | - } | |
20 | - return NULL; | |
21 | -} | |
11 | +extern struct mtd_info *__mtd_next_device(int i); | |
22 | 12 | |
23 | 13 | #define mtd_for_each_device(mtd) \ |
24 | 14 | for ((mtd) = __mtd_next_device(0); \ |