26 #include <scsi/scsi.h>
42 static __u16 sd_dif_crc_fn(
void *
data,
unsigned int len)
47 static __u16 sd_dif_ip_fn(
void *
data,
unsigned int len)
56 static void sd_dif_type1_generate(
struct blk_integrity_exchg *
bix,
csum_fn *
fn)
58 void *
buf = bix->data_buf;
63 for (i = 0 ; i < bix->data_size ; i += bix->sector_size, sdt++) {
68 buf += bix->sector_size;
73 static void sd_dif_type1_generate_crc(
struct blk_integrity_exchg *bix)
75 sd_dif_type1_generate(bix, sd_dif_crc_fn);
78 static void sd_dif_type1_generate_ip(
struct blk_integrity_exchg *bix)
80 sd_dif_type1_generate(bix, sd_dif_ip_fn);
83 static int sd_dif_type1_verify(
struct blk_integrity_exchg *bix,
csum_fn *fn)
85 void *buf = bix->data_buf;
91 for (i = 0 ; i < bix->data_size ; i += bix->sector_size, sdt++) {
97 if (sdt->
ref_tag == 0xffffffff) {
99 "%s: bad phys ref tag on sector %lu\n",
100 bix->disk_name, (
unsigned long)sector);
106 "%s: ref tag error on sector %lu (rcvd %u)\n",
107 bix->disk_name, (
unsigned long)sector,
112 csum =
fn(buf, bix->sector_size);
116 "(rcvd %04x, data %04x)\n", bix->disk_name,
117 (
unsigned long)sector,
122 buf += bix->sector_size;
129 static int sd_dif_type1_verify_crc(
struct blk_integrity_exchg *bix)
131 return sd_dif_type1_verify(bix, sd_dif_crc_fn);
134 static int sd_dif_type1_verify_ip(
struct blk_integrity_exchg *bix)
136 return sd_dif_type1_verify(bix, sd_dif_ip_fn);
142 static void sd_dif_type1_set_tag(
void *prot,
void *tag_buf,
unsigned int sectors)
148 for (i = 0, j = 0 ; i <
sectors ; i++, j += 2, sdt++) {
149 sdt->
app_tag = tag[
j] << 8 | tag[j+1];
154 static void sd_dif_type1_get_tag(
void *prot,
void *tag_buf,
unsigned int sectors)
160 for (i = 0, j = 0 ; i <
sectors ; i++, j += 2, sdt++) {
161 tag[
j] = (sdt->
app_tag & 0xff00) >> 8;
162 tag[j+1] = sdt->
app_tag & 0xff;
166 static struct blk_integrity dif_type1_integrity_crc = {
167 .name =
"T10-DIF-TYPE1-CRC",
168 .generate_fn = sd_dif_type1_generate_crc,
169 .verify_fn = sd_dif_type1_verify_crc,
170 .get_tag_fn = sd_dif_type1_get_tag,
171 .set_tag_fn = sd_dif_type1_set_tag,
176 static struct blk_integrity dif_type1_integrity_ip = {
177 .name =
"T10-DIF-TYPE1-IP",
178 .generate_fn = sd_dif_type1_generate_ip,
179 .verify_fn = sd_dif_type1_verify_ip,
180 .get_tag_fn = sd_dif_type1_get_tag,
181 .set_tag_fn = sd_dif_type1_set_tag,
191 static void sd_dif_type3_generate(
struct blk_integrity_exchg *bix,
csum_fn *fn)
193 void *buf = bix->data_buf;
197 for (i = 0 ; i < bix->data_size ; i += bix->sector_size, sdt++) {
202 buf += bix->sector_size;
206 static void sd_dif_type3_generate_crc(
struct blk_integrity_exchg *bix)
208 sd_dif_type3_generate(bix, sd_dif_crc_fn);
211 static void sd_dif_type3_generate_ip(
struct blk_integrity_exchg *bix)
213 sd_dif_type3_generate(bix, sd_dif_ip_fn);
216 static int sd_dif_type3_verify(
struct blk_integrity_exchg *bix,
csum_fn *fn)
218 void *buf = bix->data_buf;
224 for (i = 0 ; i < bix->data_size ; i += bix->sector_size, sdt++) {
229 csum =
fn(buf, bix->sector_size);
233 "(rcvd %04x, data %04x)\n", bix->disk_name,
234 (
unsigned long)sector,
239 buf += bix->sector_size;
246 static int sd_dif_type3_verify_crc(
struct blk_integrity_exchg *bix)
248 return sd_dif_type3_verify(bix, sd_dif_crc_fn);
251 static int sd_dif_type3_verify_ip(
struct blk_integrity_exchg *bix)
253 return sd_dif_type3_verify(bix, sd_dif_ip_fn);
256 static void sd_dif_type3_set_tag(
void *prot,
void *tag_buf,
unsigned int sectors)
262 for (i = 0, j = 0 ; i <
sectors ; i++, j += 6, sdt++) {
263 sdt->
app_tag = tag[
j] << 8 | tag[j+1];
264 sdt->
ref_tag = tag[j+2] << 24 | tag[j+3] << 16 |
265 tag[j+4] << 8 | tag[j+5];
269 static void sd_dif_type3_get_tag(
void *prot,
void *tag_buf,
unsigned int sectors)
275 for (i = 0, j = 0 ; i <
sectors ; i++, j += 2, sdt++) {
276 tag[
j] = (sdt->
app_tag & 0xff00) >> 8;
277 tag[j+1] = sdt->
app_tag & 0xff;
278 tag[j+2] = (sdt->
ref_tag & 0xff000000) >> 24;
279 tag[j+3] = (sdt->
ref_tag & 0xff0000) >> 16;
280 tag[j+4] = (sdt->
ref_tag & 0xff00) >> 8;
281 tag[j+5] = sdt->
ref_tag & 0xff;
286 static struct blk_integrity dif_type3_integrity_crc = {
287 .name =
"T10-DIF-TYPE3-CRC",
288 .generate_fn = sd_dif_type3_generate_crc,
289 .verify_fn = sd_dif_type3_verify_crc,
290 .get_tag_fn = sd_dif_type3_get_tag,
291 .set_tag_fn = sd_dif_type3_set_tag,
296 static struct blk_integrity dif_type3_integrity_ip = {
297 .name =
"T10-DIF-TYPE3-IP",
298 .generate_fn = sd_dif_type3_generate_ip,
299 .verify_fn = sd_dif_type3_verify_ip,
300 .get_tag_fn = sd_dif_type3_get_tag,
301 .set_tag_fn = sd_dif_type3_set_tag,
312 struct gendisk *disk = sdkp->
disk;
316 dif = scsi_host_dif_capable(sdp->
host, type);
317 dix = scsi_host_dix_capable(sdp->
host, type);
319 if (!dix && scsi_host_dix_capable(sdp->
host, 0)) {
339 "Enabling DIX %s protection\n", disk->integrity->name);
342 if (dif && type && sdkp->
ATO) {
344 disk->integrity->tag_size =
sizeof(
u16) +
sizeof(
u32);
346 disk->integrity->tag_size =
sizeof(
u16);
349 disk->integrity->tag_size);
370 unsigned int sector_sz)
379 sdkp = rq->bio->bi_bdev->bd_disk->private_data;
384 phys = hw_sector & 0xffffffff;
386 __rq_for_each_bio(bio, rq) {
390 if (bio_flagged(bio, BIO_MAPPED_INTEGRITY))
393 virt = bio->bi_integrity->bip_sector & 0xffffffff;
395 bip_for_each_vec(iv, bio->bi_integrity, i) {
399 for (j = 0 ; j < iv->bv_len ; j += tuple_sz, sdt++) {
411 bio->bi_flags |= (1 << BIO_MAPPED_INTEGRITY);
433 sector_sz = scmd->
device->sector_size;
434 sectors = good_bytes / sector_sz;
436 phys = blk_rq_pos(scmd->
request) & 0xffffffff;
437 if (sector_sz == 4096)
440 __rq_for_each_bio(bio, scmd->
request) {
443 virt = bio->bi_integrity->bip_sector & 0xffffffff;
445 bip_for_each_vec(iv, bio->bi_integrity, i) {
449 for (j = 0 ; j < iv->bv_len ; j += tuple_sz, sdt++) {