diff options
author | Martin K. Petersen <martin.petersen@oracle.com> | 2008-07-17 04:28:30 -0400 |
---|---|---|
committer | James Bottomley <James.Bottomley@HansenPartnership.com> | 2008-07-26 15:14:54 -0400 |
commit | 4469f9878059f1707f021512e6b34252c4096ee7 (patch) | |
tree | 3bc8ea358bea85235a8d9691c8b999626e685e0d | |
parent | 7c32c7a2d36c52d2b9ed040a9171364020ecc6a2 (diff) | |
download | linux-4469f9878059f1707f021512e6b34252c4096ee7.tar.bz2 |
[SCSI] Host protection capabilities
Controllers that support protection information must indicate this to
the SCSI midlayer so that the ULD can prepare scsi_cmnds accordingly.
This patch implements a host mask and various types of protection:
- DIF Type 1-3 (between HBA and disk)
- DIX Type 0-3 (between OS and HBA)
The patch also allows the HBA to set the guard type to something
different than the T10-mandated CRC.
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
-rw-r--r-- | drivers/scsi/scsi_sysfs.c | 4 | ||||
-rw-r--r-- | include/scsi/scsi_host.h | 84 |
2 files changed, 88 insertions, 0 deletions
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index b6e561059779..ab3c71869be5 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -249,6 +249,8 @@ shost_rd_attr(cmd_per_lun, "%hd\n"); shost_rd_attr(can_queue, "%hd\n"); shost_rd_attr(sg_tablesize, "%hu\n"); shost_rd_attr(unchecked_isa_dma, "%d\n"); +shost_rd_attr(prot_capabilities, "%u\n"); +shost_rd_attr(prot_guard_type, "%hd\n"); shost_rd_attr2(proc_name, hostt->proc_name, "%s\n"); static struct attribute *scsi_sysfs_shost_attrs[] = { @@ -263,6 +265,8 @@ static struct attribute *scsi_sysfs_shost_attrs[] = { &dev_attr_hstate.attr, &dev_attr_supported_mode.attr, &dev_attr_active_mode.attr, + &dev_attr_prot_capabilities.attr, + &dev_attr_prot_guard_type.attr, NULL }; diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h index d3b1e06fb142..44a55d1bf530 100644 --- a/include/scsi/scsi_host.h +++ b/include/scsi/scsi_host.h @@ -636,6 +636,10 @@ struct Scsi_Host { */ unsigned int max_host_blocked; + /* Protection Information */ + unsigned int prot_capabilities; + unsigned char prot_guard_type; + /* * q used for scsi_tgt msgs, async events or any other requests that * need to be processed in userspace @@ -756,6 +760,86 @@ extern struct request_queue *__scsi_alloc_queue(struct Scsi_Host *shost, extern void scsi_free_host_dev(struct scsi_device *); extern struct scsi_device *scsi_get_host_dev(struct Scsi_Host *); +/* + * DIF defines the exchange of protection information between + * initiator and SBC block device. + * + * DIX defines the exchange of protection information between OS and + * initiator. + */ +enum scsi_host_prot_capabilities { + SHOST_DIF_TYPE1_PROTECTION = 1 << 0, /* T10 DIF Type 1 */ + SHOST_DIF_TYPE2_PROTECTION = 1 << 1, /* T10 DIF Type 2 */ + SHOST_DIF_TYPE3_PROTECTION = 1 << 2, /* T10 DIF Type 3 */ + + SHOST_DIX_TYPE0_PROTECTION = 1 << 3, /* DIX between OS and HBA only */ + SHOST_DIX_TYPE1_PROTECTION = 1 << 4, /* DIX with DIF Type 1 */ + SHOST_DIX_TYPE2_PROTECTION = 1 << 5, /* DIX with DIF Type 2 */ + SHOST_DIX_TYPE3_PROTECTION = 1 << 6, /* DIX with DIF Type 3 */ +}; + +/* + * SCSI hosts which support the Data Integrity Extensions must + * indicate their capabilities by setting the prot_capabilities using + * this call. + */ +static inline void scsi_host_set_prot(struct Scsi_Host *shost, unsigned int mask) +{ + shost->prot_capabilities = mask; +} + +static inline unsigned int scsi_host_get_prot(struct Scsi_Host *shost) +{ + return shost->prot_capabilities; +} + +static inline unsigned int scsi_host_dif_capable(struct Scsi_Host *shost, unsigned int target_type) +{ + switch (target_type) { + case 1: return shost->prot_capabilities & SHOST_DIF_TYPE1_PROTECTION; + case 2: return shost->prot_capabilities & SHOST_DIF_TYPE2_PROTECTION; + case 3: return shost->prot_capabilities & SHOST_DIF_TYPE3_PROTECTION; + } + + return 0; +} + +static inline unsigned int scsi_host_dix_capable(struct Scsi_Host *shost, unsigned int target_type) +{ + switch (target_type) { + case 0: return shost->prot_capabilities & SHOST_DIX_TYPE0_PROTECTION; + case 1: return shost->prot_capabilities & SHOST_DIX_TYPE1_PROTECTION; + case 2: return shost->prot_capabilities & SHOST_DIX_TYPE2_PROTECTION; + case 3: return shost->prot_capabilities & SHOST_DIX_TYPE3_PROTECTION; + } + + return 0; +} + +/* + * All DIX-capable initiators must support the T10-mandated CRC + * checksum. Controllers can optionally implement the IP checksum + * scheme which has much lower impact on system performance. Note + * that the main rationale for the checksum is to match integrity + * metadata with data. Detecting bit errors are a job for ECC memory + * and buses. + */ + +enum scsi_host_guard_type { + SHOST_DIX_GUARD_CRC = 1 << 0, + SHOST_DIX_GUARD_IP = 1 << 1, +}; + +static inline void scsi_host_set_guard(struct Scsi_Host *shost, unsigned char type) +{ + shost->prot_guard_type = type; +} + +static inline unsigned char scsi_host_get_guard(struct Scsi_Host *shost) +{ + return shost->prot_guard_type; +} + /* legacy interfaces */ extern struct Scsi_Host *scsi_register(struct scsi_host_template *, int); extern void scsi_unregister(struct Scsi_Host *); |