aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mtd')
-rw-r--r--drivers/mtd/ubi/build.c100
-rw-r--r--drivers/mtd/ubi/cdev.c1
-rw-r--r--drivers/mtd/ubi/kapi.c108
-rw-r--r--drivers/mtd/ubi/ubi.h12
-rw-r--r--drivers/mtd/ubi/vmt.c4
5 files changed, 204 insertions, 21 deletions
diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c
index d3da66682667..964a99d48bc4 100644
--- a/drivers/mtd/ubi/build.c
+++ b/drivers/mtd/ubi/build.c
@@ -122,6 +122,94 @@ static struct device_attribute dev_mtd_num =
122 __ATTR(mtd_num, S_IRUGO, dev_attribute_show, NULL); 122 __ATTR(mtd_num, S_IRUGO, dev_attribute_show, NULL);
123 123
124/** 124/**
125 * ubi_volume_notify - send a volume change notification.
126 * @ubi: UBI device description object
127 * @vol: volume description object of the changed volume
128 * @ntype: notification type to send (%UBI_VOLUME_ADDED, etc)
129 *
130 * This is a helper function which notifies all subscribers about a volume
131 * change event (creation, removal, re-sizing, re-naming, updating). Returns
132 * zero in case of success and a negative error code in case of failure.
133 */
134int ubi_volume_notify(struct ubi_device *ubi, struct ubi_volume *vol, int ntype)
135{
136 struct ubi_notification nt;
137
138 ubi_do_get_device_info(ubi, &nt.di);
139 ubi_do_get_volume_info(ubi, vol, &nt.vi);
140 return blocking_notifier_call_chain(&ubi_notifiers, ntype, &nt);
141}
142
143/**
144 * ubi_notify_all - send a notification to all volumes.
145 * @ubi: UBI device description object
146 * @ntype: notification type to send (%UBI_VOLUME_ADDED, etc)
147 * @nb: the notifier to call
148 *
149 * This function walks all volumes of UBI device @ubi and sends the @ntype
150 * notification for each volume. If @nb is %NULL, then all registered notifiers
151 * are called, otherwise only the @nb notifier is called. Returns the number of
152 * sent notifications.
153 */
154int ubi_notify_all(struct ubi_device *ubi, int ntype, struct notifier_block *nb)
155{
156 struct ubi_notification nt;
157 int i, count = 0;
158
159 ubi_do_get_device_info(ubi, &nt.di);
160
161 mutex_lock(&ubi->device_mutex);
162 for (i = 0; i < ubi->vtbl_slots; i++) {
163 /*
164 * Since the @ubi->device is locked, and we are not going to
165 * change @ubi->volumes, we do not have to lock
166 * @ubi->volumes_lock.
167 */
168 if (!ubi->volumes[i])
169 continue;
170
171 ubi_do_get_volume_info(ubi, ubi->volumes[i], &nt.vi);
172 if (nb)
173 nb->notifier_call(nb, ntype, &nt);
174 else
175 blocking_notifier_call_chain(&ubi_notifiers, ntype,
176 &nt);
177 count += 1;
178 }
179 mutex_unlock(&ubi->device_mutex);
180
181 return count;
182}
183
184/**
185 * ubi_enumerate_volumes - send "add" notification for all existing volumes.
186 * @nb: the notifier to call
187 *
188 * This function walks all UBI devices and volumes and sends the
189 * %UBI_VOLUME_ADDED notification for each volume. If @nb is %NULL, then all
190 * registered notifiers are called, otherwise only the @nb notifier is called.
191 * Returns the number of sent notifications.
192 */
193int ubi_enumerate_volumes(struct notifier_block *nb)
194{
195 int i, count = 0;
196
197 /*
198 * Since the @ubi_devices_mutex is locked, and we are not going to
199 * change @ubi_devices, we do not have to lock @ubi_devices_lock.
200 */
201 for (i = 0; i < UBI_MAX_DEVICES; i++) {
202 struct ubi_device *ubi = ubi_devices[i];
203
204 if (!ubi)
205 continue;
206 count += ubi_notify_all(ubi, UBI_VOLUME_ADDED, nb);
207 }
208
209 return count;
210}
211
212/**
125 * ubi_get_device - get UBI device. 213 * ubi_get_device - get UBI device.
126 * @ubi_num: UBI device number 214 * @ubi_num: UBI device number
127 * 215 *
@@ -891,6 +979,7 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset)
891 spin_unlock(&ubi->wl_lock); 979 spin_unlock(&ubi->wl_lock);
892 980
893 ubi_devices[ubi_num] = ubi; 981 ubi_devices[ubi_num] = ubi;
982 ubi_notify_all(ubi, UBI_VOLUME_ADDED, NULL);
894 return ubi_num; 983 return ubi_num;
895 984
896out_uif: 985out_uif:
@@ -933,13 +1022,13 @@ int ubi_detach_mtd_dev(int ubi_num, int anyway)
933 if (ubi_num < 0 || ubi_num >= UBI_MAX_DEVICES) 1022 if (ubi_num < 0 || ubi_num >= UBI_MAX_DEVICES)
934 return -EINVAL; 1023 return -EINVAL;
935 1024
936 spin_lock(&ubi_devices_lock); 1025 ubi = ubi_get_device(ubi_num);
937 ubi = ubi_devices[ubi_num]; 1026 if (!ubi)
938 if (!ubi) {
939 spin_unlock(&ubi_devices_lock);
940 return -EINVAL; 1027 return -EINVAL;
941 }
942 1028
1029 spin_lock(&ubi_devices_lock);
1030 put_device(&ubi->dev);
1031 ubi->ref_count -= 1;
943 if (ubi->ref_count) { 1032 if (ubi->ref_count) {
944 if (!anyway) { 1033 if (!anyway) {
945 spin_unlock(&ubi_devices_lock); 1034 spin_unlock(&ubi_devices_lock);
@@ -953,6 +1042,7 @@ int ubi_detach_mtd_dev(int ubi_num, int anyway)
953 spin_unlock(&ubi_devices_lock); 1042 spin_unlock(&ubi_devices_lock);
954 1043
955 ubi_assert(ubi_num == ubi->ubi_num); 1044 ubi_assert(ubi_num == ubi->ubi_num);
1045 ubi_notify_all(ubi, UBI_VOLUME_REMOVED, NULL);
956 dbg_msg("detaching mtd%d from ubi%d", ubi->mtd->index, ubi_num); 1046 dbg_msg("detaching mtd%d from ubi%d", ubi->mtd->index, ubi_num);
957 1047
958 /* 1048 /*
diff --git a/drivers/mtd/ubi/cdev.c b/drivers/mtd/ubi/cdev.c
index 9a2b217941f7..631983615f11 100644
--- a/drivers/mtd/ubi/cdev.c
+++ b/drivers/mtd/ubi/cdev.c
@@ -396,6 +396,7 @@ static ssize_t vol_cdev_write(struct file *file, const char __user *buf,
396 } 396 }
397 vol->checked = 1; 397 vol->checked = 1;
398 ubi_gluebi_updated(vol); 398 ubi_gluebi_updated(vol);
399 ubi_volume_notify(ubi, vol, UBI_VOLUME_UPDATED);
399 revoke_exclusive(desc, UBI_READWRITE); 400 revoke_exclusive(desc, UBI_READWRITE);
400 } 401 }
401 402
diff --git a/drivers/mtd/ubi/kapi.c b/drivers/mtd/ubi/kapi.c
index 2675207c5fe3..88a72e9c8beb 100644
--- a/drivers/mtd/ubi/kapi.c
+++ b/drivers/mtd/ubi/kapi.c
@@ -26,6 +26,24 @@
26#include "ubi.h" 26#include "ubi.h"
27 27
28/** 28/**
29 * ubi_do_get_device_info - get information about UBI device.
30 * @ubi: UBI device description object
31 * @di: the information is stored here
32 *
33 * This function is the same as 'ubi_get_device_info()', but it assumes the UBI
34 * device is locked and cannot disappear.
35 */
36void ubi_do_get_device_info(struct ubi_device *ubi, struct ubi_device_info *di)
37{
38 di->ubi_num = ubi->ubi_num;
39 di->leb_size = ubi->leb_size;
40 di->min_io_size = ubi->min_io_size;
41 di->ro_mode = ubi->ro_mode;
42 di->cdev = ubi->cdev.dev;
43}
44EXPORT_SYMBOL_GPL(ubi_do_get_device_info);
45
46/**
29 * ubi_get_device_info - get information about UBI device. 47 * ubi_get_device_info - get information about UBI device.
30 * @ubi_num: UBI device number 48 * @ubi_num: UBI device number
31 * @di: the information is stored here 49 * @di: the information is stored here
@@ -39,33 +57,24 @@ int ubi_get_device_info(int ubi_num, struct ubi_device_info *di)
39 57
40 if (ubi_num < 0 || ubi_num >= UBI_MAX_DEVICES) 58 if (ubi_num < 0 || ubi_num >= UBI_MAX_DEVICES)
41 return -EINVAL; 59 return -EINVAL;
42
43 ubi = ubi_get_device(ubi_num); 60 ubi = ubi_get_device(ubi_num);
44 if (!ubi) 61 if (!ubi)
45 return -ENODEV; 62 return -ENODEV;
46 63 ubi_do_get_device_info(ubi, di);
47 di->ubi_num = ubi->ubi_num;
48 di->leb_size = ubi->leb_size;
49 di->min_io_size = ubi->min_io_size;
50 di->ro_mode = ubi->ro_mode;
51 di->cdev = ubi->cdev.dev;
52
53 ubi_put_device(ubi); 64 ubi_put_device(ubi);
54 return 0; 65 return 0;
55} 66}
56EXPORT_SYMBOL_GPL(ubi_get_device_info); 67EXPORT_SYMBOL_GPL(ubi_get_device_info);
57 68
58/** 69/**
59 * ubi_get_volume_info - get information about UBI volume. 70 * ubi_do_get_volume_info - get information about UBI volume.
60 * @desc: volume descriptor 71 * @ubi: UBI device description object
72 * @vol: volume description object
61 * @vi: the information is stored here 73 * @vi: the information is stored here
62 */ 74 */
63void ubi_get_volume_info(struct ubi_volume_desc *desc, 75void ubi_do_get_volume_info(struct ubi_device *ubi, struct ubi_volume *vol,
64 struct ubi_volume_info *vi) 76 struct ubi_volume_info *vi)
65{ 77{
66 const struct ubi_volume *vol = desc->vol;
67 const struct ubi_device *ubi = vol->ubi;
68
69 vi->vol_id = vol->vol_id; 78 vi->vol_id = vol->vol_id;
70 vi->ubi_num = ubi->ubi_num; 79 vi->ubi_num = ubi->ubi_num;
71 vi->size = vol->reserved_pebs; 80 vi->size = vol->reserved_pebs;
@@ -79,6 +88,17 @@ void ubi_get_volume_info(struct ubi_volume_desc *desc,
79 vi->name = vol->name; 88 vi->name = vol->name;
80 vi->cdev = vol->cdev.dev; 89 vi->cdev = vol->cdev.dev;
81} 90}
91
92/**
93 * ubi_get_volume_info - get information about UBI volume.
94 * @desc: volume descriptor
95 * @vi: the information is stored here
96 */
97void ubi_get_volume_info(struct ubi_volume_desc *desc,
98 struct ubi_volume_info *vi)
99{
100 ubi_do_get_volume_info(desc->vol->ubi, desc->vol, vi);
101}
82EXPORT_SYMBOL_GPL(ubi_get_volume_info); 102EXPORT_SYMBOL_GPL(ubi_get_volume_info);
83 103
84/** 104/**
@@ -561,7 +581,7 @@ int ubi_leb_unmap(struct ubi_volume_desc *desc, int lnum)
561EXPORT_SYMBOL_GPL(ubi_leb_unmap); 581EXPORT_SYMBOL_GPL(ubi_leb_unmap);
562 582
563/** 583/**
564 * ubi_leb_map - map logical erasblock to a physical eraseblock. 584 * ubi_leb_map - map logical eraseblock to a physical eraseblock.
565 * @desc: volume descriptor 585 * @desc: volume descriptor
566 * @lnum: logical eraseblock number 586 * @lnum: logical eraseblock number
567 * @dtype: expected data type 587 * @dtype: expected data type
@@ -659,3 +679,59 @@ int ubi_sync(int ubi_num)
659 return 0; 679 return 0;
660} 680}
661EXPORT_SYMBOL_GPL(ubi_sync); 681EXPORT_SYMBOL_GPL(ubi_sync);
682
683BLOCKING_NOTIFIER_HEAD(ubi_notifiers);
684
685/**
686 * ubi_register_volume_notifier - register a volume notifier.
687 * @nb: the notifier description object
688 * @ignore_existing: if non-zero, do not send "added" notification for all
689 * already existing volumes
690 *
691 * This function registers a volume notifier, which means that
692 * 'nb->notifier_call()' will be invoked when an UBI volume is created,
693 * removed, re-sized, re-named, or updated. The first argument of the function
694 * is the notification type. The second argument is pointer to a
695 * &struct ubi_notification object which describes the notification event.
696 * Using UBI API from the volume notifier is prohibited.
697 *
698 * This function returns zero in case of success and a negative error code
699 * in case of failure.
700 */
701int ubi_register_volume_notifier(struct notifier_block *nb,
702 int ignore_existing)
703{
704 int err;
705
706 err = blocking_notifier_chain_register(&ubi_notifiers, nb);
707 if (err != 0)
708 return err;
709 if (ignore_existing)
710 return 0;
711
712 /*
713 * We are going to walk all UBI devices and all volumes, and
714 * notify the user about existing volumes by the %UBI_VOLUME_ADDED
715 * event. We have to lock the @ubi_devices_mutex to make sure UBI
716 * devices do not disappear.
717 */
718 mutex_lock(&ubi_devices_mutex);
719 ubi_enumerate_volumes(nb);
720 mutex_unlock(&ubi_devices_mutex);
721
722 return err;
723}
724EXPORT_SYMBOL_GPL(ubi_register_volume_notifier);
725
726/**
727 * ubi_unregister_volume_notifier - unregister the volume notifier.
728 * @nb: the notifier description object
729 *
730 * This function unregisters volume notifier @nm and returns zero in case of
731 * success and a negative error code in case of failure.
732 */
733int ubi_unregister_volume_notifier(struct notifier_block *nb)
734{
735 return blocking_notifier_chain_unregister(&ubi_notifiers, nb);
736}
737EXPORT_SYMBOL_GPL(ubi_unregister_volume_notifier);
diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h
index 6d929329a8d5..86e1a4e0ab01 100644
--- a/drivers/mtd/ubi/ubi.h
+++ b/drivers/mtd/ubi/ubi.h
@@ -38,6 +38,7 @@
38#include <linux/vmalloc.h> 38#include <linux/vmalloc.h>
39#include <linux/mtd/mtd.h> 39#include <linux/mtd/mtd.h>
40#include <linux/mtd/ubi.h> 40#include <linux/mtd/ubi.h>
41#include <linux/notifier.h>
41 42
42#include "ubi-media.h" 43#include "ubi-media.h"
43#include "scan.h" 44#include "scan.h"
@@ -483,6 +484,7 @@ extern const struct file_operations ubi_cdev_operations;
483extern const struct file_operations ubi_vol_cdev_operations; 484extern const struct file_operations ubi_vol_cdev_operations;
484extern struct class *ubi_class; 485extern struct class *ubi_class;
485extern struct mutex ubi_devices_mutex; 486extern struct mutex ubi_devices_mutex;
487extern struct blocking_notifier_head ubi_notifiers;
486 488
487/* vtbl.c */ 489/* vtbl.c */
488int ubi_change_vtbl_record(struct ubi_device *ubi, int idx, 490int ubi_change_vtbl_record(struct ubi_device *ubi, int idx,
@@ -575,6 +577,16 @@ struct ubi_device *ubi_get_device(int ubi_num);
575void ubi_put_device(struct ubi_device *ubi); 577void ubi_put_device(struct ubi_device *ubi);
576struct ubi_device *ubi_get_by_major(int major); 578struct ubi_device *ubi_get_by_major(int major);
577int ubi_major2num(int major); 579int ubi_major2num(int major);
580int ubi_volume_notify(struct ubi_device *ubi, struct ubi_volume *vol,
581 int ntype);
582int ubi_notify_all(struct ubi_device *ubi, int ntype,
583 struct notifier_block *nb);
584int ubi_enumerate_volumes(struct notifier_block *nb);
585
586/* kapi.c */
587void ubi_do_get_device_info(struct ubi_device *ubi, struct ubi_device_info *di);
588void ubi_do_get_volume_info(struct ubi_device *ubi, struct ubi_volume *vol,
589 struct ubi_volume_info *vi);
578 590
579/* 591/*
580 * ubi_rb_for_each_entry - walk an RB-tree. 592 * ubi_rb_for_each_entry - walk an RB-tree.
diff --git a/drivers/mtd/ubi/vmt.c b/drivers/mtd/ubi/vmt.c
index 8e8d6fae7a02..e151862a3a98 100644
--- a/drivers/mtd/ubi/vmt.c
+++ b/drivers/mtd/ubi/vmt.c
@@ -358,6 +358,7 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req)
358 ubi->vol_count += 1; 358 ubi->vol_count += 1;
359 spin_unlock(&ubi->volumes_lock); 359 spin_unlock(&ubi->volumes_lock);
360 360
361 ubi_volume_notify(ubi, vol, UBI_VOLUME_ADDED);
361 if (paranoid_check_volumes(ubi)) 362 if (paranoid_check_volumes(ubi))
362 dbg_err("check failed while creating volume %d", vol_id); 363 dbg_err("check failed while creating volume %d", vol_id);
363 return err; 364 return err;
@@ -466,6 +467,7 @@ int ubi_remove_volume(struct ubi_volume_desc *desc, int no_vtbl)
466 ubi->vol_count -= 1; 467 ubi->vol_count -= 1;
467 spin_unlock(&ubi->volumes_lock); 468 spin_unlock(&ubi->volumes_lock);
468 469
470 ubi_volume_notify(ubi, vol, UBI_VOLUME_REMOVED);
469 if (!no_vtbl && paranoid_check_volumes(ubi)) 471 if (!no_vtbl && paranoid_check_volumes(ubi))
470 dbg_err("check failed while removing volume %d", vol_id); 472 dbg_err("check failed while removing volume %d", vol_id);
471 473
@@ -589,6 +591,7 @@ int ubi_resize_volume(struct ubi_volume_desc *desc, int reserved_pebs)
589 (long long)vol->used_ebs * vol->usable_leb_size; 591 (long long)vol->used_ebs * vol->usable_leb_size;
590 } 592 }
591 593
594 ubi_volume_notify(ubi, vol, UBI_VOLUME_RESIZED);
592 if (paranoid_check_volumes(ubi)) 595 if (paranoid_check_volumes(ubi))
593 dbg_err("check failed while re-sizing volume %d", vol_id); 596 dbg_err("check failed while re-sizing volume %d", vol_id);
594 return err; 597 return err;
@@ -635,6 +638,7 @@ int ubi_rename_volumes(struct ubi_device *ubi, struct list_head *rename_list)
635 vol->name_len = re->new_name_len; 638 vol->name_len = re->new_name_len;
636 memcpy(vol->name, re->new_name, re->new_name_len + 1); 639 memcpy(vol->name, re->new_name, re->new_name_len + 1);
637 spin_unlock(&ubi->volumes_lock); 640 spin_unlock(&ubi->volumes_lock);
641 ubi_volume_notify(ubi, vol, UBI_VOLUME_RENAMED);
638 } 642 }
639 } 643 }
640 644