aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/scsi/hosts.c10
-rw-r--r--drivers/scsi/scsi_error.c16
-rw-r--r--drivers/scsi/scsi_pm.c110
-rw-r--r--drivers/scsi/scsi_priv.h14
-rw-r--r--drivers/scsi/scsi_scan.c24
-rw-r--r--drivers/scsi/scsi_sysfs.c20
-rw-r--r--drivers/scsi/sg.c10
-rw-r--r--include/scsi/scsi_device.h8
8 files changed, 201 insertions, 11 deletions
diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c
index a2b1414da288..8a8f803439e1 100644
--- a/drivers/scsi/hosts.c
+++ b/drivers/scsi/hosts.c
@@ -32,6 +32,7 @@
32#include <linux/completion.h> 32#include <linux/completion.h>
33#include <linux/transport_class.h> 33#include <linux/transport_class.h>
34#include <linux/platform_device.h> 34#include <linux/platform_device.h>
35#include <linux/pm_runtime.h>
35 36
36#include <scsi/scsi_device.h> 37#include <scsi/scsi_device.h>
37#include <scsi/scsi_host.h> 38#include <scsi/scsi_host.h>
@@ -156,6 +157,7 @@ EXPORT_SYMBOL(scsi_host_set_state);
156void scsi_remove_host(struct Scsi_Host *shost) 157void scsi_remove_host(struct Scsi_Host *shost)
157{ 158{
158 unsigned long flags; 159 unsigned long flags;
160
159 mutex_lock(&shost->scan_mutex); 161 mutex_lock(&shost->scan_mutex);
160 spin_lock_irqsave(shost->host_lock, flags); 162 spin_lock_irqsave(shost->host_lock, flags);
161 if (scsi_host_set_state(shost, SHOST_CANCEL)) 163 if (scsi_host_set_state(shost, SHOST_CANCEL))
@@ -165,6 +167,8 @@ void scsi_remove_host(struct Scsi_Host *shost)
165 return; 167 return;
166 } 168 }
167 spin_unlock_irqrestore(shost->host_lock, flags); 169 spin_unlock_irqrestore(shost->host_lock, flags);
170
171 scsi_autopm_get_host(shost);
168 scsi_forget_host(shost); 172 scsi_forget_host(shost);
169 mutex_unlock(&shost->scan_mutex); 173 mutex_unlock(&shost->scan_mutex);
170 scsi_proc_host_rm(shost); 174 scsi_proc_host_rm(shost);
@@ -216,12 +220,14 @@ int scsi_add_host_with_dma(struct Scsi_Host *shost, struct device *dev,
216 shost->shost_gendev.parent = dev ? dev : &platform_bus; 220 shost->shost_gendev.parent = dev ? dev : &platform_bus;
217 shost->dma_dev = dma_dev; 221 shost->dma_dev = dma_dev;
218 222
219 device_enable_async_suspend(&shost->shost_gendev);
220
221 error = device_add(&shost->shost_gendev); 223 error = device_add(&shost->shost_gendev);
222 if (error) 224 if (error)
223 goto out; 225 goto out;
224 226
227 pm_runtime_set_active(&shost->shost_gendev);
228 pm_runtime_enable(&shost->shost_gendev);
229 device_enable_async_suspend(&shost->shost_gendev);
230
225 scsi_host_set_state(shost, SHOST_RUNNING); 231 scsi_host_set_state(shost, SHOST_RUNNING);
226 get_device(shost->shost_gendev.parent); 232 get_device(shost->shost_gendev.parent);
227 233
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
index c60cffbefa3c..2bf98469dc4c 100644
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -1775,6 +1775,14 @@ int scsi_error_handler(void *data)
1775 * what we need to do to get it up and online again (if we can). 1775 * what we need to do to get it up and online again (if we can).
1776 * If we fail, we end up taking the thing offline. 1776 * If we fail, we end up taking the thing offline.
1777 */ 1777 */
1778 if (scsi_autopm_get_host(shost) != 0) {
1779 SCSI_LOG_ERROR_RECOVERY(1,
1780 printk(KERN_ERR "Error handler scsi_eh_%d "
1781 "unable to autoresume\n",
1782 shost->host_no));
1783 continue;
1784 }
1785
1778 if (shost->transportt->eh_strategy_handler) 1786 if (shost->transportt->eh_strategy_handler)
1779 shost->transportt->eh_strategy_handler(shost); 1787 shost->transportt->eh_strategy_handler(shost);
1780 else 1788 else
@@ -1788,6 +1796,7 @@ int scsi_error_handler(void *data)
1788 * which are still online. 1796 * which are still online.
1789 */ 1797 */
1790 scsi_restart_operations(shost); 1798 scsi_restart_operations(shost);
1799 scsi_autopm_put_host(shost);
1791 set_current_state(TASK_INTERRUPTIBLE); 1800 set_current_state(TASK_INTERRUPTIBLE);
1792 } 1801 }
1793 __set_current_state(TASK_RUNNING); 1802 __set_current_state(TASK_RUNNING);
@@ -1885,12 +1894,16 @@ scsi_reset_provider_done_command(struct scsi_cmnd *scmd)
1885int 1894int
1886scsi_reset_provider(struct scsi_device *dev, int flag) 1895scsi_reset_provider(struct scsi_device *dev, int flag)
1887{ 1896{
1888 struct scsi_cmnd *scmd = scsi_get_command(dev, GFP_KERNEL); 1897 struct scsi_cmnd *scmd;
1889 struct Scsi_Host *shost = dev->host; 1898 struct Scsi_Host *shost = dev->host;
1890 struct request req; 1899 struct request req;
1891 unsigned long flags; 1900 unsigned long flags;
1892 int rtn; 1901 int rtn;
1893 1902
1903 if (scsi_autopm_get_host(shost) < 0)
1904 return FAILED;
1905
1906 scmd = scsi_get_command(dev, GFP_KERNEL);
1894 blk_rq_init(NULL, &req); 1907 blk_rq_init(NULL, &req);
1895 scmd->request = &req; 1908 scmd->request = &req;
1896 1909
@@ -1947,6 +1960,7 @@ scsi_reset_provider(struct scsi_device *dev, int flag)
1947 scsi_run_host_queues(shost); 1960 scsi_run_host_queues(shost);
1948 1961
1949 scsi_next_command(scmd); 1962 scsi_next_command(scmd);
1963 scsi_autopm_put_host(shost);
1950 return rtn; 1964 return rtn;
1951} 1965}
1952EXPORT_SYMBOL(scsi_reset_provider); 1966EXPORT_SYMBOL(scsi_reset_provider);
diff --git a/drivers/scsi/scsi_pm.c b/drivers/scsi/scsi_pm.c
index cd83758ce0a2..d70e91ae60af 100644
--- a/drivers/scsi/scsi_pm.c
+++ b/drivers/scsi/scsi_pm.c
@@ -59,6 +59,12 @@ static int scsi_bus_resume_common(struct device *dev)
59 59
60 if (scsi_is_sdev_device(dev)) 60 if (scsi_is_sdev_device(dev))
61 err = scsi_dev_type_resume(dev); 61 err = scsi_dev_type_resume(dev);
62
63 if (err == 0) {
64 pm_runtime_disable(dev);
65 pm_runtime_set_active(dev);
66 pm_runtime_enable(dev);
67 }
62 return err; 68 return err;
63} 69}
64 70
@@ -86,6 +92,107 @@ static int scsi_bus_poweroff(struct device *dev)
86 92
87#endif /* CONFIG_PM_SLEEP */ 93#endif /* CONFIG_PM_SLEEP */
88 94
95#ifdef CONFIG_PM_RUNTIME
96
97static int scsi_runtime_suspend(struct device *dev)
98{
99 int err = 0;
100
101 dev_dbg(dev, "scsi_runtime_suspend\n");
102 if (scsi_is_sdev_device(dev)) {
103 err = scsi_dev_type_suspend(dev, PMSG_AUTO_SUSPEND);
104 if (err == -EAGAIN)
105 pm_schedule_suspend(dev, jiffies_to_msecs(
106 round_jiffies_up_relative(HZ/10)));
107 }
108
109 /* Insert hooks here for targets, hosts, and transport classes */
110
111 return err;
112}
113
114static int scsi_runtime_resume(struct device *dev)
115{
116 int err = 0;
117
118 dev_dbg(dev, "scsi_runtime_resume\n");
119 if (scsi_is_sdev_device(dev))
120 err = scsi_dev_type_resume(dev);
121
122 /* Insert hooks here for targets, hosts, and transport classes */
123
124 return err;
125}
126
127static int scsi_runtime_idle(struct device *dev)
128{
129 int err;
130
131 dev_dbg(dev, "scsi_runtime_idle\n");
132
133 /* Insert hooks here for targets, hosts, and transport classes */
134
135 if (scsi_is_sdev_device(dev))
136 err = pm_schedule_suspend(dev, 100);
137 else
138 err = pm_runtime_suspend(dev);
139 return err;
140}
141
142int scsi_autopm_get_device(struct scsi_device *sdev)
143{
144 int err;
145
146 err = pm_runtime_get_sync(&sdev->sdev_gendev);
147 if (err < 0)
148 pm_runtime_put_sync(&sdev->sdev_gendev);
149 else if (err > 0)
150 err = 0;
151 return err;
152}
153EXPORT_SYMBOL_GPL(scsi_autopm_get_device);
154
155void scsi_autopm_put_device(struct scsi_device *sdev)
156{
157 pm_runtime_put_sync(&sdev->sdev_gendev);
158}
159EXPORT_SYMBOL_GPL(scsi_autopm_put_device);
160
161void scsi_autopm_get_target(struct scsi_target *starget)
162{
163 pm_runtime_get_sync(&starget->dev);
164}
165
166void scsi_autopm_put_target(struct scsi_target *starget)
167{
168 pm_runtime_put_sync(&starget->dev);
169}
170
171int scsi_autopm_get_host(struct Scsi_Host *shost)
172{
173 int err;
174
175 err = pm_runtime_get_sync(&shost->shost_gendev);
176 if (err < 0)
177 pm_runtime_put_sync(&shost->shost_gendev);
178 else if (err > 0)
179 err = 0;
180 return err;
181}
182
183void scsi_autopm_put_host(struct Scsi_Host *shost)
184{
185 pm_runtime_put_sync(&shost->shost_gendev);
186}
187
188#else
189
190#define scsi_runtime_suspend NULL
191#define scsi_runtime_resume NULL
192#define scsi_runtime_idle NULL
193
194#endif /* CONFIG_PM_RUNTIME */
195
89const struct dev_pm_ops scsi_bus_pm_ops = { 196const struct dev_pm_ops scsi_bus_pm_ops = {
90 .suspend = scsi_bus_suspend, 197 .suspend = scsi_bus_suspend,
91 .resume = scsi_bus_resume_common, 198 .resume = scsi_bus_resume_common,
@@ -93,4 +200,7 @@ const struct dev_pm_ops scsi_bus_pm_ops = {
93 .thaw = scsi_bus_resume_common, 200 .thaw = scsi_bus_resume_common,
94 .poweroff = scsi_bus_poweroff, 201 .poweroff = scsi_bus_poweroff,
95 .restore = scsi_bus_resume_common, 202 .restore = scsi_bus_resume_common,
203 .runtime_suspend = scsi_runtime_suspend,
204 .runtime_resume = scsi_runtime_resume,
205 .runtime_idle = scsi_runtime_idle,
96}; 206};
diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h
index dddacc732550..026295e2c539 100644
--- a/drivers/scsi/scsi_priv.h
+++ b/drivers/scsi/scsi_priv.h
@@ -7,6 +7,7 @@ struct request_queue;
7struct request; 7struct request;
8struct scsi_cmnd; 8struct scsi_cmnd;
9struct scsi_device; 9struct scsi_device;
10struct scsi_target;
10struct scsi_host_template; 11struct scsi_host_template;
11struct Scsi_Host; 12struct Scsi_Host;
12struct scsi_nl_hdr; 13struct scsi_nl_hdr;
@@ -147,9 +148,20 @@ static inline void scsi_netlink_exit(void) {}
147/* scsi_pm.c */ 148/* scsi_pm.c */
148#ifdef CONFIG_PM_OPS 149#ifdef CONFIG_PM_OPS
149extern const struct dev_pm_ops scsi_bus_pm_ops; 150extern const struct dev_pm_ops scsi_bus_pm_ops;
150#else 151#else /* CONFIG_PM_OPS */
151#define scsi_bus_pm_ops (*NULL) 152#define scsi_bus_pm_ops (*NULL)
152#endif 153#endif
154#ifdef CONFIG_PM_RUNTIME
155extern void scsi_autopm_get_target(struct scsi_target *);
156extern void scsi_autopm_put_target(struct scsi_target *);
157extern int scsi_autopm_get_host(struct Scsi_Host *);
158extern void scsi_autopm_put_host(struct Scsi_Host *);
159#else
160static inline void scsi_autopm_get_target(struct scsi_target *t) {}
161static inline void scsi_autopm_put_target(struct scsi_target *t) {}
162static inline int scsi_autopm_get_host(struct Scsi_Host *h) { return 0; }
163static inline void scsi_autopm_put_host(struct Scsi_Host *h) {}
164#endif /* CONFIG_PM_RUNTIME */
153 165
154/* 166/*
155 * internal scsi timeout functions: for use by mid-layer and transport 167 * internal scsi timeout functions: for use by mid-layer and transport
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index 1c027a97d8b9..3d0a1e6e9c48 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -1513,14 +1513,18 @@ struct scsi_device *__scsi_add_device(struct Scsi_Host *shost, uint channel,
1513 starget = scsi_alloc_target(parent, channel, id); 1513 starget = scsi_alloc_target(parent, channel, id);
1514 if (!starget) 1514 if (!starget)
1515 return ERR_PTR(-ENOMEM); 1515 return ERR_PTR(-ENOMEM);
1516 scsi_autopm_get_target(starget);
1516 1517
1517 mutex_lock(&shost->scan_mutex); 1518 mutex_lock(&shost->scan_mutex);
1518 if (!shost->async_scan) 1519 if (!shost->async_scan)
1519 scsi_complete_async_scans(); 1520 scsi_complete_async_scans();
1520 1521
1521 if (scsi_host_scan_allowed(shost)) 1522 if (scsi_host_scan_allowed(shost) && scsi_autopm_get_host(shost) == 0) {
1522 scsi_probe_and_add_lun(starget, lun, NULL, &sdev, 1, hostdata); 1523 scsi_probe_and_add_lun(starget, lun, NULL, &sdev, 1, hostdata);
1524 scsi_autopm_put_host(shost);
1525 }
1523 mutex_unlock(&shost->scan_mutex); 1526 mutex_unlock(&shost->scan_mutex);
1527 scsi_autopm_put_target(starget);
1524 scsi_target_reap(starget); 1528 scsi_target_reap(starget);
1525 put_device(&starget->dev); 1529 put_device(&starget->dev);
1526 1530
@@ -1574,6 +1578,7 @@ static void __scsi_scan_target(struct device *parent, unsigned int channel,
1574 starget = scsi_alloc_target(parent, channel, id); 1578 starget = scsi_alloc_target(parent, channel, id);
1575 if (!starget) 1579 if (!starget)
1576 return; 1580 return;
1581 scsi_autopm_get_target(starget);
1577 1582
1578 if (lun != SCAN_WILD_CARD) { 1583 if (lun != SCAN_WILD_CARD) {
1579 /* 1584 /*
@@ -1599,6 +1604,7 @@ static void __scsi_scan_target(struct device *parent, unsigned int channel,
1599 } 1604 }
1600 1605
1601 out_reap: 1606 out_reap:
1607 scsi_autopm_put_target(starget);
1602 /* now determine if the target has any children at all 1608 /* now determine if the target has any children at all
1603 * and if not, nuke it */ 1609 * and if not, nuke it */
1604 scsi_target_reap(starget); 1610 scsi_target_reap(starget);
@@ -1633,8 +1639,10 @@ void scsi_scan_target(struct device *parent, unsigned int channel,
1633 if (!shost->async_scan) 1639 if (!shost->async_scan)
1634 scsi_complete_async_scans(); 1640 scsi_complete_async_scans();
1635 1641
1636 if (scsi_host_scan_allowed(shost)) 1642 if (scsi_host_scan_allowed(shost) && scsi_autopm_get_host(shost) == 0) {
1637 __scsi_scan_target(parent, channel, id, lun, rescan); 1643 __scsi_scan_target(parent, channel, id, lun, rescan);
1644 scsi_autopm_put_host(shost);
1645 }
1638 mutex_unlock(&shost->scan_mutex); 1646 mutex_unlock(&shost->scan_mutex);
1639} 1647}
1640EXPORT_SYMBOL(scsi_scan_target); 1648EXPORT_SYMBOL(scsi_scan_target);
@@ -1686,7 +1694,7 @@ int scsi_scan_host_selected(struct Scsi_Host *shost, unsigned int channel,
1686 if (!shost->async_scan) 1694 if (!shost->async_scan)
1687 scsi_complete_async_scans(); 1695 scsi_complete_async_scans();
1688 1696
1689 if (scsi_host_scan_allowed(shost)) { 1697 if (scsi_host_scan_allowed(shost) && scsi_autopm_get_host(shost) == 0) {
1690 if (channel == SCAN_WILD_CARD) 1698 if (channel == SCAN_WILD_CARD)
1691 for (channel = 0; channel <= shost->max_channel; 1699 for (channel = 0; channel <= shost->max_channel;
1692 channel++) 1700 channel++)
@@ -1694,6 +1702,7 @@ int scsi_scan_host_selected(struct Scsi_Host *shost, unsigned int channel,
1694 rescan); 1702 rescan);
1695 else 1703 else
1696 scsi_scan_channel(shost, channel, id, lun, rescan); 1704 scsi_scan_channel(shost, channel, id, lun, rescan);
1705 scsi_autopm_put_host(shost);
1697 } 1706 }
1698 mutex_unlock(&shost->scan_mutex); 1707 mutex_unlock(&shost->scan_mutex);
1699 1708
@@ -1831,8 +1840,11 @@ static void do_scsi_scan_host(struct Scsi_Host *shost)
1831static int do_scan_async(void *_data) 1840static int do_scan_async(void *_data)
1832{ 1841{
1833 struct async_scan_data *data = _data; 1842 struct async_scan_data *data = _data;
1834 do_scsi_scan_host(data->shost); 1843 struct Scsi_Host *shost = data->shost;
1844
1845 do_scsi_scan_host(shost);
1835 scsi_finish_async_scan(data); 1846 scsi_finish_async_scan(data);
1847 scsi_autopm_put_host(shost);
1836 return 0; 1848 return 0;
1837} 1849}
1838 1850
@@ -1847,16 +1859,20 @@ void scsi_scan_host(struct Scsi_Host *shost)
1847 1859
1848 if (strncmp(scsi_scan_type, "none", 4) == 0) 1860 if (strncmp(scsi_scan_type, "none", 4) == 0)
1849 return; 1861 return;
1862 if (scsi_autopm_get_host(shost) < 0)
1863 return;
1850 1864
1851 data = scsi_prep_async_scan(shost); 1865 data = scsi_prep_async_scan(shost);
1852 if (!data) { 1866 if (!data) {
1853 do_scsi_scan_host(shost); 1867 do_scsi_scan_host(shost);
1868 scsi_autopm_put_host(shost);
1854 return; 1869 return;
1855 } 1870 }
1856 1871
1857 p = kthread_run(do_scan_async, data, "scsi_scan_%d", shost->host_no); 1872 p = kthread_run(do_scan_async, data, "scsi_scan_%d", shost->host_no);
1858 if (IS_ERR(p)) 1873 if (IS_ERR(p))
1859 do_scan_async(data); 1874 do_scan_async(data);
1875 /* scsi_autopm_put_host(shost) is called in do_scan_async() */
1860} 1876}
1861EXPORT_SYMBOL(scsi_scan_host); 1877EXPORT_SYMBOL(scsi_scan_host);
1862 1878
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
index 5f85f8e831f3..562fb3bce261 100644
--- a/drivers/scsi/scsi_sysfs.c
+++ b/drivers/scsi/scsi_sysfs.c
@@ -11,6 +11,7 @@
11#include <linux/init.h> 11#include <linux/init.h>
12#include <linux/blkdev.h> 12#include <linux/blkdev.h>
13#include <linux/device.h> 13#include <linux/device.h>
14#include <linux/pm_runtime.h>
14 15
15#include <scsi/scsi.h> 16#include <scsi/scsi.h>
16#include <scsi/scsi_device.h> 17#include <scsi/scsi_device.h>
@@ -802,8 +803,6 @@ static int scsi_target_add(struct scsi_target *starget)
802 if (starget->state != STARGET_CREATED) 803 if (starget->state != STARGET_CREATED)
803 return 0; 804 return 0;
804 805
805 device_enable_async_suspend(&starget->dev);
806
807 error = device_add(&starget->dev); 806 error = device_add(&starget->dev);
808 if (error) { 807 if (error) {
809 dev_err(&starget->dev, "target device_add failed, error %d\n", error); 808 dev_err(&starget->dev, "target device_add failed, error %d\n", error);
@@ -812,6 +811,10 @@ static int scsi_target_add(struct scsi_target *starget)
812 transport_add_device(&starget->dev); 811 transport_add_device(&starget->dev);
813 starget->state = STARGET_RUNNING; 812 starget->state = STARGET_RUNNING;
814 813
814 pm_runtime_set_active(&starget->dev);
815 pm_runtime_enable(&starget->dev);
816 device_enable_async_suspend(&starget->dev);
817
815 return 0; 818 return 0;
816} 819}
817 820
@@ -841,7 +844,20 @@ int scsi_sysfs_add_sdev(struct scsi_device *sdev)
841 return error; 844 return error;
842 845
843 transport_configure_device(&starget->dev); 846 transport_configure_device(&starget->dev);
847
844 device_enable_async_suspend(&sdev->sdev_gendev); 848 device_enable_async_suspend(&sdev->sdev_gendev);
849 scsi_autopm_get_target(starget);
850 pm_runtime_set_active(&sdev->sdev_gendev);
851 pm_runtime_forbid(&sdev->sdev_gendev);
852 pm_runtime_enable(&sdev->sdev_gendev);
853 scsi_autopm_put_target(starget);
854
855 /* The following call will keep sdev active indefinitely, until
856 * its driver does a corresponding scsi_autopm_pm_device(). Only
857 * drivers supporting autosuspend will do this.
858 */
859 scsi_autopm_get_device(sdev);
860
845 error = device_add(&sdev->sdev_gendev); 861 error = device_add(&sdev->sdev_gendev);
846 if (error) { 862 if (error) {
847 printk(KERN_INFO "error 1\n"); 863 printk(KERN_INFO "error 1\n");
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index d4549092400c..2968c6b83ddb 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -245,6 +245,10 @@ sg_open(struct inode *inode, struct file *filp)
245 if (retval) 245 if (retval)
246 goto sg_put; 246 goto sg_put;
247 247
248 retval = scsi_autopm_get_device(sdp->device);
249 if (retval)
250 goto sdp_put;
251
248 if (!((flags & O_NONBLOCK) || 252 if (!((flags & O_NONBLOCK) ||
249 scsi_block_when_processing_errors(sdp->device))) { 253 scsi_block_when_processing_errors(sdp->device))) {
250 retval = -ENXIO; 254 retval = -ENXIO;
@@ -302,8 +306,11 @@ sg_open(struct inode *inode, struct file *filp)
302 } 306 }
303 retval = 0; 307 retval = 0;
304error_out: 308error_out:
305 if (retval) 309 if (retval) {
310 scsi_autopm_put_device(sdp->device);
311sdp_put:
306 scsi_device_put(sdp->device); 312 scsi_device_put(sdp->device);
313 }
307sg_put: 314sg_put:
308 if (sdp) 315 if (sdp)
309 sg_put_dev(sdp); 316 sg_put_dev(sdp);
@@ -327,6 +334,7 @@ sg_release(struct inode *inode, struct file *filp)
327 sdp->exclude = 0; 334 sdp->exclude = 0;
328 wake_up_interruptible(&sdp->o_excl_wait); 335 wake_up_interruptible(&sdp->o_excl_wait);
329 336
337 scsi_autopm_put_device(sdp->device);
330 kref_put(&sfp->f_ref, sg_remove_sfp); 338 kref_put(&sfp->f_ref, sg_remove_sfp);
331 return 0; 339 return 0;
332} 340}
diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h
index d80b6dbed1ca..50cb34ffef11 100644
--- a/include/scsi/scsi_device.h
+++ b/include/scsi/scsi_device.h
@@ -381,6 +381,14 @@ extern int scsi_execute_req(struct scsi_device *sdev, const unsigned char *cmd,
381 struct scsi_sense_hdr *, int timeout, int retries, 381 struct scsi_sense_hdr *, int timeout, int retries,
382 int *resid); 382 int *resid);
383 383
384#ifdef CONFIG_PM_RUNTIME
385extern int scsi_autopm_get_device(struct scsi_device *);
386extern void scsi_autopm_put_device(struct scsi_device *);
387#else
388static inline int scsi_autopm_get_device(struct scsi_device *d) { return 0; }
389static inline void scsi_autopm_put_device(struct scsi_device *d) {}
390#endif /* CONFIG_PM_RUNTIME */
391
384static inline int __must_check scsi_device_reprobe(struct scsi_device *sdev) 392static inline int __must_check scsi_device_reprobe(struct scsi_device *sdev)
385{ 393{
386 return device_reprobe(&sdev->sdev_gendev); 394 return device_reprobe(&sdev->sdev_gendev);