mtdcore.c revision b520e412faaaad35641aeedd6059179f9f1b393c
1/* 2 * Core registration and callback routines for MTD 3 * drivers and users. 4 * 5 */ 6 7#include <linux/module.h> 8#include <linux/kernel.h> 9#include <linux/ptrace.h> 10#include <linux/slab.h> 11#include <linux/string.h> 12#include <linux/timer.h> 13#include <linux/major.h> 14#include <linux/fs.h> 15#include <linux/err.h> 16#include <linux/ioctl.h> 17#include <linux/init.h> 18#include <linux/mtd/compatmac.h> 19#include <linux/proc_fs.h> 20#include <linux/idr.h> 21 22#include <linux/mtd/mtd.h> 23#include "internal.h" 24 25#include "mtdcore.h" 26 27static int mtd_cls_suspend(struct device *dev, pm_message_t state); 28static int mtd_cls_resume(struct device *dev); 29 30static struct class mtd_class = { 31 .name = "mtd", 32 .owner = THIS_MODULE, 33 .suspend = mtd_cls_suspend, 34 .resume = mtd_cls_resume, 35}; 36 37static DEFINE_IDR(mtd_idr); 38 39/* These are exported solely for the purpose of mtd_blkdevs.c. You 40 should not use them for _anything_ else */ 41DEFINE_MUTEX(mtd_table_mutex); 42EXPORT_SYMBOL_GPL(mtd_table_mutex); 43 44struct mtd_info *__mtd_next_device(int i) 45{ 46 return idr_get_next(&mtd_idr, &i); 47} 48EXPORT_SYMBOL_GPL(__mtd_next_device); 49 50static LIST_HEAD(mtd_notifiers); 51 52 53#if defined(CONFIG_MTD_CHAR) || defined(CONFIG_MTD_CHAR_MODULE) 54#define MTD_DEVT(index) MKDEV(MTD_CHAR_MAJOR, (index)*2) 55#else 56#define MTD_DEVT(index) 0 57#endif 58 59/* REVISIT once MTD uses the driver model better, whoever allocates 60 * the mtd_info will probably want to use the release() hook... 61 */ 62static void mtd_release(struct device *dev) 63{ 64 dev_t index = MTD_DEVT(dev_to_mtd(dev)->index); 65 66 /* remove /dev/mtdXro node if needed */ 67 if (index) 68 device_destroy(&mtd_class, index + 1); 69} 70 71static int mtd_cls_suspend(struct device *dev, pm_message_t state) 72{ 73 struct mtd_info *mtd = dev_to_mtd(dev); 74 75 if (mtd && mtd->suspend) 76 return mtd->suspend(mtd); 77 else 78 return 0; 79} 80 81static int mtd_cls_resume(struct device *dev) 82{ 83 struct mtd_info *mtd = dev_to_mtd(dev); 84 85 if (mtd && mtd->resume) 86 mtd->resume(mtd); 87 return 0; 88} 89 90static ssize_t mtd_type_show(struct device *dev, 91 struct device_attribute *attr, char *buf) 92{ 93 struct mtd_info *mtd = dev_to_mtd(dev); 94 char *type; 95 96 switch (mtd->type) { 97 case MTD_ABSENT: 98 type = "absent"; 99 break; 100 case MTD_RAM: 101 type = "ram"; 102 break; 103 case MTD_ROM: 104 type = "rom"; 105 break; 106 case MTD_NORFLASH: 107 type = "nor"; 108 break; 109 case MTD_NANDFLASH: 110 type = "nand"; 111 break; 112 case MTD_DATAFLASH: 113 type = "dataflash"; 114 break; 115 case MTD_UBIVOLUME: 116 type = "ubi"; 117 break; 118 default: 119 type = "unknown"; 120 } 121 122 return snprintf(buf, PAGE_SIZE, "%s\n", type); 123} 124static DEVICE_ATTR(type, S_IRUGO, mtd_type_show, NULL); 125 126static ssize_t mtd_flags_show(struct device *dev, 127 struct device_attribute *attr, char *buf) 128{ 129 struct mtd_info *mtd = dev_to_mtd(dev); 130 131 return snprintf(buf, PAGE_SIZE, "0x%lx\n", (unsigned long)mtd->flags); 132 133} 134static DEVICE_ATTR(flags, S_IRUGO, mtd_flags_show, NULL); 135 136static ssize_t mtd_size_show(struct device *dev, 137 struct device_attribute *attr, char *buf) 138{ 139 struct mtd_info *mtd = dev_to_mtd(dev); 140 141 return snprintf(buf, PAGE_SIZE, "%llu\n", 142 (unsigned long long)mtd->size); 143 144} 145static DEVICE_ATTR(size, S_IRUGO, mtd_size_show, NULL); 146 147static ssize_t mtd_erasesize_show(struct device *dev, 148 struct device_attribute *attr, char *buf) 149{ 150 struct mtd_info *mtd = dev_to_mtd(dev); 151 152 return snprintf(buf, PAGE_SIZE, "%lu\n", (unsigned long)mtd->erasesize); 153 154} 155static DEVICE_ATTR(erasesize, S_IRUGO, mtd_erasesize_show, NULL); 156 157static ssize_t mtd_writesize_show(struct device *dev, 158 struct device_attribute *attr, char *buf) 159{ 160 struct mtd_info *mtd = dev_to_mtd(dev); 161 162 return snprintf(buf, PAGE_SIZE, "%lu\n", (unsigned long)mtd->writesize); 163 164} 165static DEVICE_ATTR(writesize, S_IRUGO, mtd_writesize_show, NULL); 166 167static ssize_t mtd_subpagesize_show(struct device *dev, 168 struct device_attribute *attr, char *buf) 169{ 170 struct mtd_info *mtd = dev_to_mtd(dev); 171 unsigned int subpagesize = mtd->writesize >> mtd->subpage_sft; 172 173 return snprintf(buf, PAGE_SIZE, "%u\n", subpagesize); 174 175} 176static DEVICE_ATTR(subpagesize, S_IRUGO, mtd_subpagesize_show, NULL); 177 178static ssize_t mtd_oobsize_show(struct device *dev, 179 struct device_attribute *attr, char *buf) 180{ 181 struct mtd_info *mtd = dev_to_mtd(dev); 182 183 return snprintf(buf, PAGE_SIZE, "%lu\n", (unsigned long)mtd->oobsize); 184 185} 186static DEVICE_ATTR(oobsize, S_IRUGO, mtd_oobsize_show, NULL); 187 188static ssize_t mtd_numeraseregions_show(struct device *dev, 189 struct device_attribute *attr, char *buf) 190{ 191 struct mtd_info *mtd = dev_to_mtd(dev); 192 193 return snprintf(buf, PAGE_SIZE, "%u\n", mtd->numeraseregions); 194 195} 196static DEVICE_ATTR(numeraseregions, S_IRUGO, mtd_numeraseregions_show, 197 NULL); 198 199static ssize_t mtd_name_show(struct device *dev, 200 struct device_attribute *attr, char *buf) 201{ 202 struct mtd_info *mtd = dev_to_mtd(dev); 203 204 return snprintf(buf, PAGE_SIZE, "%s\n", mtd->name); 205 206} 207static DEVICE_ATTR(name, S_IRUGO, mtd_name_show, NULL); 208 209static struct attribute *mtd_attrs[] = { 210 &dev_attr_type.attr, 211 &dev_attr_flags.attr, 212 &dev_attr_size.attr, 213 &dev_attr_erasesize.attr, 214 &dev_attr_writesize.attr, 215 &dev_attr_subpagesize.attr, 216 &dev_attr_oobsize.attr, 217 &dev_attr_numeraseregions.attr, 218 &dev_attr_name.attr, 219 NULL, 220}; 221 222static struct attribute_group mtd_group = { 223 .attrs = mtd_attrs, 224}; 225 226static const struct attribute_group *mtd_groups[] = { 227 &mtd_group, 228 NULL, 229}; 230 231static struct device_type mtd_devtype = { 232 .name = "mtd", 233 .groups = mtd_groups, 234 .release = mtd_release, 235}; 236 237/** 238 * add_mtd_device - register an MTD device 239 * @mtd: pointer to new MTD device info structure 240 * 241 * Add a device to the list of MTD devices present in the system, and 242 * notify each currently active MTD 'user' of its arrival. Returns 243 * zero on success or 1 on failure, which currently will only happen 244 * if there is insufficient memory or a sysfs error. 245 */ 246 247int add_mtd_device(struct mtd_info *mtd) 248{ 249 struct mtd_notifier *not; 250 int i, error; 251 252 if (!mtd->backing_dev_info) { 253 switch (mtd->type) { 254 case MTD_RAM: 255 mtd->backing_dev_info = &mtd_bdi_rw_mappable; 256 break; 257 case MTD_ROM: 258 mtd->backing_dev_info = &mtd_bdi_ro_mappable; 259 break; 260 default: 261 mtd->backing_dev_info = &mtd_bdi_unmappable; 262 break; 263 } 264 } 265 266 BUG_ON(mtd->writesize == 0); 267 mutex_lock(&mtd_table_mutex); 268 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); 274 275 if (error) 276 goto fail_locked; 277 278 mtd->index = i; 279 mtd->usecount = 0; 280 281 if (is_power_of_2(mtd->erasesize)) 282 mtd->erasesize_shift = ffs(mtd->erasesize) - 1; 283 else 284 mtd->erasesize_shift = 0; 285 286 if (is_power_of_2(mtd->writesize)) 287 mtd->writesize_shift = ffs(mtd->writesize) - 1; 288 else 289 mtd->writesize_shift = 0; 290 291 mtd->erasesize_mask = (1 << mtd->erasesize_shift) - 1; 292 mtd->writesize_mask = (1 << mtd->writesize_shift) - 1; 293 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 } 302 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; 313 314 if (MTD_DEVT(i)) 315 device_create(&mtd_class, mtd->dev.parent, 316 MTD_DEVT(i) + 1, 317 NULL, "mtd%dro", i); 318 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); 324 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 333fail_added: 334 idr_remove(&mtd_idr, i); 335fail_locked: 336 mutex_unlock(&mtd_table_mutex); 337 return 1; 338} 339 340/** 341 * del_mtd_device - unregister an MTD device 342 * @mtd: pointer to MTD device info structure 343 * 344 * Remove a device from the list of MTD devices present in the system, 345 * and notify each currently active MTD 'user' of its departure. 346 * Returns zero on success or 1 on failure, which currently will happen 347 * if the requested device does not appear to be present in the list. 348 */ 349 350int del_mtd_device (struct mtd_info *mtd) 351{ 352 int ret; 353 354 mutex_lock(&mtd_table_mutex); 355 356 if (idr_find(&mtd_idr, mtd->index) != mtd) { 357 ret = -ENODEV; 358 } else if (mtd->usecount) { 359 printk(KERN_NOTICE "Removing MTD device #%d (%s) with use count %d\n", 360 mtd->index, mtd->name, mtd->usecount); 361 ret = -EBUSY; 362 } else { 363 struct mtd_notifier *not; 364 365 device_unregister(&mtd->dev); 366 367 /* No need to get a refcount on the module containing 368 the notifier, since we hold the mtd_table_mutex */ 369 list_for_each_entry(not, &mtd_notifiers, list) 370 not->remove(mtd); 371 372 idr_remove(&mtd_idr, mtd->index); 373 374 module_put(THIS_MODULE); 375 ret = 0; 376 } 377 378 mutex_unlock(&mtd_table_mutex); 379 return ret; 380} 381 382/** 383 * register_mtd_user - register a 'user' of MTD devices. 384 * @new: pointer to notifier info structure 385 * 386 * Registers a pair of callbacks function to be called upon addition 387 * or removal of MTD devices. Causes the 'add' callback to be immediately 388 * invoked for each MTD device currently present in the system. 389 */ 390 391void register_mtd_user (struct mtd_notifier *new) 392{ 393 struct mtd_info *mtd; 394 395 mutex_lock(&mtd_table_mutex); 396 397 list_add(&new->list, &mtd_notifiers); 398 399 __module_get(THIS_MODULE); 400 401 mtd_for_each_device(mtd) 402 new->add(mtd); 403 404 mutex_unlock(&mtd_table_mutex); 405} 406 407/** 408 * unregister_mtd_user - unregister a 'user' of MTD devices. 409 * @old: pointer to notifier info structure 410 * 411 * Removes a callback function pair from the list of 'users' to be 412 * notified upon addition or removal of MTD devices. Causes the 413 * 'remove' callback to be immediately invoked for each MTD device 414 * currently present in the system. 415 */ 416 417int unregister_mtd_user (struct mtd_notifier *old) 418{ 419 struct mtd_info *mtd; 420 421 mutex_lock(&mtd_table_mutex); 422 423 module_put(THIS_MODULE); 424 425 mtd_for_each_device(mtd) 426 old->remove(mtd); 427 428 list_del(&old->list); 429 mutex_unlock(&mtd_table_mutex); 430 return 0; 431} 432 433 434/** 435 * get_mtd_device - obtain a validated handle for an MTD device 436 * @mtd: last known address of the required MTD device 437 * @num: internal device number of the required MTD device 438 * 439 * Given a number and NULL address, return the num'th entry in the device 440 * table, if any. Given an address and num == -1, search the device table 441 * for a device with that address and return if it's still present. Given 442 * both, return the num'th driver only if its address matches. Return 443 * error code if not. 444 */ 445 446struct mtd_info *get_mtd_device(struct mtd_info *mtd, int num) 447{ 448 struct mtd_info *ret = NULL, *other; 449 int err = -ENODEV; 450 451 mutex_lock(&mtd_table_mutex); 452 453 if (num == -1) { 454 mtd_for_each_device(other) { 455 if (other == mtd) { 456 ret = mtd; 457 break; 458 } 459 } 460 } else if (num >= 0) { 461 ret = idr_find(&mtd_idr, num); 462 if (mtd && mtd != ret) 463 ret = NULL; 464 } 465 466 if (!ret) 467 goto out_unlock; 468 469 if (!try_module_get(ret->owner)) 470 goto out_unlock; 471 472 if (ret->get_device) { 473 err = ret->get_device(ret); 474 if (err) 475 goto out_put; 476 } 477 478 ret->usecount++; 479 mutex_unlock(&mtd_table_mutex); 480 return ret; 481 482out_put: 483 module_put(ret->owner); 484out_unlock: 485 mutex_unlock(&mtd_table_mutex); 486 return ERR_PTR(err); 487} 488 489/** 490 * get_mtd_device_nm - obtain a validated handle for an MTD device by 491 * device name 492 * @name: MTD device name to open 493 * 494 * This function returns MTD device description structure in case of 495 * success and an error code in case of failure. 496 */ 497 498struct mtd_info *get_mtd_device_nm(const char *name) 499{ 500 int err = -ENODEV; 501 struct mtd_info *mtd = NULL, *other; 502 503 mutex_lock(&mtd_table_mutex); 504 505 mtd_for_each_device(other) { 506 if (!strcmp(name, other->name)) { 507 mtd = other; 508 break; 509 } 510 } 511 512 if (!mtd) 513 goto out_unlock; 514 515 if (!try_module_get(mtd->owner)) 516 goto out_unlock; 517 518 if (mtd->get_device) { 519 err = mtd->get_device(mtd); 520 if (err) 521 goto out_put; 522 } 523 524 mtd->usecount++; 525 mutex_unlock(&mtd_table_mutex); 526 return mtd; 527 528out_put: 529 module_put(mtd->owner); 530out_unlock: 531 mutex_unlock(&mtd_table_mutex); 532 return ERR_PTR(err); 533} 534 535void put_mtd_device(struct mtd_info *mtd) 536{ 537 int c; 538 539 mutex_lock(&mtd_table_mutex); 540 c = --mtd->usecount; 541 if (mtd->put_device) 542 mtd->put_device(mtd); 543 mutex_unlock(&mtd_table_mutex); 544 BUG_ON(c < 0); 545 546 module_put(mtd->owner); 547} 548 549/* default_mtd_writev - default mtd writev method for MTD devices that 550 * don't implement their own 551 */ 552 553int default_mtd_writev(struct mtd_info *mtd, const struct kvec *vecs, 554 unsigned long count, loff_t to, size_t *retlen) 555{ 556 unsigned long i; 557 size_t totlen = 0, thislen; 558 int ret = 0; 559 560 if(!mtd->write) { 561 ret = -EROFS; 562 } else { 563 for (i=0; i<count; i++) { 564 if (!vecs[i].iov_len) 565 continue; 566 ret = mtd->write(mtd, to, vecs[i].iov_len, &thislen, vecs[i].iov_base); 567 totlen += thislen; 568 if (ret || thislen != vecs[i].iov_len) 569 break; 570 to += vecs[i].iov_len; 571 } 572 } 573 if (retlen) 574 *retlen = totlen; 575 return ret; 576} 577 578EXPORT_SYMBOL_GPL(add_mtd_device); 579EXPORT_SYMBOL_GPL(del_mtd_device); 580EXPORT_SYMBOL_GPL(get_mtd_device); 581EXPORT_SYMBOL_GPL(get_mtd_device_nm); 582EXPORT_SYMBOL_GPL(put_mtd_device); 583EXPORT_SYMBOL_GPL(register_mtd_user); 584EXPORT_SYMBOL_GPL(unregister_mtd_user); 585EXPORT_SYMBOL_GPL(default_mtd_writev); 586 587#ifdef CONFIG_PROC_FS 588 589/*====================================================================*/ 590/* Support for /proc/mtd */ 591 592static struct proc_dir_entry *proc_mtd; 593 594static inline int mtd_proc_info(char *buf, struct mtd_info *this) 595{ 596 return sprintf(buf, "mtd%d: %8.8llx %8.8x \"%s\"\n", this->index, 597 (unsigned long long)this->size, 598 this->erasesize, this->name); 599} 600 601static int mtd_read_proc (char *page, char **start, off_t off, int count, 602 int *eof, void *data_unused) 603{ 604 struct mtd_info *mtd; 605 int len, l; 606 off_t begin = 0; 607 608 mutex_lock(&mtd_table_mutex); 609 610 len = sprintf(page, "dev: size erasesize name\n"); 611 mtd_for_each_device(mtd) { 612 l = mtd_proc_info(page + len, mtd); 613 len += l; 614 if (len+begin > off+count) 615 goto done; 616 if (len+begin < off) { 617 begin += len; 618 len = 0; 619 } 620 } 621 622 *eof = 1; 623 624done: 625 mutex_unlock(&mtd_table_mutex); 626 if (off >= len+begin) 627 return 0; 628 *start = page + (off-begin); 629 return ((count < begin+len-off) ? count : begin+len-off); 630} 631 632#endif /* CONFIG_PROC_FS */ 633 634/*====================================================================*/ 635/* Init code */ 636 637static int __init init_mtd(void) 638{ 639 int ret; 640 ret = class_register(&mtd_class); 641 642 if (ret) { 643 pr_err("Error registering mtd class: %d\n", ret); 644 return ret; 645 } 646#ifdef CONFIG_PROC_FS 647 if ((proc_mtd = create_proc_entry( "mtd", 0, NULL ))) 648 proc_mtd->read_proc = mtd_read_proc; 649#endif /* CONFIG_PROC_FS */ 650 return 0; 651} 652 653static void __exit cleanup_mtd(void) 654{ 655#ifdef CONFIG_PROC_FS 656 if (proc_mtd) 657 remove_proc_entry( "mtd", NULL); 658#endif /* CONFIG_PROC_FS */ 659 class_unregister(&mtd_class); 660} 661 662module_init(init_mtd); 663module_exit(cleanup_mtd); 664 665MODULE_LICENSE("GPL"); 666MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>"); 667MODULE_DESCRIPTION("Core MTD registration and access routines"); 668