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