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) |
[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"); | |||
249 | shost_rd_attr(can_queue, "%hd\n"); | 249 | shost_rd_attr(can_queue, "%hd\n"); |
250 | shost_rd_attr(sg_tablesize, "%hu\n"); | 250 | shost_rd_attr(sg_tablesize, "%hu\n"); |
251 | shost_rd_attr(unchecked_isa_dma, "%d\n"); | 251 | shost_rd_attr(unchecked_isa_dma, "%d\n"); |
252 | shost_rd_attr(prot_capabilities, "%u\n"); | ||
253 | shost_rd_attr(prot_guard_type, "%hd\n"); | ||
252 | shost_rd_attr2(proc_name, hostt->proc_name, "%s\n"); | 254 | shost_rd_attr2(proc_name, hostt->proc_name, "%s\n"); |
253 | 255 | ||
254 | static struct attribute *scsi_sysfs_shost_attrs[] = { | 256 | static struct attribute *scsi_sysfs_shost_attrs[] = { |
@@ -263,6 +265,8 @@ static struct attribute *scsi_sysfs_shost_attrs[] = { | |||
263 | &dev_attr_hstate.attr, | 265 | &dev_attr_hstate.attr, |
264 | &dev_attr_supported_mode.attr, | 266 | &dev_attr_supported_mode.attr, |
265 | &dev_attr_active_mode.attr, | 267 | &dev_attr_active_mode.attr, |
268 | &dev_attr_prot_capabilities.attr, | ||
269 | &dev_attr_prot_guard_type.attr, | ||
266 | NULL | 270 | NULL |
267 | }; | 271 | }; |
268 | 272 | ||
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 { | |||
636 | */ | 636 | */ |
637 | unsigned int max_host_blocked; | 637 | unsigned int max_host_blocked; |
638 | 638 | ||
639 | /* Protection Information */ | ||
640 | unsigned int prot_capabilities; | ||
641 | unsigned char prot_guard_type; | ||
642 | |||
639 | /* | 643 | /* |
640 | * q used for scsi_tgt msgs, async events or any other requests that | 644 | * q used for scsi_tgt msgs, async events or any other requests that |
641 | * need to be processed in userspace | 645 | * need to be processed in userspace |
@@ -756,6 +760,86 @@ extern struct request_queue *__scsi_alloc_queue(struct Scsi_Host *shost, | |||
756 | extern void scsi_free_host_dev(struct scsi_device *); | 760 | extern void scsi_free_host_dev(struct scsi_device *); |
757 | extern struct scsi_device *scsi_get_host_dev(struct Scsi_Host *); | 761 | extern struct scsi_device *scsi_get_host_dev(struct Scsi_Host *); |
758 | 762 | ||
763 | /* | ||
764 | * DIF defines the exchange of protection information between | ||
765 | * initiator and SBC block device. | ||
766 | * | ||
767 | * DIX defines the exchange of protection information between OS and | ||
768 | * initiator. | ||
769 | */ | ||
770 | enum scsi_host_prot_capabilities { | ||
771 | SHOST_DIF_TYPE1_PROTECTION = 1 << 0, /* T10 DIF Type 1 */ | ||
772 | SHOST_DIF_TYPE2_PROTECTION = 1 << 1, /* T10 DIF Type 2 */ | ||
773 | SHOST_DIF_TYPE3_PROTECTION = 1 << 2, /* T10 DIF Type 3 */ | ||
774 | |||
775 | SHOST_DIX_TYPE0_PROTECTION = 1 << 3, /* DIX between OS and HBA only */ | ||
776 | SHOST_DIX_TYPE1_PROTECTION = 1 << 4, /* DIX with DIF Type 1 */ | ||
777 | SHOST_DIX_TYPE2_PROTECTION = 1 << 5, /* DIX with DIF Type 2 */ | ||
778 | SHOST_DIX_TYPE3_PROTECTION = 1 << 6, /* DIX with DIF Type 3 */ | ||
779 | }; | ||
780 | |||
781 | /* | ||
782 | * SCSI hosts which support the Data Integrity Extensions must | ||
783 | * indicate their capabilities by setting the prot_capabilities using | ||
784 | * this call. | ||
785 | */ | ||
786 | static inline void scsi_host_set_prot(struct Scsi_Host *shost, unsigned int mask) | ||
787 | { | ||
788 | shost->prot_capabilities = mask; | ||
789 | } | ||
790 | |||
791 | static inline unsigned int scsi_host_get_prot(struct Scsi_Host *shost) | ||
792 | { | ||
793 | return shost->prot_capabilities; | ||
794 | } | ||
795 | |||
796 | static inline unsigned int scsi_host_dif_capable(struct Scsi_Host *shost, unsigned int target_type) | ||
797 | { | ||
798 | switch (target_type) { | ||
799 | case 1: return shost->prot_capabilities & SHOST_DIF_TYPE1_PROTECTION; | ||
800 | case 2: return shost->prot_capabilities & SHOST_DIF_TYPE2_PROTECTION; | ||
801 | case 3: return shost->prot_capabilities & SHOST_DIF_TYPE3_PROTECTION; | ||
802 | } | ||
803 | |||
804 | return 0; | ||
805 | } | ||
806 | |||
807 | static inline unsigned int scsi_host_dix_capable(struct Scsi_Host *shost, unsigned int target_type) | ||
808 | { | ||
809 | switch (target_type) { | ||
810 | case 0: return shost->prot_capabilities & SHOST_DIX_TYPE0_PROTECTION; | ||
811 | case 1: return shost->prot_capabilities & SHOST_DIX_TYPE1_PROTECTION; | ||
812 | case 2: return shost->prot_capabilities & SHOST_DIX_TYPE2_PROTECTION; | ||
813 | case 3: return shost->prot_capabilities & SHOST_DIX_TYPE3_PROTECTION; | ||
814 | } | ||
815 | |||
816 | return 0; | ||
817 | } | ||
818 | |||
819 | /* | ||
820 | * All DIX-capable initiators must support the T10-mandated CRC | ||
821 | * checksum. Controllers can optionally implement the IP checksum | ||
822 | * scheme which has much lower impact on system performance. Note | ||
823 | * that the main rationale for the checksum is to match integrity | ||
824 | * metadata with data. Detecting bit errors are a job for ECC memory | ||
825 | * and buses. | ||
826 | */ | ||
827 | |||
828 | enum scsi_host_guard_type { | ||
829 | SHOST_DIX_GUARD_CRC = 1 << 0, | ||
830 | SHOST_DIX_GUARD_IP = 1 << 1, | ||
831 | }; | ||
832 | |||
833 | static inline void scsi_host_set_guard(struct Scsi_Host *shost, unsigned char type) | ||
834 | { | ||
835 | shost->prot_guard_type = type; | ||
836 | } | ||
837 | |||
838 | static inline unsigned char scsi_host_get_guard(struct Scsi_Host *shost) | ||
839 | { | ||
840 | return shost->prot_guard_type; | ||
841 | } | ||
842 | |||
759 | /* legacy interfaces */ | 843 | /* legacy interfaces */ |
760 | extern struct Scsi_Host *scsi_register(struct scsi_host_template *, int); | 844 | extern struct Scsi_Host *scsi_register(struct scsi_host_template *, int); |
761 | extern void scsi_unregister(struct Scsi_Host *); | 845 | extern void scsi_unregister(struct Scsi_Host *); |