diff options
Diffstat (limited to 'drivers/mtd/ubi/build.c')
-rw-r--r-- | drivers/mtd/ubi/build.c | 100 |
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 | */ | ||
134 | int 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 | */ | ||
154 | int 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 | */ | ||
193 | int 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 | ||
896 | out_uif: | 985 | out_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 | /* |