aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/Makefile2
-rw-r--r--drivers/scsi/scsi_priv.h3
-rw-r--r--drivers/scsi/scsi_scan.c203
-rw-r--r--drivers/scsi/scsi_wait_scan.c31
4 files changed, 233 insertions, 6 deletions
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
index bcca39c3bcbf..a0a77fde3708 100644
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -141,6 +141,8 @@ obj-$(CONFIG_CHR_DEV_SCH) += ch.o
141# This goes last, so that "real" scsi devices probe earlier 141# This goes last, so that "real" scsi devices probe earlier
142obj-$(CONFIG_SCSI_DEBUG) += scsi_debug.o 142obj-$(CONFIG_SCSI_DEBUG) += scsi_debug.o
143 143
144obj-$(CONFIG_SCSI) += scsi_wait_scan.o
145
144scsi_mod-y += scsi.o hosts.o scsi_ioctl.o constants.o \ 146scsi_mod-y += scsi.o hosts.o scsi_ioctl.o constants.o \
145 scsicam.o scsi_error.o scsi_lib.o \ 147 scsicam.o scsi_error.o scsi_lib.o \
146 scsi_scan.o scsi_sysfs.o \ 148 scsi_scan.o scsi_sysfs.o \
diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h
index 5d023d44e5e7..f458c2f686d2 100644
--- a/drivers/scsi/scsi_priv.h
+++ b/drivers/scsi/scsi_priv.h
@@ -39,6 +39,9 @@ static inline void scsi_log_completion(struct scsi_cmnd *cmd, int disposition)
39 { }; 39 { };
40#endif 40#endif
41 41
42/* scsi_scan.c */
43int scsi_complete_async_scans(void);
44
42/* scsi_devinfo.c */ 45/* scsi_devinfo.c */
43extern int scsi_get_device_flags(struct scsi_device *sdev, 46extern int scsi_get_device_flags(struct scsi_device *sdev,
44 const unsigned char *vendor, 47 const unsigned char *vendor,
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index fd9e281c3bfe..148e24cc3222 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,11 @@ 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
92static char scsi_scan_type[6] = "sync";
93
94module_param_string(scan, scsi_scan_type, sizeof(scsi_scan_type), S_IRUGO);
95MODULE_PARM_DESC(scan, "sync, async or none");
96
90/* 97/*
91 * max_scsi_report_luns: the maximum number of LUNS that will be 98 * max_scsi_report_luns: the maximum number of LUNS that will be
92 * returned from the REPORT LUNS command. 8 times this value must 99 * returned from the REPORT LUNS command. 8 times this value must
@@ -108,6 +115,68 @@ MODULE_PARM_DESC(inq_timeout,
108 "Timeout (in seconds) waiting for devices to answer INQUIRY." 115 "Timeout (in seconds) waiting for devices to answer INQUIRY."
109 " Default is 5. Some non-compliant devices need more."); 116 " Default is 5. Some non-compliant devices need more.");
110 117
118static DEFINE_SPINLOCK(async_scan_lock);
119static LIST_HEAD(scanning_hosts);
120
121struct async_scan_data {
122 struct list_head list;
123 struct Scsi_Host *shost;
124 struct completion prev_finished;
125};
126
127/**
128 * scsi_complete_async_scans - Wait for asynchronous scans to complete
129 *
130 * Asynchronous scans add themselves to the scanning_hosts list. Once
131 * that list is empty, we know that the scans are complete. Rather than
132 * waking up periodically to check the state of the list, we pretend to be
133 * a scanning task by adding ourselves at the end of the list and going to
134 * sleep. When the task before us wakes us up, we take ourselves off the
135 * list and return.
136 */
137int scsi_complete_async_scans(void)
138{
139 struct async_scan_data *data;
140
141 do {
142 if (list_empty(&scanning_hosts))
143 return 0;
144 /* If we can't get memory immediately, that's OK. Just
145 * sleep a little. Even if we never get memory, the async
146 * scans will finish eventually.
147 */
148 data = kmalloc(sizeof(*data), GFP_KERNEL);
149 if (!data)
150 msleep(1);
151 } while (!data);
152
153 data->shost = NULL;
154 init_completion(&data->prev_finished);
155
156 spin_lock(&async_scan_lock);
157 /* Check that there's still somebody else on the list */
158 if (list_empty(&scanning_hosts))
159 goto done;
160 list_add_tail(&data->list, &scanning_hosts);
161 spin_unlock(&async_scan_lock);
162
163 printk(KERN_INFO "scsi: waiting for bus probes to complete ...\n");
164 wait_for_completion(&data->prev_finished);
165
166 spin_lock(&async_scan_lock);
167 list_del(&data->list);
168 done:
169 spin_unlock(&async_scan_lock);
170
171 kfree(data);
172 return 0;
173}
174
175#ifdef MODULE
176/* Only exported for the benefit of scsi_wait_scan */
177EXPORT_SYMBOL_GPL(scsi_complete_async_scans);
178#endif
179
111/** 180/**
112 * scsi_unlock_floptical - unlock device via a special MODE SENSE command 181 * scsi_unlock_floptical - unlock device via a special MODE SENSE command
113 * @sdev: scsi device to send command to 182 * @sdev: scsi device to send command to
@@ -619,7 +688,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 688 * SCSI_SCAN_LUN_PRESENT: a new scsi_device was allocated and initialized
620 **/ 689 **/
621static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result, 690static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result,
622 int *bflags) 691 int *bflags, int async)
623{ 692{
624 /* 693 /*
625 * XXX do not save the inquiry, since it can change underneath us, 694 * XXX do not save the inquiry, since it can change underneath us,
@@ -795,7 +864,7 @@ static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result,
795 * register it and tell the rest of the kernel 864 * register it and tell the rest of the kernel
796 * about it. 865 * about it.
797 */ 866 */
798 if (scsi_sysfs_add_sdev(sdev) != 0) 867 if (!async && scsi_sysfs_add_sdev(sdev) != 0)
799 return SCSI_SCAN_NO_RESPONSE; 868 return SCSI_SCAN_NO_RESPONSE;
800 869
801 return SCSI_SCAN_LUN_PRESENT; 870 return SCSI_SCAN_LUN_PRESENT;
@@ -964,7 +1033,7 @@ static int scsi_probe_and_add_lun(struct scsi_target *starget,
964 goto out_free_result; 1033 goto out_free_result;
965 } 1034 }
966 1035
967 res = scsi_add_lun(sdev, result, &bflags); 1036 res = scsi_add_lun(sdev, result, &bflags, shost->async_scan);
968 if (res == SCSI_SCAN_LUN_PRESENT) { 1037 if (res == SCSI_SCAN_LUN_PRESENT) {
969 if (bflags & BLIST_KEY) { 1038 if (bflags & BLIST_KEY) {
970 sdev->lockable = 0; 1039 sdev->lockable = 0;
@@ -1464,6 +1533,9 @@ void scsi_scan_target(struct device *parent, unsigned int channel,
1464{ 1533{
1465 struct Scsi_Host *shost = dev_to_shost(parent); 1534 struct Scsi_Host *shost = dev_to_shost(parent);
1466 1535
1536 if (!shost->async_scan)
1537 scsi_complete_async_scans();
1538
1467 mutex_lock(&shost->scan_mutex); 1539 mutex_lock(&shost->scan_mutex);
1468 if (scsi_host_scan_allowed(shost)) 1540 if (scsi_host_scan_allowed(shost))
1469 __scsi_scan_target(parent, channel, id, lun, rescan); 1541 __scsi_scan_target(parent, channel, id, lun, rescan);
@@ -1509,6 +1581,9 @@ int scsi_scan_host_selected(struct Scsi_Host *shost, unsigned int channel,
1509 "%s: <%u:%u:%u>\n", 1581 "%s: <%u:%u:%u>\n",
1510 __FUNCTION__, channel, id, lun)); 1582 __FUNCTION__, channel, id, lun));
1511 1583
1584 if (!shost->async_scan)
1585 scsi_complete_async_scans();
1586
1512 if (((channel != SCAN_WILD_CARD) && (channel > shost->max_channel)) || 1587 if (((channel != SCAN_WILD_CARD) && (channel > shost->max_channel)) ||
1513 ((id != SCAN_WILD_CARD) && (id >= shost->max_id)) || 1588 ((id != SCAN_WILD_CARD) && (id >= shost->max_id)) ||
1514 ((lun != SCAN_WILD_CARD) && (lun > shost->max_lun))) 1589 ((lun != SCAN_WILD_CARD) && (lun > shost->max_lun)))
@@ -1529,14 +1604,130 @@ int scsi_scan_host_selected(struct Scsi_Host *shost, unsigned int channel,
1529 return 0; 1604 return 0;
1530} 1605}
1531 1606
1607static void scsi_sysfs_add_devices(struct Scsi_Host *shost)
1608{
1609 struct scsi_device *sdev;
1610 shost_for_each_device(sdev, shost) {
1611 if (scsi_sysfs_add_sdev(sdev) != 0)
1612 scsi_destroy_sdev(sdev);
1613 }
1614}
1615
1616/**
1617 * scsi_prep_async_scan - prepare for an async scan
1618 * @shost: the host which will be scanned
1619 * Returns: a cookie to be passed to scsi_finish_async_scan()
1620 *
1621 * Tells the midlayer this host is going to do an asynchronous scan.
1622 * It reserves the host's position in the scanning list and ensures
1623 * that other asynchronous scans started after this one won't affect the
1624 * ordering of the discovered devices.
1625 */
1626struct async_scan_data *scsi_prep_async_scan(struct Scsi_Host *shost)
1627{
1628 struct async_scan_data *data;
1629
1630 if (strncmp(scsi_scan_type, "sync", 4) == 0)
1631 return NULL;
1632
1633 if (shost->async_scan) {
1634 printk("%s called twice for host %d", __FUNCTION__,
1635 shost->host_no);
1636 dump_stack();
1637 return NULL;
1638 }
1639
1640 data = kmalloc(sizeof(*data), GFP_KERNEL);
1641 if (!data)
1642 goto err;
1643 data->shost = scsi_host_get(shost);
1644 if (!data->shost)
1645 goto err;
1646 init_completion(&data->prev_finished);
1647
1648 spin_lock(&async_scan_lock);
1649 shost->async_scan = 1;
1650 if (list_empty(&scanning_hosts))
1651 complete(&data->prev_finished);
1652 list_add_tail(&data->list, &scanning_hosts);
1653 spin_unlock(&async_scan_lock);
1654
1655 return data;
1656
1657 err:
1658 kfree(data);
1659 return NULL;
1660}
1661
1662/**
1663 * scsi_finish_async_scan - asynchronous scan has finished
1664 * @data: cookie returned from earlier call to scsi_prep_async_scan()
1665 *
1666 * All the devices currently attached to this host have been found.
1667 * This function announces all the devices it has found to the rest
1668 * of the system.
1669 */
1670void scsi_finish_async_scan(struct async_scan_data *data)
1671{
1672 struct Scsi_Host *shost;
1673
1674 if (!data)
1675 return;
1676
1677 shost = data->shost;
1678 if (!shost->async_scan) {
1679 printk("%s called twice for host %d", __FUNCTION__,
1680 shost->host_no);
1681 dump_stack();
1682 return;
1683 }
1684
1685 wait_for_completion(&data->prev_finished);
1686
1687 scsi_sysfs_add_devices(shost);
1688
1689 spin_lock(&async_scan_lock);
1690 shost->async_scan = 0;
1691 list_del(&data->list);
1692 if (!list_empty(&scanning_hosts)) {
1693 struct async_scan_data *next = list_entry(scanning_hosts.next,
1694 struct async_scan_data, list);
1695 complete(&next->prev_finished);
1696 }
1697 spin_unlock(&async_scan_lock);
1698
1699 scsi_host_put(shost);
1700 kfree(data);
1701}
1702
1703static int do_scan_async(void *_data)
1704{
1705 struct async_scan_data *data = _data;
1706 scsi_scan_host_selected(data->shost, SCAN_WILD_CARD, SCAN_WILD_CARD,
1707 SCAN_WILD_CARD, 0);
1708
1709 scsi_finish_async_scan(data);
1710 return 0;
1711}
1712
1532/** 1713/**
1533 * scsi_scan_host - scan the given adapter 1714 * scsi_scan_host - scan the given adapter
1534 * @shost: adapter to scan 1715 * @shost: adapter to scan
1535 **/ 1716 **/
1536void scsi_scan_host(struct Scsi_Host *shost) 1717void scsi_scan_host(struct Scsi_Host *shost)
1537{ 1718{
1538 scsi_scan_host_selected(shost, SCAN_WILD_CARD, SCAN_WILD_CARD, 1719 struct async_scan_data *data;
1539 SCAN_WILD_CARD, 0); 1720
1721 if (strncmp(scsi_scan_type, "none", 4) == 0)
1722 return;
1723
1724 data = scsi_prep_async_scan(shost);
1725 if (!data) {
1726 scsi_scan_host_selected(shost, SCAN_WILD_CARD, SCAN_WILD_CARD,
1727 SCAN_WILD_CARD, 0);
1728 return;
1729 }
1730 kthread_run(do_scan_async, data, "scsi_scan_%d", shost->host_no);
1540} 1731}
1541EXPORT_SYMBOL(scsi_scan_host); 1732EXPORT_SYMBOL(scsi_scan_host);
1542 1733
diff --git a/drivers/scsi/scsi_wait_scan.c b/drivers/scsi/scsi_wait_scan.c
new file mode 100644
index 000000000000..8a636103083d
--- /dev/null
+++ b/drivers/scsi/scsi_wait_scan.c
@@ -0,0 +1,31 @@
1/*
2 * scsi_wait_scan.c
3 *
4 * Copyright (C) 2006 James Bottomley <James.Bottomley@SteelEye.com>
5 *
6 * This is a simple module to wait until all the async scans are
7 * complete. The idea is to use it in initrd/initramfs scripts. You
8 * modprobe it after all the modprobes of the root SCSI drivers and it
9 * will wait until they have all finished scanning their busses before
10 * allowing the boot to proceed
11 */
12
13#include <linux/module.h>
14#include "scsi_priv.h"
15
16static int __init wait_scan_init(void)
17{
18 scsi_complete_async_scans();
19 return 0;
20}
21
22static void __exit wait_scan_exit(void)
23{
24}
25
26MODULE_DESCRIPTION("SCSI wait for scans");
27MODULE_AUTHOR("James Bottomley");
28MODULE_LICENSE("GPL");
29
30late_initcall(wait_scan_init);
31module_exit(wait_scan_exit);