* [RFC] Asynchronous scanning for FC/SAS version 2
@ 2006-11-09 22:54 Matthew Wilcox
2006-11-10 12:53 ` Matthew Wilcox
0 siblings, 1 reply; 2+ messages in thread
From: Matthew Wilcox @ 2006-11-09 22:54 UTC (permalink / raw)
To: linux-scsi
Here's the second iteration of
http://marc.theaimsgroup.com/?l=linux-scsi&m=116136002113903&w=2
Changes since that version:
- Restructure to put the callback in the scsi_host_template (thanks to
James Smart for insisting).
Now drivers can fill in scan_finished and call scsi_scan_host(). That
takes care of doing their scans asynchronously.
I should document the new role of scsi_scan_host().
James, relative to the one you've been looking at, this version adds the
'elapsed_jiffies' parameter back in (renamed to 'time'). qla2xxx and
aic94xx needed it too, and it seemed rather intrusive to add an extra
element to their host data structures when I can just keep it on the
stack.
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index 9540eb8..c312444 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -216,6 +216,23 @@ config SCSI_LOGGING
there should be no noticeable performance impact as long as you have
logging turned off.
+config SCSI_SCAN_ASYNC
+ bool "Asynchronous SCSI scanning"
+ depends on SCSI
+ help
+ The SCSI subsystem can probe for devices while the rest of the
+ system continues booting, and even probe devices on different
+ busses in parallel, leading to a significant speed-up.
+ If you have built SCSI as modules, enabling this option can
+ be a problem as the devices may not have been found by the
+ time your system expects them to have been. You can load the
+ scsi_wait_scan module to ensure that all scans have completed.
+ If you build your SCSI drivers into the kernel, then everything
+ will work fine if you say Y here.
+
+ You can override this choice by specifying scsi_mod.scan="sync"
+ or "async" on the kernel's command line.
+
menu "SCSI Transports"
depends on SCSI
diff --git a/drivers/scsi/aic94xx/aic94xx_init.c b/drivers/scsi/aic94xx/aic94xx_init.c
index 99743ca..3c46005 100644
--- a/drivers/scsi/aic94xx/aic94xx_init.c
+++ b/drivers/scsi/aic94xx/aic94xx_init.c
@@ -57,6 +57,7 @@ MODULE_PARM_DESC(collector, "\n"
char sas_addr_str[2*SAS_ADDR_SIZE + 1] = "";
static struct scsi_transport_template *aic94xx_transport_template;
+static int asd_scan_finished(struct Scsi_Host *, unsigned long);
static struct scsi_host_template aic94xx_sht = {
.module = THIS_MODULE,
@@ -66,6 +67,7 @@ static struct scsi_host_template aic94xx
.target_alloc = sas_target_alloc,
.slave_configure = sas_slave_configure,
.slave_destroy = sas_slave_destroy,
+ .scan_finished = asd_scan_finished,
.change_queue_depth = sas_change_queue_depth,
.change_queue_type = sas_change_queue_type,
.bios_param = sas_bios_param,
@@ -546,6 +548,18 @@ static int asd_unregister_sas_ha(struct
return err;
}
+static int asd_scan_finished(struct Scsi_Host *shost, unsigned long time)
+{
+ /* give the phy enabling interrupt event time to come in (1s
+ * is empirically about all it takes) */
+ if (time < HZ)
+ return 0;
+
+ /* Wait for discovery to finish */
+ scsi_flush_work(shost);
+ return 1;
+}
+
static int __devinit asd_pci_probe(struct pci_dev *dev,
const struct pci_device_id *id)
{
@@ -677,11 +691,8 @@ static int __devinit asd_pci_probe(struc
goto Err_en_phys;
}
ASD_DPRINTK("enabled phys\n");
- /* give the phy enabling interrupt event time to come in (1s
- * is empirically about all it takes) */
- ssleep(1);
- /* Wait for discovery to finish */
- scsi_flush_work(asd_ha->sas_ha.core.shost);
+
+ scsi_scan_host(shost);
return 0;
Err_en_phys:
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index a5723ad..3ad31df 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -416,33 +416,6 @@ lpfc_config_port_post(struct lpfc_hba *
return (0);
}
-static int
-lpfc_discovery_wait(struct lpfc_hba *phba)
-{
- int i = 0;
-
- while ((phba->hba_state != LPFC_HBA_READY) ||
- (phba->num_disc_nodes) || (phba->fc_prli_sent) ||
- ((phba->fc_map_cnt == 0) && (i<2)) ||
- (phba->sli.sli_flag & LPFC_SLI_MBOX_ACTIVE)) {
- /* Check every second for 30 retries. */
- i++;
- if (i > 30) {
- return -ETIMEDOUT;
- }
- if ((i >= 15) && (phba->hba_state <= LPFC_LINK_DOWN)) {
- /* The link is down. Set linkdown timeout */
- return -ETIMEDOUT;
- }
-
- /* Delay for 1 second to give discovery time to complete. */
- msleep(1000);
-
- }
-
- return 0;
-}
-
/************************************************************************/
/* */
/* lpfc_hba_down_prep */
@@ -1441,7 +1414,6 @@ lpfc_scsi_free(struct lpfc_hba * phba)
return 0;
}
-
static int __devinit
lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
{
@@ -1647,6 +1619,7 @@ lpfc_pci_probe_one(struct pci_dev *pdev,
if (error)
goto out_kthread_stop;
+ scsi_scan_host(host);
error = lpfc_alloc_sysfs_attr(phba);
if (error)
goto out_remove_host;
@@ -1677,8 +1650,6 @@ lpfc_pci_probe_one(struct pci_dev *pdev,
*/
host->can_queue = phba->cfg_hba_queue_depth - 10;
- lpfc_discovery_wait(phba);
-
if (phba->cfg_poll & DISABLE_FCP_RING_INT) {
spin_lock_irq(phba->host->host_lock);
lpfc_poll_start_timer(phba);
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c
index 97ae98d..60623f1 100644
--- a/drivers/scsi/lpfc/lpfc_scsi.c
+++ b/drivers/scsi/lpfc/lpfc_scsi.c
@@ -1267,6 +1267,29 @@ lpfc_slave_destroy(struct scsi_device *s
return;
}
+static int lpfc_scan_finished(struct Scsi_Host *shost, unsigned long time)
+{
+ struct lpfc_hba *phba = (struct lpfc_hba *)shost->hostdata;
+
+ if (!phba->host)
+ return 1;
+ if (time >= 30 * HZ)
+ return 1;
+
+ if (phba->hba_state != LPFC_HBA_READY)
+ return 0;
+ if (phba->num_disc_nodes || phba->fc_prli_sent)
+ return 0;
+ if ((phba->fc_map_cnt == 0) && (time < 2 * HZ))
+ return 0;
+ if (phba->sli.sli_flag & LPFC_SLI_MBOX_ACTIVE)
+ return 0;
+ if ((phba->hba_state > LPFC_LINK_DOWN) || (time < 15 * HZ))
+ return 0;
+
+ return 1;
+}
+
struct scsi_host_template lpfc_template = {
.module = THIS_MODULE,
.name = LPFC_DRIVER_NAME,
@@ -1278,6 +1301,7 @@ struct scsi_host_template lpfc_template
.slave_alloc = lpfc_slave_alloc,
.slave_configure = lpfc_slave_configure,
.slave_destroy = lpfc_slave_destroy,
+ .scan_finished = lpfc_scan_finished,
.this_id = -1,
.sg_tablesize = LPFC_SG_SEG_CNT,
.cmd_per_lun = LPFC_CMD_PER_LUN,
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 3f20d76..91b8bf3 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -83,6 +83,7 @@ MODULE_PARM_DESC(ql2xfdmienable,
static int qla2xxx_slave_configure(struct scsi_device * device);
static int qla2xxx_slave_alloc(struct scsi_device *);
static void qla2xxx_slave_destroy(struct scsi_device *);
+static int qla2xxx_scan_finished(struct Scsi_Host *);
static int qla2x00_queuecommand(struct scsi_cmnd *cmd,
void (*fn)(struct scsi_cmnd *));
static int qla24xx_queuecommand(struct scsi_cmnd *cmd,
@@ -111,6 +112,7 @@ static struct scsi_host_template qla2x00
.slave_alloc = qla2xxx_slave_alloc,
.slave_destroy = qla2xxx_slave_destroy,
+ .scan_finished = qla2x00_scan_finished,
.change_queue_depth = qla2x00_change_queue_depth,
.change_queue_type = qla2x00_change_queue_type,
.this_id = -1,
@@ -1353,6 +1355,20 @@ qla24xx_disable_intrs(scsi_qla_host_t *h
spin_unlock_irqrestore(&ha->hardware_lock, flags);
}
+static int qla2x00_scan_finished(struct Scsi_Host *shost, unsigned long time)
+{
+ scsi_qla_host_t *ha = (scsi_qla_host_t *)shost->hostdata;
+
+ if (time > ha->loop_reset_delay * HZ)
+ return 1;
+
+ qla2x00_check_fabric_devices(ha);
+
+ if (ha->device_flags & (DFLG_NO_CABLE | DFLG_FABRIC_DEVICES))
+ return 1;
+ return !(ha->device_flags & SWITCH_FOUND);
+}
+
/*
* PCI driver interface
*/
@@ -1363,8 +1379,7 @@ qla2x00_probe_one(struct pci_dev *pdev,
device_reg_t __iomem *reg;
struct Scsi_Host *host;
scsi_qla_host_t *ha;
- unsigned long flags = 0;
- unsigned long wait_switch = 0;
+ unsigned long flags;
char pci_info[20];
char fw_str[30];
fc_port_t *fcport;
@@ -1614,22 +1629,6 @@ qla2x00_probe_one(struct pci_dev *pdev,
ha->isp_ops.enable_intrs(ha);
- /* v2.19.5b6 */
- /*
- * Wait around max loop_reset_delay secs for the devices to come
- * on-line. We don't want Linux scanning before we are ready.
- *
- */
- for (wait_switch = jiffies + (ha->loop_reset_delay * HZ);
- time_before(jiffies,wait_switch) &&
- !(ha->device_flags & (DFLG_NO_CABLE | DFLG_FABRIC_DEVICES))
- && (ha->device_flags & SWITCH_FOUND) ;) {
-
- qla2x00_check_fabric_devices(ha);
-
- msleep(10);
- }
-
pci_set_drvdata(pdev, ha);
ha->flags.init_done = 1;
num_hosts++;
@@ -1637,6 +1636,7 @@ qla2x00_probe_one(struct pci_dev *pdev,
ret = scsi_add_host(host, &pdev->dev);
if (ret)
goto probe_failed;
+ scsi_scan_host(host);
qla2x00_alloc_sysfs_attr(ha);
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index 148e24c..bbeddf9 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -89,7 +89,13 @@ module_param_named(max_luns, max_scsi_lu
MODULE_PARM_DESC(max_luns,
"last scsi LUN (should be between 1 and 2^32-1)");
-static char scsi_scan_type[6] = "sync";
+#ifdef CONFIG_SCSI_SCAN_ASYNC
+#define SCSI_SCAN_TYPE_DEFAULT "async"
+#else
+#define SCSI_SCAN_TYPE_DEFAULT "sync"
+#endif
+
+static char scsi_scan_type[6] = SCSI_SCAN_TYPE_DEFAULT;
module_param_string(scan, scsi_scan_type, sizeof(scsi_scan_type), S_IRUGO);
MODULE_PARM_DESC(scan, "sync, async or none");
@@ -1533,6 +1539,9 @@ void scsi_scan_target(struct device *par
{
struct Scsi_Host *shost = dev_to_shost(parent);
+ if (strncmp(scsi_scan_type, "none", 4) == 0)
+ return;
+
if (!shost->async_scan)
scsi_complete_async_scans();
@@ -1623,7 +1632,7 @@ static void scsi_sysfs_add_devices(struc
* 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;
@@ -1667,7 +1676,7 @@ struct async_scan_data *scsi_prep_async_
* 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;
@@ -1700,12 +1709,22 @@ void scsi_finish_async_scan(struct async
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;
+ 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;
}
@@ -1723,10 +1742,10 @@ void scsi_scan_host(struct Scsi_Host *sh
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 ba5b3eb..359672a 100644
--- a/include/scsi/scsi_host.h
+++ b/include/scsi/scsi_host.h
@@ -241,6 +241,17 @@ #endif
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);
+
+ /*
* fill in this function to allow the queue depth of this host
* to be changeable (on a per device basis). returns either
* the current queue depth setting (may be different from what
^ permalink raw reply related [flat|nested] 2+ messages in thread
* Re: [RFC] Asynchronous scanning for FC/SAS version 2
2006-11-09 22:54 [RFC] Asynchronous scanning for FC/SAS version 2 Matthew Wilcox
@ 2006-11-10 12:53 ` Matthew Wilcox
0 siblings, 0 replies; 2+ messages in thread
From: Matthew Wilcox @ 2006-11-10 12:53 UTC (permalink / raw)
To: linux-scsi
On Thu, Nov 09, 2006 at 03:54:17PM -0700, Matthew Wilcox wrote:
> Here's the second iteration of
> http://marc.theaimsgroup.com/?l=linux-scsi&m=116136002113903&w=2
Many thanks to Justin Chen for testing a couple of intermediate versions;
this incremental patch rearranges the QLogic driver initialisation to
perform the LIP reset in the scanning thread. This gets the time to
initialise qlogic devices down to under a tenth of a second per device.
I introduce another scsi_host_template method to achieve this. I suppose
I could have done it by calling scan_finished(host, 0) and checking
the time argument in the qlogic implementation ... but that seemed a
bit unclean.
Still todo:
- Get Emulex LPFC using scan_start
- Work out how to use this interface for USB/Firewire/iSCSI
- Get LSI Fusion using this infrastructure
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 91b8bf3..048dd3f 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -83,7 +83,8 @@ MODULE_PARM_DESC(ql2xfdmienable,
static int qla2xxx_slave_configure(struct scsi_device * device);
static int qla2xxx_slave_alloc(struct scsi_device *);
static void qla2xxx_slave_destroy(struct scsi_device *);
-static int qla2xxx_scan_finished(struct Scsi_Host *);
+static int qla2xxx_scan_finished(struct Scsi_Host *, unsigned long time);
+static void qla2xxx_scan_start(struct Scsi_Host *);
static int qla2x00_queuecommand(struct scsi_cmnd *cmd,
void (*fn)(struct scsi_cmnd *));
static int qla24xx_queuecommand(struct scsi_cmnd *cmd,
@@ -112,7 +113,8 @@ static struct scsi_host_template qla2x00
.slave_alloc = qla2xxx_slave_alloc,
.slave_destroy = qla2xxx_slave_destroy,
- .scan_finished = qla2x00_scan_finished,
+ .scan_finished = qla2xxx_scan_finished,
+ .scan_start = qla2xxx_scan_start,
.change_queue_depth = qla2x00_change_queue_depth,
.change_queue_type = qla2x00_change_queue_type,
.this_id = -1,
@@ -1355,18 +1357,115 @@ qla24xx_disable_intrs(scsi_qla_host_t *h
spin_unlock_irqrestore(&ha->hardware_lock, flags);
}
-static int qla2x00_scan_finished(struct Scsi_Host *shost, unsigned long time)
+static void qla2xxx_remove_device(scsi_qla_host_t *ha)
{
+ qla2x00_free_sysfs_attr(ha);
+ fc_remove_host(ha->host);
+ scsi_remove_host(ha->host);
+ qla2x00_free_device(ha);
+ scsi_host_put(ha->host);
+}
+
+static void qla2xxx_scan_start(struct Scsi_Host *shost)
+{
+ unsigned long flags;
+ device_reg_t __iomem *reg;
scsi_qla_host_t *ha = (scsi_qla_host_t *)shost->hostdata;
- if (time > ha->loop_reset_delay * HZ)
+ if (qla2x00_initialize_adapter(ha) &&
+ !(ha->device_flags & DFLG_NO_CABLE)) {
+
+ qla_printk(KERN_WARNING, ha,
+ "Failed to initialize adapter\n");
+
+ DEBUG2(printk("scsi(%ld): Failed to initialize adapter - "
+ "Adapter flags %x.\n",
+ ha->host_no, ha->device_flags));
+ goto error;
+ }
+
+ /*
+ * Startup the kernel thread for this host adapter
+ */
+ ha->dpc_thread = kthread_create(qla2x00_do_dpc, ha,
+ "%s_dpc", ha->host_str);
+ if (IS_ERR(ha->dpc_thread)) {
+ qla_printk(KERN_WARNING, ha,
+ "Unable to start DPC thread!\n");
+ goto error;
+ }
+
+ qla2x00_start_timer(ha, qla2x00_timer, WATCH_INTERVAL);
+
+ DEBUG2(printk("DEBUG: detect hba %ld at address = %p\n",
+ ha->host_no, ha));
+
+ ha->isp_ops.disable_intrs(ha);
+
+ spin_lock_irqsave(&ha->hardware_lock, flags);
+ reg = ha->iobase;
+ if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) {
+ WRT_REG_DWORD(®->isp24.hccr, HCCRX_CLR_HOST_INT);
+ WRT_REG_DWORD(®->isp24.hccr, HCCRX_CLR_RISC_INT);
+ } else {
+ WRT_REG_WORD(®->isp.semaphore, 0);
+ WRT_REG_WORD(®->isp.hccr, HCCR_CLR_RISC_INT);
+ WRT_REG_WORD(®->isp.hccr, HCCR_CLR_HOST_INT);
+
+ /* Enable proper parity */
+ if (!IS_QLA2100(ha) && !IS_QLA2200(ha)) {
+ if (IS_QLA2300(ha))
+ /* SRAM parity */
+ WRT_REG_WORD(®->isp.hccr,
+ (HCCR_ENABLE_PARITY + 0x1));
+ else
+ /* SRAM, Instruction RAM and GP RAM parity */
+ WRT_REG_WORD(®->isp.hccr,
+ (HCCR_ENABLE_PARITY + 0x7));
+ }
+ }
+ spin_unlock_irqrestore(&ha->hardware_lock, flags);
+
+ ha->isp_ops.enable_intrs(ha);
+ ha->flags.init_done = 1;
+
+ return;
+
+ error:
+ qla2xxx_remove_device(ha);
+ ha->host = NULL;
+}
+
+static int qla2xxx_scan_finished(struct Scsi_Host *shost, unsigned long time)
+{
+ fc_port_t *fcport;
+ scsi_qla_host_t *ha = (scsi_qla_host_t *)shost->hostdata;
+
+ if (!ha->host)
return 1;
+ if (time > ha->loop_reset_delay * HZ)
+ goto finished;
+
qla2x00_check_fabric_devices(ha);
if (ha->device_flags & (DFLG_NO_CABLE | DFLG_FABRIC_DEVICES))
- return 1;
- return !(ha->device_flags & SWITCH_FOUND);
+ goto finished;
+ if (!(ha->device_flags & SWITCH_FOUND))
+ goto finished;
+
+ return 0;
+
+ finished:
+ qla2x00_alloc_sysfs_attr(ha);
+
+ qla2x00_init_host_attr(ha);
+
+ /* Go with fc_rport registration. */
+ list_for_each_entry(fcport, &ha->fcports, list)
+ qla2x00_reg_remote_port(ha, fcport);
+
+ return 1;
}
/*
@@ -1376,13 +1475,10 @@ static int __devinit
qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
{
int ret = -ENODEV;
- device_reg_t __iomem *reg;
struct Scsi_Host *host;
scsi_qla_host_t *ha;
- unsigned long flags;
char pci_info[20];
char fw_str[30];
- fc_port_t *fcport;
struct scsi_host_template *sht;
if (pci_enable_device(pdev))
@@ -1526,7 +1622,7 @@ qla2x00_probe_one(struct pci_dev *pdev,
host->can_queue = ha->request_q_length + 128;
/* load the F/W, read paramaters, and init the H/W */
- ha->instance = num_hosts;
+ ha->instance = num_hosts++;
init_MUTEX(&ha->mbx_cmd_sem);
init_MUTEX_LOCKED(&ha->mbx_intr_sem);
@@ -1551,32 +1647,6 @@ qla2x00_probe_one(struct pci_dev *pdev,
goto probe_failed;
}
- if (qla2x00_initialize_adapter(ha) &&
- !(ha->device_flags & DFLG_NO_CABLE)) {
-
- qla_printk(KERN_WARNING, ha,
- "Failed to initialize adapter\n");
-
- DEBUG2(printk("scsi(%ld): Failed to initialize adapter - "
- "Adapter flags %x.\n",
- ha->host_no, ha->device_flags));
-
- ret = -ENODEV;
- goto probe_failed;
- }
-
- /*
- * Startup the kernel thread for this host adapter
- */
- ha->dpc_thread = kthread_create(qla2x00_do_dpc, ha,
- "%s_dpc", ha->host_str);
- if (IS_ERR(ha->dpc_thread)) {
- qla_printk(KERN_WARNING, ha,
- "Unable to start DPC thread!\n");
- ret = PTR_ERR(ha->dpc_thread);
- goto probe_failed;
- }
-
host->this_id = 255;
host->cmd_per_lun = 3;
host->unique_id = ha->instance;
@@ -1594,54 +1664,13 @@ qla2x00_probe_one(struct pci_dev *pdev,
goto probe_failed;
}
host->irq = pdev->irq;
-
- /* Initialized the timer */
- qla2x00_start_timer(ha, qla2x00_timer, WATCH_INTERVAL);
-
- DEBUG2(printk("DEBUG: detect hba %ld at address = %p\n",
- ha->host_no, ha));
-
- ha->isp_ops.disable_intrs(ha);
-
- spin_lock_irqsave(&ha->hardware_lock, flags);
- reg = ha->iobase;
- if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) {
- WRT_REG_DWORD(®->isp24.hccr, HCCRX_CLR_HOST_INT);
- WRT_REG_DWORD(®->isp24.hccr, HCCRX_CLR_RISC_INT);
- } else {
- WRT_REG_WORD(®->isp.semaphore, 0);
- WRT_REG_WORD(®->isp.hccr, HCCR_CLR_RISC_INT);
- WRT_REG_WORD(®->isp.hccr, HCCR_CLR_HOST_INT);
-
- /* Enable proper parity */
- if (!IS_QLA2100(ha) && !IS_QLA2200(ha)) {
- if (IS_QLA2300(ha))
- /* SRAM parity */
- WRT_REG_WORD(®->isp.hccr,
- (HCCR_ENABLE_PARITY + 0x1));
- else
- /* SRAM, Instruction RAM and GP RAM parity */
- WRT_REG_WORD(®->isp.hccr,
- (HCCR_ENABLE_PARITY + 0x7));
- }
- }
- spin_unlock_irqrestore(&ha->hardware_lock, flags);
-
- ha->isp_ops.enable_intrs(ha);
-
pci_set_drvdata(pdev, ha);
- ha->flags.init_done = 1;
- num_hosts++;
ret = scsi_add_host(host, &pdev->dev);
if (ret)
goto probe_failed;
scsi_scan_host(host);
- qla2x00_alloc_sysfs_attr(ha);
-
- qla2x00_init_host_attr(ha);
-
qla_printk(KERN_INFO, ha, "\n"
" QLogic Fibre Channel HBA Driver: %s\n"
" QLogic %s - %s\n"
@@ -1652,10 +1681,6 @@ qla2x00_probe_one(struct pci_dev *pdev,
ha->flags.enable_64bit_addressing ? '+': '-', ha->host_no,
ha->isp_ops.fw_version_str(ha, fw_str));
- /* Go with fc_rport registration. */
- list_for_each_entry(fcport, &ha->fcports, list)
- qla2x00_reg_remote_port(ha, fcport);
-
return 0;
probe_failed:
@@ -1676,17 +1701,7 @@ qla2x00_remove_one(struct pci_dev *pdev)
scsi_qla_host_t *ha;
ha = pci_get_drvdata(pdev);
-
- qla2x00_free_sysfs_attr(ha);
-
- fc_remove_host(ha->host);
-
- scsi_remove_host(ha->host);
-
- qla2x00_free_device(ha);
-
- scsi_host_put(ha->host);
-
+ qla2xxx_remove_device(ha);
pci_set_drvdata(pdev, NULL);
}
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index bbeddf9..5c7d65d 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -1713,6 +1713,9 @@ static void do_scsi_scan_host(struct Scs
{
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 {
diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h
index 359672a..20ebcea 100644
--- a/include/scsi/scsi_host.h
+++ b/include/scsi/scsi_host.h
@@ -252,6 +252,13 @@ #endif
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
* the current queue depth setting (may be different from what
^ permalink raw reply related [flat|nested] 2+ messages in thread
end of thread, other threads:[~2006-11-10 12:53 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-11-09 22:54 [RFC] Asynchronous scanning for FC/SAS version 2 Matthew Wilcox
2006-11-10 12:53 ` Matthew Wilcox
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).