|
@@ -210,6 +210,8 @@
|
|
|
|
|
|
#define AXI_MASTER_CFG_BASE (0x5000)
|
|
|
#define AM_CTRL_GLOBAL (0x0)
|
|
|
+#define AM_CTRL_SHUTDOWN_REQ_OFF 0
|
|
|
+#define AM_CTRL_SHUTDOWN_REQ_MSK (0x1 << AM_CTRL_SHUTDOWN_REQ_OFF)
|
|
|
#define AM_CURR_TRANS_RETURN (0x150)
|
|
|
|
|
|
#define AM_CFG_MAX_TRANS (0x5010)
|
|
@@ -1976,11 +1978,11 @@ static void phy_get_events_v3_hw(struct hisi_hba *hisi_hba, int phy_no)
|
|
|
|
|
|
}
|
|
|
|
|
|
-static int soft_reset_v3_hw(struct hisi_hba *hisi_hba)
|
|
|
+static int disable_host_v3_hw(struct hisi_hba *hisi_hba)
|
|
|
{
|
|
|
struct device *dev = hisi_hba->dev;
|
|
|
+ u32 status, reg_val;
|
|
|
int rc;
|
|
|
- u32 status;
|
|
|
|
|
|
interrupt_disable_v3_hw(hisi_hba);
|
|
|
hisi_sas_write32(hisi_hba, DLVRY_QUEUE_ENABLE, 0x0);
|
|
@@ -1990,14 +1992,32 @@ static int soft_reset_v3_hw(struct hisi_hba *hisi_hba)
|
|
|
|
|
|
mdelay(10);
|
|
|
|
|
|
- hisi_sas_write32(hisi_hba, AXI_MASTER_CFG_BASE + AM_CTRL_GLOBAL, 0x1);
|
|
|
+ reg_val = hisi_sas_read32(hisi_hba, AXI_MASTER_CFG_BASE +
|
|
|
+ AM_CTRL_GLOBAL);
|
|
|
+ reg_val |= AM_CTRL_SHUTDOWN_REQ_MSK;
|
|
|
+ hisi_sas_write32(hisi_hba, AXI_MASTER_CFG_BASE +
|
|
|
+ AM_CTRL_GLOBAL, reg_val);
|
|
|
|
|
|
/* wait until bus idle */
|
|
|
rc = hisi_sas_read32_poll_timeout(AXI_MASTER_CFG_BASE +
|
|
|
AM_CURR_TRANS_RETURN, status,
|
|
|
status == 0x3, 10, 100);
|
|
|
if (rc) {
|
|
|
- dev_err(dev, "axi bus is not idle, rc = %d\n", rc);
|
|
|
+ dev_err(dev, "axi bus is not idle, rc=%d\n", rc);
|
|
|
+ return rc;
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static int soft_reset_v3_hw(struct hisi_hba *hisi_hba)
|
|
|
+{
|
|
|
+ struct device *dev = hisi_hba->dev;
|
|
|
+ int rc;
|
|
|
+
|
|
|
+ rc = disable_host_v3_hw(hisi_hba);
|
|
|
+ if (rc) {
|
|
|
+ dev_err(dev, "soft reset: disable host failed rc=%d\n", rc);
|
|
|
return rc;
|
|
|
}
|
|
|
|
|
@@ -2456,9 +2476,8 @@ static int hisi_sas_v3_suspend(struct pci_dev *pdev, pm_message_t state)
|
|
|
struct hisi_hba *hisi_hba = sha->lldd_ha;
|
|
|
struct device *dev = hisi_hba->dev;
|
|
|
struct Scsi_Host *shost = hisi_hba->shost;
|
|
|
- u32 device_state, status;
|
|
|
+ u32 device_state;
|
|
|
int rc;
|
|
|
- u32 reg_val;
|
|
|
|
|
|
if (!pdev->pm_cap) {
|
|
|
dev_err(dev, "PCI PM not supported\n");
|
|
@@ -2471,25 +2490,10 @@ static int hisi_sas_v3_suspend(struct pci_dev *pdev, pm_message_t state)
|
|
|
scsi_block_requests(shost);
|
|
|
set_bit(HISI_SAS_REJECT_CMD_BIT, &hisi_hba->flags);
|
|
|
flush_workqueue(hisi_hba->wq);
|
|
|
- /* disable DQ/PHY/bus */
|
|
|
- interrupt_disable_v3_hw(hisi_hba);
|
|
|
- hisi_sas_write32(hisi_hba, DLVRY_QUEUE_ENABLE, 0x0);
|
|
|
- hisi_sas_kill_tasklets(hisi_hba);
|
|
|
|
|
|
- hisi_sas_stop_phys(hisi_hba);
|
|
|
-
|
|
|
- reg_val = hisi_sas_read32(hisi_hba, AXI_MASTER_CFG_BASE +
|
|
|
- AM_CTRL_GLOBAL);
|
|
|
- reg_val |= 0x1;
|
|
|
- hisi_sas_write32(hisi_hba, AXI_MASTER_CFG_BASE +
|
|
|
- AM_CTRL_GLOBAL, reg_val);
|
|
|
-
|
|
|
- /* wait until bus idle */
|
|
|
- rc = hisi_sas_read32_poll_timeout(AXI_MASTER_CFG_BASE +
|
|
|
- AM_CURR_TRANS_RETURN, status,
|
|
|
- status == 0x3, 10, 100);
|
|
|
+ rc = disable_host_v3_hw(hisi_hba);
|
|
|
if (rc) {
|
|
|
- dev_err(dev, "axi bus is not idle, rc = %d\n", rc);
|
|
|
+ dev_err(dev, "PM suspend: disable host failed rc=%d\n", rc);
|
|
|
clear_bit(HISI_SAS_REJECT_CMD_BIT, &hisi_hba->flags);
|
|
|
clear_bit(HISI_SAS_RESET_BIT, &hisi_hba->flags);
|
|
|
scsi_unblock_requests(shost);
|