summaryrefslogtreecommitdiff
path: root/drivers/scsi/sd_dif.c
diff options
context:
space:
mode:
authorMartin K. Petersen <martin.petersen@oracle.com>2008-09-19 18:47:21 -0400
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2008-10-13 09:28:58 -0400
commit9e06688e7d60149cc9ef78ff29515c20186bb418 (patch)
treecb6df4657c1964244a51d6ad3a5a54b849b93894 /drivers/scsi/sd_dif.c
parentbe922f478f430f8fab4db952ffc20c86f23de397 (diff)
downloadlinux-3.10-9e06688e7d60149cc9ef78ff29515c20186bb418.tar.gz
linux-3.10-9e06688e7d60149cc9ef78ff29515c20186bb418.tar.bz2
linux-3.10-9e06688e7d60149cc9ef78ff29515c20186bb418.zip
[SCSI] sd: Correctly handle all combinations of DIF and DIX
The old detection code couldn't handle all possible combinations of DIX and DIF. This version does, giving priority to DIX if the controller is capable. Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com> Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers/scsi/sd_dif.c')
-rw-r--r--drivers/scsi/sd_dif.c37
1 files changed, 20 insertions, 17 deletions
diff --git a/drivers/scsi/sd_dif.c b/drivers/scsi/sd_dif.c
index 943fde7e7ff..194c7706083 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);
}
/*