aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin K. Petersen <martin.petersen@oracle.com>2008-07-17 04:28:31 -0400
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2008-07-26 15:14:54 -0400
commitdb007fc5e20c00b356e9ffe2d0e007398c65c837 (patch)
treeab0483beff7abaddb9648bc0b2ef1ceacfeb02a9
parent4469f9878059f1707f021512e6b34252c4096ee7 (diff)
[SCSI] Command protection operation
Controllers that support DMA of protection information must be told explicitly how to handle the I/O. The controller has no knowledge of the protection capabilities of the target device so this information must be passed in the scsi_cmnd. - The protection operation tells the HBA whether to generate, strip or verify protection information. - The protection type tells the HBA which layout the target is formatted with. This is necessary because the controller must be able to correctly interpret the included protection information in order to verify it. - When a scsi_cmnd is reused for error handling the protection operation must be cleared and saved while error handling is in progress. - prot_op and prot_type are placed in an existing hole in scsi_cmnd and don't cause the structure to grow. Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com> Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
-rw-r--r--drivers/scsi/scsi_error.c3
-rw-r--r--include/scsi/scsi_cmnd.h66
-rw-r--r--include/scsi/scsi_eh.h1
3 files changed, 70 insertions, 0 deletions
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
index 006a95916f72..a69397fd314a 100644
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -664,7 +664,9 @@ void scsi_eh_prep_cmnd(struct scsi_cmnd *scmd, struct scsi_eh_save *ses,
664 ses->sdb = scmd->sdb; 664 ses->sdb = scmd->sdb;
665 ses->next_rq = scmd->request->next_rq; 665 ses->next_rq = scmd->request->next_rq;
666 ses->result = scmd->result; 666 ses->result = scmd->result;
667 ses->prot_op = scmd->prot_op;
667 668
669 scmd->prot_op = SCSI_PROT_NORMAL;
668 scmd->cmnd = ses->eh_cmnd; 670 scmd->cmnd = ses->eh_cmnd;
669 memset(scmd->cmnd, 0, BLK_MAX_CDB); 671 memset(scmd->cmnd, 0, BLK_MAX_CDB);
670 memset(&scmd->sdb, 0, sizeof(scmd->sdb)); 672 memset(&scmd->sdb, 0, sizeof(scmd->sdb));
@@ -722,6 +724,7 @@ void scsi_eh_restore_cmnd(struct scsi_cmnd* scmd, struct scsi_eh_save *ses)
722 scmd->sdb = ses->sdb; 724 scmd->sdb = ses->sdb;
723 scmd->request->next_rq = ses->next_rq; 725 scmd->request->next_rq = ses->next_rq;
724 scmd->result = ses->result; 726 scmd->result = ses->result;
727 scmd->prot_op = ses->prot_op;
725} 728}
726EXPORT_SYMBOL(scsi_eh_restore_cmnd); 729EXPORT_SYMBOL(scsi_eh_restore_cmnd);
727 730
diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h
index 66c944849d6b..402c1078d01c 100644
--- a/include/scsi/scsi_cmnd.h
+++ b/include/scsi/scsi_cmnd.h
@@ -77,6 +77,9 @@ struct scsi_cmnd {
77 int allowed; 77 int allowed;
78 int timeout_per_command; 78 int timeout_per_command;
79 79
80 unsigned char prot_op;
81 unsigned char prot_type;
82
80 unsigned short cmd_len; 83 unsigned short cmd_len;
81 enum dma_data_direction sc_data_direction; 84 enum dma_data_direction sc_data_direction;
82 85
@@ -208,4 +211,67 @@ static inline int scsi_sg_copy_to_buffer(struct scsi_cmnd *cmd,
208 buf, buflen); 211 buf, buflen);
209} 212}
210 213
214/*
215 * The operations below are hints that tell the controller driver how
216 * to handle I/Os with DIF or similar types of protection information.
217 */
218enum scsi_prot_operations {
219 /* Normal I/O */
220 SCSI_PROT_NORMAL = 0,
221
222 /* OS-HBA: Protected, HBA-Target: Unprotected */
223 SCSI_PROT_READ_INSERT,
224 SCSI_PROT_WRITE_STRIP,
225
226 /* OS-HBA: Unprotected, HBA-Target: Protected */
227 SCSI_PROT_READ_STRIP,
228 SCSI_PROT_WRITE_INSERT,
229
230 /* OS-HBA: Protected, HBA-Target: Protected */
231 SCSI_PROT_READ_PASS,
232 SCSI_PROT_WRITE_PASS,
233
234 /* OS-HBA: Protected, HBA-Target: Protected, checksum conversion */
235 SCSI_PROT_READ_CONVERT,
236 SCSI_PROT_WRITE_CONVERT,
237};
238
239static inline void scsi_set_prot_op(struct scsi_cmnd *scmd, unsigned char op)
240{
241 scmd->prot_op = op;
242}
243
244static inline unsigned char scsi_get_prot_op(struct scsi_cmnd *scmd)
245{
246 return scmd->prot_op;
247}
248
249/*
250 * The controller usually does not know anything about the target it
251 * is communicating with. However, when DIX is enabled the controller
252 * must be know target type so it can verify the protection
253 * information passed along with the I/O.
254 */
255enum scsi_prot_target_type {
256 SCSI_PROT_DIF_TYPE0 = 0,
257 SCSI_PROT_DIF_TYPE1,
258 SCSI_PROT_DIF_TYPE2,
259 SCSI_PROT_DIF_TYPE3,
260};
261
262static inline void scsi_set_prot_type(struct scsi_cmnd *scmd, unsigned char type)
263{
264 scmd->prot_type = type;
265}
266
267static inline unsigned char scsi_get_prot_type(struct scsi_cmnd *scmd)
268{
269 return scmd->prot_type;
270}
271
272static inline sector_t scsi_get_lba(struct scsi_cmnd *scmd)
273{
274 return scmd->request->sector;
275}
276
211#endif /* _SCSI_SCSI_CMND_H */ 277#endif /* _SCSI_SCSI_CMND_H */
diff --git a/include/scsi/scsi_eh.h b/include/scsi/scsi_eh.h
index 2a9add21267d..e5499ed0e376 100644
--- a/include/scsi/scsi_eh.h
+++ b/include/scsi/scsi_eh.h
@@ -75,6 +75,7 @@ struct scsi_eh_save {
75 int result; 75 int result;
76 enum dma_data_direction data_direction; 76 enum dma_data_direction data_direction;
77 unsigned char cmd_len; 77 unsigned char cmd_len;
78 unsigned char prot_op;
78 unsigned char *cmnd; 79 unsigned char *cmnd;
79 struct scsi_data_buffer sdb; 80 struct scsi_data_buffer sdb;
80 struct request *next_rq; 81 struct request *next_rq;