diff options
Diffstat (limited to 'drivers/scsi/scsi_debug.c')
-rw-r--r-- | drivers/scsi/scsi_debug.c | 174 |
1 files changed, 70 insertions, 104 deletions
diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c index d055450c2a4a..cb4fefa1bfba 100644 --- a/drivers/scsi/scsi_debug.c +++ b/drivers/scsi/scsi_debug.c @@ -258,7 +258,7 @@ struct sdebug_queued_cmd { static struct sdebug_queued_cmd queued_arr[SCSI_DEBUG_CANQUEUE]; static unsigned char * fake_storep; /* ramdisk storage */ -static unsigned char *dif_storep; /* protection info */ +static struct sd_dif_tuple *dif_storep; /* protection info */ static void *map_storep; /* provisioning map */ static unsigned long map_size; @@ -277,11 +277,6 @@ static char sdebug_proc_name[] = "scsi_debug"; static struct bus_type pseudo_lld_bus; -static inline sector_t dif_offset(sector_t sector) -{ - return sector << 3; -} - static struct device_driver sdebug_driverfs_driver = { .name = sdebug_proc_name, .bus = &pseudo_lld_bus, @@ -1736,6 +1731,50 @@ static int do_device_access(struct scsi_cmnd *scmd, return ret; } +static u16 dif_compute_csum(const void *buf, int len) +{ + u16 csum; + + switch (scsi_debug_guard) { + case 1: + csum = ip_compute_csum(buf, len); + break; + case 0: + csum = cpu_to_be16(crc_t10dif(buf, len)); + break; + } + return csum; +} + +static int dif_verify(struct sd_dif_tuple *sdt, const void *data, + sector_t sector, u32 ei_lba) +{ + u16 csum = dif_compute_csum(data, scsi_debug_sector_size); + + if (sdt->guard_tag != csum) { + pr_err("%s: GUARD check failed on sector %lu rcvd 0x%04x, data 0x%04x\n", + __func__, + (unsigned long)sector, + be16_to_cpu(sdt->guard_tag), + be16_to_cpu(csum)); + return 0x01; + } + if (scsi_debug_dif == SD_DIF_TYPE1_PROTECTION && + be32_to_cpu(sdt->ref_tag) != (sector & 0xffffffff)) { + pr_err("%s: REF check failed on sector %lu\n", + __func__, (unsigned long)sector); + return 0x03; + } + if (scsi_debug_dif == SD_DIF_TYPE2_PROTECTION && + be32_to_cpu(sdt->ref_tag) != ei_lba) { + pr_err("%s: REF check failed on sector %lu\n", + __func__, (unsigned long)sector); + dif_errors++; + return 0x03; + } + return 0; +} + static int prot_verify_read(struct scsi_cmnd *SCpnt, sector_t start_sec, unsigned int sectors, u32 ei_lba) { @@ -1748,71 +1787,38 @@ static int prot_verify_read(struct scsi_cmnd *SCpnt, sector_t start_sec, start_sec = do_div(tmp_sec, sdebug_store_sectors); - sdt = (struct sd_dif_tuple *)(dif_storep + dif_offset(start_sec)); + sdt = dif_storep + start_sec; for (i = 0 ; i < sectors ; i++) { - u16 csum; + int ret; if (sdt[i].app_tag == 0xffff) continue; sector = start_sec + i; - switch (scsi_debug_guard) { - case 1: - csum = ip_compute_csum(fake_storep + - sector * scsi_debug_sector_size, - scsi_debug_sector_size); - break; - case 0: - csum = crc_t10dif(fake_storep + - sector * scsi_debug_sector_size, - scsi_debug_sector_size); - csum = cpu_to_be16(csum); - break; - default: - BUG(); - } - - if (sdt[i].guard_tag != csum) { - printk(KERN_ERR "%s: GUARD check failed on sector %lu" \ - " rcvd 0x%04x, data 0x%04x\n", __func__, - (unsigned long)sector, - be16_to_cpu(sdt[i].guard_tag), - be16_to_cpu(csum)); - dif_errors++; - return 0x01; - } - - if (scsi_debug_dif == SD_DIF_TYPE1_PROTECTION && - be32_to_cpu(sdt[i].ref_tag) != (sector & 0xffffffff)) { - printk(KERN_ERR "%s: REF check failed on sector %lu\n", - __func__, (unsigned long)sector); + ret = dif_verify(&sdt[i], + fake_storep + sector * scsi_debug_sector_size, + sector, ei_lba); + if (ret) { dif_errors++; - return 0x03; - } - - if (scsi_debug_dif == SD_DIF_TYPE2_PROTECTION && - be32_to_cpu(sdt[i].ref_tag) != ei_lba) { - printk(KERN_ERR "%s: REF check failed on sector %lu\n", - __func__, (unsigned long)sector); - dif_errors++; - return 0x03; + return ret; } ei_lba++; } - resid = sectors * 8; /* Bytes of protection data to copy into sgl */ + /* Bytes of protection data to copy into sgl */ + resid = sectors * sizeof(*dif_storep); sector = start_sec; scsi_for_each_prot_sg(SCpnt, psgl, scsi_prot_sg_count(SCpnt), i) { int len = min(psgl->length, resid); paddr = kmap_atomic(sg_page(psgl)) + psgl->offset; - memcpy(paddr, dif_storep + dif_offset(sector), len); + memcpy(paddr, dif_storep + sector, len); - sector += len >> 3; + sector += len / sizeof(*dif_storep); if (sector >= sdebug_store_sectors) { /* Force wrap */ tmp_sec = sector; @@ -1910,22 +1916,21 @@ static int prot_verify_write(struct scsi_cmnd *SCpnt, sector_t start_sec, sector_t tmp_sec = start_sec; sector_t sector; int ppage_offset; - unsigned short csum; sector = do_div(tmp_sec, sdebug_store_sectors); BUG_ON(scsi_sg_count(SCpnt) == 0); BUG_ON(scsi_prot_sg_count(SCpnt) == 0); - paddr = kmap_atomic(sg_page(psgl)) + psgl->offset; ppage_offset = 0; /* For each data page */ scsi_for_each_sg(SCpnt, dsgl, scsi_sg_count(SCpnt), i) { daddr = kmap_atomic(sg_page(dsgl)) + dsgl->offset; + paddr = kmap_atomic(sg_page(psgl)) + psgl->offset; /* For each sector-sized chunk in data page */ - for (j = 0 ; j < dsgl->length ; j += scsi_debug_sector_size) { + for (j = 0; j < dsgl->length; j += scsi_debug_sector_size) { /* If we're at the end of the current * protection page advance to the next one @@ -1941,51 +1946,9 @@ static int prot_verify_write(struct scsi_cmnd *SCpnt, sector_t start_sec, sdt = paddr + ppage_offset; - switch (scsi_debug_guard) { - case 1: - csum = ip_compute_csum(daddr, - scsi_debug_sector_size); - break; - case 0: - csum = cpu_to_be16(crc_t10dif(daddr, - scsi_debug_sector_size)); - break; - default: - BUG(); - ret = 0; - goto out; - } - - if (sdt->guard_tag != csum) { - printk(KERN_ERR - "%s: GUARD check failed on sector %lu " \ - "rcvd 0x%04x, calculated 0x%04x\n", - __func__, (unsigned long)sector, - be16_to_cpu(sdt->guard_tag), - be16_to_cpu(csum)); - ret = 0x01; - dump_sector(daddr, scsi_debug_sector_size); - goto out; - } - - if (scsi_debug_dif == SD_DIF_TYPE1_PROTECTION && - be32_to_cpu(sdt->ref_tag) - != (start_sec & 0xffffffff)) { - printk(KERN_ERR - "%s: REF check failed on sector %lu\n", - __func__, (unsigned long)sector); - ret = 0x03; - dump_sector(daddr, scsi_debug_sector_size); - goto out; - } - - if (scsi_debug_dif == SD_DIF_TYPE2_PROTECTION && - be32_to_cpu(sdt->ref_tag) != ei_lba) { - printk(KERN_ERR - "%s: REF check failed on sector %lu\n", - __func__, (unsigned long)sector); - ret = 0x03; - dump_sector(daddr, scsi_debug_sector_size); + ret = dif_verify(sdt, daddr + j, start_sec, ei_lba); + if (ret) { + dump_sector(daddr + j, scsi_debug_sector_size); goto out; } @@ -1994,7 +1957,7 @@ static int prot_verify_write(struct scsi_cmnd *SCpnt, sector_t start_sec, * correctness we need to verify each sector * before writing it to "stable" storage */ - memcpy(dif_storep + dif_offset(sector), sdt, 8); + memcpy(dif_storep + sector, sdt, sizeof(*sdt)); sector++; @@ -2003,23 +1966,21 @@ static int prot_verify_write(struct scsi_cmnd *SCpnt, sector_t start_sec, start_sec++; ei_lba++; - daddr += scsi_debug_sector_size; ppage_offset += sizeof(struct sd_dif_tuple); } + kunmap_atomic(paddr); kunmap_atomic(daddr); } - kunmap_atomic(paddr); - dix_writes++; return 0; out: dif_errors++; - kunmap_atomic(daddr); kunmap_atomic(paddr); + kunmap_atomic(daddr); return ret; } @@ -2092,6 +2053,11 @@ static void unmap_region(sector_t lba, unsigned int len) scsi_debug_sector_size * scsi_debug_unmap_granularity); } + if (dif_storep) { + memset(dif_storep + lba, 0xff, + sizeof(*dif_storep) * + scsi_debug_unmap_granularity); + } } lba = map_index_to_lba(index + 1); } @@ -3400,7 +3366,7 @@ static int __init scsi_debug_init(void) if (scsi_debug_num_parts > 0) sdebug_build_parts(fake_storep, sz); - if (scsi_debug_dif) { + if (scsi_debug_dix) { int dif_size; dif_size = sdebug_store_sectors * sizeof(struct sd_dif_tuple); |