sd: Dump command information when a DIF/DIX command fails --- diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -1006,6 +1006,67 @@ static unsigned int sd_completed_bytes(s return (bad_lba - start_lba) * scmd->device->sector_size; } + +const char *cmd_str(struct scsi_cmnd *scmd) +{ + switch (scmd->cmnd[0]) { + case READ_10: + return "READ(10)"; + case READ_12: + return "READ(12)"; + case READ_16: + return "READ(16)"; + case WRITE_10: + return "WRITE(10)"; + case WRITE_12: + return "WRITE(12)"; + case WRITE_16: + return "WRITE(16)"; + } + + return "N/A"; +} + +unsigned int rdwr_protect(struct scsi_cmnd *scmd) +{ + switch (scmd->cmnd[0]) { + case READ_10: + case READ_12: + case READ_16: + case WRITE_10: + case WRITE_12: + case WRITE_16: + return ((scmd->cmnd[1] >> 5) & 1); + } + + return 0; +} + +static char *prot_op_str[] = { + "SCSI_PROT_NORMAL", + "SCSI_PROT_READ_INSERT", + "SCSI_PROT_WRITE_STRIP", + "SCSI_PROT_READ_STRIP", + "SCSI_PROT_WRITE_INSERT", + "SCSI_PROT_READ_PASS", + "SCSI_PROT_WRITE_PASS", + "SCSI_PROT_READ_CONVERT", + "SCSI_PROT_WRITE_CONVERT" +}; + +void sd_dump_cmnd(struct scsi_disk *sdkp, struct scsi_cmnd * scmd, unsigned int good_bytes) +{ + sd_printk(KERN_ERR, sdkp, "%s sec %lu prot %u, dif %u, prot_op %s\n", + cmd_str(scmd), (unsigned long)scmd->request->sector, + rdwr_protect(scmd), scsi_get_prot_type(scmd), + prot_op_str[scsi_get_prot_op(scmd)]); + sd_printk(KERN_ERR, sdkp, + "%u data bytes, %u data segs, %u prot bytes, %u prot segs\n", + scsi_bufflen(scmd), scsi_sg_count(scmd), + scsi_bufflen(scmd) >> 6, scsi_prot_sg_count(scmd)); + sd_printk(KERN_ERR, sdkp, "%u good bytes\n", good_bytes); +} + /** * sd_done - bottom half handler: called when the lower level * driver has completed (successfully or otherwise) a scsi command. @@ -1018,6 +1079,7 @@ static int sd_done(struct scsi_cmnd *SCp int result = SCpnt->result; unsigned int good_bytes = result ? 0 : scsi_bufflen(SCpnt); struct scsi_sense_hdr sshdr; + struct scsi_disk *sdkp = scsi_disk(SCpnt->request->rq_disk); int sense_valid = 0; int sense_deferred = 0; @@ -1061,6 +1123,7 @@ static int sd_done(struct scsi_cmnd *SCp scsi_print_result(SCpnt); scsi_print_sense("sd", SCpnt); good_bytes = sd_completed_bytes(SCpnt); + sd_dump_cmnd(sdkp, SCpnt, good_bytes); } break; case ILLEGAL_REQUEST: @@ -1068,6 +1131,7 @@ static int sd_done(struct scsi_cmnd *SCp scsi_print_result(SCpnt); scsi_print_sense("sd", SCpnt); good_bytes = sd_completed_bytes(SCpnt); + sd_dump_cmnd(sdkp, SCpnt, good_bytes); } if (!scsi_device_protection(SCpnt->device) && SCpnt->device->use_10_for_rw &&