Commit b520e412faaaad35641aeedd6059179f9f1b393c

Authored by Ben Hutchings
Committed by David Woodhouse
1 parent 4d1ee80f3a

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); \
include/linux/mtd/mtd.h
... ... @@ -20,7 +20,6 @@
20 20  
21 21 #define MTD_CHAR_MAJOR 90
22 22 #define MTD_BLOCK_MAJOR 31
23   -#define MAX_MTD_DEVICES 32
24 23  
25 24 #define MTD_ERASE_PENDING 0x01
26 25 #define MTD_ERASING 0x02