From: Matthew Wilcox Date: Wed, 22 Nov 2006 20:24:54 +0000 (-0700) Subject: [SCSI] Make scsi_scan_host work for drivers which find their own targets X-Git-Tag: v2.6.20-rc1~34^2~20^2~41^2~32 X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1aa8fab2acf1cb8b341131b726773fcff0abc707;p=linux-2.6 [SCSI] Make scsi_scan_host work for drivers which find their own targets If a driver can find its own targets, it can now fill in scan_finished and (optionally) scan_start in the scsi_host_template. Then, when it calls scsi_scan_host(), it will be called back (from a thread if asynchronous discovery is enabled), first to start the scan, and then at intervals to check if the scan is completed. Also make scsi_prep_async_scan and scsi_finish_async_scan static. Signed-off-by: Matthew Wilcox Signed-off-by: James Bottomley --- diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index 3ccaa4be92..4d656148bd 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -1642,7 +1642,7 @@ static void scsi_sysfs_add_devices(struct Scsi_Host *shost) * that other asynchronous scans started after this one won't affect the * ordering of the discovered devices. */ -struct async_scan_data *scsi_prep_async_scan(struct Scsi_Host *shost) +static struct async_scan_data *scsi_prep_async_scan(struct Scsi_Host *shost) { struct async_scan_data *data; @@ -1686,7 +1686,7 @@ struct async_scan_data *scsi_prep_async_scan(struct Scsi_Host *shost) * This function announces all the devices it has found to the rest * of the system. */ -void scsi_finish_async_scan(struct async_scan_data *data) +static void scsi_finish_async_scan(struct async_scan_data *data) { struct Scsi_Host *shost; @@ -1719,12 +1719,25 @@ void scsi_finish_async_scan(struct async_scan_data *data) kfree(data); } -static int do_scan_async(void *_data) +static void do_scsi_scan_host(struct Scsi_Host *shost) { - struct async_scan_data *data = _data; - scsi_scan_host_selected(data->shost, SCAN_WILD_CARD, SCAN_WILD_CARD, + if (shost->hostt->scan_finished) { + unsigned long start = jiffies; + if (shost->hostt->scan_start) + shost->hostt->scan_start(shost); + + while (!shost->hostt->scan_finished(shost, jiffies - start)) + msleep(10); + } else { + scsi_scan_host_selected(shost, SCAN_WILD_CARD, SCAN_WILD_CARD, SCAN_WILD_CARD, 0); + } +} +static int do_scan_async(void *_data) +{ + struct async_scan_data *data = _data; + do_scsi_scan_host(data->shost); scsi_finish_async_scan(data); return 0; } @@ -1742,10 +1755,10 @@ void scsi_scan_host(struct Scsi_Host *shost) data = scsi_prep_async_scan(shost); if (!data) { - scsi_scan_host_selected(shost, SCAN_WILD_CARD, SCAN_WILD_CARD, - SCAN_WILD_CARD, 0); + do_scsi_scan_host(shost); return; } + kthread_run(do_scan_async, data, "scsi_scan_%d", shost->host_no); } EXPORT_SYMBOL(scsi_scan_host); diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h index e618e711ea..6d8945d71c 100644 --- a/include/scsi/scsi_host.h +++ b/include/scsi/scsi_host.h @@ -240,6 +240,24 @@ struct scsi_host_template { */ void (* target_destroy)(struct scsi_target *); + /* + * If a host has the ability to discover targets on its own instead + * of scanning the entire bus, it can fill in this function and + * call scsi_scan_host(). This function will be called periodically + * until it returns 1 with the scsi_host and the elapsed time of + * the scan in jiffies. + * + * Status: OPTIONAL + */ + int (* scan_finished)(struct Scsi_Host *, unsigned long); + + /* + * If the host wants to be called before the scan starts, but + * after the midlayer has set up ready for the scan, it can fill + * in this function. + */ + void (* scan_start)(struct Scsi_Host *); + /* * fill in this function to allow the queue depth of this host * to be changeable (on a per device basis). returns either