diff options
| -rw-r--r-- | drivers/scsi/hisi_sas/hisi_sas.h | 7 | ||||
| -rw-r--r-- | drivers/scsi/hisi_sas/hisi_sas_main.c | 44 | ||||
| -rw-r--r-- | drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 1 |
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 | ||
| 98 | enum dev_status { | ||
| 99 | HISI_SAS_DEV_INIT, | ||
| 100 | HISI_SAS_DEV_NORMAL, | ||
| 101 | }; | ||
| 102 | |||
| 97 | enum { | 103 | enum { |
| 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 | ||
| 814 | err_out: | 843 | err_out: |
| @@ -1715,20 +1744,23 @@ static int hisi_sas_clear_aca(struct domain_device *device, u8 *lun) | |||
| 1715 | static int hisi_sas_debug_I_T_nexus_reset(struct domain_device *device) | 1744 | static 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; |
