aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd/mtdpart.c
diff options
context:
space:
mode:
authorRoman Tereshonkov <roman.tereshonkov@nokia.com>2010-09-17 06:31:41 -0400
committerDavid Woodhouse <David.Woodhouse@intel.com>2010-10-24 19:47:37 -0400
commit5daa7b21496aebf057c12be03038e7220e33353b (patch)
tree7ec8f8a086dcfdcb7aec800bf528d3704bcaadc8 /drivers/mtd/mtdpart.c
parent93ac5a552c831096003f9bc74471300dc1710a42 (diff)
mtd: prepare partition add and del functions for ioctl requests
mtd_is_master, mtd_add_partition and mtd_del_partition functions are added to give the possibility of partition manipulation by ioctl request. The old partition add function is modified to fit the dynamic allocation. Signed-off-by: Roman Tereshonkov <roman.tereshonkov@nokia.com> Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com> Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
Diffstat (limited to 'drivers/mtd/mtdpart.c')
-rw-r--r--drivers/mtd/mtdpart.c154
1 files changed, 136 insertions, 18 deletions
diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c
index dc6558568876..79e3689f1e16 100644
--- a/drivers/mtd/mtdpart.c
+++ b/drivers/mtd/mtdpart.c
@@ -29,9 +29,11 @@
29#include <linux/kmod.h> 29#include <linux/kmod.h>
30#include <linux/mtd/mtd.h> 30#include <linux/mtd/mtd.h>
31#include <linux/mtd/partitions.h> 31#include <linux/mtd/partitions.h>
32#include <linux/err.h>
32 33
33/* Our partition linked list */ 34/* Our partition linked list */
34static LIST_HEAD(mtd_partitions); 35static LIST_HEAD(mtd_partitions);
36static DEFINE_MUTEX(mtd_partitions_mutex);
35 37
36/* Our partition node structure */ 38/* Our partition node structure */
37struct mtd_part { 39struct mtd_part {
@@ -326,6 +328,12 @@ static int part_block_markbad(struct mtd_info *mtd, loff_t ofs)
326 return res; 328 return res;
327} 329}
328 330
331static inline void free_partition(struct mtd_part *p)
332{
333 kfree(p->mtd.name);
334 kfree(p);
335}
336
329/* 337/*
330 * This function unregisters and destroy all slave MTD objects which are 338 * This function unregisters and destroy all slave MTD objects which are
331 * attached to the given master MTD object. 339 * attached to the given master MTD object.
@@ -334,33 +342,42 @@ static int part_block_markbad(struct mtd_info *mtd, loff_t ofs)
334int del_mtd_partitions(struct mtd_info *master) 342int del_mtd_partitions(struct mtd_info *master)
335{ 343{
336 struct mtd_part *slave, *next; 344 struct mtd_part *slave, *next;
345 int ret, err = 0;
337 346
347 mutex_lock(&mtd_partitions_mutex);
338 list_for_each_entry_safe(slave, next, &mtd_partitions, list) 348 list_for_each_entry_safe(slave, next, &mtd_partitions, list)
339 if (slave->master == master) { 349 if (slave->master == master) {
350 ret = del_mtd_device(&slave->mtd);
351 if (ret < 0) {
352 err = ret;
353 continue;
354 }
340 list_del(&slave->list); 355 list_del(&slave->list);
341 del_mtd_device(&slave->mtd); 356 free_partition(slave);
342 kfree(slave);
343 } 357 }
358 mutex_unlock(&mtd_partitions_mutex);
344 359
345 return 0; 360 return err;
346} 361}
347EXPORT_SYMBOL(del_mtd_partitions); 362EXPORT_SYMBOL(del_mtd_partitions);
348 363
349static struct mtd_part *add_one_partition(struct mtd_info *master, 364static struct mtd_part *allocate_partition(struct mtd_info *master,
350 const struct mtd_partition *part, int partno, 365 const struct mtd_partition *part, int partno,
351 uint64_t cur_offset) 366 uint64_t cur_offset)
352{ 367{
353 struct mtd_part *slave; 368 struct mtd_part *slave;
369 char *name;
354 370
355 /* allocate the partition structure */ 371 /* allocate the partition structure */
356 slave = kzalloc(sizeof(*slave), GFP_KERNEL); 372 slave = kzalloc(sizeof(*slave), GFP_KERNEL);
357 if (!slave) { 373 name = kstrdup(part->name, GFP_KERNEL);
374 if (!name || !slave) {
358 printk(KERN_ERR"memory allocation error while creating partitions for \"%s\"\n", 375 printk(KERN_ERR"memory allocation error while creating partitions for \"%s\"\n",
359 master->name); 376 master->name);
360 del_mtd_partitions(master); 377 kfree(name);
361 return NULL; 378 kfree(slave);
379 return ERR_PTR(-ENOMEM);
362 } 380 }
363 list_add(&slave->list, &mtd_partitions);
364 381
365 /* set up the MTD object for this partition */ 382 /* set up the MTD object for this partition */
366 slave->mtd.type = master->type; 383 slave->mtd.type = master->type;
@@ -371,7 +388,7 @@ static struct mtd_part *add_one_partition(struct mtd_info *master,
371 slave->mtd.oobavail = master->oobavail; 388 slave->mtd.oobavail = master->oobavail;
372 slave->mtd.subpage_sft = master->subpage_sft; 389 slave->mtd.subpage_sft = master->subpage_sft;
373 390
374 slave->mtd.name = part->name; 391 slave->mtd.name = name;
375 slave->mtd.owner = master->owner; 392 slave->mtd.owner = master->owner;
376 slave->mtd.backing_dev_info = master->backing_dev_info; 393 slave->mtd.backing_dev_info = master->backing_dev_info;
377 394
@@ -518,12 +535,89 @@ static struct mtd_part *add_one_partition(struct mtd_info *master,
518 } 535 }
519 536
520out_register: 537out_register:
521 /* register our partition */
522 add_mtd_device(&slave->mtd);
523
524 return slave; 538 return slave;
525} 539}
526 540
541int mtd_add_partition(struct mtd_info *master, char *name,
542 long long offset, long long length)
543{
544 struct mtd_partition part;
545 struct mtd_part *p, *new;
546 uint64_t start, end;
547 int ret = 0;
548
549 /* the direct offset is expected */
550 if (offset == MTDPART_OFS_APPEND ||
551 offset == MTDPART_OFS_NXTBLK)
552 return -EINVAL;
553
554 if (length == MTDPART_SIZ_FULL)
555 length = master->size - offset;
556
557 if (length <= 0)
558 return -EINVAL;
559
560 part.name = name;
561 part.size = length;
562 part.offset = offset;
563 part.mask_flags = 0;
564 part.ecclayout = NULL;
565
566 new = allocate_partition(master, &part, -1, offset);
567 if (IS_ERR(new))
568 return PTR_ERR(new);
569
570 start = offset;
571 end = offset + length;
572
573 mutex_lock(&mtd_partitions_mutex);
574 list_for_each_entry(p, &mtd_partitions, list)
575 if (p->master == master) {
576 if ((start >= p->offset) &&
577 (start < (p->offset + p->mtd.size)))
578 goto err_inv;
579
580 if ((end >= p->offset) &&
581 (end < (p->offset + p->mtd.size)))
582 goto err_inv;
583 }
584
585 list_add(&new->list, &mtd_partitions);
586 mutex_unlock(&mtd_partitions_mutex);
587
588 add_mtd_device(&new->mtd);
589
590 return ret;
591err_inv:
592 mutex_unlock(&mtd_partitions_mutex);
593 free_partition(new);
594 return -EINVAL;
595}
596EXPORT_SYMBOL_GPL(mtd_add_partition);
597
598int mtd_del_partition(struct mtd_info *master, int partno)
599{
600 struct mtd_part *slave, *next;
601 int ret = -EINVAL;
602
603 mutex_lock(&mtd_partitions_mutex);
604 list_for_each_entry_safe(slave, next, &mtd_partitions, list)
605 if ((slave->master == master) &&
606 (slave->mtd.index == partno)) {
607 ret = del_mtd_device(&slave->mtd);
608 if (ret < 0)
609 break;
610
611 list_del(&slave->list);
612 free_partition(slave);
613 break;
614 }
615 mutex_unlock(&mtd_partitions_mutex);
616
617 return ret;
618}
619EXPORT_SYMBOL_GPL(mtd_del_partition);
620
527/* 621/*
528 * This function, given a master MTD object and a partition table, creates 622 * This function, given a master MTD object and a partition table, creates
529 * and registers slave MTD objects which are bound to the master according to 623 * and registers slave MTD objects which are bound to the master according to
@@ -544,9 +638,16 @@ int add_mtd_partitions(struct mtd_info *master,
544 printk(KERN_NOTICE "Creating %d MTD partitions on \"%s\":\n", nbparts, master->name); 638 printk(KERN_NOTICE "Creating %d MTD partitions on \"%s\":\n", nbparts, master->name);
545 639
546 for (i = 0; i < nbparts; i++) { 640 for (i = 0; i < nbparts; i++) {
547 slave = add_one_partition(master, parts + i, i, cur_offset); 641 slave = allocate_partition(master, parts + i, i, cur_offset);
548 if (!slave) 642 if (IS_ERR(slave))
549 return -ENOMEM; 643 return PTR_ERR(slave);
644
645 mutex_lock(&mtd_partitions_mutex);
646 list_add(&slave->list, &mtd_partitions);
647 mutex_unlock(&mtd_partitions_mutex);
648
649 add_mtd_device(&slave->mtd);
650
550 cur_offset = slave->offset + slave->mtd.size; 651 cur_offset = slave->offset + slave->mtd.size;
551 } 652 }
552 653
@@ -618,3 +719,20 @@ int parse_mtd_partitions(struct mtd_info *master, const char **types,
618 return ret; 719 return ret;
619} 720}
620EXPORT_SYMBOL_GPL(parse_mtd_partitions); 721EXPORT_SYMBOL_GPL(parse_mtd_partitions);
722
723int mtd_is_master(struct mtd_info *mtd)
724{
725 struct mtd_part *part;
726 int nopart = 0;
727
728 mutex_lock(&mtd_partitions_mutex);
729 list_for_each_entry(part, &mtd_partitions, list)
730 if (&part->mtd == mtd) {
731 nopart = 1;
732 break;
733 }
734 mutex_unlock(&mtd_partitions_mutex);
735
736 return nopart;
737}
738EXPORT_SYMBOL_GPL(mtd_is_master);