diff options
author | Martin K. Petersen <martin.petersen@oracle.com> | 2009-09-18 17:33:00 -0400 |
---|---|---|
committer | James Bottomley <James.Bottomley@suse.de> | 2009-10-02 09:46:39 -0500 |
commit | 35e1a5d90b66487d754ef2f2dcbf1007f806d921 (patch) | |
tree | 964511498993ed8fe0c1604ab74ac7a3db9361ba /drivers/scsi | |
parent | c6af404215bab0d333accbb497f835d10cb0050c (diff) | |
download | kernel_goldelico_gta04-35e1a5d90b66487d754ef2f2dcbf1007f806d921.zip kernel_goldelico_gta04-35e1a5d90b66487d754ef2f2dcbf1007f806d921.tar.gz kernel_goldelico_gta04-35e1a5d90b66487d754ef2f2dcbf1007f806d921.tar.bz2 |
[SCSI] sd: Detach DIF from block integrity infrastructure
So far we have only issued DIF commands if CONFIG_BLK_DEV_INTEGRITY is
enabled. However, communication between initiator and target should be
independent of protection information DMA. There are DIF-only host
adapters coming out that will be able to take advantage of this.
Move the relevant DIF bits to sd.c.
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/scsi')
-rw-r--r-- | drivers/scsi/sd.c | 61 | ||||
-rw-r--r-- | drivers/scsi/sd.h | 4 | ||||
-rw-r--r-- | drivers/scsi/sd_dif.c | 53 |
3 files changed, 42 insertions, 76 deletions
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 8dd96dc..1e0a0b0 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -370,6 +370,31 @@ static void scsi_disk_put(struct scsi_disk *sdkp) mutex_unlock(&sd_ref_mutex); } +static void sd_prot_op(struct scsi_cmnd *scmd, unsigned int dif) +{ + unsigned int prot_op = SCSI_PROT_NORMAL; + unsigned int dix = scsi_prot_sg_count(scmd); + + if (scmd->sc_data_direction == DMA_FROM_DEVICE) { + if (dif && dix) + prot_op = SCSI_PROT_READ_PASS; + else if (dif && !dix) + prot_op = SCSI_PROT_READ_STRIP; + else if (!dif && dix) + prot_op = SCSI_PROT_READ_INSERT; + } else { + if (dif && dix) + prot_op = SCSI_PROT_WRITE_PASS; + else if (dif && !dix) + prot_op = SCSI_PROT_WRITE_INSERT; + else if (!dif && dix) + prot_op = SCSI_PROT_WRITE_STRIP; + } + + scsi_set_prot_op(scmd, prot_op); + scsi_set_prot_type(scmd, dif); +} + /** * sd_init_command - build a scsi (read or write) command from * information in the request structure. @@ -578,8 +603,7 @@ 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, host_dif, scsi_prot_sg_count(SCpnt), - sdkp->protection_type); + sd_prot_op(SCpnt, host_dif); /* * We shouldn't disconnect in the middle of a sector, so with a dumb @@ -1238,34 +1262,33 @@ void sd_read_protection_type(struct scsi_disk *sdkp, unsigned char *buffer) u8 type; if (scsi_device_protection(sdp) == 0 || (buffer[12] & 1) == 0) - type = 0; - else - type = ((buffer[12] >> 1) & 7) + 1; /* P_TYPE 0 = Type 1 */ + return; + + type = ((buffer[12] >> 1) & 7) + 1; /* P_TYPE 0 = Type 1 */ + + if (type == sdkp->protection_type || !sdkp->first_scan) + return; sdkp->protection_type = type; switch (type) { - case SD_DIF_TYPE0_PROTECTION: case SD_DIF_TYPE1_PROTECTION: case SD_DIF_TYPE3_PROTECTION: break; - case SD_DIF_TYPE2_PROTECTION: - sd_printk(KERN_ERR, sdkp, "formatted with DIF Type 2 " \ - "protection which is currently unsupported. " \ - "Disabling disk!\n"); - goto disable; - default: - sd_printk(KERN_ERR, sdkp, "formatted with unknown " \ - "protection type %d. Disabling disk!\n", type); - goto disable; + sd_printk(KERN_ERR, sdkp, "formatted with unsupported " \ + "protection type %u. Disabling disk!\n", type); + sdkp->capacity = 0; + return; } - return; - -disable: - sdkp->capacity = 0; + if (scsi_host_dif_capable(sdp->host, type)) + sd_printk(KERN_NOTICE, sdkp, + "Enabling DIF Type %u protection\n", type); + else + sd_printk(KERN_NOTICE, sdkp, + "Disabling DIF Type %u protection\n", type); } static void read_capacity_error(struct scsi_disk *sdkp, struct scsi_device *sdp, diff --git a/drivers/scsi/sd.h b/drivers/scsi/sd.h index 8474b5ba..ce1f5f8 100644 --- a/drivers/scsi/sd.h +++ b/drivers/scsi/sd.h @@ -101,16 +101,12 @@ struct sd_dif_tuple { #ifdef CONFIG_BLK_DEV_INTEGRITY -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); #else /* CONFIG_BLK_DEV_INTEGRITY */ -static inline void sd_dif_op(struct scsi_cmnd *cmd, unsigned int a, unsigned int b, unsigned int c) -{ -} static inline void sd_dif_config_host(struct scsi_disk *disk) { } diff --git a/drivers/scsi/sd_dif.c b/drivers/scsi/sd_dif.c index 84224dd..88da977 100644 --- a/drivers/scsi/sd_dif.c +++ b/drivers/scsi/sd_dif.c @@ -320,15 +320,6 @@ void sd_dif_config_host(struct scsi_disk *sdkp) dif = 0; dix = 1; } - if (type) { - if (dif) - sd_printk(KERN_NOTICE, sdkp, - "Enabling DIF Type %d protection\n", type); - else - sd_printk(KERN_NOTICE, sdkp, - "Disabling DIF Type %d protection\n", type); - } - if (!dix) return; @@ -360,50 +351,6 @@ 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, unsigned int type) -{ - int prot_op; - - prot_op = SCSI_PROT_NORMAL; - - BUG_ON(dif && (scmd->cmnd[0] == READ_6 || scmd->cmnd[0] == WRITE_6)); - - switch (scmd->cmnd[0]) { - case READ_6: - case READ_10: - case READ_12: - case READ_16: - if (dif && dix) - prot_op = SCSI_PROT_READ_PASS; - else if (dif && !dix) - prot_op = SCSI_PROT_READ_STRIP; - else if (!dif && dix) - prot_op = SCSI_PROT_READ_INSERT; - - break; - - case WRITE_6: - case WRITE_10: - case WRITE_12: - case WRITE_16: - if (dif && dix) - prot_op = SCSI_PROT_WRITE_PASS; - else if (dif && !dix) - prot_op = SCSI_PROT_WRITE_INSERT; - else if (!dif && dix) - prot_op = SCSI_PROT_WRITE_STRIP; - - break; - } - - scsi_set_prot_op(scmd, prot_op); - if (dif) - scsi_set_prot_type(scmd, type); -} - -/* * The virtual start sector is the one that was originally submitted * by the block layer. Due to partitioning, MD/DM cloning, etc. the * actual physical start sector is likely to be different. Remap |