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