aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArtem Bityutskiy <Artem.Bityutskiy@nokia.com>2007-12-17 13:33:20 -0500
committerArtem Bityutskiy <Artem.Bityutskiy@nokia.com>2007-12-26 12:15:17 -0500
commitcdfa788acd134a35d3e5b73d1a76fca4033d8aa9 (patch)
treeccc8cbf0bad80f569d9e3bbdc7cbf9c97556f155
parente73f4459d969bb266f03dd4cbe21bdba8cb2732c (diff)
UBI: prepare attach and detach functions
Prepare the attach and detach functions to by used outside of module initialization: * detach function checks reference count before detaching * it kills the background thread as well Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
-rw-r--r--drivers/mtd/ubi/build.c235
-rw-r--r--drivers/mtd/ubi/ubi.h5
-rw-r--r--drivers/mtd/ubi/wl.c16
3 files changed, 169 insertions, 87 deletions
diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c
index a4faf71ee3f2..071454376643 100644
--- a/drivers/mtd/ubi/build.c
+++ b/drivers/mtd/ubi/build.c
@@ -40,6 +40,7 @@
40#include <linux/stat.h> 40#include <linux/stat.h>
41#include <linux/miscdevice.h> 41#include <linux/miscdevice.h>
42#include <linux/log2.h> 42#include <linux/log2.h>
43#include <linux/kthread.h>
43#include "ubi.h" 44#include "ubi.h"
44 45
45/* Maximum length of the 'mtd=' parameter */ 46/* Maximum length of the 'mtd=' parameter */
@@ -83,6 +84,9 @@ static struct miscdevice ubi_ctrl_cdev = {
83/* All UBI devices in system */ 84/* All UBI devices in system */
84static struct ubi_device *ubi_devices[UBI_MAX_DEVICES]; 85static struct ubi_device *ubi_devices[UBI_MAX_DEVICES];
85 86
87/* Serializes UBI devices creations and removals */
88DEFINE_MUTEX(ubi_devices_mutex);
89
86/* Protects @ubi_devices and @ubi->ref_count */ 90/* Protects @ubi_devices and @ubi->ref_count */
87static DEFINE_SPINLOCK(ubi_devices_lock); 91static DEFINE_SPINLOCK(ubi_devices_lock);
88 92
@@ -192,7 +196,7 @@ struct ubi_device *ubi_get_by_major(int major)
192 * @major: major number 196 * @major: major number
193 * 197 *
194 * This function searches UBI device number object by its major number. If UBI 198 * This function searches UBI device number object by its major number. If UBI
195 * device was not found, this function returns -ENODEV, othewise the UBI device 199 * device was not found, this function returns -ENODEV, otherwise the UBI device
196 * number is returned. 200 * number is returned.
197 */ 201 */
198int ubi_major2num(int major) 202int ubi_major2num(int major)
@@ -485,9 +489,9 @@ out_si:
485 * assumed: 489 * assumed:
486 * o EC header is always at offset zero - this cannot be changed; 490 * o EC header is always at offset zero - this cannot be changed;
487 * o VID header starts just after the EC header at the closest address 491 * o VID header starts just after the EC header at the closest address
488 * aligned to @io->@hdrs_min_io_size; 492 * aligned to @io->hdrs_min_io_size;
489 * o data starts just after the VID header at the closest address aligned to 493 * o data starts just after the VID header at the closest address aligned to
490 * @io->@min_io_size 494 * @io->min_io_size
491 * 495 *
492 * This function returns zero in case of success and a negative error code in 496 * This function returns zero in case of success and a negative error code in
493 * case of failure. 497 * case of failure.
@@ -508,6 +512,9 @@ static int io_init(struct ubi_device *ubi)
508 return -EINVAL; 512 return -EINVAL;
509 } 513 }
510 514
515 if (ubi->vid_hdr_offset < 0 || ubi->leb_start < ubi->vid_hdr_offset)
516 return -EINVAL;
517
511 /* 518 /*
512 * Note, in this implementation we support MTD devices with 0x7FFFFFFF 519 * Note, in this implementation we support MTD devices with 0x7FFFFFFF
513 * physical eraseblocks maximum. 520 * physical eraseblocks maximum.
@@ -616,84 +623,62 @@ static int io_init(struct ubi_device *ubi)
616} 623}
617 624
618/** 625/**
619 * attach_mtd_dev - attach an MTD device. 626 * ubi_attach_mtd_dev - attach an MTD device.
620 * @mtd_dev: MTD device name or number string 627 * @mtd_dev: MTD device description object
621 * @vid_hdr_offset: VID header offset 628 * @vid_hdr_offset: VID header offset
622 * @data_offset: data offset 629 * @data_offset: data offset
623 * 630 *
624 * This function attaches an MTD device to UBI. It first treats @mtd_dev as the 631 * This function attaches an MTD device to UBI. It first treats @mtd_dev as the
625 * MTD device name, and tries to open it by this name. If it is unable to open, 632 * MTD device name, and tries to open it by this name. If it is unable to open,
626 * it tries to convert @mtd_dev to an integer and open the MTD device by its 633 * it tries to convert @mtd_dev to an integer and open the MTD device by its
627 * number. Returns zero in case of success and a negative error code in case of 634 * number. Returns new UBI device's number in case of success and a negative
628 * failure. 635 * error code in case of failure.
636 *
637 * Note, the invocations of this function has to be serialized by the
638 * @ubi_devices_mutex.
629 */ 639 */
630static int attach_mtd_dev(const char *mtd_dev, int vid_hdr_offset, 640int ubi_attach_mtd_dev(struct mtd_info *mtd, int vid_hdr_offset,
631 int data_offset) 641 int data_offset)
632{ 642{
633 struct ubi_device *ubi; 643 struct ubi_device *ubi;
634 struct mtd_info *mtd;
635 int i, err; 644 int i, err;
636 645
637 mtd = get_mtd_device_nm(mtd_dev); 646 /*
638 if (IS_ERR(mtd)) { 647 * Check if we already have the same MTD device attached.
639 int mtd_num; 648 *
640 char *endp; 649 * Note, this function assumes that UBI devices creations and deletions
641 650 * are serialized, so it does not take the &ubi_devices_lock.
642 if (PTR_ERR(mtd) != -ENODEV) 651 */
643 return PTR_ERR(mtd);
644
645 /*
646 * Probably this is not MTD device name but MTD device number -
647 * check this out.
648 */
649 mtd_num = simple_strtoul(mtd_dev, &endp, 0);
650 if (*endp != '\0' || mtd_dev == endp) {
651 ubi_err("incorrect MTD device: \"%s\"", mtd_dev);
652 return -ENODEV;
653 }
654
655 mtd = get_mtd_device(NULL, mtd_num);
656 if (IS_ERR(mtd))
657 return PTR_ERR(mtd);
658 }
659
660 /* Check if we already have the same MTD device attached */
661 for (i = 0; i < UBI_MAX_DEVICES; i++) 652 for (i = 0; i < UBI_MAX_DEVICES; i++)
662 ubi = ubi_devices[i]; 653 ubi = ubi_devices[i];
663 if (ubi && ubi->mtd->index == mtd->index) { 654 if (ubi && mtd->index == ubi->mtd->index) {
664 ubi_err("mtd%d is already attached to ubi%d", 655 ubi_err("mtd%d is already attached to ubi%d",
665 mtd->index, i); 656 mtd->index, i);
666 err = -EINVAL; 657 return -EINVAL;
667 goto out_mtd;
668 } 658 }
669 659
670 ubi = kzalloc(sizeof(struct ubi_device), GFP_KERNEL);
671 if (!ubi) {
672 err = -ENOMEM;
673 goto out_mtd;
674 }
675
676 ubi->mtd = mtd;
677
678 /* Search for an empty slot in the @ubi_devices array */ 660 /* Search for an empty slot in the @ubi_devices array */
679 ubi->ubi_num = -1;
680 for (i = 0; i < UBI_MAX_DEVICES; i++) 661 for (i = 0; i < UBI_MAX_DEVICES; i++)
681 if (!ubi_devices[i]) { 662 if (!ubi_devices[i])
682 ubi->ubi_num = i;
683 break; 663 break;
684 }
685 664
686 if (ubi->ubi_num == -1) { 665 if (i == UBI_MAX_DEVICES) {
687 ubi_err("only %d UBI devices may be created", UBI_MAX_DEVICES); 666 ubi_err("only %d UBI devices may be created", UBI_MAX_DEVICES);
688 err = -ENFILE; 667 return -ENFILE;
689 goto out_free;
690 } 668 }
691 669
692 dbg_msg("attaching mtd%d to ubi%d: VID header offset %d data offset %d", 670 ubi = kzalloc(sizeof(struct ubi_device), GFP_KERNEL);
693 ubi->mtd->index, ubi->ubi_num, vid_hdr_offset, data_offset); 671 if (!ubi)
672 return -ENOMEM;
694 673
674 ubi->mtd = mtd;
675 ubi->ubi_num = i;
695 ubi->vid_hdr_offset = vid_hdr_offset; 676 ubi->vid_hdr_offset = vid_hdr_offset;
696 ubi->leb_start = data_offset; 677 ubi->leb_start = data_offset;
678
679 dbg_msg("attaching mtd%d to ubi%d: VID header offset %d data offset %d",
680 mtd->index, ubi->ubi_num, vid_hdr_offset, data_offset);
681
697 err = io_init(ubi); 682 err = io_init(ubi);
698 if (err) 683 if (err)
699 goto out_free; 684 goto out_free;
@@ -724,8 +709,16 @@ static int attach_mtd_dev(const char *mtd_dev, int vid_hdr_offset,
724 if (err) 709 if (err)
725 goto out_detach; 710 goto out_detach;
726 711
727 ubi_msg("attached mtd%d to ubi%d", ubi->mtd->index, ubi->ubi_num); 712 ubi->bgt_thread = kthread_create(ubi_thread, ubi, ubi->bgt_name);
728 ubi_msg("MTD device name: \"%s\"", ubi->mtd->name); 713 if (IS_ERR(ubi->bgt_thread)) {
714 err = PTR_ERR(ubi->bgt_thread);
715 ubi_err("cannot spawn \"%s\", error %d", ubi->bgt_name,
716 err);
717 goto out_uif;
718 }
719
720 ubi_msg("attached mtd%d to ubi%d", mtd->index, ubi->ubi_num);
721 ubi_msg("MTD device name: \"%s\"", mtd->name);
729 ubi_msg("MTD device size: %llu MiB", ubi->flash_size >> 20); 722 ubi_msg("MTD device size: %llu MiB", ubi->flash_size >> 20);
730 ubi_msg("physical eraseblock size: %d bytes (%d KiB)", 723 ubi_msg("physical eraseblock size: %d bytes (%d KiB)",
731 ubi->peb_size, ubi->peb_size >> 10); 724 ubi->peb_size, ubi->peb_size >> 10);
@@ -754,8 +747,10 @@ static int attach_mtd_dev(const char *mtd_dev, int vid_hdr_offset,
754 } 747 }
755 748
756 ubi_devices[ubi->ubi_num] = ubi; 749 ubi_devices[ubi->ubi_num] = ubi;
757 return 0; 750 return ubi->ubi_num;
758 751
752out_uif:
753 uif_close(ubi);
759out_detach: 754out_detach:
760 ubi_eba_close(ubi); 755 ubi_eba_close(ubi);
761 ubi_wl_close(ubi); 756 ubi_wl_close(ubi);
@@ -767,21 +762,57 @@ out_free:
767 vfree(ubi->dbg_peb_buf); 762 vfree(ubi->dbg_peb_buf);
768#endif 763#endif
769 kfree(ubi); 764 kfree(ubi);
770out_mtd:
771 put_mtd_device(mtd);
772 return err; 765 return err;
773} 766}
774 767
775/** 768/**
776 * detach_mtd_dev - detach an MTD device. 769 * ubi_detach_mtd_dev - detach an MTD device.
777 * @ubi: UBI device description object 770 * @ubi_num: UBI device number to detach from
771 * @anyway: detach MTD even if device reference count is not zero
772 *
773 * This function destroys an UBI device number @ubi_num and detaches the
774 * underlying MTD device. Returns zero in case of success and %-EBUSY if the
775 * UBI device is busy and cannot be destroyed, and %-EINVAL if it does not
776 * exist.
777 *
778 * Note, the invocations of this function has to be serialized by the
779 * @ubi_devices_mutex.
778 */ 780 */
779static void detach_mtd_dev(struct ubi_device *ubi) 781int ubi_detach_mtd_dev(int ubi_num, int anyway)
780{ 782{
781 int ubi_num = ubi->ubi_num, mtd_num = ubi->mtd->index; 783 struct ubi_device *ubi;
784
785 if (ubi_num < 0 || ubi_num >= UBI_MAX_DEVICES)
786 return -EINVAL;
787
788 spin_lock(&ubi_devices_lock);
789 ubi = ubi_devices[ubi_num];
790 if (!ubi) {
791 spin_lock(&ubi_devices_lock);
792 return -EINVAL;
793 }
794
795 if (ubi->ref_count) {
796 if (!anyway) {
797 spin_lock(&ubi_devices_lock);
798 return -EBUSY;
799 }
800 /* This may only happen if there is a bug */
801 ubi_err("%s reference count %d, destroy anyway",
802 ubi->ubi_name, ubi->ref_count);
803 }
804 ubi_devices[ubi->ubi_num] = NULL;
805 spin_unlock(&ubi_devices_lock);
806
807 dbg_msg("detaching mtd%d from ubi%d", ubi->mtd->index, ubi->ubi_num);
808
809 /*
810 * Before freeing anything, we have to stop the background thread to
811 * prevent it from doing anything on this device while we are freeing.
812 */
813 if (ubi->bgt_thread)
814 kthread_stop(ubi->bgt_thread);
782 815
783 dbg_msg("detaching mtd%d from ubi%d", ubi->mtd->index, ubi_num);
784 ubi_assert(ubi->ref_count == 0);
785 uif_close(ubi); 816 uif_close(ubi);
786 ubi_eba_close(ubi); 817 ubi_eba_close(ubi);
787 ubi_wl_close(ubi); 818 ubi_wl_close(ubi);
@@ -792,9 +823,9 @@ static void detach_mtd_dev(struct ubi_device *ubi)
792#ifdef CONFIG_MTD_UBI_DEBUG 823#ifdef CONFIG_MTD_UBI_DEBUG
793 vfree(ubi->dbg_peb_buf); 824 vfree(ubi->dbg_peb_buf);
794#endif 825#endif
795 kfree(ubi_devices[ubi_num]); 826 ubi_msg("mtd%d is detached from ubi%d", ubi->mtd->index, ubi->ubi_num);
796 ubi_devices[ubi_num] = NULL; 827 kfree(ubi);
797 ubi_msg("mtd%d is detached from ubi%d", mtd_num, ubi_num); 828 return 0;
798} 829}
799 830
800/** 831/**
@@ -811,6 +842,46 @@ static void ltree_entry_ctor(struct kmem_cache *cache, void *obj)
811 init_rwsem(&le->mutex); 842 init_rwsem(&le->mutex);
812} 843}
813 844
845/**
846 * find_mtd_device - open an MTD device by its name or number.
847 * @mtd_dev: name or number of the device
848 *
849 * This function tries to open and MTD device with name @mtd_dev, and if it
850 * fails, then it tries to interpret the @mtd_dev string as an ASCII-coded
851 * integer and open an MTD device with this number. Returns MTD device
852 * description object in case of success and a negative error code in case of
853 * failure.
854 */
855static struct mtd_info * __init open_mtd_device(const char *mtd_dev)
856{
857 struct mtd_info *mtd;
858
859 mtd = get_mtd_device_nm(mtd_dev);
860 if (IS_ERR(mtd)) {
861 int mtd_num;
862 char *endp;
863
864 if (PTR_ERR(mtd) != -ENODEV)
865 return mtd;
866
867 /*
868 * Probably this is not MTD device name but MTD device number -
869 * check this out.
870 */
871 mtd_num = simple_strtoul(mtd_dev, &endp, 0);
872 if (*endp != '\0' || mtd_dev == endp) {
873 ubi_err("incorrect MTD device: \"%s\"", mtd_dev);
874 return ERR_PTR(-ENODEV);
875 }
876
877 mtd = get_mtd_device(NULL, mtd_num);
878 if (IS_ERR(mtd))
879 return mtd;
880 }
881
882 return mtd;
883}
884
814static int __init ubi_init(void) 885static int __init ubi_init(void)
815{ 886{
816 int err, i, k; 887 int err, i, k;
@@ -860,10 +931,21 @@ static int __init ubi_init(void)
860 /* Attach MTD devices */ 931 /* Attach MTD devices */
861 for (i = 0; i < mtd_devs; i++) { 932 for (i = 0; i < mtd_devs; i++) {
862 struct mtd_dev_param *p = &mtd_dev_param[i]; 933 struct mtd_dev_param *p = &mtd_dev_param[i];
934 struct mtd_info *mtd;
863 935
864 cond_resched(); 936 cond_resched();
865 err = attach_mtd_dev(p->name, p->vid_hdr_offs, p->data_offs); 937
866 if (err) { 938 mtd = open_mtd_device(p->name);
939 if (IS_ERR(mtd)) {
940 err = PTR_ERR(mtd);
941 goto out_detach;
942 }
943
944 mutex_lock(&ubi_devices_mutex);
945 err = ubi_attach_mtd_dev(mtd, p->vid_hdr_offs, p->data_offs);
946 mutex_unlock(&ubi_devices_mutex);
947 if (err < 0) {
948 put_mtd_device(mtd);
867 printk(KERN_ERR "UBI error: cannot attach %s\n", 949 printk(KERN_ERR "UBI error: cannot attach %s\n",
868 p->name); 950 p->name);
869 goto out_detach; 951 goto out_detach;
@@ -874,7 +956,11 @@ static int __init ubi_init(void)
874 956
875out_detach: 957out_detach:
876 for (k = 0; k < i; k++) 958 for (k = 0; k < i; k++)
877 detach_mtd_dev(ubi_devices[k]); 959 if (ubi_devices[k]) {
960 mutex_lock(&ubi_devices_mutex);
961 ubi_detach_mtd_dev(ubi_devices[k]->ubi_num, 1);
962 mutex_unlock(&ubi_devices_mutex);
963 }
878 kmem_cache_destroy(ubi_wl_entry_slab); 964 kmem_cache_destroy(ubi_wl_entry_slab);
879out_ltree: 965out_ltree:
880 kmem_cache_destroy(ubi_ltree_slab); 966 kmem_cache_destroy(ubi_ltree_slab);
@@ -895,8 +981,11 @@ static void __exit ubi_exit(void)
895 int i; 981 int i;
896 982
897 for (i = 0; i < UBI_MAX_DEVICES; i++) 983 for (i = 0; i < UBI_MAX_DEVICES; i++)
898 if (ubi_devices[i]) 984 if (ubi_devices[i]) {
899 detach_mtd_dev(ubi_devices[i]); 985 mutex_lock(&ubi_devices_mutex);
986 ubi_detach_mtd_dev(ubi_devices[i]->ubi_num, 1);
987 mutex_unlock(&ubi_devices_mutex);
988 }
900 kmem_cache_destroy(ubi_wl_entry_slab); 989 kmem_cache_destroy(ubi_wl_entry_slab);
901 kmem_cache_destroy(ubi_ltree_slab); 990 kmem_cache_destroy(ubi_ltree_slab);
902 misc_deregister(&ubi_ctrl_cdev); 991 misc_deregister(&ubi_ctrl_cdev);
diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h
index 91fde0e8ff58..25ff15a7fc58 100644
--- a/drivers/mtd/ubi/ubi.h
+++ b/drivers/mtd/ubi/ubi.h
@@ -404,6 +404,7 @@ extern struct file_operations ubi_ctrl_cdev_operations;
404extern struct file_operations ubi_cdev_operations; 404extern struct file_operations ubi_cdev_operations;
405extern struct file_operations ubi_vol_cdev_operations; 405extern struct file_operations ubi_vol_cdev_operations;
406extern struct class *ubi_class; 406extern struct class *ubi_class;
407extern struct mutex ubi_devices_mutex;
407 408
408/* vtbl.c */ 409/* vtbl.c */
409int ubi_change_vtbl_record(struct ubi_device *ubi, int idx, 410int ubi_change_vtbl_record(struct ubi_device *ubi, int idx,
@@ -462,6 +463,7 @@ int ubi_wl_flush(struct ubi_device *ubi);
462int ubi_wl_scrub_peb(struct ubi_device *ubi, int pnum); 463int ubi_wl_scrub_peb(struct ubi_device *ubi, int pnum);
463int ubi_wl_init_scan(struct ubi_device *ubi, struct ubi_scan_info *si); 464int ubi_wl_init_scan(struct ubi_device *ubi, struct ubi_scan_info *si);
464void ubi_wl_close(struct ubi_device *ubi); 465void ubi_wl_close(struct ubi_device *ubi);
466int ubi_thread(void *u);
465 467
466/* io.c */ 468/* io.c */
467int ubi_io_read(const struct ubi_device *ubi, void *buf, int pnum, int offset, 469int ubi_io_read(const struct ubi_device *ubi, void *buf, int pnum, int offset,
@@ -481,6 +483,9 @@ int ubi_io_write_vid_hdr(struct ubi_device *ubi, int pnum,
481 struct ubi_vid_hdr *vid_hdr); 483 struct ubi_vid_hdr *vid_hdr);
482 484
483/* build.c */ 485/* build.c */
486int ubi_attach_mtd_dev(struct mtd_info *mtd, int vid_hdr_offset,
487 int data_offset);
488int ubi_detach_mtd_dev(int ubi_num, int anyway);
484struct ubi_device *ubi_get_device(int ubi_num); 489struct ubi_device *ubi_get_device(int ubi_num);
485void ubi_put_device(struct ubi_device *ubi); 490void ubi_put_device(struct ubi_device *ubi);
486struct ubi_device *ubi_get_by_major(int major); 491struct ubi_device *ubi_get_by_major(int major);
diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c
index bfc64c824165..1142aabcfc8c 100644
--- a/drivers/mtd/ubi/wl.c
+++ b/drivers/mtd/ubi/wl.c
@@ -1356,7 +1356,7 @@ static void tree_destroy(struct rb_root *root)
1356 * ubi_thread - UBI background thread. 1356 * ubi_thread - UBI background thread.
1357 * @u: the UBI device description object pointer 1357 * @u: the UBI device description object pointer
1358 */ 1358 */
1359static int ubi_thread(void *u) 1359int ubi_thread(void *u)
1360{ 1360{
1361 int failures = 0; 1361 int failures = 0;
1362 struct ubi_device *ubi = u; 1362 struct ubi_device *ubi = u;
@@ -1454,18 +1454,10 @@ int ubi_wl_init_scan(struct ubi_device *ubi, struct ubi_scan_info *si)
1454 1454
1455 sprintf(ubi->bgt_name, UBI_BGT_NAME_PATTERN, ubi->ubi_num); 1455 sprintf(ubi->bgt_name, UBI_BGT_NAME_PATTERN, ubi->ubi_num);
1456 1456
1457 ubi->bgt_thread = kthread_create(ubi_thread, ubi, ubi->bgt_name);
1458 if (IS_ERR(ubi->bgt_thread)) {
1459 err = PTR_ERR(ubi->bgt_thread);
1460 ubi_err("cannot spawn \"%s\", error %d", ubi->bgt_name,
1461 err);
1462 return err;
1463 }
1464
1465 err = -ENOMEM; 1457 err = -ENOMEM;
1466 ubi->lookuptbl = kzalloc(ubi->peb_count * sizeof(void *), GFP_KERNEL); 1458 ubi->lookuptbl = kzalloc(ubi->peb_count * sizeof(void *), GFP_KERNEL);
1467 if (!ubi->lookuptbl) 1459 if (!ubi->lookuptbl)
1468 goto out_free; 1460 return err;
1469 1461
1470 list_for_each_entry_safe(seb, tmp, &si->erase, u.list) { 1462 list_for_each_entry_safe(seb, tmp, &si->erase, u.list) {
1471 cond_resched(); 1463 cond_resched();
@@ -1598,10 +1590,6 @@ static void protection_trees_destroy(struct ubi_device *ubi)
1598 */ 1590 */
1599void ubi_wl_close(struct ubi_device *ubi) 1591void ubi_wl_close(struct ubi_device *ubi)
1600{ 1592{
1601 dbg_wl("disable \"%s\"", ubi->bgt_name);
1602 if (ubi->bgt_thread)
1603 kthread_stop(ubi->bgt_thread);
1604
1605 dbg_wl("close the UBI wear-leveling unit"); 1593 dbg_wl("close the UBI wear-leveling unit");
1606 1594
1607 cancel_pending(ubi); 1595 cancel_pending(ubi);