diff options
author | Matthew Wilcox <matthew@wil.cx> | 2006-09-28 17:19:20 -0400 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.il.steeleye.com> | 2006-10-11 14:44:25 -0400 |
commit | 3e082a910d217b2e7b186077ebf5a1126a68c62f (patch) | |
tree | b4ef4152b8ad0198283e36c74c990f38d90d27b7 | |
parent | 53a5fbdc2dff55161a206ed1a1385a8fa8055c34 (diff) |
[SCSI] Add ability to scan scsi busses asynchronously
Since it often takes around 20-30 seconds to scan a scsi bus, it's
highly advantageous to do this in parallel with other things. The bulk
of this patch is ensuring that devices don't change numbering, and that
all devices are discovered prior to trying to start init. For those
who build SCSI as modules, there's a new scsi_wait_scan module that will
ensure all bus scans are finished.
This patch only handles drivers which call scsi_scan_host. Fibre Channel,
SAS, SATA, USB and Firewire all need additional work.
Signed-off-by: Matthew Wilcox <matthew@wil.cx>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
-rw-r--r-- | Documentation/kernel-parameters.txt | 5 | ||||
-rw-r--r-- | drivers/scsi/Makefile | 2 | ||||
-rw-r--r-- | drivers/scsi/scsi_priv.h | 3 | ||||
-rw-r--r-- | drivers/scsi/scsi_scan.c | 203 | ||||
-rw-r--r-- | drivers/scsi/scsi_wait_scan.c | 31 | ||||
-rw-r--r-- | include/scsi/scsi_device.h | 30 | ||||
-rw-r--r-- | include/scsi/scsi_host.h | 3 |
7 files changed, 256 insertions, 21 deletions
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index ff571f9298e0..5a92ac085969 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt | |||
@@ -1410,6 +1410,11 @@ and is between 256 and 4096 characters. It is defined in the file | |||
1410 | 1410 | ||
1411 | scsi_logging= [SCSI] | 1411 | scsi_logging= [SCSI] |
1412 | 1412 | ||
1413 | scsi_mod.scan= [SCSI] sync (default) scans SCSI busses as they are | ||
1414 | discovered. async scans them in kernel threads, | ||
1415 | allowing boot to proceed. none ignores them, expecting | ||
1416 | user space to do the scan. | ||
1417 | |||
1413 | selinux [SELINUX] Disable or enable SELinux at boot time. | 1418 | selinux [SELINUX] Disable or enable SELinux at boot time. |
1414 | Format: { "0" | "1" } | 1419 | Format: { "0" | "1" } |
1415 | See security/selinux/Kconfig help text. | 1420 | See security/selinux/Kconfig help text. |
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 |
142 | obj-$(CONFIG_SCSI_DEBUG) += scsi_debug.o | 142 | obj-$(CONFIG_SCSI_DEBUG) += scsi_debug.o |
143 | 143 | ||
144 | obj-$(CONFIG_SCSI) += scsi_wait_scan.o | ||
145 | |||
144 | scsi_mod-y += scsi.o hosts.o scsi_ioctl.o constants.o \ | 146 | scsi_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 */ | ||
43 | int scsi_complete_async_scans(void); | ||
44 | |||
42 | /* scsi_devinfo.c */ | 45 | /* scsi_devinfo.c */ |
43 | extern int scsi_get_device_flags(struct scsi_device *sdev, | 46 | extern 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); | |||
87 | MODULE_PARM_DESC(max_luns, | 89 | MODULE_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 | static char scsi_scan_type[6] = "sync"; | ||
93 | |||
94 | module_param_string(scan, scsi_scan_type, sizeof(scsi_scan_type), S_IRUGO); | ||
95 | MODULE_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 | ||
118 | static DEFINE_SPINLOCK(async_scan_lock); | ||
119 | static LIST_HEAD(scanning_hosts); | ||
120 | |||
121 | struct 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 | */ | ||
137 | int 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 */ | ||
177 | EXPORT_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 | **/ |
621 | static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result, | 690 | static 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 | ||
1607 | static 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 | */ | ||
1626 | struct 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 | */ | ||
1670 | void 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 | |||
1703 | static 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 | **/ |
1536 | void scsi_scan_host(struct Scsi_Host *shost) | 1717 | void 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 | } |
1541 | EXPORT_SYMBOL(scsi_scan_host); | 1732 | EXPORT_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 | |||
16 | static int __init wait_scan_init(void) | ||
17 | { | ||
18 | scsi_complete_async_scans(); | ||
19 | return 0; | ||
20 | } | ||
21 | |||
22 | static void __exit wait_scan_exit(void) | ||
23 | { | ||
24 | } | ||
25 | |||
26 | MODULE_DESCRIPTION("SCSI wait for scans"); | ||
27 | MODULE_AUTHOR("James Bottomley"); | ||
28 | MODULE_LICENSE("GPL"); | ||
29 | |||
30 | late_initcall(wait_scan_init); | ||
31 | module_exit(wait_scan_exit); | ||
diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h index b401c82036be..ebf31b16dc49 100644 --- a/include/scsi/scsi_device.h +++ b/include/scsi/scsi_device.h | |||
@@ -223,13 +223,13 @@ extern struct scsi_device *__scsi_iterate_devices(struct Scsi_Host *, | |||
223 | struct scsi_device *); | 223 | struct scsi_device *); |
224 | 224 | ||
225 | /** | 225 | /** |
226 | * shost_for_each_device - iterate over all devices of a host | 226 | * shost_for_each_device - iterate over all devices of a host |
227 | * @sdev: iterator | 227 | * @sdev: the &struct scsi_device to use as a cursor |
228 | * @host: host whiches devices we want to iterate over | 228 | * @shost: the &struct scsi_host to iterate over |
229 | * | 229 | * |
230 | * This traverses over each devices of @shost. The devices have | 230 | * Iterator that returns each device attached to @shost. This loop |
231 | * a reference that must be released by scsi_host_put when breaking | 231 | * takes a reference on each device and releases it at the end. If |
232 | * out of the loop. | 232 | * you break out of the loop, you must call scsi_device_put(sdev). |
233 | */ | 233 | */ |
234 | #define shost_for_each_device(sdev, shost) \ | 234 | #define shost_for_each_device(sdev, shost) \ |
235 | for ((sdev) = __scsi_iterate_devices((shost), NULL); \ | 235 | for ((sdev) = __scsi_iterate_devices((shost), NULL); \ |
@@ -237,17 +237,17 @@ extern struct scsi_device *__scsi_iterate_devices(struct Scsi_Host *, | |||
237 | (sdev) = __scsi_iterate_devices((shost), (sdev))) | 237 | (sdev) = __scsi_iterate_devices((shost), (sdev))) |
238 | 238 | ||
239 | /** | 239 | /** |
240 | * __shost_for_each_device - iterate over all devices of a host (UNLOCKED) | 240 | * __shost_for_each_device - iterate over all devices of a host (UNLOCKED) |
241 | * @sdev: iterator | 241 | * @sdev: the &struct scsi_device to use as a cursor |
242 | * @host: host whiches devices we want to iterate over | 242 | * @shost: the &struct scsi_host to iterate over |
243 | * | 243 | * |
244 | * This traverses over each devices of @shost. It does _not_ take a | 244 | * Iterator that returns each device attached to @shost. It does _not_ |
245 | * reference on the scsi_device, thus it the whole loop must be protected | 245 | * take a reference on the scsi_device, so the whole loop must be |
246 | * by shost->host_lock. | 246 | * protected by shost->host_lock. |
247 | * | 247 | * |
248 | * Note: The only reason why drivers would want to use this is because | 248 | * Note: The only reason to use this is because you need to access the |
249 | * they're need to access the device list in irq context. Otherwise you | 249 | * device list in interrupt context. Otherwise you really want to use |
250 | * really want to use shost_for_each_device instead. | 250 | * shost_for_each_device instead. |
251 | */ | 251 | */ |
252 | #define __shost_for_each_device(sdev, shost) \ | 252 | #define __shost_for_each_device(sdev, shost) \ |
253 | list_for_each_entry((sdev), &((shost)->__devices), siblings) | 253 | list_for_each_entry((sdev), &((shost)->__devices), siblings) |
diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h index 39c6f8cc20c3..ba5b3eb6b43f 100644 --- a/include/scsi/scsi_host.h +++ b/include/scsi/scsi_host.h | |||
@@ -552,6 +552,9 @@ struct Scsi_Host { | |||
552 | /* task mgmt function in progress */ | 552 | /* task mgmt function in progress */ |
553 | unsigned tmf_in_progress:1; | 553 | unsigned tmf_in_progress:1; |
554 | 554 | ||
555 | /* Asynchronous scan in progress */ | ||
556 | unsigned async_scan:1; | ||
557 | |||
555 | /* | 558 | /* |
556 | * Optional work queue to be utilized by the transport | 559 | * Optional work queue to be utilized by the transport |
557 | */ | 560 | */ |