aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd/ubi/build.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mtd/ubi/build.c')
-rw-r--r--drivers/mtd/ubi/build.c100
1 files changed, 95 insertions, 5 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 /*