diff options
-rw-r--r-- | block/Kconfig | 1 | ||||
-rw-r--r-- | block/Makefile | 4 | ||||
-rw-r--r-- | block/t10-pi.c | 197 | ||||
-rw-r--r-- | drivers/scsi/Kconfig | 1 | ||||
-rw-r--r-- | drivers/scsi/sd_dif.c | 241 | ||||
-rw-r--r-- | include/linux/crc-t10dif.h | 5 | ||||
-rw-r--r-- | include/linux/t10-pi.h | 22 |
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 | ||
78 | config BLK_DEV_INTEGRITY | 78 | config 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 | |||
20 | obj-$(CONFIG_IOSCHED_CFQ) += cfq-iosched.o | 20 | obj-$(CONFIG_IOSCHED_CFQ) += cfq-iosched.o |
21 | 21 | ||
22 | obj-$(CONFIG_BLOCK_COMPAT) += compat_ioctl.o | 22 | obj-$(CONFIG_BLOCK_COMPAT) += compat_ioctl.o |
23 | obj-$(CONFIG_BLK_DEV_INTEGRITY) += blk-integrity.o | ||
24 | obj-$(CONFIG_BLK_CMDLINE_PARSER) += cmdline-parser.o | 23 | obj-$(CONFIG_BLK_CMDLINE_PARSER) += cmdline-parser.o |
25 | obj-$(CONFIG_BLK_DEV_INTEGRITY) += bio-integrity.o | 24 | obj-$(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 | |||
29 | typedef __be16 (csum_fn) (void *, unsigned int); | ||
30 | |||
31 | static const __be16 APP_ESCAPE = (__force __be16) 0xffff; | ||
32 | static const __be32 REF_ESCAPE = (__force __be32) 0xffffffff; | ||
33 | |||
34 | static __be16 t10_pi_crc_fn(void *data, unsigned int len) | ||
35 | { | ||
36 | return cpu_to_be16(crc_t10dif(data, len)); | ||
37 | } | ||
38 | |||
39 | static __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 | */ | ||
49 | static 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 | |||
73 | static 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 | |||
114 | next: | ||
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 | |||
123 | static 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 | |||
128 | static 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 | |||
133 | static 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 | |||
138 | static 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 | |||
143 | static 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 | |||
148 | static 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 | |||
153 | static 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 | |||
158 | static 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 | |||
163 | struct 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 | }; | ||
170 | EXPORT_SYMBOL(t10_pi_type1_crc); | ||
171 | |||
172 | struct 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 | }; | ||
179 | EXPORT_SYMBOL(t10_pi_type1_ip); | ||
180 | |||
181 | struct 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 | }; | ||
188 | EXPORT_SYMBOL(t10_pi_type3_crc); | ||
189 | |||
190 | struct 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 | }; | ||
197 | EXPORT_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)" | |||
62 | config BLK_DEV_SD | 62 | config 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 | ||
40 | typedef __u16 (csum_fn) (void *, unsigned int); | ||
41 | |||
42 | static __u16 sd_dif_crc_fn(void *data, unsigned int len) | ||
43 | { | ||
44 | return cpu_to_be16(crc_t10dif(data, len)); | ||
45 | } | ||
46 | |||
47 | static __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 | */ | ||
56 | static 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 | |||
73 | static 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 | |||
79 | static 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 | |||
85 | static 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 | |||
123 | static 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 | |||
128 | static 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 | |||
133 | static 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 | |||
141 | static 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 | */ | ||
154 | static 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 | |||
169 | static 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 | |||
175 | static 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 | |||
181 | static 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 | |||
211 | static 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 | |||
216 | static 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 | |||
221 | static 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 | |||
229 | static 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) | |||
308 | void sd_dif_prepare(struct request *rq, sector_t hw_sector, | 109 | void 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 | */ |
360 | void sd_dif_complete(struct scsi_cmnd *scmd, unsigned int good_bytes) | 160 | void 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); | 9 | extern __u16 crc_t10dif_generic(__u16 crc, const unsigned char *buffer, |
10 | __u16 crc_t10dif(unsigned char const *, size_t); | 10 | size_t len); |
11 | extern __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 | */ | ||
10 | struct 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 | |||
17 | extern struct blk_integrity t10_pi_type1_crc; | ||
18 | extern struct blk_integrity t10_pi_type1_ip; | ||
19 | extern struct blk_integrity t10_pi_type3_crc; | ||
20 | extern struct blk_integrity t10_pi_type3_ip; | ||
21 | |||
22 | #endif | ||