aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/scsi_scan.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@woody.osdl.org>2006-12-05 19:09:46 -0500
committerLinus Torvalds <torvalds@woody.osdl.org>2006-12-05 19:09:46 -0500
commitec0bf39a471bf6fcd01def2bd677128cea940b73 (patch)
tree0d98b304d97605613a14329b40ed8cbb88296528 /drivers/scsi/scsi_scan.c
parentbf83c2a315637dee8a8b5c2221ce5030cc38c6db (diff)
parentd32adcb85c74fd81963714689842993e7014515f (diff)
Merge master.kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6
* master.kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6: (73 commits) [SCSI] aic79xx: Add ASC-29320LPE ids to driver [SCSI] stex: version update [SCSI] stex: change wait loop code [SCSI] stex: add new device type support [SCSI] stex: update device id info [SCSI] stex: adjust default queue length [SCSI] stex: add value check in hard reset routine [SCSI] stex: fix controller_info command handling [SCSI] stex: fix biosparam calculation [SCSI] megaraid: fix MMIO casts [SCSI] tgt: fix undefined flush_dcache_page() problem [SCSI] libsas: better error handling in sas_expander.c [SCSI] lpfc 8.1.11 : Change version number to 8.1.11 [SCSI] lpfc 8.1.11 : Misc Fixes [SCSI] lpfc 8.1.11 : Add soft_wwnn sysfs attribute, rename soft_wwn_enable [SCSI] lpfc 8.1.11 : Removed decoding of PCI Subsystem Id [SCSI] lpfc 8.1.11 : Add MSI (Message Signalled Interrupts) support [SCSI] lpfc 8.1.11 : Adjust LOG_FCP logging [SCSI] lpfc 8.1.11 : Fix Memory leaks [SCSI] lpfc 8.1.11 : Fix lpfc_multi_ring_support ...
Diffstat (limited to 'drivers/scsi/scsi_scan.c')
-rw-r--r--drivers/scsi/scsi_scan.c225
1 files changed, 219 insertions, 6 deletions
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index 94a274645f6f..4d656148bd67 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -29,7 +29,9 @@
29#include <linux/moduleparam.h> 29#include <linux/moduleparam.h>
30#include <linux/init.h> 30#include <linux/init.h>
31#include <linux/blkdev.h> 31#include <linux/blkdev.h>
32#include <asm/semaphore.h> 32#include <linux/delay.h>
33#include <linux/kthread.h>
34#include <linux/spinlock.h>
33 35
34#include <scsi/scsi.h> 36#include <scsi/scsi.h>
35#include <scsi/scsi_cmnd.h> 37#include <scsi/scsi_cmnd.h>
@@ -87,6 +89,17 @@ module_param_named(max_luns, max_scsi_luns, int, S_IRUGO|S_IWUSR);
87MODULE_PARM_DESC(max_luns, 89MODULE_PARM_DESC(max_luns,
88 "last scsi LUN (should be between 1 and 2^32-1)"); 90 "last scsi LUN (should be between 1 and 2^32-1)");
89 91
92#ifdef CONFIG_SCSI_SCAN_ASYNC
93#define SCSI_SCAN_TYPE_DEFAULT "async"
94#else
95#define SCSI_SCAN_TYPE_DEFAULT "sync"
96#endif
97
98static char scsi_scan_type[6] = SCSI_SCAN_TYPE_DEFAULT;
99
100module_param_string(scan, scsi_scan_type, sizeof(scsi_scan_type), S_IRUGO);
101MODULE_PARM_DESC(scan, "sync, async or none");
102
90/* 103/*
91 * max_scsi_report_luns: the maximum number of LUNS that will be 104 * max_scsi_report_luns: the maximum number of LUNS that will be
92 * returned from the REPORT LUNS command. 8 times this value must 105 * returned from the REPORT LUNS command. 8 times this value must
@@ -108,6 +121,68 @@ MODULE_PARM_DESC(inq_timeout,
108 "Timeout (in seconds) waiting for devices to answer INQUIRY." 121 "Timeout (in seconds) waiting for devices to answer INQUIRY."
109 " Default is 5. Some non-compliant devices need more."); 122 " Default is 5. Some non-compliant devices need more.");
110 123
124static DEFINE_SPINLOCK(async_scan_lock);
125static LIST_HEAD(scanning_hosts);
126
127struct async_scan_data {
128 struct list_head list;
129 struct Scsi_Host *shost;
130 struct completion prev_finished;
131};
132
133/**
134 * scsi_complete_async_scans - Wait for asynchronous scans to complete
135 *
136 * Asynchronous scans add themselves to the scanning_hosts list. Once
137 * that list is empty, we know that the scans are complete. Rather than
138 * waking up periodically to check the state of the list, we pretend to be
139 * a scanning task by adding ourselves at the end of the list and going to
140 * sleep. When the task before us wakes us up, we take ourselves off the
141 * list and return.
142 */
143int scsi_complete_async_scans(void)
144{
145 struct async_scan_data *data;
146
147 do {
148 if (list_empty(&scanning_hosts))
149 return 0;
150 /* If we can't get memory immediately, that's OK. Just
151 * sleep a little. Even if we never get memory, the async
152 * scans will finish eventually.
153 */
154 data = kmalloc(sizeof(*data), GFP_KERNEL);
155 if (!data)
156 msleep(1);
157 } while (!data);
158
159 data->shost = NULL;
160 init_completion(&data->prev_finished);
161
162 spin_lock(&async_scan_lock);
163 /* Check that there's still somebody else on the list */
164 if (list_empty(&scanning_hosts))
165 goto done;
166 list_add_tail(&data->list, &scanning_hosts);
167 spin_unlock(&async_scan_lock);
168
169 printk(KERN_INFO "scsi: waiting for bus probes to complete ...\n");
170 wait_for_completion(&data->prev_finished);
171
172 spin_lock(&async_scan_lock);
173 list_del(&data->list);
174 done:
175 spin_unlock(&async_scan_lock);
176
177 kfree(data);
178 return 0;
179}
180
181#ifdef MODULE
182/* Only exported for the benefit of scsi_wait_scan */
183EXPORT_SYMBOL_GPL(scsi_complete_async_scans);
184#endif
185
111/** 186/**
112 * scsi_unlock_floptical - unlock device via a special MODE SENSE command 187 * scsi_unlock_floptical - unlock device via a special MODE SENSE command
113 * @sdev: scsi device to send command to 188 * @sdev: scsi device to send command to
@@ -619,7 +694,7 @@ static int scsi_probe_lun(struct scsi_device *sdev, unsigned char *inq_result,
619 * SCSI_SCAN_LUN_PRESENT: a new scsi_device was allocated and initialized 694 * SCSI_SCAN_LUN_PRESENT: a new scsi_device was allocated and initialized
620 **/ 695 **/
621static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result, 696static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result,
622 int *bflags) 697 int *bflags, int async)
623{ 698{
624 /* 699 /*
625 * XXX do not save the inquiry, since it can change underneath us, 700 * XXX do not save the inquiry, since it can change underneath us,
@@ -805,7 +880,7 @@ static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result,
805 * register it and tell the rest of the kernel 880 * register it and tell the rest of the kernel
806 * about it. 881 * about it.
807 */ 882 */
808 if (scsi_sysfs_add_sdev(sdev) != 0) 883 if (!async && scsi_sysfs_add_sdev(sdev) != 0)
809 return SCSI_SCAN_NO_RESPONSE; 884 return SCSI_SCAN_NO_RESPONSE;
810 885
811 return SCSI_SCAN_LUN_PRESENT; 886 return SCSI_SCAN_LUN_PRESENT;
@@ -974,7 +1049,7 @@ static int scsi_probe_and_add_lun(struct scsi_target *starget,
974 goto out_free_result; 1049 goto out_free_result;
975 } 1050 }
976 1051
977 res = scsi_add_lun(sdev, result, &bflags); 1052 res = scsi_add_lun(sdev, result, &bflags, shost->async_scan);
978 if (res == SCSI_SCAN_LUN_PRESENT) { 1053 if (res == SCSI_SCAN_LUN_PRESENT) {
979 if (bflags & BLIST_KEY) { 1054 if (bflags & BLIST_KEY) {
980 sdev->lockable = 0; 1055 sdev->lockable = 0;
@@ -1474,6 +1549,12 @@ void scsi_scan_target(struct device *parent, unsigned int channel,
1474{ 1549{
1475 struct Scsi_Host *shost = dev_to_shost(parent); 1550 struct Scsi_Host *shost = dev_to_shost(parent);
1476 1551
1552 if (strncmp(scsi_scan_type, "none", 4) == 0)
1553 return;
1554
1555 if (!shost->async_scan)
1556 scsi_complete_async_scans();
1557
1477 mutex_lock(&shost->scan_mutex); 1558 mutex_lock(&shost->scan_mutex);
1478 if (scsi_host_scan_allowed(shost)) 1559 if (scsi_host_scan_allowed(shost))
1479 __scsi_scan_target(parent, channel, id, lun, rescan); 1560 __scsi_scan_target(parent, channel, id, lun, rescan);
@@ -1519,6 +1600,9 @@ int scsi_scan_host_selected(struct Scsi_Host *shost, unsigned int channel,
1519 "%s: <%u:%u:%u>\n", 1600 "%s: <%u:%u:%u>\n",
1520 __FUNCTION__, channel, id, lun)); 1601 __FUNCTION__, channel, id, lun));
1521 1602
1603 if (!shost->async_scan)
1604 scsi_complete_async_scans();
1605
1522 if (((channel != SCAN_WILD_CARD) && (channel > shost->max_channel)) || 1606 if (((channel != SCAN_WILD_CARD) && (channel > shost->max_channel)) ||
1523 ((id != SCAN_WILD_CARD) && (id >= shost->max_id)) || 1607 ((id != SCAN_WILD_CARD) && (id >= shost->max_id)) ||
1524 ((lun != SCAN_WILD_CARD) && (lun > shost->max_lun))) 1608 ((lun != SCAN_WILD_CARD) && (lun > shost->max_lun)))
@@ -1539,14 +1623,143 @@ int scsi_scan_host_selected(struct Scsi_Host *shost, unsigned int channel,
1539 return 0; 1623 return 0;
1540} 1624}
1541 1625
1626static void scsi_sysfs_add_devices(struct Scsi_Host *shost)
1627{
1628 struct scsi_device *sdev;
1629 shost_for_each_device(sdev, shost) {
1630 if (scsi_sysfs_add_sdev(sdev) != 0)
1631 scsi_destroy_sdev(sdev);
1632 }
1633}
1634
1635/**
1636 * scsi_prep_async_scan - prepare for an async scan
1637 * @shost: the host which will be scanned
1638 * Returns: a cookie to be passed to scsi_finish_async_scan()
1639 *
1640 * Tells the midlayer this host is going to do an asynchronous scan.
1641 * It reserves the host's position in the scanning list and ensures
1642 * that other asynchronous scans started after this one won't affect the
1643 * ordering of the discovered devices.
1644 */
1645static struct async_scan_data *scsi_prep_async_scan(struct Scsi_Host *shost)
1646{
1647 struct async_scan_data *data;
1648
1649 if (strncmp(scsi_scan_type, "sync", 4) == 0)
1650 return NULL;
1651
1652 if (shost->async_scan) {
1653 printk("%s called twice for host %d", __FUNCTION__,
1654 shost->host_no);
1655 dump_stack();
1656 return NULL;
1657 }
1658
1659 data = kmalloc(sizeof(*data), GFP_KERNEL);
1660 if (!data)
1661 goto err;
1662 data->shost = scsi_host_get(shost);
1663 if (!data->shost)
1664 goto err;
1665 init_completion(&data->prev_finished);
1666
1667 spin_lock(&async_scan_lock);
1668 shost->async_scan = 1;
1669 if (list_empty(&scanning_hosts))
1670 complete(&data->prev_finished);
1671 list_add_tail(&data->list, &scanning_hosts);
1672 spin_unlock(&async_scan_lock);
1673
1674 return data;
1675
1676 err:
1677 kfree(data);
1678 return NULL;
1679}
1680
1681/**
1682 * scsi_finish_async_scan - asynchronous scan has finished
1683 * @data: cookie returned from earlier call to scsi_prep_async_scan()
1684 *
1685 * All the devices currently attached to this host have been found.
1686 * This function announces all the devices it has found to the rest
1687 * of the system.
1688 */
1689static void scsi_finish_async_scan(struct async_scan_data *data)
1690{
1691 struct Scsi_Host *shost;
1692
1693 if (!data)
1694 return;
1695
1696 shost = data->shost;
1697 if (!shost->async_scan) {
1698 printk("%s called twice for host %d", __FUNCTION__,
1699 shost->host_no);
1700 dump_stack();
1701 return;
1702 }
1703
1704 wait_for_completion(&data->prev_finished);
1705
1706 scsi_sysfs_add_devices(shost);
1707
1708 spin_lock(&async_scan_lock);
1709 shost->async_scan = 0;
1710 list_del(&data->list);
1711 if (!list_empty(&scanning_hosts)) {
1712 struct async_scan_data *next = list_entry(scanning_hosts.next,
1713 struct async_scan_data, list);
1714 complete(&next->prev_finished);
1715 }
1716 spin_unlock(&async_scan_lock);
1717
1718 scsi_host_put(shost);
1719 kfree(data);
1720}
1721
1722static void do_scsi_scan_host(struct Scsi_Host *shost)
1723{
1724 if (shost->hostt->scan_finished) {
1725 unsigned long start = jiffies;
1726 if (shost->hostt->scan_start)
1727 shost->hostt->scan_start(shost);
1728
1729 while (!shost->hostt->scan_finished(shost, jiffies - start))
1730 msleep(10);
1731 } else {
1732 scsi_scan_host_selected(shost, SCAN_WILD_CARD, SCAN_WILD_CARD,
1733 SCAN_WILD_CARD, 0);
1734 }
1735}
1736
1737static int do_scan_async(void *_data)
1738{
1739 struct async_scan_data *data = _data;
1740 do_scsi_scan_host(data->shost);
1741 scsi_finish_async_scan(data);
1742 return 0;
1743}
1744
1542/** 1745/**
1543 * scsi_scan_host - scan the given adapter 1746 * scsi_scan_host - scan the given adapter
1544 * @shost: adapter to scan 1747 * @shost: adapter to scan
1545 **/ 1748 **/
1546void scsi_scan_host(struct Scsi_Host *shost) 1749void scsi_scan_host(struct Scsi_Host *shost)
1547{ 1750{
1548 scsi_scan_host_selected(shost, SCAN_WILD_CARD, SCAN_WILD_CARD, 1751 struct async_scan_data *data;
1549 SCAN_WILD_CARD, 0); 1752
1753 if (strncmp(scsi_scan_type, "none", 4) == 0)
1754 return;
1755
1756 data = scsi_prep_async_scan(shost);
1757 if (!data) {
1758 do_scsi_scan_host(shost);
1759 return;
1760 }
1761
1762 kthread_run(do_scan_async, data, "scsi_scan_%d", shost->host_no);
1550} 1763}
1551EXPORT_SYMBOL(scsi_scan_host); 1764EXPORT_SYMBOL(scsi_scan_host);
1552 1765