127127#define PHY_CTRL (PORT_BASE + 0x14)
128128#define PHY_CTRL_RESET_OFF 0
129129#define PHY_CTRL_RESET_MSK (0x1 << PHY_CTRL_RESET_OFF)
130+ #define CMD_HDR_PIR_OFF 8
131+ #define CMD_HDR_PIR_MSK (0x1 << CMD_HDR_PIR_OFF)
130132#define SL_CFG (PORT_BASE + 0x84)
131133#define AIP_LIMIT (PORT_BASE + 0x90)
132134#define SL_CONTROL (PORT_BASE + 0x94)
333335#define ITCT_HDR_RTOLT_OFF 48
334336#define ITCT_HDR_RTOLT_MSK (0xffffULL << ITCT_HDR_RTOLT_OFF)
335337
338+ struct hisi_sas_protect_iu_v3_hw {
339+ u32 dw0 ;
340+ u32 lbrtcv ;
341+ u32 lbrtgv ;
342+ u32 dw3 ;
343+ u32 dw4 ;
344+ u32 dw5 ;
345+ u32 rsv ;
346+ };
347+
336348struct hisi_sas_complete_v3_hdr {
337349 __le32 dw0 ;
338350 __le32 dw1 ;
@@ -372,9 +384,28 @@ struct hisi_sas_err_record_v3 {
372384 ((fis.command == ATA_CMD_DEV_RESET) && \
373385 ((fis.control & ATA_SRST) != 0)))
374386
387+ #define T10_INSRT_EN_OFF 0
388+ #define T10_INSRT_EN_MSK (1 << T10_INSRT_EN_OFF)
389+ #define T10_RMV_EN_OFF 1
390+ #define T10_RMV_EN_MSK (1 << T10_RMV_EN_OFF)
391+ #define T10_RPLC_EN_OFF 2
392+ #define T10_RPLC_EN_MSK (1 << T10_RPLC_EN_OFF)
393+ #define T10_CHK_EN_OFF 3
394+ #define T10_CHK_EN_MSK (1 << T10_CHK_EN_OFF)
395+ #define INCR_LBRT_OFF 5
396+ #define INCR_LBRT_MSK (1 << INCR_LBRT_OFF)
397+ #define USR_DATA_BLOCK_SZ_OFF 20
398+ #define USR_DATA_BLOCK_SZ_MSK (0x3 << USR_DATA_BLOCK_SZ_OFF)
399+ #define T10_CHK_MSK_OFF 16
400+
375401static bool hisi_sas_intr_conv ;
376402MODULE_PARM_DESC (intr_conv , "interrupt converge enable (0-1)" );
377403
404+ /* permit overriding the host protection capabilities mask (EEDP/T10 PI) */
405+ static int prot_mask ;
406+ module_param (prot_mask , int , 0 );
407+ MODULE_PARM_DESC (prot_mask , " host protection capabilities mask, def=0x0 " );
408+
378409static u32 hisi_sas_read32 (struct hisi_hba * hisi_hba , u32 off )
379410{
380411 void __iomem * regs = hisi_hba -> regs + off ;
@@ -941,6 +972,58 @@ static void prep_prd_sge_v3_hw(struct hisi_hba *hisi_hba,
941972 hdr -> sg_len = cpu_to_le32 (n_elem << CMD_HDR_DATA_SGL_LEN_OFF );
942973}
943974
975+ static u32 get_prot_chk_msk_v3_hw (struct scsi_cmnd * scsi_cmnd )
976+ {
977+ unsigned char prot_flags = scsi_cmnd -> prot_flags ;
978+
979+ if (prot_flags & SCSI_PROT_TRANSFER_PI ) {
980+ if (prot_flags & SCSI_PROT_REF_CHECK )
981+ return 0xc << 16 ;
982+ return 0xfc << 16 ;
983+ }
984+ return 0 ;
985+ }
986+
987+ static void fill_prot_v3_hw (struct scsi_cmnd * scsi_cmnd ,
988+ struct hisi_sas_protect_iu_v3_hw * prot )
989+ {
990+ unsigned char prot_op = scsi_get_prot_op (scsi_cmnd );
991+ unsigned int interval = scsi_prot_interval (scsi_cmnd );
992+ u32 lbrt_chk_val = t10_pi_ref_tag (scsi_cmnd -> request );
993+
994+ switch (prot_op ) {
995+ case SCSI_PROT_READ_STRIP :
996+ prot -> dw0 |= (T10_RMV_EN_MSK | T10_CHK_EN_MSK );
997+ prot -> lbrtcv = lbrt_chk_val ;
998+ prot -> dw4 |= get_prot_chk_msk_v3_hw (scsi_cmnd );
999+ break ;
1000+ case SCSI_PROT_WRITE_INSERT :
1001+ prot -> dw0 |= T10_INSRT_EN_MSK ;
1002+ prot -> lbrtgv = lbrt_chk_val ;
1003+ break ;
1004+ default :
1005+ WARN (1 , "prot_op(0x%x) is not valid\n" , prot_op );
1006+ break ;
1007+ }
1008+
1009+ switch (interval ) {
1010+ case 512 :
1011+ break ;
1012+ case 4096 :
1013+ prot -> dw0 |= (0x1 << USR_DATA_BLOCK_SZ_OFF );
1014+ break ;
1015+ case 520 :
1016+ prot -> dw0 |= (0x2 << USR_DATA_BLOCK_SZ_OFF );
1017+ break ;
1018+ default :
1019+ WARN (1 , "protection interval (0x%x) invalid\n" ,
1020+ interval );
1021+ break ;
1022+ }
1023+
1024+ prot -> dw0 |= INCR_LBRT_MSK ;
1025+ }
1026+
9441027static void prep_ssp_v3_hw (struct hisi_hba * hisi_hba ,
9451028 struct hisi_sas_slot * slot )
9461029{
@@ -952,9 +1035,10 @@ static void prep_ssp_v3_hw(struct hisi_hba *hisi_hba,
9521035 struct sas_ssp_task * ssp_task = & task -> ssp_task ;
9531036 struct scsi_cmnd * scsi_cmnd = ssp_task -> cmd ;
9541037 struct hisi_sas_tmf_task * tmf = slot -> tmf ;
1038+ unsigned char prot_op = scsi_get_prot_op (scsi_cmnd );
9551039 int has_data = 0 , priority = !!tmf ;
9561040 u8 * buf_cmd ;
957- u32 dw1 = 0 , dw2 = 0 ;
1041+ u32 dw1 = 0 , dw2 = 0 , len = 0 ;
9581042
9591043 hdr -> dw0 = cpu_to_le32 ((1 << CMD_HDR_RESP_REPORT_OFF ) |
9601044 (2 << CMD_HDR_TLR_CTRL_OFF ) |
@@ -984,7 +1068,6 @@ static void prep_ssp_v3_hw(struct hisi_hba *hisi_hba,
9841068
9851069 /* map itct entry */
9861070 dw1 |= sas_dev -> device_id << CMD_HDR_DEV_ID_OFF ;
987- hdr -> dw1 = cpu_to_le32 (dw1 );
9881071
9891072 dw2 = (((sizeof (struct ssp_command_iu ) + sizeof (struct ssp_frame_hdr )
9901073 + 3 ) / 4 ) << CMD_HDR_CFL_OFF ) |
@@ -997,7 +1080,6 @@ static void prep_ssp_v3_hw(struct hisi_hba *hisi_hba,
9971080 prep_prd_sge_v3_hw (hisi_hba , slot , hdr , task -> scatter ,
9981081 slot -> n_elem );
9991082
1000- hdr -> data_transfer_len = cpu_to_le32 (task -> total_xfer_len );
10011083 hdr -> cmd_table_addr = cpu_to_le64 (hisi_sas_cmd_hdr_addr_dma (slot ));
10021084 hdr -> sts_buffer_addr = cpu_to_le64 (hisi_sas_status_buf_addr_dma (slot ));
10031085
@@ -1022,6 +1104,38 @@ static void prep_ssp_v3_hw(struct hisi_hba *hisi_hba,
10221104 break ;
10231105 }
10241106 }
1107+
1108+ if (has_data && (prot_op != SCSI_PROT_NORMAL )) {
1109+ struct hisi_sas_protect_iu_v3_hw prot ;
1110+ u8 * buf_cmd_prot ;
1111+
1112+ hdr -> dw7 |= cpu_to_le32 (1 << CMD_HDR_ADDR_MODE_SEL_OFF );
1113+ dw1 |= CMD_HDR_PIR_MSK ;
1114+ buf_cmd_prot = hisi_sas_cmd_hdr_addr_mem (slot ) +
1115+ sizeof (struct ssp_frame_hdr ) +
1116+ sizeof (struct ssp_command_iu );
1117+
1118+ memset (& prot , 0 , sizeof (struct hisi_sas_protect_iu_v3_hw ));
1119+ fill_prot_v3_hw (scsi_cmnd , & prot );
1120+ memcpy (buf_cmd_prot , & prot ,
1121+ sizeof (struct hisi_sas_protect_iu_v3_hw ));
1122+
1123+ /*
1124+ * For READ, we need length of info read to memory, while for
1125+ * WRITE we need length of data written to the disk.
1126+ */
1127+ if (prot_op == SCSI_PROT_WRITE_INSERT ) {
1128+ unsigned int interval = scsi_prot_interval (scsi_cmnd );
1129+ unsigned int ilog2_interval = ilog2 (interval );
1130+
1131+ len = (task -> total_xfer_len >> ilog2_interval ) * 8 ;
1132+ }
1133+
1134+ }
1135+
1136+ hdr -> dw1 = cpu_to_le32 (dw1 );
1137+
1138+ hdr -> data_transfer_len = cpu_to_le32 (task -> total_xfer_len + len );
10251139}
10261140
10271141static void prep_smp_v3_hw (struct hisi_hba * hisi_hba ,
@@ -2291,6 +2405,12 @@ hisi_sas_shost_alloc_pci(struct pci_dev *pdev)
22912405 hisi_hba -> shost = shost ;
22922406 SHOST_TO_SAS_HA (shost ) = & hisi_hba -> sha ;
22932407
2408+ if (prot_mask & ~HISI_SAS_PROT_MASK )
2409+ dev_err (dev , "unsupported protection mask 0x%x, using default (0x0)\n" ,
2410+ prot_mask );
2411+ else
2412+ hisi_hba -> prot_mask = prot_mask ;
2413+
22942414 timer_setup (& hisi_hba -> timer , NULL , 0 );
22952415
22962416 if (hisi_sas_get_fw_info (hisi_hba ) < 0 )
@@ -2401,6 +2521,12 @@ hisi_sas_v3_probe(struct pci_dev *pdev, const struct pci_device_id *id)
24012521 if (rc )
24022522 goto err_out_register_ha ;
24032523
2524+ if (hisi_hba -> prot_mask ) {
2525+ dev_info (dev , "Registering for DIF/DIX prot_mask=0x%x\n" ,
2526+ prot_mask );
2527+ scsi_host_set_prot (hisi_hba -> shost , prot_mask );
2528+ }
2529+
24042530 scsi_scan_host (shost );
24052531
24062532 return 0 ;
0 commit comments