diff options
-rw-r--r-- | drivers/scsi/scsi_scan.c | 37 |
1 files changed, 27 insertions, 10 deletions
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index a86e62f4b3ba..309b2246d2d3 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c | |||
@@ -121,6 +121,7 @@ MODULE_PARM_DESC(inq_timeout, | |||
121 | "Timeout (in seconds) waiting for devices to answer INQUIRY." | 121 | "Timeout (in seconds) waiting for devices to answer INQUIRY." |
122 | " Default is 5. Some non-compliant devices need more."); | 122 | " Default is 5. Some non-compliant devices need more."); |
123 | 123 | ||
124 | /* This lock protects only this list */ | ||
124 | static DEFINE_SPINLOCK(async_scan_lock); | 125 | static DEFINE_SPINLOCK(async_scan_lock); |
125 | static LIST_HEAD(scanning_hosts); | 126 | static LIST_HEAD(scanning_hosts); |
126 | 127 | ||
@@ -1466,14 +1467,14 @@ struct scsi_device *__scsi_add_device(struct Scsi_Host *shost, uint channel, | |||
1466 | if (strncmp(scsi_scan_type, "none", 4) == 0) | 1467 | if (strncmp(scsi_scan_type, "none", 4) == 0) |
1467 | return ERR_PTR(-ENODEV); | 1468 | return ERR_PTR(-ENODEV); |
1468 | 1469 | ||
1469 | if (!shost->async_scan) | ||
1470 | scsi_complete_async_scans(); | ||
1471 | |||
1472 | starget = scsi_alloc_target(parent, channel, id); | 1470 | starget = scsi_alloc_target(parent, channel, id); |
1473 | if (!starget) | 1471 | if (!starget) |
1474 | return ERR_PTR(-ENOMEM); | 1472 | return ERR_PTR(-ENOMEM); |
1475 | 1473 | ||
1476 | mutex_lock(&shost->scan_mutex); | 1474 | mutex_lock(&shost->scan_mutex); |
1475 | if (!shost->async_scan) | ||
1476 | scsi_complete_async_scans(); | ||
1477 | |||
1477 | if (scsi_host_scan_allowed(shost)) | 1478 | if (scsi_host_scan_allowed(shost)) |
1478 | scsi_probe_and_add_lun(starget, lun, NULL, &sdev, 1, hostdata); | 1479 | scsi_probe_and_add_lun(starget, lun, NULL, &sdev, 1, hostdata); |
1479 | mutex_unlock(&shost->scan_mutex); | 1480 | mutex_unlock(&shost->scan_mutex); |
@@ -1586,10 +1587,10 @@ void scsi_scan_target(struct device *parent, unsigned int channel, | |||
1586 | if (strncmp(scsi_scan_type, "none", 4) == 0) | 1587 | if (strncmp(scsi_scan_type, "none", 4) == 0) |
1587 | return; | 1588 | return; |
1588 | 1589 | ||
1590 | mutex_lock(&shost->scan_mutex); | ||
1589 | if (!shost->async_scan) | 1591 | if (!shost->async_scan) |
1590 | scsi_complete_async_scans(); | 1592 | scsi_complete_async_scans(); |
1591 | 1593 | ||
1592 | mutex_lock(&shost->scan_mutex); | ||
1593 | if (scsi_host_scan_allowed(shost)) | 1594 | if (scsi_host_scan_allowed(shost)) |
1594 | __scsi_scan_target(parent, channel, id, lun, rescan); | 1595 | __scsi_scan_target(parent, channel, id, lun, rescan); |
1595 | mutex_unlock(&shost->scan_mutex); | 1596 | mutex_unlock(&shost->scan_mutex); |
@@ -1634,15 +1635,15 @@ int scsi_scan_host_selected(struct Scsi_Host *shost, unsigned int channel, | |||
1634 | "%s: <%u:%u:%u>\n", | 1635 | "%s: <%u:%u:%u>\n", |
1635 | __FUNCTION__, channel, id, lun)); | 1636 | __FUNCTION__, channel, id, lun)); |
1636 | 1637 | ||
1637 | if (!shost->async_scan) | ||
1638 | scsi_complete_async_scans(); | ||
1639 | |||
1640 | if (((channel != SCAN_WILD_CARD) && (channel > shost->max_channel)) || | 1638 | if (((channel != SCAN_WILD_CARD) && (channel > shost->max_channel)) || |
1641 | ((id != SCAN_WILD_CARD) && (id >= shost->max_id)) || | 1639 | ((id != SCAN_WILD_CARD) && (id >= shost->max_id)) || |
1642 | ((lun != SCAN_WILD_CARD) && (lun > shost->max_lun))) | 1640 | ((lun != SCAN_WILD_CARD) && (lun > shost->max_lun))) |
1643 | return -EINVAL; | 1641 | return -EINVAL; |
1644 | 1642 | ||
1645 | mutex_lock(&shost->scan_mutex); | 1643 | mutex_lock(&shost->scan_mutex); |
1644 | if (!shost->async_scan) | ||
1645 | scsi_complete_async_scans(); | ||
1646 | |||
1646 | if (scsi_host_scan_allowed(shost)) { | 1647 | if (scsi_host_scan_allowed(shost)) { |
1647 | if (channel == SCAN_WILD_CARD) | 1648 | if (channel == SCAN_WILD_CARD) |
1648 | for (channel = 0; channel <= shost->max_channel; | 1649 | for (channel = 0; channel <= shost->max_channel; |
@@ -1661,7 +1662,8 @@ static void scsi_sysfs_add_devices(struct Scsi_Host *shost) | |||
1661 | { | 1662 | { |
1662 | struct scsi_device *sdev; | 1663 | struct scsi_device *sdev; |
1663 | shost_for_each_device(sdev, shost) { | 1664 | shost_for_each_device(sdev, shost) { |
1664 | if (scsi_sysfs_add_sdev(sdev) != 0) | 1665 | if (!scsi_host_scan_allowed(shost) || |
1666 | scsi_sysfs_add_sdev(sdev) != 0) | ||
1665 | scsi_destroy_sdev(sdev); | 1667 | scsi_destroy_sdev(sdev); |
1666 | } | 1668 | } |
1667 | } | 1669 | } |
@@ -1679,6 +1681,7 @@ static void scsi_sysfs_add_devices(struct Scsi_Host *shost) | |||
1679 | static struct async_scan_data *scsi_prep_async_scan(struct Scsi_Host *shost) | 1681 | static struct async_scan_data *scsi_prep_async_scan(struct Scsi_Host *shost) |
1680 | { | 1682 | { |
1681 | struct async_scan_data *data; | 1683 | struct async_scan_data *data; |
1684 | unsigned long flags; | ||
1682 | 1685 | ||
1683 | if (strncmp(scsi_scan_type, "sync", 4) == 0) | 1686 | if (strncmp(scsi_scan_type, "sync", 4) == 0) |
1684 | return NULL; | 1687 | return NULL; |
@@ -1698,8 +1701,13 @@ static struct async_scan_data *scsi_prep_async_scan(struct Scsi_Host *shost) | |||
1698 | goto err; | 1701 | goto err; |
1699 | init_completion(&data->prev_finished); | 1702 | init_completion(&data->prev_finished); |
1700 | 1703 | ||
1701 | spin_lock(&async_scan_lock); | 1704 | mutex_lock(&shost->scan_mutex); |
1705 | spin_lock_irqsave(shost->host_lock, flags); | ||
1702 | shost->async_scan = 1; | 1706 | shost->async_scan = 1; |
1707 | spin_unlock_irqrestore(shost->host_lock, flags); | ||
1708 | mutex_unlock(&shost->scan_mutex); | ||
1709 | |||
1710 | spin_lock(&async_scan_lock); | ||
1703 | if (list_empty(&scanning_hosts)) | 1711 | if (list_empty(&scanning_hosts)) |
1704 | complete(&data->prev_finished); | 1712 | complete(&data->prev_finished); |
1705 | list_add_tail(&data->list, &scanning_hosts); | 1713 | list_add_tail(&data->list, &scanning_hosts); |
@@ -1723,11 +1731,15 @@ static struct async_scan_data *scsi_prep_async_scan(struct Scsi_Host *shost) | |||
1723 | static void scsi_finish_async_scan(struct async_scan_data *data) | 1731 | static void scsi_finish_async_scan(struct async_scan_data *data) |
1724 | { | 1732 | { |
1725 | struct Scsi_Host *shost; | 1733 | struct Scsi_Host *shost; |
1734 | unsigned long flags; | ||
1726 | 1735 | ||
1727 | if (!data) | 1736 | if (!data) |
1728 | return; | 1737 | return; |
1729 | 1738 | ||
1730 | shost = data->shost; | 1739 | shost = data->shost; |
1740 | |||
1741 | mutex_lock(&shost->scan_mutex); | ||
1742 | |||
1731 | if (!shost->async_scan) { | 1743 | if (!shost->async_scan) { |
1732 | printk("%s called twice for host %d", __FUNCTION__, | 1744 | printk("%s called twice for host %d", __FUNCTION__, |
1733 | shost->host_no); | 1745 | shost->host_no); |
@@ -1739,8 +1751,13 @@ static void scsi_finish_async_scan(struct async_scan_data *data) | |||
1739 | 1751 | ||
1740 | scsi_sysfs_add_devices(shost); | 1752 | scsi_sysfs_add_devices(shost); |
1741 | 1753 | ||
1742 | spin_lock(&async_scan_lock); | 1754 | spin_lock_irqsave(shost->host_lock, flags); |
1743 | shost->async_scan = 0; | 1755 | shost->async_scan = 0; |
1756 | spin_unlock_irqrestore(shost->host_lock, flags); | ||
1757 | |||
1758 | mutex_unlock(&shost->scan_mutex); | ||
1759 | |||
1760 | spin_lock(&async_scan_lock); | ||
1744 | list_del(&data->list); | 1761 | list_del(&data->list); |
1745 | if (!list_empty(&scanning_hosts)) { | 1762 | if (!list_empty(&scanning_hosts)) { |
1746 | struct async_scan_data *next = list_entry(scanning_hosts.next, | 1763 | struct async_scan_data *next = list_entry(scanning_hosts.next, |