2  * sd_dif.c - SCSI Data Integrity Field
 
   4  * Copyright (C) 2007, 2008 Oracle Corporation
 
   5  * Written by: Martin K. Petersen <martin.petersen@oracle.com>
 
   7  * This program is free software; you can redistribute it and/or
 
   8  * modify it under the terms of the GNU General Public License version
 
   9  * 2 as published by the Free Software Foundation.
 
  11  * This program is distributed in the hope that it will be useful, but
 
  12  * WITHOUT ANY WARRANTY; without even the implied warranty of
 
  13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
  14  * General Public License for more details.
 
  16  * You should have received a copy of the GNU General Public License
 
  17  * along with this program; see the file COPYING.  If not, write to
 
  18  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139,
 
  23 #include <linux/blkdev.h>
 
  24 #include <linux/crc-t10dif.h>
 
  26 #include <scsi/scsi.h>
 
  27 #include <scsi/scsi_cmnd.h>
 
  28 #include <scsi/scsi_dbg.h>
 
  29 #include <scsi/scsi_device.h>
 
  30 #include <scsi/scsi_driver.h>
 
  31 #include <scsi/scsi_eh.h>
 
  32 #include <scsi/scsi_host.h>
 
  33 #include <scsi/scsi_ioctl.h>
 
  34 #include <scsi/scsicam.h>
 
  36 #include <net/checksum.h>
 
  40 typedef __u16 (csum_fn) (void *, unsigned int);
 
  42 static __u16 sd_dif_crc_fn(void *data, unsigned int len)
 
  44         return cpu_to_be16(crc_t10dif(data, len));
 
  47 static __u16 sd_dif_ip_fn(void *data, unsigned int len)
 
  49         return ip_compute_csum(data, len);
 
  53  * Type 1 and Type 2 protection use the same format: 16 bit guard tag,
 
  54  * 16 bit app tag, 32 bit reference tag.
 
  56 static void sd_dif_type1_generate(struct blk_integrity_exchg *bix, csum_fn *fn)
 
  58         void *buf = bix->data_buf;
 
  59         struct sd_dif_tuple *sdt = bix->prot_buf;
 
  60         sector_t sector = bix->sector;
 
  63         for (i = 0 ; i < bix->data_size ; i += bix->sector_size, sdt++) {
 
  64                 sdt->guard_tag = fn(buf, bix->sector_size);
 
  65                 sdt->ref_tag = cpu_to_be32(sector & 0xffffffff);
 
  68                 buf += bix->sector_size;
 
  73 static void sd_dif_type1_generate_crc(struct blk_integrity_exchg *bix)
 
  75         sd_dif_type1_generate(bix, sd_dif_crc_fn);
 
  78 static void sd_dif_type1_generate_ip(struct blk_integrity_exchg *bix)
 
  80         sd_dif_type1_generate(bix, sd_dif_ip_fn);
 
  83 static int sd_dif_type1_verify(struct blk_integrity_exchg *bix, csum_fn *fn)
 
  85         void *buf = bix->data_buf;
 
  86         struct sd_dif_tuple *sdt = bix->prot_buf;
 
  87         sector_t sector = bix->sector;
 
  91         for (i = 0 ; i < bix->data_size ; i += bix->sector_size, sdt++) {
 
  92                 /* Unwritten sectors */
 
  93                 if (sdt->app_tag == 0xffff)
 
  96                 /* Bad ref tag received from disk */
 
  97                 if (sdt->ref_tag == 0xffffffff) {
 
  99                                "%s: bad phys ref tag on sector %lu\n",
 
 100                                bix->disk_name, (unsigned long)sector);
 
 104                 if (be32_to_cpu(sdt->ref_tag) != (sector & 0xffffffff)) {
 
 106                                "%s: ref tag error on sector %lu (rcvd %u)\n",
 
 107                                bix->disk_name, (unsigned long)sector,
 
 108                                be32_to_cpu(sdt->ref_tag));
 
 112                 csum = fn(buf, bix->sector_size);
 
 114                 if (sdt->guard_tag != csum) {
 
 115                         printk(KERN_ERR "%s: guard tag error on sector %lu " \
 
 116                                "(rcvd %04x, data %04x)\n", bix->disk_name,
 
 117                                (unsigned long)sector,
 
 118                                be16_to_cpu(sdt->guard_tag), be16_to_cpu(csum));
 
 122                 buf += bix->sector_size;
 
 129 static int sd_dif_type1_verify_crc(struct blk_integrity_exchg *bix)
 
 131         return sd_dif_type1_verify(bix, sd_dif_crc_fn);
 
 134 static int sd_dif_type1_verify_ip(struct blk_integrity_exchg *bix)
 
 136         return sd_dif_type1_verify(bix, sd_dif_ip_fn);
 
 140  * Functions for interleaving and deinterleaving application tags
 
 142 static void sd_dif_type1_set_tag(void *prot, void *tag_buf, unsigned int sectors)
 
 144         struct sd_dif_tuple *sdt = prot;
 
 148         for (i = 0, j = 0 ; i < sectors ; i++, j += 2, sdt++) {
 
 149                 sdt->app_tag = tag[j] << 8 | tag[j+1];
 
 150                 BUG_ON(sdt->app_tag == 0xffff);
 
 154 static void sd_dif_type1_get_tag(void *prot, void *tag_buf, unsigned int sectors)
 
 156         struct sd_dif_tuple *sdt = prot;
 
 160         for (i = 0, j = 0 ; i < sectors ; i++, j += 2, sdt++) {
 
 161                 tag[j] = (sdt->app_tag & 0xff00) >> 8;
 
 162                 tag[j+1] = sdt->app_tag & 0xff;
 
 166 static struct blk_integrity dif_type1_integrity_crc = {
 
 167         .name                   = "T10-DIF-TYPE1-CRC",
 
 168         .generate_fn            = sd_dif_type1_generate_crc,
 
 169         .verify_fn              = sd_dif_type1_verify_crc,
 
 170         .get_tag_fn             = sd_dif_type1_get_tag,
 
 171         .set_tag_fn             = sd_dif_type1_set_tag,
 
 172         .tuple_size             = sizeof(struct sd_dif_tuple),
 
 176 static struct blk_integrity dif_type1_integrity_ip = {
 
 177         .name                   = "T10-DIF-TYPE1-IP",
 
 178         .generate_fn            = sd_dif_type1_generate_ip,
 
 179         .verify_fn              = sd_dif_type1_verify_ip,
 
 180         .get_tag_fn             = sd_dif_type1_get_tag,
 
 181         .set_tag_fn             = sd_dif_type1_set_tag,
 
 182         .tuple_size             = sizeof(struct sd_dif_tuple),
 
 188  * Type 3 protection has a 16-bit guard tag and 16 + 32 bits of opaque
 
 191 static void sd_dif_type3_generate(struct blk_integrity_exchg *bix, csum_fn *fn)
 
 193         void *buf = bix->data_buf;
 
 194         struct sd_dif_tuple *sdt = bix->prot_buf;
 
 197         for (i = 0 ; i < bix->data_size ; i += bix->sector_size, sdt++) {
 
 198                 sdt->guard_tag = fn(buf, bix->sector_size);
 
 202                 buf += bix->sector_size;
 
 206 static void sd_dif_type3_generate_crc(struct blk_integrity_exchg *bix)
 
 208         sd_dif_type3_generate(bix, sd_dif_crc_fn);
 
 211 static void sd_dif_type3_generate_ip(struct blk_integrity_exchg *bix)
 
 213         sd_dif_type3_generate(bix, sd_dif_ip_fn);
 
 216 static int sd_dif_type3_verify(struct blk_integrity_exchg *bix, csum_fn *fn)
 
 218         void *buf = bix->data_buf;
 
 219         struct sd_dif_tuple *sdt = bix->prot_buf;
 
 220         sector_t sector = bix->sector;
 
 224         for (i = 0 ; i < bix->data_size ; i += bix->sector_size, sdt++) {
 
 225                 /* Unwritten sectors */
 
 226                 if (sdt->app_tag == 0xffff && sdt->ref_tag == 0xffffffff)
 
 229                 csum = fn(buf, bix->sector_size);
 
 231                 if (sdt->guard_tag != csum) {
 
 232                         printk(KERN_ERR "%s: guard tag error on sector %lu " \
 
 233                                "(rcvd %04x, data %04x)\n", bix->disk_name,
 
 234                                (unsigned long)sector,
 
 235                                be16_to_cpu(sdt->guard_tag), be16_to_cpu(csum));
 
 239                 buf += bix->sector_size;
 
 246 static int sd_dif_type3_verify_crc(struct blk_integrity_exchg *bix)
 
 248         return sd_dif_type3_verify(bix, sd_dif_crc_fn);
 
 251 static int sd_dif_type3_verify_ip(struct blk_integrity_exchg *bix)
 
 253         return sd_dif_type3_verify(bix, sd_dif_ip_fn);
 
 256 static void sd_dif_type3_set_tag(void *prot, void *tag_buf, unsigned int sectors)
 
 258         struct sd_dif_tuple *sdt = prot;
 
 262         for (i = 0, j = 0 ; i < sectors ; i++, j += 6, sdt++) {
 
 263                 sdt->app_tag = tag[j] << 8 | tag[j+1];
 
 264                 sdt->ref_tag = tag[j+2] << 24 | tag[j+3] << 16 |
 
 265                         tag[j+4] << 8 | tag[j+5];
 
 269 static void sd_dif_type3_get_tag(void *prot, void *tag_buf, unsigned int sectors)
 
 271         struct sd_dif_tuple *sdt = prot;
 
 275         for (i = 0, j = 0 ; i < sectors ; i++, j += 2, sdt++) {
 
 276                 tag[j] = (sdt->app_tag & 0xff00) >> 8;
 
 277                 tag[j+1] = sdt->app_tag & 0xff;
 
 278                 tag[j+2] = (sdt->ref_tag & 0xff000000) >> 24;
 
 279                 tag[j+3] = (sdt->ref_tag & 0xff0000) >> 16;
 
 280                 tag[j+4] = (sdt->ref_tag & 0xff00) >> 8;
 
 281                 tag[j+5] = sdt->ref_tag & 0xff;
 
 282                 BUG_ON(sdt->app_tag == 0xffff || sdt->ref_tag == 0xffffffff);
 
 286 static struct blk_integrity dif_type3_integrity_crc = {
 
 287         .name                   = "T10-DIF-TYPE3-CRC",
 
 288         .generate_fn            = sd_dif_type3_generate_crc,
 
 289         .verify_fn              = sd_dif_type3_verify_crc,
 
 290         .get_tag_fn             = sd_dif_type3_get_tag,
 
 291         .set_tag_fn             = sd_dif_type3_set_tag,
 
 292         .tuple_size             = sizeof(struct sd_dif_tuple),
 
 296 static struct blk_integrity dif_type3_integrity_ip = {
 
 297         .name                   = "T10-DIF-TYPE3-IP",
 
 298         .generate_fn            = sd_dif_type3_generate_ip,
 
 299         .verify_fn              = sd_dif_type3_verify_ip,
 
 300         .get_tag_fn             = sd_dif_type3_get_tag,
 
 301         .set_tag_fn             = sd_dif_type3_set_tag,
 
 302         .tuple_size             = sizeof(struct sd_dif_tuple),
 
 307  * Configure exchange of protection information between OS and HBA.
 
 309 void sd_dif_config_host(struct scsi_disk *sdkp)
 
 311         struct scsi_device *sdp = sdkp->device;
 
 312         struct gendisk *disk = sdkp->disk;
 
 313         u8 type = sdkp->protection_type;
 
 315         /* If this HBA doesn't support DIX, resort to normal I/O or DIF */
 
 316         if (scsi_host_dix_capable(sdp->host, type) == 0) {
 
 318                 if (type == SD_DIF_TYPE0_PROTECTION)
 
 321                 if (scsi_host_dif_capable(sdp->host, type) == 0) {
 
 322                         sd_printk(KERN_INFO, sdkp, "Type %d protection " \
 
 323                                   "unsupported by HBA. Disabling DIF.\n", type);
 
 324                         sdkp->protection_type = 0;
 
 328                 sd_printk(KERN_INFO, sdkp, "Enabling DIF Type %d protection\n",
 
 334         /* Enable DMA of protection information */
 
 335         if (scsi_host_get_guard(sdkp->device->host) & SHOST_DIX_GUARD_IP)
 
 336                 if (type == SD_DIF_TYPE3_PROTECTION)
 
 337                         blk_integrity_register(disk, &dif_type3_integrity_ip);
 
 339                         blk_integrity_register(disk, &dif_type1_integrity_ip);
 
 341                 if (type == SD_DIF_TYPE3_PROTECTION)
 
 342                         blk_integrity_register(disk, &dif_type3_integrity_crc);
 
 344                         blk_integrity_register(disk, &dif_type1_integrity_crc);
 
 346         sd_printk(KERN_INFO, sdkp,
 
 347                   "Enabling %s integrity protection\n", disk->integrity->name);
 
 349         /* Signal to block layer that we support sector tagging */
 
 350         if (type && sdkp->ATO) {
 
 351                 if (type == SD_DIF_TYPE3_PROTECTION)
 
 352                         disk->integrity->tag_size = sizeof(u16) + sizeof(u32);
 
 354                         disk->integrity->tag_size = sizeof(u16);
 
 356                 sd_printk(KERN_INFO, sdkp, "DIF application tag size %u\n",
 
 357                           disk->integrity->tag_size);
 
 362  * DIF DMA operation magic decoder ring.
 
 364 void sd_dif_op(struct scsi_cmnd *scmd, unsigned int dif, unsigned int dix)
 
 366         int csum_convert, prot_op;
 
 370         /* Convert checksum? */
 
 371         if (scsi_host_get_guard(scmd->device->host) != SHOST_DIX_GUARD_CRC)
 
 376         switch (scmd->cmnd[0]) {
 
 382                                 prot_op = SCSI_PROT_READ_CONVERT;
 
 384                                 prot_op = SCSI_PROT_READ_PASS;
 
 385                 else if (dif && !dix)
 
 386                         prot_op = SCSI_PROT_READ_STRIP;
 
 387                 else if (!dif && dix)
 
 388                         prot_op = SCSI_PROT_READ_INSERT;
 
 397                                 prot_op = SCSI_PROT_WRITE_CONVERT;
 
 399                                 prot_op = SCSI_PROT_WRITE_PASS;
 
 400                 else if (dif && !dix)
 
 401                         prot_op = SCSI_PROT_WRITE_INSERT;
 
 402                 else if (!dif && dix)
 
 403                         prot_op = SCSI_PROT_WRITE_STRIP;
 
 408         scsi_set_prot_op(scmd, prot_op);
 
 409         scsi_set_prot_type(scmd, dif);
 
 413  * The virtual start sector is the one that was originally submitted
 
 414  * by the block layer.  Due to partitioning, MD/DM cloning, etc. the
 
 415  * actual physical start sector is likely to be different.  Remap
 
 416  * protection information to match the physical LBA.
 
 418  * From a protocol perspective there's a slight difference between
 
 419  * Type 1 and 2.  The latter uses 32-byte CDBs exclusively, and the
 
 420  * reference tag is seeded in the CDB.  This gives us the potential to
 
 421  * avoid virt->phys remapping during write.  However, at read time we
 
 422  * don't know whether the virt sector is the same as when we wrote it
 
 423  * (we could be reading from real disk as opposed to MD/DM device.  So
 
 424  * we always remap Type 2 making it identical to Type 1.
 
 426  * Type 3 does not have a reference tag so no remapping is required.
 
 428 int sd_dif_prepare(struct request *rq, sector_t hw_sector, unsigned int sector_sz)
 
 430         const int tuple_sz = sizeof(struct sd_dif_tuple);
 
 432         struct scsi_disk *sdkp;
 
 433         struct sd_dif_tuple *sdt;
 
 437         /* Already remapped? */
 
 438         if (rq->cmd_flags & REQ_INTEGRITY)
 
 441         sdkp = rq->bio->bi_bdev->bd_disk->private_data;
 
 443         if (sdkp->protection_type == SD_DIF_TYPE3_PROTECTION)
 
 446         rq->cmd_flags |= REQ_INTEGRITY;
 
 447         phys = hw_sector & 0xffffffff;
 
 449         __rq_for_each_bio(bio, rq) {
 
 452                 virt = bio->bi_integrity->bip_sector & 0xffffffff;
 
 454                 bip_for_each_vec(iv, bio->bi_integrity, i) {
 
 455                         sdt = kmap_atomic(iv->bv_page, KM_USER0)
 
 458                         for (j = 0 ; j < iv->bv_len ; j += tuple_sz, sdt++) {
 
 460                                 if (be32_to_cpu(sdt->ref_tag) != virt)
 
 463                                 sdt->ref_tag = cpu_to_be32(phys);
 
 468                         kunmap_atomic(sdt, KM_USER0);
 
 475         kunmap_atomic(sdt, KM_USER0);
 
 476         sd_printk(KERN_ERR, sdkp, "%s: virt %u, phys %u, ref %u\n",
 
 477                   __func__, virt, phys, be32_to_cpu(sdt->ref_tag));
 
 483  * Remap physical sector values in the reference tag to the virtual
 
 484  * values expected by the block layer.
 
 486 void sd_dif_complete(struct scsi_cmnd *scmd, unsigned int good_bytes)
 
 488         const int tuple_sz = sizeof(struct sd_dif_tuple);
 
 489         struct scsi_disk *sdkp;
 
 491         struct sd_dif_tuple *sdt;
 
 492         unsigned int i, j, sectors, sector_sz;
 
 495         sdkp = scsi_disk(scmd->request->rq_disk);
 
 497         if (sdkp->protection_type == SD_DIF_TYPE3_PROTECTION || good_bytes == 0)
 
 500         sector_sz = scmd->device->sector_size;
 
 501         sectors = good_bytes / sector_sz;
 
 503         phys = scmd->request->sector & 0xffffffff;
 
 504         if (sector_sz == 4096)
 
 507         __rq_for_each_bio(bio, scmd->request) {
 
 510                 virt = bio->bi_integrity->bip_sector & 0xffffffff;
 
 512                 bip_for_each_vec(iv, bio->bi_integrity, i) {
 
 513                         sdt = kmap_atomic(iv->bv_page, KM_USER0)
 
 516                         for (j = 0 ; j < iv->bv_len ; j += tuple_sz, sdt++) {
 
 519                                         kunmap_atomic(sdt, KM_USER0);
 
 523                                 if (be32_to_cpu(sdt->ref_tag) != phys &&
 
 524                                     sdt->app_tag != 0xffff)
 
 525                                         sdt->ref_tag = 0xffffffff; /* Bad ref */
 
 527                                         sdt->ref_tag = cpu_to_be32(virt);
 
 534                         kunmap_atomic(sdt, KM_USER0);