summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCharles <charles.chiou@tw.promise.com>2016-02-22 07:07:09 -0500
committerMartin K. Petersen <martin.petersen@oracle.com>2016-02-23 21:27:02 -0500
commit797150b98a34a27356195d5888c8eac0e2cc6b65 (patch)
tree194caa181189c7eb1c859e394690f6fc08c31bb6
parent45b42adbec68872529e4e24ba7570de367240818 (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.c68
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
172struct st_sgitem { 180struct st_sgitem {
@@ -1718,7 +1726,7 @@ out_disable:
1718 return err; 1726 return err;
1719} 1727}
1720 1728
1721static void stex_hba_stop(struct st_hba *hba) 1729static 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
1767static void stex_hba_free(struct st_hba *hba) 1793static 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
1836static 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
1848static 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
1859static 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}
1807MODULE_DEVICE_TABLE(pci, stex_pci_tbl); 1867MODULE_DEVICE_TABLE(pci, stex_pci_tbl);
1808 1868
1809static struct pci_driver stex_pci_driver = { 1869static 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
1817static int __init stex_init(void) 1879static int __init stex_init(void)