Lines Matching refs:ftl

57 struct attribute_group *sm_create_sysfs_attributes(struct sm_ftl *ftl)  in sm_create_sysfs_attributes()  argument
63 int vendor_len = strnlen(ftl->cis_buffer + SM_CIS_VENDOR_OFFSET, in sm_create_sysfs_attributes()
69 memcpy(vendor, ftl->cis_buffer + SM_CIS_VENDOR_OFFSET, vendor_len); in sm_create_sysfs_attributes()
110 void sm_delete_sysfs_attributes(struct sm_ftl *ftl) in sm_delete_sysfs_attributes() argument
112 struct attribute **attributes = ftl->disk_attributes->attrs; in sm_delete_sysfs_attributes()
128 kfree(ftl->disk_attributes->attrs); in sm_delete_sysfs_attributes()
129 kfree(ftl->disk_attributes); in sm_delete_sysfs_attributes()
198 static loff_t sm_mkoffset(struct sm_ftl *ftl, int zone, int block, int boffset) in sm_mkoffset() argument
201 WARN_ON(zone < 0 || zone >= ftl->zone_count); in sm_mkoffset()
202 WARN_ON(block >= ftl->zone_size); in sm_mkoffset()
203 WARN_ON(boffset >= ftl->block_size); in sm_mkoffset()
208 return (zone * SM_MAX_ZONE_SIZE + block) * ftl->block_size + boffset; in sm_mkoffset()
212 static void sm_break_offset(struct sm_ftl *ftl, loff_t offset, in sm_break_offset() argument
215 *boffset = do_div(offset, ftl->block_size); in sm_break_offset()
216 *block = do_div(offset, ftl->max_lba); in sm_break_offset()
217 *zone = offset >= ftl->zone_count ? -1 : offset; in sm_break_offset()
239 static int sm_read_sector(struct sm_ftl *ftl, in sm_read_sector() argument
243 struct mtd_info *mtd = ftl->trans->mtd; in sm_read_sector()
259 ops.mode = ftl->smallpagenand ? MTD_OOB_RAW : MTD_OOB_PLACE; in sm_read_sector()
270 if (zone == 0 && block == ftl->cis_block && boffset == in sm_read_sector()
271 ftl->cis_boffset) in sm_read_sector()
275 if (try == 3 || sm_recheck_media(ftl)) in sm_read_sector()
281 ret = mtd->read_oob(mtd, sm_mkoffset(ftl, zone, block, boffset), &ops); in sm_read_sector()
310 (ftl->smallpagenand && sm_correct_sector(buffer, oob))) { in sm_read_sector()
321 static int sm_write_sector(struct sm_ftl *ftl, in sm_write_sector() argument
326 struct mtd_info *mtd = ftl->trans->mtd; in sm_write_sector()
329 BUG_ON(ftl->readonly); in sm_write_sector()
331 if (zone == 0 && (block == ftl->cis_block || block == 0)) { in sm_write_sector()
336 if (ftl->unstable) in sm_write_sector()
339 ops.mode = ftl->smallpagenand ? MTD_OOB_RAW : MTD_OOB_PLACE; in sm_write_sector()
346 ret = mtd->write_oob(mtd, sm_mkoffset(ftl, zone, block, boffset), &ops); in sm_write_sector()
355 sm_recheck_media(ftl); in sm_write_sector()
369 static int sm_write_block(struct sm_ftl *ftl, uint8_t *buf, in sm_write_block() argument
381 if (ftl->unstable) in sm_write_block()
384 for (boffset = 0; boffset < ftl->block_size; in sm_write_block()
398 if (ftl->smallpagenand) { in sm_write_block()
405 if (!sm_write_sector(ftl, zone, block, boffset, in sm_write_block()
417 if (sm_erase_block(ftl, zone, block, 0)) in sm_write_block()
423 sm_mark_block_bad(ftl, zone, block); in sm_write_block()
432 static void sm_mark_block_bad(struct sm_ftl *ftl, int zone, int block) in sm_mark_block_bad() argument
440 if (ftl->unstable) in sm_mark_block_bad()
443 if (sm_recheck_media(ftl)) in sm_mark_block_bad()
451 for (boffset = 0; boffset < ftl->block_size; boffset += SM_SECTOR_SIZE) in sm_mark_block_bad()
452 sm_write_sector(ftl, zone, block, boffset, NULL, &oob); in sm_mark_block_bad()
459 static int sm_erase_block(struct sm_ftl *ftl, int zone_num, uint16_t block, in sm_erase_block() argument
462 struct ftl_zone *zone = &ftl->zones[zone_num]; in sm_erase_block()
463 struct mtd_info *mtd = ftl->trans->mtd; in sm_erase_block()
468 erase.addr = sm_mkoffset(ftl, zone_num, block, 0); in sm_erase_block()
469 erase.len = ftl->block_size; in sm_erase_block()
470 erase.priv = (u_long)ftl; in sm_erase_block()
472 if (ftl->unstable) in sm_erase_block()
475 BUG_ON(ftl->readonly); in sm_erase_block()
477 if (zone_num == 0 && (block == ftl->cis_block || block == 0)) { in sm_erase_block()
489 wait_for_completion(&ftl->erase_completion); in sm_erase_block()
503 sm_mark_block_bad(ftl, zone_num, block); in sm_erase_block()
509 struct sm_ftl *ftl = (struct sm_ftl *)self->priv; in sm_erase_callback() local
510 complete(&ftl->erase_completion); in sm_erase_callback()
514 static int sm_check_block(struct sm_ftl *ftl, int zone, int block) in sm_check_block() argument
526 for (boffset = 0; boffset < ftl->block_size; in sm_check_block()
530 if (sm_read_sector(ftl, zone, block, boffset, NULL, &oob)) in sm_check_block()
545 sm_erase_block(ftl, zone, block, 1); in sm_check_block()
575 int sm_get_media_info(struct sm_ftl *ftl, struct mtd_info *mtd) in sm_get_media_info() argument
580 ftl->readonly = mtd->type == MTD_ROM; in sm_get_media_info()
583 ftl->zone_count = 1; in sm_get_media_info()
584 ftl->smallpagenand = 0; in sm_get_media_info()
589 ftl->zone_size = 256; in sm_get_media_info()
590 ftl->max_lba = 250; in sm_get_media_info()
591 ftl->block_size = 8 * SM_SECTOR_SIZE; in sm_get_media_info()
592 ftl->smallpagenand = 1; in sm_get_media_info()
598 ftl->zone_size = 512; in sm_get_media_info()
599 ftl->max_lba = 500; in sm_get_media_info()
600 ftl->block_size = 8 * SM_SECTOR_SIZE; in sm_get_media_info()
601 ftl->smallpagenand = 1; in sm_get_media_info()
605 if (!ftl->readonly) in sm_get_media_info()
608 ftl->zone_size = 256; in sm_get_media_info()
609 ftl->max_lba = 250; in sm_get_media_info()
610 ftl->block_size = 16 * SM_SECTOR_SIZE; in sm_get_media_info()
615 ftl->zone_size = 512; in sm_get_media_info()
616 ftl->max_lba = 500; in sm_get_media_info()
617 ftl->block_size = 16 * SM_SECTOR_SIZE; in sm_get_media_info()
621 ftl->zone_size = 1024; in sm_get_media_info()
622 ftl->max_lba = 1000; in sm_get_media_info()
623 ftl->block_size = 16 * SM_SECTOR_SIZE; in sm_get_media_info()
629 ftl->zone_count = size_in_megs / 16; in sm_get_media_info()
630 ftl->zone_size = 1024; in sm_get_media_info()
631 ftl->max_lba = 1000; in sm_get_media_info()
632 ftl->block_size = 32 * SM_SECTOR_SIZE; in sm_get_media_info()
636 if (mtd->erasesize > ftl->block_size) in sm_get_media_info()
642 if (ftl->smallpagenand && mtd->oobsize < SM_SMALL_OOB_SIZE) in sm_get_media_info()
645 if (!ftl->smallpagenand && mtd->oobsize < SM_OOB_SIZE) in sm_get_media_info()
655 ftl->cylinders = chs_table[i].cyl; in sm_get_media_info()
656 ftl->heads = chs_table[i].head; in sm_get_media_info()
657 ftl->sectors = chs_table[i].sec; in sm_get_media_info()
663 ftl->cylinders = 985; in sm_get_media_info()
664 ftl->heads = 33; in sm_get_media_info()
665 ftl->sectors = 63; in sm_get_media_info()
670 static int sm_read_cis(struct sm_ftl *ftl) in sm_read_cis() argument
674 if (sm_read_sector(ftl, in sm_read_cis()
675 0, ftl->cis_block, ftl->cis_boffset, ftl->cis_buffer, &oob)) in sm_read_cis()
681 if (!memcmp(ftl->cis_buffer + ftl->cis_page_offset, in sm_read_cis()
690 static int sm_find_cis(struct sm_ftl *ftl) in sm_find_cis() argument
698 for (block = 0 ; block < ftl->zone_size - ftl->max_lba ; block++) { in sm_find_cis()
700 if (sm_read_sector(ftl, 0, block, 0, NULL, &oob)) in sm_find_cis()
713 for (boffset = 0 ; boffset < ftl->block_size; in sm_find_cis()
716 if (sm_read_sector(ftl, 0, block, boffset, NULL, &oob)) in sm_find_cis()
724 if (boffset == ftl->block_size) in sm_find_cis()
727 ftl->cis_block = block; in sm_find_cis()
728 ftl->cis_boffset = boffset; in sm_find_cis()
729 ftl->cis_page_offset = 0; in sm_find_cis()
731 cis_found = !sm_read_cis(ftl); in sm_find_cis()
734 ftl->cis_page_offset = SM_SMALL_PAGE; in sm_find_cis()
735 cis_found = !sm_read_cis(ftl); in sm_find_cis()
740 block * ftl->block_size + in sm_find_cis()
741 boffset + ftl->cis_page_offset); in sm_find_cis()
748 static int sm_recheck_media(struct sm_ftl *ftl) in sm_recheck_media() argument
750 if (sm_read_cis(ftl)) { in sm_recheck_media()
752 if (!ftl->unstable) { in sm_recheck_media()
754 ftl->unstable = 1; in sm_recheck_media()
762 static int sm_init_zone(struct sm_ftl *ftl, int zone_num) in sm_init_zone() argument
764 struct ftl_zone *zone = &ftl->zones[zone_num]; in sm_init_zone()
774 zone->lba_to_phys_table = kmalloc(ftl->max_lba * 2, GFP_KERNEL); in sm_init_zone()
778 memset(zone->lba_to_phys_table, -1, ftl->max_lba * 2); in sm_init_zone()
782 if (kfifo_alloc(&zone->free_sectors, ftl->zone_size * 2, GFP_KERNEL)) { in sm_init_zone()
788 for (block = 0 ; block < ftl->zone_size ; block++) { in sm_init_zone()
791 if (zone_num == 0 && block <= ftl->cis_block) in sm_init_zone()
795 if (sm_read_sector(ftl, zone_num, block, 0, NULL, &oob)) in sm_init_zone()
821 if (lba == -2 || lba >= ftl->max_lba) { in sm_init_zone()
840 if (sm_check_block(ftl, zone_num, block)) in sm_init_zone()
844 if (sm_check_block(ftl, zone_num, in sm_init_zone()
855 sm_erase_block(ftl, zone_num, block, 1); in sm_init_zone()
882 struct ftl_zone *sm_get_zone(struct sm_ftl *ftl, int zone_num) in sm_get_zone() argument
887 BUG_ON(zone_num >= ftl->zone_count); in sm_get_zone()
888 zone = &ftl->zones[zone_num]; in sm_get_zone()
891 error = sm_init_zone(ftl, zone_num); in sm_get_zone()
903 void sm_cache_init(struct sm_ftl *ftl) in sm_cache_init() argument
905 ftl->cache_data_invalid_bitmap = 0xFFFFFFFF; in sm_cache_init()
906 ftl->cache_clean = 1; in sm_cache_init()
907 ftl->cache_zone = -1; in sm_cache_init()
908 ftl->cache_block = -1; in sm_cache_init()
913 void sm_cache_put(struct sm_ftl *ftl, char *buffer, int boffset) in sm_cache_put() argument
915 memcpy(ftl->cache_data + boffset, buffer, SM_SECTOR_SIZE); in sm_cache_put()
916 clear_bit(boffset / SM_SECTOR_SIZE, &ftl->cache_data_invalid_bitmap); in sm_cache_put()
917 ftl->cache_clean = 0; in sm_cache_put()
921 int sm_cache_get(struct sm_ftl *ftl, char *buffer, int boffset) in sm_cache_get() argument
924 &ftl->cache_data_invalid_bitmap)) in sm_cache_get()
927 memcpy(buffer, ftl->cache_data + boffset, SM_SECTOR_SIZE); in sm_cache_get()
932 int sm_cache_flush(struct sm_ftl *ftl) in sm_cache_flush() argument
938 int zone_num = ftl->cache_zone; in sm_cache_flush()
941 if (ftl->cache_clean) in sm_cache_flush()
944 if (ftl->unstable) in sm_cache_flush()
948 zone = &ftl->zones[zone_num]; in sm_cache_flush()
949 block_num = zone->lba_to_phys_table[ftl->cache_block]; in sm_cache_flush()
953 for_each_set_bit(sector_num, &ftl->cache_data_invalid_bitmap, in sm_cache_flush()
954 ftl->block_size / SM_SECTOR_SIZE) { in sm_cache_flush()
956 if (!sm_read_sector(ftl, in sm_cache_flush()
958 ftl->cache_data + sector_num * SM_SECTOR_SIZE, NULL)) in sm_cache_flush()
960 &ftl->cache_data_invalid_bitmap); in sm_cache_flush()
964 if (ftl->unstable) in sm_cache_flush()
978 if (sm_write_block(ftl, ftl->cache_data, zone_num, write_sector, in sm_cache_flush()
979 ftl->cache_block, ftl->cache_data_invalid_bitmap)) in sm_cache_flush()
983 zone->lba_to_phys_table[ftl->cache_block] = write_sector; in sm_cache_flush()
987 sm_erase_block(ftl, zone_num, block_num, 1); in sm_cache_flush()
989 sm_cache_init(ftl); in sm_cache_flush()
997 struct sm_ftl *ftl = (struct sm_ftl *)data; in sm_cache_flush_timer() local
998 queue_work(cache_flush_workqueue, &ftl->flush_work); in sm_cache_flush_timer()
1004 struct sm_ftl *ftl = container_of(work, struct sm_ftl, flush_work); in sm_cache_flush_work() local
1005 mutex_lock(&ftl->mutex); in sm_cache_flush_work()
1006 sm_cache_flush(ftl); in sm_cache_flush_work()
1007 mutex_unlock(&ftl->mutex); in sm_cache_flush_work()
1017 struct sm_ftl *ftl = dev->priv; in sm_read() local
1022 sm_break_offset(ftl, sect_no << 9, &zone_num, &block, &boffset); in sm_read()
1023 mutex_lock(&ftl->mutex); in sm_read()
1026 zone = sm_get_zone(ftl, zone_num); in sm_read()
1033 if (ftl->cache_zone == zone_num && ftl->cache_block == block) { in sm_read()
1035 if (!sm_cache_get(ftl, buf, boffset)) in sm_read()
1047 if (sm_read_sector(ftl, zone_num, block, boffset, buf, NULL)) { in sm_read()
1053 sm_cache_put(ftl, buf, boffset); in sm_read()
1055 mutex_unlock(&ftl->mutex); in sm_read()
1063 struct sm_ftl *ftl = dev->priv; in sm_write() local
1067 BUG_ON(ftl->readonly); in sm_write()
1068 sm_break_offset(ftl, sec_no << 9, &zone_num, &block, &boffset); in sm_write()
1071 del_timer(&ftl->timer); in sm_write()
1072 mutex_lock(&ftl->mutex); in sm_write()
1074 zone = sm_get_zone(ftl, zone_num); in sm_write()
1081 if (ftl->cache_block != block || ftl->cache_zone != zone_num) { in sm_write()
1083 error = sm_cache_flush(ftl); in sm_write()
1087 ftl->cache_block = block; in sm_write()
1088 ftl->cache_zone = zone_num; in sm_write()
1091 sm_cache_put(ftl, buf, boffset); in sm_write()
1093 mod_timer(&ftl->timer, jiffies + msecs_to_jiffies(cache_timeout)); in sm_write()
1094 mutex_unlock(&ftl->mutex); in sm_write()
1101 struct sm_ftl *ftl = dev->priv; in sm_flush() local
1104 mutex_lock(&ftl->mutex); in sm_flush()
1105 retval = sm_cache_flush(ftl); in sm_flush()
1106 mutex_unlock(&ftl->mutex); in sm_flush()
1113 struct sm_ftl *ftl = dev->priv; in sm_release() local
1115 mutex_lock(&ftl->mutex); in sm_release()
1116 del_timer_sync(&ftl->timer); in sm_release()
1117 cancel_work_sync(&ftl->flush_work); in sm_release()
1118 sm_cache_flush(ftl); in sm_release()
1119 mutex_unlock(&ftl->mutex); in sm_release()
1126 struct sm_ftl *ftl = dev->priv; in sm_getgeo() local
1127 geo->heads = ftl->heads; in sm_getgeo()
1128 geo->sectors = ftl->sectors; in sm_getgeo()
1129 geo->cylinders = ftl->cylinders; in sm_getgeo()
1137 struct sm_ftl *ftl; in sm_add_mtd() local
1140 ftl = kzalloc(sizeof(struct sm_ftl), GFP_KERNEL); in sm_add_mtd()
1141 if (!ftl) in sm_add_mtd()
1145 mutex_init(&ftl->mutex); in sm_add_mtd()
1146 setup_timer(&ftl->timer, sm_cache_flush_timer, (unsigned long)ftl); in sm_add_mtd()
1147 INIT_WORK(&ftl->flush_work, sm_cache_flush_work); in sm_add_mtd()
1148 init_completion(&ftl->erase_completion); in sm_add_mtd()
1151 if (sm_get_media_info(ftl, mtd)) { in sm_add_mtd()
1158 ftl->cis_buffer = kzalloc(SM_SECTOR_SIZE, GFP_KERNEL); in sm_add_mtd()
1159 if (!ftl->cis_buffer) in sm_add_mtd()
1163 ftl->zones = kzalloc(sizeof(struct ftl_zone) * ftl->zone_count, in sm_add_mtd()
1165 if (!ftl->zones) in sm_add_mtd()
1169 ftl->cache_data = kzalloc(ftl->block_size, GFP_KERNEL); in sm_add_mtd()
1171 if (!ftl->cache_data) in sm_add_mtd()
1174 sm_cache_init(ftl); in sm_add_mtd()
1182 ftl->trans = trans; in sm_add_mtd()
1183 trans->priv = ftl; in sm_add_mtd()
1188 trans->size = (ftl->block_size * ftl->max_lba * ftl->zone_count) >> 9; in sm_add_mtd()
1189 trans->readonly = ftl->readonly; in sm_add_mtd()
1191 if (sm_find_cis(ftl)) { in sm_add_mtd()
1196 ftl->disk_attributes = sm_create_sysfs_attributes(ftl); in sm_add_mtd()
1197 if (!ftl->disk_attributes) in sm_add_mtd()
1199 trans->disk_attributes = ftl->disk_attributes; in sm_add_mtd()
1206 ftl->zone_count, ftl->max_lba, in sm_add_mtd()
1207 ftl->zone_size - ftl->max_lba); in sm_add_mtd()
1209 ftl->block_size); in sm_add_mtd()
1221 kfree(ftl->cache_data); in sm_add_mtd()
1223 kfree(ftl->zones); in sm_add_mtd()
1225 kfree(ftl->cis_buffer); in sm_add_mtd()
1227 kfree(ftl); in sm_add_mtd()
1235 struct sm_ftl *ftl = dev->priv; in sm_remove_dev() local
1239 ftl->trans = NULL; in sm_remove_dev()
1241 for (i = 0 ; i < ftl->zone_count; i++) { in sm_remove_dev()
1243 if (!ftl->zones[i].initialized) in sm_remove_dev()
1246 kfree(ftl->zones[i].lba_to_phys_table); in sm_remove_dev()
1247 kfifo_free(&ftl->zones[i].free_sectors); in sm_remove_dev()
1250 sm_delete_sysfs_attributes(ftl); in sm_remove_dev()
1251 kfree(ftl->cis_buffer); in sm_remove_dev()
1252 kfree(ftl->zones); in sm_remove_dev()
1253 kfree(ftl->cache_data); in sm_remove_dev()
1254 kfree(ftl); in sm_remove_dev()