]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - drivers/scsi/scsi_debug.c
Merge tag 'usb-3.11-rc8' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb
[karo-tx-linux.git] / drivers / scsi / scsi_debug.c
index d055450c2a4a41d6d8f1d724104e184d37bbdaf0..cb4fefa1bfbaea58a03e973de770233f41f6b34c 100644 (file)
@@ -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);