Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Ben Hutchings and committed by
David Woodhouse
b520e412 4d1ee80f

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