diff options
author | Xiaofei Tan <tanxiaofei@huawei.com> | 2017-08-11 00:09:26 +0800 |
---|---|---|
committer | Martin K. Petersen <martin.petersen@oracle.com> | 2017-08-10 20:15:01 -0400 |
commit | 917d3bdaf8f2ab3bace2bd60b78d83a2b3096d98 (patch) | |
tree | 09c3858f2b6bffc33f45aeadc3332d42edaa40d7 /drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | |
parent | b98117caa0e3d99e4aee1114bcb03ae9ad02bf22 (diff) |
scsi: hisi_sas: fix reset and port ID refresh issues
This patch provides fixes for the following issues:
1. Fix issue of controller reset required to send commands. For reset
process, it may be required to send commands to the controller, but
not during soft reset. So add HISI_SAS_NOT_ACCEPT_CMD_BIT to prevent
executing a task during this period.
2. Send a broadcast event in rescan topology to detect any topology
changes during reset.
3. Previously it was not ensured that libsas has processed the PHY up
and down events after reset. Potentially this could cause an issue
that we still process the PHY event after reset. So resolve this by
flushing shot workqueue in LLDD reset.
4. Port ID requires refresh after reset. The port ID generated after
reset is not guaranteed to be the same as before reset, so it needs
to be refreshed for each device's ITCT.
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>
Diffstat (limited to 'drivers/scsi/hisi_sas/hisi_sas_v2_hw.c')
-rw-r--r-- | drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 36 |
1 files changed, 15 insertions, 21 deletions
diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c index 2bfea7082e3a..a6be33c36e86 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c @@ -1364,8 +1364,15 @@ static void start_phys_v2_hw(struct hisi_hba *hisi_hba) { int i; - for (i = 0; i < hisi_hba->n_phy; i++) + for (i = 0; i < hisi_hba->n_phy; i++) { + struct hisi_sas_phy *phy = &hisi_hba->phy[i]; + struct asd_sas_phy *sas_phy = &phy->sas_phy; + + if (!sas_phy->phy->enabled) + continue; + start_phy_v2_hw(hisi_hba, i); + } } static void phys_init_v2_hw(struct hisi_hba *hisi_hba) @@ -3383,14 +3390,16 @@ static void interrupt_disable_v2_hw(struct hisi_hba *hisi_hba) synchronize_irq(platform_get_irq(pdev, i)); } + +static u32 get_phys_state_v2_hw(struct hisi_hba *hisi_hba) +{ + return hisi_sas_read32(hisi_hba, PHY_STATE); +} + static int soft_reset_v2_hw(struct hisi_hba *hisi_hba) { struct device *dev = hisi_hba->dev; - u32 old_state, state; int rc, cnt; - int phy_no; - - old_state = hisi_sas_read32(hisi_hba, PHY_STATE); interrupt_disable_v2_hw(hisi_hba); hisi_sas_write32(hisi_hba, DLVRY_QUEUE_ENABLE, 0x0); @@ -3425,22 +3434,6 @@ static int soft_reset_v2_hw(struct hisi_hba *hisi_hba) phys_reject_stp_links_v2_hw(hisi_hba); - /* Re-enable the PHYs */ - for (phy_no = 0; phy_no < hisi_hba->n_phy; phy_no++) { - struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no]; - struct asd_sas_phy *sas_phy = &phy->sas_phy; - - if (sas_phy->enabled) - start_phy_v2_hw(hisi_hba, phy_no); - } - - /* Wait for the PHYs to come up and read the PHY state */ - msleep(1000); - - state = hisi_sas_read32(hisi_hba, PHY_STATE); - - hisi_sas_rescan_topology(hisi_hba, old_state, state); - return 0; } @@ -3468,6 +3461,7 @@ static const struct hisi_sas_hw hisi_sas_v2_hw = { .max_command_entries = HISI_SAS_COMMAND_ENTRIES_V2_HW, .complete_hdr_size = sizeof(struct hisi_sas_complete_v2_hdr), .soft_reset = soft_reset_v2_hw, + .get_phys_state = get_phys_state_v2_hw, }; static int hisi_sas_v2_probe(struct platform_device *pdev) |