The T10 Protection Information format is also used by some devices that
do not go through the SCSI layer (virtual block devices, NVMe). Relocate
the relevant functions to a library that can be used without involving
SCSI.
Signed-off-by: Martin K. Petersen martin.peter...@oracle.com
---
block/Kconfig | 1 +
drivers/scsi/Kconfig | 2 +-
drivers/scsi/sd_dif.c | 193 +++--
include/linux/crc-t10dif.h | 5 +-
include/linux/t10-pi.h | 28 +++
lib/Kconfig| 7 ++
lib/Makefile | 2 +
lib/t10-pi.c | 164 ++
8 files changed, 219 insertions(+), 183 deletions(-)
create mode 100644 include/linux/t10-pi.h
create mode 100644 lib/t10-pi.c
diff --git a/block/Kconfig b/block/Kconfig
index 2429515c05c2..947658db8456 100644
--- a/block/Kconfig
+++ b/block/Kconfig
@@ -77,6 +77,7 @@ config BLK_DEV_BSGLIB
config BLK_DEV_INTEGRITY
bool Block layer data integrity support
+ select T10_PI if BLK_DEV_INTEGRITY
---help---
Some storage devices allow extra information to be
stored/retrieved to help protect the data. The block layer
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index 02832d64d918..1096b16b2a0c 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -69,7 +69,7 @@ comment SCSI support type (disk, tape, CD-ROM)
config BLK_DEV_SD
tristate SCSI disk support
depends on SCSI
- select CRC_T10DIF if BLK_DEV_INTEGRITY
+ select T10_PI if BLK_DEV_INTEGRITY
---help---
If you want to use SCSI hard disks, Fibre Channel disks,
Serial ATA (SATA) or Parallel ATA (PATA) hard disks,
diff --git a/drivers/scsi/sd_dif.c b/drivers/scsi/sd_dif.c
index 033d30d37952..d7109fff327d 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,204 +33,37 @@
#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 0x);
- 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 == 0x)
- return 0;
-
- if (be32_to_cpu(sdt-ref_tag) != (seed 0x)) {
- 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,