diff options
-rw-r--r-- | drivers/scsi/sd.c | 3 | ||||
-rw-r--r-- | drivers/scsi/sd.h | 2 | ||||
-rw-r--r-- | drivers/scsi/sd_dif.c | 37 |
3 files changed, 23 insertions, 19 deletions
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index a494a2ec67d7..7c4d2e68df1c 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -575,7 +575,8 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq) /* If DIF or DIX is enabled, tell HBA how to handle request */ if (host_dif || scsi_prot_sg_count(SCpnt)) - sd_dif_op(SCpnt, sdkp->protection_type, scsi_prot_sg_count(SCpnt)); + sd_dif_op(SCpnt, host_dif, scsi_prot_sg_count(SCpnt), + sdkp->protection_type); /* * We shouldn't disconnect in the middle of a sector, so with a dumb diff --git a/drivers/scsi/sd.h b/drivers/scsi/sd.h index 95b9f06534d5..a92b991d98ab 100644 --- a/drivers/scsi/sd.h +++ b/drivers/scsi/sd.h @@ -99,7 +99,7 @@ struct sd_dif_tuple { #if defined(CONFIG_BLK_DEV_INTEGRITY) -extern void sd_dif_op(struct scsi_cmnd *, unsigned int, unsigned int); +extern void sd_dif_op(struct scsi_cmnd *, unsigned int, unsigned int, unsigned int); extern void sd_dif_config_host(struct scsi_disk *); extern int sd_dif_prepare(struct request *rq, sector_t, unsigned int); extern void sd_dif_complete(struct scsi_cmnd *, unsigned int); diff --git a/drivers/scsi/sd_dif.c b/drivers/scsi/sd_dif.c index 943fde7e7ffb..194c7706083b 100644 --- a/drivers/scsi/sd_dif.c +++ b/drivers/scsi/sd_dif.c @@ -311,24 +311,26 @@ void sd_dif_config_host(struct scsi_disk *sdkp) struct scsi_device *sdp = sdkp->device; struct gendisk *disk = sdkp->disk; u8 type = sdkp->protection_type; + int dif, dix; - /* If this HBA doesn't support DIX, resort to normal I/O or DIF */ - if (scsi_host_dix_capable(sdp->host, type) == 0) { + dif = scsi_host_dif_capable(sdp->host, type); + dix = scsi_host_dix_capable(sdp->host, type); - if (type == SD_DIF_TYPE0_PROTECTION) - return; - - if (scsi_host_dif_capable(sdp->host, type) == 0) { - sd_printk(KERN_INFO, sdkp, "Type %d protection " \ - "unsupported by HBA. Disabling DIF.\n", type); - return; - } + if (!dix && scsi_host_dix_capable(sdp->host, 0)) { + dif = 0; dix = 1; + } - sd_printk(KERN_INFO, sdkp, "Enabling DIF Type %d protection\n", - type); + if (type) { + if (dif) + sd_printk(KERN_INFO, sdkp, + "Enabling DIF Type %d protection\n", type); + else + sd_printk(KERN_INFO, sdkp, + "Disabling DIF Type %d protection\n", type); + } + if (!dix) return; - } /* Enable DMA of protection information */ if (scsi_host_get_guard(sdkp->device->host) & SHOST_DIX_GUARD_IP) @@ -343,10 +345,10 @@ void sd_dif_config_host(struct scsi_disk *sdkp) blk_integrity_register(disk, &dif_type1_integrity_crc); sd_printk(KERN_INFO, sdkp, - "Enabling %s integrity protection\n", disk->integrity->name); + "Enabling DIX %s protection\n", disk->integrity->name); /* Signal to block layer that we support sector tagging */ - if (type && sdkp->ATO) { + if (dif && type && sdkp->ATO) { if (type == SD_DIF_TYPE3_PROTECTION) disk->integrity->tag_size = sizeof(u16) + sizeof(u32); else @@ -360,7 +362,7 @@ void sd_dif_config_host(struct scsi_disk *sdkp) /* * DIF DMA operation magic decoder ring. */ -void sd_dif_op(struct scsi_cmnd *scmd, unsigned int dif, unsigned int dix) +void sd_dif_op(struct scsi_cmnd *scmd, unsigned int dif, unsigned int dix, unsigned int type) { int csum_convert, prot_op; @@ -405,7 +407,8 @@ void sd_dif_op(struct scsi_cmnd *scmd, unsigned int dif, unsigned int dix) } scsi_set_prot_op(scmd, prot_op); - scsi_set_prot_type(scmd, dif); + if (dif) + scsi_set_prot_type(scmd, type); } /* |