hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/drivers/mtd/mtdpart.c
....@@ -1,24 +1,10 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * Simple MTD partitioning layer
34 *
45 * Copyright © 2000 Nicolas Pitre <nico@fluxnic.net>
56 * Copyright © 2002 Thomas Gleixner <gleixner@linutronix.de>
67 * Copyright © 2000-2010 David Woodhouse <dwmw2@infradead.org>
7
- *
8
- * This program is free software; you can redistribute it and/or modify
9
- * it under the terms of the GNU General Public License as published by
10
- * the Free Software Foundation; either version 2 of the License, or
11
- * (at your option) any later version.
12
- *
13
- * This program is distributed in the hope that it will be useful,
14
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
- * GNU General Public License for more details.
17
- *
18
- * You should have received a copy of the GNU General Public License
19
- * along with this program; if not, write to the Free Software
20
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21
- *
228 */
239
2410 #include <linux/module.h>
....@@ -34,329 +20,56 @@
3420
3521 #include "mtdcore.h"
3622
37
-/* Our partition linked list */
38
-static LIST_HEAD(mtd_partitions);
39
-static DEFINE_MUTEX(mtd_partitions_mutex);
40
-
41
-/**
42
- * struct mtd_part - our partition node structure
43
- *
44
- * @mtd: struct holding partition details
45
- * @parent: parent mtd - flash device or another partition
46
- * @offset: partition offset relative to the *flash device*
47
- */
48
-struct mtd_part {
49
- struct mtd_info mtd;
50
- struct mtd_info *parent;
51
- uint64_t offset;
52
- struct list_head list;
53
-};
54
-
55
-/*
56
- * Given a pointer to the MTD object in the mtd_part structure, we can retrieve
57
- * the pointer to that structure.
58
- */
59
-static inline struct mtd_part *mtd_to_part(const struct mtd_info *mtd)
60
-{
61
- return container_of(mtd, struct mtd_part, mtd);
62
-}
63
-
64
-
6523 /*
6624 * MTD methods which simply translate the effective address and pass through
6725 * to the _real_ device.
6826 */
6927
70
-static int part_read(struct mtd_info *mtd, loff_t from, size_t len,
71
- size_t *retlen, u_char *buf)
28
+static inline void free_partition(struct mtd_info *mtd)
7229 {
73
- struct mtd_part *part = mtd_to_part(mtd);
74
- struct mtd_ecc_stats stats;
75
- int res;
76
-
77
- stats = part->parent->ecc_stats;
78
- res = part->parent->_read(part->parent, from + part->offset, len,
79
- retlen, buf);
80
- if (unlikely(mtd_is_eccerr(res)))
81
- mtd->ecc_stats.failed +=
82
- part->parent->ecc_stats.failed - stats.failed;
83
- else
84
- mtd->ecc_stats.corrected +=
85
- part->parent->ecc_stats.corrected - stats.corrected;
86
- return res;
30
+ kfree(mtd->name);
31
+ kfree(mtd);
8732 }
8833
89
-static int part_point(struct mtd_info *mtd, loff_t from, size_t len,
90
- size_t *retlen, void **virt, resource_size_t *phys)
34
+static struct mtd_info *allocate_partition(struct mtd_info *parent,
35
+ const struct mtd_partition *part,
36
+ int partno, uint64_t cur_offset)
9137 {
92
- struct mtd_part *part = mtd_to_part(mtd);
93
-
94
- return part->parent->_point(part->parent, from + part->offset, len,
95
- retlen, virt, phys);
96
-}
97
-
98
-static int part_unpoint(struct mtd_info *mtd, loff_t from, size_t len)
99
-{
100
- struct mtd_part *part = mtd_to_part(mtd);
101
-
102
- return part->parent->_unpoint(part->parent, from + part->offset, len);
103
-}
104
-
105
-static int part_read_oob(struct mtd_info *mtd, loff_t from,
106
- struct mtd_oob_ops *ops)
107
-{
108
- struct mtd_part *part = mtd_to_part(mtd);
109
- struct mtd_ecc_stats stats;
110
- int res;
111
-
112
- stats = part->parent->ecc_stats;
113
- res = part->parent->_read_oob(part->parent, from + part->offset, ops);
114
- if (unlikely(mtd_is_eccerr(res)))
115
- mtd->ecc_stats.failed +=
116
- part->parent->ecc_stats.failed - stats.failed;
117
- else
118
- mtd->ecc_stats.corrected +=
119
- part->parent->ecc_stats.corrected - stats.corrected;
120
- return res;
121
-}
122
-
123
-static int part_read_user_prot_reg(struct mtd_info *mtd, loff_t from,
124
- size_t len, size_t *retlen, u_char *buf)
125
-{
126
- struct mtd_part *part = mtd_to_part(mtd);
127
- return part->parent->_read_user_prot_reg(part->parent, from, len,
128
- retlen, buf);
129
-}
130
-
131
-static int part_get_user_prot_info(struct mtd_info *mtd, size_t len,
132
- size_t *retlen, struct otp_info *buf)
133
-{
134
- struct mtd_part *part = mtd_to_part(mtd);
135
- return part->parent->_get_user_prot_info(part->parent, len, retlen,
136
- buf);
137
-}
138
-
139
-static int part_read_fact_prot_reg(struct mtd_info *mtd, loff_t from,
140
- size_t len, size_t *retlen, u_char *buf)
141
-{
142
- struct mtd_part *part = mtd_to_part(mtd);
143
- return part->parent->_read_fact_prot_reg(part->parent, from, len,
144
- retlen, buf);
145
-}
146
-
147
-static int part_get_fact_prot_info(struct mtd_info *mtd, size_t len,
148
- size_t *retlen, struct otp_info *buf)
149
-{
150
- struct mtd_part *part = mtd_to_part(mtd);
151
- return part->parent->_get_fact_prot_info(part->parent, len, retlen,
152
- buf);
153
-}
154
-
155
-static int part_write(struct mtd_info *mtd, loff_t to, size_t len,
156
- size_t *retlen, const u_char *buf)
157
-{
158
- struct mtd_part *part = mtd_to_part(mtd);
159
- return part->parent->_write(part->parent, to + part->offset, len,
160
- retlen, buf);
161
-}
162
-
163
-static int part_panic_write(struct mtd_info *mtd, loff_t to, size_t len,
164
- size_t *retlen, const u_char *buf)
165
-{
166
- struct mtd_part *part = mtd_to_part(mtd);
167
- return part->parent->_panic_write(part->parent, to + part->offset, len,
168
- retlen, buf);
169
-}
170
-
171
-static int part_write_oob(struct mtd_info *mtd, loff_t to,
172
- struct mtd_oob_ops *ops)
173
-{
174
- struct mtd_part *part = mtd_to_part(mtd);
175
-
176
- return part->parent->_write_oob(part->parent, to + part->offset, ops);
177
-}
178
-
179
-static int part_write_user_prot_reg(struct mtd_info *mtd, loff_t from,
180
- size_t len, size_t *retlen, u_char *buf)
181
-{
182
- struct mtd_part *part = mtd_to_part(mtd);
183
- return part->parent->_write_user_prot_reg(part->parent, from, len,
184
- retlen, buf);
185
-}
186
-
187
-static int part_lock_user_prot_reg(struct mtd_info *mtd, loff_t from,
188
- size_t len)
189
-{
190
- struct mtd_part *part = mtd_to_part(mtd);
191
- return part->parent->_lock_user_prot_reg(part->parent, from, len);
192
-}
193
-
194
-static int part_writev(struct mtd_info *mtd, const struct kvec *vecs,
195
- unsigned long count, loff_t to, size_t *retlen)
196
-{
197
- struct mtd_part *part = mtd_to_part(mtd);
198
- return part->parent->_writev(part->parent, vecs, count,
199
- to + part->offset, retlen);
200
-}
201
-
202
-static int part_erase(struct mtd_info *mtd, struct erase_info *instr)
203
-{
204
- struct mtd_part *part = mtd_to_part(mtd);
205
- int ret;
206
-
207
- instr->addr += part->offset;
208
- ret = part->parent->_erase(part->parent, instr);
209
- if (instr->fail_addr != MTD_FAIL_ADDR_UNKNOWN)
210
- instr->fail_addr -= part->offset;
211
- instr->addr -= part->offset;
212
-
213
- return ret;
214
-}
215
-
216
-static int part_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
217
-{
218
- struct mtd_part *part = mtd_to_part(mtd);
219
- return part->parent->_lock(part->parent, ofs + part->offset, len);
220
-}
221
-
222
-static int part_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
223
-{
224
- struct mtd_part *part = mtd_to_part(mtd);
225
- return part->parent->_unlock(part->parent, ofs + part->offset, len);
226
-}
227
-
228
-static int part_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len)
229
-{
230
- struct mtd_part *part = mtd_to_part(mtd);
231
- return part->parent->_is_locked(part->parent, ofs + part->offset, len);
232
-}
233
-
234
-static void part_sync(struct mtd_info *mtd)
235
-{
236
- struct mtd_part *part = mtd_to_part(mtd);
237
- part->parent->_sync(part->parent);
238
-}
239
-
240
-static int part_suspend(struct mtd_info *mtd)
241
-{
242
- struct mtd_part *part = mtd_to_part(mtd);
243
- return part->parent->_suspend(part->parent);
244
-}
245
-
246
-static void part_resume(struct mtd_info *mtd)
247
-{
248
- struct mtd_part *part = mtd_to_part(mtd);
249
- part->parent->_resume(part->parent);
250
-}
251
-
252
-static int part_block_isreserved(struct mtd_info *mtd, loff_t ofs)
253
-{
254
- struct mtd_part *part = mtd_to_part(mtd);
255
- ofs += part->offset;
256
- return part->parent->_block_isreserved(part->parent, ofs);
257
-}
258
-
259
-static int part_block_isbad(struct mtd_info *mtd, loff_t ofs)
260
-{
261
- struct mtd_part *part = mtd_to_part(mtd);
262
- ofs += part->offset;
263
- return part->parent->_block_isbad(part->parent, ofs);
264
-}
265
-
266
-static int part_block_markbad(struct mtd_info *mtd, loff_t ofs)
267
-{
268
- struct mtd_part *part = mtd_to_part(mtd);
269
- int res;
270
-
271
- ofs += part->offset;
272
- res = part->parent->_block_markbad(part->parent, ofs);
273
- if (!res)
274
- mtd->ecc_stats.badblocks++;
275
- return res;
276
-}
277
-
278
-static int part_get_device(struct mtd_info *mtd)
279
-{
280
- struct mtd_part *part = mtd_to_part(mtd);
281
- return part->parent->_get_device(part->parent);
282
-}
283
-
284
-static void part_put_device(struct mtd_info *mtd)
285
-{
286
- struct mtd_part *part = mtd_to_part(mtd);
287
- part->parent->_put_device(part->parent);
288
-}
289
-
290
-static int part_ooblayout_ecc(struct mtd_info *mtd, int section,
291
- struct mtd_oob_region *oobregion)
292
-{
293
- struct mtd_part *part = mtd_to_part(mtd);
294
-
295
- return mtd_ooblayout_ecc(part->parent, section, oobregion);
296
-}
297
-
298
-static int part_ooblayout_free(struct mtd_info *mtd, int section,
299
- struct mtd_oob_region *oobregion)
300
-{
301
- struct mtd_part *part = mtd_to_part(mtd);
302
-
303
- return mtd_ooblayout_free(part->parent, section, oobregion);
304
-}
305
-
306
-static const struct mtd_ooblayout_ops part_ooblayout_ops = {
307
- .ecc = part_ooblayout_ecc,
308
- .free = part_ooblayout_free,
309
-};
310
-
311
-static int part_max_bad_blocks(struct mtd_info *mtd, loff_t ofs, size_t len)
312
-{
313
- struct mtd_part *part = mtd_to_part(mtd);
314
-
315
- return part->parent->_max_bad_blocks(part->parent,
316
- ofs + part->offset, len);
317
-}
318
-
319
-static inline void free_partition(struct mtd_part *p)
320
-{
321
- kfree(p->mtd.name);
322
- kfree(p);
323
-}
324
-
325
-static struct mtd_part *allocate_partition(struct mtd_info *parent,
326
- const struct mtd_partition *part, int partno,
327
- uint64_t cur_offset)
328
-{
329
- int wr_alignment = (parent->flags & MTD_NO_ERASE) ? parent->writesize :
330
- parent->erasesize;
331
- struct mtd_part *slave;
38
+ struct mtd_info *master = mtd_get_master(parent);
39
+ int wr_alignment = (parent->flags & MTD_NO_ERASE) ?
40
+ master->writesize : master->erasesize;
41
+ u64 parent_size = mtd_is_partition(parent) ?
42
+ parent->part.size : parent->size;
43
+ struct mtd_info *child;
33244 u32 remainder;
33345 char *name;
33446 u64 tmp;
33547
33648 /* allocate the partition structure */
337
- slave = kzalloc(sizeof(*slave), GFP_KERNEL);
49
+ child = kzalloc(sizeof(*child), GFP_KERNEL);
33850 name = kstrdup(part->name, GFP_KERNEL);
339
- if (!name || !slave) {
51
+ if (!name || !child) {
34052 printk(KERN_ERR"memory allocation error while creating partitions for \"%s\"\n",
34153 parent->name);
34254 kfree(name);
343
- kfree(slave);
55
+ kfree(child);
34456 return ERR_PTR(-ENOMEM);
34557 }
34658
34759 /* set up the MTD object for this partition */
348
- slave->mtd.type = parent->type;
349
- slave->mtd.flags = parent->flags & ~part->mask_flags;
350
- slave->mtd.size = part->size;
351
- slave->mtd.writesize = parent->writesize;
352
- slave->mtd.writebufsize = parent->writebufsize;
353
- slave->mtd.oobsize = parent->oobsize;
354
- slave->mtd.oobavail = parent->oobavail;
355
- slave->mtd.subpage_sft = parent->subpage_sft;
356
- slave->mtd.pairing = parent->pairing;
60
+ child->type = parent->type;
61
+ child->part.flags = parent->flags & ~part->mask_flags;
62
+ child->part.flags |= part->add_flags;
63
+ child->flags = child->part.flags;
64
+ child->part.size = part->size;
65
+ child->writesize = parent->writesize;
66
+ child->writebufsize = parent->writebufsize;
67
+ child->oobsize = parent->oobsize;
68
+ child->oobavail = parent->oobavail;
69
+ child->subpage_sft = parent->subpage_sft;
35770
358
- slave->mtd.name = name;
359
- slave->mtd.owner = parent->owner;
71
+ child->name = name;
72
+ child->owner = parent->owner;
36073
36174 /* NOTE: Historically, we didn't arrange MTDs as a tree out of
36275 * concern for showing the same data in multiple partitions.
....@@ -364,134 +77,77 @@
36477 * so the MTD_PARTITIONED_MASTER option allows that. The master
36578 * will have device nodes etc only if this is set, so make the
36679 * parent conditional on that option. Note, this is a way to
367
- * distinguish between the master and the partition in sysfs.
80
+ * distinguish between the parent and its partitions in sysfs.
36881 */
369
- slave->mtd.dev.parent = IS_ENABLED(CONFIG_MTD_PARTITIONED_MASTER) || mtd_is_partition(parent) ?
370
- &parent->dev :
371
- parent->dev.parent;
372
- slave->mtd.dev.of_node = part->of_node;
82
+ child->dev.parent = IS_ENABLED(CONFIG_MTD_PARTITIONED_MASTER) || mtd_is_partition(parent) ?
83
+ &parent->dev : parent->dev.parent;
84
+ child->dev.of_node = part->of_node;
85
+ child->parent = parent;
86
+ child->part.offset = part->offset;
87
+ INIT_LIST_HEAD(&child->partitions);
37388
374
- if (parent->_read)
375
- slave->mtd._read = part_read;
376
- if (parent->_write)
377
- slave->mtd._write = part_write;
378
-
379
- if (parent->_panic_write)
380
- slave->mtd._panic_write = part_panic_write;
381
-
382
- if (parent->_point && parent->_unpoint) {
383
- slave->mtd._point = part_point;
384
- slave->mtd._unpoint = part_unpoint;
385
- }
386
-
387
- if (parent->_read_oob)
388
- slave->mtd._read_oob = part_read_oob;
389
- if (parent->_write_oob)
390
- slave->mtd._write_oob = part_write_oob;
391
- if (parent->_read_user_prot_reg)
392
- slave->mtd._read_user_prot_reg = part_read_user_prot_reg;
393
- if (parent->_read_fact_prot_reg)
394
- slave->mtd._read_fact_prot_reg = part_read_fact_prot_reg;
395
- if (parent->_write_user_prot_reg)
396
- slave->mtd._write_user_prot_reg = part_write_user_prot_reg;
397
- if (parent->_lock_user_prot_reg)
398
- slave->mtd._lock_user_prot_reg = part_lock_user_prot_reg;
399
- if (parent->_get_user_prot_info)
400
- slave->mtd._get_user_prot_info = part_get_user_prot_info;
401
- if (parent->_get_fact_prot_info)
402
- slave->mtd._get_fact_prot_info = part_get_fact_prot_info;
403
- if (parent->_sync)
404
- slave->mtd._sync = part_sync;
405
- if (!partno && !parent->dev.class && parent->_suspend &&
406
- parent->_resume) {
407
- slave->mtd._suspend = part_suspend;
408
- slave->mtd._resume = part_resume;
409
- }
410
- if (parent->_writev)
411
- slave->mtd._writev = part_writev;
412
- if (parent->_lock)
413
- slave->mtd._lock = part_lock;
414
- if (parent->_unlock)
415
- slave->mtd._unlock = part_unlock;
416
- if (parent->_is_locked)
417
- slave->mtd._is_locked = part_is_locked;
418
- if (parent->_block_isreserved)
419
- slave->mtd._block_isreserved = part_block_isreserved;
420
- if (parent->_block_isbad)
421
- slave->mtd._block_isbad = part_block_isbad;
422
- if (parent->_block_markbad)
423
- slave->mtd._block_markbad = part_block_markbad;
424
- if (parent->_max_bad_blocks)
425
- slave->mtd._max_bad_blocks = part_max_bad_blocks;
426
-
427
- if (parent->_get_device)
428
- slave->mtd._get_device = part_get_device;
429
- if (parent->_put_device)
430
- slave->mtd._put_device = part_put_device;
431
-
432
- slave->mtd._erase = part_erase;
433
- slave->parent = parent;
434
- slave->offset = part->offset;
435
-
436
- if (slave->offset == MTDPART_OFS_APPEND)
437
- slave->offset = cur_offset;
438
- if (slave->offset == MTDPART_OFS_NXTBLK) {
89
+ if (child->part.offset == MTDPART_OFS_APPEND)
90
+ child->part.offset = cur_offset;
91
+ if (child->part.offset == MTDPART_OFS_NXTBLK) {
43992 tmp = cur_offset;
440
- slave->offset = cur_offset;
93
+ child->part.offset = cur_offset;
44194 remainder = do_div(tmp, wr_alignment);
44295 if (remainder) {
443
- slave->offset += wr_alignment - remainder;
96
+ child->part.offset += wr_alignment - remainder;
44497 printk(KERN_NOTICE "Moving partition %d: "
44598 "0x%012llx -> 0x%012llx\n", partno,
446
- (unsigned long long)cur_offset, (unsigned long long)slave->offset);
99
+ (unsigned long long)cur_offset,
100
+ child->part.offset);
447101 }
448102 }
449
- if (slave->offset == MTDPART_OFS_RETAIN) {
450
- slave->offset = cur_offset;
451
- if (parent->size - slave->offset >= slave->mtd.size) {
452
- slave->mtd.size = parent->size - slave->offset
453
- - slave->mtd.size;
103
+ if (child->part.offset == MTDPART_OFS_RETAIN) {
104
+ child->part.offset = cur_offset;
105
+ if (parent_size - child->part.offset >= child->part.size) {
106
+ child->part.size = parent_size - child->part.offset -
107
+ child->part.size;
454108 } else {
455109 printk(KERN_ERR "mtd partition \"%s\" doesn't have enough space: %#llx < %#llx, disabled\n",
456
- part->name, parent->size - slave->offset,
457
- slave->mtd.size);
110
+ part->name, parent_size - child->part.offset,
111
+ child->part.size);
458112 /* register to preserve ordering */
459113 goto out_register;
460114 }
461115 }
462
- if (slave->mtd.size == MTDPART_SIZ_FULL)
463
- slave->mtd.size = parent->size - slave->offset;
116
+ if (child->part.size == MTDPART_SIZ_FULL)
117
+ child->part.size = parent_size - child->part.offset;
464118
465
- printk(KERN_NOTICE "0x%012llx-0x%012llx : \"%s\"\n", (unsigned long long)slave->offset,
466
- (unsigned long long)(slave->offset + slave->mtd.size), slave->mtd.name);
119
+ printk(KERN_NOTICE "0x%012llx-0x%012llx : \"%s\"\n",
120
+ child->part.offset, child->part.offset + child->part.size,
121
+ child->name);
467122
468123 /* let's do some sanity checks */
469
- if (slave->offset >= parent->size) {
124
+ if (child->part.offset >= parent_size) {
470125 /* let's register it anyway to preserve ordering */
471
- slave->offset = 0;
472
- slave->mtd.size = 0;
126
+ child->part.offset = 0;
127
+ child->part.size = 0;
473128
474129 /* Initialize ->erasesize to make add_mtd_device() happy. */
475
- slave->mtd.erasesize = parent->erasesize;
476
-
130
+ child->erasesize = parent->erasesize;
477131 printk(KERN_ERR"mtd: partition \"%s\" is out of reach -- disabled\n",
478132 part->name);
479133 goto out_register;
480134 }
481
- if (slave->offset + slave->mtd.size > parent->size) {
482
- slave->mtd.size = parent->size - slave->offset;
135
+ if (child->part.offset + child->part.size > parent->size) {
136
+ child->part.size = parent_size - child->part.offset;
483137 printk(KERN_WARNING"mtd: partition \"%s\" extends beyond the end of device \"%s\" -- size truncated to %#llx\n",
484
- part->name, parent->name, (unsigned long long)slave->mtd.size);
138
+ part->name, parent->name, child->part.size);
485139 }
140
+
486141 if (parent->numeraseregions > 1) {
487142 /* Deal with variable erase size stuff */
488143 int i, max = parent->numeraseregions;
489
- u64 end = slave->offset + slave->mtd.size;
144
+ u64 end = child->part.offset + child->part.size;
490145 struct mtd_erase_region_info *regions = parent->eraseregions;
491146
492147 /* Find the first erase regions which is part of this
493148 * partition. */
494
- for (i = 0; i < max && regions[i].offset <= slave->offset; i++)
149
+ for (i = 0; i < max && regions[i].offset <= child->part.offset;
150
+ i++)
495151 ;
496152 /* The loop searched for the region _behind_ the first one */
497153 if (i > 0)
....@@ -499,70 +155,69 @@
499155
500156 /* Pick biggest erasesize */
501157 for (; i < max && regions[i].offset < end; i++) {
502
- if (slave->mtd.erasesize < regions[i].erasesize) {
503
- slave->mtd.erasesize = regions[i].erasesize;
504
- }
158
+ if (child->erasesize < regions[i].erasesize)
159
+ child->erasesize = regions[i].erasesize;
505160 }
506
- BUG_ON(slave->mtd.erasesize == 0);
161
+ BUG_ON(child->erasesize == 0);
507162 } else {
508163 /* Single erase size */
509
- slave->mtd.erasesize = parent->erasesize;
164
+ child->erasesize = master->erasesize;
510165 }
511166
512167 /*
513
- * Slave erasesize might differ from the master one if the master
168
+ * Child erasesize might differ from the parent one if the parent
514169 * exposes several regions with different erasesize. Adjust
515170 * wr_alignment accordingly.
516171 */
517
- if (!(slave->mtd.flags & MTD_NO_ERASE))
518
- wr_alignment = slave->mtd.erasesize;
172
+ if (!(child->flags & MTD_NO_ERASE))
173
+ wr_alignment = child->erasesize;
519174
520
- tmp = slave->offset;
175
+ tmp = mtd_get_master_ofs(child, 0);
521176 remainder = do_div(tmp, wr_alignment);
522
- if ((slave->mtd.flags & MTD_WRITEABLE) && remainder) {
177
+ if ((child->flags & MTD_WRITEABLE) && remainder) {
523178 /* Doesn't start on a boundary of major erase size */
524179 /* FIXME: Let it be writable if it is on a boundary of
525180 * _minor_ erase size though */
526
- slave->mtd.flags &= ~MTD_WRITEABLE;
181
+ child->flags &= ~MTD_WRITEABLE;
527182 printk(KERN_WARNING"mtd: partition \"%s\" doesn't start on an erase/write block boundary -- force read-only\n",
528183 part->name);
529184 }
530185
531
- tmp = slave->mtd.size;
186
+ tmp = mtd_get_master_ofs(child, 0) + child->part.size;
532187 remainder = do_div(tmp, wr_alignment);
533
- if ((slave->mtd.flags & MTD_WRITEABLE) && remainder) {
534
- slave->mtd.flags &= ~MTD_WRITEABLE;
188
+ if ((child->flags & MTD_WRITEABLE) && remainder) {
189
+ child->flags &= ~MTD_WRITEABLE;
535190 printk(KERN_WARNING"mtd: partition \"%s\" doesn't end on an erase/write block -- force read-only\n",
536191 part->name);
537192 }
538193
539
- mtd_set_ooblayout(&slave->mtd, &part_ooblayout_ops);
540
- slave->mtd.ecc_step_size = parent->ecc_step_size;
541
- slave->mtd.ecc_strength = parent->ecc_strength;
542
- slave->mtd.bitflip_threshold = parent->bitflip_threshold;
194
+ child->size = child->part.size;
195
+ child->ecc_step_size = parent->ecc_step_size;
196
+ child->ecc_strength = parent->ecc_strength;
197
+ child->bitflip_threshold = parent->bitflip_threshold;
543198
544
- if (parent->_block_isbad) {
199
+ if (master->_block_isbad) {
545200 uint64_t offs = 0;
546201
547
- while (offs < slave->mtd.size) {
548
- if (mtd_block_isreserved(parent, offs + slave->offset))
549
- slave->mtd.ecc_stats.bbtblocks++;
550
- else if (mtd_block_isbad(parent, offs + slave->offset))
551
- slave->mtd.ecc_stats.badblocks++;
552
- offs += slave->mtd.erasesize;
202
+ while (offs < child->part.size) {
203
+ if (mtd_block_isreserved(child, offs))
204
+ child->ecc_stats.bbtblocks++;
205
+ else if (mtd_block_isbad(child, offs))
206
+ child->ecc_stats.badblocks++;
207
+ offs += child->erasesize;
553208 }
554209 }
555210
556211 out_register:
557
- return slave;
212
+ return child;
558213 }
559214
560215 static ssize_t mtd_partition_offset_show(struct device *dev,
561216 struct device_attribute *attr, char *buf)
562217 {
563218 struct mtd_info *mtd = dev_get_drvdata(dev);
564
- struct mtd_part *part = mtd_to_part(mtd);
565
- return snprintf(buf, PAGE_SIZE, "%lld\n", part->offset);
219
+
220
+ return snprintf(buf, PAGE_SIZE, "%lld\n", mtd->part.offset);
566221 }
567222
568223 static DEVICE_ATTR(offset, S_IRUGO, mtd_partition_offset_show, NULL);
....@@ -572,9 +227,9 @@
572227 NULL
573228 };
574229
575
-static int mtd_add_partition_attrs(struct mtd_part *new)
230
+static int mtd_add_partition_attrs(struct mtd_info *new)
576231 {
577
- int ret = sysfs_create_files(&new->mtd.dev.kobj, mtd_partition_attrs);
232
+ int ret = sysfs_create_files(&new->dev.kobj, mtd_partition_attrs);
578233 if (ret)
579234 printk(KERN_WARNING
580235 "mtd: failed to create partition attrs, err=%d\n", ret);
....@@ -584,8 +239,11 @@
584239 int mtd_add_partition(struct mtd_info *parent, const char *name,
585240 long long offset, long long length)
586241 {
242
+ struct mtd_info *master = mtd_get_master(parent);
243
+ u64 parent_size = mtd_is_partition(parent) ?
244
+ parent->part.size : parent->size;
587245 struct mtd_partition part;
588
- struct mtd_part *new;
246
+ struct mtd_info *child;
589247 int ret = 0;
590248
591249 /* the direct offset is expected */
....@@ -594,7 +252,7 @@
594252 return -EINVAL;
595253
596254 if (length == MTDPART_SIZ_FULL)
597
- length = parent->size - offset;
255
+ length = parent_size - offset;
598256
599257 if (length <= 0)
600258 return -EINVAL;
....@@ -604,28 +262,28 @@
604262 part.size = length;
605263 part.offset = offset;
606264
607
- new = allocate_partition(parent, &part, -1, offset);
608
- if (IS_ERR(new))
609
- return PTR_ERR(new);
265
+ child = allocate_partition(parent, &part, -1, offset);
266
+ if (IS_ERR(child))
267
+ return PTR_ERR(child);
610268
611
- mutex_lock(&mtd_partitions_mutex);
612
- list_add(&new->list, &mtd_partitions);
613
- mutex_unlock(&mtd_partitions_mutex);
269
+ mutex_lock(&master->master.partitions_lock);
270
+ list_add_tail(&child->part.node, &parent->partitions);
271
+ mutex_unlock(&master->master.partitions_lock);
614272
615
- ret = add_mtd_device(&new->mtd);
273
+ ret = add_mtd_device(child);
616274 if (ret)
617275 goto err_remove_part;
618276
619
- mtd_add_partition_attrs(new);
277
+ mtd_add_partition_attrs(child);
620278
621279 return 0;
622280
623281 err_remove_part:
624
- mutex_lock(&mtd_partitions_mutex);
625
- list_del(&new->list);
626
- mutex_unlock(&mtd_partitions_mutex);
282
+ mutex_lock(&master->master.partitions_lock);
283
+ list_del(&child->part.node);
284
+ mutex_unlock(&master->master.partitions_lock);
627285
628
- free_partition(new);
286
+ free_partition(child);
629287
630288 return ret;
631289 }
....@@ -634,119 +292,142 @@
634292 /**
635293 * __mtd_del_partition - delete MTD partition
636294 *
637
- * @priv: internal MTD struct for partition to be deleted
295
+ * @priv: MTD structure to be deleted
638296 *
639297 * This function must be called with the partitions mutex locked.
640298 */
641
-static int __mtd_del_partition(struct mtd_part *priv)
299
+static int __mtd_del_partition(struct mtd_info *mtd)
642300 {
643
- struct mtd_part *child, *next;
301
+ struct mtd_info *child, *next;
644302 int err;
645303
646
- list_for_each_entry_safe(child, next, &mtd_partitions, list) {
647
- if (child->parent == &priv->mtd) {
648
- err = __mtd_del_partition(child);
649
- if (err)
650
- return err;
651
- }
304
+ list_for_each_entry_safe(child, next, &mtd->partitions, part.node) {
305
+ err = __mtd_del_partition(child);
306
+ if (err)
307
+ return err;
652308 }
653309
654
- sysfs_remove_files(&priv->mtd.dev.kobj, mtd_partition_attrs);
310
+ sysfs_remove_files(&mtd->dev.kobj, mtd_partition_attrs);
655311
656
- err = del_mtd_device(&priv->mtd);
312
+ err = del_mtd_device(mtd);
657313 if (err)
658314 return err;
659315
660
- list_del(&priv->list);
661
- free_partition(priv);
316
+ list_del(&mtd->part.node);
317
+ free_partition(mtd);
662318
663319 return 0;
664320 }
665321
666322 /*
667323 * This function unregisters and destroy all slave MTD objects which are
668
- * attached to the given MTD object.
324
+ * attached to the given MTD object, recursively.
669325 */
670
-int del_mtd_partitions(struct mtd_info *mtd)
326
+static int __del_mtd_partitions(struct mtd_info *mtd)
671327 {
672
- struct mtd_part *slave, *next;
328
+ struct mtd_info *child, *next;
329
+ LIST_HEAD(tmp_list);
673330 int ret, err = 0;
674331
675
- mutex_lock(&mtd_partitions_mutex);
676
- list_for_each_entry_safe(slave, next, &mtd_partitions, list)
677
- if (slave->parent == mtd) {
678
- ret = __mtd_del_partition(slave);
679
- if (ret < 0)
680
- err = ret;
332
+ list_for_each_entry_safe(child, next, &mtd->partitions, part.node) {
333
+ if (mtd_has_partitions(child))
334
+ __del_mtd_partitions(child);
335
+
336
+ pr_info("Deleting %s MTD partition\n", child->name);
337
+ ret = del_mtd_device(child);
338
+ if (ret < 0) {
339
+ pr_err("Error when deleting partition \"%s\" (%d)\n",
340
+ child->name, ret);
341
+ err = ret;
342
+ continue;
681343 }
682
- mutex_unlock(&mtd_partitions_mutex);
344
+
345
+ list_del(&child->part.node);
346
+ free_partition(child);
347
+ }
683348
684349 return err;
685350 }
686351
352
+int del_mtd_partitions(struct mtd_info *mtd)
353
+{
354
+ struct mtd_info *master = mtd_get_master(mtd);
355
+ int ret;
356
+
357
+ pr_info("Deleting MTD partitions on \"%s\":\n", mtd->name);
358
+
359
+ mutex_lock(&master->master.partitions_lock);
360
+ ret = __del_mtd_partitions(mtd);
361
+ mutex_unlock(&master->master.partitions_lock);
362
+
363
+ return ret;
364
+}
365
+
687366 int mtd_del_partition(struct mtd_info *mtd, int partno)
688367 {
689
- struct mtd_part *slave, *next;
368
+ struct mtd_info *child, *master = mtd_get_master(mtd);
690369 int ret = -EINVAL;
691370
692
- mutex_lock(&mtd_partitions_mutex);
693
- list_for_each_entry_safe(slave, next, &mtd_partitions, list)
694
- if ((slave->parent == mtd) &&
695
- (slave->mtd.index == partno)) {
696
- ret = __mtd_del_partition(slave);
371
+ mutex_lock(&master->master.partitions_lock);
372
+ list_for_each_entry(child, &mtd->partitions, part.node) {
373
+ if (child->index == partno) {
374
+ ret = __mtd_del_partition(child);
697375 break;
698376 }
699
- mutex_unlock(&mtd_partitions_mutex);
377
+ }
378
+ mutex_unlock(&master->master.partitions_lock);
700379
701380 return ret;
702381 }
703382 EXPORT_SYMBOL_GPL(mtd_del_partition);
704383
705384 /*
706
- * This function, given a master MTD object and a partition table, creates
707
- * and registers slave MTD objects which are bound to the master according to
708
- * the partition definitions.
385
+ * This function, given a parent MTD object and a partition table, creates
386
+ * and registers the child MTD objects which are bound to the parent according
387
+ * to the partition definitions.
709388 *
710
- * For historical reasons, this function's caller only registers the master
389
+ * For historical reasons, this function's caller only registers the parent
711390 * if the MTD_PARTITIONED_MASTER config option is set.
712391 */
713392
714
-int add_mtd_partitions(struct mtd_info *master,
393
+int add_mtd_partitions(struct mtd_info *parent,
715394 const struct mtd_partition *parts,
716395 int nbparts)
717396 {
718
- struct mtd_part *slave;
397
+ struct mtd_info *child, *master = mtd_get_master(parent);
719398 uint64_t cur_offset = 0;
720399 int i, ret;
721400
722
- printk(KERN_NOTICE "Creating %d MTD partitions on \"%s\":\n", nbparts, master->name);
401
+ printk(KERN_NOTICE "Creating %d MTD partitions on \"%s\":\n",
402
+ nbparts, parent->name);
723403
724404 for (i = 0; i < nbparts; i++) {
725
- slave = allocate_partition(master, parts + i, i, cur_offset);
726
- if (IS_ERR(slave)) {
727
- ret = PTR_ERR(slave);
405
+ child = allocate_partition(parent, parts + i, i, cur_offset);
406
+ if (IS_ERR(child)) {
407
+ ret = PTR_ERR(child);
728408 goto err_del_partitions;
729409 }
730410
731
- mutex_lock(&mtd_partitions_mutex);
732
- list_add(&slave->list, &mtd_partitions);
733
- mutex_unlock(&mtd_partitions_mutex);
411
+ mutex_lock(&master->master.partitions_lock);
412
+ list_add_tail(&child->part.node, &parent->partitions);
413
+ mutex_unlock(&master->master.partitions_lock);
734414
735
- ret = add_mtd_device(&slave->mtd);
415
+ ret = add_mtd_device(child);
736416 if (ret) {
737
- mutex_lock(&mtd_partitions_mutex);
738
- list_del(&slave->list);
739
- mutex_unlock(&mtd_partitions_mutex);
417
+ mutex_lock(&master->master.partitions_lock);
418
+ list_del(&child->part.node);
419
+ mutex_unlock(&master->master.partitions_lock);
740420
741
- free_partition(slave);
421
+ free_partition(child);
742422 goto err_del_partitions;
743423 }
744424
745
- mtd_add_partition_attrs(slave);
746
- /* Look for subpartitions */
747
- parse_mtd_partitions(&slave->mtd, parts[i].types, NULL);
425
+ mtd_add_partition_attrs(child);
748426
749
- cur_offset = slave->offset + slave->mtd.size;
427
+ /* Look for subpartitions */
428
+ parse_mtd_partitions(child, parts[i].types, NULL);
429
+
430
+ cur_offset = child->part.offset + child->part.size;
750431 }
751432
752433 return 0;
....@@ -1027,29 +708,11 @@
1027708 }
1028709 }
1029710
1030
-int mtd_is_partition(const struct mtd_info *mtd)
1031
-{
1032
- struct mtd_part *part;
1033
- int ispart = 0;
1034
-
1035
- mutex_lock(&mtd_partitions_mutex);
1036
- list_for_each_entry(part, &mtd_partitions, list)
1037
- if (&part->mtd == mtd) {
1038
- ispart = 1;
1039
- break;
1040
- }
1041
- mutex_unlock(&mtd_partitions_mutex);
1042
-
1043
- return ispart;
1044
-}
1045
-EXPORT_SYMBOL_GPL(mtd_is_partition);
1046
-
1047711 /* Returns the size of the entire flash chip */
1048712 uint64_t mtd_get_device_size(const struct mtd_info *mtd)
1049713 {
1050
- if (!mtd_is_partition(mtd))
1051
- return mtd->size;
714
+ struct mtd_info *master = mtd_get_master((struct mtd_info *)mtd);
1052715
1053
- return mtd_get_device_size(mtd_to_part(mtd)->parent);
716
+ return master->size;
1054717 }
1055718 EXPORT_SYMBOL_GPL(mtd_get_device_size);