diff options
author | Scott Wood <scottwood@freescale.com> | 2014-04-07 23:49:35 (GMT) |
---|---|---|
committer | Scott Wood <scottwood@freescale.com> | 2014-04-07 23:49:35 (GMT) |
commit | 62b8c978ee6b8d135d9e7953221de58000dba986 (patch) | |
tree | 683b04b2e627f6710c22c151b23c8cc9a165315e /drivers/scsi/scsi_debug.c | |
parent | 78fd82238d0e5716578c326404184a27ba67fd6e (diff) | |
download | linux-fsl-qoriq-62b8c978ee6b8d135d9e7953221de58000dba986.tar.xz |
Rewind v3.13-rc3+ (78fd82238d0e5716) to v3.12
Diffstat (limited to 'drivers/scsi/scsi_debug.c')
-rw-r--r-- | drivers/scsi/scsi_debug.c | 137 |
1 files changed, 64 insertions, 73 deletions
diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c index 80b8b10..01c0ffa 100644 --- a/drivers/scsi/scsi_debug.c +++ b/drivers/scsi/scsi_debug.c @@ -169,7 +169,7 @@ static int scsi_debug_dix = DEF_DIX; static int scsi_debug_dsense = DEF_D_SENSE; static int scsi_debug_every_nth = DEF_EVERY_NTH; static int scsi_debug_fake_rw = DEF_FAKE_RW; -static unsigned int scsi_debug_guard = DEF_GUARD; +static int scsi_debug_guard = DEF_GUARD; static int scsi_debug_lowest_aligned = DEF_LOWEST_ALIGNED; static int scsi_debug_max_luns = DEF_MAX_LUNS; static int scsi_debug_max_queue = SCSI_DEBUG_CANQUEUE; @@ -293,20 +293,6 @@ static unsigned char ctrl_m_pg[] = {0xa, 10, 2, 0, 0, 0, 0, 0, static unsigned char iec_m_pg[] = {0x1c, 0xa, 0x08, 0, 0, 0, 0, 0, 0, 0, 0x0, 0x0}; -static void *fake_store(unsigned long long lba) -{ - lba = do_div(lba, sdebug_store_sectors); - - return fake_storep + lba * scsi_debug_sector_size; -} - -static struct sd_dif_tuple *dif_store(sector_t sector) -{ - sector = do_div(sector, sdebug_store_sectors); - - return dif_storep + sector; -} - static int sdebug_add_adapter(void); static void sdebug_remove_adapter(void); @@ -1745,22 +1731,25 @@ static int do_device_access(struct scsi_cmnd *scmd, return ret; } -static __be16 dif_compute_csum(const void *buf, int len) +static u16 dif_compute_csum(const void *buf, int len) { - __be16 csum; + u16 csum; - if (scsi_debug_guard) - csum = (__force __be16)ip_compute_csum(buf, len); - else + 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) { - __be16 csum = dif_compute_csum(data, scsi_debug_sector_size); + 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", @@ -1786,71 +1775,59 @@ static int dif_verify(struct sd_dif_tuple *sdt, const void *data, return 0; } -static void dif_copy_prot(struct scsi_cmnd *SCpnt, sector_t sector, - unsigned int sectors, bool read) +static int prot_verify_read(struct scsi_cmnd *SCpnt, sector_t start_sec, + unsigned int sectors, u32 ei_lba) { unsigned int i, resid; struct scatterlist *psgl; + struct sd_dif_tuple *sdt; + sector_t sector; + sector_t tmp_sec = start_sec; void *paddr; - const void *dif_store_end = dif_storep + sdebug_store_sectors; - /* Bytes of protection data to copy into sgl */ - resid = sectors * sizeof(*dif_storep); + start_sec = do_div(tmp_sec, sdebug_store_sectors); - scsi_for_each_prot_sg(SCpnt, psgl, scsi_prot_sg_count(SCpnt), i) { - int len = min(psgl->length, resid); - void *start = dif_store(sector); - int rest = 0; + sdt = dif_storep + start_sec; - if (dif_store_end < start + len) - rest = start + len - dif_store_end; + for (i = 0 ; i < sectors ; i++) { + int ret; - paddr = kmap_atomic(sg_page(psgl)) + psgl->offset; + if (sdt[i].app_tag == 0xffff) + continue; - if (read) - memcpy(paddr, start, len - rest); - else - memcpy(start, paddr, len - rest); + sector = start_sec + i; - if (rest) { - if (read) - memcpy(paddr + len - rest, dif_storep, rest); - else - memcpy(dif_storep, paddr + len - rest, rest); + ret = dif_verify(&sdt[i], + fake_storep + sector * scsi_debug_sector_size, + sector, ei_lba); + if (ret) { + dif_errors++; + return ret; } - sector += len / sizeof(*dif_storep); - resid -= len; - kunmap_atomic(paddr); + ei_lba++; } -} - -static int prot_verify_read(struct scsi_cmnd *SCpnt, sector_t start_sec, - unsigned int sectors, u32 ei_lba) -{ - unsigned int i; - struct sd_dif_tuple *sdt; - sector_t sector; - for (i = 0; i < sectors; i++) { - int ret; + /* Bytes of protection data to copy into sgl */ + resid = sectors * sizeof(*dif_storep); + sector = start_sec; - sector = start_sec + i; - sdt = dif_store(sector); + scsi_for_each_prot_sg(SCpnt, psgl, scsi_prot_sg_count(SCpnt), i) { + int len = min(psgl->length, resid); - if (sdt->app_tag == cpu_to_be16(0xffff)) - continue; + paddr = kmap_atomic(sg_page(psgl)) + psgl->offset; + memcpy(paddr, dif_storep + sector, len); - ret = dif_verify(sdt, fake_store(sector), sector, ei_lba); - if (ret) { - dif_errors++; - return ret; + sector += len / sizeof(*dif_storep); + if (sector >= sdebug_store_sectors) { + /* Force wrap */ + tmp_sec = sector; + sector = do_div(tmp_sec, sdebug_store_sectors); } - - ei_lba++; + resid -= len; + kunmap_atomic(paddr); } - dif_copy_prot(SCpnt, start_sec, sectors, true); dix_reads++; return 0; @@ -1933,12 +1910,15 @@ static int prot_verify_write(struct scsi_cmnd *SCpnt, sector_t start_sec, { int i, j, ret; struct sd_dif_tuple *sdt; - struct scatterlist *dsgl; + struct scatterlist *dsgl = scsi_sglist(SCpnt); struct scatterlist *psgl = scsi_prot_sglist(SCpnt); void *daddr, *paddr; - sector_t sector = start_sec; + sector_t tmp_sec = start_sec; + sector_t sector; int ppage_offset; + sector = do_div(tmp_sec, sdebug_store_sectors); + BUG_ON(scsi_sg_count(SCpnt) == 0); BUG_ON(scsi_prot_sg_count(SCpnt) == 0); @@ -1966,13 +1946,25 @@ static int prot_verify_write(struct scsi_cmnd *SCpnt, sector_t start_sec, sdt = paddr + ppage_offset; - ret = dif_verify(sdt, daddr + j, sector, ei_lba); + ret = dif_verify(sdt, daddr + j, start_sec, ei_lba); if (ret) { dump_sector(daddr + j, scsi_debug_sector_size); goto out; } + /* Would be great to copy this in bigger + * chunks. However, for the sake of + * correctness we need to verify each sector + * before writing it to "stable" storage + */ + memcpy(dif_storep + sector, sdt, sizeof(*sdt)); + sector++; + + if (sector == sdebug_store_sectors) + sector = 0; /* Force wrap */ + + start_sec++; ei_lba++; ppage_offset += sizeof(struct sd_dif_tuple); } @@ -1981,7 +1973,6 @@ static int prot_verify_write(struct scsi_cmnd *SCpnt, sector_t start_sec, kunmap_atomic(daddr); } - dif_copy_prot(SCpnt, start_sec, sectors, false); dix_writes++; return 0; @@ -2751,7 +2742,7 @@ module_param_named(dix, scsi_debug_dix, int, S_IRUGO); module_param_named(dsense, scsi_debug_dsense, int, S_IRUGO | S_IWUSR); module_param_named(every_nth, scsi_debug_every_nth, int, S_IRUGO | S_IWUSR); module_param_named(fake_rw, scsi_debug_fake_rw, int, S_IRUGO | S_IWUSR); -module_param_named(guard, scsi_debug_guard, uint, S_IRUGO); +module_param_named(guard, scsi_debug_guard, int, S_IRUGO); module_param_named(lbpu, scsi_debug_lbpu, int, S_IRUGO); module_param_named(lbpws, scsi_debug_lbpws, int, S_IRUGO); module_param_named(lbpws10, scsi_debug_lbpws10, int, S_IRUGO); @@ -3181,7 +3172,7 @@ DRIVER_ATTR(dif, S_IRUGO, sdebug_dif_show, NULL); static ssize_t sdebug_guard_show(struct device_driver *ddp, char *buf) { - return scnprintf(buf, PAGE_SIZE, "%u\n", scsi_debug_guard); + return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_guard); } DRIVER_ATTR(guard, S_IRUGO, sdebug_guard_show, NULL); |