aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorXiaofei Tan <tanxiaofei@huawei.com>2018-05-21 06:09:23 -0400
committerMartin K. Petersen <martin.petersen@oracle.com>2018-05-28 22:40:32 -0400
commit31709548d2aca9861a72e2890d62fc87c52199de (patch)
tree80ec90612effbd594966ae1b279b39537e51e9cb
parentb09fcd09e9767f81187aa4036fb16d14e2f2fc79 (diff)
scsi: hisi_sas: Terminate STP reject quickly for v2 hw
For v2 hw, STP link from target is rejected after host reset because of a SoC bug. The STP reject will be terminated after we have sent IO from each PHY of a port. This is not an problem before, as we don't need to setup STP link from target immediately after host reset. But now, it is. Because we want to send soft-reset immediately after host reset. In order to terminate STP reject quickly, this patch send ATA reset command through each PHY of a port. Notes: ATA reset command don't need target's response. Besides, we do abort dev for each device before terminating STP reject. This is a quirk of v2 hw. Signed-off-by: Xiaofei Tan <tanxiaofei@huawei.com> Signed-off-by: John Garry <john.garry@huawei.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
-rw-r--r--drivers/scsi/hisi_sas/hisi_sas_main.c78
1 files changed, 78 insertions, 0 deletions
diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c
index 4e8046ecf477..cd55849bcd07 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -1275,6 +1275,81 @@ static void hisi_sas_reset_init_all_devices(struct hisi_hba *hisi_hba)
1275 } 1275 }
1276} 1276}
1277 1277
1278static void hisi_sas_send_ata_reset_each_phy(struct hisi_hba *hisi_hba,
1279 struct asd_sas_port *sas_port,
1280 struct domain_device *device)
1281{
1282 struct hisi_sas_tmf_task tmf_task = { .force_phy = 1 };
1283 struct ata_port *ap = device->sata_dev.ap;
1284 struct device *dev = hisi_hba->dev;
1285 int s = sizeof(struct host_to_dev_fis);
1286 int rc = TMF_RESP_FUNC_FAILED;
1287 struct asd_sas_phy *sas_phy;
1288 struct ata_link *link;
1289 u8 fis[20] = {0};
1290 u32 state;
1291
1292 state = hisi_hba->hw->get_phys_state(hisi_hba);
1293 list_for_each_entry(sas_phy, &sas_port->phy_list, port_phy_el) {
1294 if (!(state & BIT(sas_phy->id)))
1295 continue;
1296
1297 ata_for_each_link(link, ap, EDGE) {
1298 int pmp = sata_srst_pmp(link);
1299
1300 tmf_task.phy_id = sas_phy->id;
1301 hisi_sas_fill_ata_reset_cmd(link->device, 1, pmp, fis);
1302 rc = hisi_sas_exec_internal_tmf_task(device, fis, s,
1303 &tmf_task);
1304 if (rc != TMF_RESP_FUNC_COMPLETE) {
1305 dev_err(dev, "phy%d ata reset failed rc=%d\n",
1306 sas_phy->id, rc);
1307 break;
1308 }
1309 }
1310 }
1311}
1312
1313static void hisi_sas_terminate_stp_reject(struct hisi_hba *hisi_hba)
1314{
1315 struct device *dev = hisi_hba->dev;
1316 int port_no, rc, i;
1317
1318 for (i = 0; i < HISI_SAS_MAX_DEVICES; i++) {
1319 struct hisi_sas_device *sas_dev = &hisi_hba->devices[i];
1320 struct domain_device *device = sas_dev->sas_device;
1321
1322 if ((sas_dev->dev_type == SAS_PHY_UNUSED) || !device)
1323 continue;
1324
1325 rc = hisi_sas_internal_task_abort(hisi_hba, device,
1326 HISI_SAS_INT_ABT_DEV, 0);
1327 if (rc < 0)
1328 dev_err(dev, "STP reject: abort dev failed %d\n", rc);
1329 }
1330
1331 for (port_no = 0; port_no < hisi_hba->n_phy; port_no++) {
1332 struct hisi_sas_port *port = &hisi_hba->port[port_no];
1333 struct asd_sas_port *sas_port = &port->sas_port;
1334 struct domain_device *port_dev = sas_port->port_dev;
1335 struct domain_device *device;
1336
1337 if (!port_dev || !DEV_IS_EXPANDER(port_dev->dev_type))
1338 continue;
1339
1340 /* Try to find a SATA device */
1341 list_for_each_entry(device, &sas_port->dev_list,
1342 dev_list_node) {
1343 if (dev_is_sata(device)) {
1344 hisi_sas_send_ata_reset_each_phy(hisi_hba,
1345 sas_port,
1346 device);
1347 break;
1348 }
1349 }
1350 }
1351}
1352
1278static int hisi_sas_controller_reset(struct hisi_hba *hisi_hba) 1353static int hisi_sas_controller_reset(struct hisi_hba *hisi_hba)
1279{ 1354{
1280 struct device *dev = hisi_hba->dev; 1355 struct device *dev = hisi_hba->dev;
@@ -1312,6 +1387,9 @@ static int hisi_sas_controller_reset(struct hisi_hba *hisi_hba)
1312 hisi_hba->hw->phys_init(hisi_hba); 1387 hisi_hba->hw->phys_init(hisi_hba);
1313 msleep(1000); 1388 msleep(1000);
1314 hisi_sas_refresh_port_id(hisi_hba); 1389 hisi_sas_refresh_port_id(hisi_hba);
1390
1391 if (hisi_hba->reject_stp_links_msk)
1392 hisi_sas_terminate_stp_reject(hisi_hba);
1315 hisi_sas_reset_init_all_devices(hisi_hba); 1393 hisi_sas_reset_init_all_devices(hisi_hba);
1316 scsi_unblock_requests(shost); 1394 scsi_unblock_requests(shost);
1317 1395