Skip to content

Commit d6a9000

Browse files
Xiang Chenmartinkpetersen
authored andcommitted
scsi: hisi_sas: Add support for DIF feature for v2 hw
For v3 hw, we support DIF operation for SAS, but not SATA. In addition, DIF CRC16 is supported. This patchset adds the SW support for the described features. The main components are as follows: - Get protection mask from module param - Fill PI fields - Fill related to DIF in DQ and protection iu memories Signed-off-by: Xiang Chen <chenxiang66@hisilicon.com> Signed-off-by: John Garry <john.garry@huawei.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
1 parent 4e87eb2 commit d6a9000

File tree

2 files changed

+137
-3
lines changed

2 files changed

+137
-3
lines changed

drivers/scsi/hisi_sas/hisi_sas.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,12 @@
6969
#define HISI_SAS_SATA_PROTOCOL_FPDMA 0x8
7070
#define HISI_SAS_SATA_PROTOCOL_ATAPI 0x10
7171

72+
#define HISI_SAS_DIF_PROT_MASK (SHOST_DIF_TYPE1_PROTECTION | \
73+
SHOST_DIF_TYPE2_PROTECTION | \
74+
SHOST_DIF_TYPE3_PROTECTION)
75+
76+
#define HISI_SAS_PROT_MASK (HISI_SAS_DIF_PROT_MASK)
77+
7278
struct hisi_hba;
7379

7480
enum {
@@ -268,6 +274,8 @@ struct hisi_hba {
268274
struct pci_dev *pci_dev;
269275
struct device *dev;
270276

277+
int prot_mask;
278+
271279
void __iomem *regs;
272280
void __iomem *sgpio_regs;
273281
struct regmap *ctrl;

drivers/scsi/hisi_sas/hisi_sas_v3_hw.c

Lines changed: 129 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,8 @@
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)
@@ -333,6 +335,16 @@
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+
336348
struct 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+
375401
static bool hisi_sas_intr_conv;
376402
MODULE_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+
378409
static 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+
9441027
static 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

10271141
static 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

Comments
 (0)