[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>

authored by

Martin K. Petersen and committed by
James Bottomley
db007fc5 4469f987

+70
+3
drivers/scsi/scsi_error.c
··· 664 ses->sdb = scmd->sdb; 665 ses->next_rq = scmd->request->next_rq; 666 ses->result = scmd->result; 667 668 scmd->cmnd = ses->eh_cmnd; 669 memset(scmd->cmnd, 0, BLK_MAX_CDB); 670 memset(&scmd->sdb, 0, sizeof(scmd->sdb)); ··· 724 scmd->sdb = ses->sdb; 725 scmd->request->next_rq = ses->next_rq; 726 scmd->result = ses->result; 727 } 728 EXPORT_SYMBOL(scsi_eh_restore_cmnd); 729
··· 664 ses->sdb = scmd->sdb; 665 ses->next_rq = scmd->request->next_rq; 666 ses->result = scmd->result; 667 + ses->prot_op = scmd->prot_op; 668 669 + scmd->prot_op = SCSI_PROT_NORMAL; 670 scmd->cmnd = ses->eh_cmnd; 671 memset(scmd->cmnd, 0, BLK_MAX_CDB); 672 memset(&scmd->sdb, 0, sizeof(scmd->sdb)); ··· 722 scmd->sdb = ses->sdb; 723 scmd->request->next_rq = ses->next_rq; 724 scmd->result = ses->result; 725 + scmd->prot_op = ses->prot_op; 726 } 727 EXPORT_SYMBOL(scsi_eh_restore_cmnd); 728
+66
include/scsi/scsi_cmnd.h
··· 77 int allowed; 78 int timeout_per_command; 79 80 unsigned short cmd_len; 81 enum dma_data_direction sc_data_direction; 82 ··· 209 { 210 return sg_copy_to_buffer(scsi_sglist(cmd), scsi_sg_count(cmd), 211 buf, buflen); 212 } 213 214 #endif /* _SCSI_SCSI_CMND_H */
··· 77 int allowed; 78 int timeout_per_command; 79 80 + unsigned char prot_op; 81 + unsigned char prot_type; 82 + 83 unsigned short cmd_len; 84 enum dma_data_direction sc_data_direction; 85 ··· 206 { 207 return sg_copy_to_buffer(scsi_sglist(cmd), scsi_sg_count(cmd), 208 buf, buflen); 209 + } 210 + 211 + /* 212 + * The operations below are hints that tell the controller driver how 213 + * to handle I/Os with DIF or similar types of protection information. 214 + */ 215 + enum scsi_prot_operations { 216 + /* Normal I/O */ 217 + SCSI_PROT_NORMAL = 0, 218 + 219 + /* OS-HBA: Protected, HBA-Target: Unprotected */ 220 + SCSI_PROT_READ_INSERT, 221 + SCSI_PROT_WRITE_STRIP, 222 + 223 + /* OS-HBA: Unprotected, HBA-Target: Protected */ 224 + SCSI_PROT_READ_STRIP, 225 + SCSI_PROT_WRITE_INSERT, 226 + 227 + /* OS-HBA: Protected, HBA-Target: Protected */ 228 + SCSI_PROT_READ_PASS, 229 + SCSI_PROT_WRITE_PASS, 230 + 231 + /* OS-HBA: Protected, HBA-Target: Protected, checksum conversion */ 232 + SCSI_PROT_READ_CONVERT, 233 + SCSI_PROT_WRITE_CONVERT, 234 + }; 235 + 236 + static inline void scsi_set_prot_op(struct scsi_cmnd *scmd, unsigned char op) 237 + { 238 + scmd->prot_op = op; 239 + } 240 + 241 + static inline unsigned char scsi_get_prot_op(struct scsi_cmnd *scmd) 242 + { 243 + return scmd->prot_op; 244 + } 245 + 246 + /* 247 + * The controller usually does not know anything about the target it 248 + * is communicating with. However, when DIX is enabled the controller 249 + * must be know target type so it can verify the protection 250 + * information passed along with the I/O. 251 + */ 252 + enum scsi_prot_target_type { 253 + SCSI_PROT_DIF_TYPE0 = 0, 254 + SCSI_PROT_DIF_TYPE1, 255 + SCSI_PROT_DIF_TYPE2, 256 + SCSI_PROT_DIF_TYPE3, 257 + }; 258 + 259 + static inline void scsi_set_prot_type(struct scsi_cmnd *scmd, unsigned char type) 260 + { 261 + scmd->prot_type = type; 262 + } 263 + 264 + static inline unsigned char scsi_get_prot_type(struct scsi_cmnd *scmd) 265 + { 266 + return scmd->prot_type; 267 + } 268 + 269 + static inline sector_t scsi_get_lba(struct scsi_cmnd *scmd) 270 + { 271 + return scmd->request->sector; 272 } 273 274 #endif /* _SCSI_SCSI_CMND_H */
+1
include/scsi/scsi_eh.h
··· 75 int result; 76 enum dma_data_direction data_direction; 77 unsigned char cmd_len; 78 unsigned char *cmnd; 79 struct scsi_data_buffer sdb; 80 struct request *next_rq;
··· 75 int result; 76 enum dma_data_direction data_direction; 77 unsigned char cmd_len; 78 + unsigned char prot_op; 79 unsigned char *cmnd; 80 struct scsi_data_buffer sdb; 81 struct request *next_rq;