diff options
Diffstat (limited to 'drivers/scsi/sd_dif.c')
-rw-r--r-- | drivers/scsi/sd_dif.c | 241 |
1 files changed, 20 insertions, 221 deletions
diff --git a/drivers/scsi/sd_dif.c b/drivers/scsi/sd_dif.c index 2198abee619e..b7eaeadc18f9 100644 --- a/drivers/scsi/sd_dif.c +++ b/drivers/scsi/sd_dif.c @@ -21,7 +21,7 @@ */ #include <linux/blkdev.h> -#include <linux/crc-t10dif.h> +#include <linux/t10-pi.h> #include <scsi/scsi.h> #include <scsi/scsi_cmnd.h> @@ -33,207 +33,8 @@ #include <scsi/scsi_ioctl.h> #include <scsi/scsicam.h> -#include <net/checksum.h> - #include "sd.h" -typedef __u16 (csum_fn) (void *, unsigned int); - -static __u16 sd_dif_crc_fn(void *data, unsigned int len) -{ - return cpu_to_be16(crc_t10dif(data, len)); -} - -static __u16 sd_dif_ip_fn(void *data, unsigned int len) -{ - return ip_compute_csum(data, len); -} - -/* - * Type 1 and Type 2 protection use the same format: 16 bit guard tag, - * 16 bit app tag, 32 bit reference tag. - */ -static void sd_dif_type1_generate(struct blk_integrity_iter *iter, csum_fn *fn) -{ - void *buf = iter->data_buf; - struct sd_dif_tuple *sdt = iter->prot_buf; - sector_t seed = iter->seed; - unsigned int i; - - for (i = 0 ; i < iter->data_size ; i += iter->interval, sdt++) { - sdt->guard_tag = fn(buf, iter->interval); - sdt->ref_tag = cpu_to_be32(seed & 0xffffffff); - sdt->app_tag = 0; - - buf += iter->interval; - seed++; - } -} - -static int sd_dif_type1_generate_crc(struct blk_integrity_iter *iter) -{ - sd_dif_type1_generate(iter, sd_dif_crc_fn); - return 0; -} - -static int sd_dif_type1_generate_ip(struct blk_integrity_iter *iter) -{ - sd_dif_type1_generate(iter, sd_dif_ip_fn); - return 0; -} - -static int sd_dif_type1_verify(struct blk_integrity_iter *iter, csum_fn *fn) -{ - void *buf = iter->data_buf; - struct sd_dif_tuple *sdt = iter->prot_buf; - sector_t seed = iter->seed; - unsigned int i; - __u16 csum; - - for (i = 0 ; i < iter->data_size ; i += iter->interval, sdt++) { - /* Unwritten sectors */ - if (sdt->app_tag == 0xffff) - return 0; - - if (be32_to_cpu(sdt->ref_tag) != (seed & 0xffffffff)) { - printk(KERN_ERR - "%s: ref tag error on sector %lu (rcvd %u)\n", - iter->disk_name, (unsigned long)seed, - be32_to_cpu(sdt->ref_tag)); - return -EIO; - } - - csum = fn(buf, iter->interval); - - if (sdt->guard_tag != csum) { - printk(KERN_ERR "%s: guard tag error on sector %lu " \ - "(rcvd %04x, data %04x)\n", iter->disk_name, - (unsigned long)seed, - be16_to_cpu(sdt->guard_tag), be16_to_cpu(csum)); - return -EIO; - } - - buf += iter->interval; - seed++; - } - - return 0; -} - -static int sd_dif_type1_verify_crc(struct blk_integrity_iter *iter) -{ - return sd_dif_type1_verify(iter, sd_dif_crc_fn); -} - -static int sd_dif_type1_verify_ip(struct blk_integrity_iter *iter) -{ - return sd_dif_type1_verify(iter, sd_dif_ip_fn); -} - -static struct blk_integrity dif_type1_integrity_crc = { - .name = "T10-DIF-TYPE1-CRC", - .generate_fn = sd_dif_type1_generate_crc, - .verify_fn = sd_dif_type1_verify_crc, - .tuple_size = sizeof(struct sd_dif_tuple), - .tag_size = 0, -}; - -static struct blk_integrity dif_type1_integrity_ip = { - .name = "T10-DIF-TYPE1-IP", - .generate_fn = sd_dif_type1_generate_ip, - .verify_fn = sd_dif_type1_verify_ip, - .tuple_size = sizeof(struct sd_dif_tuple), - .tag_size = 0, -}; - - -/* - * Type 3 protection has a 16-bit guard tag and 16 + 32 bits of opaque - * tag space. - */ -static void sd_dif_type3_generate(struct blk_integrity_iter *iter, csum_fn *fn) -{ - void *buf = iter->data_buf; - struct sd_dif_tuple *sdt = iter->prot_buf; - unsigned int i; - - for (i = 0 ; i < iter->data_size ; i += iter->interval, sdt++) { - sdt->guard_tag = fn(buf, iter->interval); - sdt->ref_tag = 0; - sdt->app_tag = 0; - - buf += iter->interval; - } -} - -static int sd_dif_type3_generate_crc(struct blk_integrity_iter *iter) -{ - sd_dif_type3_generate(iter, sd_dif_crc_fn); - return 0; -} - -static int sd_dif_type3_generate_ip(struct blk_integrity_iter *iter) -{ - sd_dif_type3_generate(iter, sd_dif_ip_fn); - return 0; -} - -static int sd_dif_type3_verify(struct blk_integrity_iter *iter, csum_fn *fn) -{ - void *buf = iter->data_buf; - struct sd_dif_tuple *sdt = iter->prot_buf; - sector_t seed = iter->seed; - unsigned int i; - __u16 csum; - - for (i = 0 ; i < iter->data_size ; i += iter->interval, sdt++) { - /* Unwritten sectors */ - if (sdt->app_tag == 0xffff && sdt->ref_tag == 0xffffffff) - return 0; - - csum = fn(buf, iter->interval); - - if (sdt->guard_tag != csum) { - printk(KERN_ERR "%s: guard tag error on sector %lu " \ - "(rcvd %04x, data %04x)\n", iter->disk_name, - (unsigned long)seed, - be16_to_cpu(sdt->guard_tag), be16_to_cpu(csum)); - return -EIO; - } - - buf += iter->interval; - seed++; - } - - return 0; -} - -static int sd_dif_type3_verify_crc(struct blk_integrity_iter *iter) -{ - return sd_dif_type3_verify(iter, sd_dif_crc_fn); -} - -static int sd_dif_type3_verify_ip(struct blk_integrity_iter *iter) -{ - return sd_dif_type3_verify(iter, sd_dif_ip_fn); -} - -static struct blk_integrity dif_type3_integrity_crc = { - .name = "T10-DIF-TYPE3-CRC", - .generate_fn = sd_dif_type3_generate_crc, - .verify_fn = sd_dif_type3_verify_crc, - .tuple_size = sizeof(struct sd_dif_tuple), - .tag_size = 0, -}; - -static struct blk_integrity dif_type3_integrity_ip = { - .name = "T10-DIF-TYPE3-IP", - .generate_fn = sd_dif_type3_generate_ip, - .verify_fn = sd_dif_type3_verify_ip, - .tuple_size = sizeof(struct sd_dif_tuple), - .tag_size = 0, -}; - /* * Configure exchange of protection information between OS and HBA. */ @@ -257,16 +58,16 @@ void sd_dif_config_host(struct scsi_disk *sdkp) /* Enable DMA of protection information */ if (scsi_host_get_guard(sdkp->device->host) & SHOST_DIX_GUARD_IP) { if (type == SD_DIF_TYPE3_PROTECTION) - blk_integrity_register(disk, &dif_type3_integrity_ip); + blk_integrity_register(disk, &t10_pi_type3_ip); else - blk_integrity_register(disk, &dif_type1_integrity_ip); + blk_integrity_register(disk, &t10_pi_type1_ip); disk->integrity->flags |= BLK_INTEGRITY_IP_CHECKSUM; } else if (type == SD_DIF_TYPE3_PROTECTION) - blk_integrity_register(disk, &dif_type3_integrity_crc); + blk_integrity_register(disk, &t10_pi_type3_crc); else - blk_integrity_register(disk, &dif_type1_integrity_crc); + blk_integrity_register(disk, &t10_pi_type1_crc); sd_printk(KERN_NOTICE, sdkp, "Enabling DIX %s protection\n", disk->integrity->name); @@ -308,10 +109,10 @@ void sd_dif_config_host(struct scsi_disk *sdkp) void sd_dif_prepare(struct request *rq, sector_t hw_sector, unsigned int sector_sz) { - const int tuple_sz = sizeof(struct sd_dif_tuple); + const int tuple_sz = sizeof(struct t10_pi_tuple); struct bio *bio; struct scsi_disk *sdkp; - struct sd_dif_tuple *sdt; + struct t10_pi_tuple *pi; u32 phys, virt; sdkp = rq->bio->bi_bdev->bd_disk->private_data; @@ -334,19 +135,18 @@ void sd_dif_prepare(struct request *rq, sector_t hw_sector, virt = bip_get_seed(bip) & 0xffffffff; bip_for_each_vec(iv, bip, iter) { - sdt = kmap_atomic(iv.bv_page) - + iv.bv_offset; + pi = kmap_atomic(iv.bv_page) + iv.bv_offset; - for (j = 0; j < iv.bv_len; j += tuple_sz, sdt++) { + for (j = 0; j < iv.bv_len; j += tuple_sz, pi++) { - if (be32_to_cpu(sdt->ref_tag) == virt) - sdt->ref_tag = cpu_to_be32(phys); + if (be32_to_cpu(pi->ref_tag) == virt) + pi->ref_tag = cpu_to_be32(phys); virt++; phys++; } - kunmap_atomic(sdt); + kunmap_atomic(pi); } bip->bip_flags |= BIP_MAPPED_INTEGRITY; @@ -359,10 +159,10 @@ void sd_dif_prepare(struct request *rq, sector_t hw_sector, */ void sd_dif_complete(struct scsi_cmnd *scmd, unsigned int good_bytes) { - const int tuple_sz = sizeof(struct sd_dif_tuple); + const int tuple_sz = sizeof(struct t10_pi_tuple); struct scsi_disk *sdkp; struct bio *bio; - struct sd_dif_tuple *sdt; + struct t10_pi_tuple *pi; unsigned int j, sectors, sector_sz; u32 phys, virt; @@ -386,25 +186,24 @@ void sd_dif_complete(struct scsi_cmnd *scmd, unsigned int good_bytes) virt = bip_get_seed(bip) & 0xffffffff; bip_for_each_vec(iv, bip, iter) { - sdt = kmap_atomic(iv.bv_page) - + iv.bv_offset; + pi = kmap_atomic(iv.bv_page) + iv.bv_offset; - for (j = 0; j < iv.bv_len; j += tuple_sz, sdt++) { + for (j = 0; j < iv.bv_len; j += tuple_sz, pi++) { if (sectors == 0) { - kunmap_atomic(sdt); + kunmap_atomic(pi); return; } - if (be32_to_cpu(sdt->ref_tag) == phys) - sdt->ref_tag = cpu_to_be32(virt); + if (be32_to_cpu(pi->ref_tag) == phys) + pi->ref_tag = cpu_to_be32(virt); virt++; phys++; sectors--; } - kunmap_atomic(sdt); + kunmap_atomic(pi); } } } |