Skip to content

Commit 1773fbf

Browse files
Xingui Yanggregkh
Xingui Yang
authored andcommitted
scsi: hisi_sas: Enable force phy when SATA disk directly connected
[ Upstream commit 8aa580c ] when a SATA disk is directly connected the SAS controller determines the disk to which I/Os are delivered based on the port ID in the DQ entry. When many phys are disconnected and reconnect, the port ID of phys were changed and used by other link, resulting in I/O being sent to incorrect disk. Data inconsistency on the SATA disk may occur during I/O retries using the old port ID. So enable force phy, then force the command to be executed in a certain phy, and if the actual phy ID of the port does not match the phy configured in the command, the chip will stop delivering the I/O to disk. Fixes: ce60689 ("scsi: hisi_sas: add v3 code to send ATA frame") Signed-off-by: Xingui Yang <[email protected]> Link: https://lore.kernel.org/r/[email protected] Reviewed-by: Yihang Li <[email protected]> Signed-off-by: Martin K. Petersen <[email protected]> Signed-off-by: Sasha Levin <[email protected]>
1 parent b6efa8c commit 1773fbf

File tree

2 files changed

+19
-4
lines changed

2 files changed

+19
-4
lines changed

drivers/scsi/hisi_sas/hisi_sas_v2_hw.c

+7-2
Original file line numberDiff line numberDiff line change
@@ -2501,17 +2501,22 @@ static void prep_ata_v2_hw(struct hisi_hba *hisi_hba,
25012501
struct hisi_sas_port *port = to_hisi_sas_port(sas_port);
25022502
struct sas_ata_task *ata_task = &task->ata_task;
25032503
struct sas_tmf_task *tmf = slot->tmf;
2504+
int phy_id;
25042505
u8 *buf_cmd;
25052506
int has_data = 0, hdr_tag = 0;
25062507
u32 dw0, dw1 = 0, dw2 = 0;
25072508

25082509
/* create header */
25092510
/* dw0 */
25102511
dw0 = port->id << CMD_HDR_PORT_OFF;
2511-
if (parent_dev && dev_is_expander(parent_dev->dev_type))
2512+
if (parent_dev && dev_is_expander(parent_dev->dev_type)) {
25122513
dw0 |= 3 << CMD_HDR_CMD_OFF;
2513-
else
2514+
} else {
2515+
phy_id = device->phy->identify.phy_identifier;
2516+
dw0 |= (1U << phy_id) << CMD_HDR_PHY_ID_OFF;
2517+
dw0 |= CMD_HDR_FORCE_PHY_MSK;
25142518
dw0 |= 4 << CMD_HDR_CMD_OFF;
2519+
}
25152520

25162521
if (tmf && ata_task->force_phy) {
25172522
dw0 |= CMD_HDR_FORCE_PHY_MSK;

drivers/scsi/hisi_sas/hisi_sas_v3_hw.c

+12-2
Original file line numberDiff line numberDiff line change
@@ -358,6 +358,10 @@
358358
#define CMD_HDR_RESP_REPORT_MSK (0x1 << CMD_HDR_RESP_REPORT_OFF)
359359
#define CMD_HDR_TLR_CTRL_OFF 6
360360
#define CMD_HDR_TLR_CTRL_MSK (0x3 << CMD_HDR_TLR_CTRL_OFF)
361+
#define CMD_HDR_PHY_ID_OFF 8
362+
#define CMD_HDR_PHY_ID_MSK (0x1ff << CMD_HDR_PHY_ID_OFF)
363+
#define CMD_HDR_FORCE_PHY_OFF 17
364+
#define CMD_HDR_FORCE_PHY_MSK (0x1U << CMD_HDR_FORCE_PHY_OFF)
361365
#define CMD_HDR_PORT_OFF 18
362366
#define CMD_HDR_PORT_MSK (0xf << CMD_HDR_PORT_OFF)
363367
#define CMD_HDR_PRIORITY_OFF 27
@@ -1425,15 +1429,21 @@ static void prep_ata_v3_hw(struct hisi_hba *hisi_hba,
14251429
struct hisi_sas_cmd_hdr *hdr = slot->cmd_hdr;
14261430
struct asd_sas_port *sas_port = device->port;
14271431
struct hisi_sas_port *port = to_hisi_sas_port(sas_port);
1432+
int phy_id;
14281433
u8 *buf_cmd;
14291434
int has_data = 0, hdr_tag = 0;
14301435
u32 dw1 = 0, dw2 = 0;
14311436

14321437
hdr->dw0 = cpu_to_le32(port->id << CMD_HDR_PORT_OFF);
1433-
if (parent_dev && dev_is_expander(parent_dev->dev_type))
1438+
if (parent_dev && dev_is_expander(parent_dev->dev_type)) {
14341439
hdr->dw0 |= cpu_to_le32(3 << CMD_HDR_CMD_OFF);
1435-
else
1440+
} else {
1441+
phy_id = device->phy->identify.phy_identifier;
1442+
hdr->dw0 |= cpu_to_le32((1U << phy_id)
1443+
<< CMD_HDR_PHY_ID_OFF);
1444+
hdr->dw0 |= CMD_HDR_FORCE_PHY_MSK;
14361445
hdr->dw0 |= cpu_to_le32(4U << CMD_HDR_CMD_OFF);
1446+
}
14371447

14381448
switch (task->data_dir) {
14391449
case DMA_TO_DEVICE:

0 commit comments

Comments
 (0)