[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>

authored by

Martin K. Petersen and committed by
James Bottomley
4469f987 7c32c7a2

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