linux-scsi.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [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(&reg->isp24.hccr, HCCRX_CLR_HOST_INT);
+		WRT_REG_DWORD(&reg->isp24.hccr, HCCRX_CLR_RISC_INT);
+	} else {
+		WRT_REG_WORD(&reg->isp.semaphore, 0);
+		WRT_REG_WORD(&reg->isp.hccr, HCCR_CLR_RISC_INT);
+		WRT_REG_WORD(&reg->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(&reg->isp.hccr,
+				    (HCCR_ENABLE_PARITY + 0x1));
+			else
+				/* SRAM, Instruction RAM and GP RAM parity */
+				WRT_REG_WORD(&reg->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(&reg->isp24.hccr, HCCRX_CLR_HOST_INT);
-		WRT_REG_DWORD(&reg->isp24.hccr, HCCRX_CLR_RISC_INT);
-	} else {
-		WRT_REG_WORD(&reg->isp.semaphore, 0);
-		WRT_REG_WORD(&reg->isp.hccr, HCCR_CLR_RISC_INT);
-		WRT_REG_WORD(&reg->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(&reg->isp.hccr,
-				    (HCCR_ENABLE_PARITY + 0x1));
-			else
-				/* SRAM, Instruction RAM and GP RAM parity */
-				WRT_REG_WORD(&reg->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).