127
127
#define PHY_CTRL (PORT_BASE + 0x14)
128
128
#define PHY_CTRL_RESET_OFF 0
129
129
#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)
130
132
#define SL_CFG (PORT_BASE + 0x84)
131
133
#define AIP_LIMIT (PORT_BASE + 0x90)
132
134
#define SL_CONTROL (PORT_BASE + 0x94)
333
335
#define ITCT_HDR_RTOLT_OFF 48
334
336
#define ITCT_HDR_RTOLT_MSK (0xffffULL << ITCT_HDR_RTOLT_OFF)
335
337
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
+
336
348
struct hisi_sas_complete_v3_hdr {
337
349
__le32 dw0 ;
338
350
__le32 dw1 ;
@@ -372,9 +384,28 @@ struct hisi_sas_err_record_v3 {
372
384
((fis.command == ATA_CMD_DEV_RESET) && \
373
385
((fis.control & ATA_SRST) != 0)))
374
386
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
+
375
401
static bool hisi_sas_intr_conv ;
376
402
MODULE_PARM_DESC (intr_conv , "interrupt converge enable (0-1)" );
377
403
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
+
378
409
static u32 hisi_sas_read32 (struct hisi_hba * hisi_hba , u32 off )
379
410
{
380
411
void __iomem * regs = hisi_hba -> regs + off ;
@@ -941,6 +972,58 @@ static void prep_prd_sge_v3_hw(struct hisi_hba *hisi_hba,
941
972
hdr -> sg_len = cpu_to_le32 (n_elem << CMD_HDR_DATA_SGL_LEN_OFF );
942
973
}
943
974
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
+
944
1027
static void prep_ssp_v3_hw (struct hisi_hba * hisi_hba ,
945
1028
struct hisi_sas_slot * slot )
946
1029
{
@@ -952,9 +1035,10 @@ static void prep_ssp_v3_hw(struct hisi_hba *hisi_hba,
952
1035
struct sas_ssp_task * ssp_task = & task -> ssp_task ;
953
1036
struct scsi_cmnd * scsi_cmnd = ssp_task -> cmd ;
954
1037
struct hisi_sas_tmf_task * tmf = slot -> tmf ;
1038
+ unsigned char prot_op = scsi_get_prot_op (scsi_cmnd );
955
1039
int has_data = 0 , priority = !!tmf ;
956
1040
u8 * buf_cmd ;
957
- u32 dw1 = 0 , dw2 = 0 ;
1041
+ u32 dw1 = 0 , dw2 = 0 , len = 0 ;
958
1042
959
1043
hdr -> dw0 = cpu_to_le32 ((1 << CMD_HDR_RESP_REPORT_OFF ) |
960
1044
(2 << CMD_HDR_TLR_CTRL_OFF ) |
@@ -984,7 +1068,6 @@ static void prep_ssp_v3_hw(struct hisi_hba *hisi_hba,
984
1068
985
1069
/* map itct entry */
986
1070
dw1 |= sas_dev -> device_id << CMD_HDR_DEV_ID_OFF ;
987
- hdr -> dw1 = cpu_to_le32 (dw1 );
988
1071
989
1072
dw2 = (((sizeof (struct ssp_command_iu ) + sizeof (struct ssp_frame_hdr )
990
1073
+ 3 ) / 4 ) << CMD_HDR_CFL_OFF ) |
@@ -997,7 +1080,6 @@ static void prep_ssp_v3_hw(struct hisi_hba *hisi_hba,
997
1080
prep_prd_sge_v3_hw (hisi_hba , slot , hdr , task -> scatter ,
998
1081
slot -> n_elem );
999
1082
1000
- hdr -> data_transfer_len = cpu_to_le32 (task -> total_xfer_len );
1001
1083
hdr -> cmd_table_addr = cpu_to_le64 (hisi_sas_cmd_hdr_addr_dma (slot ));
1002
1084
hdr -> sts_buffer_addr = cpu_to_le64 (hisi_sas_status_buf_addr_dma (slot ));
1003
1085
@@ -1022,6 +1104,38 @@ static void prep_ssp_v3_hw(struct hisi_hba *hisi_hba,
1022
1104
break ;
1023
1105
}
1024
1106
}
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 );
1025
1139
}
1026
1140
1027
1141
static void prep_smp_v3_hw (struct hisi_hba * hisi_hba ,
@@ -2291,6 +2405,12 @@ hisi_sas_shost_alloc_pci(struct pci_dev *pdev)
2291
2405
hisi_hba -> shost = shost ;
2292
2406
SHOST_TO_SAS_HA (shost ) = & hisi_hba -> sha ;
2293
2407
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
+
2294
2414
timer_setup (& hisi_hba -> timer , NULL , 0 );
2295
2415
2296
2416
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)
2401
2521
if (rc )
2402
2522
goto err_out_register_ha ;
2403
2523
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
+
2404
2530
scsi_scan_host (shost );
2405
2531
2406
2532
return 0 ;
0 commit comments