diff options
-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 | */ |