aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorXiang Chen <chenxiang66@hisilicon.com>2019-02-28 09:51:01 -0500
committerMartin K. Petersen <martin.petersen@oracle.com>2019-03-06 19:26:46 -0500
commit57dbb2b218eb6b4faa39025e3e5974742a4e8986 (patch)
tree46d6ac77a3db6b5260a4fe4c58ff86eaa933e89f
parentefdcad62e7b8a02fcccc5ccca57806dce1482ac8 (diff)
scsi: hisi_sas: Send HARD RESET to clear the previous affiliation of STP target port
If we exchange SAS expander from one SAS controller to other SAS controller without powering it down, the STP target port will maintain previous affiliation and reject all subsequent connection requests from other STP initiator ports with OPEN_REJECT (STP RESOURCES BUSY). To solve this issue, send HARD RESET to clear the previous affiliation of STP target port according to SPL (chapter 6.19.4). We (re-)introduce dev status flag to know if to sleep in NEXUS reset code or not for remote PHYs. The idea is that if the device is being initialised, we don't require the delay, and caller would wait for link to be established, cf. sas_ata_hard_reset(). Co-developed-by: Luo Jiaxing <luojiaxing@huawei.com> 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>
-rw-r--r--drivers/scsi/hisi_sas/hisi_sas.h7
-rw-r--r--drivers/scsi/hisi_sas/hisi_sas_main.c44
-rw-r--r--drivers/scsi/hisi_sas/hisi_sas_v2_hw.c1
3 files changed, 49 insertions, 3 deletions
diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h
index 515aee9318a4..9bfa9f12d81e 100644
--- a/drivers/scsi/hisi_sas/hisi_sas.h
+++ b/drivers/scsi/hisi_sas/hisi_sas.h
@@ -18,6 +18,7 @@
18#include <linux/dmapool.h> 18#include <linux/dmapool.h>
19#include <linux/iopoll.h> 19#include <linux/iopoll.h>
20#include <linux/lcm.h> 20#include <linux/lcm.h>
21#include <linux/libata.h>
21#include <linux/mfd/syscon.h> 22#include <linux/mfd/syscon.h>
22#include <linux/module.h> 23#include <linux/module.h>
23#include <linux/of_address.h> 24#include <linux/of_address.h>
@@ -94,6 +95,11 @@ enum {
94 PORT_TYPE_SATA = (1U << 0), 95 PORT_TYPE_SATA = (1U << 0),
95}; 96};
96 97
98enum dev_status {
99 HISI_SAS_DEV_INIT,
100 HISI_SAS_DEV_NORMAL,
101};
102
97enum { 103enum {
98 HISI_SAS_INT_ABT_CMD = 0, 104 HISI_SAS_INT_ABT_CMD = 0,
99 HISI_SAS_INT_ABT_DEV = 1, 105 HISI_SAS_INT_ABT_DEV = 1,
@@ -195,6 +201,7 @@ struct hisi_sas_device {
195 struct hisi_sas_dq *dq; 201 struct hisi_sas_dq *dq;
196 struct list_head list; 202 struct list_head list;
197 enum sas_device_type dev_type; 203 enum sas_device_type dev_type;
204 enum dev_status dev_status;
198 int device_id; 205 int device_id;
199 int sata_idx; 206 int sata_idx;
200 spinlock_t lock; /* For protecting slots */ 207 spinlock_t lock; /* For protecting slots */
diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c
index d8204bc3931b..d12924256964 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -708,6 +708,7 @@ static struct hisi_sas_device *hisi_sas_alloc_dev(struct domain_device *device)
708 708
709 hisi_hba->devices[i].device_id = i; 709 hisi_hba->devices[i].device_id = i;
710 sas_dev = &hisi_hba->devices[i]; 710 sas_dev = &hisi_hba->devices[i];
711 sas_dev->dev_status = HISI_SAS_DEV_INIT;
711 sas_dev->dev_type = device->dev_type; 712 sas_dev->dev_type = device->dev_type;
712 sas_dev->hisi_hba = hisi_hba; 713 sas_dev->hisi_hba = hisi_hba;
713 sas_dev->sas_device = device; 714 sas_dev->sas_device = device;
@@ -732,6 +733,8 @@ static int hisi_sas_init_device(struct domain_device *device)
732 struct hisi_sas_tmf_task tmf_task; 733 struct hisi_sas_tmf_task tmf_task;
733 int retry = HISI_SAS_SRST_ATA_DISK_CNT; 734 int retry = HISI_SAS_SRST_ATA_DISK_CNT;
734 struct hisi_hba *hisi_hba = dev_to_hisi_hba(device); 735 struct hisi_hba *hisi_hba = dev_to_hisi_hba(device);
736 struct device *dev = hisi_hba->dev;
737 struct sas_phy *local_phy;
735 738
736 switch (device->dev_type) { 739 switch (device->dev_type) {
737 case SAS_END_DEVICE: 740 case SAS_END_DEVICE:
@@ -747,6 +750,31 @@ static int hisi_sas_init_device(struct domain_device *device)
747 case SAS_SATA_PM: 750 case SAS_SATA_PM:
748 case SAS_SATA_PM_PORT: 751 case SAS_SATA_PM_PORT:
749 case SAS_SATA_PENDING: 752 case SAS_SATA_PENDING:
753 /*
754 * send HARD RESET to clear previous affiliation of
755 * STP target port
756 */
757 local_phy = sas_get_local_phy(device);
758 if (!scsi_is_sas_phy_local(local_phy)) {
759 unsigned long deadline = ata_deadline(jiffies, 20000);
760 struct sata_device *sata_dev = &device->sata_dev;
761 struct ata_host *ata_host = sata_dev->ata_host;
762 struct ata_port_operations *ops = ata_host->ops;
763 struct ata_port *ap = sata_dev->ap;
764 struct ata_link *link;
765 unsigned int classes;
766
767 ata_for_each_link(link, ap, EDGE)
768 rc = ops->hardreset(link, &classes,
769 deadline);
770 }
771 sas_put_local_phy(local_phy);
772 if (rc) {
773 dev_warn(dev, "SATA disk hardreset fail: 0x%x\n",
774 rc);
775 return rc;
776 }
777
750 while (retry-- > 0) { 778 while (retry-- > 0) {
751 rc = hisi_sas_softreset_ata_disk(device); 779 rc = hisi_sas_softreset_ata_disk(device);
752 if (!rc) 780 if (!rc)
@@ -809,6 +837,7 @@ static int hisi_sas_dev_found(struct domain_device *device)
809 rc = hisi_sas_init_device(device); 837 rc = hisi_sas_init_device(device);
810 if (rc) 838 if (rc)
811 goto err_out; 839 goto err_out;
840 sas_dev->dev_status = HISI_SAS_DEV_NORMAL;
812 return 0; 841 return 0;
813 842
814err_out: 843err_out:
@@ -1715,20 +1744,23 @@ static int hisi_sas_clear_aca(struct domain_device *device, u8 *lun)
1715static int hisi_sas_debug_I_T_nexus_reset(struct domain_device *device) 1744static int hisi_sas_debug_I_T_nexus_reset(struct domain_device *device)
1716{ 1745{
1717 struct sas_phy *local_phy = sas_get_local_phy(device); 1746 struct sas_phy *local_phy = sas_get_local_phy(device);
1718 int rc, reset_type = (device->dev_type == SAS_SATA_DEV || 1747 struct hisi_sas_device *sas_dev = device->lldd_dev;
1719 (device->tproto & SAS_PROTOCOL_STP)) ? 0 : 1;
1720 struct hisi_hba *hisi_hba = dev_to_hisi_hba(device); 1748 struct hisi_hba *hisi_hba = dev_to_hisi_hba(device);
1721 struct sas_ha_struct *sas_ha = &hisi_hba->sha; 1749 struct sas_ha_struct *sas_ha = &hisi_hba->sha;
1722 struct asd_sas_phy *sas_phy = sas_ha->sas_phy[local_phy->number]; 1750 struct asd_sas_phy *sas_phy = sas_ha->sas_phy[local_phy->number];
1723 struct hisi_sas_phy *phy = container_of(sas_phy, 1751 struct hisi_sas_phy *phy = container_of(sas_phy,
1724 struct hisi_sas_phy, sas_phy); 1752 struct hisi_sas_phy, sas_phy);
1725 DECLARE_COMPLETION_ONSTACK(phyreset); 1753 DECLARE_COMPLETION_ONSTACK(phyreset);
1754 int rc, reset_type;
1726 1755
1727 if (scsi_is_sas_phy_local(local_phy)) { 1756 if (scsi_is_sas_phy_local(local_phy)) {
1728 phy->in_reset = 1; 1757 phy->in_reset = 1;
1729 phy->reset_completion = &phyreset; 1758 phy->reset_completion = &phyreset;
1730 } 1759 }
1731 1760
1761 reset_type = (sas_dev->dev_status == HISI_SAS_DEV_INIT ||
1762 !dev_is_sata(device)) ? 1 : 0;
1763
1732 rc = sas_phy_reset(local_phy, reset_type); 1764 rc = sas_phy_reset(local_phy, reset_type);
1733 sas_put_local_phy(local_phy); 1765 sas_put_local_phy(local_phy);
1734 1766
@@ -1744,8 +1776,13 @@ static int hisi_sas_debug_I_T_nexus_reset(struct domain_device *device)
1744 /* report PHY down if timed out */ 1776 /* report PHY down if timed out */
1745 if (!ret) 1777 if (!ret)
1746 hisi_sas_phy_down(hisi_hba, sas_phy->id, 0); 1778 hisi_sas_phy_down(hisi_hba, sas_phy->id, 0);
1747 } else 1779 } else if (sas_dev->dev_status != HISI_SAS_DEV_INIT) {
1780 /*
1781 * If in init state, we rely on caller to wait for link to be
1782 * ready; otherwise, delay.
1783 */
1748 msleep(2000); 1784 msleep(2000);
1785 }
1749 1786
1750 return rc; 1787 return rc;
1751} 1788}
@@ -2264,6 +2301,7 @@ int hisi_sas_alloc(struct hisi_hba *hisi_hba)
2264 for (i = 0; i < HISI_SAS_MAX_DEVICES; i++) { 2301 for (i = 0; i < HISI_SAS_MAX_DEVICES; i++) {
2265 hisi_hba->devices[i].dev_type = SAS_PHY_UNUSED; 2302 hisi_hba->devices[i].dev_type = SAS_PHY_UNUSED;
2266 hisi_hba->devices[i].device_id = i; 2303 hisi_hba->devices[i].device_id = i;
2304 hisi_hba->devices[i].dev_status = HISI_SAS_DEV_INIT;
2267 } 2305 }
2268 2306
2269 for (i = 0; i < hisi_hba->queue_count; i++) { 2307 for (i = 0; i < hisi_hba->queue_count; i++) {
diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
index e40cc6b3b67b..89160ab3efb0 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
@@ -868,6 +868,7 @@ hisi_sas_device *alloc_dev_quirk_v2_hw(struct domain_device *device)
868 868
869 hisi_hba->devices[i].device_id = i; 869 hisi_hba->devices[i].device_id = i;
870 sas_dev = &hisi_hba->devices[i]; 870 sas_dev = &hisi_hba->devices[i];
871 sas_dev->dev_status = HISI_SAS_DEV_INIT;
871 sas_dev->dev_type = device->dev_type; 872 sas_dev->dev_type = device->dev_type;
872 sas_dev->hisi_hba = hisi_hba; 873 sas_dev->hisi_hba = hisi_hba;
873 sas_dev->sas_device = device; 874 sas_dev->sas_device = device;