diff options
Diffstat (limited to 'drivers/scsi')
-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) | |||
575 | 575 | ||
576 | /* If DIF or DIX is enabled, tell HBA how to handle request */ | 576 | /* If DIF or DIX is enabled, tell HBA how to handle request */ |
577 | if (host_dif || scsi_prot_sg_count(SCpnt)) | 577 | if (host_dif || scsi_prot_sg_count(SCpnt)) |
578 | sd_dif_op(SCpnt, sdkp->protection_type, scsi_prot_sg_count(SCpnt)); | 578 | sd_dif_op(SCpnt, host_dif, scsi_prot_sg_count(SCpnt), |
579 | sdkp->protection_type); | ||
579 | 580 | ||
580 | /* | 581 | /* |
581 | * We shouldn't disconnect in the middle of a sector, so with a dumb | 582 | * 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 { | |||
99 | 99 | ||
100 | #if defined(CONFIG_BLK_DEV_INTEGRITY) | 100 | #if defined(CONFIG_BLK_DEV_INTEGRITY) |
101 | 101 | ||
102 | extern void sd_dif_op(struct scsi_cmnd *, unsigned int, unsigned int); | 102 | extern void sd_dif_op(struct scsi_cmnd *, unsigned int, unsigned int, unsigned int); |
103 | extern void sd_dif_config_host(struct scsi_disk *); | 103 | extern void sd_dif_config_host(struct scsi_disk *); |
104 | extern int sd_dif_prepare(struct request *rq, sector_t, unsigned int); | 104 | extern int sd_dif_prepare(struct request *rq, sector_t, unsigned int); |
105 | extern void sd_dif_complete(struct scsi_cmnd *, unsigned int); | 105 | 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) | |||
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 | */ |
363 | void sd_dif_op(struct scsi_cmnd *scmd, unsigned int dif, unsigned int dix) | 365 | void 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 | /* |