diff options
Diffstat (limited to 'drivers/scsi/scsi_scan.c')
-rw-r--r-- | drivers/scsi/scsi_scan.c | 24 |
1 files changed, 20 insertions, 4 deletions
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 | } |
1640 | EXPORT_SYMBOL(scsi_scan_target); | 1648 | EXPORT_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) | |||
1831 | static int do_scan_async(void *_data) | 1840 | static 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 | } |
1861 | EXPORT_SYMBOL(scsi_scan_host); | 1877 | EXPORT_SYMBOL(scsi_scan_host); |
1862 | 1878 | ||