public inbox for linux-scsi@vger.kernel.org
 help / color / mirror / Atom feed
From: Christoph Hellwig <hch@infradead.org>
To: Jamie Wellnitz <Jamie.Wellnitz@emulex.com>
Cc: Christoph Hellwig <hch@infradead.org>,
	"Smart, James" <James.Smart@emulex.com>,
	Linux SCSI Reflector <linux-scsi@vger.kernel.org>
Subject: Re: [Emulex] Ready for next round...
Date: Wed, 16 Jun 2004 14:50:08 +0100	[thread overview]
Message-ID: <20040616135008.GA12260@infradead.org> (raw)
In-Reply-To: <20040616133518.GS11371@ma.emulex.com>

On Wed, Jun 16, 2004 at 09:35:18AM -0400, Jamie Wellnitz wrote:
> Christoph,
> 
> Am I missing the big diff for lpfc_fcp.c?  I don't see it . . .

Umm, sorry.  Here it is:

diff -uNr -p -X dontdiff lpfcdriver-2.6-8.0.4/lpfc_fcp.c lpfcdriver-2.6-8.0.4-hch/lpfc_fcp.c
--- lpfcdriver-2.6-8.0.4/lpfc_fcp.c	2004-06-15 00:07:01.000000000 +0200
+++ lpfcdriver-2.6-8.0.4-hch/lpfc_fcp.c	2004-06-16 10:15:00.306818584 +0200
@@ -70,71 +70,12 @@
 
 static char *lpfc_drvr_name = LPFC_DRIVER_NAME;
 
-MODULE_DESCRIPTION(LPFC_MODULE_DESC);
-MODULE_AUTHOR("Emulex Corporation - tech.support@emulex.com");
-MODULE_VERSION("0:" LPFC_DRIVER_VERSION);
-
 #define FC_EXTEND_TRANS_A 1
 
-static int lpfc_get_bind_type(struct lpfc_hba *);
-static int lpfc_slave_alloc(struct scsi_device *);
-static int lpfc_slave_configure(struct scsi_device *);
-static void lpfc_slave_destroy(struct scsi_device *);
-
-
-static int lpfc_device_queue_depth(struct lpfc_hba *, struct scsi_device *);
-static int lpfc_reset_bus_handler(struct scsi_cmnd *cmnd);
-
-static int lpfc_memmap(struct lpfc_hba *);
-static int lpfc_unmemmap(struct lpfc_hba *);
-static int lpfc_pcimap(struct lpfc_hba *);
-
-static int lpfc_config_setup(struct lpfc_hba *);
-static int lpfc_bind_setup(struct lpfc_hba *);
-static int lpfc_sli_setup(struct lpfc_hba *);
-static int lpfc_bind_wwpn(struct lpfc_hba *, char **, u_int);
-static int lpfc_bind_wwnn(struct lpfc_hba *, char **, u_int);
-static int lpfc_bind_did(struct lpfc_hba *, char **, u_int);
-static int lpfc_biosparam(struct scsi_device *, struct block_device *,
-			  sector_t capacity, int ip[]);
-static int lpfc_proc_info(struct Scsi_Host *, char *, char **, off_t, int, int);
-static uint32_t lpfc_get_cfgparam(int, int);
-
-static int lpfc_do_dpc(void *);
-
 /* Binding Definitions: Max string size  */
 #define FC_MAX_DID_STRING       6
 #define FC_MAX_WW_NN_PN_STRING 16
 
-
-static struct scsi_host_template driver_template = {
-	.module = THIS_MODULE,
-	.name = LPFC_DRIVER_NAME,
-	.info = lpfc_info,
-	.queuecommand = lpfc_queuecommand,
-
-	.eh_abort_handler = lpfc_abort_handler,
-	.eh_device_reset_handler = lpfc_reset_lun_handler,
-	.eh_bus_reset_handler = lpfc_reset_bus_handler,
-
-	.slave_alloc = lpfc_slave_alloc,
-	.slave_configure = lpfc_slave_configure,
-	.slave_destroy = lpfc_slave_destroy,
-
-	.bios_param = lpfc_biosparam,
-	.proc_info = lpfc_proc_info,
-	.proc_name = LPFC_DRIVER_NAME,
-
-	.can_queue = LPFC_DFT_HBA_Q_DEPTH,
-	.this_id = -1,
-
-	.sg_tablesize = SG_ALL,
-	.cmd_per_lun = 30,
-	.use_clustering = ENABLE_CLUSTERING,
-};
-
-
-
 unsigned long lpfc_loadtime;
 static struct list_head lpfc_hba_list = LIST_HEAD_INIT(lpfc_hba_list);
 
@@ -259,1135 +200,793 @@ static DEVICE_ATTR(lpfc_max_target, S_IR
 		   lpfc_sysfs_max_target_show, lpfc_sysfs_max_target_store);
 static DRIVER_ATTR(version, S_IRUGO, lpfc_sysfs_version_show, NULL);
 
-static struct pci_device_id lpfc_id_table[] = {
-	{
-		.vendor = PCI_VENDOR_ID_EMULEX,
-		.device	= PCI_DEVICE_ID_VIPER,
-		.subvendor = PCI_ANY_ID,
-		.subdevice = PCI_ANY_ID,
-		.class = 0,
-		.class_mask = 0,
-		.driver_data = 0UL
-	},
-	{
-		.vendor = PCI_VENDOR_ID_EMULEX,
-		.device	= PCI_DEVICE_ID_THOR,
-		.subvendor = PCI_ANY_ID,
-		.subdevice = PCI_ANY_ID,
-		.class = 0,
-		.class_mask = 0,
-		.driver_data = 0UL
-	},
-	{
-		.vendor = PCI_VENDOR_ID_EMULEX,
-		.device	= PCI_DEVICE_ID_PEGASUS,
-		.subvendor = PCI_ANY_ID,
-		.subdevice = PCI_ANY_ID,
-		.class = 0,
-		.class_mask = 0,
-		.driver_data = 0UL
-	},
-	{
-		.vendor = PCI_VENDOR_ID_EMULEX,
-		.device	= PCI_DEVICE_ID_CENTAUR,
-		.subvendor = PCI_ANY_ID,
-		.subdevice = PCI_ANY_ID,
-	},
-	{
-		.vendor = PCI_VENDOR_ID_EMULEX,
-		.device	= PCI_DEVICE_ID_DRAGONFLY,
-		.subvendor = PCI_ANY_ID,
-		.subdevice = PCI_ANY_ID,
-		.class = 0,
-		.class_mask = 0,
-		.driver_data = 0UL
-	},
-	{
-		.vendor = PCI_VENDOR_ID_EMULEX,
-		.device	= PCI_DEVICE_ID_SUPERFLY,
-		.subvendor = PCI_ANY_ID,
-		.subdevice = PCI_ANY_ID,
-		.class = 0,
-		.class_mask = 0,
-		.driver_data = 0UL
-	},
-	{
-		.vendor = PCI_VENDOR_ID_EMULEX,
-		.device	= PCI_DEVICE_ID_RFLY,
-		.subvendor = PCI_ANY_ID,
-		.subdevice = PCI_ANY_ID,
-		.class = 0,
-		.class_mask = 0,
-		.driver_data = 0UL
-	},
-	{
-		.vendor = PCI_VENDOR_ID_EMULEX,
-		.device	= PCI_DEVICE_ID_PFLY,
-		.subvendor = PCI_ANY_ID,
-		.subdevice = PCI_ANY_ID,
-		.class = 0,
-		.class_mask = 0,
-		.driver_data = 0UL
-	},
-	{
-		.vendor = PCI_VENDOR_ID_EMULEX,
-		.device	= PCI_DEVICE_ID_TFLY,
-		.subvendor = PCI_ANY_ID,
-		.subdevice = PCI_ANY_ID,
-		.class = 0,
-		.class_mask = 0,
-		.driver_data = 0UL
-	},
-	{ 0 }
-};
-
-MODULE_DEVICE_TABLE(pci, lpfc_id_table);
-
-static int __devinit
-lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
+/*
+ * Retrieve lpfc_hba * matching instance (board no)
+ * If found return lpfc_hba *
+ * If not found return NULL
+ */
+struct lpfc_hba *
+lpfc_get_phba_by_inst(int inst)
 {
-	struct Scsi_Host *host;
-	struct lpfc_hba *phba;
-	struct lpfc_cfgparam *clp;
-	struct clk_data *clkData;
-	int rc, i;
-	unsigned long iflag;
-	uint32_t timeout;
-	struct timer_list *cur_timer;
-	
-
-	if (pci_enable_device(pdev))
-		return -ENODEV;
-	if (pci_request_regions(pdev, LPFC_DRIVER_NAME)) {
-		printk("lpfc PCI I/O region is already in use.\n");
-		printk("a driver for lpfc is already loaded on this system.\n");
-		return -ENODEV;
-	}
-	
-	/*
-	 * Allocate space for adapter info structure
-	 */
-	if (!(phba = kmalloc(sizeof (struct lpfc_hba), GFP_KERNEL))) {
-		goto error;
-	}
-
-	/* By default, the driver expects this attach to succeed. */
-	rc = 0;
-
-	memset(phba, 0, sizeof (struct lpfc_hba));
-	INIT_LIST_HEAD(&phba->timerList);
-
-	/* Initialize default values for configuration parameters */
-	if (!(phba->config = kmalloc(sizeof (lpfc_icfgparam), GFP_KERNEL))) {
-		goto error_1;
-	}
-	memset(phba->config, 0, sizeof (lpfc_icfgparam));
-
-	memcpy(&phba->config[0], (uint8_t *) & lpfc_icfgparam[0],
-	       sizeof (lpfc_icfgparam));
-
-	clp = &phba->config[0];
+	struct lpfc_hba * phba;
+	int    found = 0;
 
-	/* Set everything to the defaults */
-	for (i = 0; i < LPFC_TOTAL_NUM_OF_CFG_PARAM; i++)
-		clp[i].a_current = clp[i].a_default;
-	
-	/* Assign an unused board number */
-	i = 0;
-	while (1) {
-		if (lpfc_get_phba_by_inst(i) == NULL ) {
-			phba->brd_no = i;
+	phba = NULL;
+	list_for_each_entry(phba, &lpfc_hba_list, hba_list) {
+		if (phba->brd_no == inst) {
+			found = 1;
 			break;
 		}
-		i++;
 	}
+	
+	if (!found)
+		return(NULL);
+	else
+		return(phba);
+	
+}
 
-	/* Add adapter structure to list */
-	list_add_tail(&phba->hba_list, &lpfc_hba_list);
-
-	/* Initialize all internally managed lists. */
-	INIT_LIST_HEAD(&phba->fc_nlpmap_list);
-	INIT_LIST_HEAD(&phba->fc_nlpunmap_list);
-	INIT_LIST_HEAD(&phba->fc_plogi_list);
-	INIT_LIST_HEAD(&phba->fc_adisc_list);
-	INIT_LIST_HEAD(&phba->fc_nlpbind_list);
-
-	/* Initialize plxhba - LINUX specific */
-	phba->pcidev = pdev;
-	init_waitqueue_head(&phba->linkevtwq);
-	init_waitqueue_head(&phba->rscnevtwq);
-	init_waitqueue_head(&phba->ctevtwq);
-
-	if ((rc = lpfc_pcimap(phba))) {
-		goto error_2;
+const char *
+lpfc_info(struct Scsi_Host *host)
+{
+	struct lpfc_hba    *phba = (struct lpfc_hba *) host->hostdata[0];
+	int len;
+	static char  lpfcinfobuf[128];
+	
+	memset(lpfcinfobuf,0,128);
+	if(phba && phba->pcidev){
+	        lpfc_get_hba_model_desc(phba, 0, lpfcinfobuf);
+		len = strlen(lpfcinfobuf);	
+		snprintf(lpfcinfobuf + len,
+			128-len,
+	       		" on PCI bus %02x device %02x irq %d",
+			phba->pcidev->bus->number,
+		 	phba->pcidev->devfn,
+			phba->pcidev->irq);
 	}
+	return lpfcinfobuf;
+}
 
-	if ((rc = lpfc_memmap(phba))) {
-		goto error_2;
-	}
+static int
+lpfc_proc_info(struct Scsi_Host *host,
+	       char *buf, char **start, off_t offset, int count, int rw)
+{
 
-	lpfc_num_hba++;
-	lpfc_config_setup(phba);	/* Setup configuration parameters */
+	struct lpfc_hba *phba = NULL;
+	struct pci_dev *pdev;
+	char fwrev[32];
+	lpfc_vpd_t *vp;
+	struct lpfc_nodelist *ndlp;
+	int  i, j, incr;
+	char hdw[9];
+	int len = 0, found = 0;
+	
+	/* Sufficient bytes to hold a port or node name. */
+	uint8_t name[sizeof (struct lpfc_name)];
 
-	/*
-	 * If the t.o value is not set, set it to 30
+	/* If rw = 0, then read info
+	 * If rw = 1, then write info (NYI)
 	 */
-	if (clp[LPFC_CFG_SCSI_REQ_TMO].a_current == 0) {
-		clp[LPFC_CFG_SCSI_REQ_TMO].a_current = 30;
-	}
+	if (rw)
+		return -EINVAL;
 
-	if (clp[LPFC_CFG_DISC_THREADS].a_current) {
-		/*
-		 * Set to FC_NLP_REQ if automap is set to 0 since order of
-		 * discovery does not matter if everything is persistently
-		 * bound.
-		 */
-		if (clp[LPFC_CFG_AUTOMAP].a_current == 0) {
-			clp[LPFC_CFG_DISC_THREADS].a_current =
-			    LPFC_MAX_DISC_THREADS;
+
+	list_for_each_entry(phba, &lpfc_hba_list, hba_list) {
+		if (phba == (struct lpfc_hba *)host->hostdata[0]) {
+			found = 1;
+			break;
 		}
 	}
 
-	/* Initialize all per HBA locks */
-	spin_lock_init(&phba->drvrlock);
-	spin_lock_init(&phba->hiprilock);
-
-	lpfc_sli_setup(phba);	/* Setup SLI Layer to run over lpfc HBAs */
-	lpfc_sli_queue_setup(phba);	/* Initialize the SLI Layer */
-
-	if (lpfc_mem_alloc(phba) == 0) {
-		goto error_3;
+	if (!found) {
+		return sprintf(buf, "Cannot find adapter for requested host "
+			       "number.\n");
 	}
-	lpfc_bind_setup(phba);	/* Setup binding configuration parameters */
-
-	/* Initialize HBA structure */
-	phba->fc_edtov = FF_DEF_EDTOV;
-	phba->fc_ratov = FF_DEF_RATOV;
-	phba->fc_altov = FF_DEF_ALTOV;
-	phba->fc_arbtov = FF_DEF_ARBTOV;
 
-	/* Set the FARP and XRI timeout values now since they depend on
-	   fc_ratov. */
-	phba->fc_ipfarp_timeout = (3 * phba->fc_ratov);
-	phba->fc_ipxri_timeout = (3 * phba->fc_ratov);
+	vp = &phba->vpd;
+	pdev = phba->pcidev;
 
-	spin_lock_init(&phba->dpc_lock);
-	INIT_LIST_HEAD(&phba->dpc_disc);
-	init_completion(&phba->dpc_startup);
-	init_completion(&phba->dpc_exiting);
+	len += snprintf(buf, PAGE_SIZE, LPFC_MODULE_DESC "\n");
 
-	/*
-	* Startup the kernel thread for this host adapter
-	*/
-	phba->dpc_kill = 0;
-	phba->dpc_pid = kernel_thread(lpfc_do_dpc, phba, 0);
-	if (phba->dpc_pid < 0) {
-		goto error_3;
-	}
-	wait_for_completion(&phba->dpc_startup);
+	len += snprintf(buf + len, PAGE_SIZE-len, "%s\n",
+			lpfc_info(phba->host));
 
+	len += snprintf(buf + len, PAGE_SIZE-len, "SerialNum: %s\n",
+			phba->SerialNumber);
 
+	lpfc_decode_firmware_rev(phba, fwrev, 1);
+	len += snprintf(buf + len, PAGE_SIZE-len, "Firmware Version: %s\n",
+			fwrev);
 
-	/* Call SLI to initialize the HBA. */
-	if ((rc = lpfc_sli_hba_setup(phba)) != 0) {
-		goto error_5;
+	len += snprintf(buf + len, PAGE_SIZE-len, "Hdw: ");
+	/* Convert JEDEC ID to ascii for hardware version */
+	incr = vp->rev.biuRev;
+	for (i = 0; i < 8; i++) {
+		j = (incr & 0xf);
+		if (j <= 9)
+			hdw[7 - i] = (char)((uint8_t) 0x30 + (uint8_t) j);
+		else
+			hdw[7 - i] =
+			    (char)((uint8_t) 0x61 + (uint8_t) (j - 10));
+		incr = (incr >> 4);
 	}
+	hdw[8] = 0;
+	len += snprintf(buf + len, PAGE_SIZE-len, hdw);
 
+	len += snprintf(buf + len, PAGE_SIZE-len, "\nVendorId: 0x%x\n",
+		       ((((uint32_t) pdev->device) << 16) |
+			(uint32_t) (pdev->vendor)));
 
-	   /* Register this board */
-	host = scsi_host_alloc(&driver_template, sizeof (unsigned long));
-
-	if (host) {
-		phba->host = host;
-		host->can_queue = clp[LPFC_CFG_DFT_HBA_Q_DEPTH].a_current - 10;
-	}
-	else {
-		printk (KERN_WARNING "%s%d: scsi_host_alloc failed during "
-			"attach\n", lpfc_drvr_name, phba->brd_no);
-		goto error_5;
-	}
-
-	/*
-	 * Adjust the number of id's
-	 * Although max_id is an int, target id's are unsined chars
-	 * Do not exceed 255, otherwise the device scan will wrap around
+	/* A Fibre Channel node or port name is 8 octets long and delimited by
+	 * colons.
 	 */
-	if (clp[LPFC_CFG_MAX_TARGET].a_current > LPFC_MAX_TARGET) {
-		clp[LPFC_CFG_MAX_TARGET].a_current = LPFC_DFT_MAX_TARGET;
-	}
-	host->max_id = clp[LPFC_CFG_MAX_TARGET].a_current;
-	host->unique_id = lpfc_num_hba;
-
-	if (clp[LPFC_CFG_MAX_LUN].a_current > LPFC_MAX_LUN) {
-		clp[LPFC_CFG_MAX_LUN].a_current = LPFC_DFT_MAX_LUN;
-	}
-	host->max_lun = clp[LPFC_CFG_MAX_LUN].a_current;
+	len += snprintf(buf + len, PAGE_SIZE-len, "Portname: ");
+	memcpy (&name[0], &phba->fc_portname, sizeof (struct lpfc_name));
+	len += snprintf(buf + len, PAGE_SIZE-len,
+			"%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
+			name[0], name[1], name[2], name[3], name[4], name[5],
+			name[6], name[7]);
 
-	/* Adapter ID - tell midlayer not to reserve an ID for us */
-	host->this_id = -1;
+	len += snprintf(buf + len, PAGE_SIZE-len, "   Nodename: ");
+	memcpy (&name[0], &phba->fc_nodename, sizeof (struct lpfc_name));
+	len += snprintf(buf + len, PAGE_SIZE-len,
+			"%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
+			name[0], name[1], name[2], name[3], name[4], name[5],
+			name[6], name[7]);
 
-	/*
-	 * Setup the scsi timeout handler with a
-	 * timeout value = greater of (2*RATOV, 5).
-	 */
-	timeout = (phba->fc_ratov << 1) > 5 ? (phba->fc_ratov << 1) : 5;
-	phba->scsi_tmo_data.timeObj = &phba->scsi_tmofunc;
-	phba->scsi_tmo_data.phba = phba;
-	phba->scsi_tmo_data.clData1 = (unsigned long)timeout;
-	init_timer(&phba->scsi_tmofunc);
-	phba->scsi_tmofunc.function = lpfc_scsi_timeout_handler;
-	phba->scsi_tmofunc.expires = jiffies + HZ * timeout;
-	phba->scsi_tmofunc.data = (unsigned long)&phba->scsi_tmo_data;
-	list_add(&phba->scsi_tmo_data.listLink, &phba->timerList);
-	add_timer(&phba->scsi_tmofunc);
+	switch (phba->hba_state) {
+	case LPFC_INIT_START:
+	case LPFC_INIT_MBX_CMDS:
+	case LPFC_LINK_DOWN:
+		len += snprintf(buf + len, PAGE_SIZE-len, "\n\nLink Down\n");
+		break;
+	case LPFC_LINK_UP:
+	case LPFC_LOCAL_CFG_LINK:
+		len += snprintf(buf + len, PAGE_SIZE-len, "\n\nLink Up\n");
+		break;
+	case LPFC_FLOGI:
+	case LPFC_FABRIC_CFG_LINK:
+	case LPFC_NS_REG:
+	case LPFC_NS_QRY:
+	case LPFC_BUILD_DISC_LIST:
+	case LPFC_DISC_AUTH:
+	case LPFC_CLEAR_LA:
+		len += snprintf(buf + len, PAGE_SIZE-len,
+				"\n\nLink Up - Discovery\n");
+		break;
+	case LPFC_HBA_READY:
+		len += snprintf(buf + len, PAGE_SIZE-len,
+				"\n\nLink Up - Ready:\n");
+		len += snprintf(buf + len, PAGE_SIZE-len, "   PortID 0x%x\n",
+				phba->fc_myDID);
+		if (phba->fc_topology == TOPOLOGY_LOOP) {
+			if (phba->fc_flag & FC_PUBLIC_LOOP)
+				len += snprintf(buf + len, PAGE_SIZE-len,
+						"   Public Loop\n");
+			else
+				len += snprintf(buf + len, PAGE_SIZE-len,
+						"   Private Loop\n");
+		} else {
+			if (phba->fc_flag & FC_FABRIC)
+				len += snprintf(buf + len, PAGE_SIZE-len,
+						"   Fabric\n");
+			else
+				len += snprintf(buf + len, PAGE_SIZE-len,
+						"   Point-2-Point\n");
+		}
 
+		if (phba->fc_linkspeed == LA_2GHZ_LINK)
+			len += snprintf(buf + len, PAGE_SIZE-len,
+					"   Current speed 2G\n");
+		else
+			len += snprintf(buf + len, PAGE_SIZE-len,
+					"   Current speed 1G\n\n");
 
-	/*
-	 * Starting with 2.4.0 kernel, Linux can support commands longer
-	 * than 12 bytes. However, scsi_register() always sets it to 12.
-	 * For it to be useful to the midlayer, we have to set it here.
-	 */
-	host->max_cmd_len = 16;
+		/* Loop through the list of mapped nodes and dump the known node
+		   information. */
+		list_for_each_entry(ndlp, &phba->fc_nlpmap_list, nlp_listp) {
+			if (ndlp->nlp_state == NLP_STE_MAPPED_NODE){
+				len += snprintf(buf + len, PAGE_SIZE -len,
+						"lpfc%dt%02x DID %06x WWPN ",
+						ndlp->nlp_Target->pHba->brd_no,
+						ndlp->nlp_sid, ndlp->nlp_DID);
 
-	/*
-	 * Queue depths per lun
-	 */
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,6)
-	host->transportt = lpfc_transport_template;
-#endif
-	host->hostdata[0] = (unsigned long)phba;
-	pci_set_drvdata(pdev, host);
-	if (scsi_add_host(host, &pdev->dev))
-		goto error_6;
-	device_create_file(&(pdev->dev), &dev_attr_info);
-	device_create_file(&(pdev->dev), &dev_attr_serialnum);
-	device_create_file(&(pdev->dev), &dev_attr_fwrev);
-	device_create_file(&(pdev->dev), &dev_attr_hdw);
-	device_create_file(&(pdev->dev), &dev_attr_lpfc_log_verbose);
-	device_create_file(&(pdev->dev), &dev_attr_lpfc_tgt_queue_depth);
-	device_create_file(&(pdev->dev), &dev_attr_lpfc_lun_queue_depth);
-	device_create_file(&(pdev->dev), &dev_attr_lpfc_extra_io_tmo);
-	device_create_file(&(pdev->dev), &dev_attr_lpfc_no_device_delay);
-	device_create_file(&(pdev->dev), &dev_attr_lpfc_linkdown_tmo);
-	device_create_file(&(pdev->dev), &dev_attr_lpfc_nodev_holdio);
-	device_create_file(&(pdev->dev), &dev_attr_lpfc_delay_rsp_err);
-	device_create_file(&(pdev->dev), &dev_attr_lpfc_check_cond_err);
-	device_create_file(&(pdev->dev), &dev_attr_lpfc_nodev_tmo);
-	device_create_file(&(pdev->dev),
-			   &dev_attr_lpfc_dqfull_throttle_up_time);
-	device_create_file(&(pdev->dev), &dev_attr_lpfc_dqfull_throttle_up_inc);
-	device_create_file(&(pdev->dev), &dev_attr_lpfc_max_lun);
-	device_create_file(&(pdev->dev), &dev_attr_lpfc_lun_skip);
-	device_create_file(&(pdev->dev), &dev_attr_lpfc_automap);
-	device_create_file(&(pdev->dev), &dev_attr_lpfc_fcp_class);
-	device_create_file(&(pdev->dev), &dev_attr_lpfc_use_adisc);
-	device_create_file(&(pdev->dev), &dev_attr_lpfc_network_on);
-	device_create_file(&(pdev->dev), &dev_attr_lpfc_post_ip_buf);
-	device_create_file(&(pdev->dev), &dev_attr_lpfc_xmt_que_size);
-	device_create_file(&(pdev->dev), &dev_attr_lpfc_ip_class);
-	device_create_file(&(pdev->dev), &dev_attr_lpfc_ack0);
-	device_create_file(&(pdev->dev), &dev_attr_lpfc_topology);
-	device_create_file(&(pdev->dev), &dev_attr_lpfc_scan_down);
-	device_create_file(&(pdev->dev), &dev_attr_lpfc_link_speed);
-	device_create_file(&(pdev->dev), &dev_attr_lpfc_cr_delay);
-	device_create_file(&(pdev->dev), &dev_attr_lpfc_cr_count);
-	device_create_file(&(pdev->dev), &dev_attr_lpfc_fdmi_on);
-	device_create_file(&(pdev->dev), &dev_attr_lpfc_fcp_bind_method);
-	device_create_file(&(pdev->dev), &dev_attr_lpfc_discovery_threads);
-	device_create_file(&(pdev->dev), &dev_attr_lpfc_scsi_req_tmo);
-	device_create_file(&(pdev->dev), &dev_attr_lpfc_max_target);
-	scsi_scan_host(host);
-	goto out;
-error_6:
-	scsi_host_put(host);
-error_5:
-	lpfc_sli_hba_down(phba);
+				/* A Fibre Channel node or port name is 8 octets
+				 * long and delimited by colons.
+				 */
+				memcpy (&name[0], &ndlp->nlp_portname,
+					sizeof (struct lpfc_name));
+				len += snprintf(buf + len, PAGE_SIZE-len,
+						"%02x:%02x:%02x:%02x:%02x:%02x:"
+						"%02x:%02x",
+						name[0], name[1], name[2],
+						name[3], name[4], name[5],
+						name[6], name[7]);
 
-error_3:
-	/* Stop any timers that were started during this attach. */
-	spin_lock_irqsave(&(phba->drvrlock), iflag);
-	while (!list_empty(&phba->timerList)) {
-		clkData = (struct clk_data *)(phba->timerList.next);
-		if (clkData) {
-			cur_timer = clkData->timeObj;
-			del_timer_sync(cur_timer);
-			cur_timer->function = 0;
-			list_del(&clkData->listLink);
+				len += snprintf(buf + len, PAGE_SIZE-len,
+						" WWNN ");
+				memcpy (&name[0], &ndlp->nlp_nodename,
+					sizeof (struct lpfc_name));
+				len += snprintf(buf + len, PAGE_SIZE-len,
+						"%02x:%02x:%02x:%02x:%02x:%02x:"
+						"%02x:%02x\n",
+						name[0], name[1], name[2],
+						name[3], name[4], name[5],
+						name[6], name[7]);
+
+			}
+			if(PAGE_SIZE - len < 90)
+				break;
 		}
+
+		if(&ndlp->nlp_listp != &phba->fc_nlpmap_list)
+			len += snprintf(buf+len, PAGE_SIZE-len, "...\n");
+
 	}
-	spin_unlock_irqrestore(&(phba->drvrlock), iflag);
+	return (len);
+}
 
-	/* Kill the kernel thread for this host */
-	if (phba->dpc_pid >= 0) {
-		phba->dpc_kill = 1;
-		wmb();
-		kill_proc(phba->dpc_pid, SIGHUP, 1);
-		wait_for_completion(&phba->dpc_exiting);
+static int
+lpfc_reset_bus_handler(struct scsi_cmnd *cmnd)
+{
+	struct lpfc_hba *phba;
+	LPFC_SCSI_BUF_t *lpfc_cmd;
+	unsigned long iflag;
+	int rc, tgt, lun;
+
+	phba = (struct lpfc_hba *) cmnd->device->host->hostdata[0];
+	tgt = cmnd->device->id;
+	lun = cmnd->device->lun;
+
+	rc = 0;
+	if ((lpfc_cmd = lpfc_get_scsi_buf(phba, GFP_ATOMIC))) {
+		rc = lpfc_scsi_hba_reset(phba, lpfc_cmd);
+		spin_lock_irqsave(&(phba->drvrlock), iflag);
+		lpfc_free_scsi_buf(lpfc_cmd);
+		spin_unlock_irqrestore(&(phba->drvrlock), iflag);
 	}
 
-	free_irq(phba->pcidev->irq, phba);
-	lpfc_mem_free(phba);
-	lpfc_unmemmap(phba);
-	lpfc_num_hba--;
+	/* SCSI layer issued Bus Reset */
+	lpfc_printf_log(phba,
+		        KERN_ERR,
+		        LOG_FCP,
+		        "0714 SCSI layer issued Bus Reset Data: x%x x%x x%x",
+		        tgt, lun, rc);
 
-error_2:
-	kfree(phba->config);
 
-error_1:
-	/* Remove from list of active HBAs */
-	list_del_init(&phba->hba_list);
-	kfree(phba);
+	return (SUCCESS);
+
+}				/* lpfc_reset_bus_handler */
+
+static int
+lpfc_slave_alloc(struct scsi_device *scsi_devs)
+{
+	struct lpfc_hba *phba;
+	struct lpfc_lun *lunp;
 
-error:
-	/* Any error in the attach routine will end up here.  Set the return
- 	 * code to 1 and exit.
+	/* Store the lun pointer in the scsi_device hostdata pointer provided
+	 * the driver has already discovered the target/lun id.  Undiscovered
+	 * target/lun information is handled dynamically via the driver's 
+	 * discovery state machine.
 	 */
-	rc = -1;
-	pci_release_regions(pdev);
-	pci_disable_device(pdev);	
-out:	
-	return rc;
+	phba = (struct lpfc_hba *) scsi_devs->host->hostdata[0];
+	lunp = lpfc_find_lun(phba, scsi_devs->id, scsi_devs->lun, 1);
+	if (lunp) {
+		scsi_devs->hostdata = lunp;
+	}
+		
+	/* Always return success from this routine since the driver handles
+	 * target/lun discovery and resource allocation dynamically.  Failing
+	 * this call causes the midlayer to dump an error message per target 
+	 * based on conflicting information from the driver.  Although the 
+	 * driver could allocate a target instance here for each scsi device 
+	 * passed by the midlayer, a TUR or SCSI_INQUIRY issued to
+	 * queuecommand would just fail and result in lpfc_slave_destroy freeing
+	 * the memory.  Returning success avoids this situation.
+	 */
+	return 0;
 }
 
-static void __devexit
-lpfc_pci_remove_one(struct pci_dev *pdev)
+static int
+lpfc_slave_configure(struct scsi_device *sdev)
 {
-	struct Scsi_Host *host;
-	struct lpfc_hba        * phba;
-	LPFC_SLI_t       * psli;
-	struct clk_data  * clkData;
-	unsigned long      iflag;
-	struct timer_list *cur_timer;
+	struct lpfc_hba *phba = (struct lpfc_hba *)sdev->host->hostdata[0];
+	struct lpfc_cfgparam *clp = &phba->config[0];
 
-	host = pci_get_drvdata(pdev);
-	phba = (struct lpfc_hba *) host->hostdata[0];
+	if (sdev->tagged_supported) {
+		sdev->current_tag = 0;
+		sdev->queue_depth = clp[LPFC_CFG_DFT_LUN_Q_DEPTH].a_current;
+	} else
+		sdev->queue_depth = 16;
 
-	device_remove_file(&(pdev->dev), &dev_attr_info);
-	device_remove_file(&(pdev->dev), &dev_attr_serialnum);
-	device_remove_file(&(pdev->dev), &dev_attr_fwrev);
-	device_remove_file(&(pdev->dev), &dev_attr_hdw);
-	device_remove_file(&(pdev->dev), &dev_attr_lpfc_log_verbose);
-	device_remove_file(&(pdev->dev), &dev_attr_lpfc_tgt_queue_depth);
-	device_remove_file(&(pdev->dev), &dev_attr_lpfc_lun_queue_depth);
-	device_remove_file(&(pdev->dev), &dev_attr_lpfc_extra_io_tmo);
-	device_remove_file(&(pdev->dev), &dev_attr_lpfc_no_device_delay);
-	device_remove_file(&(pdev->dev), &dev_attr_lpfc_linkdown_tmo);
-	device_remove_file(&(pdev->dev), &dev_attr_lpfc_nodev_holdio);
-	device_remove_file(&(pdev->dev), &dev_attr_lpfc_delay_rsp_err);
-	device_remove_file(&(pdev->dev), &dev_attr_lpfc_check_cond_err);
-	device_remove_file(&(pdev->dev), &dev_attr_lpfc_nodev_tmo);
-	device_remove_file(&(pdev->dev),
-			   &dev_attr_lpfc_dqfull_throttle_up_time);
-	device_remove_file(&(pdev->dev), &dev_attr_lpfc_dqfull_throttle_up_inc);
-	device_remove_file(&(pdev->dev), &dev_attr_lpfc_max_lun);
-	device_remove_file(&(pdev->dev), &dev_attr_lpfc_lun_skip);
-	device_remove_file(&(pdev->dev), &dev_attr_lpfc_automap);
-	device_remove_file(&(pdev->dev), &dev_attr_lpfc_fcp_class);
-	device_remove_file(&(pdev->dev), &dev_attr_lpfc_use_adisc);
-	device_remove_file(&(pdev->dev), &dev_attr_lpfc_network_on);
-	device_remove_file(&(pdev->dev), &dev_attr_lpfc_post_ip_buf);
-	device_remove_file(&(pdev->dev), &dev_attr_lpfc_xmt_que_size);
-	device_remove_file(&(pdev->dev), &dev_attr_lpfc_ip_class);
-	device_remove_file(&(pdev->dev), &dev_attr_lpfc_ack0);
-	device_remove_file(&(pdev->dev), &dev_attr_lpfc_topology);
-	device_remove_file(&(pdev->dev), &dev_attr_lpfc_scan_down);
-	device_remove_file(&(pdev->dev), &dev_attr_lpfc_link_speed);
-	device_remove_file(&(pdev->dev), &dev_attr_lpfc_cr_delay);
-	device_remove_file(&(pdev->dev), &dev_attr_lpfc_cr_count);
-	device_remove_file(&(pdev->dev), &dev_attr_lpfc_fdmi_on);
-	device_remove_file(&(pdev->dev), &dev_attr_lpfc_fcp_bind_method);
-	device_remove_file(&(pdev->dev), &dev_attr_lpfc_discovery_threads);
-	device_remove_file(&(pdev->dev), &dev_attr_lpfc_scsi_req_tmo);
-	device_remove_file(&(pdev->dev), &dev_attr_lpfc_max_target);
+	return 0;
+}
 
-	/*
-	 *  detach the board
+static void
+lpfc_slave_destroy(struct scsi_device *sdev)
+{
+        /*
+	 * Since the driver allocated no memory in lpfc_slave_alloc,
+	 * no resources have to be released here.  Just set the hostdata
+	 * pointer to 0 provided the driver previously set it to a 
+	 * nonzero value.
 	 */
+	sdev->hostdata = NULL;
+}
 
-	psli = &phba->sli;
+static int
+lpfc_biosparam(struct scsi_device *sdev, struct block_device *bdev,
+		sector_t capacity, int ip[])
+{
+	int size = capacity;
 
-	spin_lock_irqsave(&(phba->drvrlock), iflag);
-	while (!list_empty(&phba->timerList)) {
-		clkData = (struct clk_data *)(phba->timerList.next);
-		if (clkData) {
-			cur_timer = clkData->timeObj;
-			del_timer_sync(cur_timer);
-			cur_timer->function = 0;
-			list_del(&clkData->listLink);
-		}
+	ip[0] = 64;
+	ip[1] = 32;
+	ip[2] = size >> 11;
+	if (ip[2] > 1024) {
+		ip[0] = 255;
+		ip[1] = 63;
+		ip[2] = size / (ip[0] * ip[1]);
+#ifndef FC_EXTEND_TRANS_A
+		if (ip[2] > 1023)
+			ip[2] = 1023;
+#endif
 	}
-	
-	spin_unlock_irqrestore(&(phba->drvrlock), iflag);
+	return (0);
+}
 
-	/* Kill the kernel thread for this host */
-	if (phba->dpc_pid >= 0) {
-		phba->dpc_kill = 1;
-		wmb();
-		kill_proc(phba->dpc_pid, SIGHUP, 1);
-		wait_for_completion(&phba->dpc_exiting);
-	}
+static struct scsi_host_template driver_template = {
+	.module			= THIS_MODULE,
+	.name			= LPFC_DRIVER_NAME,
+	.info			= lpfc_info,
+	.queuecommand		= lpfc_queuecommand,
+	.eh_abort_handler	= lpfc_abort_handler,
+	.eh_device_reset_handler= lpfc_reset_lun_handler,
+	.eh_bus_reset_handler	= lpfc_reset_bus_handler,
+	.slave_alloc		= lpfc_slave_alloc,
+	.slave_configure	= lpfc_slave_configure,
+	.slave_destroy		= lpfc_slave_destroy,
+	.bios_param		= lpfc_biosparam,
+	.proc_info		= lpfc_proc_info,
+	.proc_name		= LPFC_DRIVER_NAME,
+	.can_queue		= LPFC_DFT_HBA_Q_DEPTH,
+	.this_id		= -1,
+	.sg_tablesize		= SG_ALL,
+	.cmd_per_lun		= 30,
+	.use_clustering		= ENABLE_CLUSTERING,
+};
 
+void
+lpfc_setup_slim_access(struct lpfc_hba * arg)
+{
+	struct lpfc_hba *phba;
 
-	scsi_remove_host(phba->host);
-	scsi_host_put(phba->host);
+	phba = (struct lpfc_hba *) arg;
+	phba->MBslimaddr = phba->slim_memmap_p;
+	phba->HAregaddr = (uint32_t *) (phba->ctrl_regs_memmap_p) +
+		HA_REG_OFFSET;
+	phba->HCregaddr = (uint32_t *) (phba->ctrl_regs_memmap_p) +
+		HC_REG_OFFSET;
+	phba->CAregaddr = (uint32_t *) (phba->ctrl_regs_memmap_p) +
+		CA_REG_OFFSET;
+	phba->HSregaddr = (uint32_t *) (phba->ctrl_regs_memmap_p) +
+		HS_REG_OFFSET;
+	return;
+}
 
-	/*
-	 * Bring down the SLI Layer. This step disable all interrupts,
-	 * clears the rings, discards all mailbox commands, and resets
-	 * the HBA.
-	 */
-	lpfc_sli_hba_down(phba);	
 
-	/* Release the irq reservation */
-	free_irq(phba->pcidev->irq, phba);
+uint32_t
+lpfc_intr_prep(struct lpfc_hba * phba)
+{
+	uint32_t ha_copy;
 
-	if (phba->pcidev) {
-		pci_release_regions(phba->pcidev);
-		pci_disable_device(phba->pcidev);
+	/* Ignore all interrupts during initialization. */
+	if (phba->hba_state < LPFC_LINK_DOWN) {
+		return (0);
 	}
 
-	lpfc_cleanup(phba, 0);
-	lpfc_scsi_free(phba);
-	lpfc_mem_free(phba);
-	lpfc_unmemmap(phba);
-
-
-	if (phba->config)
-		kfree(phba->config);
-
-	/* Remove from list of active HBAs */
-	list_del(&phba->hba_list);
-
-	kfree(phba);
+	/* Read host attention register to determine interrupt source */
+	ha_copy = readl(phba->HAregaddr);
 
-	lpfc_num_hba--;
+	/* Clear Attention Sources, except ERATT (to preserve status) & LATT
+	 *    (ha_copy & ~(HA_ERATT | HA_LATT));
+	 */
+	writel((ha_copy & ~(HA_LATT | HA_ERATT)), phba->HAregaddr);
+	return (ha_copy);
+}				/* lpfc_intr_prep */
 
-	pci_set_drvdata(pdev, 0);
 
-	return;
-}
+static int
+lpfc_sli_setup(struct lpfc_hba * phba)
+{
+	int i, totiocb;
+	LPFC_SLI_t *psli;
+	LPFC_RING_INIT_t *pring;
+	struct lpfc_cfgparam *clp;
 
+	psli = &phba->sli;
+	psli->sliinit.num_rings = MAX_CONFIGURED_RINGS;
+	psli->fcp_ring = LPFC_FCP_RING;
+	psli->next_ring = LPFC_FCP_NEXT_RING;
+	psli->ip_ring = LPFC_IP_RING;
 
-/*
- * Retrieve lpfc_hba * matching instance (board no)
- * If found return lpfc_hba *
- * If not found return NULL
- */
-struct lpfc_hba *
-lpfc_get_phba_by_inst(int inst)
-{
-	struct lpfc_hba * phba;
-	int    found = 0;
+	clp = &phba->config[0];
 
-	phba = NULL;
-	list_for_each_entry(phba, &lpfc_hba_list, hba_list) {
-		if (phba->brd_no == inst) {
-			found = 1;
+	totiocb = 0;
+	for (i = 0; i < psli->sliinit.num_rings; i++) {
+		pring = &psli->sliinit.ringinit[i];
+		switch (i) {
+		case LPFC_FCP_RING:	/* ring 0 - FCP */
+			/* numCiocb and numRiocb are used in config_port */
+			pring->numCiocb = SLI2_IOCB_CMD_R0_ENTRIES;
+			pring->numRiocb = SLI2_IOCB_RSP_R0_ENTRIES;
+			pring->numCiocb += SLI2_IOCB_CMD_R1XTRA_ENTRIES;
+			pring->numRiocb += SLI2_IOCB_RSP_R1XTRA_ENTRIES;
+			pring->numCiocb += SLI2_IOCB_CMD_R3XTRA_ENTRIES;
+			pring->numRiocb += SLI2_IOCB_RSP_R3XTRA_ENTRIES;
+			pring->iotag_ctr = 0;
+			pring->iotag_max =
+			    (clp[LPFC_CFG_DFT_HBA_Q_DEPTH].a_current * 2);
+			pring->fast_iotag = pring->iotag_max;
+			pring->num_mask = 0;
+			break;
+		case LPFC_IP_RING:	/* ring 1 - IP */
+			/* numCiocb and numRiocb are used in config_port */
+			pring->numCiocb = SLI2_IOCB_CMD_R1_ENTRIES;
+			pring->numRiocb = SLI2_IOCB_RSP_R1_ENTRIES;
+			pring->num_mask = 0;
+			pring->iotag_ctr = 0;
+			pring->iotag_max = clp[LPFC_CFG_XMT_Q_SIZE].a_current;
+			pring->fast_iotag = 0;
+			break;
+		case LPFC_ELS_RING:	/* ring 2 - ELS / CT */
+			/* numCiocb and numRiocb are used in config_port */
+			pring->numCiocb = SLI2_IOCB_CMD_R2_ENTRIES;
+			pring->numRiocb = SLI2_IOCB_RSP_R2_ENTRIES;
+			pring->fast_iotag = 0;
+			pring->iotag_ctr = 0;
+			pring->iotag_max = 4096;
+			pring->num_mask = 4;
+			pring->prt[0].profile = 0;	/* Mask 0 */
+			pring->prt[0].rctl = FC_ELS_REQ;
+			pring->prt[0].type = FC_ELS_DATA;
+			pring->prt[0].lpfc_sli_rcv_unsol_event =
+			    lpfc_els_unsol_event;
+			pring->prt[1].profile = 0;	/* Mask 1 */
+			pring->prt[1].rctl = FC_ELS_RSP;
+			pring->prt[1].type = FC_ELS_DATA;
+			pring->prt[1].lpfc_sli_rcv_unsol_event =
+			    lpfc_els_unsol_event;
+			pring->prt[2].profile = 0;	/* Mask 2 */
+			/* NameServer Inquiry */
+			pring->prt[2].rctl = FC_UNSOL_CTL;
+			/* NameServer */
+			pring->prt[2].type = FC_COMMON_TRANSPORT_ULP;
+			pring->prt[2].lpfc_sli_rcv_unsol_event =
+			    lpfc_ct_unsol_event;
+			pring->prt[3].profile = 0;	/* Mask 3 */
+			/* NameServer response */
+			pring->prt[3].rctl = FC_SOL_CTL;
+			/* NameServer */
+			pring->prt[3].type = FC_COMMON_TRANSPORT_ULP;
+			pring->prt[3].lpfc_sli_rcv_unsol_event =
+			    lpfc_ct_unsol_event;
 			break;
 		}
+		totiocb += (pring->numCiocb + pring->numRiocb);
 	}
-	
-	if (!found)
-		return(NULL);
-	else
-		return(phba);
-	
-}
-
-const char *
-lpfc_info(struct Scsi_Host *host)
-{
-	struct lpfc_hba    *phba = (struct lpfc_hba *) host->hostdata[0];
-	int len;
-	static char  lpfcinfobuf[128];
-	
-	memset(lpfcinfobuf,0,128);
-	if(phba && phba->pcidev){
-	        lpfc_get_hba_model_desc(phba, 0, lpfcinfobuf);
-		len = strlen(lpfcinfobuf);	
-		snprintf(lpfcinfobuf + len,
-			128-len,
-	       		" on PCI bus %02x device %02x irq %d",
-			phba->pcidev->bus->number,
-		 	phba->pcidev->devfn,
-			phba->pcidev->irq);
+	if (totiocb > MAX_SLI2_IOCB) {
+		/* Too many cmd / rsp ring entries in SLI2 SLIM */
+		lpfc_printf_log(phba,
+			        KERN_ERR,
+			        LOG_INIT,
+			        "0462 Too many cmd / rsp ring entries in SLI2 SLIM Data: x%x x%x",
+			        totiocb, MAX_SLI2_IOCB);
 	}
-	return lpfcinfobuf;
+
+#ifdef USE_HGP_HOST_SLIM
+	psli->sliinit.sli_flag = LPFC_HGP_HOSTSLIM;
+#else
+	psli->sliinit.sli_flag = 0;
+#endif
+
+	return (0);
 }
 
-int
-lpfc_proc_info(struct Scsi_Host *host,
-	       char *buf, char **start, off_t offset, int count, int rw)
+irqreturn_t
+lpfc_intr_handler(int irq, void *dev_id, struct pt_regs * regs)
 {
+	struct lpfc_hba *phba;
+	int intr_status;
 
-	struct lpfc_hba *phba = NULL;
-	struct pci_dev *pdev;
-	char fwrev[32];
-	lpfc_vpd_t *vp;
-	struct lpfc_nodelist *ndlp;
-	int  i, j, incr;
-	char hdw[9];
-	int len = 0, found = 0;
-	
-	/* Sufficient bytes to hold a port or node name. */
-	uint8_t name[sizeof (struct lpfc_name)];
-
-	/* If rw = 0, then read info
-	 * If rw = 1, then write info (NYI)
+	/*
+	 * Get the driver's phba structure from the dev_id and
+	 * assume the HBA is not interrupting.
 	 */
-	if (rw)
-		return -EINVAL;
-
-
-	list_for_each_entry(phba, &lpfc_hba_list, hba_list) {
-		if (phba == (struct lpfc_hba *)host->hostdata[0]) {
-			found = 1;
-			break;
-		}
-	}
+	phba = (struct lpfc_hba *) dev_id;
 
-	if (!found) {
-		return sprintf(buf, "Cannot find adapter for requested host "
-			       "number.\n");
+	if (phba) {
+		/* Call SLI to handle the interrupt event. */
+		intr_status = lpfc_sli_intr(phba);
+		if (intr_status == 0)
+			return IRQ_HANDLED;
 	}
 
-	vp = &phba->vpd;
-	pdev = phba->pcidev;
-
-	len += snprintf(buf, PAGE_SIZE, LPFC_MODULE_DESC "\n");
-
-	len += snprintf(buf + len, PAGE_SIZE-len, "%s\n",
-			lpfc_info(phba->host));
-
-	len += snprintf(buf + len, PAGE_SIZE-len, "SerialNum: %s\n",
-			phba->SerialNumber);
-
-	lpfc_decode_firmware_rev(phba, fwrev, 1);
-	len += snprintf(buf + len, PAGE_SIZE-len, "Firmware Version: %s\n",
-			fwrev);
+	return IRQ_NONE;
 
-	len += snprintf(buf + len, PAGE_SIZE-len, "Hdw: ");
-	/* Convert JEDEC ID to ascii for hardware version */
-	incr = vp->rev.biuRev;
-	for (i = 0; i < 8; i++) {
-		j = (incr & 0xf);
-		if (j <= 9)
-			hdw[7 - i] = (char)((uint8_t) 0x30 + (uint8_t) j);
-		else
-			hdw[7 - i] =
-			    (char)((uint8_t) 0x61 + (uint8_t) (j - 10));
-		incr = (incr >> 4);
-	}
-	hdw[8] = 0;
-	len += snprintf(buf + len, PAGE_SIZE-len, hdw);
+} /* lpfc_intr_handler */
 
-	len += snprintf(buf + len, PAGE_SIZE-len, "\nVendorId: 0x%x\n",
-		       ((((uint32_t) pdev->device) << 16) |
-			(uint32_t) (pdev->vendor)));
+static int
+lpfc_get_bind_type(struct lpfc_hba * phba)
+{
+	int bind_type;
+	struct lpfc_cfgparam *clp;
 
-	/* A Fibre Channel node or port name is 8 octets long and delimited by
-	 * colons.
-	 */
-	len += snprintf(buf + len, PAGE_SIZE-len, "Portname: ");
-	memcpy (&name[0], &phba->fc_portname, sizeof (struct lpfc_name));
-	len += snprintf(buf + len, PAGE_SIZE-len,
-			"%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
-			name[0], name[1], name[2], name[3], name[4], name[5],
-			name[6], name[7]);
+	clp = &phba->config[0];
 
-	len += snprintf(buf + len, PAGE_SIZE-len, "   Nodename: ");
-	memcpy (&name[0], &phba->fc_nodename, sizeof (struct lpfc_name));
-	len += snprintf(buf + len, PAGE_SIZE-len,
-			"%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
-			name[0], name[1], name[2], name[3], name[4], name[5],
-			name[6], name[7]);
+	bind_type = clp[LPFC_CFG_BINDMETHOD].a_current;
 
-	switch (phba->hba_state) {
-	case LPFC_INIT_START:
-	case LPFC_INIT_MBX_CMDS:
-	case LPFC_LINK_DOWN:
-		len += snprintf(buf + len, PAGE_SIZE-len, "\n\nLink Down\n");
+	switch (bind_type) {
+	case 1:
+		phba->fcp_mapping = FCP_SEED_WWNN;
 		break;
-	case LPFC_LINK_UP:
-	case LPFC_LOCAL_CFG_LINK:
-		len += snprintf(buf + len, PAGE_SIZE-len, "\n\nLink Up\n");
+
+	case 2:
+		phba->fcp_mapping = FCP_SEED_WWPN;
 		break;
-	case LPFC_FLOGI:
-	case LPFC_FABRIC_CFG_LINK:
-	case LPFC_NS_REG:
-	case LPFC_NS_QRY:
-	case LPFC_BUILD_DISC_LIST:
-	case LPFC_DISC_AUTH:
-	case LPFC_CLEAR_LA:
-		len += snprintf(buf + len, PAGE_SIZE-len,
-				"\n\nLink Up - Discovery\n");
+
+	case 3:
+		phba->fcp_mapping = FCP_SEED_DID;
 		break;
-	case LPFC_HBA_READY:
-		len += snprintf(buf + len, PAGE_SIZE-len,
-				"\n\nLink Up - Ready:\n");
-		len += snprintf(buf + len, PAGE_SIZE-len, "   PortID 0x%x\n",
-				phba->fc_myDID);
-		if (phba->fc_topology == TOPOLOGY_LOOP) {
-			if (phba->fc_flag & FC_PUBLIC_LOOP)
-				len += snprintf(buf + len, PAGE_SIZE-len,
-						"   Public Loop\n");
-			else
-				len += snprintf(buf + len, PAGE_SIZE-len,
-						"   Private Loop\n");
-		} else {
-			if (phba->fc_flag & FC_FABRIC)
-				len += snprintf(buf + len, PAGE_SIZE-len,
-						"   Fabric\n");
-			else
-				len += snprintf(buf + len, PAGE_SIZE-len,
-						"   Point-2-Point\n");
-		}
 
-		if (phba->fc_linkspeed == LA_2GHZ_LINK)
-			len += snprintf(buf + len, PAGE_SIZE-len,
-					"   Current speed 2G\n");
-		else
-			len += snprintf(buf + len, PAGE_SIZE-len,
-					"   Current speed 1G\n\n");
+	case 4:
+		phba->fcp_mapping = FCP_SEED_DID;
+		break;
+	}
 
-		/* Loop through the list of mapped nodes and dump the known node
-		   information. */
-		list_for_each_entry(ndlp, &phba->fc_nlpmap_list, nlp_listp) {
-			if (ndlp->nlp_state == NLP_STE_MAPPED_NODE){
-				len += snprintf(buf + len, PAGE_SIZE -len,
-						"lpfc%dt%02x DID %06x WWPN ",
-						ndlp->nlp_Target->pHba->brd_no,
-						ndlp->nlp_sid, ndlp->nlp_DID);
+	return 0;
+}
 
-				/* A Fibre Channel node or port name is 8 octets
-				 * long and delimited by colons.
-				 */
-				memcpy (&name[0], &ndlp->nlp_portname,
-					sizeof (struct lpfc_name));
-				len += snprintf(buf + len, PAGE_SIZE-len,
-						"%02x:%02x:%02x:%02x:%02x:%02x:"
-						"%02x:%02x",
-						name[0], name[1], name[2],
-						name[3], name[4], name[5],
-						name[6], name[7]);
+static int
+lpfc_bind_wwpn(struct lpfc_hba * phba, char **arrayp, u_int cnt)
+{
+	uint8_t *datap, *np;
+	struct lpfc_bindlist *blp;
+	struct lpfc_name pn;
+	int i, entry, lpfc_num, rstatus;
+	unsigned int sum;
 
-				len += snprintf(buf + len, PAGE_SIZE-len,
-						" WWNN ");
-				memcpy (&name[0], &ndlp->nlp_nodename,
-					sizeof (struct lpfc_name));
-				len += snprintf(buf + len, PAGE_SIZE-len,
-						"%02x:%02x:%02x:%02x:%02x:%02x:"
-						"%02x:%02x\n",
-						name[0], name[1], name[2],
-						name[3], name[4], name[5],
-						name[6], name[7]);
+	phba->fcp_mapping = FCP_SEED_WWPN;
+	np = (uint8_t *) & pn;
 
-			}
-			if(PAGE_SIZE - len < 90)
+	for (entry = 0; entry < cnt; entry++) {
+		datap = (uint8_t *) arrayp[entry];
+		if (datap == 0)
+			break;
+		/* Determined the number of ASC hex chars in WWNN & WWPN */
+		for (i = 0; i < FC_MAX_WW_NN_PN_STRING; i++) {
+			if (!isxdigit(datap[i]))
 				break;
 		}
+		if ((rstatus = lpfc_parse_binding_entry(phba, datap, np,
+						i, sizeof (struct lpfc_name),
+						LPFC_BIND_WW_NN_PN, &sum, entry,
+						&lpfc_num)) > 0) {
+			if (rstatus == LPFC_SYNTAX_OK_BUT_NOT_THIS_BRD)
+				continue;
+
+			/* For syntax error code definitions see
+			   LPFC_SYNTAX_ERR_ defines. */
+			/* WWPN binding entry <num>: Syntax error code <code> */
+			lpfc_printf_log(phba,
+					KERN_ERR,
+					LOG_INIT,
+					"0430 WWPN binding entry %d: Syntax error code %d",
+					entry, rstatus);
+			goto out;
+		}
 
-		if(&ndlp->nlp_listp != &phba->fc_nlpmap_list)
-			len += snprintf(buf+len, PAGE_SIZE-len, "...\n");
+		/* Loop through all BINDLIST entries and find
+		 * the next available entry.
+		 */
+		if ((blp = mempool_alloc(phba->bind_mem_pool, GFP_ATOMIC))
+		    == 0) {
+			/* WWPN binding entry: node table full */
+			lpfc_printf_log(phba,
+					KERN_ERR,
+					LOG_INIT,
+					"0432 WWPN binding entry: node table full");
+			goto out;
+		}
+		memset(blp, 0, sizeof (struct lpfc_bindlist));
+		blp->nlp_bind_type = FCP_SEED_WWPN;
+		blp->nlp_sid = (sum & 0xff);
+		memcpy(&blp->nlp_portname, (uint8_t *) & pn,
+		       sizeof (struct lpfc_name));
 
+		lpfc_nlp_bind(phba, blp);
+
+out:
+		np = (uint8_t *) & pn;
 	}
-	return (len);
-}
+	return (0);
+}				/* lpfc_bind_wwpn */
 
-static int
-lpfc_reset_bus_handler(struct scsi_cmnd *cmnd)
+	static int
+lpfc_bind_wwnn(struct lpfc_hba * phba, char **arrayp, u_int cnt)
 {
-	struct lpfc_hba *phba;
-	LPFC_SCSI_BUF_t *lpfc_cmd;
-	unsigned long iflag;
-	int rc, tgt, lun;
+	uint8_t *datap, *np;
+	struct lpfc_bindlist *blp;
+	struct lpfc_name pn;
+	int i, entry, lpfc_num, rstatus;
+	unsigned int sum;
 
-	phba = (struct lpfc_hba *) cmnd->device->host->hostdata[0];
-	tgt = cmnd->device->id;
-	lun = cmnd->device->lun;
+	phba->fcp_mapping = FCP_SEED_WWNN;
+	np = (uint8_t *) & pn;
 
-	rc = 0;
-	if ((lpfc_cmd = lpfc_get_scsi_buf(phba, GFP_ATOMIC))) {
-		rc = lpfc_scsi_hba_reset(phba, lpfc_cmd);
-		spin_lock_irqsave(&(phba->drvrlock), iflag);
-		lpfc_free_scsi_buf(lpfc_cmd);
-		spin_unlock_irqrestore(&(phba->drvrlock), iflag);
-	}
-
-	/* SCSI layer issued Bus Reset */
-	lpfc_printf_log(phba,
-		        KERN_ERR,
-		        LOG_FCP,
-		        "0714 SCSI layer issued Bus Reset Data: x%x x%x x%x",
-		        tgt, lun, rc);
-
-
-	return (SUCCESS);
-
-}				/* lpfc_reset_bus_handler */
-
-int
-lpfc_slave_alloc(struct scsi_device *scsi_devs)
-{
-	struct lpfc_hba *phba;
-	struct lpfc_lun *lunp;
-
-	/* Store the lun pointer in the scsi_device hostdata pointer provided
-	 * the driver has already discovered the target/lun id.  Undiscovered
-	 * target/lun information is handled dynamically via the driver's 
-	 * discovery state machine.
-	 */
-	phba = (struct lpfc_hba *) scsi_devs->host->hostdata[0];
-	lunp = lpfc_find_lun(phba, scsi_devs->id, scsi_devs->lun, 1);
-	if (lunp) {
-		scsi_devs->hostdata = lunp;
-	}
-		
-	/* Always return success from this routine since the driver handles
-	 * target/lun discovery and resource allocation dynamically.  Failing
-	 * this call causes the midlayer to dump an error message per target 
-	 * based on conflicting information from the driver.  Although the 
-	 * driver could allocate a target instance here for each scsi device 
-	 * passed by the midlayer, a TUR or SCSI_INQUIRY issued to
-	 * queuecommand would just fail and result in lpfc_slave_destroy freeing
-	 * the memory.  Returning success avoids this situation.
-	 */
-	return 0;
-}
-
-int
-lpfc_slave_configure(struct scsi_device *scsi_devs)
-{
-	struct lpfc_hba *phba = (struct lpfc_hba *)scsi_devs->host->hostdata[0];
-	lpfc_device_queue_depth(phba, scsi_devs);
-	return 0;
-}
-
-void
-lpfc_slave_destroy(struct scsi_device *scsi_devs)
-{
-        /* Since the driver allocated no memory in lpfc_slave_alloc,
-	 * no resources have to be released here.  Just set the hostdata
-	 * pointer to 0 provided the driver previously set it to a 
-	 * nonzero value.
-	 */
-	if (scsi_devs->hostdata != 0) {
-		scsi_devs->hostdata = 0;
-	}
-
-	return;
-}
-
-static int
-lpfc_device_queue_depth(struct lpfc_hba * phba, struct scsi_device *device)
-{
-	struct lpfc_cfgparam *clp;
-
-	clp = &phba->config[0];
+	for (entry = 0; entry < cnt; entry++) {
+		datap = (uint8_t *) arrayp[entry];
+		if (datap == 0)
+			break;
+		/* Determined the number of ASC hex chars in WWNN & WWPN */
+		for (i = 0; i < FC_MAX_WW_NN_PN_STRING; i++) {
+			if (!isxdigit(datap[i]))
+				break;
+		}
+		if ((rstatus = lpfc_parse_binding_entry(phba, datap, np,
+						i, sizeof (struct lpfc_name),
+						LPFC_BIND_WW_NN_PN, &sum, entry,
+						&lpfc_num)) > 0) {
+			if (rstatus == LPFC_SYNTAX_OK_BUT_NOT_THIS_BRD) {
+				continue;
+			}
 
-	if (device->tagged_supported) {
-		device->current_tag = 0;
-		device->queue_depth = clp[LPFC_CFG_DFT_LUN_Q_DEPTH].a_current;
-	} else {
-		device->queue_depth = 16;
-	}
-	return (device->queue_depth);
-}
+			/* For syntax error code definitions see
+			   LPFC_SYNTAX_ERR_ defines. */
+			/* WWNN binding entry <num>: Syntax error code <code> */
+			lpfc_printf_log(phba,
+					KERN_ERR,
+					LOG_INIT,
+					"0431 WWNN binding entry %d: Syntax error code %d",
+					entry, rstatus);
+			goto out;
+		}
 
+		/* Loop through all BINDLIST entries and find
+		 * the next available entry.
+		 */
+		if ((blp = mempool_alloc(phba->bind_mem_pool, GFP_ATOMIC))
+		    == 0) {
+			/* WWNN binding entry: node table full */
+			lpfc_printf_log(phba,
+					KERN_ERR,
+					LOG_INIT,
+					"0433 WWNN binding entry: node table full");
+			goto out;
+		}
+		memset(blp, 0, sizeof (struct lpfc_bindlist));
+		blp->nlp_bind_type = FCP_SEED_WWNN;
+		blp->nlp_sid = (sum & 0xff);
+		memcpy(&blp->nlp_nodename, (uint8_t *) & pn,
+		       sizeof (struct lpfc_name));
+		lpfc_nlp_bind(phba, blp);
 
+out:
+		np = (uint8_t *) & pn;
+	}			/* for loop */
+	return (0);
+}				/* lpfc_bind_wwnn */
 
 static int
-lpfc_memmap(struct lpfc_hba * phba)
+lpfc_bind_did(struct lpfc_hba * phba, char **arrayp, u_int cnt)
 {
-	unsigned long bar0map_len, bar2map_len;
+	uint8_t *datap, *np;
+	struct lpfc_bindlist *blp;
+	D_ID ndid;
+	int i, entry, lpfc_num, rstatus;
+	unsigned int sum;
 
-	if (phba->pcidev == 0)
-		return (1);
+	phba->fcp_mapping = FCP_SEED_DID;
+	ndid.un.word = 0;
+	np = (uint8_t *) & ndid.un.word;
 
-	/* Configure DMA attributes. */
-	if (dma_set_mask(&phba->pcidev->dev, 0xffffffffffffffffULL)) {
-		if (dma_set_mask(&phba->pcidev->dev, 0xffffffffULL)) {
-			return (1);
+	for (entry = 0; entry < cnt; entry++) {
+		datap = (uint8_t *) arrayp[entry];
+		if (datap == 0)
+			break;
+		/* Determined the number of ASC hex chars in DID */
+		for (i = 0; i < FC_MAX_DID_STRING; i++) {
+			if (!isxdigit(datap[i]))
+				break;
 		}
-	}
-
-	/*
-	 * Get the physical address of Bar0 and Bar2 and the number of bytes
-	 * required by each mapping.
-	 */
-	phba->pci_bar0_map = pci_resource_start(phba->pcidev, 0);
-	bar0map_len        = pci_resource_len(phba->pcidev, 0);
-	
-	phba->pci_bar2_map = pci_resource_start(phba->pcidev, 2);
-	bar2map_len        = pci_resource_len(phba->pcidev, 2);
+		if ((rstatus = lpfc_parse_binding_entry(phba, datap, np,
+							i, sizeof (D_ID),
+							LPFC_BIND_DID, &sum,
+							entry,
+							&lpfc_num)) > 0) {
+			if (rstatus == LPFC_SYNTAX_OK_BUT_NOT_THIS_BRD)
+				continue;
 
-	/* Map HBA SLIM and Control Registers to a kernel virtual address. */
-	phba->slim_memmap_p      = ioremap(phba->pci_bar0_map, bar0map_len);
-	phba->ctrl_regs_memmap_p = ioremap(phba->pci_bar2_map, bar2map_len);
+			/* For syntax error code definitions see
+			   LPFC_SYNTAX_ERR_ defines. */
+			/* DID binding entry <num>: Syntax error code <code> */
+			lpfc_printf_log(phba,
+				        KERN_ERR,
+				        LOG_INIT,
+				        "0434 DID binding entry %d: Syntax error code %d",
+				        entry, rstatus);
+			goto out;
+		}
 
-	/* Setup SLI2 interface */
-	if (phba->slim2p.virt == 0) {
-		/*
-		 * Allocate memory for SLI-2 structures
+		/* Loop through all BINDLIST entries and find
+		 * the next available entry.
 		 */
-		phba->slim2p.virt = dma_alloc_coherent(&phba->pcidev->dev,
-						       sizeof (SLI2_SLIM_t),
-						       &(phba->slim2p.phys),
-						       GFP_ATOMIC);
-		
-		if (phba->slim2p.virt == 0) {
-			/* Cleanup adapter SLIM and Control Register
-			   mappings. */
-			iounmap(phba->ctrl_regs_memmap_p);
-			iounmap(phba->slim_memmap_p);
-			return (1);
+		if ((blp = mempool_alloc(phba->bind_mem_pool, GFP_ATOMIC))
+		    == 0) {
+			/* DID binding entry: node table full */
+			lpfc_printf_log(phba,
+				        KERN_ERR,
+				        LOG_INIT,
+				        "0435 DID binding entry: node table full");
+			goto out;
 		}
+		memset(blp, 0, sizeof (struct lpfc_bindlist));
+		blp->nlp_bind_type = FCP_SEED_DID;
+		blp->nlp_sid = (sum & 0xff);
+		blp->nlp_DID = be32_to_cpu(ndid.un.word);
 
-		/* The SLIM2 size is stored in the next field */
-		phba->slim_size = sizeof (SLI2_SLIM_t);
-		memset((char *)phba->slim2p.virt, 0, sizeof (SLI2_SLIM_t));
+		lpfc_nlp_bind(phba, blp);
+
+out:
+
+		np = (uint8_t *) & ndid.un.word;
 	}
 	return (0);
 }
 
-static int
-lpfc_unmemmap(struct lpfc_hba * phba)
+static void
+lpfc_wakeup_event(struct lpfc_hba * phba, fcEVTHDR_t * ep)
 {
-	struct pci_dev *pdev;
-
-	pdev = phba->pcidev;
-
-	/* unmap adapter SLIM and Control Registers */
-	iounmap(phba->ctrl_regs_memmap_p);
-	iounmap(phba->slim_memmap_p);
-	
-	/* Free resources associated with SLI2 interface */
-	if (phba->slim2p.virt) {
-
-		
-		dma_free_coherent(&pdev->dev,
-				  phba->slim_size,
-				  phba->slim2p.virt,
-				  phba->slim2p.phys);
-
+	ep->e_mode &= ~E_SLEEPING_MODE;
+	switch (ep->e_mask) {
+	case FC_REG_LINK_EVENT:
+		wake_up_interruptible(&phba->linkevtwq);
+		break;
+	case FC_REG_RSCN_EVENT:
+		wake_up_interruptible(&phba->rscnevtwq);
+		break;
+	case FC_REG_CT_EVENT:
+		wake_up_interruptible(&phba->ctevtwq);
+		break;
 	}
-	return (0);
+	return;
 }
 
+
 static int
-lpfc_pcimap(struct lpfc_hba * phba)
+lpfc_bind_setup(struct lpfc_hba * phba)
 {
-	struct pci_dev *pdev;
-	int ret_val;
+	struct lpfc_cfgparam *clp;
+	char **arrayp = 0;
+	u_int cnt = 0;
 
 	/*
-	 * PCI for board
-	 */
-	pdev = phba->pcidev;
-	if (!pdev)
-		return (1);
-
-	/* The LPFC HBAs are bus-master capable.  Call the kernel and have this
-	 * functionality enabled.  Note that setting pci bus master also sets
-	 * the latency value as well.  Also turn on MWI so that the cache line
-	 * size is set to match the host pci bridge.
+	 * Check if there are any WWNN / scsid bindings
 	 */
+	clp = &phba->config[0];
 
-	pci_set_master (pdev);
-	ret_val = pci_set_mwi (pdev);
-	if (ret_val != 0) {
-		/* The mwi set operation failed.  This is not a fatal error
-		 * so don't return an error.
-		 */
-	}
+	lpfc_get_bind_type(phba);
 
-	return (0);
-}
-
-void
-lpfc_setup_slim_access(struct lpfc_hba * arg)
-{
-	struct lpfc_hba *phba;
-
-	phba = (struct lpfc_hba *) arg;
-	phba->MBslimaddr = phba->slim_memmap_p;
-	phba->HAregaddr = (uint32_t *) (phba->ctrl_regs_memmap_p) +
-		HA_REG_OFFSET;
-	phba->HCregaddr = (uint32_t *) (phba->ctrl_regs_memmap_p) +
-		HC_REG_OFFSET;
-	phba->CAregaddr = (uint32_t *) (phba->ctrl_regs_memmap_p) +
-		CA_REG_OFFSET;
-	phba->HSregaddr = (uint32_t *) (phba->ctrl_regs_memmap_p) +
-		HS_REG_OFFSET;
-	return;
-}
-
-
-uint32_t
-lpfc_intr_prep(struct lpfc_hba * phba)
-{
-	uint32_t ha_copy;
-
-	/* Ignore all interrupts during initialization. */
-	if (phba->hba_state < LPFC_LINK_DOWN) {
-		return (0);
-	}
-
-	/* Read host attention register to determine interrupt source */
-	ha_copy = readl(phba->HAregaddr);
-
-	/* Clear Attention Sources, except ERATT (to preserve status) & LATT
-	 *    (ha_copy & ~(HA_ERATT | HA_LATT));
-	 */
-	writel((ha_copy & ~(HA_LATT | HA_ERATT)), phba->HAregaddr);
-	return (ha_copy);
-}				/* lpfc_intr_prep */
-
-
-static int
-lpfc_sli_setup(struct lpfc_hba * phba)
-{
-	int i, totiocb;
-	LPFC_SLI_t *psli;
-	LPFC_RING_INIT_t *pring;
-	struct lpfc_cfgparam *clp;
-
-	psli = &phba->sli;
-	psli->sliinit.num_rings = MAX_CONFIGURED_RINGS;
-	psli->fcp_ring = LPFC_FCP_RING;
-	psli->next_ring = LPFC_FCP_NEXT_RING;
-	psli->ip_ring = LPFC_IP_RING;
-
-	clp = &phba->config[0];
-
-	totiocb = 0;
-	for (i = 0; i < psli->sliinit.num_rings; i++) {
-		pring = &psli->sliinit.ringinit[i];
-		switch (i) {
-		case LPFC_FCP_RING:	/* ring 0 - FCP */
-			/* numCiocb and numRiocb are used in config_port */
-			pring->numCiocb = SLI2_IOCB_CMD_R0_ENTRIES;
-			pring->numRiocb = SLI2_IOCB_RSP_R0_ENTRIES;
-			pring->numCiocb += SLI2_IOCB_CMD_R1XTRA_ENTRIES;
-			pring->numRiocb += SLI2_IOCB_RSP_R1XTRA_ENTRIES;
-			pring->numCiocb += SLI2_IOCB_CMD_R3XTRA_ENTRIES;
-			pring->numRiocb += SLI2_IOCB_RSP_R3XTRA_ENTRIES;
-			pring->iotag_ctr = 0;
-			pring->iotag_max =
-			    (clp[LPFC_CFG_DFT_HBA_Q_DEPTH].a_current * 2);
-			pring->fast_iotag = pring->iotag_max;
-			pring->num_mask = 0;
-			break;
-		case LPFC_IP_RING:	/* ring 1 - IP */
-			/* numCiocb and numRiocb are used in config_port */
-			pring->numCiocb = SLI2_IOCB_CMD_R1_ENTRIES;
-			pring->numRiocb = SLI2_IOCB_RSP_R1_ENTRIES;
-			pring->num_mask = 0;
-			pring->iotag_ctr = 0;
-			pring->iotag_max = clp[LPFC_CFG_XMT_Q_SIZE].a_current;
-			pring->fast_iotag = 0;
-			break;
-		case LPFC_ELS_RING:	/* ring 2 - ELS / CT */
-			/* numCiocb and numRiocb are used in config_port */
-			pring->numCiocb = SLI2_IOCB_CMD_R2_ENTRIES;
-			pring->numRiocb = SLI2_IOCB_RSP_R2_ENTRIES;
-			pring->fast_iotag = 0;
-			pring->iotag_ctr = 0;
-			pring->iotag_max = 4096;
-			pring->num_mask = 4;
-			pring->prt[0].profile = 0;	/* Mask 0 */
-			pring->prt[0].rctl = FC_ELS_REQ;
-			pring->prt[0].type = FC_ELS_DATA;
-			pring->prt[0].lpfc_sli_rcv_unsol_event =
-			    lpfc_els_unsol_event;
-			pring->prt[1].profile = 0;	/* Mask 1 */
-			pring->prt[1].rctl = FC_ELS_RSP;
-			pring->prt[1].type = FC_ELS_DATA;
-			pring->prt[1].lpfc_sli_rcv_unsol_event =
-			    lpfc_els_unsol_event;
-			pring->prt[2].profile = 0;	/* Mask 2 */
-			/* NameServer Inquiry */
-			pring->prt[2].rctl = FC_UNSOL_CTL;
-			/* NameServer */
-			pring->prt[2].type = FC_COMMON_TRANSPORT_ULP;
-			pring->prt[2].lpfc_sli_rcv_unsol_event =
-			    lpfc_ct_unsol_event;
-			pring->prt[3].profile = 0;	/* Mask 3 */
-			/* NameServer response */
-			pring->prt[3].rctl = FC_SOL_CTL;
-			/* NameServer */
-			pring->prt[3].type = FC_COMMON_TRANSPORT_ULP;
-			pring->prt[3].lpfc_sli_rcv_unsol_event =
-			    lpfc_ct_unsol_event;
-			break;
-		}
-		totiocb += (pring->numCiocb + pring->numRiocb);
-	}
-	if (totiocb > MAX_SLI2_IOCB) {
-		/* Too many cmd / rsp ring entries in SLI2 SLIM */
-		lpfc_printf_log(phba,
-			        KERN_ERR,
-			        LOG_INIT,
-			        "0462 Too many cmd / rsp ring entries in SLI2 SLIM Data: x%x x%x",
-			        totiocb, MAX_SLI2_IOCB);
-	}
-
-#ifdef USE_HGP_HOST_SLIM
-	psli->sliinit.sli_flag = LPFC_HGP_HOSTSLIM;
-#else
-	psli->sliinit.sli_flag = 0;
-#endif
-
-	return (0);
-}
-
-irqreturn_t
-lpfc_intr_handler(int irq, void *dev_id, struct pt_regs * regs)
-{
-	struct lpfc_hba *phba;
-	int intr_status;
-
-	/*
-	 * Get the driver's phba structure from the dev_id and
-	 * assume the HBA is not interrupting.
-	 */
-	phba = (struct lpfc_hba *) dev_id;
-
-	if (phba) {
-		/* Call SLI to handle the interrupt event. */
-		intr_status = lpfc_sli_intr(phba);
-		if (intr_status == 0)
-			return IRQ_HANDLED;
-	}
-
-	return IRQ_NONE;
-
-} /* lpfc_intr_handler */
-
-static int
-lpfc_bind_setup(struct lpfc_hba * phba)
-{
-	struct lpfc_cfgparam *clp;
-	char **arrayp = 0;
-	u_int cnt = 0;
-
-	/*
-	 * Check if there are any WWNN / scsid bindings
-	 */
-	clp = &phba->config[0];
-
-	lpfc_get_bind_type(phba);
-
-	switch (phba->fcp_mapping) {
-	case FCP_SEED_WWNN:
-		arrayp = lpfc_fcp_bind_WWNN;
-		cnt = 0;
-		while (arrayp[cnt] != 0)
-			cnt++;
-		if (cnt && (*arrayp != 0)) {
-			lpfc_bind_wwnn(phba, arrayp, cnt);
-		}
-		break;
+	switch (phba->fcp_mapping) {
+	case FCP_SEED_WWNN:
+		arrayp = lpfc_fcp_bind_WWNN;
+		cnt = 0;
+		while (arrayp[cnt] != 0)
+			cnt++;
+		if (cnt && (*arrayp != 0)) {
+			lpfc_bind_wwnn(phba, arrayp, cnt);
+		}
+		break;
 
 	case FCP_SEED_WWPN:
 		arrayp = lpfc_fcp_bind_WWPN;
@@ -1436,67 +1035,197 @@ lpfc_bind_setup(struct lpfc_hba * phba)
 	return (0);
 }
 
-/******************************************************************************
-* Function name : lpfc_config_setup
-*
-* Description   : Called from attach to setup configuration parameters for
-*                 adapter
-*                 The goal of this routine is to fill in all the a_current
-*                 members of the CfgParam structure for all configuration
-*                 parameters.
-* Example:
-* clp[LPFC_CFG_XXX].a_current = (uint32_t)value;
-* value might be a define, a global variable, clp[LPFC_CFG_XXX].a_default,
-* or some other enviroment specific way of initializing config parameters.
-******************************************************************************/
-
-static int
-lpfc_config_setup(struct lpfc_hba * phba)
+static uint32_t
+lpfc_get_cfgtkval(const char *string, const char *tk)
 {
-	struct lpfc_cfgparam *clp;
-	LPFC_SLI_t *psli;
-	int i;
-	int brd;
-
-	clp = &phba->config[0];
-	psli = &phba->sli;
-	brd = phba->brd_no;
-
-	/*
-	 * Read the configuration parameters. Also set to default if
-	 * parameter value is out of allowed range.
-	 */
-	for (i = 0; i < LPFC_TOTAL_NUM_OF_CFG_PARAM; i++) {
-		clp[i].a_current = lpfc_get_cfgparam(brd, i);
+	int i=0,ibound,tklen,val=-1;
+	ibound = strlen(string);
+	tklen = strlen(tk);
+	while(i < ibound && strnicmp(string+i,tk,tklen) !=0)
+		i++;
+	i += tklen;
+	if( i < ibound){
+		if (strnicmp(string+i,"0x",2)==0)
+			sscanf(string+i,"0x%x",&val);
+		else
+			sscanf(string+i,"%d",&val);
+	}
+	return val;
+}
 
-		if (i == LPFC_CFG_DFT_HBA_Q_DEPTH)
-			continue;
+static uint32_t
+lpfc_get_cfgnamedparam(int brd, const char *param)
+{
+	uint32_t val = (uint32_t)-1;
+	uint32_t defval = (uint32_t)-1;
+	char tk[16];
+	snprintf(tk, 16, "lpfc:");
+	defval = lpfc_get_cfgtkval(param, tk);
+	snprintf(tk, 16, "lpfc%d:", brd);
+	val = lpfc_get_cfgtkval(param, tk);
+	if( val == -1 && defval != -1)
+		val = defval;
+	return val;
+}
 
-		if ((clp[i].a_current >= clp[i].a_low) &&
-		    (clp[i].a_current <= clp[i].a_hi)) {
-			/* we continue if the range check is satisfied
-			 * however LPFC_CFG_TOPOLOGY has holes and both
-			 * LPFC_CFG_FCP_CLASS AND LPFC_CFG_IP_CLASS need
-			 * to readjusted iff they satisfy the range check
-			 */
-			if (i == LPFC_CFG_TOPOLOGY) {
-				/* odd values 1,3,5 are out */
-				if (!(clp[i].a_current & 1))
-					continue;
-			} else if ((i == LPFC_CFG_FCP_CLASS)
-				   || (i == LPFC_CFG_IP_CLASS)) {
-				switch (clp[i].a_current) {
-				case 2:
-					/* CLASS2 = 1 */
-					clp[i].a_current = CLASS2;
-					break;
-				case 3:
-					/* CLASS3 = 2 */
-					clp[i].a_current = CLASS3;
-					break;
-				}
-				continue;
-			} else
+static uint32_t
+lpfc_get_cfgparam(int brd, int param)
+{
+	uint32_t value = (uint32_t)-1;
+	
+	switch (param) {
+	case LPFC_CFG_LOG_VERBOSE:	/* log-verbose */
+		value = lpfc_get_cfgnamedparam(brd, lpfc_log_verbose);
+		break;
+	case LPFC_CFG_AUTOMAP:	/* automap */
+		value = lpfc_get_cfgnamedparam(brd, lpfc_automap);
+		break;
+	case LPFC_CFG_BINDMETHOD:	/* bind-method */
+		value = lpfc_get_cfgnamedparam(brd, lpfc_fcp_bind_method);
+		break;
+	case LPFC_CFG_CR_DELAY:	/* cr_delay */
+		value = lpfc_get_cfgnamedparam(brd, lpfc_cr_delay);
+		break;
+	case LPFC_CFG_CR_COUNT:	/* cr_count */
+		value = lpfc_get_cfgnamedparam(brd, lpfc_cr_count);
+		break;
+	case LPFC_CFG_DFT_TGT_Q_DEPTH:	/* tgt_queue_depth */
+		value = lpfc_get_cfgnamedparam(brd, lpfc_tgt_queue_depth);
+		break;
+	case LPFC_CFG_DFT_LUN_Q_DEPTH:	/* lun_queue_depth */
+		value = lpfc_get_cfgnamedparam(brd, lpfc_lun_queue_depth);
+		break;
+	case LPFC_CFG_EXTRA_IO_TMO:	/* fcpfabric-tmo */
+		value = lpfc_get_cfgnamedparam(brd, lpfc_extra_io_tmo);
+		break;
+	case LPFC_CFG_FCP_CLASS:	/* fcp-class */
+		value = lpfc_get_cfgnamedparam(brd, lpfc_fcp_class);
+		break;
+	case LPFC_CFG_USE_ADISC:	/* use-adisc */
+		value = lpfc_get_cfgnamedparam(brd, lpfc_use_adisc);
+		break;
+	case LPFC_CFG_NO_DEVICE_DELAY:	/* no-device-delay */
+		value = lpfc_get_cfgnamedparam(brd, lpfc_no_device_delay);
+		break;
+	case LPFC_CFG_NETWORK_ON:	/* network-on */
+		value = lpfc_get_cfgnamedparam(brd, lpfc_network_on);
+		break;
+	case LPFC_CFG_POST_IP_BUF:	/* post-ip-buf */
+		value = lpfc_get_cfgnamedparam(brd, lpfc_post_ip_buf);
+		break;
+	case LPFC_CFG_XMT_Q_SIZE:	/* xmt-que-size */
+		value = lpfc_get_cfgnamedparam(brd, lpfc_xmt_que_size);
+		break;
+	case LPFC_CFG_IP_CLASS:	/* ip-class */
+		value = lpfc_get_cfgnamedparam(brd, lpfc_ip_class);
+		break;
+	case LPFC_CFG_ACK0:	/* ack0 */
+		value = lpfc_get_cfgnamedparam(brd, lpfc_ack0);
+		break;
+	case LPFC_CFG_TOPOLOGY:	/* topology */
+		value = lpfc_get_cfgnamedparam(brd, lpfc_topology);
+		break;
+	case LPFC_CFG_SCAN_DOWN:	/* scan-down */
+		value = lpfc_get_cfgnamedparam(brd, lpfc_scan_down);
+		break;
+	case LPFC_CFG_LINKDOWN_TMO:	/* linkdown-tmo */
+		value = lpfc_get_cfgnamedparam(brd, lpfc_linkdown_tmo);
+		break;
+	case LPFC_CFG_HOLDIO:	/* nodev-holdio */
+		value = lpfc_get_cfgnamedparam(brd, lpfc_nodev_holdio);
+		break;
+	case LPFC_CFG_DELAY_RSP_ERR:	/* delay-rsp-err */
+		value = lpfc_get_cfgnamedparam(brd, lpfc_delay_rsp_err);
+		break;
+	case LPFC_CFG_CHK_COND_ERR:	/* check-cond-err */
+		value = lpfc_get_cfgnamedparam(brd, lpfc_check_cond_err);
+		break;
+	case LPFC_CFG_NODEV_TMO:	/* nodev-tmo */
+		value = lpfc_get_cfgnamedparam(brd, lpfc_nodev_tmo);
+		break;
+	case LPFC_CFG_LINK_SPEED:	/* link-speed */
+		value = lpfc_get_cfgnamedparam(brd, lpfc_link_speed);
+		break;
+	case LPFC_CFG_DQFULL_THROTTLE_UP_TIME:	/* dqfull-throttle-up-time */
+		value = lpfc_get_cfgnamedparam(brd,
+					       lpfc_dqfull_throttle_up_time);
+		break;
+	case LPFC_CFG_DQFULL_THROTTLE_UP_INC:	/* dqfull-throttle-up-inc */
+		value = lpfc_get_cfgnamedparam(brd,
+					       lpfc_dqfull_throttle_up_inc);
+		break;
+	case LPFC_CFG_FDMI_ON:	/* fdmi-on */
+		value = lpfc_get_cfgnamedparam(brd, lpfc_fdmi_on);
+		break;
+	case LPFC_CFG_MAX_LUN:	/* max-lun */
+		value = lpfc_get_cfgnamedparam(brd, lpfc_max_lun);
+		break;
+	case LPFC_CFG_DISC_THREADS:	/* discovery-threads */
+		value = lpfc_get_cfgnamedparam(brd, lpfc_discovery_threads);
+		break;
+	case LPFC_CFG_MAX_TARGET:	/* max-target */
+		value = lpfc_get_cfgnamedparam(brd, lpfc_max_target);
+		break;
+	case LPFC_CFG_SCSI_REQ_TMO:	/* scsi-req-tmo */
+		value = lpfc_get_cfgnamedparam(brd, lpfc_scsi_req_tmo);
+		break;
+	case LPFC_CFG_LUN_SKIP:	/* lun-skip */
+		value = lpfc_get_cfgnamedparam(brd, lpfc_lun_skip);
+		break;
+	default:
+		break;
+	}
+
+	return (value);
+}
+
+static int
+lpfc_config_setup(struct lpfc_hba * phba)
+{
+	struct lpfc_cfgparam *clp;
+	LPFC_SLI_t *psli;
+	int i;
+	int brd;
+
+	clp = &phba->config[0];
+	psli = &phba->sli;
+	brd = phba->brd_no;
+
+	/*
+	 * Read the configuration parameters. Also set to default if
+	 * parameter value is out of allowed range.
+	 */
+	for (i = 0; i < LPFC_TOTAL_NUM_OF_CFG_PARAM; i++) {
+		clp[i].a_current = lpfc_get_cfgparam(brd, i);
+
+		if (i == LPFC_CFG_DFT_HBA_Q_DEPTH)
+			continue;
+
+		if ((clp[i].a_current >= clp[i].a_low) &&
+		    (clp[i].a_current <= clp[i].a_hi)) {
+			/* we continue if the range check is satisfied
+			 * however LPFC_CFG_TOPOLOGY has holes and both
+			 * LPFC_CFG_FCP_CLASS AND LPFC_CFG_IP_CLASS need
+			 * to readjusted iff they satisfy the range check
+			 */
+			if (i == LPFC_CFG_TOPOLOGY) {
+				/* odd values 1,3,5 are out */
+				if (!(clp[i].a_current & 1))
+					continue;
+			} else if ((i == LPFC_CFG_FCP_CLASS)
+				   || (i == LPFC_CFG_IP_CLASS)) {
+				switch (clp[i].a_current) {
+				case 2:
+					/* CLASS2 = 1 */
+					clp[i].a_current = CLASS2;
+					break;
+				case 3:
+					/* CLASS3 = 2 */
+					clp[i].a_current = CLASS3;
+					break;
+				}
+				continue;
+			} else
 				continue;
 		}
 
@@ -1543,288 +1272,42 @@ lpfc_config_setup(struct lpfc_hba * phba
 	return (0);
 }
 
-static int
-lpfc_bind_wwpn(struct lpfc_hba * phba, char **arrayp, u_int cnt)
+int
+lpfc_put_event(struct lpfc_hba * phba,
+	      uint32_t evcode, uint32_t evdata0, void *evdata1, void *evdata2)
 {
-	uint8_t *datap, *np;
-	struct lpfc_bindlist *blp;
-	struct lpfc_name pn;
-	int i, entry, lpfc_num, rstatus;
-	unsigned int sum;
+	fcEVT_t *ep;
+	fcEVT_t *oep;
+	fcEVTHDR_t *ehp = 0;
+	int found;
+	DMABUF_t *mp;
+	void *fstype;
+	struct lpfc_sli_ct_request *ctp;
 
-	phba->fcp_mapping = FCP_SEED_WWPN;
-	np = (uint8_t *) & pn;
+	ehp = (fcEVTHDR_t *) phba->fc_evt_head;
+	fstype = 0;
+	switch (evcode) {
+	case FC_REG_CT_EVENT:
+		mp = (DMABUF_t *) evdata1;
+		ctp = (struct lpfc_sli_ct_request *) mp->virt;
+		fstype = (void *)(ulong) (ctp->FsType);
+		break;
+	}
 
-	for (entry = 0; entry < cnt; entry++) {
-		datap = (uint8_t *) arrayp[entry];
-		if (datap == 0)
+	while (ehp) {
+		if ((ehp->e_mask == evcode) && (ehp->e_type == fstype))
 			break;
-		/* Determined the number of ASC hex chars in WWNN & WWPN */
-		for (i = 0; i < FC_MAX_WW_NN_PN_STRING; i++) {
-			if (!isxdigit(datap[i]))
-				break;
-		}
-		if ((rstatus = lpfc_parse_binding_entry(phba, datap, np,
-						i, sizeof (struct lpfc_name),
-						LPFC_BIND_WW_NN_PN, &sum, entry,
-						&lpfc_num)) > 0) {
-			if (rstatus == LPFC_SYNTAX_OK_BUT_NOT_THIS_BRD)
-				continue;
-
-			/* For syntax error code definitions see
-			   LPFC_SYNTAX_ERR_ defines. */
-			/* WWPN binding entry <num>: Syntax error code <code> */
-			lpfc_printf_log(phba,
-					KERN_ERR,
-					LOG_INIT,
-					"0430 WWPN binding entry %d: Syntax error code %d",
-					entry, rstatus);
-			goto out;
-		}
-
-		/* Loop through all BINDLIST entries and find
-		 * the next available entry.
-		 */
-		if ((blp = mempool_alloc(phba->bind_mem_pool, GFP_ATOMIC))
-		    == 0) {
-			/* WWPN binding entry: node table full */
-			lpfc_printf_log(phba,
-					KERN_ERR,
-					LOG_INIT,
-					"0432 WWPN binding entry: node table full");
-			goto out;
-		}
-		memset(blp, 0, sizeof (struct lpfc_bindlist));
-		blp->nlp_bind_type = FCP_SEED_WWPN;
-		blp->nlp_sid = (sum & 0xff);
-		memcpy(&blp->nlp_portname, (uint8_t *) & pn,
-		       sizeof (struct lpfc_name));
-
-		lpfc_nlp_bind(phba, blp);
-
-out:
-		np = (uint8_t *) & pn;
+		
+		ehp = (fcEVTHDR_t *) ehp->e_next_header;
 	}
-	return (0);
-}				/* lpfc_bind_wwpn */
 
-static int
-lpfc_get_bind_type(struct lpfc_hba * phba)
-{
-	int bind_type;
-	struct lpfc_cfgparam *clp;
-
-	clp = &phba->config[0];
+	if (!ehp) {
+		return (0);
+	}
 
-	bind_type = clp[LPFC_CFG_BINDMETHOD].a_current;
-
-	switch (bind_type) {
-	case 1:
-		phba->fcp_mapping = FCP_SEED_WWNN;
-		break;
-
-	case 2:
-		phba->fcp_mapping = FCP_SEED_WWPN;
-		break;
-
-	case 3:
-		phba->fcp_mapping = FCP_SEED_DID;
-		break;
-
-	case 4:
-		phba->fcp_mapping = FCP_SEED_DID;
-		break;
-	}
-
-	return 0;
-}
-
-static int
-lpfc_bind_wwnn(struct lpfc_hba * phba, char **arrayp, u_int cnt)
-{
-	uint8_t *datap, *np;
-	struct lpfc_bindlist *blp;
-	struct lpfc_name pn;
-	int i, entry, lpfc_num, rstatus;
-	unsigned int sum;
-
-	phba->fcp_mapping = FCP_SEED_WWNN;
-	np = (uint8_t *) & pn;
-
-	for (entry = 0; entry < cnt; entry++) {
-		datap = (uint8_t *) arrayp[entry];
-		if (datap == 0)
-			break;
-		/* Determined the number of ASC hex chars in WWNN & WWPN */
-		for (i = 0; i < FC_MAX_WW_NN_PN_STRING; i++) {
-			if (!isxdigit(datap[i]))
-				break;
-		}
-		if ((rstatus = lpfc_parse_binding_entry(phba, datap, np,
-						i, sizeof (struct lpfc_name),
-						LPFC_BIND_WW_NN_PN, &sum, entry,
-						&lpfc_num)) > 0) {
-			if (rstatus == LPFC_SYNTAX_OK_BUT_NOT_THIS_BRD) {
-				continue;
-			}
-
-			/* For syntax error code definitions see
-			   LPFC_SYNTAX_ERR_ defines. */
-			/* WWNN binding entry <num>: Syntax error code <code> */
-			lpfc_printf_log(phba,
-					KERN_ERR,
-					LOG_INIT,
-					"0431 WWNN binding entry %d: Syntax error code %d",
-					entry, rstatus);
-			goto out;
-		}
-
-		/* Loop through all BINDLIST entries and find
-		 * the next available entry.
-		 */
-		if ((blp = mempool_alloc(phba->bind_mem_pool, GFP_ATOMIC))
-		    == 0) {
-			/* WWNN binding entry: node table full */
-			lpfc_printf_log(phba,
-					KERN_ERR,
-					LOG_INIT,
-					"0433 WWNN binding entry: node table full");
-			goto out;
-		}
-		memset(blp, 0, sizeof (struct lpfc_bindlist));
-		blp->nlp_bind_type = FCP_SEED_WWNN;
-		blp->nlp_sid = (sum & 0xff);
-		memcpy(&blp->nlp_nodename, (uint8_t *) & pn,
-		       sizeof (struct lpfc_name));
-		lpfc_nlp_bind(phba, blp);
-
-out:
-		np = (uint8_t *) & pn;
-	}			/* for loop */
-	return (0);
-}				/* lpfc_bind_wwnn */
-
-static int
-lpfc_bind_did(struct lpfc_hba * phba, char **arrayp, u_int cnt)
-{
-	uint8_t *datap, *np;
-	struct lpfc_bindlist *blp;
-	D_ID ndid;
-	int i, entry, lpfc_num, rstatus;
-	unsigned int sum;
-
-	phba->fcp_mapping = FCP_SEED_DID;
-	ndid.un.word = 0;
-	np = (uint8_t *) & ndid.un.word;
-
-	for (entry = 0; entry < cnt; entry++) {
-		datap = (uint8_t *) arrayp[entry];
-		if (datap == 0)
-			break;
-		/* Determined the number of ASC hex chars in DID */
-		for (i = 0; i < FC_MAX_DID_STRING; i++) {
-			if (!isxdigit(datap[i]))
-				break;
-		}
-		if ((rstatus = lpfc_parse_binding_entry(phba, datap, np,
-							i, sizeof (D_ID),
-							LPFC_BIND_DID, &sum,
-							entry,
-							&lpfc_num)) > 0) {
-			if (rstatus == LPFC_SYNTAX_OK_BUT_NOT_THIS_BRD)
-				continue;
-
-			/* For syntax error code definitions see
-			   LPFC_SYNTAX_ERR_ defines. */
-			/* DID binding entry <num>: Syntax error code <code> */
-			lpfc_printf_log(phba,
-				        KERN_ERR,
-				        LOG_INIT,
-				        "0434 DID binding entry %d: Syntax error code %d",
-				        entry, rstatus);
-			goto out;
-		}
-
-		/* Loop through all BINDLIST entries and find
-		 * the next available entry.
-		 */
-		if ((blp = mempool_alloc(phba->bind_mem_pool, GFP_ATOMIC))
-		    == 0) {
-			/* DID binding entry: node table full */
-			lpfc_printf_log(phba,
-				        KERN_ERR,
-				        LOG_INIT,
-				        "0435 DID binding entry: node table full");
-			goto out;
-		}
-		memset(blp, 0, sizeof (struct lpfc_bindlist));
-		blp->nlp_bind_type = FCP_SEED_DID;
-		blp->nlp_sid = (sum & 0xff);
-		blp->nlp_DID = be32_to_cpu(ndid.un.word);
-
-		lpfc_nlp_bind(phba, blp);
-
-out:
-
-		np = (uint8_t *) & ndid.un.word;
-	}
-	return (0);
-}
-
-static void
-lpfc_wakeup_event(struct lpfc_hba * phba, fcEVTHDR_t * ep)
-{
-	ep->e_mode &= ~E_SLEEPING_MODE;
-	switch (ep->e_mask) {
-	case FC_REG_LINK_EVENT:
-		wake_up_interruptible(&phba->linkevtwq);
-		break;
-	case FC_REG_RSCN_EVENT:
-		wake_up_interruptible(&phba->rscnevtwq);
-		break;
-	case FC_REG_CT_EVENT:
-		wake_up_interruptible(&phba->ctevtwq);
-		break;
-	}
-	return;
-}
-
-int
-lpfc_put_event(struct lpfc_hba * phba,
-	      uint32_t evcode, uint32_t evdata0, void *evdata1, void *evdata2)
-{
-	fcEVT_t *ep;
-	fcEVT_t *oep;
-	fcEVTHDR_t *ehp = 0;
-	int found;
-	DMABUF_t *mp;
-	void *fstype;
-	struct lpfc_sli_ct_request *ctp;
-
-	ehp = (fcEVTHDR_t *) phba->fc_evt_head;
-	fstype = 0;
-	switch (evcode) {
-	case FC_REG_CT_EVENT:
-		mp = (DMABUF_t *) evdata1;
-		ctp = (struct lpfc_sli_ct_request *) mp->virt;
-		fstype = (void *)(ulong) (ctp->FsType);
-		break;
-	}
-
-	while (ehp) {
-		if ((ehp->e_mask == evcode) && (ehp->e_type == fstype))
-			break;
-		
-		ehp = (fcEVTHDR_t *) ehp->e_next_header;
-	}
-
-	if (!ehp) {
-		return (0);
-	}
-
-	ep = ehp->e_head;
-	oep = 0;
-	found = 0;
+	ep = ehp->e_head;
+	oep = 0;
+	found = 0;
 
 	while (ep && !(found)) {
 		if (ep->evt_sleep) {
@@ -1899,157 +1382,630 @@ lpfc_hba_put_event(struct lpfc_hba * phb
 	return (0);
 }
 
-static uint32_t
-lpfc_get_cfgtkval(const char *string, const char *tk)
-{
-	int i=0,ibound,tklen,val=-1;
-	ibound = strlen(string);
-	tklen = strlen(tk);
-	while(i < ibound && strnicmp(string+i,tk,tklen) !=0)
-		i++;
-	i += tklen;
-	if( i < ibound){
-		if (strnicmp(string+i,"0x",2)==0)
-			sscanf(string+i,"0x%x",&val);
-		else
-			sscanf(string+i,"%d",&val);
-	}
-	return val;
-}
-static uint32_t
-lpfc_get_cfgnamedparam(int brd, const char *param)
+void
+lpfc_nodev(unsigned long l)
 {
-	uint32_t val = (uint32_t)-1;
-	uint32_t defval = (uint32_t)-1;
-	char tk[16];
-	snprintf(tk, 16, "lpfc:");
-	defval = lpfc_get_cfgtkval(param, tk);
-	snprintf(tk, 16, "lpfc%d:", brd);
-	val = lpfc_get_cfgtkval(param, tk);
-	if( val == -1 && defval != -1)
-		val = defval;
-	return val;
+	return;
 }
 
-static uint32_t
-lpfc_get_cfgparam(int brd, int param)
+/*
+ * This is only called to handle FC discovery events. Since this a rare
+ * occurance, we allocate an LPFC_DISC_EVT_t structure here instead of
+ * embedding it in the IOCB.
+ */
+int
+lpfc_discq_post_event(struct lpfc_hba * phba, void *arg1, void *arg2,
+		      uint32_t evt)
 {
-	uint32_t value = (uint32_t)-1;
-	
-	switch (param) {
-	case LPFC_CFG_LOG_VERBOSE:	/* log-verbose */
-		value = lpfc_get_cfgnamedparam(brd, lpfc_log_verbose);
-		break;
-	case LPFC_CFG_AUTOMAP:	/* automap */
-		value = lpfc_get_cfgnamedparam(brd, lpfc_automap);
-		break;
-	case LPFC_CFG_BINDMETHOD:	/* bind-method */
-		value = lpfc_get_cfgnamedparam(brd, lpfc_fcp_bind_method);
-		break;
-	case LPFC_CFG_CR_DELAY:	/* cr_delay */
-		value = lpfc_get_cfgnamedparam(brd, lpfc_cr_delay);
-		break;
-	case LPFC_CFG_CR_COUNT:	/* cr_count */
-		value = lpfc_get_cfgnamedparam(brd, lpfc_cr_count);
-		break;
-	case LPFC_CFG_DFT_TGT_Q_DEPTH:	/* tgt_queue_depth */
-		value = lpfc_get_cfgnamedparam(brd, lpfc_tgt_queue_depth);
-		break;
-	case LPFC_CFG_DFT_LUN_Q_DEPTH:	/* lun_queue_depth */
-		value = lpfc_get_cfgnamedparam(brd, lpfc_lun_queue_depth);
-		break;
-	case LPFC_CFG_EXTRA_IO_TMO:	/* fcpfabric-tmo */
-		value = lpfc_get_cfgnamedparam(brd, lpfc_extra_io_tmo);
-		break;
-	case LPFC_CFG_FCP_CLASS:	/* fcp-class */
-		value = lpfc_get_cfgnamedparam(brd, lpfc_fcp_class);
-		break;
-	case LPFC_CFG_USE_ADISC:	/* use-adisc */
-		value = lpfc_get_cfgnamedparam(brd, lpfc_use_adisc);
-		break;
-	case LPFC_CFG_NO_DEVICE_DELAY:	/* no-device-delay */
-		value = lpfc_get_cfgnamedparam(brd, lpfc_no_device_delay);
-		break;
-	case LPFC_CFG_NETWORK_ON:	/* network-on */
-		value = lpfc_get_cfgnamedparam(brd, lpfc_network_on);
-		break;
-	case LPFC_CFG_POST_IP_BUF:	/* post-ip-buf */
-		value = lpfc_get_cfgnamedparam(brd, lpfc_post_ip_buf);
-		break;
-	case LPFC_CFG_XMT_Q_SIZE:	/* xmt-que-size */
-		value = lpfc_get_cfgnamedparam(brd, lpfc_xmt_que_size);
-		break;
-	case LPFC_CFG_IP_CLASS:	/* ip-class */
-		value = lpfc_get_cfgnamedparam(brd, lpfc_ip_class);
-		break;
-	case LPFC_CFG_ACK0:	/* ack0 */
-		value = lpfc_get_cfgnamedparam(brd, lpfc_ack0);
-		break;
-	case LPFC_CFG_TOPOLOGY:	/* topology */
-		value = lpfc_get_cfgnamedparam(brd, lpfc_topology);
-		break;
-	case LPFC_CFG_SCAN_DOWN:	/* scan-down */
-		value = lpfc_get_cfgnamedparam(brd, lpfc_scan_down);
-		break;
-	case LPFC_CFG_LINKDOWN_TMO:	/* linkdown-tmo */
-		value = lpfc_get_cfgnamedparam(brd, lpfc_linkdown_tmo);
-		break;
-	case LPFC_CFG_HOLDIO:	/* nodev-holdio */
-		value = lpfc_get_cfgnamedparam(brd, lpfc_nodev_holdio);
-		break;
-	case LPFC_CFG_DELAY_RSP_ERR:	/* delay-rsp-err */
-		value = lpfc_get_cfgnamedparam(brd, lpfc_delay_rsp_err);
-		break;
-	case LPFC_CFG_CHK_COND_ERR:	/* check-cond-err */
-		value = lpfc_get_cfgnamedparam(brd, lpfc_check_cond_err);
-		break;
-	case LPFC_CFG_NODEV_TMO:	/* nodev-tmo */
-		value = lpfc_get_cfgnamedparam(brd, lpfc_nodev_tmo);
-		break;
-	case LPFC_CFG_LINK_SPEED:	/* link-speed */
-		value = lpfc_get_cfgnamedparam(brd, lpfc_link_speed);
-		break;
-	case LPFC_CFG_DQFULL_THROTTLE_UP_TIME:	/* dqfull-throttle-up-time */
-		value = lpfc_get_cfgnamedparam(brd,
-					       lpfc_dqfull_throttle_up_time);
-		break;
-	case LPFC_CFG_DQFULL_THROTTLE_UP_INC:	/* dqfull-throttle-up-inc */
-		value = lpfc_get_cfgnamedparam(brd,
-					       lpfc_dqfull_throttle_up_inc);
-		break;
-	case LPFC_CFG_FDMI_ON:	/* fdmi-on */
-		value = lpfc_get_cfgnamedparam(brd, lpfc_fdmi_on);
-		break;
-	case LPFC_CFG_MAX_LUN:	/* max-lun */
-		value = lpfc_get_cfgnamedparam(brd, lpfc_max_lun);
-		break;
-	case LPFC_CFG_DISC_THREADS:	/* discovery-threads */
-		value = lpfc_get_cfgnamedparam(brd, lpfc_discovery_threads);
-		break;
-	case LPFC_CFG_MAX_TARGET:	/* max-target */
-		value = lpfc_get_cfgnamedparam(brd, lpfc_max_target);
-		break;
-	case LPFC_CFG_SCSI_REQ_TMO:	/* scsi-req-tmo */
-		value = lpfc_get_cfgnamedparam(brd, lpfc_scsi_req_tmo);
-		break;
-	case LPFC_CFG_LUN_SKIP:	/* lun-skip */
-		value = lpfc_get_cfgnamedparam(brd, lpfc_lun_skip);
-		break;
-	default:
-		break;
+	LPFC_DISC_EVT_t  *evtp;
+	unsigned long flags;
+
+	/* All Mailbox completions and LPFC_ELS_RING rcv ring IOCB events
+	 * will be queued to DPC for processing
+	 */
+	evtp = (LPFC_DISC_EVT_t *) kmalloc(sizeof(LPFC_DISC_EVT_t), GFP_ATOMIC);
+	if(evtp == 0) {
+		return (0);
+	}
+	evtp->evt_arg1  = arg1;
+	evtp->evt_arg2  = arg2;
+	evtp->evt       = evt;
+	evtp->evt_listp.next = 0;
+	evtp->evt_listp.prev = 0;
+
+	/* Queue the event to the DPC to be processed later */
+	spin_lock_irqsave(&phba->dpc_lock, flags);
+	list_add_tail(&evtp->evt_listp, &phba->dpc_disc);
+	spin_unlock_irqrestore(&phba->dpc_lock, flags);
+	if(phba->dpc_wait) {
+		up(phba->dpc_wait);
+	}
+
+	return (1);
+}
+
+
+static void
+lpfc_evt_iocb_free(struct lpfc_hba * phba, struct lpfc_iocbq * saveq)
+{
+	struct lpfc_iocbq  *rspiocbp, *tmpiocbp;
+
+	/* Free up iocb buffer chain for cmd just processed */
+	list_for_each_entry_safe(rspiocbp, tmpiocbp,
+		&saveq->list, list) {
+		list_del(&rspiocbp->list);
+		mempool_free( rspiocbp, phba->iocb_mem_pool);
+	}
+	mempool_free( saveq, phba->iocb_mem_pool);
+}
+
+int
+lpfc_disc_done(struct lpfc_hba * phba)
+{
+	LPFC_SLI_t       * psli;
+	LPFC_DISC_EVT_t  * evtp, *next_evtp;
+	LPFC_MBOXQ_t     * pmb;
+	struct lpfc_iocbq     * cmdiocbp;
+	struct lpfc_iocbq     * saveq;
+	LPFC_RING_MASK_t * func;
+	LIST_HEAD(local_dpc_disc);
+	unsigned long      flags;
+
+	psli = &phba->sli;
+	spin_lock_irqsave(&phba->dpc_lock, flags);
+	list_splice_init(&phba->dpc_disc, &local_dpc_disc);
+	spin_unlock_irqrestore(&phba->dpc_lock, flags);
+	/* check discovery event list */
+	list_for_each_entry_safe(evtp, next_evtp, &local_dpc_disc, evt_listp) {
+		list_del(&evtp->evt_listp);
+
+		spin_lock_irqsave(&(phba->drvrlock), flags);
+		switch(evtp->evt) {
+		case LPFC_EVT_MBOX:
+			pmb = (LPFC_MBOXQ_t *)(evtp->evt_arg1);
+			(pmb->mbox_cmpl) (phba, pmb);
+			break;
+		case LPFC_EVT_SOL_IOCB:
+			cmdiocbp = (struct lpfc_iocbq *)(evtp->evt_arg1);
+			saveq = (struct lpfc_iocbq *)(evtp->evt_arg2);
+			(cmdiocbp->iocb_cmpl) (phba, cmdiocbp, saveq);
+			lpfc_evt_iocb_free(phba, saveq);
+			break;
+		case LPFC_EVT_UNSOL_IOCB:
+			func = (LPFC_RING_MASK_t *)(evtp->evt_arg1);
+			saveq = (struct lpfc_iocbq *)(evtp->evt_arg2);
+			(func->lpfc_sli_rcv_unsol_event) (phba,
+	 		&psli->ring[LPFC_ELS_RING], saveq);
+			lpfc_evt_iocb_free(phba, saveq);
+			break;
+		}
+		spin_unlock_irqrestore(&(phba->drvrlock), flags);
+
+		kfree(evtp);
+	}
+	return(0);
+}
+
+static int
+lpfc_do_dpc(void *p)
+{
+	DECLARE_MUTEX_LOCKED(sem);
+	struct lpfc_hba        * phba = (struct lpfc_hba *)p;
+	unsigned long      flags;
+
+	lock_kernel();
+
+	daemonize("lpfc_dpc_%d", phba->brd_no);
+	allow_signal(SIGHUP);
+
+	phba->dpc_wait = &sem;
+	set_user_nice(current, -20);
+
+	unlock_kernel();
+
+	complete(&phba->dpc_startup);
+
+	while (1) {
+		if (down_interruptible(&sem))
+			break;
+
+		if (signal_pending(current) )
+			break;
+
+		if (phba->dpc_kill)
+			break;
+
+		spin_lock_irqsave(&phba->dpc_lock, flags);
+		if (!list_empty(&phba->dpc_disc)) {
+			spin_unlock_irqrestore(&phba->dpc_lock, flags);
+			lpfc_disc_done(phba);
+		}
+		else {
+			spin_unlock_irqrestore(&phba->dpc_lock, flags);
+		}
+	}
+	/*
+	* Zero out semaphore we were waiting on.
+	*/
+	phba->dpc_wait = NULL;
+
+	complete_and_exit(&phba->dpc_exiting, 0);
+
+	return(0);
+}
+
+static int __devinit
+lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
+{
+	struct Scsi_Host *host;
+	struct lpfc_hba *phba;
+	struct lpfc_cfgparam *clp;
+	struct clk_data *clkData;
+	unsigned long iflag;
+	uint32_t timeout;
+	struct timer_list *cur_timer;
+	unsigned long bar0map_len, bar2map_len;
+	int error = -ENODEV, i;
+	
+	if (pci_enable_device(pdev))
+		goto out;
+	if (pci_request_regions(pdev, LPFC_DRIVER_NAME))
+		goto out_disable_device;
+
+	/*
+	 * Allocate space for adapter info structure
+	 */
+	phba = kmalloc(sizeof(*phba), GFP_KERNEL);
+	if (!phba)
+		goto out_release_regions;
+
+	memset(phba, 0, sizeof (struct lpfc_hba));
+	INIT_LIST_HEAD(&phba->timerList);
+
+	error = -ENOMEM;
+	/* Initialize default values for configuration parameters */
+	phba->config = kmalloc(sizeof(*phba->config), GFP_KERNEL);
+	if (!phba)
+		goto out_kfree_phba;
+
+	memset(phba->config, 0, sizeof(lpfc_icfgparam));
+	memcpy(&phba->config[0], &lpfc_icfgparam[0], sizeof(lpfc_icfgparam));
+
+	clp = &phba->config[0];
+
+	/* Set everything to the defaults */
+	for (i = 0; i < LPFC_TOTAL_NUM_OF_CFG_PARAM; i++)
+		clp[i].a_current = clp[i].a_default;
+	
+	/* Assign an unused board number */
+	i = 0;
+	while (1) {
+		if (lpfc_get_phba_by_inst(i) == NULL ) {
+			phba->brd_no = i;
+			break;
+		}
+		i++;
+	}
+
+	/* Add adapter structure to list */
+	list_add_tail(&phba->hba_list, &lpfc_hba_list);
+
+	/* Initialize all internally managed lists. */
+	INIT_LIST_HEAD(&phba->fc_nlpmap_list);
+	INIT_LIST_HEAD(&phba->fc_nlpunmap_list);
+	INIT_LIST_HEAD(&phba->fc_plogi_list);
+	INIT_LIST_HEAD(&phba->fc_adisc_list);
+	INIT_LIST_HEAD(&phba->fc_nlpbind_list);
+
+	/* Initialize plxhba - LINUX specific */
+	phba->pcidev = pdev;
+	init_waitqueue_head(&phba->linkevtwq);
+	init_waitqueue_head(&phba->rscnevtwq);
+	init_waitqueue_head(&phba->ctevtwq);
+
+	pci_set_master(pdev);
+	pci_set_mwi(pdev);
+
+	/* Configure DMA attributes. */
+	if (dma_set_mask(&phba->pcidev->dev, 0xffffffffffffffffULL) &&
+	    dma_set_mask(&phba->pcidev->dev, 0xffffffffULL))
+		goto out_list_del;
+
+	/*
+	 * Get the physical address of Bar0 and Bar2 and the number of bytes
+	 * required by each mapping.
+	 */
+	phba->pci_bar0_map = pci_resource_start(phba->pcidev, 0);
+	bar0map_len        = pci_resource_len(phba->pcidev, 0);
+	
+	phba->pci_bar2_map = pci_resource_start(phba->pcidev, 2);
+	bar2map_len        = pci_resource_len(phba->pcidev, 2);
+
+	/* Map HBA SLIM and Control Registers to a kernel virtual address. */
+	phba->slim_memmap_p      = ioremap(phba->pci_bar0_map, bar0map_len);
+	phba->ctrl_regs_memmap_p = ioremap(phba->pci_bar2_map, bar2map_len);
+
+	/* Setup SLI2 interface */
+	if (!phba->slim2p.virt) {
+		/*
+		 * Allocate memory for SLI-2 structures
+		 */
+		phba->slim2p.virt = dma_alloc_coherent(&phba->pcidev->dev,
+						       sizeof (SLI2_SLIM_t),
+						       &(phba->slim2p.phys),
+						       GFP_ATOMIC);
+		if (!phba->slim2p.virt)
+			goto out_iounmap;
+
+		/* The SLIM2 size is stored in the next field */
+		phba->slim_size = sizeof (SLI2_SLIM_t);
+		memset(phba->slim2p.virt, 0, sizeof (SLI2_SLIM_t));
+	}
+
+	lpfc_num_hba++;
+	lpfc_config_setup(phba);	/* Setup configuration parameters */
+
+	/*
+	 * If the t.o value is not set, set it to 30
+	 */
+	if (clp[LPFC_CFG_SCSI_REQ_TMO].a_current == 0) {
+		clp[LPFC_CFG_SCSI_REQ_TMO].a_current = 30;
+	}
+
+	if (clp[LPFC_CFG_DISC_THREADS].a_current) {
+		/*
+		 * Set to FC_NLP_REQ if automap is set to 0 since order of
+		 * discovery does not matter if everything is persistently
+		 * bound.
+		 */
+		if (clp[LPFC_CFG_AUTOMAP].a_current == 0) {
+			clp[LPFC_CFG_DISC_THREADS].a_current =
+			    LPFC_MAX_DISC_THREADS;
+		}
+	}
+
+	/* Initialize all per HBA locks */
+	spin_lock_init(&phba->drvrlock);
+	spin_lock_init(&phba->hiprilock);
+
+	lpfc_sli_setup(phba);	/* Setup SLI Layer to run over lpfc HBAs */
+	lpfc_sli_queue_setup(phba);	/* Initialize the SLI Layer */
+
+	if (!lpfc_mem_alloc(phba))
+		goto out_dec_nhbas;
+
+	lpfc_bind_setup(phba);	/* Setup binding configuration parameters */
+
+	/* Initialize HBA structure */
+	phba->fc_edtov = FF_DEF_EDTOV;
+	phba->fc_ratov = FF_DEF_RATOV;
+	phba->fc_altov = FF_DEF_ALTOV;
+	phba->fc_arbtov = FF_DEF_ARBTOV;
+
+	/* Set the FARP and XRI timeout values now since they depend on
+	   fc_ratov. */
+	phba->fc_ipfarp_timeout = (3 * phba->fc_ratov);
+	phba->fc_ipxri_timeout = (3 * phba->fc_ratov);
+
+	spin_lock_init(&phba->dpc_lock);
+	INIT_LIST_HEAD(&phba->dpc_disc);
+	init_completion(&phba->dpc_startup);
+	init_completion(&phba->dpc_exiting);
+
+	/*
+	* Startup the kernel thread for this host adapter
+	*/
+	phba->dpc_kill = 0;
+	phba->dpc_pid = kernel_thread(lpfc_do_dpc, phba, 0);
+	if (phba->dpc_pid < 0) {
+		error = phba->dpc_pid;
+		goto out_free_mem;
+	}
+	wait_for_completion(&phba->dpc_startup);
+
+	/* Call SLI to initialize the HBA. */
+	/* Eek, this returns positive error codes, --hch */
+	error = -lpfc_sli_hba_setup(phba);
+	if (error)
+		goto out_hba_down;
+
+	/* Register this board */
+	host = scsi_host_alloc(&driver_template, sizeof (unsigned long));
+	if (!host) {
+		printk (KERN_WARNING "%s%d: scsi_host_alloc failed during "
+			"attach\n", lpfc_drvr_name, phba->brd_no);
+		error = -ENOMEM;
+		goto out_cleanup_timers;
+	}
+
+	phba->host = host;
+	host->can_queue = clp[LPFC_CFG_DFT_HBA_Q_DEPTH].a_current - 10;
+
+	/*
+	 * Adjust the number of id's
+	 * Although max_id is an int, target id's are unsined chars
+	 * Do not exceed 255, otherwise the device scan will wrap around
+	 */
+	if (clp[LPFC_CFG_MAX_TARGET].a_current > LPFC_MAX_TARGET)
+		clp[LPFC_CFG_MAX_TARGET].a_current = LPFC_DFT_MAX_TARGET;
+
+	host->max_id = clp[LPFC_CFG_MAX_TARGET].a_current;
+	host->unique_id = lpfc_num_hba;
+
+	if (clp[LPFC_CFG_MAX_LUN].a_current > LPFC_MAX_LUN)
+		clp[LPFC_CFG_MAX_LUN].a_current = LPFC_DFT_MAX_LUN;
+	host->max_lun = clp[LPFC_CFG_MAX_LUN].a_current;
+
+	/* Adapter ID - tell midlayer not to reserve an ID for us */
+	host->this_id = -1;
+
+	/*
+	 * Setup the scsi timeout handler with a
+	 * timeout value = greater of (2*RATOV, 5).
+	 */
+	timeout = (phba->fc_ratov << 1) > 5 ? (phba->fc_ratov << 1) : 5;
+	phba->scsi_tmo_data.timeObj = &phba->scsi_tmofunc;
+	phba->scsi_tmo_data.phba = phba;
+	phba->scsi_tmo_data.clData1 = (unsigned long)timeout;
+	init_timer(&phba->scsi_tmofunc);
+	phba->scsi_tmofunc.function = lpfc_scsi_timeout_handler;
+	phba->scsi_tmofunc.expires = jiffies + HZ * timeout;
+	phba->scsi_tmofunc.data = (unsigned long)&phba->scsi_tmo_data;
+	list_add(&phba->scsi_tmo_data.listLink, &phba->timerList);
+	add_timer(&phba->scsi_tmofunc);
+
+
+	/*
+	 * Starting with 2.4.0 kernel, Linux can support commands longer
+	 * than 12 bytes. However, scsi_register() always sets it to 12.
+	 * For it to be useful to the midlayer, we have to set it here.
+	 */
+	host->max_cmd_len = 16;
+
+	/*
+	 * Queue depths per lun
+	 */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,6)
+	host->transportt = lpfc_transport_template;
+#endif
+	host->hostdata[0] = (unsigned long)phba;
+	pci_set_drvdata(pdev, host);
+
+	error = scsi_add_host(host, &pdev->dev);
+	if (error)
+		goto out_put_host;
+
+	device_create_file(&(pdev->dev), &dev_attr_info);
+	device_create_file(&(pdev->dev), &dev_attr_serialnum);
+	device_create_file(&(pdev->dev), &dev_attr_fwrev);
+	device_create_file(&(pdev->dev), &dev_attr_hdw);
+	device_create_file(&(pdev->dev), &dev_attr_lpfc_log_verbose);
+	device_create_file(&(pdev->dev), &dev_attr_lpfc_tgt_queue_depth);
+	device_create_file(&(pdev->dev), &dev_attr_lpfc_lun_queue_depth);
+	device_create_file(&(pdev->dev), &dev_attr_lpfc_extra_io_tmo);
+	device_create_file(&(pdev->dev), &dev_attr_lpfc_no_device_delay);
+	device_create_file(&(pdev->dev), &dev_attr_lpfc_linkdown_tmo);
+	device_create_file(&(pdev->dev), &dev_attr_lpfc_nodev_holdio);
+	device_create_file(&(pdev->dev), &dev_attr_lpfc_delay_rsp_err);
+	device_create_file(&(pdev->dev), &dev_attr_lpfc_check_cond_err);
+	device_create_file(&(pdev->dev), &dev_attr_lpfc_nodev_tmo);
+	device_create_file(&(pdev->dev),
+			   &dev_attr_lpfc_dqfull_throttle_up_time);
+	device_create_file(&(pdev->dev), &dev_attr_lpfc_dqfull_throttle_up_inc);
+	device_create_file(&(pdev->dev), &dev_attr_lpfc_max_lun);
+	device_create_file(&(pdev->dev), &dev_attr_lpfc_lun_skip);
+	device_create_file(&(pdev->dev), &dev_attr_lpfc_automap);
+	device_create_file(&(pdev->dev), &dev_attr_lpfc_fcp_class);
+	device_create_file(&(pdev->dev), &dev_attr_lpfc_use_adisc);
+	device_create_file(&(pdev->dev), &dev_attr_lpfc_network_on);
+	device_create_file(&(pdev->dev), &dev_attr_lpfc_post_ip_buf);
+	device_create_file(&(pdev->dev), &dev_attr_lpfc_xmt_que_size);
+	device_create_file(&(pdev->dev), &dev_attr_lpfc_ip_class);
+	device_create_file(&(pdev->dev), &dev_attr_lpfc_ack0);
+	device_create_file(&(pdev->dev), &dev_attr_lpfc_topology);
+	device_create_file(&(pdev->dev), &dev_attr_lpfc_scan_down);
+	device_create_file(&(pdev->dev), &dev_attr_lpfc_link_speed);
+	device_create_file(&(pdev->dev), &dev_attr_lpfc_cr_delay);
+	device_create_file(&(pdev->dev), &dev_attr_lpfc_cr_count);
+	device_create_file(&(pdev->dev), &dev_attr_lpfc_fdmi_on);
+	device_create_file(&(pdev->dev), &dev_attr_lpfc_fcp_bind_method);
+	device_create_file(&(pdev->dev), &dev_attr_lpfc_discovery_threads);
+	device_create_file(&(pdev->dev), &dev_attr_lpfc_scsi_req_tmo);
+	device_create_file(&(pdev->dev), &dev_attr_lpfc_max_target);
+
+	scsi_scan_host(host);
+	return 0;
+
+ out_put_host:
+	scsi_host_put(host);
+ out_hba_down:
+	lpfc_sli_hba_down(phba);
+
+ out_cleanup_timers:
+	/* Stop any timers that were started during this attach. */
+	spin_lock_irqsave(&(phba->drvrlock), iflag);
+	while (!list_empty(&phba->timerList)) {
+		clkData = (struct clk_data *)(phba->timerList.next);
+		if (clkData) {
+			cur_timer = clkData->timeObj;
+			del_timer_sync(cur_timer);
+			cur_timer->function = 0;
+			list_del(&clkData->listLink);
+		}
+	}
+	spin_unlock_irqrestore(&(phba->drvrlock), iflag);
+
+	/* Kill the kernel thread for this host */
+	if (phba->dpc_pid >= 0) {
+		phba->dpc_kill = 1;
+		wmb();
+		kill_proc(phba->dpc_pid, SIGHUP, 1);
+		wait_for_completion(&phba->dpc_exiting);
+	}
+
+	free_irq(phba->pcidev->irq, phba);
+ out_free_mem:
+	lpfc_mem_free(phba);
+ out_dec_nhbas:
+	lpfc_num_hba--;
+	if (phba->slim2p.virt) {
+		dma_free_coherent(&pdev->dev,
+				  phba->slim_size,
+				  phba->slim2p.virt,
+				  phba->slim2p.phys);
+	}
+ out_iounmap:
+	iounmap(phba->ctrl_regs_memmap_p);
+	iounmap(phba->slim_memmap_p);
+ out_list_del:
+	list_del_init(&phba->hba_list);
+	kfree(phba->config);
+ out_kfree_phba:
+	kfree(phba);
+ out_release_regions:
+	pci_release_regions(pdev);
+ out_disable_device:
+	pci_disable_device(pdev);	
+ out:
+	return error;
+}
+
+static void __devexit
+lpfc_pci_remove_one(struct pci_dev *pdev)
+{
+	struct Scsi_Host *host = pci_get_drvdata(pdev);
+	struct lpfc_hba *phba = (struct lpfc_hba *)host->hostdata[0];
+	struct clk_data *clkData;
+	struct timer_list *cur_timer;
+	unsigned long iflag;
+
+	scsi_remove_host(phba->host);
+	list_del(&phba->hba_list);
+
+	device_remove_file(&(pdev->dev), &dev_attr_info);
+	device_remove_file(&(pdev->dev), &dev_attr_serialnum);
+	device_remove_file(&(pdev->dev), &dev_attr_fwrev);
+	device_remove_file(&(pdev->dev), &dev_attr_hdw);
+	device_remove_file(&(pdev->dev), &dev_attr_lpfc_log_verbose);
+	device_remove_file(&(pdev->dev), &dev_attr_lpfc_tgt_queue_depth);
+	device_remove_file(&(pdev->dev), &dev_attr_lpfc_lun_queue_depth);
+	device_remove_file(&(pdev->dev), &dev_attr_lpfc_extra_io_tmo);
+	device_remove_file(&(pdev->dev), &dev_attr_lpfc_no_device_delay);
+	device_remove_file(&(pdev->dev), &dev_attr_lpfc_linkdown_tmo);
+	device_remove_file(&(pdev->dev), &dev_attr_lpfc_nodev_holdio);
+	device_remove_file(&(pdev->dev), &dev_attr_lpfc_delay_rsp_err);
+	device_remove_file(&(pdev->dev), &dev_attr_lpfc_check_cond_err);
+	device_remove_file(&(pdev->dev), &dev_attr_lpfc_nodev_tmo);
+	device_remove_file(&(pdev->dev),
+			   &dev_attr_lpfc_dqfull_throttle_up_time);
+	device_remove_file(&(pdev->dev), &dev_attr_lpfc_dqfull_throttle_up_inc);
+	device_remove_file(&(pdev->dev), &dev_attr_lpfc_max_lun);
+	device_remove_file(&(pdev->dev), &dev_attr_lpfc_lun_skip);
+	device_remove_file(&(pdev->dev), &dev_attr_lpfc_automap);
+	device_remove_file(&(pdev->dev), &dev_attr_lpfc_fcp_class);
+	device_remove_file(&(pdev->dev), &dev_attr_lpfc_use_adisc);
+	device_remove_file(&(pdev->dev), &dev_attr_lpfc_network_on);
+	device_remove_file(&(pdev->dev), &dev_attr_lpfc_post_ip_buf);
+	device_remove_file(&(pdev->dev), &dev_attr_lpfc_xmt_que_size);
+	device_remove_file(&(pdev->dev), &dev_attr_lpfc_ip_class);
+	device_remove_file(&(pdev->dev), &dev_attr_lpfc_ack0);
+	device_remove_file(&(pdev->dev), &dev_attr_lpfc_topology);
+	device_remove_file(&(pdev->dev), &dev_attr_lpfc_scan_down);
+	device_remove_file(&(pdev->dev), &dev_attr_lpfc_link_speed);
+	device_remove_file(&(pdev->dev), &dev_attr_lpfc_cr_delay);
+	device_remove_file(&(pdev->dev), &dev_attr_lpfc_cr_count);
+	device_remove_file(&(pdev->dev), &dev_attr_lpfc_fdmi_on);
+	device_remove_file(&(pdev->dev), &dev_attr_lpfc_fcp_bind_method);
+	device_remove_file(&(pdev->dev), &dev_attr_lpfc_discovery_threads);
+	device_remove_file(&(pdev->dev), &dev_attr_lpfc_scsi_req_tmo);
+	device_remove_file(&(pdev->dev), &dev_attr_lpfc_max_target);
+
+	spin_lock_irqsave(&(phba->drvrlock), iflag);
+	while (!list_empty(&phba->timerList)) {
+		clkData = (struct clk_data *)(phba->timerList.next);
+		if (clkData) {
+			cur_timer = clkData->timeObj;
+			del_timer_sync(cur_timer);
+			cur_timer->function = 0;
+			list_del(&clkData->listLink);
+		}
 	}
+	spin_unlock_irqrestore(&(phba->drvrlock), iflag);
 
-	return (value);
-}
+	/* Kill the kernel thread for this host */
+	if (phba->dpc_pid >= 0) {
+		phba->dpc_kill = 1;
+		wmb();
+		kill_proc(phba->dpc_pid, SIGHUP, 1);
+		wait_for_completion(&phba->dpc_exiting);
+	}
+
+	/*
+	 * Bring down the SLI Layer. This step disable all interrupts,
+	 * clears the rings, discards all mailbox commands, and resets
+	 * the HBA.
+	 */
+	lpfc_sli_hba_down(phba);	
+
+	/* Release the irq reservation */
+	free_irq(phba->pcidev->irq, phba);
+
+	lpfc_cleanup(phba, 0);
+	lpfc_scsi_free(phba);
+	lpfc_mem_free(phba);
+
+	/* Free resources associated with SLI2 interface */
+	if (phba->slim2p.virt) {
+		dma_free_coherent(&pdev->dev,
+				  phba->slim_size,
+				  phba->slim2p.virt,
+				  phba->slim2p.phys);
+
+	}
+
+	/* unmap adapter SLIM and Control Registers */
+	iounmap(phba->ctrl_regs_memmap_p);
+	iounmap(phba->slim_memmap_p);
+
+	pci_release_regions(phba->pcidev);
+	pci_disable_device(phba->pcidev);
 
+	kfree(phba->config);
+	kfree(phba);
 
+	scsi_host_put(phba->host);
+	pci_set_drvdata(pdev, 0);
+	lpfc_num_hba--;
+}
 
+static struct pci_device_id lpfc_id_table[] = {
+	{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_VIPER,
+		PCI_ANY_ID, PCI_ANY_ID, },
+	{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_THOR,
+		PCI_ANY_ID, PCI_ANY_ID, },
+	{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_PEGASUS,
+		PCI_ANY_ID, PCI_ANY_ID, },
+	{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_CENTAUR,
+		PCI_ANY_ID, PCI_ANY_ID, },
+	{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_DRAGONFLY,
+		PCI_ANY_ID, PCI_ANY_ID, },
+	{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_SUPERFLY,
+		PCI_ANY_ID, PCI_ANY_ID, },
+	{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_RFLY,
+		PCI_ANY_ID, PCI_ANY_ID, },
+	{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_PFLY,
+		PCI_ANY_ID, PCI_ANY_ID, },
+	{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_TFLY,
+		PCI_ANY_ID, PCI_ANY_ID, },
+	{ 0 }
+};
+MODULE_DEVICE_TABLE(pci, lpfc_id_table);
 
 static struct pci_driver lpfc_driver = {
-	.name = LPFC_DRIVER_NAME,
-	.id_table = lpfc_id_table,
-	.probe = lpfc_pci_probe_one,
-	.remove = __devexit_p(lpfc_pci_remove_one),
+	.name		= LPFC_DRIVER_NAME,
+	.id_table	= lpfc_id_table,
+	.probe		= lpfc_pci_probe_one,
+	.remove		= __devexit_p(lpfc_pci_remove_one),
 };
 
 static int __init
@@ -2059,20 +2015,15 @@ lpfc_init(void)
 
 	printk(LPFC_MODULE_DESC "\n");
 
-	lpfc_loadtime = jiffies;
-
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,6)
 	lpfc_transport_template =
 		fc_attach_transport(&lpfc_transport_functions);
-	if(!lpfc_transport_template)
+	if (!lpfc_transport_template)
 		return -ENODEV;
 #endif
 	rc = pci_module_init(&lpfc_driver);
-	
-	if(rc == 0)
+	if (!rc)
 		driver_create_file(&(lpfc_driver.driver), &driver_attr_version);
-	
-	
 	return rc;
 
 }
@@ -2086,182 +2037,10 @@ lpfc_exit(void)
 #endif
 }
 
-static int
-lpfc_biosparam(struct scsi_device *psdev,
-	      struct block_device *pbdev, sector_t capacity, int ip[])
-{
-	int size = capacity;
-
-	ip[0] = 64;
-	ip[1] = 32;
-	ip[2] = size >> 11;
-	if (ip[2] > 1024) {
-		ip[0] = 255;
-		ip[1] = 63;
-		ip[2] = size / (ip[0] * ip[1]);
-#ifndef FC_EXTEND_TRANS_A
-		if (ip[2] > 1023)
-			ip[2] = 1023;
-#endif
-	}
-	return (0);
-}
-
-
-void
-lpfc_nodev(unsigned long l)
-{
-	return;
-}
-
-
-
-/*
- * This is only called to handle FC discovery events. Since this a rare
- * occurance, we allocate an LPFC_DISC_EVT_t structure here instead of
- * embedding it in the IOCB.
- */
-int
-lpfc_discq_post_event(struct lpfc_hba * phba, void *arg1, void *arg2,
-		      uint32_t evt)
-{
-	LPFC_DISC_EVT_t  *evtp;
-	unsigned long flags;
-
-	/* All Mailbox completions and LPFC_ELS_RING rcv ring IOCB events
-	 * will be queued to DPC for processing
-	 */
-	evtp = (LPFC_DISC_EVT_t *) kmalloc(sizeof(LPFC_DISC_EVT_t), GFP_ATOMIC);
-	if(evtp == 0) {
-		return (0);
-	}
-	evtp->evt_arg1  = arg1;
-	evtp->evt_arg2  = arg2;
-	evtp->evt       = evt;
-	evtp->evt_listp.next = 0;
-	evtp->evt_listp.prev = 0;
-
-	/* Queue the event to the DPC to be processed later */
-	spin_lock_irqsave(&phba->dpc_lock, flags);
-	list_add_tail(&evtp->evt_listp, &phba->dpc_disc);
-	spin_unlock_irqrestore(&phba->dpc_lock, flags);
-	if(phba->dpc_wait) {
-		up(phba->dpc_wait);
-	}
-
-	return (1);
-}
-
-
-static void
-lpfc_evt_iocb_free(struct lpfc_hba * phba, struct lpfc_iocbq * saveq)
-{
-	struct lpfc_iocbq  *rspiocbp, *tmpiocbp;
-
-	/* Free up iocb buffer chain for cmd just processed */
-	list_for_each_entry_safe(rspiocbp, tmpiocbp,
-		&saveq->list, list) {
-		list_del(&rspiocbp->list);
-		mempool_free( rspiocbp, phba->iocb_mem_pool);
-	}
-	mempool_free( saveq, phba->iocb_mem_pool);
-}
-
-int
-lpfc_disc_done(struct lpfc_hba * phba)
-{
-	LPFC_SLI_t       * psli;
-	LPFC_DISC_EVT_t  * evtp, *next_evtp;
-	LPFC_MBOXQ_t     * pmb;
-	struct lpfc_iocbq     * cmdiocbp;
-	struct lpfc_iocbq     * saveq;
-	LPFC_RING_MASK_t * func;
-	LIST_HEAD(local_dpc_disc);
-	unsigned long      flags;
-
-	psli = &phba->sli;
-	spin_lock_irqsave(&phba->dpc_lock, flags);
-	list_splice_init(&phba->dpc_disc, &local_dpc_disc);
-	spin_unlock_irqrestore(&phba->dpc_lock, flags);
-	/* check discovery event list */
-	list_for_each_entry_safe(evtp, next_evtp, &local_dpc_disc, evt_listp) {
-		list_del(&evtp->evt_listp);
-
-		spin_lock_irqsave(&(phba->drvrlock), flags);
-		switch(evtp->evt) {
-		case LPFC_EVT_MBOX:
-			pmb = (LPFC_MBOXQ_t *)(evtp->evt_arg1);
-			(pmb->mbox_cmpl) (phba, pmb);
-			break;
-		case LPFC_EVT_SOL_IOCB:
-			cmdiocbp = (struct lpfc_iocbq *)(evtp->evt_arg1);
-			saveq = (struct lpfc_iocbq *)(evtp->evt_arg2);
-			(cmdiocbp->iocb_cmpl) (phba, cmdiocbp, saveq);
-			lpfc_evt_iocb_free(phba, saveq);
-			break;
-		case LPFC_EVT_UNSOL_IOCB:
-			func = (LPFC_RING_MASK_t *)(evtp->evt_arg1);
-			saveq = (struct lpfc_iocbq *)(evtp->evt_arg2);
-			(func->lpfc_sli_rcv_unsol_event) (phba,
-	 		&psli->ring[LPFC_ELS_RING], saveq);
-			lpfc_evt_iocb_free(phba, saveq);
-			break;
-		}
-		spin_unlock_irqrestore(&(phba->drvrlock), flags);
-
-		kfree(evtp);
-	}
-	return(0);
-}
-
-static int
-lpfc_do_dpc(void *p)
-{
-	DECLARE_MUTEX_LOCKED(sem);
-	struct lpfc_hba        * phba = (struct lpfc_hba *)p;
-	unsigned long      flags;
-
-	lock_kernel();
-
-	daemonize("lpfc_dpc_%d", phba->brd_no);
-	allow_signal(SIGHUP);
-
-	phba->dpc_wait = &sem;
-	set_user_nice(current, -20);
-
-	unlock_kernel();
-
-	complete(&phba->dpc_startup);
-
-	while (1) {
-		if (down_interruptible(&sem))
-			break;
-
-		if (signal_pending(current) )
-			break;
-
-		if (phba->dpc_kill)
-			break;
-
-		spin_lock_irqsave(&phba->dpc_lock, flags);
-		if (!list_empty(&phba->dpc_disc)) {
-			spin_unlock_irqrestore(&phba->dpc_lock, flags);
-			lpfc_disc_done(phba);
-		}
-		else {
-			spin_unlock_irqrestore(&phba->dpc_lock, flags);
-		}
-	}
-	/*
-	* Zero out semaphore we were waiting on.
-	*/
-	phba->dpc_wait = NULL;
-
-	complete_and_exit(&phba->dpc_exiting, 0);
-
-	return(0);
-}
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION(LPFC_MODULE_DESC);
+MODULE_AUTHOR("Emulex Corporation - tech.support@emulex.com");
+MODULE_VERSION("0:" LPFC_DRIVER_VERSION);
 
 module_init(lpfc_init);
 module_exit(lpfc_exit);
-MODULE_LICENSE("GPL");

  reply	other threads:[~2004-06-16 13:50 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2004-06-15 17:32 [Emulex] Ready for next round Smart, James
2004-06-16  8:17 ` Christoph Hellwig
2004-06-16 13:35   ` Jamie Wellnitz
2004-06-16 13:50     ` Christoph Hellwig [this message]
2004-06-16  8:20 ` Christoph Hellwig
2004-06-16  8:31 ` Christoph Hellwig
2004-06-20 13:35 ` Christoph Hellwig
2004-06-23 15:31 ` Anton Blanchard
  -- strict thread matches above, loose matches on Subject: below --
2004-06-18 19:56 Smart, James
2004-06-18 20:58 ` 'Christoph Hellwig'
2004-07-09 19:24 Smart, James
2004-07-09 22:08 ` 'Christoph Hellwig'
2004-07-09 22:10 ` 'Christoph Hellwig'
2004-07-17 11:26 Smart, James
2004-07-17 20:17 ` 'Christoph Hellwig'
2004-07-17 20:26   ` 'Christoph Hellwig'
2004-07-19 20:02 Ely, Paul

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20040616135008.GA12260@infradead.org \
    --to=hch@infradead.org \
    --cc=James.Smart@emulex.com \
    --cc=Jamie.Wellnitz@emulex.com \
    --cc=linux-scsi@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox