|
@@ -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);
|
|
|
}
|
|
|
}
|
|
|
}
|