aboutsummaryrefslogtreecommitdiffstats
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)
[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 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)
311 struct scsi_device *sdp = sdkp->device; 311 struct scsi_device *sdp = sdkp->device;
312 struct gendisk *disk = sdkp->disk; 312 struct gendisk *disk = sdkp->disk;
313 u8 type = sdkp->protection_type; 313 u8 type = sdkp->protection_type;
314 int dif, dix;
314 315
315 /* If this HBA doesn't support DIX, resort to normal I/O or DIF */ 316 dif = scsi_host_dif_capable(sdp->host, type);
316 if (scsi_host_dix_capable(sdp->host, type) == 0) { 317 dix = scsi_host_dix_capable(sdp->host, type);
317 318
318 if (type == SD_DIF_TYPE0_PROTECTION) 319 if (!dix && scsi_host_dix_capable(sdp->host, 0)) {
319 return; 320 dif = 0; dix = 1;
320 321 }
321 if (scsi_host_dif_capable(sdp->host, type) == 0) {
322 sd_printk(KERN_INFO, sdkp, "Type %d protection " \
323 "unsupported by HBA. Disabling DIF.\n", type);
324 return;
325 }
326 322
327 sd_printk(KERN_INFO, sdkp, "Enabling DIF Type %d protection\n", 323 if (type) {
328 type); 324 if (dif)
325 sd_printk(KERN_INFO, sdkp,
326 "Enabling DIF Type %d protection\n", type);
327 else
328 sd_printk(KERN_INFO, sdkp,
329 "Disabling DIF Type %d protection\n", type);
330 }
329 331
332 if (!dix)
330 return; 333 return;
331 }
332 334
333 /* Enable DMA of protection information */ 335 /* Enable DMA of protection information */
334 if (scsi_host_get_guard(sdkp->device->host) & SHOST_DIX_GUARD_IP) 336 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)
343 blk_integrity_register(disk, &dif_type1_integrity_crc); 345 blk_integrity_register(disk, &dif_type1_integrity_crc);
344 346
345 sd_printk(KERN_INFO, sdkp, 347 sd_printk(KERN_INFO, sdkp,
346 "Enabling %s integrity protection\n", disk->integrity->name); 348 "Enabling DIX %s protection\n", disk->integrity->name);
347 349
348 /* Signal to block layer that we support sector tagging */ 350 /* Signal to block layer that we support sector tagging */
349 if (type && sdkp->ATO) { 351 if (dif && type && sdkp->ATO) {
350 if (type == SD_DIF_TYPE3_PROTECTION) 352 if (type == SD_DIF_TYPE3_PROTECTION)
351 disk->integrity->tag_size = sizeof(u16) + sizeof(u32); 353 disk->integrity->tag_size = sizeof(u16) + sizeof(u32);
352 else 354 else
@@ -360,7 +362,7 @@ void sd_dif_config_host(struct scsi_disk *sdkp)
360/* 362/*
361 * DIF DMA operation magic decoder ring. 363 * DIF DMA operation magic decoder ring.
362 */ 364 */
363void sd_dif_op(struct scsi_cmnd *scmd, unsigned int dif, unsigned int dix) 365void sd_dif_op(struct scsi_cmnd *scmd, unsigned int dif, unsigned int dix, unsigned int type)
364{ 366{
365 int csum_convert, prot_op; 367 int csum_convert, prot_op;
366 368
@@ -405,7 +407,8 @@ void sd_dif_op(struct scsi_cmnd *scmd, unsigned int dif, unsigned int dix)
405 } 407 }
406 408
407 scsi_set_prot_op(scmd, prot_op); 409 scsi_set_prot_op(scmd, prot_op);
408 scsi_set_prot_type(scmd, dif); 410 if (dif)
411 scsi_set_prot_type(scmd, type);
409} 412}
410 413
411/* 414/*