diff options
author | Charles <charles.chiou@tw.promise.com> | 2016-02-22 07:07:09 -0500 |
---|---|---|
committer | Martin K. Petersen <martin.petersen@oracle.com> | 2016-02-23 21:27:02 -0500 |
commit | 797150b98a34a27356195d5888c8eac0e2cc6b65 (patch) | |
tree | 194caa181189c7eb1c859e394690f6fc08c31bb6 | |
parent | 45b42adbec68872529e4e24ba7570de367240818 (diff) |
stex: Add S3/S4 support
Add S3/S4 support, add .suspend and .resume function in pci_driver. In
.suspend handler, driver send S3/S4 signal to the device.
Signed-off-by: Charles Chiou <charles.chiou@tw.promise.com>
Reviewed-by: Johannes Thumshirn <jthumshirn@suse.de>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
-rw-r--r-- | drivers/scsi/stex.c | 68 |
1 files changed, 65 insertions, 3 deletions
diff --git a/drivers/scsi/stex.c b/drivers/scsi/stex.c index 19946031fa9a..5b23175a584c 100644 --- a/drivers/scsi/stex.c +++ b/drivers/scsi/stex.c | |||
@@ -167,6 +167,14 @@ enum { | |||
167 | 167 | ||
168 | ST_ADDITIONAL_MEM = 0x200000, | 168 | ST_ADDITIONAL_MEM = 0x200000, |
169 | ST_ADDITIONAL_MEM_MIN = 0x80000, | 169 | ST_ADDITIONAL_MEM_MIN = 0x80000, |
170 | PMIC_SHUTDOWN = 0x0D, | ||
171 | PMIC_REUMSE = 0x10, | ||
172 | ST_IGNORED = -1, | ||
173 | ST_NOTHANDLED = 7, | ||
174 | ST_S3 = 3, | ||
175 | ST_S4 = 4, | ||
176 | ST_S5 = 5, | ||
177 | ST_S6 = 6, | ||
170 | }; | 178 | }; |
171 | 179 | ||
172 | struct st_sgitem { | 180 | struct st_sgitem { |
@@ -1718,7 +1726,7 @@ out_disable: | |||
1718 | return err; | 1726 | return err; |
1719 | } | 1727 | } |
1720 | 1728 | ||
1721 | static void stex_hba_stop(struct st_hba *hba) | 1729 | static void stex_hba_stop(struct st_hba *hba, int st_sleep_mic) |
1722 | { | 1730 | { |
1723 | struct req_msg *req; | 1731 | struct req_msg *req; |
1724 | struct st_msg_header *msg_h; | 1732 | struct st_msg_header *msg_h; |
@@ -1727,6 +1735,15 @@ static void stex_hba_stop(struct st_hba *hba) | |||
1727 | u16 tag = 0; | 1735 | u16 tag = 0; |
1728 | 1736 | ||
1729 | spin_lock_irqsave(hba->host->host_lock, flags); | 1737 | spin_lock_irqsave(hba->host->host_lock, flags); |
1738 | |||
1739 | if (hba->cardtype == st_yel && hba->supports_pm == 1) | ||
1740 | { | ||
1741 | if(st_sleep_mic == ST_NOTHANDLED) | ||
1742 | { | ||
1743 | spin_unlock_irqrestore(hba->host->host_lock, flags); | ||
1744 | return; | ||
1745 | } | ||
1746 | } | ||
1730 | req = hba->alloc_rq(hba); | 1747 | req = hba->alloc_rq(hba); |
1731 | if (hba->cardtype == st_yel) { | 1748 | if (hba->cardtype == st_yel) { |
1732 | msg_h = (struct st_msg_header *)req - 1; | 1749 | msg_h = (struct st_msg_header *)req - 1; |
@@ -1734,11 +1751,18 @@ static void stex_hba_stop(struct st_hba *hba) | |||
1734 | } else | 1751 | } else |
1735 | memset(req, 0, hba->rq_size); | 1752 | memset(req, 0, hba->rq_size); |
1736 | 1753 | ||
1737 | if (hba->cardtype == st_yosemite || hba->cardtype == st_yel) { | 1754 | if ((hba->cardtype == st_yosemite || hba->cardtype == st_yel) |
1755 | && st_sleep_mic == ST_IGNORED) { | ||
1738 | req->cdb[0] = MGT_CMD; | 1756 | req->cdb[0] = MGT_CMD; |
1739 | req->cdb[1] = MGT_CMD_SIGNATURE; | 1757 | req->cdb[1] = MGT_CMD_SIGNATURE; |
1740 | req->cdb[2] = CTLR_CONFIG_CMD; | 1758 | req->cdb[2] = CTLR_CONFIG_CMD; |
1741 | req->cdb[3] = CTLR_SHUTDOWN; | 1759 | req->cdb[3] = CTLR_SHUTDOWN; |
1760 | } else if (hba->cardtype == st_yel && st_sleep_mic != ST_IGNORED) { | ||
1761 | req->cdb[0] = MGT_CMD; | ||
1762 | req->cdb[1] = MGT_CMD_SIGNATURE; | ||
1763 | req->cdb[2] = CTLR_CONFIG_CMD; | ||
1764 | req->cdb[3] = PMIC_SHUTDOWN; | ||
1765 | req->cdb[4] = st_sleep_mic; | ||
1742 | } else { | 1766 | } else { |
1743 | req->cdb[0] = CONTROLLER_CMD; | 1767 | req->cdb[0] = CONTROLLER_CMD; |
1744 | req->cdb[1] = CTLR_POWER_STATE_CHANGE; | 1768 | req->cdb[1] = CTLR_POWER_STATE_CHANGE; |
@@ -1758,10 +1782,12 @@ static void stex_hba_stop(struct st_hba *hba) | |||
1758 | while (hba->ccb[tag].req_type & PASSTHRU_REQ_TYPE) { | 1782 | while (hba->ccb[tag].req_type & PASSTHRU_REQ_TYPE) { |
1759 | if (time_after(jiffies, before + ST_INTERNAL_TIMEOUT * HZ)) { | 1783 | if (time_after(jiffies, before + ST_INTERNAL_TIMEOUT * HZ)) { |
1760 | hba->ccb[tag].req_type = 0; | 1784 | hba->ccb[tag].req_type = 0; |
1785 | hba->mu_status = MU_STATE_STOP; | ||
1761 | return; | 1786 | return; |
1762 | } | 1787 | } |
1763 | msleep(1); | 1788 | msleep(1); |
1764 | } | 1789 | } |
1790 | hba->mu_status = MU_STATE_STOP; | ||
1765 | } | 1791 | } |
1766 | 1792 | ||
1767 | static void stex_hba_free(struct st_hba *hba) | 1793 | static void stex_hba_free(struct st_hba *hba) |
@@ -1801,9 +1827,43 @@ static void stex_shutdown(struct pci_dev *pdev) | |||
1801 | { | 1827 | { |
1802 | struct st_hba *hba = pci_get_drvdata(pdev); | 1828 | struct st_hba *hba = pci_get_drvdata(pdev); |
1803 | 1829 | ||
1804 | stex_hba_stop(hba); | 1830 | if (hba->supports_pm == 0) |
1831 | stex_hba_stop(hba, ST_IGNORED); | ||
1832 | else | ||
1833 | stex_hba_stop(hba, ST_S5); | ||
1834 | } | ||
1835 | |||
1836 | static int stex_choice_sleep_mic(pm_message_t state) | ||
1837 | { | ||
1838 | switch (state.event) { | ||
1839 | case PM_EVENT_SUSPEND: | ||
1840 | return ST_S3; | ||
1841 | case PM_EVENT_HIBERNATE: | ||
1842 | return ST_S4; | ||
1843 | default: | ||
1844 | return ST_NOTHANDLED; | ||
1845 | } | ||
1805 | } | 1846 | } |
1806 | 1847 | ||
1848 | static int stex_suspend(struct pci_dev *pdev, pm_message_t state) | ||
1849 | { | ||
1850 | struct st_hba *hba = pci_get_drvdata(pdev); | ||
1851 | |||
1852 | if (hba->cardtype == st_yel && hba->supports_pm == 1) | ||
1853 | stex_hba_stop(hba, stex_choice_sleep_mic(state)); | ||
1854 | else | ||
1855 | stex_hba_stop(hba, ST_IGNORED); | ||
1856 | return 0; | ||
1857 | } | ||
1858 | |||
1859 | static int stex_resume(struct pci_dev *pdev) | ||
1860 | { | ||
1861 | struct st_hba *hba = pci_get_drvdata(pdev); | ||
1862 | |||
1863 | hba->mu_status = MU_STATE_STARTING; | ||
1864 | stex_handshake(hba); | ||
1865 | return 0; | ||
1866 | } | ||
1807 | MODULE_DEVICE_TABLE(pci, stex_pci_tbl); | 1867 | MODULE_DEVICE_TABLE(pci, stex_pci_tbl); |
1808 | 1868 | ||
1809 | static struct pci_driver stex_pci_driver = { | 1869 | static struct pci_driver stex_pci_driver = { |
@@ -1812,6 +1872,8 @@ static struct pci_driver stex_pci_driver = { | |||
1812 | .probe = stex_probe, | 1872 | .probe = stex_probe, |
1813 | .remove = stex_remove, | 1873 | .remove = stex_remove, |
1814 | .shutdown = stex_shutdown, | 1874 | .shutdown = stex_shutdown, |
1875 | .suspend = stex_suspend, | ||
1876 | .resume = stex_resume, | ||
1815 | }; | 1877 | }; |
1816 | 1878 | ||
1817 | static int __init stex_init(void) | 1879 | static int __init stex_init(void) |