diff options
Diffstat (limited to 'drivers/mtd/mtdpart.c')
-rw-r--r-- | drivers/mtd/mtdpart.c | 99 |
1 files changed, 50 insertions, 49 deletions
diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c index b92e6bfffaf2..99395911d26f 100644 --- a/drivers/mtd/mtdpart.c +++ b/drivers/mtd/mtdpart.c | |||
@@ -5,11 +5,11 @@ | |||
5 | * | 5 | * |
6 | * This code is GPL | 6 | * This code is GPL |
7 | * | 7 | * |
8 | * $Id: mtdpart.c,v 1.53 2005/02/08 17:11:13 nico Exp $ | 8 | * $Id: mtdpart.c,v 1.55 2005/11/07 11:14:20 gleixner Exp $ |
9 | * | 9 | * |
10 | * 02-21-2002 Thomas Gleixner <gleixner@autronix.de> | 10 | * 02-21-2002 Thomas Gleixner <gleixner@autronix.de> |
11 | * added support for read_oob, write_oob | 11 | * added support for read_oob, write_oob |
12 | */ | 12 | */ |
13 | 13 | ||
14 | #include <linux/module.h> | 14 | #include <linux/module.h> |
15 | #include <linux/types.h> | 15 | #include <linux/types.h> |
@@ -41,13 +41,13 @@ struct mtd_part { | |||
41 | */ | 41 | */ |
42 | #define PART(x) ((struct mtd_part *)(x)) | 42 | #define PART(x) ((struct mtd_part *)(x)) |
43 | 43 | ||
44 | 44 | ||
45 | /* | 45 | /* |
46 | * MTD methods which simply translate the effective address and pass through | 46 | * MTD methods which simply translate the effective address and pass through |
47 | * to the _real_ device. | 47 | * to the _real_ device. |
48 | */ | 48 | */ |
49 | 49 | ||
50 | static int part_read (struct mtd_info *mtd, loff_t from, size_t len, | 50 | static int part_read (struct mtd_info *mtd, loff_t from, size_t len, |
51 | size_t *retlen, u_char *buf) | 51 | size_t *retlen, u_char *buf) |
52 | { | 52 | { |
53 | struct mtd_part *part = PART(mtd); | 53 | struct mtd_part *part = PART(mtd); |
@@ -55,15 +55,15 @@ static int part_read (struct mtd_info *mtd, loff_t from, size_t len, | |||
55 | len = 0; | 55 | len = 0; |
56 | else if (from + len > mtd->size) | 56 | else if (from + len > mtd->size) |
57 | len = mtd->size - from; | 57 | len = mtd->size - from; |
58 | if (part->master->read_ecc == NULL) | 58 | if (part->master->read_ecc == NULL) |
59 | return part->master->read (part->master, from + part->offset, | 59 | return part->master->read (part->master, from + part->offset, |
60 | len, retlen, buf); | 60 | len, retlen, buf); |
61 | else | 61 | else |
62 | return part->master->read_ecc (part->master, from + part->offset, | 62 | return part->master->read_ecc (part->master, from + part->offset, |
63 | len, retlen, buf, NULL, &mtd->oobinfo); | 63 | len, retlen, buf, NULL, &mtd->oobinfo); |
64 | } | 64 | } |
65 | 65 | ||
66 | static int part_point (struct mtd_info *mtd, loff_t from, size_t len, | 66 | static int part_point (struct mtd_info *mtd, loff_t from, size_t len, |
67 | size_t *retlen, u_char **buf) | 67 | size_t *retlen, u_char **buf) |
68 | { | 68 | { |
69 | struct mtd_part *part = PART(mtd); | 69 | struct mtd_part *part = PART(mtd); |
@@ -71,7 +71,7 @@ static int part_point (struct mtd_info *mtd, loff_t from, size_t len, | |||
71 | len = 0; | 71 | len = 0; |
72 | else if (from + len > mtd->size) | 72 | else if (from + len > mtd->size) |
73 | len = mtd->size - from; | 73 | len = mtd->size - from; |
74 | return part->master->point (part->master, from + part->offset, | 74 | return part->master->point (part->master, from + part->offset, |
75 | len, retlen, buf); | 75 | len, retlen, buf); |
76 | } | 76 | } |
77 | static void part_unpoint (struct mtd_info *mtd, u_char *addr, loff_t from, size_t len) | 77 | static void part_unpoint (struct mtd_info *mtd, u_char *addr, loff_t from, size_t len) |
@@ -82,7 +82,7 @@ static void part_unpoint (struct mtd_info *mtd, u_char *addr, loff_t from, size_ | |||
82 | } | 82 | } |
83 | 83 | ||
84 | 84 | ||
85 | static int part_read_ecc (struct mtd_info *mtd, loff_t from, size_t len, | 85 | static int part_read_ecc (struct mtd_info *mtd, loff_t from, size_t len, |
86 | size_t *retlen, u_char *buf, u_char *eccbuf, struct nand_oobinfo *oobsel) | 86 | size_t *retlen, u_char *buf, u_char *eccbuf, struct nand_oobinfo *oobsel) |
87 | { | 87 | { |
88 | struct mtd_part *part = PART(mtd); | 88 | struct mtd_part *part = PART(mtd); |
@@ -92,11 +92,11 @@ static int part_read_ecc (struct mtd_info *mtd, loff_t from, size_t len, | |||
92 | len = 0; | 92 | len = 0; |
93 | else if (from + len > mtd->size) | 93 | else if (from + len > mtd->size) |
94 | len = mtd->size - from; | 94 | len = mtd->size - from; |
95 | return part->master->read_ecc (part->master, from + part->offset, | 95 | return part->master->read_ecc (part->master, from + part->offset, |
96 | len, retlen, buf, eccbuf, oobsel); | 96 | len, retlen, buf, eccbuf, oobsel); |
97 | } | 97 | } |
98 | 98 | ||
99 | static int part_read_oob (struct mtd_info *mtd, loff_t from, size_t len, | 99 | static int part_read_oob (struct mtd_info *mtd, loff_t from, size_t len, |
100 | size_t *retlen, u_char *buf) | 100 | size_t *retlen, u_char *buf) |
101 | { | 101 | { |
102 | struct mtd_part *part = PART(mtd); | 102 | struct mtd_part *part = PART(mtd); |
@@ -104,15 +104,15 @@ static int part_read_oob (struct mtd_info *mtd, loff_t from, size_t len, | |||
104 | len = 0; | 104 | len = 0; |
105 | else if (from + len > mtd->size) | 105 | else if (from + len > mtd->size) |
106 | len = mtd->size - from; | 106 | len = mtd->size - from; |
107 | return part->master->read_oob (part->master, from + part->offset, | 107 | return part->master->read_oob (part->master, from + part->offset, |
108 | len, retlen, buf); | 108 | len, retlen, buf); |
109 | } | 109 | } |
110 | 110 | ||
111 | static int part_read_user_prot_reg (struct mtd_info *mtd, loff_t from, size_t len, | 111 | static int part_read_user_prot_reg (struct mtd_info *mtd, loff_t from, size_t len, |
112 | size_t *retlen, u_char *buf) | 112 | size_t *retlen, u_char *buf) |
113 | { | 113 | { |
114 | struct mtd_part *part = PART(mtd); | 114 | struct mtd_part *part = PART(mtd); |
115 | return part->master->read_user_prot_reg (part->master, from, | 115 | return part->master->read_user_prot_reg (part->master, from, |
116 | len, retlen, buf); | 116 | len, retlen, buf); |
117 | } | 117 | } |
118 | 118 | ||
@@ -123,11 +123,11 @@ static int part_get_user_prot_info (struct mtd_info *mtd, | |||
123 | return part->master->get_user_prot_info (part->master, buf, len); | 123 | return part->master->get_user_prot_info (part->master, buf, len); |
124 | } | 124 | } |
125 | 125 | ||
126 | static int part_read_fact_prot_reg (struct mtd_info *mtd, loff_t from, size_t len, | 126 | static int part_read_fact_prot_reg (struct mtd_info *mtd, loff_t from, size_t len, |
127 | size_t *retlen, u_char *buf) | 127 | size_t *retlen, u_char *buf) |
128 | { | 128 | { |
129 | struct mtd_part *part = PART(mtd); | 129 | struct mtd_part *part = PART(mtd); |
130 | return part->master->read_fact_prot_reg (part->master, from, | 130 | return part->master->read_fact_prot_reg (part->master, from, |
131 | len, retlen, buf); | 131 | len, retlen, buf); |
132 | } | 132 | } |
133 | 133 | ||
@@ -148,13 +148,13 @@ static int part_write (struct mtd_info *mtd, loff_t to, size_t len, | |||
148 | len = 0; | 148 | len = 0; |
149 | else if (to + len > mtd->size) | 149 | else if (to + len > mtd->size) |
150 | len = mtd->size - to; | 150 | len = mtd->size - to; |
151 | if (part->master->write_ecc == NULL) | 151 | if (part->master->write_ecc == NULL) |
152 | return part->master->write (part->master, to + part->offset, | 152 | return part->master->write (part->master, to + part->offset, |
153 | len, retlen, buf); | 153 | len, retlen, buf); |
154 | else | 154 | else |
155 | return part->master->write_ecc (part->master, to + part->offset, | 155 | return part->master->write_ecc (part->master, to + part->offset, |
156 | len, retlen, buf, NULL, &mtd->oobinfo); | 156 | len, retlen, buf, NULL, &mtd->oobinfo); |
157 | 157 | ||
158 | } | 158 | } |
159 | 159 | ||
160 | static int part_write_ecc (struct mtd_info *mtd, loff_t to, size_t len, | 160 | static int part_write_ecc (struct mtd_info *mtd, loff_t to, size_t len, |
@@ -170,7 +170,7 @@ static int part_write_ecc (struct mtd_info *mtd, loff_t to, size_t len, | |||
170 | len = 0; | 170 | len = 0; |
171 | else if (to + len > mtd->size) | 171 | else if (to + len > mtd->size) |
172 | len = mtd->size - to; | 172 | len = mtd->size - to; |
173 | return part->master->write_ecc (part->master, to + part->offset, | 173 | return part->master->write_ecc (part->master, to + part->offset, |
174 | len, retlen, buf, eccbuf, oobsel); | 174 | len, retlen, buf, eccbuf, oobsel); |
175 | } | 175 | } |
176 | 176 | ||
@@ -184,19 +184,19 @@ static int part_write_oob (struct mtd_info *mtd, loff_t to, size_t len, | |||
184 | len = 0; | 184 | len = 0; |
185 | else if (to + len > mtd->size) | 185 | else if (to + len > mtd->size) |
186 | len = mtd->size - to; | 186 | len = mtd->size - to; |
187 | return part->master->write_oob (part->master, to + part->offset, | 187 | return part->master->write_oob (part->master, to + part->offset, |
188 | len, retlen, buf); | 188 | len, retlen, buf); |
189 | } | 189 | } |
190 | 190 | ||
191 | static int part_write_user_prot_reg (struct mtd_info *mtd, loff_t from, size_t len, | 191 | static int part_write_user_prot_reg (struct mtd_info *mtd, loff_t from, size_t len, |
192 | size_t *retlen, u_char *buf) | 192 | size_t *retlen, u_char *buf) |
193 | { | 193 | { |
194 | struct mtd_part *part = PART(mtd); | 194 | struct mtd_part *part = PART(mtd); |
195 | return part->master->write_user_prot_reg (part->master, from, | 195 | return part->master->write_user_prot_reg (part->master, from, |
196 | len, retlen, buf); | 196 | len, retlen, buf); |
197 | } | 197 | } |
198 | 198 | ||
199 | static int part_lock_user_prot_reg (struct mtd_info *mtd, loff_t from, size_t len) | 199 | static int part_lock_user_prot_reg (struct mtd_info *mtd, loff_t from, size_t len) |
200 | { | 200 | { |
201 | struct mtd_part *part = PART(mtd); | 201 | struct mtd_part *part = PART(mtd); |
202 | return part->master->lock_user_prot_reg (part->master, from, len); | 202 | return part->master->lock_user_prot_reg (part->master, from, len); |
@@ -208,7 +208,7 @@ static int part_writev (struct mtd_info *mtd, const struct kvec *vecs, | |||
208 | struct mtd_part *part = PART(mtd); | 208 | struct mtd_part *part = PART(mtd); |
209 | if (!(mtd->flags & MTD_WRITEABLE)) | 209 | if (!(mtd->flags & MTD_WRITEABLE)) |
210 | return -EROFS; | 210 | return -EROFS; |
211 | if (part->master->writev_ecc == NULL) | 211 | if (part->master->writev_ecc == NULL) |
212 | return part->master->writev (part->master, vecs, count, | 212 | return part->master->writev (part->master, vecs, count, |
213 | to + part->offset, retlen); | 213 | to + part->offset, retlen); |
214 | else | 214 | else |
@@ -221,12 +221,12 @@ static int part_readv (struct mtd_info *mtd, struct kvec *vecs, | |||
221 | unsigned long count, loff_t from, size_t *retlen) | 221 | unsigned long count, loff_t from, size_t *retlen) |
222 | { | 222 | { |
223 | struct mtd_part *part = PART(mtd); | 223 | struct mtd_part *part = PART(mtd); |
224 | if (part->master->readv_ecc == NULL) | 224 | if (part->master->readv_ecc == NULL) |
225 | return part->master->readv (part->master, vecs, count, | 225 | return part->master->readv (part->master, vecs, count, |
226 | from + part->offset, retlen); | 226 | from + part->offset, retlen); |
227 | else | 227 | else |
228 | return part->master->readv_ecc (part->master, vecs, count, | 228 | return part->master->readv_ecc (part->master, vecs, count, |
229 | from + part->offset, retlen, | 229 | from + part->offset, retlen, |
230 | NULL, &mtd->oobinfo); | 230 | NULL, &mtd->oobinfo); |
231 | } | 231 | } |
232 | 232 | ||
@@ -252,7 +252,7 @@ static int part_readv_ecc (struct mtd_info *mtd, struct kvec *vecs, | |||
252 | if (oobsel == NULL) | 252 | if (oobsel == NULL) |
253 | oobsel = &mtd->oobinfo; | 253 | oobsel = &mtd->oobinfo; |
254 | return part->master->readv_ecc (part->master, vecs, count, | 254 | return part->master->readv_ecc (part->master, vecs, count, |
255 | from + part->offset, retlen, | 255 | from + part->offset, retlen, |
256 | eccbuf, oobsel); | 256 | eccbuf, oobsel); |
257 | } | 257 | } |
258 | 258 | ||
@@ -286,7 +286,7 @@ EXPORT_SYMBOL_GPL(mtd_erase_callback); | |||
286 | static int part_lock (struct mtd_info *mtd, loff_t ofs, size_t len) | 286 | static int part_lock (struct mtd_info *mtd, loff_t ofs, size_t len) |
287 | { | 287 | { |
288 | struct mtd_part *part = PART(mtd); | 288 | struct mtd_part *part = PART(mtd); |
289 | if ((len + ofs) > mtd->size) | 289 | if ((len + ofs) > mtd->size) |
290 | return -EINVAL; | 290 | return -EINVAL; |
291 | return part->master->lock(part->master, ofs + part->offset, len); | 291 | return part->master->lock(part->master, ofs + part->offset, len); |
292 | } | 292 | } |
@@ -294,7 +294,7 @@ static int part_lock (struct mtd_info *mtd, loff_t ofs, size_t len) | |||
294 | static int part_unlock (struct mtd_info *mtd, loff_t ofs, size_t len) | 294 | static int part_unlock (struct mtd_info *mtd, loff_t ofs, size_t len) |
295 | { | 295 | { |
296 | struct mtd_part *part = PART(mtd); | 296 | struct mtd_part *part = PART(mtd); |
297 | if ((len + ofs) > mtd->size) | 297 | if ((len + ofs) > mtd->size) |
298 | return -EINVAL; | 298 | return -EINVAL; |
299 | return part->master->unlock(part->master, ofs + part->offset, len); | 299 | return part->master->unlock(part->master, ofs + part->offset, len); |
300 | } | 300 | } |
@@ -337,8 +337,8 @@ static int part_block_markbad (struct mtd_info *mtd, loff_t ofs) | |||
337 | return part->master->block_markbad(part->master, ofs); | 337 | return part->master->block_markbad(part->master, ofs); |
338 | } | 338 | } |
339 | 339 | ||
340 | /* | 340 | /* |
341 | * This function unregisters and destroy all slave MTD objects which are | 341 | * This function unregisters and destroy all slave MTD objects which are |
342 | * attached to the given master MTD object. | 342 | * attached to the given master MTD object. |
343 | */ | 343 | */ |
344 | 344 | ||
@@ -371,7 +371,7 @@ int del_mtd_partitions(struct mtd_info *master) | |||
371 | * (Q: should we register the master MTD object as well?) | 371 | * (Q: should we register the master MTD object as well?) |
372 | */ | 372 | */ |
373 | 373 | ||
374 | int add_mtd_partitions(struct mtd_info *master, | 374 | int add_mtd_partitions(struct mtd_info *master, |
375 | const struct mtd_partition *parts, | 375 | const struct mtd_partition *parts, |
376 | int nbparts) | 376 | int nbparts) |
377 | { | 377 | { |
@@ -414,7 +414,7 @@ int add_mtd_partitions(struct mtd_info *master, | |||
414 | slave->mtd.point = part_point; | 414 | slave->mtd.point = part_point; |
415 | slave->mtd.unpoint = part_unpoint; | 415 | slave->mtd.unpoint = part_unpoint; |
416 | } | 416 | } |
417 | 417 | ||
418 | if (master->read_ecc) | 418 | if (master->read_ecc) |
419 | slave->mtd.read_ecc = part_read_ecc; | 419 | slave->mtd.read_ecc = part_read_ecc; |
420 | if (master->write_ecc) | 420 | if (master->write_ecc) |
@@ -465,9 +465,10 @@ int add_mtd_partitions(struct mtd_info *master, | |||
465 | if (slave->offset == MTDPART_OFS_APPEND) | 465 | if (slave->offset == MTDPART_OFS_APPEND) |
466 | slave->offset = cur_offset; | 466 | slave->offset = cur_offset; |
467 | if (slave->offset == MTDPART_OFS_NXTBLK) { | 467 | if (slave->offset == MTDPART_OFS_NXTBLK) { |
468 | u_int32_t emask = master->erasesize-1; | 468 | slave->offset = cur_offset; |
469 | slave->offset = (cur_offset + emask) & ~emask; | 469 | if ((cur_offset % master->erasesize) != 0) { |
470 | if (slave->offset != cur_offset) { | 470 | /* Round up to next erasesize */ |
471 | slave->offset = ((cur_offset / master->erasesize) + 1) * master->erasesize; | ||
471 | printk(KERN_NOTICE "Moving partition %d: " | 472 | printk(KERN_NOTICE "Moving partition %d: " |
472 | "0x%08x -> 0x%08x\n", i, | 473 | "0x%08x -> 0x%08x\n", i, |
473 | cur_offset, slave->offset); | 474 | cur_offset, slave->offset); |
@@ -476,8 +477,8 @@ int add_mtd_partitions(struct mtd_info *master, | |||
476 | if (slave->mtd.size == MTDPART_SIZ_FULL) | 477 | if (slave->mtd.size == MTDPART_SIZ_FULL) |
477 | slave->mtd.size = master->size - slave->offset; | 478 | slave->mtd.size = master->size - slave->offset; |
478 | cur_offset = slave->offset + slave->mtd.size; | 479 | cur_offset = slave->offset + slave->mtd.size; |
479 | 480 | ||
480 | printk (KERN_NOTICE "0x%08x-0x%08x : \"%s\"\n", slave->offset, | 481 | printk (KERN_NOTICE "0x%08x-0x%08x : \"%s\"\n", slave->offset, |
481 | slave->offset + slave->mtd.size, slave->mtd.name); | 482 | slave->offset + slave->mtd.size, slave->mtd.name); |
482 | 483 | ||
483 | /* let's do some sanity checks */ | 484 | /* let's do some sanity checks */ |
@@ -497,7 +498,7 @@ int add_mtd_partitions(struct mtd_info *master, | |||
497 | /* Deal with variable erase size stuff */ | 498 | /* Deal with variable erase size stuff */ |
498 | int i; | 499 | int i; |
499 | struct mtd_erase_region_info *regions = master->eraseregions; | 500 | struct mtd_erase_region_info *regions = master->eraseregions; |
500 | 501 | ||
501 | /* Find the first erase regions which is part of this partition. */ | 502 | /* Find the first erase regions which is part of this partition. */ |
502 | for (i=0; i < master->numeraseregions && slave->offset >= regions[i].offset; i++) | 503 | for (i=0; i < master->numeraseregions && slave->offset >= regions[i].offset; i++) |
503 | ; | 504 | ; |
@@ -512,7 +513,7 @@ int add_mtd_partitions(struct mtd_info *master, | |||
512 | slave->mtd.erasesize = master->erasesize; | 513 | slave->mtd.erasesize = master->erasesize; |
513 | } | 514 | } |
514 | 515 | ||
515 | if ((slave->mtd.flags & MTD_WRITEABLE) && | 516 | if ((slave->mtd.flags & MTD_WRITEABLE) && |
516 | (slave->offset % slave->mtd.erasesize)) { | 517 | (slave->offset % slave->mtd.erasesize)) { |
517 | /* Doesn't start on a boundary of major erase size */ | 518 | /* Doesn't start on a boundary of major erase size */ |
518 | /* FIXME: Let it be writable if it is on a boundary of _minor_ erase size though */ | 519 | /* FIXME: Let it be writable if it is on a boundary of _minor_ erase size though */ |
@@ -520,14 +521,14 @@ int add_mtd_partitions(struct mtd_info *master, | |||
520 | printk ("mtd: partition \"%s\" doesn't start on an erase block boundary -- force read-only\n", | 521 | printk ("mtd: partition \"%s\" doesn't start on an erase block boundary -- force read-only\n", |
521 | parts[i].name); | 522 | parts[i].name); |
522 | } | 523 | } |
523 | if ((slave->mtd.flags & MTD_WRITEABLE) && | 524 | if ((slave->mtd.flags & MTD_WRITEABLE) && |
524 | (slave->mtd.size % slave->mtd.erasesize)) { | 525 | (slave->mtd.size % slave->mtd.erasesize)) { |
525 | slave->mtd.flags &= ~MTD_WRITEABLE; | 526 | slave->mtd.flags &= ~MTD_WRITEABLE; |
526 | printk ("mtd: partition \"%s\" doesn't end on an erase block -- force read-only\n", | 527 | printk ("mtd: partition \"%s\" doesn't end on an erase block -- force read-only\n", |
527 | parts[i].name); | 528 | parts[i].name); |
528 | } | 529 | } |
529 | 530 | ||
530 | /* copy oobinfo from master */ | 531 | /* copy oobinfo from master */ |
531 | memcpy(&slave->mtd.oobinfo, &master->oobinfo, sizeof(slave->mtd.oobinfo)); | 532 | memcpy(&slave->mtd.oobinfo, &master->oobinfo, sizeof(slave->mtd.oobinfo)); |
532 | 533 | ||
533 | if(parts[i].mtdp) | 534 | if(parts[i].mtdp) |
@@ -588,12 +589,12 @@ int deregister_mtd_parser(struct mtd_part_parser *p) | |||
588 | return 0; | 589 | return 0; |
589 | } | 590 | } |
590 | 591 | ||
591 | int parse_mtd_partitions(struct mtd_info *master, const char **types, | 592 | int parse_mtd_partitions(struct mtd_info *master, const char **types, |
592 | struct mtd_partition **pparts, unsigned long origin) | 593 | struct mtd_partition **pparts, unsigned long origin) |
593 | { | 594 | { |
594 | struct mtd_part_parser *parser; | 595 | struct mtd_part_parser *parser; |
595 | int ret = 0; | 596 | int ret = 0; |
596 | 597 | ||
597 | for ( ; ret <= 0 && *types; types++) { | 598 | for ( ; ret <= 0 && *types; types++) { |
598 | parser = get_partition_parser(*types); | 599 | parser = get_partition_parser(*types); |
599 | #ifdef CONFIG_KMOD | 600 | #ifdef CONFIG_KMOD |
@@ -607,7 +608,7 @@ int parse_mtd_partitions(struct mtd_info *master, const char **types, | |||
607 | } | 608 | } |
608 | ret = (*parser->parse_fn)(master, pparts, origin); | 609 | ret = (*parser->parse_fn)(master, pparts, origin); |
609 | if (ret > 0) { | 610 | if (ret > 0) { |
610 | printk(KERN_NOTICE "%d %s partitions found on MTD device %s\n", | 611 | printk(KERN_NOTICE "%d %s partitions found on MTD device %s\n", |
611 | ret, parser->name, master->name); | 612 | ret, parser->name, master->name); |
612 | } | 613 | } |
613 | put_partition_parser(parser); | 614 | put_partition_parser(parser); |