aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--block/Kconfig1
-rw-r--r--block/Makefile4
-rw-r--r--block/t10-pi.c197
-rw-r--r--drivers/scsi/Kconfig1
-rw-r--r--drivers/scsi/sd_dif.c241
-rw-r--r--include/linux/crc-t10dif.h5
-rw-r--r--include/linux/t10-pi.h22
7 files changed, 245 insertions, 226 deletions
diff --git a/block/Kconfig b/block/Kconfig
index 2429515c05c2..161491d0a879 100644
--- a/block/Kconfig
+++ b/block/Kconfig
@@ -77,6 +77,7 @@ config BLK_DEV_BSGLIB
77 77
78config BLK_DEV_INTEGRITY 78config BLK_DEV_INTEGRITY
79 bool "Block layer data integrity support" 79 bool "Block layer data integrity support"
80 select CRC_T10DIF if BLK_DEV_INTEGRITY
80 ---help--- 81 ---help---
81 Some storage devices allow extra information to be 82 Some storage devices allow extra information to be
82 stored/retrieved to help protect the data. The block layer 83 stored/retrieved to help protect the data. The block layer
diff --git a/block/Makefile b/block/Makefile
index a2ce6ac935ec..00ecc97629db 100644
--- a/block/Makefile
+++ b/block/Makefile
@@ -20,6 +20,6 @@ obj-$(CONFIG_IOSCHED_DEADLINE) += deadline-iosched.o
20obj-$(CONFIG_IOSCHED_CFQ) += cfq-iosched.o 20obj-$(CONFIG_IOSCHED_CFQ) += cfq-iosched.o
21 21
22obj-$(CONFIG_BLOCK_COMPAT) += compat_ioctl.o 22obj-$(CONFIG_BLOCK_COMPAT) += compat_ioctl.o
23obj-$(CONFIG_BLK_DEV_INTEGRITY) += blk-integrity.o
24obj-$(CONFIG_BLK_CMDLINE_PARSER) += cmdline-parser.o 23obj-$(CONFIG_BLK_CMDLINE_PARSER) += cmdline-parser.o
25obj-$(CONFIG_BLK_DEV_INTEGRITY) += bio-integrity.o 24obj-$(CONFIG_BLK_DEV_INTEGRITY) += bio-integrity.o blk-integrity.o t10-pi.o
25
diff --git a/block/t10-pi.c b/block/t10-pi.c
new file mode 100644
index 000000000000..24d6e9715318
--- /dev/null
+++ b/block/t10-pi.c
@@ -0,0 +1,197 @@
1/*
2 * t10_pi.c - Functions for generating and verifying T10 Protection
3 * Information.
4 *
5 * Copyright (C) 2007, 2008, 2014 Oracle Corporation
6 * Written by: Martin K. Petersen <martin.petersen@oracle.com>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License version
10 * 2 as published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; see the file COPYING. If not, write to
19 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139,
20 * USA.
21 *
22 */
23
24#include <linux/t10-pi.h>
25#include <linux/blkdev.h>
26#include <linux/crc-t10dif.h>
27#include <net/checksum.h>
28
29typedef __be16 (csum_fn) (void *, unsigned int);
30
31static const __be16 APP_ESCAPE = (__force __be16) 0xffff;
32static const __be32 REF_ESCAPE = (__force __be32) 0xffffffff;
33
34static __be16 t10_pi_crc_fn(void *data, unsigned int len)
35{
36 return cpu_to_be16(crc_t10dif(data, len));
37}
38
39static __be16 t10_pi_ip_fn(void *data, unsigned int len)
40{
41 return (__force __be16)ip_compute_csum(data, len);
42}
43
44/*
45 * Type 1 and Type 2 protection use the same format: 16 bit guard tag,
46 * 16 bit app tag, 32 bit reference tag. Type 3 does not define the ref
47 * tag.
48 */
49static int t10_pi_generate(struct blk_integrity_iter *iter, csum_fn *fn,
50 unsigned int type)
51{
52 unsigned int i;
53
54 for (i = 0 ; i < iter->data_size ; i += iter->interval) {
55 struct t10_pi_tuple *pi = iter->prot_buf;
56
57 pi->guard_tag = fn(iter->data_buf, iter->interval);
58 pi->app_tag = 0;
59
60 if (type == 1)
61 pi->ref_tag = cpu_to_be32(lower_32_bits(iter->seed));
62 else
63 pi->ref_tag = 0;
64
65 iter->data_buf += iter->interval;
66 iter->prot_buf += sizeof(struct t10_pi_tuple);
67 iter->seed++;
68 }
69
70 return 0;
71}
72
73static int t10_pi_verify(struct blk_integrity_iter *iter, csum_fn *fn,
74 unsigned int type)
75{
76 unsigned int i;
77
78 for (i = 0 ; i < iter->data_size ; i += iter->interval) {
79 struct t10_pi_tuple *pi = iter->prot_buf;
80 __be16 csum;
81
82 switch (type) {
83 case 1:
84 case 2:
85 if (pi->app_tag == APP_ESCAPE)
86 goto next;
87
88 if (be32_to_cpu(pi->ref_tag) !=
89 lower_32_bits(iter->seed)) {
90 pr_err("%s: ref tag error at location %llu " \
91 "(rcvd %u)\n", iter->disk_name,
92 (unsigned long long)
93 iter->seed, be32_to_cpu(pi->ref_tag));
94 return -EILSEQ;
95 }
96 break;
97 case 3:
98 if (pi->app_tag == APP_ESCAPE &&
99 pi->ref_tag == REF_ESCAPE)
100 goto next;
101 break;
102 }
103
104 csum = fn(iter->data_buf, iter->interval);
105
106 if (pi->guard_tag != csum) {
107 pr_err("%s: guard tag error at sector %llu " \
108 "(rcvd %04x, want %04x)\n", iter->disk_name,
109 (unsigned long long)iter->seed,
110 be16_to_cpu(pi->guard_tag), be16_to_cpu(csum));
111 return -EILSEQ;
112 }
113
114next:
115 iter->data_buf += iter->interval;
116 iter->prot_buf += sizeof(struct t10_pi_tuple);
117 iter->seed++;
118 }
119
120 return 0;
121}
122
123static int t10_pi_type1_generate_crc(struct blk_integrity_iter *iter)
124{
125 return t10_pi_generate(iter, t10_pi_crc_fn, 1);
126}
127
128static int t10_pi_type1_generate_ip(struct blk_integrity_iter *iter)
129{
130 return t10_pi_generate(iter, t10_pi_ip_fn, 1);
131}
132
133static int t10_pi_type1_verify_crc(struct blk_integrity_iter *iter)
134{
135 return t10_pi_verify(iter, t10_pi_crc_fn, 1);
136}
137
138static int t10_pi_type1_verify_ip(struct blk_integrity_iter *iter)
139{
140 return t10_pi_verify(iter, t10_pi_ip_fn, 1);
141}
142
143static int t10_pi_type3_generate_crc(struct blk_integrity_iter *iter)
144{
145 return t10_pi_generate(iter, t10_pi_crc_fn, 3);
146}
147
148static int t10_pi_type3_generate_ip(struct blk_integrity_iter *iter)
149{
150 return t10_pi_generate(iter, t10_pi_ip_fn, 3);
151}
152
153static int t10_pi_type3_verify_crc(struct blk_integrity_iter *iter)
154{
155 return t10_pi_verify(iter, t10_pi_crc_fn, 3);
156}
157
158static int t10_pi_type3_verify_ip(struct blk_integrity_iter *iter)
159{
160 return t10_pi_verify(iter, t10_pi_ip_fn, 3);
161}
162
163struct blk_integrity t10_pi_type1_crc = {
164 .name = "T10-DIF-TYPE1-CRC",
165 .generate_fn = t10_pi_type1_generate_crc,
166 .verify_fn = t10_pi_type1_verify_crc,
167 .tuple_size = sizeof(struct t10_pi_tuple),
168 .tag_size = 0,
169};
170EXPORT_SYMBOL(t10_pi_type1_crc);
171
172struct blk_integrity t10_pi_type1_ip = {
173 .name = "T10-DIF-TYPE1-IP",
174 .generate_fn = t10_pi_type1_generate_ip,
175 .verify_fn = t10_pi_type1_verify_ip,
176 .tuple_size = sizeof(struct t10_pi_tuple),
177 .tag_size = 0,
178};
179EXPORT_SYMBOL(t10_pi_type1_ip);
180
181struct blk_integrity t10_pi_type3_crc = {
182 .name = "T10-DIF-TYPE3-CRC",
183 .generate_fn = t10_pi_type3_generate_crc,
184 .verify_fn = t10_pi_type3_verify_crc,
185 .tuple_size = sizeof(struct t10_pi_tuple),
186 .tag_size = 0,
187};
188EXPORT_SYMBOL(t10_pi_type3_crc);
189
190struct blk_integrity t10_pi_type3_ip = {
191 .name = "T10-DIF-TYPE3-IP",
192 .generate_fn = t10_pi_type3_generate_ip,
193 .verify_fn = t10_pi_type3_verify_ip,
194 .tuple_size = sizeof(struct t10_pi_tuple),
195 .tag_size = 0,
196};
197EXPORT_SYMBOL(t10_pi_type3_ip);
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index 18a3358eb1d4..9ece13f922a6 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -62,7 +62,6 @@ comment "SCSI support type (disk, tape, CD-ROM)"
62config BLK_DEV_SD 62config BLK_DEV_SD
63 tristate "SCSI disk support" 63 tristate "SCSI disk support"
64 depends on SCSI 64 depends on SCSI
65 select CRC_T10DIF if BLK_DEV_INTEGRITY
66 ---help--- 65 ---help---
67 If you want to use SCSI hard disks, Fibre Channel disks, 66 If you want to use SCSI hard disks, Fibre Channel disks,
68 Serial ATA (SATA) or Parallel ATA (PATA) hard disks, 67 Serial ATA (SATA) or Parallel ATA (PATA) hard disks,
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 @@
21 */ 21 */
22 22
23#include <linux/blkdev.h> 23#include <linux/blkdev.h>
24#include <linux/crc-t10dif.h> 24#include <linux/t10-pi.h>
25 25
26#include <scsi/scsi.h> 26#include <scsi/scsi.h>
27#include <scsi/scsi_cmnd.h> 27#include <scsi/scsi_cmnd.h>
@@ -33,207 +33,8 @@
33#include <scsi/scsi_ioctl.h> 33#include <scsi/scsi_ioctl.h>
34#include <scsi/scsicam.h> 34#include <scsi/scsicam.h>
35 35
36#include <net/checksum.h>
37
38#include "sd.h" 36#include "sd.h"
39 37
40typedef __u16 (csum_fn) (void *, unsigned int);
41
42static __u16 sd_dif_crc_fn(void *data, unsigned int len)
43{
44 return cpu_to_be16(crc_t10dif(data, len));
45}
46
47static __u16 sd_dif_ip_fn(void *data, unsigned int len)
48{
49 return ip_compute_csum(data, len);
50}
51
52/*
53 * Type 1 and Type 2 protection use the same format: 16 bit guard tag,
54 * 16 bit app tag, 32 bit reference tag.
55 */
56static void sd_dif_type1_generate(struct blk_integrity_iter *iter, csum_fn *fn)
57{
58 void *buf = iter->data_buf;
59 struct sd_dif_tuple *sdt = iter->prot_buf;
60 sector_t seed = iter->seed;
61 unsigned int i;
62
63 for (i = 0 ; i < iter->data_size ; i += iter->interval, sdt++) {
64 sdt->guard_tag = fn(buf, iter->interval);
65 sdt->ref_tag = cpu_to_be32(seed & 0xffffffff);
66 sdt->app_tag = 0;
67
68 buf += iter->interval;
69 seed++;
70 }
71}
72
73static int sd_dif_type1_generate_crc(struct blk_integrity_iter *iter)
74{
75 sd_dif_type1_generate(iter, sd_dif_crc_fn);
76 return 0;
77}
78
79static int sd_dif_type1_generate_ip(struct blk_integrity_iter *iter)
80{
81 sd_dif_type1_generate(iter, sd_dif_ip_fn);
82 return 0;
83}
84
85static int sd_dif_type1_verify(struct blk_integrity_iter *iter, csum_fn *fn)
86{
87 void *buf = iter->data_buf;
88 struct sd_dif_tuple *sdt = iter->prot_buf;
89 sector_t seed = iter->seed;
90 unsigned int i;
91 __u16 csum;
92
93 for (i = 0 ; i < iter->data_size ; i += iter->interval, sdt++) {
94 /* Unwritten sectors */
95 if (sdt->app_tag == 0xffff)
96 return 0;
97
98 if (be32_to_cpu(sdt->ref_tag) != (seed & 0xffffffff)) {
99 printk(KERN_ERR
100 "%s: ref tag error on sector %lu (rcvd %u)\n",
101 iter->disk_name, (unsigned long)seed,
102 be32_to_cpu(sdt->ref_tag));
103 return -EIO;
104 }
105
106 csum = fn(buf, iter->interval);
107
108 if (sdt->guard_tag != csum) {
109 printk(KERN_ERR "%s: guard tag error on sector %lu " \
110 "(rcvd %04x, data %04x)\n", iter->disk_name,
111 (unsigned long)seed,
112 be16_to_cpu(sdt->guard_tag), be16_to_cpu(csum));
113 return -EIO;
114 }
115
116 buf += iter->interval;
117 seed++;
118 }
119
120 return 0;
121}
122
123static int sd_dif_type1_verify_crc(struct blk_integrity_iter *iter)
124{
125 return sd_dif_type1_verify(iter, sd_dif_crc_fn);
126}
127
128static int sd_dif_type1_verify_ip(struct blk_integrity_iter *iter)
129{
130 return sd_dif_type1_verify(iter, sd_dif_ip_fn);
131}
132
133static struct blk_integrity dif_type1_integrity_crc = {
134 .name = "T10-DIF-TYPE1-CRC",
135 .generate_fn = sd_dif_type1_generate_crc,
136 .verify_fn = sd_dif_type1_verify_crc,
137 .tuple_size = sizeof(struct sd_dif_tuple),
138 .tag_size = 0,
139};
140
141static struct blk_integrity dif_type1_integrity_ip = {
142 .name = "T10-DIF-TYPE1-IP",
143 .generate_fn = sd_dif_type1_generate_ip,
144 .verify_fn = sd_dif_type1_verify_ip,
145 .tuple_size = sizeof(struct sd_dif_tuple),
146 .tag_size = 0,
147};
148
149
150/*
151 * Type 3 protection has a 16-bit guard tag and 16 + 32 bits of opaque
152 * tag space.
153 */
154static void sd_dif_type3_generate(struct blk_integrity_iter *iter, csum_fn *fn)
155{
156 void *buf = iter->data_buf;
157 struct sd_dif_tuple *sdt = iter->prot_buf;
158 unsigned int i;
159
160 for (i = 0 ; i < iter->data_size ; i += iter->interval, sdt++) {
161 sdt->guard_tag = fn(buf, iter->interval);
162 sdt->ref_tag = 0;
163 sdt->app_tag = 0;
164
165 buf += iter->interval;
166 }
167}
168
169static int sd_dif_type3_generate_crc(struct blk_integrity_iter *iter)
170{
171 sd_dif_type3_generate(iter, sd_dif_crc_fn);
172 return 0;
173}
174
175static int sd_dif_type3_generate_ip(struct blk_integrity_iter *iter)
176{
177 sd_dif_type3_generate(iter, sd_dif_ip_fn);
178 return 0;
179}
180
181static int sd_dif_type3_verify(struct blk_integrity_iter *iter, csum_fn *fn)
182{
183 void *buf = iter->data_buf;
184 struct sd_dif_tuple *sdt = iter->prot_buf;
185 sector_t seed = iter->seed;
186 unsigned int i;
187 __u16 csum;
188
189 for (i = 0 ; i < iter->data_size ; i += iter->interval, sdt++) {
190 /* Unwritten sectors */
191 if (sdt->app_tag == 0xffff && sdt->ref_tag == 0xffffffff)
192 return 0;
193
194 csum = fn(buf, iter->interval);
195
196 if (sdt->guard_tag != csum) {
197 printk(KERN_ERR "%s: guard tag error on sector %lu " \
198 "(rcvd %04x, data %04x)\n", iter->disk_name,
199 (unsigned long)seed,
200 be16_to_cpu(sdt->guard_tag), be16_to_cpu(csum));
201 return -EIO;
202 }
203
204 buf += iter->interval;
205 seed++;
206 }
207
208 return 0;
209}
210
211static int sd_dif_type3_verify_crc(struct blk_integrity_iter *iter)
212{
213 return sd_dif_type3_verify(iter, sd_dif_crc_fn);
214}
215
216static int sd_dif_type3_verify_ip(struct blk_integrity_iter *iter)
217{
218 return sd_dif_type3_verify(iter, sd_dif_ip_fn);
219}
220
221static struct blk_integrity dif_type3_integrity_crc = {
222 .name = "T10-DIF-TYPE3-CRC",
223 .generate_fn = sd_dif_type3_generate_crc,
224 .verify_fn = sd_dif_type3_verify_crc,
225 .tuple_size = sizeof(struct sd_dif_tuple),
226 .tag_size = 0,
227};
228
229static struct blk_integrity dif_type3_integrity_ip = {
230 .name = "T10-DIF-TYPE3-IP",
231 .generate_fn = sd_dif_type3_generate_ip,
232 .verify_fn = sd_dif_type3_verify_ip,
233 .tuple_size = sizeof(struct sd_dif_tuple),
234 .tag_size = 0,
235};
236
237/* 38/*
238 * Configure exchange of protection information between OS and HBA. 39 * Configure exchange of protection information between OS and HBA.
239 */ 40 */
@@ -257,16 +58,16 @@ void sd_dif_config_host(struct scsi_disk *sdkp)
257 /* Enable DMA of protection information */ 58 /* Enable DMA of protection information */
258 if (scsi_host_get_guard(sdkp->device->host) & SHOST_DIX_GUARD_IP) { 59 if (scsi_host_get_guard(sdkp->device->host) & SHOST_DIX_GUARD_IP) {
259 if (type == SD_DIF_TYPE3_PROTECTION) 60 if (type == SD_DIF_TYPE3_PROTECTION)
260 blk_integrity_register(disk, &dif_type3_integrity_ip); 61 blk_integrity_register(disk, &t10_pi_type3_ip);
261 else 62 else
262 blk_integrity_register(disk, &dif_type1_integrity_ip); 63 blk_integrity_register(disk, &t10_pi_type1_ip);
263 64
264 disk->integrity->flags |= BLK_INTEGRITY_IP_CHECKSUM; 65 disk->integrity->flags |= BLK_INTEGRITY_IP_CHECKSUM;
265 } else 66 } else
266 if (type == SD_DIF_TYPE3_PROTECTION) 67 if (type == SD_DIF_TYPE3_PROTECTION)
267 blk_integrity_register(disk, &dif_type3_integrity_crc); 68 blk_integrity_register(disk, &t10_pi_type3_crc);
268 else 69 else
269 blk_integrity_register(disk, &dif_type1_integrity_crc); 70 blk_integrity_register(disk, &t10_pi_type1_crc);
270 71
271 sd_printk(KERN_NOTICE, sdkp, 72 sd_printk(KERN_NOTICE, sdkp,
272 "Enabling DIX %s protection\n", disk->integrity->name); 73 "Enabling DIX %s protection\n", disk->integrity->name);
@@ -308,10 +109,10 @@ void sd_dif_config_host(struct scsi_disk *sdkp)
308void sd_dif_prepare(struct request *rq, sector_t hw_sector, 109void sd_dif_prepare(struct request *rq, sector_t hw_sector,
309 unsigned int sector_sz) 110 unsigned int sector_sz)
310{ 111{
311 const int tuple_sz = sizeof(struct sd_dif_tuple); 112 const int tuple_sz = sizeof(struct t10_pi_tuple);
312 struct bio *bio; 113 struct bio *bio;
313 struct scsi_disk *sdkp; 114 struct scsi_disk *sdkp;
314 struct sd_dif_tuple *sdt; 115 struct t10_pi_tuple *pi;
315 u32 phys, virt; 116 u32 phys, virt;
316 117
317 sdkp = rq->bio->bi_bdev->bd_disk->private_data; 118 sdkp = rq->bio->bi_bdev->bd_disk->private_data;
@@ -334,19 +135,18 @@ void sd_dif_prepare(struct request *rq, sector_t hw_sector,
334 virt = bip_get_seed(bip) & 0xffffffff; 135 virt = bip_get_seed(bip) & 0xffffffff;
335 136
336 bip_for_each_vec(iv, bip, iter) { 137 bip_for_each_vec(iv, bip, iter) {
337 sdt = kmap_atomic(iv.bv_page) 138 pi = kmap_atomic(iv.bv_page) + iv.bv_offset;
338 + iv.bv_offset;
339 139
340 for (j = 0; j < iv.bv_len; j += tuple_sz, sdt++) { 140 for (j = 0; j < iv.bv_len; j += tuple_sz, pi++) {
341 141
342 if (be32_to_cpu(sdt->ref_tag) == virt) 142 if (be32_to_cpu(pi->ref_tag) == virt)
343 sdt->ref_tag = cpu_to_be32(phys); 143 pi->ref_tag = cpu_to_be32(phys);
344 144
345 virt++; 145 virt++;
346 phys++; 146 phys++;
347 } 147 }
348 148
349 kunmap_atomic(sdt); 149 kunmap_atomic(pi);
350 } 150 }
351 151
352 bip->bip_flags |= BIP_MAPPED_INTEGRITY; 152 bip->bip_flags |= BIP_MAPPED_INTEGRITY;
@@ -359,10 +159,10 @@ void sd_dif_prepare(struct request *rq, sector_t hw_sector,
359 */ 159 */
360void sd_dif_complete(struct scsi_cmnd *scmd, unsigned int good_bytes) 160void sd_dif_complete(struct scsi_cmnd *scmd, unsigned int good_bytes)
361{ 161{
362 const int tuple_sz = sizeof(struct sd_dif_tuple); 162 const int tuple_sz = sizeof(struct t10_pi_tuple);
363 struct scsi_disk *sdkp; 163 struct scsi_disk *sdkp;
364 struct bio *bio; 164 struct bio *bio;
365 struct sd_dif_tuple *sdt; 165 struct t10_pi_tuple *pi;
366 unsigned int j, sectors, sector_sz; 166 unsigned int j, sectors, sector_sz;
367 u32 phys, virt; 167 u32 phys, virt;
368 168
@@ -386,25 +186,24 @@ void sd_dif_complete(struct scsi_cmnd *scmd, unsigned int good_bytes)
386 virt = bip_get_seed(bip) & 0xffffffff; 186 virt = bip_get_seed(bip) & 0xffffffff;
387 187
388 bip_for_each_vec(iv, bip, iter) { 188 bip_for_each_vec(iv, bip, iter) {
389 sdt = kmap_atomic(iv.bv_page) 189 pi = kmap_atomic(iv.bv_page) + iv.bv_offset;
390 + iv.bv_offset;
391 190
392 for (j = 0; j < iv.bv_len; j += tuple_sz, sdt++) { 191 for (j = 0; j < iv.bv_len; j += tuple_sz, pi++) {
393 192
394 if (sectors == 0) { 193 if (sectors == 0) {
395 kunmap_atomic(sdt); 194 kunmap_atomic(pi);
396 return; 195 return;
397 } 196 }
398 197
399 if (be32_to_cpu(sdt->ref_tag) == phys) 198 if (be32_to_cpu(pi->ref_tag) == phys)
400 sdt->ref_tag = cpu_to_be32(virt); 199 pi->ref_tag = cpu_to_be32(virt);
401 200
402 virt++; 201 virt++;
403 phys++; 202 phys++;
404 sectors--; 203 sectors--;
405 } 204 }
406 205
407 kunmap_atomic(sdt); 206 kunmap_atomic(pi);
408 } 207 }
409 } 208 }
410} 209}
diff --git a/include/linux/crc-t10dif.h b/include/linux/crc-t10dif.h
index b3cb71f0d3b0..cf53d0773ce3 100644
--- a/include/linux/crc-t10dif.h
+++ b/include/linux/crc-t10dif.h
@@ -6,7 +6,8 @@
6#define CRC_T10DIF_DIGEST_SIZE 2 6#define CRC_T10DIF_DIGEST_SIZE 2
7#define CRC_T10DIF_BLOCK_SIZE 1 7#define CRC_T10DIF_BLOCK_SIZE 1
8 8
9__u16 crc_t10dif_generic(__u16 crc, const unsigned char *buffer, size_t len); 9extern __u16 crc_t10dif_generic(__u16 crc, const unsigned char *buffer,
10__u16 crc_t10dif(unsigned char const *, size_t); 10 size_t len);
11extern __u16 crc_t10dif(unsigned char const *, size_t);
11 12
12#endif 13#endif
diff --git a/include/linux/t10-pi.h b/include/linux/t10-pi.h
new file mode 100644
index 000000000000..6a8b9942632d
--- /dev/null
+++ b/include/linux/t10-pi.h
@@ -0,0 +1,22 @@
1#ifndef _LINUX_T10_PI_H
2#define _LINUX_T10_PI_H
3
4#include <linux/types.h>
5#include <linux/blkdev.h>
6
7/*
8 * T10 Protection Information tuple.
9 */
10struct t10_pi_tuple {
11 __be16 guard_tag; /* Checksum */
12 __be16 app_tag; /* Opaque storage */
13 __be32 ref_tag; /* Target LBA or indirect LBA */
14};
15
16
17extern struct blk_integrity t10_pi_type1_crc;
18extern struct blk_integrity t10_pi_type1_ip;
19extern struct blk_integrity t10_pi_type3_crc;
20extern struct blk_integrity t10_pi_type3_ip;
21
22#endif