aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin K. Petersen <martin.petersen@oracle.com>2014-09-26 19:20:08 -0400
committerJens Axboe <axboe@fb.com>2014-09-30 17:17:35 -0400
commitc611529e7cd3465ec0eada0f44200e8420c38908 (patch)
treec1cbfbd9b3229906ec36c897761d06e1521823bd
parent582940508b5d589229d0232e0eeee8fef0d54809 (diff)
sd: Honor block layer integrity handling flags
A set of flags introduced in the block layer enable better control over how protection information is handled. These flags are useful for both error injection and data recovery purposes. Checking can be enabled and disabled for controller and disk, and the guard tag format is now a per-I/O property. Update sd_protect_op to communicate the relevant information to the low-level device driver via a set of flags in scsi_cmnd. Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com> Reviewed-by: Sagi Grimberg <sagig@mellanox.com> Acked-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Jens Axboe <axboe@fb.com>
-rw-r--r--drivers/scsi/sd.c73
-rw-r--r--drivers/scsi/sd.h66
-rw-r--r--drivers/scsi/sd_dif.c23
-rw-r--r--include/linux/bio.h33
-rw-r--r--include/scsi/scsi_cmnd.h36
5 files changed, 166 insertions, 65 deletions
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 2c2041ca4b70..9f7099f4b537 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -610,29 +610,44 @@ static void scsi_disk_put(struct scsi_disk *sdkp)
610 mutex_unlock(&sd_ref_mutex); 610 mutex_unlock(&sd_ref_mutex);
611} 611}
612 612
613static void sd_prot_op(struct scsi_cmnd *scmd, unsigned int dif) 613
614{ 614
615 unsigned int prot_op = SCSI_PROT_NORMAL; 615static unsigned char sd_setup_protect_cmnd(struct scsi_cmnd *scmd,
616 unsigned int dix = scsi_prot_sg_count(scmd); 616 unsigned int dix, unsigned int dif)
617 617{
618 if (scmd->sc_data_direction == DMA_FROM_DEVICE) { 618 struct bio *bio = scmd->request->bio;
619 if (dif && dix) 619 unsigned int prot_op = sd_prot_op(rq_data_dir(scmd->request), dix, dif);
620 prot_op = SCSI_PROT_READ_PASS; 620 unsigned int protect = 0;
621 else if (dif && !dix) 621
622 prot_op = SCSI_PROT_READ_STRIP; 622 if (dix) { /* DIX Type 0, 1, 2, 3 */
623 else if (!dif && dix) 623 if (bio_integrity_flagged(bio, BIP_IP_CHECKSUM))
624 prot_op = SCSI_PROT_READ_INSERT; 624 scmd->prot_flags |= SCSI_PROT_IP_CHECKSUM;
625 } else { 625
626 if (dif && dix) 626 if (bio_integrity_flagged(bio, BIP_CTRL_NOCHECK) == false)
627 prot_op = SCSI_PROT_WRITE_PASS; 627 scmd->prot_flags |= SCSI_PROT_GUARD_CHECK;
628 else if (dif && !dix) 628 }
629 prot_op = SCSI_PROT_WRITE_INSERT; 629
630 else if (!dif && dix) 630 if (dif != SD_DIF_TYPE3_PROTECTION) { /* DIX/DIF Type 0, 1, 2 */
631 prot_op = SCSI_PROT_WRITE_STRIP; 631 scmd->prot_flags |= SCSI_PROT_REF_INCREMENT;
632
633 if (bio_integrity_flagged(bio, BIP_CTRL_NOCHECK) == false)
634 scmd->prot_flags |= SCSI_PROT_REF_CHECK;
635 }
636
637 if (dif) { /* DIX/DIF Type 1, 2, 3 */
638 scmd->prot_flags |= SCSI_PROT_TRANSFER_PI;
639
640 if (bio_integrity_flagged(bio, BIP_DISK_NOCHECK))
641 protect = 3 << 5; /* Disable target PI checking */
642 else
643 protect = 1 << 5; /* Enable target PI checking */
632 } 644 }
633 645
634 scsi_set_prot_op(scmd, prot_op); 646 scsi_set_prot_op(scmd, prot_op);
635 scsi_set_prot_type(scmd, dif); 647 scsi_set_prot_type(scmd, dif);
648 scmd->prot_flags &= sd_prot_flag_mask(prot_op);
649
650 return protect;
636} 651}
637 652
638static void sd_config_discard(struct scsi_disk *sdkp, unsigned int mode) 653static void sd_config_discard(struct scsi_disk *sdkp, unsigned int mode)
@@ -893,7 +908,8 @@ static int sd_setup_read_write_cmnd(struct scsi_cmnd *SCpnt)
893 sector_t block = blk_rq_pos(rq); 908 sector_t block = blk_rq_pos(rq);
894 sector_t threshold; 909 sector_t threshold;
895 unsigned int this_count = blk_rq_sectors(rq); 910 unsigned int this_count = blk_rq_sectors(rq);
896 int ret, host_dif; 911 unsigned int dif, dix;
912 int ret;
897 unsigned char protect; 913 unsigned char protect;
898 914
899 ret = scsi_init_io(SCpnt, GFP_ATOMIC); 915 ret = scsi_init_io(SCpnt, GFP_ATOMIC);
@@ -995,7 +1011,7 @@ static int sd_setup_read_write_cmnd(struct scsi_cmnd *SCpnt)
995 SCpnt->cmnd[0] = WRITE_6; 1011 SCpnt->cmnd[0] = WRITE_6;
996 1012
997 if (blk_integrity_rq(rq)) 1013 if (blk_integrity_rq(rq))
998 sd_dif_prepare(rq, block, sdp->sector_size); 1014 sd_dif_prepare(SCpnt);
999 1015
1000 } else if (rq_data_dir(rq) == READ) { 1016 } else if (rq_data_dir(rq) == READ) {
1001 SCpnt->cmnd[0] = READ_6; 1017 SCpnt->cmnd[0] = READ_6;
@@ -1010,14 +1026,15 @@ static int sd_setup_read_write_cmnd(struct scsi_cmnd *SCpnt)
1010 "writing" : "reading", this_count, 1026 "writing" : "reading", this_count,
1011 blk_rq_sectors(rq))); 1027 blk_rq_sectors(rq)));
1012 1028
1013 /* Set RDPROTECT/WRPROTECT if disk is formatted with DIF */ 1029 dix = scsi_prot_sg_count(SCpnt);
1014 host_dif = scsi_host_dif_capable(sdp->host, sdkp->protection_type); 1030 dif = scsi_host_dif_capable(SCpnt->device->host, sdkp->protection_type);
1015 if (host_dif) 1031
1016 protect = 1 << 5; 1032 if (dif || dix)
1033 protect = sd_setup_protect_cmnd(SCpnt, dix, dif);
1017 else 1034 else
1018 protect = 0; 1035 protect = 0;
1019 1036
1020 if (host_dif == SD_DIF_TYPE2_PROTECTION) { 1037 if (protect && sdkp->protection_type == SD_DIF_TYPE2_PROTECTION) {
1021 SCpnt->cmnd = mempool_alloc(sd_cdb_pool, GFP_ATOMIC); 1038 SCpnt->cmnd = mempool_alloc(sd_cdb_pool, GFP_ATOMIC);
1022 1039
1023 if (unlikely(SCpnt->cmnd == NULL)) { 1040 if (unlikely(SCpnt->cmnd == NULL)) {
@@ -1102,10 +1119,6 @@ static int sd_setup_read_write_cmnd(struct scsi_cmnd *SCpnt)
1102 } 1119 }
1103 SCpnt->sdb.length = this_count * sdp->sector_size; 1120 SCpnt->sdb.length = this_count * sdp->sector_size;
1104 1121
1105 /* If DIF or DIX is enabled, tell HBA how to handle request */
1106 if (host_dif || scsi_prot_sg_count(SCpnt))
1107 sd_prot_op(SCpnt, host_dif);
1108
1109 /* 1122 /*
1110 * We shouldn't disconnect in the middle of a sector, so with a dumb 1123 * We shouldn't disconnect in the middle of a sector, so with a dumb
1111 * host adapter, it's safe to assume that we can at least transfer 1124 * host adapter, it's safe to assume that we can at least transfer
diff --git a/drivers/scsi/sd.h b/drivers/scsi/sd.h
index 4c3ab8377fd3..467377884b63 100644
--- a/drivers/scsi/sd.h
+++ b/drivers/scsi/sd.h
@@ -167,6 +167,68 @@ enum sd_dif_target_protection_types {
167}; 167};
168 168
169/* 169/*
170 * Look up the DIX operation based on whether the command is read or
171 * write and whether dix and dif are enabled.
172 */
173static inline unsigned int sd_prot_op(bool write, bool dix, bool dif)
174{
175 /* Lookup table: bit 2 (write), bit 1 (dix), bit 0 (dif) */
176 const unsigned int ops[] = { /* wrt dix dif */
177 SCSI_PROT_NORMAL, /* 0 0 0 */
178 SCSI_PROT_READ_STRIP, /* 0 0 1 */
179 SCSI_PROT_READ_INSERT, /* 0 1 0 */
180 SCSI_PROT_READ_PASS, /* 0 1 1 */
181 SCSI_PROT_NORMAL, /* 1 0 0 */
182 SCSI_PROT_WRITE_INSERT, /* 1 0 1 */
183 SCSI_PROT_WRITE_STRIP, /* 1 1 0 */
184 SCSI_PROT_WRITE_PASS, /* 1 1 1 */
185 };
186
187 return ops[write << 2 | dix << 1 | dif];
188}
189
190/*
191 * Returns a mask of the protection flags that are valid for a given DIX
192 * operation.
193 */
194static inline unsigned int sd_prot_flag_mask(unsigned int prot_op)
195{
196 const unsigned int flag_mask[] = {
197 [SCSI_PROT_NORMAL] = 0,
198
199 [SCSI_PROT_READ_STRIP] = SCSI_PROT_TRANSFER_PI |
200 SCSI_PROT_GUARD_CHECK |
201 SCSI_PROT_REF_CHECK |
202 SCSI_PROT_REF_INCREMENT,
203
204 [SCSI_PROT_READ_INSERT] = SCSI_PROT_REF_INCREMENT |
205 SCSI_PROT_IP_CHECKSUM,
206
207 [SCSI_PROT_READ_PASS] = SCSI_PROT_TRANSFER_PI |
208 SCSI_PROT_GUARD_CHECK |
209 SCSI_PROT_REF_CHECK |
210 SCSI_PROT_REF_INCREMENT |
211 SCSI_PROT_IP_CHECKSUM,
212
213 [SCSI_PROT_WRITE_INSERT] = SCSI_PROT_TRANSFER_PI |
214 SCSI_PROT_REF_INCREMENT,
215
216 [SCSI_PROT_WRITE_STRIP] = SCSI_PROT_GUARD_CHECK |
217 SCSI_PROT_REF_CHECK |
218 SCSI_PROT_REF_INCREMENT |
219 SCSI_PROT_IP_CHECKSUM,
220
221 [SCSI_PROT_WRITE_PASS] = SCSI_PROT_TRANSFER_PI |
222 SCSI_PROT_GUARD_CHECK |
223 SCSI_PROT_REF_CHECK |
224 SCSI_PROT_REF_INCREMENT |
225 SCSI_PROT_IP_CHECKSUM,
226 };
227
228 return flag_mask[prot_op];
229}
230
231/*
170 * Data Integrity Field tuple. 232 * Data Integrity Field tuple.
171 */ 233 */
172struct sd_dif_tuple { 234struct sd_dif_tuple {
@@ -178,7 +240,7 @@ struct sd_dif_tuple {
178#ifdef CONFIG_BLK_DEV_INTEGRITY 240#ifdef CONFIG_BLK_DEV_INTEGRITY
179 241
180extern void sd_dif_config_host(struct scsi_disk *); 242extern void sd_dif_config_host(struct scsi_disk *);
181extern void sd_dif_prepare(struct request *rq, sector_t, unsigned int); 243extern void sd_dif_prepare(struct scsi_cmnd *scmd);
182extern void sd_dif_complete(struct scsi_cmnd *, unsigned int); 244extern void sd_dif_complete(struct scsi_cmnd *, unsigned int);
183 245
184#else /* CONFIG_BLK_DEV_INTEGRITY */ 246#else /* CONFIG_BLK_DEV_INTEGRITY */
@@ -186,7 +248,7 @@ extern void sd_dif_complete(struct scsi_cmnd *, unsigned int);
186static inline void sd_dif_config_host(struct scsi_disk *disk) 248static inline void sd_dif_config_host(struct scsi_disk *disk)
187{ 249{
188} 250}
189static inline int sd_dif_prepare(struct request *rq, sector_t s, unsigned int a) 251static inline int sd_dif_prepare(struct scsi_cmnd *scmd)
190{ 252{
191 return 0; 253 return 0;
192} 254}
diff --git a/drivers/scsi/sd_dif.c b/drivers/scsi/sd_dif.c
index b7eaeadc18f9..14c7d42a11c2 100644
--- a/drivers/scsi/sd_dif.c
+++ b/drivers/scsi/sd_dif.c
@@ -106,8 +106,7 @@ void sd_dif_config_host(struct scsi_disk *sdkp)
106 * 106 *
107 * Type 3 does not have a reference tag so no remapping is required. 107 * Type 3 does not have a reference tag so no remapping is required.
108 */ 108 */
109void sd_dif_prepare(struct request *rq, sector_t hw_sector, 109void sd_dif_prepare(struct scsi_cmnd *scmd)
110 unsigned int sector_sz)
111{ 110{
112 const int tuple_sz = sizeof(struct t10_pi_tuple); 111 const int tuple_sz = sizeof(struct t10_pi_tuple);
113 struct bio *bio; 112 struct bio *bio;
@@ -115,14 +114,14 @@ void sd_dif_prepare(struct request *rq, sector_t hw_sector,
115 struct t10_pi_tuple *pi; 114 struct t10_pi_tuple *pi;
116 u32 phys, virt; 115 u32 phys, virt;
117 116
118 sdkp = rq->bio->bi_bdev->bd_disk->private_data; 117 sdkp = scsi_disk(scmd->request->rq_disk);
119 118
120 if (sdkp->protection_type == SD_DIF_TYPE3_PROTECTION) 119 if (sdkp->protection_type == SD_DIF_TYPE3_PROTECTION)
121 return; 120 return;
122 121
123 phys = hw_sector & 0xffffffff; 122 phys = scsi_prot_ref_tag(scmd);
124 123
125 __rq_for_each_bio(bio, rq) { 124 __rq_for_each_bio(bio, scmd->request) {
126 struct bio_integrity_payload *bip = bio_integrity(bio); 125 struct bio_integrity_payload *bip = bio_integrity(bio);
127 struct bio_vec iv; 126 struct bio_vec iv;
128 struct bvec_iter iter; 127 struct bvec_iter iter;
@@ -163,7 +162,7 @@ void sd_dif_complete(struct scsi_cmnd *scmd, unsigned int good_bytes)
163 struct scsi_disk *sdkp; 162 struct scsi_disk *sdkp;
164 struct bio *bio; 163 struct bio *bio;
165 struct t10_pi_tuple *pi; 164 struct t10_pi_tuple *pi;
166 unsigned int j, sectors, sector_sz; 165 unsigned int j, intervals;
167 u32 phys, virt; 166 u32 phys, virt;
168 167
169 sdkp = scsi_disk(scmd->request->rq_disk); 168 sdkp = scsi_disk(scmd->request->rq_disk);
@@ -171,12 +170,8 @@ void sd_dif_complete(struct scsi_cmnd *scmd, unsigned int good_bytes)
171 if (sdkp->protection_type == SD_DIF_TYPE3_PROTECTION || good_bytes == 0) 170 if (sdkp->protection_type == SD_DIF_TYPE3_PROTECTION || good_bytes == 0)
172 return; 171 return;
173 172
174 sector_sz = scmd->device->sector_size; 173 intervals = good_bytes / scsi_prot_interval(scmd);
175 sectors = good_bytes / sector_sz; 174 phys = scsi_prot_ref_tag(scmd);
176
177 phys = blk_rq_pos(scmd->request) & 0xffffffff;
178 if (sector_sz == 4096)
179 phys >>= 3;
180 175
181 __rq_for_each_bio(bio, scmd->request) { 176 __rq_for_each_bio(bio, scmd->request) {
182 struct bio_integrity_payload *bip = bio_integrity(bio); 177 struct bio_integrity_payload *bip = bio_integrity(bio);
@@ -190,7 +185,7 @@ void sd_dif_complete(struct scsi_cmnd *scmd, unsigned int good_bytes)
190 185
191 for (j = 0; j < iv.bv_len; j += tuple_sz, pi++) { 186 for (j = 0; j < iv.bv_len; j += tuple_sz, pi++) {
192 187
193 if (sectors == 0) { 188 if (intervals == 0) {
194 kunmap_atomic(pi); 189 kunmap_atomic(pi);
195 return; 190 return;
196 } 191 }
@@ -200,7 +195,7 @@ void sd_dif_complete(struct scsi_cmnd *scmd, unsigned int good_bytes)
200 195
201 virt++; 196 virt++;
202 phys++; 197 phys++;
203 sectors--; 198 intervals--;
204 } 199 }
205 200
206 kunmap_atomic(pi); 201 kunmap_atomic(pi);
diff --git a/include/linux/bio.h b/include/linux/bio.h
index 14bff3fe56d4..ce6b75964b71 100644
--- a/include/linux/bio.h
+++ b/include/linux/bio.h
@@ -292,6 +292,14 @@ static inline unsigned bio_segments(struct bio *bio)
292 */ 292 */
293#define bio_get(bio) atomic_inc(&(bio)->bi_cnt) 293#define bio_get(bio) atomic_inc(&(bio)->bi_cnt)
294 294
295enum bip_flags {
296 BIP_BLOCK_INTEGRITY = 1 << 0, /* block layer owns integrity data */
297 BIP_MAPPED_INTEGRITY = 1 << 1, /* ref tag has been remapped */
298 BIP_CTRL_NOCHECK = 1 << 2, /* disable HBA integrity checking */
299 BIP_DISK_NOCHECK = 1 << 3, /* disable disk integrity checking */
300 BIP_IP_CHECKSUM = 1 << 4, /* IP checksum */
301};
302
295#if defined(CONFIG_BLK_DEV_INTEGRITY) 303#if defined(CONFIG_BLK_DEV_INTEGRITY)
296 304
297static inline struct bio_integrity_payload *bio_integrity(struct bio *bio) 305static inline struct bio_integrity_payload *bio_integrity(struct bio *bio)
@@ -323,13 +331,15 @@ struct bio_integrity_payload {
323 struct bio_vec bip_inline_vecs[0];/* embedded bvec array */ 331 struct bio_vec bip_inline_vecs[0];/* embedded bvec array */
324}; 332};
325 333
326enum bip_flags { 334static inline bool bio_integrity_flagged(struct bio *bio, enum bip_flags flag)
327 BIP_BLOCK_INTEGRITY = 1 << 0, /* block layer owns integrity data */ 335{
328 BIP_MAPPED_INTEGRITY = 1 << 1, /* ref tag has been remapped */ 336 struct bio_integrity_payload *bip = bio_integrity(bio);
329 BIP_CTRL_NOCHECK = 1 << 2, /* disable HBA integrity checking */ 337
330 BIP_DISK_NOCHECK = 1 << 3, /* disable disk integrity checking */ 338 if (bip)
331 BIP_IP_CHECKSUM = 1 << 4, /* IP checksum */ 339 return bip->bip_flags & flag;
332}; 340
341 return false;
342}
333 343
334static inline sector_t bip_get_seed(struct bio_integrity_payload *bip) 344static inline sector_t bip_get_seed(struct bio_integrity_payload *bip)
335{ 345{
@@ -701,9 +711,9 @@ extern void bio_integrity_init(void);
701 711
702#else /* CONFIG_BLK_DEV_INTEGRITY */ 712#else /* CONFIG_BLK_DEV_INTEGRITY */
703 713
704static inline int bio_integrity(struct bio *bio) 714static inline void *bio_integrity(struct bio *bio)
705{ 715{
706 return 0; 716 return NULL;
707} 717}
708 718
709static inline bool bio_integrity_enabled(struct bio *bio) 719static inline bool bio_integrity_enabled(struct bio *bio)
@@ -754,6 +764,11 @@ static inline void bio_integrity_init(void)
754 return; 764 return;
755} 765}
756 766
767static inline bool bio_integrity_flagged(struct bio *bio, enum bip_flags flag)
768{
769 return false;
770}
771
757#endif /* CONFIG_BLK_DEV_INTEGRITY */ 772#endif /* CONFIG_BLK_DEV_INTEGRITY */
758 773
759#endif /* CONFIG_BLOCK */ 774#endif /* CONFIG_BLOCK */
diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h
index 73f349044941..522a5f27f553 100644
--- a/include/scsi/scsi_cmnd.h
+++ b/include/scsi/scsi_cmnd.h
@@ -10,9 +10,10 @@
10#include <scsi/scsi_device.h> 10#include <scsi/scsi_device.h>
11 11
12struct Scsi_Host; 12struct Scsi_Host;
13struct scsi_device;
14struct scsi_driver; 13struct scsi_driver;
15 14
15#include <scsi/scsi_device.h>
16
16/* 17/*
17 * MAX_COMMAND_SIZE is: 18 * MAX_COMMAND_SIZE is:
18 * The longest fixed-length SCSI CDB as per the SCSI standard. 19 * The longest fixed-length SCSI CDB as per the SCSI standard.
@@ -81,6 +82,7 @@ struct scsi_cmnd {
81 82
82 unsigned char prot_op; 83 unsigned char prot_op;
83 unsigned char prot_type; 84 unsigned char prot_type;
85 unsigned char prot_flags;
84 86
85 unsigned short cmd_len; 87 unsigned short cmd_len;
86 enum dma_data_direction sc_data_direction; 88 enum dma_data_direction sc_data_direction;
@@ -252,6 +254,14 @@ static inline unsigned char scsi_get_prot_op(struct scsi_cmnd *scmd)
252 return scmd->prot_op; 254 return scmd->prot_op;
253} 255}
254 256
257enum scsi_prot_flags {
258 SCSI_PROT_TRANSFER_PI = 1 << 0,
259 SCSI_PROT_GUARD_CHECK = 1 << 1,
260 SCSI_PROT_REF_CHECK = 1 << 2,
261 SCSI_PROT_REF_INCREMENT = 1 << 3,
262 SCSI_PROT_IP_CHECKSUM = 1 << 4,
263};
264
255/* 265/*
256 * The controller usually does not know anything about the target it 266 * The controller usually does not know anything about the target it
257 * is communicating with. However, when DIX is enabled the controller 267 * is communicating with. However, when DIX is enabled the controller
@@ -280,6 +290,17 @@ static inline sector_t scsi_get_lba(struct scsi_cmnd *scmd)
280 return blk_rq_pos(scmd->request); 290 return blk_rq_pos(scmd->request);
281} 291}
282 292
293static inline unsigned int scsi_prot_interval(struct scsi_cmnd *scmd)
294{
295 return scmd->device->sector_size;
296}
297
298static inline u32 scsi_prot_ref_tag(struct scsi_cmnd *scmd)
299{
300 return blk_rq_pos(scmd->request) >>
301 (ilog2(scsi_prot_interval(scmd)) - 9) & 0xffffffff;
302}
303
283static inline unsigned scsi_prot_sg_count(struct scsi_cmnd *cmd) 304static inline unsigned scsi_prot_sg_count(struct scsi_cmnd *cmd)
284{ 305{
285 return cmd->prot_sdb ? cmd->prot_sdb->table.nents : 0; 306 return cmd->prot_sdb ? cmd->prot_sdb->table.nents : 0;
@@ -316,17 +337,12 @@ static inline void set_driver_byte(struct scsi_cmnd *cmd, char status)
316static inline unsigned scsi_transfer_length(struct scsi_cmnd *scmd) 337static inline unsigned scsi_transfer_length(struct scsi_cmnd *scmd)
317{ 338{
318 unsigned int xfer_len = scsi_out(scmd)->length; 339 unsigned int xfer_len = scsi_out(scmd)->length;
319 unsigned int prot_op = scsi_get_prot_op(scmd); 340 unsigned int prot_interval = scsi_prot_interval(scmd);
320 unsigned int sector_size = scmd->device->sector_size;
321 341
322 switch (prot_op) { 342 if (scmd->prot_flags & SCSI_PROT_TRANSFER_PI)
323 case SCSI_PROT_NORMAL: 343 xfer_len += (xfer_len >> ilog2(prot_interval)) * 8;
324 case SCSI_PROT_WRITE_STRIP:
325 case SCSI_PROT_READ_INSERT:
326 return xfer_len;
327 }
328 344
329 return xfer_len + (xfer_len >> ilog2(sector_size)) * 8; 345 return xfer_len;
330} 346}
331 347
332#endif /* _SCSI_SCSI_CMND_H */ 348#endif /* _SCSI_SCSI_CMND_H */