aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/scsi_scan.c
diff options
context:
space:
mode:
authorJeff Garzik <jeff@garzik.org>2006-12-07 04:57:19 -0500
committerJeff Garzik <jeff@garzik.org>2006-12-07 04:57:19 -0500
commit8d1413b28033c49c7f1a4d320e815d7a5531acee (patch)
treeb37281abef014cd60803b81c100388d7a475d49e /drivers/scsi/scsi_scan.c
parented25ffa16434724f5ed825aa48734c7f3aefa203 (diff)
parent620034c84d1d939717bdfbe02c51a3fee43541c3 (diff)
Merge branch 'master' into upstream
Conflicts: drivers/net/netxen/netxen_nic.h drivers/net/netxen/netxen_nic_main.c
Diffstat (limited to 'drivers/scsi/scsi_scan.c')
-rw-r--r--drivers/scsi/scsi_scan.c232
1 files changed, 223 insertions, 9 deletions
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index 94a274645f6f..14e635aa44ce 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
@@ -362,9 +437,10 @@ static struct scsi_target *scsi_alloc_target(struct device *parent,
362 goto retry; 437 goto retry;
363} 438}
364 439
365static void scsi_target_reap_usercontext(void *data) 440static void scsi_target_reap_usercontext(struct work_struct *work)
366{ 441{
367 struct scsi_target *starget = data; 442 struct scsi_target *starget =
443 container_of(work, struct scsi_target, ew.work);
368 struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); 444 struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
369 unsigned long flags; 445 unsigned long flags;
370 446
@@ -400,7 +476,7 @@ void scsi_target_reap(struct scsi_target *starget)
400 starget->state = STARGET_DEL; 476 starget->state = STARGET_DEL;
401 spin_unlock_irqrestore(shost->host_lock, flags); 477 spin_unlock_irqrestore(shost->host_lock, flags);
402 execute_in_process_context(scsi_target_reap_usercontext, 478 execute_in_process_context(scsi_target_reap_usercontext,
403 starget, &starget->ew); 479 &starget->ew);
404 return; 480 return;
405 481
406 } 482 }
@@ -619,7 +695,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 695 * SCSI_SCAN_LUN_PRESENT: a new scsi_device was allocated and initialized
620 **/ 696 **/
621static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result, 697static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result,
622 int *bflags) 698 int *bflags, int async)
623{ 699{
624 /* 700 /*
625 * XXX do not save the inquiry, since it can change underneath us, 701 * XXX do not save the inquiry, since it can change underneath us,
@@ -805,7 +881,7 @@ static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result,
805 * register it and tell the rest of the kernel 881 * register it and tell the rest of the kernel
806 * about it. 882 * about it.
807 */ 883 */
808 if (scsi_sysfs_add_sdev(sdev) != 0) 884 if (!async && scsi_sysfs_add_sdev(sdev) != 0)
809 return SCSI_SCAN_NO_RESPONSE; 885 return SCSI_SCAN_NO_RESPONSE;
810 886
811 return SCSI_SCAN_LUN_PRESENT; 887 return SCSI_SCAN_LUN_PRESENT;
@@ -974,7 +1050,7 @@ static int scsi_probe_and_add_lun(struct scsi_target *starget,
974 goto out_free_result; 1050 goto out_free_result;
975 } 1051 }
976 1052
977 res = scsi_add_lun(sdev, result, &bflags); 1053 res = scsi_add_lun(sdev, result, &bflags, shost->async_scan);
978 if (res == SCSI_SCAN_LUN_PRESENT) { 1054 if (res == SCSI_SCAN_LUN_PRESENT) {
979 if (bflags & BLIST_KEY) { 1055 if (bflags & BLIST_KEY) {
980 sdev->lockable = 0; 1056 sdev->lockable = 0;
@@ -1474,6 +1550,12 @@ void scsi_scan_target(struct device *parent, unsigned int channel,
1474{ 1550{
1475 struct Scsi_Host *shost = dev_to_shost(parent); 1551 struct Scsi_Host *shost = dev_to_shost(parent);
1476 1552
1553 if (strncmp(scsi_scan_type, "none", 4) == 0)
1554 return;
1555
1556 if (!shost->async_scan)
1557 scsi_complete_async_scans();
1558
1477 mutex_lock(&shost->scan_mutex); 1559 mutex_lock(&shost->scan_mutex);
1478 if (scsi_host_scan_allowed(shost)) 1560 if (scsi_host_scan_allowed(shost))
1479 __scsi_scan_target(parent, channel, id, lun, rescan); 1561 __scsi_scan_target(parent, channel, id, lun, rescan);
@@ -1519,6 +1601,9 @@ int scsi_scan_host_selected(struct Scsi_Host *shost, unsigned int channel,
1519 "%s: <%u:%u:%u>\n", 1601 "%s: <%u:%u:%u>\n",
1520 __FUNCTION__, channel, id, lun)); 1602 __FUNCTION__, channel, id, lun));
1521 1603
1604 if (!shost->async_scan)
1605 scsi_complete_async_scans();
1606
1522 if (((channel != SCAN_WILD_CARD) && (channel > shost->max_channel)) || 1607 if (((channel != SCAN_WILD_CARD) && (channel > shost->max_channel)) ||
1523 ((id != SCAN_WILD_CARD) && (id >= shost->max_id)) || 1608 ((id != SCAN_WILD_CARD) && (id >= shost->max_id)) ||
1524 ((lun != SCAN_WILD_CARD) && (lun > shost->max_lun))) 1609 ((lun != SCAN_WILD_CARD) && (lun > shost->max_lun)))
@@ -1539,14 +1624,143 @@ int scsi_scan_host_selected(struct Scsi_Host *shost, unsigned int channel,
1539 return 0; 1624 return 0;
1540} 1625}
1541 1626
1627static void scsi_sysfs_add_devices(struct Scsi_Host *shost)
1628{
1629 struct scsi_device *sdev;
1630 shost_for_each_device(sdev, shost) {
1631 if (scsi_sysfs_add_sdev(sdev) != 0)
1632 scsi_destroy_sdev(sdev);
1633 }
1634}
1635
1636/**
1637 * scsi_prep_async_scan - prepare for an async scan
1638 * @shost: the host which will be scanned
1639 * Returns: a cookie to be passed to scsi_finish_async_scan()
1640 *
1641 * Tells the midlayer this host is going to do an asynchronous scan.
1642 * It reserves the host's position in the scanning list and ensures
1643 * that other asynchronous scans started after this one won't affect the
1644 * ordering of the discovered devices.
1645 */
1646static struct async_scan_data *scsi_prep_async_scan(struct Scsi_Host *shost)
1647{
1648 struct async_scan_data *data;
1649
1650 if (strncmp(scsi_scan_type, "sync", 4) == 0)
1651 return NULL;
1652
1653 if (shost->async_scan) {
1654 printk("%s called twice for host %d", __FUNCTION__,
1655 shost->host_no);
1656 dump_stack();
1657 return NULL;
1658 }
1659
1660 data = kmalloc(sizeof(*data), GFP_KERNEL);
1661 if (!data)
1662 goto err;
1663 data->shost = scsi_host_get(shost);
1664 if (!data->shost)
1665 goto err;
1666 init_completion(&data->prev_finished);
1667
1668 spin_lock(&async_scan_lock);
1669 shost->async_scan = 1;
1670 if (list_empty(&scanning_hosts))
1671 complete(&data->prev_finished);
1672 list_add_tail(&data->list, &scanning_hosts);
1673 spin_unlock(&async_scan_lock);
1674
1675 return data;
1676
1677 err:
1678 kfree(data);
1679 return NULL;
1680}
1681
1682/**
1683 * scsi_finish_async_scan - asynchronous scan has finished
1684 * @data: cookie returned from earlier call to scsi_prep_async_scan()
1685 *
1686 * All the devices currently attached to this host have been found.
1687 * This function announces all the devices it has found to the rest
1688 * of the system.
1689 */
1690static void scsi_finish_async_scan(struct async_scan_data *data)
1691{
1692 struct Scsi_Host *shost;
1693
1694 if (!data)
1695 return;
1696
1697 shost = data->shost;
1698 if (!shost->async_scan) {
1699 printk("%s called twice for host %d", __FUNCTION__,
1700 shost->host_no);
1701 dump_stack();
1702 return;
1703 }
1704
1705 wait_for_completion(&data->prev_finished);
1706
1707 scsi_sysfs_add_devices(shost);
1708
1709 spin_lock(&async_scan_lock);
1710 shost->async_scan = 0;
1711 list_del(&data->list);
1712 if (!list_empty(&scanning_hosts)) {
1713 struct async_scan_data *next = list_entry(scanning_hosts.next,
1714 struct async_scan_data, list);
1715 complete(&next->prev_finished);
1716 }
1717 spin_unlock(&async_scan_lock);
1718
1719 scsi_host_put(shost);
1720 kfree(data);
1721}
1722
1723static void do_scsi_scan_host(struct Scsi_Host *shost)
1724{
1725 if (shost->hostt->scan_finished) {
1726 unsigned long start = jiffies;
1727 if (shost->hostt->scan_start)
1728 shost->hostt->scan_start(shost);
1729
1730 while (!shost->hostt->scan_finished(shost, jiffies - start))
1731 msleep(10);
1732 } else {
1733 scsi_scan_host_selected(shost, SCAN_WILD_CARD, SCAN_WILD_CARD,
1734 SCAN_WILD_CARD, 0);
1735 }
1736}
1737
1738static int do_scan_async(void *_data)
1739{
1740 struct async_scan_data *data = _data;
1741 do_scsi_scan_host(data->shost);
1742 scsi_finish_async_scan(data);
1743 return 0;
1744}
1745
1542/** 1746/**
1543 * scsi_scan_host - scan the given adapter 1747 * scsi_scan_host - scan the given adapter
1544 * @shost: adapter to scan 1748 * @shost: adapter to scan
1545 **/ 1749 **/
1546void scsi_scan_host(struct Scsi_Host *shost) 1750void scsi_scan_host(struct Scsi_Host *shost)
1547{ 1751{
1548 scsi_scan_host_selected(shost, SCAN_WILD_CARD, SCAN_WILD_CARD, 1752 struct async_scan_data *data;
1549 SCAN_WILD_CARD, 0); 1753
1754 if (strncmp(scsi_scan_type, "none", 4) == 0)
1755 return;
1756
1757 data = scsi_prep_async_scan(shost);
1758 if (!data) {
1759 do_scsi_scan_host(shost);
1760 return;
1761 }
1762
1763 kthread_run(do_scan_async, data, "scsi_scan_%d", shost->host_no);
1550} 1764}
1551EXPORT_SYMBOL(scsi_scan_host); 1765EXPORT_SYMBOL(scsi_scan_host);
1552 1766