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