1
2
3
4
5
6
7
8
9
10#include <linux/kernel.h>
11#include <linux/module.h>
12#include <linux/random.h>
13#include <linux/hdreg.h>
14#include <linux/kthread.h>
15#include <linux/freezer.h>
16#include <linux/sysfs.h>
17#include <linux/bitops.h>
18#include <linux/slab.h>
19#include <linux/mtd/nand_ecc.h>
20#include "nand/sm_common.h"
21#include "sm_ftl.h"
22
23
24
25static struct workqueue_struct *cache_flush_workqueue;
26
27static int cache_timeout = 1000;
28module_param(cache_timeout, int, S_IRUGO);
29MODULE_PARM_DESC(cache_timeout,
30 "Timeout (in ms) for cache flush (1000 ms default");
31
32static int debug;
33module_param(debug, int, S_IRUGO | S_IWUSR);
34MODULE_PARM_DESC(debug, "Debug level (0-2)");
35
36
37
38struct sm_sysfs_attribute {
39 struct device_attribute dev_attr;
40 char *data;
41 int len;
42};
43
44static ssize_t sm_attr_show(struct device *dev, struct device_attribute *attr,
45 char *buf)
46{
47 struct sm_sysfs_attribute *sm_attr =
48 container_of(attr, struct sm_sysfs_attribute, dev_attr);
49
50 strncpy(buf, sm_attr->data, sm_attr->len);
51 return sm_attr->len;
52}
53
54
55#define NUM_ATTRIBUTES 1
56#define SM_CIS_VENDOR_OFFSET 0x59
57static struct attribute_group *sm_create_sysfs_attributes(struct sm_ftl *ftl)
58{
59 struct attribute_group *attr_group;
60 struct attribute **attributes;
61 struct sm_sysfs_attribute *vendor_attribute;
62 char *vendor;
63
64 vendor = kstrndup(ftl->cis_buffer + SM_CIS_VENDOR_OFFSET,
65 SM_SMALL_PAGE - SM_CIS_VENDOR_OFFSET, GFP_KERNEL);
66 if (!vendor)
67 goto error1;
68
69
70 vendor_attribute =
71 kzalloc(sizeof(struct sm_sysfs_attribute), GFP_KERNEL);
72 if (!vendor_attribute)
73 goto error2;
74
75 sysfs_attr_init(&vendor_attribute->dev_attr.attr);
76
77 vendor_attribute->data = vendor;
78 vendor_attribute->len = strlen(vendor);
79 vendor_attribute->dev_attr.attr.name = "vendor";
80 vendor_attribute->dev_attr.attr.mode = S_IRUGO;
81 vendor_attribute->dev_attr.show = sm_attr_show;
82
83
84
85 attributes = kzalloc(sizeof(struct attribute *) * (NUM_ATTRIBUTES + 1),
86 GFP_KERNEL);
87 if (!attributes)
88 goto error3;
89 attributes[0] = &vendor_attribute->dev_attr.attr;
90
91
92 attr_group = kzalloc(sizeof(struct attribute_group), GFP_KERNEL);
93 if (!attr_group)
94 goto error4;
95 attr_group->attrs = attributes;
96 return attr_group;
97error4:
98 kfree(attributes);
99error3:
100 kfree(vendor_attribute);
101error2:
102 kfree(vendor);
103error1:
104 return NULL;
105}
106
107static void sm_delete_sysfs_attributes(struct sm_ftl *ftl)
108{
109 struct attribute **attributes = ftl->disk_attributes->attrs;
110 int i;
111
112 for (i = 0; attributes[i] ; i++) {
113
114 struct device_attribute *dev_attr = container_of(attributes[i],
115 struct device_attribute, attr);
116
117 struct sm_sysfs_attribute *sm_attr =
118 container_of(dev_attr,
119 struct sm_sysfs_attribute, dev_attr);
120
121 kfree(sm_attr->data);
122 kfree(sm_attr);
123 }
124
125 kfree(ftl->disk_attributes->attrs);
126 kfree(ftl->disk_attributes);
127}
128
129
130
131
132static int sm_get_lba(uint8_t *lba)
133{
134
135 if ((lba[0] & 0xF8) != 0x10)
136 return -2;
137
138
139 if (hweight16(*(uint16_t *)lba) & 1)
140 return -2;
141
142 return (lba[1] >> 1) | ((lba[0] & 0x07) << 7);
143}
144
145
146
147
148
149
150
151static int sm_read_lba(struct sm_oob *oob)
152{
153 static const uint32_t erased_pattern[4] = {
154 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF };
155
156 uint16_t lba_test;
157 int lba;
158
159
160 if (!memcmp(oob, erased_pattern, SM_OOB_SIZE))
161 return -1;
162
163
164 lba_test = *(uint16_t *)oob->lba_copy1 ^ *(uint16_t*)oob->lba_copy2;
165 if (lba_test && !is_power_of_2(lba_test))
166 return -2;
167
168
169 lba = sm_get_lba(oob->lba_copy1);
170
171 if (lba == -2)
172 lba = sm_get_lba(oob->lba_copy2);
173
174 return lba;
175}
176
177static void sm_write_lba(struct sm_oob *oob, uint16_t lba)
178{
179 uint8_t tmp[2];
180
181 WARN_ON(lba >= 1000);
182
183 tmp[0] = 0x10 | ((lba >> 7) & 0x07);
184 tmp[1] = (lba << 1) & 0xFF;
185
186 if (hweight16(*(uint16_t *)tmp) & 0x01)
187 tmp[1] |= 1;
188
189 oob->lba_copy1[0] = oob->lba_copy2[0] = tmp[0];
190 oob->lba_copy1[1] = oob->lba_copy2[1] = tmp[1];
191}
192
193
194
195static loff_t sm_mkoffset(struct sm_ftl *ftl, int zone, int block, int boffset)
196{
197 WARN_ON(boffset & (SM_SECTOR_SIZE - 1));
198 WARN_ON(zone < 0 || zone >= ftl->zone_count);
199 WARN_ON(block >= ftl->zone_size);
200 WARN_ON(boffset >= ftl->block_size);
201
202 if (block == -1)
203 return -1;
204
205 return (zone * SM_MAX_ZONE_SIZE + block) * ftl->block_size + boffset;
206}
207
208
209static void sm_break_offset(struct sm_ftl *ftl, loff_t loffset,
210 int *zone, int *block, int *boffset)
211{
212 u64 offset = loffset;
213 *boffset = do_div(offset, ftl->block_size);
214 *block = do_div(offset, ftl->max_lba);
215 *zone = offset >= ftl->zone_count ? -1 : offset;
216}
217
218
219
220static int sm_correct_sector(uint8_t *buffer, struct sm_oob *oob)
221{
222 uint8_t ecc[3];
223
224 __nand_calculate_ecc(buffer, SM_SMALL_PAGE, ecc);
225 if (__nand_correct_data(buffer, ecc, oob->ecc1, SM_SMALL_PAGE) < 0)
226 return -EIO;
227
228 buffer += SM_SMALL_PAGE;
229
230 __nand_calculate_ecc(buffer, SM_SMALL_PAGE, ecc);
231 if (__nand_correct_data(buffer, ecc, oob->ecc2, SM_SMALL_PAGE) < 0)
232 return -EIO;
233 return 0;
234}
235
236
237static int sm_read_sector(struct sm_ftl *ftl,
238 int zone, int block, int boffset,
239 uint8_t *buffer, struct sm_oob *oob)
240{
241 struct mtd_info *mtd = ftl->trans->mtd;
242 struct mtd_oob_ops ops;
243 struct sm_oob tmp_oob;
244 int ret = -EIO;
245 int try = 0;
246
247
248 if (block == -1) {
249 memset(buffer, 0xFF, SM_SECTOR_SIZE);
250 return 0;
251 }
252
253
254 if (!oob)
255 oob = &tmp_oob;
256
257 ops.mode = ftl->smallpagenand ? MTD_OPS_RAW : MTD_OPS_PLACE_OOB;
258 ops.ooboffs = 0;
259 ops.ooblen = SM_OOB_SIZE;
260 ops.oobbuf = (void *)oob;
261 ops.len = SM_SECTOR_SIZE;
262 ops.datbuf = buffer;
263
264again:
265 if (try++) {
266
267
268 if (zone == 0 && block == ftl->cis_block && boffset ==
269 ftl->cis_boffset)
270 return ret;
271
272
273 if (try == 3 || sm_recheck_media(ftl))
274 return ret;
275 }
276
277
278
279 ret = mtd_read_oob(mtd, sm_mkoffset(ftl, zone, block, boffset), &ops);
280
281
282 if (ret != 0 && !mtd_is_bitflip_or_eccerr(ret)) {
283 dbg("read of block %d at zone %d, failed due to error (%d)",
284 block, zone, ret);
285 goto again;
286 }
287
288
289 if (oob->reserved != 0xFFFFFFFF && !is_power_of_2(~oob->reserved))
290 goto again;
291
292
293 WARN_ON(ops.oobretlen != SM_OOB_SIZE);
294 WARN_ON(buffer && ops.retlen != SM_SECTOR_SIZE);
295
296 if (!buffer)
297 return 0;
298
299
300 if (!sm_sector_valid(oob)) {
301 dbg("read of block %d at zone %d, failed because it is marked"
302 " as bad" , block, zone);
303 goto again;
304 }
305
306
307 if (mtd_is_eccerr(ret) ||
308 (ftl->smallpagenand && sm_correct_sector(buffer, oob))) {
309
310 dbg("read of block %d at zone %d, failed due to ECC error",
311 block, zone);
312 goto again;
313 }
314
315 return 0;
316}
317
318
319static int sm_write_sector(struct sm_ftl *ftl,
320 int zone, int block, int boffset,
321 uint8_t *buffer, struct sm_oob *oob)
322{
323 struct mtd_oob_ops ops;
324 struct mtd_info *mtd = ftl->trans->mtd;
325 int ret;
326
327 BUG_ON(ftl->readonly);
328
329 if (zone == 0 && (block == ftl->cis_block || block == 0)) {
330 dbg("attempted to write the CIS!");
331 return -EIO;
332 }
333
334 if (ftl->unstable)
335 return -EIO;
336
337 ops.mode = ftl->smallpagenand ? MTD_OPS_RAW : MTD_OPS_PLACE_OOB;
338 ops.len = SM_SECTOR_SIZE;
339 ops.datbuf = buffer;
340 ops.ooboffs = 0;
341 ops.ooblen = SM_OOB_SIZE;
342 ops.oobbuf = (void *)oob;
343
344 ret = mtd_write_oob(mtd, sm_mkoffset(ftl, zone, block, boffset), &ops);
345
346
347
348 if (ret) {
349 dbg("write to block %d at zone %d, failed with error %d",
350 block, zone, ret);
351
352 sm_recheck_media(ftl);
353 return ret;
354 }
355
356
357 WARN_ON(ops.oobretlen != SM_OOB_SIZE);
358 WARN_ON(buffer && ops.retlen != SM_SECTOR_SIZE);
359
360 return 0;
361}
362
363
364
365
366static int sm_write_block(struct sm_ftl *ftl, uint8_t *buf,
367 int zone, int block, int lba,
368 unsigned long invalid_bitmap)
369{
370 struct sm_oob oob;
371 int boffset;
372 int retry = 0;
373
374
375 memset(&oob, 0xFF, SM_OOB_SIZE);
376 sm_write_lba(&oob, lba);
377restart:
378 if (ftl->unstable)
379 return -EIO;
380
381 for (boffset = 0; boffset < ftl->block_size;
382 boffset += SM_SECTOR_SIZE) {
383
384 oob.data_status = 0xFF;
385
386 if (test_bit(boffset / SM_SECTOR_SIZE, &invalid_bitmap)) {
387
388 sm_printk("sector %d of block at LBA %d of zone %d"
389 " couldn't be read, marking it as invalid",
390 boffset / SM_SECTOR_SIZE, lba, zone);
391
392 oob.data_status = 0;
393 }
394
395 if (ftl->smallpagenand) {
396 __nand_calculate_ecc(buf + boffset,
397 SM_SMALL_PAGE, oob.ecc1);
398
399 __nand_calculate_ecc(buf + boffset + SM_SMALL_PAGE,
400 SM_SMALL_PAGE, oob.ecc2);
401 }
402 if (!sm_write_sector(ftl, zone, block, boffset,
403 buf + boffset, &oob))
404 continue;
405
406 if (!retry) {
407
408
409
410
411
412
413
414 if (sm_erase_block(ftl, zone, block, 0))
415 return -EIO;
416
417 retry = 1;
418 goto restart;
419 } else {
420 sm_mark_block_bad(ftl, zone, block);
421 return -EIO;
422 }
423 }
424 return 0;
425}
426
427
428
429static void sm_mark_block_bad(struct sm_ftl *ftl, int zone, int block)
430{
431 struct sm_oob oob;
432 int boffset;
433
434 memset(&oob, 0xFF, SM_OOB_SIZE);
435 oob.block_status = 0xF0;
436
437 if (ftl->unstable)
438 return;
439
440 if (sm_recheck_media(ftl))
441 return;
442
443 sm_printk("marking block %d of zone %d as bad", block, zone);
444
445
446
447
448 for (boffset = 0; boffset < ftl->block_size; boffset += SM_SECTOR_SIZE)
449 sm_write_sector(ftl, zone, block, boffset, NULL, &oob);
450}
451
452
453
454
455
456static int sm_erase_block(struct sm_ftl *ftl, int zone_num, uint16_t block,
457 int put_free)
458{
459 struct ftl_zone *zone = &ftl->zones[zone_num];
460 struct mtd_info *mtd = ftl->trans->mtd;
461 struct erase_info erase;
462
463 erase.mtd = mtd;
464 erase.callback = sm_erase_callback;
465 erase.addr = sm_mkoffset(ftl, zone_num, block, 0);
466 erase.len = ftl->block_size;
467 erase.priv = (u_long)ftl;
468
469 if (ftl->unstable)
470 return -EIO;
471
472 BUG_ON(ftl->readonly);
473
474 if (zone_num == 0 && (block == ftl->cis_block || block == 0)) {
475 sm_printk("attempted to erase the CIS!");
476 return -EIO;
477 }
478
479 if (mtd_erase(mtd, &erase)) {
480 sm_printk("erase of block %d in zone %d failed",
481 block, zone_num);
482 goto error;
483 }
484
485 if (erase.state == MTD_ERASE_PENDING)
486 wait_for_completion(&ftl->erase_completion);
487
488 if (erase.state != MTD_ERASE_DONE) {
489 sm_printk("erase of block %d in zone %d failed after wait",
490 block, zone_num);
491 goto error;
492 }
493
494 if (put_free)
495 kfifo_in(&zone->free_sectors,
496 (const unsigned char *)&block, sizeof(block));
497
498 return 0;
499error:
500 sm_mark_block_bad(ftl, zone_num, block);
501 return -EIO;
502}
503
504static void sm_erase_callback(struct erase_info *self)
505{
506 struct sm_ftl *ftl = (struct sm_ftl *)self->priv;
507 complete(&ftl->erase_completion);
508}
509
510
511static int sm_check_block(struct sm_ftl *ftl, int zone, int block)
512{
513 int boffset;
514 struct sm_oob oob;
515 int lbas[] = { -3, 0, 0, 0 };
516 int i = 0;
517 int test_lba;
518
519
520
521
522
523 for (boffset = 0; boffset < ftl->block_size;
524 boffset += SM_SECTOR_SIZE) {
525
526
527 if (sm_read_sector(ftl, zone, block, boffset, NULL, &oob))
528 return -2;
529
530 test_lba = sm_read_lba(&oob);
531
532 if (lbas[i] != test_lba)
533 lbas[++i] = test_lba;
534
535
536 if (i == 3)
537 return -EIO;
538 }
539
540
541 if (i == 2) {
542 sm_erase_block(ftl, zone, block, 1);
543 return 1;
544 }
545
546 return 0;
547}
548
549
550static const struct chs_entry chs_table[] = {
551 { 1, 125, 4, 4 },
552 { 2, 125, 4, 8 },
553 { 4, 250, 4, 8 },
554 { 8, 250, 4, 16 },
555 { 16, 500, 4, 16 },
556 { 32, 500, 8, 16 },
557 { 64, 500, 8, 32 },
558 { 128, 500, 16, 32 },
559 { 256, 1000, 16, 32 },
560 { 512, 1015, 32, 63 },
561 { 1024, 985, 33, 63 },
562 { 2048, 985, 33, 63 },
563 { 0 },
564};
565
566
567static const uint8_t cis_signature[] = {
568 0x01, 0x03, 0xD9, 0x01, 0xFF, 0x18, 0x02, 0xDF, 0x01, 0x20
569};
570
571
572static int sm_get_media_info(struct sm_ftl *ftl, struct mtd_info *mtd)
573{
574 int i;
575 int size_in_megs = mtd->size / (1024 * 1024);
576
577 ftl->readonly = mtd->type == MTD_ROM;
578
579
580 ftl->zone_count = 1;
581 ftl->smallpagenand = 0;
582
583 switch (size_in_megs) {
584 case 1:
585
586 ftl->zone_size = 256;
587 ftl->max_lba = 250;
588 ftl->block_size = 8 * SM_SECTOR_SIZE;
589 ftl->smallpagenand = 1;
590
591 break;
592 case 2:
593
594 if (mtd->writesize == SM_SMALL_PAGE) {
595 ftl->zone_size = 512;
596 ftl->max_lba = 500;
597 ftl->block_size = 8 * SM_SECTOR_SIZE;
598 ftl->smallpagenand = 1;
599
600 } else {
601
602 if (!ftl->readonly)
603 return -ENODEV;
604
605 ftl->zone_size = 256;
606 ftl->max_lba = 250;
607 ftl->block_size = 16 * SM_SECTOR_SIZE;
608 }
609 break;
610 case 4:
611
612 ftl->zone_size = 512;
613 ftl->max_lba = 500;
614 ftl->block_size = 16 * SM_SECTOR_SIZE;
615 break;
616 case 8:
617
618 ftl->zone_size = 1024;
619 ftl->max_lba = 1000;
620 ftl->block_size = 16 * SM_SECTOR_SIZE;
621 }
622
623
624
625 if (size_in_megs >= 16) {
626 ftl->zone_count = size_in_megs / 16;
627 ftl->zone_size = 1024;
628 ftl->max_lba = 1000;
629 ftl->block_size = 32 * SM_SECTOR_SIZE;
630 }
631
632
633 if (mtd->erasesize > ftl->block_size)
634 return -ENODEV;
635
636 if (mtd->writesize > SM_SECTOR_SIZE)
637 return -ENODEV;
638
639 if (ftl->smallpagenand && mtd->oobsize < SM_SMALL_OOB_SIZE)
640 return -ENODEV;
641
642 if (!ftl->smallpagenand && mtd->oobsize < SM_OOB_SIZE)
643 return -ENODEV;
644
645
646 if (!mtd_has_oob(mtd))
647 return -ENODEV;
648
649
650 for (i = 0 ; i < ARRAY_SIZE(chs_table) ; i++) {
651 if (chs_table[i].size == size_in_megs) {
652 ftl->cylinders = chs_table[i].cyl;
653 ftl->heads = chs_table[i].head;
654 ftl->sectors = chs_table[i].sec;
655 return 0;
656 }
657 }
658
659 sm_printk("media has unknown size : %dMiB", size_in_megs);
660 ftl->cylinders = 985;
661 ftl->heads = 33;
662 ftl->sectors = 63;
663 return 0;
664}
665
666
667static int sm_read_cis(struct sm_ftl *ftl)
668{
669 struct sm_oob oob;
670
671 if (sm_read_sector(ftl,
672 0, ftl->cis_block, ftl->cis_boffset, ftl->cis_buffer, &oob))
673 return -EIO;
674
675 if (!sm_sector_valid(&oob) || !sm_block_valid(&oob))
676 return -EIO;
677
678 if (!memcmp(ftl->cis_buffer + ftl->cis_page_offset,
679 cis_signature, sizeof(cis_signature))) {
680 return 0;
681 }
682
683 return -EIO;
684}
685
686
687static int sm_find_cis(struct sm_ftl *ftl)
688{
689 struct sm_oob oob;
690 int block, boffset;
691 int block_found = 0;
692 int cis_found = 0;
693
694
695 for (block = 0 ; block < ftl->zone_size - ftl->max_lba ; block++) {
696
697 if (sm_read_sector(ftl, 0, block, 0, NULL, &oob))
698 continue;
699
700 if (!sm_block_valid(&oob))
701 continue;
702 block_found = 1;
703 break;
704 }
705
706 if (!block_found)
707 return -EIO;
708
709
710 for (boffset = 0 ; boffset < ftl->block_size;
711 boffset += SM_SECTOR_SIZE) {
712
713 if (sm_read_sector(ftl, 0, block, boffset, NULL, &oob))
714 continue;
715
716 if (!sm_sector_valid(&oob))
717 continue;
718 break;
719 }
720
721 if (boffset == ftl->block_size)
722 return -EIO;
723
724 ftl->cis_block = block;
725 ftl->cis_boffset = boffset;
726 ftl->cis_page_offset = 0;
727
728 cis_found = !sm_read_cis(ftl);
729
730 if (!cis_found) {
731 ftl->cis_page_offset = SM_SMALL_PAGE;
732 cis_found = !sm_read_cis(ftl);
733 }
734
735 if (cis_found) {
736 dbg("CIS block found at offset %x",
737 block * ftl->block_size +
738 boffset + ftl->cis_page_offset);
739 return 0;
740 }
741 return -EIO;
742}
743
744
745static int sm_recheck_media(struct sm_ftl *ftl)
746{
747 if (sm_read_cis(ftl)) {
748
749 if (!ftl->unstable) {
750 sm_printk("media unstable, not allowing writes");
751 ftl->unstable = 1;
752 }
753 return -EIO;
754 }
755 return 0;
756}
757
758
759static int sm_init_zone(struct sm_ftl *ftl, int zone_num)
760{
761 struct ftl_zone *zone = &ftl->zones[zone_num];
762 struct sm_oob oob;
763 uint16_t block;
764 int lba;
765 int i = 0;
766 int len;
767
768 dbg("initializing zone %d", zone_num);
769
770
771 zone->lba_to_phys_table = kmalloc(ftl->max_lba * 2, GFP_KERNEL);
772
773 if (!zone->lba_to_phys_table)
774 return -ENOMEM;
775 memset(zone->lba_to_phys_table, -1, ftl->max_lba * 2);
776
777
778
779 if (kfifo_alloc(&zone->free_sectors, ftl->zone_size * 2, GFP_KERNEL)) {
780 kfree(zone->lba_to_phys_table);
781 return -ENOMEM;
782 }
783
784
785 for (block = 0 ; block < ftl->zone_size ; block++) {
786
787
788 if (zone_num == 0 && block <= ftl->cis_block)
789 continue;
790
791
792 if (sm_read_sector(ftl, zone_num, block, 0, NULL, &oob))
793 return -EIO;
794
795
796
797 if (sm_block_erased(&oob)) {
798 kfifo_in(&zone->free_sectors,
799 (unsigned char *)&block, 2);
800 continue;
801 }
802
803
804
805
806
807 if (!sm_block_valid(&oob)) {
808 dbg("PH %04d <-> <marked bad>", block);
809 continue;
810 }
811
812
813 lba = sm_read_lba(&oob);
814
815
816
817
818 if (lba == -2 || lba >= ftl->max_lba) {
819 dbg("PH %04d <-> LBA %04d(bad)", block, lba);
820 continue;
821 }
822
823
824
825
826 if (zone->lba_to_phys_table[lba] < 0) {
827 dbg_verbose("PH %04d <-> LBA %04d", block, lba);
828 zone->lba_to_phys_table[lba] = block;
829 continue;
830 }
831
832 sm_printk("collision"
833 " of LBA %d between blocks %d and %d in zone %d",
834 lba, zone->lba_to_phys_table[lba], block, zone_num);
835
836
837 if (sm_check_block(ftl, zone_num, block))
838 continue;
839
840
841 if (sm_check_block(ftl, zone_num,
842 zone->lba_to_phys_table[lba])) {
843 zone->lba_to_phys_table[lba] = block;
844 continue;
845 }
846
847
848
849
850
851 sm_printk("both blocks are valid, erasing the later");
852 sm_erase_block(ftl, zone_num, block, 1);
853 }
854
855 dbg("zone initialized");
856 zone->initialized = 1;
857
858
859
860 if (!kfifo_len(&zone->free_sectors)) {
861 sm_printk("no free blocks in zone %d", zone_num);
862 return 0;
863 }
864
865
866 get_random_bytes(&i, 2);
867 i %= (kfifo_len(&zone->free_sectors) / 2);
868
869 while (i--) {
870 len = kfifo_out(&zone->free_sectors,
871 (unsigned char *)&block, 2);
872 WARN_ON(len != 2);
873 kfifo_in(&zone->free_sectors, (const unsigned char *)&block, 2);
874 }
875 return 0;
876}
877
878
879static struct ftl_zone *sm_get_zone(struct sm_ftl *ftl, int zone_num)
880{
881 struct ftl_zone *zone;
882 int error;
883
884 BUG_ON(zone_num >= ftl->zone_count);
885 zone = &ftl->zones[zone_num];
886
887 if (!zone->initialized) {
888 error = sm_init_zone(ftl, zone_num);
889
890 if (error)
891 return ERR_PTR(error);
892 }
893 return zone;
894}
895
896
897
898
899
900static void sm_cache_init(struct sm_ftl *ftl)
901{
902 ftl->cache_data_invalid_bitmap = 0xFFFFFFFF;
903 ftl->cache_clean = 1;
904 ftl->cache_zone = -1;
905 ftl->cache_block = -1;
906
907}
908
909
910static void sm_cache_put(struct sm_ftl *ftl, char *buffer, int boffset)
911{
912 memcpy(ftl->cache_data + boffset, buffer, SM_SECTOR_SIZE);
913 clear_bit(boffset / SM_SECTOR_SIZE, &ftl->cache_data_invalid_bitmap);
914 ftl->cache_clean = 0;
915}
916
917
918static int sm_cache_get(struct sm_ftl *ftl, char *buffer, int boffset)
919{
920 if (test_bit(boffset / SM_SECTOR_SIZE,
921 &ftl->cache_data_invalid_bitmap))
922 return -1;
923
924 memcpy(buffer, ftl->cache_data + boffset, SM_SECTOR_SIZE);
925 return 0;
926}
927
928
929static int sm_cache_flush(struct sm_ftl *ftl)
930{
931 struct ftl_zone *zone;
932
933 int sector_num;
934 uint16_t write_sector;
935 int zone_num = ftl->cache_zone;
936 int block_num;
937
938 if (ftl->cache_clean)
939 return 0;
940
941 if (ftl->unstable)
942 return -EIO;
943
944 BUG_ON(zone_num < 0);
945 zone = &ftl->zones[zone_num];
946 block_num = zone->lba_to_phys_table[ftl->cache_block];
947
948
949
950 for_each_set_bit(sector_num, &ftl->cache_data_invalid_bitmap,
951 ftl->block_size / SM_SECTOR_SIZE) {
952
953 if (!sm_read_sector(ftl,
954 zone_num, block_num, sector_num * SM_SECTOR_SIZE,
955 ftl->cache_data + sector_num * SM_SECTOR_SIZE, NULL))
956 clear_bit(sector_num,
957 &ftl->cache_data_invalid_bitmap);
958 }
959restart:
960
961 if (ftl->unstable)
962 return -EIO;
963
964
965
966
967
968 if (kfifo_out(&zone->free_sectors,
969 (unsigned char *)&write_sector, 2) != 2) {
970 dbg("no free sectors for write!");
971 return -EIO;
972 }
973
974
975 if (sm_write_block(ftl, ftl->cache_data, zone_num, write_sector,
976 ftl->cache_block, ftl->cache_data_invalid_bitmap))
977 goto restart;
978
979
980 zone->lba_to_phys_table[ftl->cache_block] = write_sector;
981
982
983 if (block_num > 0)
984 sm_erase_block(ftl, zone_num, block_num, 1);
985
986 sm_cache_init(ftl);
987 return 0;
988}
989
990
991
992static void sm_cache_flush_timer(unsigned long data)
993{
994 struct sm_ftl *ftl = (struct sm_ftl *)data;
995 queue_work(cache_flush_workqueue, &ftl->flush_work);
996}
997
998
999static void sm_cache_flush_work(struct work_struct *work)
1000{
1001 struct sm_ftl *ftl = container_of(work, struct sm_ftl, flush_work);
1002 mutex_lock(&ftl->mutex);
1003 sm_cache_flush(ftl);
1004 mutex_unlock(&ftl->mutex);
1005 return;
1006}
1007
1008
1009
1010
1011static int sm_read(struct mtd_blktrans_dev *dev,
1012 unsigned long sect_no, char *buf)
1013{
1014 struct sm_ftl *ftl = dev->priv;
1015 struct ftl_zone *zone;
1016 int error = 0, in_cache = 0;
1017 int zone_num, block, boffset;
1018
1019 sm_break_offset(ftl, sect_no << 9, &zone_num, &block, &boffset);
1020 mutex_lock(&ftl->mutex);
1021
1022
1023 zone = sm_get_zone(ftl, zone_num);
1024 if (IS_ERR(zone)) {
1025 error = PTR_ERR(zone);
1026 goto unlock;
1027 }
1028
1029
1030 if (ftl->cache_zone == zone_num && ftl->cache_block == block) {
1031 in_cache = 1;
1032 if (!sm_cache_get(ftl, buf, boffset))
1033 goto unlock;
1034 }
1035
1036
1037 block = zone->lba_to_phys_table[block];
1038
1039 if (block == -1) {
1040 memset(buf, 0xFF, SM_SECTOR_SIZE);
1041 goto unlock;
1042 }
1043
1044 if (sm_read_sector(ftl, zone_num, block, boffset, buf, NULL)) {
1045 error = -EIO;
1046 goto unlock;
1047 }
1048
1049 if (in_cache)
1050 sm_cache_put(ftl, buf, boffset);
1051unlock:
1052 mutex_unlock(&ftl->mutex);
1053 return error;
1054}
1055
1056
1057static int sm_write(struct mtd_blktrans_dev *dev,
1058 unsigned long sec_no, char *buf)
1059{
1060 struct sm_ftl *ftl = dev->priv;
1061 struct ftl_zone *zone;
1062 int error = 0, zone_num, block, boffset;
1063
1064 BUG_ON(ftl->readonly);
1065 sm_break_offset(ftl, sec_no << 9, &zone_num, &block, &boffset);
1066
1067
1068 del_timer(&ftl->timer);
1069 mutex_lock(&ftl->mutex);
1070
1071 zone = sm_get_zone(ftl, zone_num);
1072 if (IS_ERR(zone)) {
1073 error = PTR_ERR(zone);
1074 goto unlock;
1075 }
1076
1077
1078 if (ftl->cache_block != block || ftl->cache_zone != zone_num) {
1079
1080 error = sm_cache_flush(ftl);
1081 if (error)
1082 goto unlock;
1083
1084 ftl->cache_block = block;
1085 ftl->cache_zone = zone_num;
1086 }
1087
1088 sm_cache_put(ftl, buf, boffset);
1089unlock:
1090 mod_timer(&ftl->timer, jiffies + msecs_to_jiffies(cache_timeout));
1091 mutex_unlock(&ftl->mutex);
1092 return error;
1093}
1094
1095
1096static int sm_flush(struct mtd_blktrans_dev *dev)
1097{
1098 struct sm_ftl *ftl = dev->priv;
1099 int retval;
1100
1101 mutex_lock(&ftl->mutex);
1102 retval = sm_cache_flush(ftl);
1103 mutex_unlock(&ftl->mutex);
1104 return retval;
1105}
1106
1107
1108static void sm_release(struct mtd_blktrans_dev *dev)
1109{
1110 struct sm_ftl *ftl = dev->priv;
1111
1112 mutex_lock(&ftl->mutex);
1113 del_timer_sync(&ftl->timer);
1114 cancel_work_sync(&ftl->flush_work);
1115 sm_cache_flush(ftl);
1116 mutex_unlock(&ftl->mutex);
1117}
1118
1119
1120static int sm_getgeo(struct mtd_blktrans_dev *dev, struct hd_geometry *geo)
1121{
1122 struct sm_ftl *ftl = dev->priv;
1123 geo->heads = ftl->heads;
1124 geo->sectors = ftl->sectors;
1125 geo->cylinders = ftl->cylinders;
1126 return 0;
1127}
1128
1129
1130static void sm_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
1131{
1132 struct mtd_blktrans_dev *trans;
1133 struct sm_ftl *ftl;
1134
1135
1136 ftl = kzalloc(sizeof(struct sm_ftl), GFP_KERNEL);
1137 if (!ftl)
1138 goto error1;
1139
1140
1141 mutex_init(&ftl->mutex);
1142 setup_timer(&ftl->timer, sm_cache_flush_timer, (unsigned long)ftl);
1143 INIT_WORK(&ftl->flush_work, sm_cache_flush_work);
1144 init_completion(&ftl->erase_completion);
1145
1146
1147 if (sm_get_media_info(ftl, mtd)) {
1148 dbg("found unsupported mtd device, aborting");
1149 goto error2;
1150 }
1151
1152
1153
1154 ftl->cis_buffer = kzalloc(SM_SECTOR_SIZE, GFP_KERNEL);
1155 if (!ftl->cis_buffer)
1156 goto error2;
1157
1158
1159 ftl->zones = kzalloc(sizeof(struct ftl_zone) * ftl->zone_count,
1160 GFP_KERNEL);
1161 if (!ftl->zones)
1162 goto error3;
1163
1164
1165 ftl->cache_data = kzalloc(ftl->block_size, GFP_KERNEL);
1166
1167 if (!ftl->cache_data)
1168 goto error4;
1169
1170 sm_cache_init(ftl);
1171
1172
1173
1174 trans = kzalloc(sizeof(struct mtd_blktrans_dev), GFP_KERNEL);
1175 if (!trans)
1176 goto error5;
1177
1178 ftl->trans = trans;
1179 trans->priv = ftl;
1180
1181 trans->tr = tr;
1182 trans->mtd = mtd;
1183 trans->devnum = -1;
1184 trans->size = (ftl->block_size * ftl->max_lba * ftl->zone_count) >> 9;
1185 trans->readonly = ftl->readonly;
1186
1187 if (sm_find_cis(ftl)) {
1188 dbg("CIS not found on mtd device, aborting");
1189 goto error6;
1190 }
1191
1192 ftl->disk_attributes = sm_create_sysfs_attributes(ftl);
1193 if (!ftl->disk_attributes)
1194 goto error6;
1195 trans->disk_attributes = ftl->disk_attributes;
1196
1197 sm_printk("Found %d MiB xD/SmartMedia FTL on mtd%d",
1198 (int)(mtd->size / (1024 * 1024)), mtd->index);
1199
1200 dbg("FTL layout:");
1201 dbg("%d zone(s), each consists of %d blocks (+%d spares)",
1202 ftl->zone_count, ftl->max_lba,
1203 ftl->zone_size - ftl->max_lba);
1204 dbg("each block consists of %d bytes",
1205 ftl->block_size);
1206
1207
1208
1209 if (add_mtd_blktrans_dev(trans)) {
1210 dbg("error in mtdblktrans layer");
1211 goto error6;
1212 }
1213 return;
1214error6:
1215 kfree(trans);
1216error5:
1217 kfree(ftl->cache_data);
1218error4:
1219 kfree(ftl->zones);
1220error3:
1221 kfree(ftl->cis_buffer);
1222error2:
1223 kfree(ftl);
1224error1:
1225 return;
1226}
1227
1228
1229static void sm_remove_dev(struct mtd_blktrans_dev *dev)
1230{
1231 struct sm_ftl *ftl = dev->priv;
1232 int i;
1233
1234 del_mtd_blktrans_dev(dev);
1235 ftl->trans = NULL;
1236
1237 for (i = 0 ; i < ftl->zone_count; i++) {
1238
1239 if (!ftl->zones[i].initialized)
1240 continue;
1241
1242 kfree(ftl->zones[i].lba_to_phys_table);
1243 kfifo_free(&ftl->zones[i].free_sectors);
1244 }
1245
1246 sm_delete_sysfs_attributes(ftl);
1247 kfree(ftl->cis_buffer);
1248 kfree(ftl->zones);
1249 kfree(ftl->cache_data);
1250 kfree(ftl);
1251}
1252
1253static struct mtd_blktrans_ops sm_ftl_ops = {
1254 .name = "smblk",
1255 .major = 0,
1256 .part_bits = SM_FTL_PARTN_BITS,
1257 .blksize = SM_SECTOR_SIZE,
1258 .getgeo = sm_getgeo,
1259
1260 .add_mtd = sm_add_mtd,
1261 .remove_dev = sm_remove_dev,
1262
1263 .readsect = sm_read,
1264 .writesect = sm_write,
1265
1266 .flush = sm_flush,
1267 .release = sm_release,
1268
1269 .owner = THIS_MODULE,
1270};
1271
1272static __init int sm_module_init(void)
1273{
1274 int error = 0;
1275
1276 cache_flush_workqueue = create_freezable_workqueue("smflush");
1277 if (!cache_flush_workqueue)
1278 return -ENOMEM;
1279
1280 error = register_mtd_blktrans(&sm_ftl_ops);
1281 if (error)
1282 destroy_workqueue(cache_flush_workqueue);
1283 return error;
1284
1285}
1286
1287static void __exit sm_module_exit(void)
1288{
1289 destroy_workqueue(cache_flush_workqueue);
1290 deregister_mtd_blktrans(&sm_ftl_ops);
1291}
1292
1293module_init(sm_module_init);
1294module_exit(sm_module_exit);
1295
1296MODULE_LICENSE("GPL");
1297MODULE_AUTHOR("Maxim Levitsky <maximlevitsky@gmail.com>");
1298MODULE_DESCRIPTION("Smartmedia/xD mtd translation layer");
1299