public inbox for linux-scsi@vger.kernel.org
 help / color / mirror / Atom feed
* [Emulex] Ready for next round...
@ 2004-06-15 17:32 Smart, James
  2004-06-16  8:17 ` Christoph Hellwig
                   ` (4 more replies)
  0 siblings, 5 replies; 17+ messages in thread
From: Smart, James @ 2004-06-15 17:32 UTC (permalink / raw)
  To: Linux SCSI Reflector

Christoph, et al...

I'd like to request the next round of review comments on the driver.

We believe that tonights posting on SourceForge has addressed all of the
comments to date with only a couple of exceptions (see below).

-- James S



Open items:
------------
[From 5/9] Re: typedefs in sSuDly Caps and pfoo pointer naming.
We have addressed some, but not all of this. We will remove all of it.

[From 5/9] Re: explain USE_HGP_HOST_SLIM and why only ppc64 sets it
A very valid question (thank you). This was masking several issues. Some of
which we are still testing. For now, the code has been left as is. We will
be posting the actual change shortly.

[From 5/0] Re: don't mess with eh_timeout from a LLDD please
We haven't sync'd with the IBM patch as yet. Will be doing so.


Comments:
--------------
[From 5/9] Re: lpfc_msg* stuff is not acceptable.
We've inlined the print strings and filter values. Should be acceptable now.

[From 5/9] Re: you should probably redesign your driver to use the host_lock
instead of the drvlock everywhere.
For now, we haven't changed. However, we are actively looking at this.

[From 5/9] Re: what do you need lpfcDRVR.loadtime for?
Is used for diagnostics and trouble-shooting.

[From 5/18] Re: while we're at it reorder includes alphabetically
We do not agree with alphabetical ordering. We believe in letting the header
dependencies decide the ordering, and where ordering is not dictated, let
logical grouping take place.

[From 5/31] Re: remove dead EXPORT_SYMBOLS
Based on the feedback and recommendations - we've removed the external
symbols. At a later date, we'll propose patches to reintroduce the
functionality in a manner that will be more acceptable to the group.

[From 6/1]Re: Adam Blanchard's comment on page alloc fail on ppc64, thought
on using a mempool & Re: other queuecommand problems - too many allocations,
allocs under spinlock, etc.
We made several code reorgs to move locks, and change the allocations so
that everything is GFP_NOIO under no locks. However, we're subject to an
issue with blk_run_queue() which invokes us under softirq. At this point, we
have to move things back to GFP_ATOMIC to be safe. What you will see in
tonights drop is: a) we've removed a couple of "always allocate" cases by
embedding the structures into the base scsi_buf; b) we've implemented a
mempool to hopefully help (but not solve) the failure case.




^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [Emulex] Ready for next round...
  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  8:20 ` Christoph Hellwig
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 17+ messages in thread
From: Christoph Hellwig @ 2004-06-16  8:17 UTC (permalink / raw)
  To: Smart, James; +Cc: Linux SCSI Reflector

On Tue, Jun 15, 2004 at 01:32:56PM -0400, Smart, James wrote:
> Christoph, et al...
> 
> I'd like to request the next round of review comments on the driver.
> 
> We believe that tonights posting on SourceForge has addressed all of the
> comments to date with only a couple of exceptions (see below).

Before commenting on anything here's a big diff turning lpfc_fcp.c into
normal driver function ordering, aka function above invokations, scsi
methods over pci methods, and fixes gazillions of leaks in the ->probe
failure cases.  It's guranteed to conflict with just about everything
touching that file.

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [Emulex] Ready for next round...
  2004-06-15 17:32 [Emulex] Ready for next round Smart, James
  2004-06-16  8:17 ` Christoph Hellwig
@ 2004-06-16  8:20 ` Christoph Hellwig
  2004-06-16  8:31 ` Christoph Hellwig
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 17+ messages in thread
From: Christoph Hellwig @ 2004-06-16  8:20 UTC (permalink / raw)
  To: Smart, James; +Cc: Linux SCSI Reflector

On Tue, Jun 15, 2004 at 01:32:56PM -0400, Smart, James wrote:
> Comments:
> --------------
> [From 5/9] Re: lpfc_msg* stuff is not acceptable.
> We've inlined the print strings and filter values. Should be acceptable now.

Still quite horrible.  Please use dev_printk ala qlogic:

#define qla_printk(level, ha, format, arg...) \
        dev_printk(level , &((ha)->pdev->dev) , format , ## arg)



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [Emulex] Ready for next round...
  2004-06-15 17:32 [Emulex] Ready for next round Smart, James
  2004-06-16  8:17 ` Christoph Hellwig
  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
  4 siblings, 0 replies; 17+ messages in thread
From: Christoph Hellwig @ 2004-06-16  8:31 UTC (permalink / raw)
  To: Smart, James; +Cc: Linux SCSI Reflector

On Tue, Jun 15, 2004 at 01:32:56PM -0400, Smart, James wrote:
> Christoph, et al...
> 
> I'd like to request the next round of review comments on the driver.
> 
> We believe that tonights posting on SourceForge has addressed all of the
> comments to date with only a couple of exceptions (see below).

Okay, here's a review vs the original comments:

> - your module_param usage is b0rked.  Instead of duplicating every
>   option 31 times use module_param_array.  You also seem to miss
>   the paramter descriptions (MODULE_PARAM_DESC)

Your paramters are still extremly crappy.  lpfc.conf is horrible, as is
having the module paramters in a header.  What's especially bad is that
they are character paramters without any abvious reasons, please use
the proper integer types.

lpfc_cfgparm.h is truely horrible.

> - lpfc_clock.c should go away, just use add_timer/etc. diretly and
>   embedd the timer into your structures.  Yes, I know that's not
>   how SVR4-derivates work, but Linux does.  You also have an
>   unchecked kmalloc and a list_head cast in there..

Still not much better.  In fact the crappy datastructures and code are
still there, just spread all over the place now instead of fixed up.

> - dito for lpfc_sysfs_info_show, in short all your sysfs work is completely
>   wrong, also you seem to use driver attributes instead of scsi device/host
>   attributes.  why?

You're still attaching all the attributes yourself.  Please use the
scsi-provided host/device attributes instead.

> - the lpfc_find_target usage in queuecommand looks bogus.  You have
>   scsi_device->hostdata to put per-lun data, from which you can trivially
>   link per-target data directly.  All the checks for inquiry and valid
>   luns are similarly b0rked - scsi probing works by calling ->slave_alloc
>   first so you'll a) have a place where you know the midlayer is probing
>   and b) always private data when quecommand is called.

While you started using sdev->hostdata the whole code is still more than
fishy.  You have a complete set of secondary data structures for target/lun
data lookup yet.  Please allocate all per-lun data in ->slave_alloc and
if the target data doesn't exist yet that one too and hang it off the lun
data.


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [Emulex] Ready for next round...
  2004-06-16  8:17 ` Christoph Hellwig
@ 2004-06-16 13:35   ` Jamie Wellnitz
  2004-06-16 13:50     ` Christoph Hellwig
  0 siblings, 1 reply; 17+ messages in thread
From: Jamie Wellnitz @ 2004-06-16 13:35 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: Smart, James, Linux SCSI Reflector

Christoph,

Am I missing the big diff for lpfc_fcp.c?  I don't see it . . .

Thanks,
Jamie

On Wed, Jun 16, 2004 at 09:17:57AM +0100, Christoph Hellwig wrote:
> On Tue, Jun 15, 2004 at 01:32:56PM -0400, Smart, James wrote:
> > Christoph, et al...
> > 
> > I'd like to request the next round of review comments on the driver.
> > 
> > We believe that tonights posting on SourceForge has addressed all of the
> > comments to date with only a couple of exceptions (see below).
> 
> Before commenting on anything here's a big diff turning lpfc_fcp.c into
> normal driver function ordering, aka function above invokations, scsi
> methods over pci methods, and fixes gazillions of leaks in the ->probe
> failure cases.  It's guranteed to conflict with just about everything
> touching that file.
> -
> To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [Emulex] Ready for next round...
  2004-06-16 13:35   ` Jamie Wellnitz
@ 2004-06-16 13:50     ` Christoph Hellwig
  0 siblings, 0 replies; 17+ messages in thread
From: Christoph Hellwig @ 2004-06-16 13:50 UTC (permalink / raw)
  To: Jamie Wellnitz; +Cc: Christoph Hellwig, Smart, James, Linux SCSI Reflector

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");

^ permalink raw reply	[flat|nested] 17+ messages in thread

* RE: [Emulex] Ready for next round...
@ 2004-06-18 19:56 Smart, James
  2004-06-18 20:58 ` 'Christoph Hellwig'
  0 siblings, 1 reply; 17+ messages in thread
From: Smart, James @ 2004-06-18 19:56 UTC (permalink / raw)
  To: 'Christoph Hellwig'; +Cc: Linux SCSI Reflector

Christoph,

per your comments:
 
> > - your module_param usage is b0rked.  Instead of duplicating every
> >   option 31 times use module_param_array.  You also seem to miss
> >   the paramter descriptions (MODULE_PARAM_DESC)
> 
> Your paramters are still extremly crappy.  lpfc.conf is 
> horrible, as is
> having the module paramters in a header.  What's especially 
> bad is that
> they are character paramters without any abvious reasons, please use
> the proper integer types.
> 
> lpfc_cfgparm.h is truely horrible.

More guidance needed than the terms used.... What are you looking for ?

lpfc.conf - should be better renamed to a .c file and it is compiled into
the driver. It provides the default values for the attributes for each
adapter. Our requirement is to have individual attributes per instance, with
the approach to setting them being - supply a global default, then
optionally allow per-instance overrides.

Why per-instance attributes ?  With large adapter counts (no real max,
expect > 32), the potential uses and configurations can vary widely on each.
This requirement has been confirmed by customer requests.

Why compile it in ? The view on how an attribute can be dynamically updated
is either via modules.conf or a utility that runs post module load. Given
the large adapter count and the number of attributes - it's too much for
modules.conf. Given that anything that runs post module load means the
driver has already performed adapter initialization and link bringup, it's
too late for some parameters. For these late parameters, we can reconfigure
to pick up the dynamic settings, but brief behavior with the unwanted
parameters may cause undesired effects for the user. The end result - we let
users update the values and recompile the driver. If there's a better way,
please point us in the right direction. I'd love to not require
recompilation.

Why the character parameters ? It becomes clear rapidly. Previously, we had
integer arrays, but as we didn't want to cap the number of adapters that can
be supported, nor require huge numbers of elements to be dealt with (a set
per adapter), we reduced it to 1 element per attribute - a character string
so that it can be dynamic in length. The string contains the global default,
and can be extended if there are 1 or more instances that needed specific
values. This significantly reduced the memory requirements, the number of
elements, and seemed more intuitive to specify by the user.  We also looked
at module_param_array, but this doesn't seem to work with the model of
wanting to set different defaults for different elements at compile time.

lpfc_cfgparm.h: for the most part, it's a structured way to manage the
attributes. Contains min/max so that we can verify the user didn't
inadvertantly screw up a setting, as well as knowing what to fall back to in
case they did. A couple of the elements, such as the strings, are largely
unnecessary, but could be useful for log messages.  One thing we will change
- this huge array is currently copied per instance right now. It will be
changes so that there is only 1 master array containing the boundaries, and
the current values will be the only thing kept per instance.

Can you provide some additional comments or options ?

> 
> > - lpfc_clock.c should go away, just use add_timer/etc. diretly and
> >   embedd the timer into your structures.  Yes, I know that's not
> >   how SVR4-derivates work, but Linux does.  You also have an
> >   unchecked kmalloc and a list_head cast in there..
> 
> Still not much better.  In fact the crappy datastructures and code are
> still there, just spread all over the place now instead of fixed up.

Ok - so the disagreement here really is the fact we had clock data
structures.

The data structures were for 2 purposes:
- to pass more than 1 argument to a callback.  
- to keep a "safety" list of all timers when we needed to take an adapter
offline.

Since this isn't acceptable, here's what our approach is:
- Were seeing if the need for >1 arg is really needed. If so, we'll axe this
part of the structure.
- We're removing the safety list. We shouldn't need it anyway as normal data
structure teardown should handle it.
If both happen, the structure will be gone.

> 
> > - dito for lpfc_sysfs_info_show, in short all your sysfs 
> work is completely
> >   wrong, also you seem to use driver attributes instead of 
> scsi device/host
> >   attributes.  why?
> 
> You're still attaching all the attributes yourself.  Please use the
> scsi-provided host/device attributes instead.

Ok. The way I interpret this comment: the sysfs implementation (mechanics)
is ok. The per adapter attributes are ok, with the exception of where they
overlap with scsi attributes (such as lun skip and queue depths).  I agree -
we'll remove the overlaps. This was old history..

> 
> > - the lpfc_find_target usage in queuecommand looks bogus.  You have
> >   scsi_device->hostdata to put per-lun data, from which you 
> can trivially
> >   link per-target data directly.  All the checks for 
> inquiry and valid
> >   luns are similarly b0rked - scsi probing works by calling 
> ->slave_alloc
> >   first so you'll a) have a place where you know the 
> midlayer is probing
> >   and b) always private data when quecommand is called.
> 
> While you started using sdev->hostdata the whole code is 
> still more than
> fishy.  You have a complete set of secondary data structures 
> for target/lun
> data lookup yet.  Please allocate all per-lun data in 
> ->slave_alloc and
> if the target data doesn't exist yet that one too and hang it 
> off the lun
> data.
> 

Not fishy - but done differently based on the code's history.  In either
case, we'll rework to fit the desired approach.

-- James

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [Emulex] Ready for next round...
  2004-06-18 19:56 Smart, James
@ 2004-06-18 20:58 ` 'Christoph Hellwig'
  0 siblings, 0 replies; 17+ messages in thread
From: 'Christoph Hellwig' @ 2004-06-18 20:58 UTC (permalink / raw)
  To: Smart, James; +Cc: Linux SCSI Reflector

On Fri, Jun 18, 2004 at 03:56:37PM -0400, Smart, James wrote:
> Why compile it in ? The view on how an attribute can be dynamically updated
> is either via modules.conf or a utility that runs post module load. Given
> the large adapter count and the number of attributes - it's too much for
> modules.conf.

In what way?  If there's a bug in module-init-tools or the kernel paramter
parsing please report it and we'll fix it.

> Why the character parameters ? It becomes clear rapidly. Previously, we had
> integer arrays, but as we didn't want to cap the number of adapters that can
> be supported, nor require huge numbers of elements to be dealt with (a set
> per adapter),

Capping the numbers you can pass paramters for is fine, we do it all over
the place.  Please don't try to be artifically different from other drivers,
that's the last thing we want.

> lpfc_cfgparm.h: for the most part, it's a structured way to manage the
> attributes. Contains min/max so that we can verify the user didn't
> inadvertantly screw up a setting, as well as knowing what to fall back to in
> case they did. A couple of the elements, such as the strings, are largely
> unnecessary, but could be useful for log messages.  One thing we will change
> - this huge array is currently copied per instance right now. It will be
> changes so that there is only 1 master array containing the boundaries, and
> the current values will be the only thing kept per instance.

Which then would obsolete most of that mess.  I'm looking forward to that
change.

> Since this isn't acceptable, here's what our approach is:
> - Were seeing if the need for >1 arg is really needed. If so, we'll axe this
> part of the structure.

Currently clk_data is always (at least where I checked) embedded into another
structure.  Instead of losing all type checking by using that intermediate
structure continaining void pointers just add pointers to the addition data
object directly to the structure.

> - We're removing the safety list. We shouldn't need it anyway as normal data
> structure teardown should handle it.
> If both happen, the structure will be gone.

It's actually not a safetyguard.  It's your excuse for beeing sloppy with
object lifetimes in respect to timers.  For the normal case where one
timer is used with one callback only that is:

 - init_timer, setting of callback and data on object creation
 - add_timer the first time a timer is fired off and mod_timer if it's
   running or you don't know
 - del_timer_sync on object destruction

> > > - dito for lpfc_sysfs_info_show, in short all your sysfs 
> > work is completely
> > >   wrong, also you seem to use driver attributes instead of 
> > scsi device/host
> > >   attributes.  why?
> > 
> > You're still attaching all the attributes yourself.  Please use the
> > scsi-provided host/device attributes instead.
> 
> Ok. The way I interpret this comment: the sysfs implementation (mechanics)
> is ok. The per adapter attributes are ok, with the exception of where they
> overlap with scsi attributes (such as lun skip and queue depths).  I agree -
> we'll remove the overlaps. This was old history..

Not only.  You should please use the shost_attrs and sdev_attrs fields
in struct scsi_host_template for all your attributes, please look at
the 53c700 or ipr drivers for examples.


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [Emulex] Ready for next round...
  2004-06-15 17:32 [Emulex] Ready for next round Smart, James
                   ` (2 preceding siblings ...)
  2004-06-16  8:31 ` Christoph Hellwig
@ 2004-06-20 13:35 ` Christoph Hellwig
  2004-06-23 15:31 ` Anton Blanchard
  4 siblings, 0 replies; 17+ messages in thread
From: Christoph Hellwig @ 2004-06-20 13:35 UTC (permalink / raw)
  To: Smart, James; +Cc: Linux SCSI Reflector


Can you please try to get rid of lpfc_disc_issue_rptlun()?  The scsi midlayer
already issues REPORT_LUNS on your behalf during scanning, and you should
be able to use it.  (IIRC we don't have midlayer help for the addressing mode
yet, but an addition of that would be welcome)

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [Emulex] Ready for next round...
  2004-06-15 17:32 [Emulex] Ready for next round Smart, James
                   ` (3 preceding siblings ...)
  2004-06-20 13:35 ` Christoph Hellwig
@ 2004-06-23 15:31 ` Anton Blanchard
  4 siblings, 0 replies; 17+ messages in thread
From: Anton Blanchard @ 2004-06-23 15:31 UTC (permalink / raw)
  To: Smart, James; +Cc: Linux SCSI Reflector

 
Hi,

> [From 6/1]Re: Adam Blanchard's comment on page alloc fail on ppc64, thought
> on using a mempool & Re: other queuecommand problems - too many allocations,
> allocs under spinlock, etc.

Anton :)

We tested this version and the error messages due to slave_alloc failing
are gone now. Good stuff.

Anton

^ permalink raw reply	[flat|nested] 17+ messages in thread

* RE: [Emulex] Ready for next round...
@ 2004-07-09 19:24 Smart, James
  2004-07-09 22:08 ` 'Christoph Hellwig'
  2004-07-09 22:10 ` 'Christoph Hellwig'
  0 siblings, 2 replies; 17+ messages in thread
From: Smart, James @ 2004-07-09 19:24 UTC (permalink / raw)
  To: 'Christoph Hellwig'; +Cc: Linux SCSI Reflector

Christoph,

Can you please take a look at the snapshot just posted on SourceForge.

The following things have been reworked:
- USE_HGP_HOST_SLIM: finally resolved this issue and implemented it
correctly.
- Logging: We killed lpfc_logmsg.c and converted over to a single define
using dev_printk. Still implements a subsystem filter in the macro.
- Attributes: They have been moved over to shost_attrs. We changed the basic
philosophy about per-instance attributes, as many simply aren't needed to be
set prior to attachment. This allowed them to go back integers. You will
find several removed as we removed some of the logic that insulated the
midlayer and above from transient conditions (delayed io error, etc - see
last paragraph). We killed lpfc.conf and have converted over to a separation
of attributes from their description arrays. One discrepancy - the static
configuration array for persistent bindings remains for compatibility - but
it's own file.
- Your big patch to lpfc_fcp.c - was incorporated.
- [PATCH] streamline lpfc error handling: This was incorporated. There were
some changes to clean up return codes and misplaced blocks.
- [PATCH] remove dead event counters from lpfc. Rather than remove this
code, as it will be used later, we have at least consolidated it and made
the events visible via sysfs.


Things we're still addressing - and should be in drop on 7/16:
- clk_data: We're removing the safety list, and converting from multiple
clock args to 1 so that it better maps to the kernel api.
- secondary data structures for target/lun data : We're attempting to
reduce/remove the notions of luns as, in general, the driver issues i/o at
the target level. Part of this is removing report luns use, etc. Note: We
will see if we can help the midlayer with addressing mode support.

We have one major issue, which has been partially discussed already
(http://marc.theaimsgroup.com/?l=linux-scsi&m=108275840501608&w=2). In
summary, there are discovery state machine events when we lose connectivity
with the target for a short period. If we do not suspend i/o to the target,
the upper layer retries can exhaust before the target comes back, triggering
other system error reports/problems/etc.  James Bottomly suggested adding a
scsi device SUSPEND function. We are actively addressing this and you should
see a conversation started shortly.


-- James S



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [Emulex] Ready for next round...
  2004-07-09 19:24 Smart, James
@ 2004-07-09 22:08 ` 'Christoph Hellwig'
  2004-07-09 22:10 ` 'Christoph Hellwig'
  1 sibling, 0 replies; 17+ messages in thread
From: 'Christoph Hellwig' @ 2004-07-09 22:08 UTC (permalink / raw)
  To: Smart, James; +Cc: Linux SCSI Reflector

On Fri, Jul 09, 2004 at 03:24:14PM -0400, Smart, James wrote:
> Christoph,
> 
> Can you please take a look at the snapshot just posted on SourceForge.

Unfortunatley the links on sourceforge are broken.  Any chance you could
host your tarballs somewhere else?  Besides the always annoying deep link
hiearchies sourceforge tends to also have all kinds of major outages these
days. 

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [Emulex] Ready for next round...
  2004-07-09 19:24 Smart, James
  2004-07-09 22:08 ` 'Christoph Hellwig'
@ 2004-07-09 22:10 ` 'Christoph Hellwig'
  1 sibling, 0 replies; 17+ messages in thread
From: 'Christoph Hellwig' @ 2004-07-09 22:10 UTC (permalink / raw)
  To: Smart, James; +Cc: 'Christoph Hellwig', Linux SCSI Reflector

> - [PATCH] remove dead event counters from lpfc. Rather than remove this
> code, as it will be used later, we have at least consolidated it and made
> the events visible via sysfs.

Still a bad idea to keep dead code around.  Propose the chances if you have
a sysfs implementation, I'm pretty sure it will need major rework.

Btw, if someone sends you patches it would be nice to get timely applied/not
applied/needs works/please changes this and that feedback after you looked
at the patch.


^ permalink raw reply	[flat|nested] 17+ messages in thread

* RE: [Emulex] Ready for next round...
@ 2004-07-17 11:26 Smart, James
  2004-07-17 20:17 ` 'Christoph Hellwig'
  0 siblings, 1 reply; 17+ messages in thread
From: Smart, James @ 2004-07-17 11:26 UTC (permalink / raw)
  To: Smart, James, 'Christoph Hellwig'; +Cc: Linux SCSI Reflector

Christoph,

We've updated the driver on SourceForge again.  This addresses the rework of
the clk functions. Also rids the driver of Report Lun use.

I know this next week will probably be busy due to the OLS, but we would
appreciate comments any time that you can provide them.

Thanks.

- James S


> -----Original Message-----
> From: Smart, James 
> Sent: Friday, July 09, 2004 3:24 PM
> To: 'Christoph Hellwig'
> Cc: Linux SCSI Reflector
> Subject: RE: [Emulex] Ready for next round...
> 
> 
> Christoph,
> 
> Can you please take a look at the snapshot just posted on SourceForge.
> 
> The following things have been reworked:
> - USE_HGP_HOST_SLIM: finally resolved this issue and implemented it
> correctly.
> - Logging: We killed lpfc_logmsg.c and converted over to a 
> single define
> using dev_printk. Still implements a subsystem filter in the macro.
> - Attributes: They have been moved over to shost_attrs. We 
> changed the basic
> philosophy about per-instance attributes, as many simply 
> aren't needed to be
> set prior to attachment. This allowed them to go back 
> integers. You will
> find several removed as we removed some of the logic that 
> insulated the
> midlayer and above from transient conditions (delayed io 
> error, etc - see
> last paragraph). We killed lpfc.conf and have converted over 
> to a separation
> of attributes from their description arrays. One discrepancy 
> - the static
> configuration array for persistent bindings remains for 
> compatibility - but
> it's own file.
> - Your big patch to lpfc_fcp.c - was incorporated.
> - [PATCH] streamline lpfc error handling: This was 
> incorporated. There were
> some changes to clean up return codes and misplaced blocks.
> - [PATCH] remove dead event counters from lpfc. Rather than 
> remove this
> code, as it will be used later, we have at least consolidated 
> it and made
> the events visible via sysfs.
> 
> 
> Things we're still addressing - and should be in drop on 7/16:
> - clk_data: We're removing the safety list, and converting 
> from multiple
> clock args to 1 so that it better maps to the kernel api.
> - secondary data structures for target/lun data : We're attempting to
> reduce/remove the notions of luns as, in general, the driver 
> issues i/o at
> the target level. Part of this is removing report luns use, 
> etc. Note: We
> will see if we can help the midlayer with addressing mode support.
> 
> We have one major issue, which has been partially discussed already
> (http://marc.theaimsgroup.com/?l=linux-scsi&m=108275840501608&w=2). In
> summary, there are discovery state machine events when we 
> lose connectivity
> with the target for a short period. If we do not suspend i/o 
> to the target,
> the upper layer retries can exhaust before the target comes 
> back, triggering
> other system error reports/problems/etc.  James Bottomly 
> suggested adding a
> scsi device SUSPEND function. We are actively addressing this 
> and you should
> see a conversation started shortly.
> 
> 
> -- James S
> 
> 
> -
> To unsubscribe from this list: send the line "unsubscribe 
> linux-scsi" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [Emulex] Ready for next round...
  2004-07-17 11:26 Smart, James
@ 2004-07-17 20:17 ` 'Christoph Hellwig'
  2004-07-17 20:26   ` 'Christoph Hellwig'
  0 siblings, 1 reply; 17+ messages in thread
From: 'Christoph Hellwig' @ 2004-07-17 20:17 UTC (permalink / raw)
  To: Smart, James; +Cc: 'Christoph Hellwig', Linux SCSI Reflector

On Sat, Jul 17, 2004 at 07:26:32AM -0400, Smart, James wrote:
> Christoph,
> 
> We've updated the driver on SourceForge again.  This addresses the rework of
> the clk functions. Also rids the driver of Report Lun use.
> 
> I know this next week will probably be busy due to the OLS, but we would
> appreciate comments any time that you can provide them.

Okay, this starts to look better.  There's lots of dead code again, see the
patch below to remove it.  Also while the parameter rework in the last drop
is already much better it still needs some more work I think.

Instead of the array + index approach use a simple variable in struct
lpfc_hba, that of cousr makes your paraneter checking a little more difficult,
but I'd suggest to just reomve it like the other drivers - after all it's
root only.
Easiest would be to just drop the range checking, as all other drivers do


diff -uNr -X /home/hch/dontdiff lpfcdriver-2.6-8.0.6/lpfc.h lpfcdriver-2.6-8.0.6-hch/lpfc.h
--- lpfcdriver-2.6-8.0.6/lpfc.h	2004-07-16 20:59:54.000000000 +0200
+++ lpfcdriver-2.6-8.0.6-hch/lpfc.h	2004-07-17 21:07:40.000000000 +0200
@@ -411,9 +411,7 @@
 	/* pci_mem_pools */
 	struct pci_pool *lpfc_scsi_dma_ext_pool;
 	struct pci_pool *lpfc_mbuf_pool;
-	struct pci_pool *lpfc_page_pool;
 	struct lpfc_dma_pool lpfc_mbuf_safety_pool;
-	struct lpfc_dma_pool lpfc_page_safety_pool;
 	mempool_t *scsibuf_mem_pool;
 
 	mempool_t *iocb_mem_pool;
diff -uNr -X /home/hch/dontdiff lpfcdriver-2.6-8.0.6/lpfc_crtn.h lpfcdriver-2.6-8.0.6-hch/lpfc_crtn.h
--- lpfcdriver-2.6-8.0.6/lpfc_crtn.h	2004-07-16 20:59:54.000000000 +0200
+++ lpfcdriver-2.6-8.0.6-hch/lpfc_crtn.h	2004-07-17 20:57:50.000000000 +0200
@@ -76,13 +76,9 @@
 void lpfc_disc_start(struct lpfc_hba *);
 void lpfc_disc_flush_list(struct lpfc_hba *);
 void lpfc_linkdown_timeout(unsigned long);
-void lpfc_nodev_timeout(unsigned long);
 void lpfc_establish_link_tmo(unsigned long);
 void lpfc_disc_timeout(unsigned long);
 struct lpfc_lun *lpfc_find_lun(struct lpfc_hba *, uint32_t, uint64_t, int);
-struct lpfc_scsi_buf *lpfc_build_scsi_cmd(struct lpfc_hba *,
-					  struct lpfc_nodelist *,
-					  uint32_t, uint64_t);
 void lpfc_set_failmask(struct lpfc_hba *, struct lpfc_nodelist *, uint32_t,
 		       uint32_t);
 
@@ -223,7 +219,6 @@
 			    uint16_t);
 void lpfc_mbox_timeout(unsigned long);
 
-void lpfc_free_scsi_buf(struct lpfc_scsi_buf *);
 void lpfc_map_fcp_cmnd_to_bpl(struct lpfc_hba *, struct lpfc_scsi_buf *);
 void lpfc_free_scsi_cmd(struct lpfc_scsi_buf *);
 uint32_t lpfc_os_timeout_transform(struct lpfc_hba *, uint32_t);
@@ -242,9 +237,6 @@
 void lpfc_sli_wake_iocb_high_priority(struct lpfc_hba * phba,
 				      struct lpfc_iocbq * queue1,
 				      struct lpfc_iocbq * queue2);
-void *lpfc_page_alloc(struct lpfc_hba *, int, dma_addr_t *);
-void lpfc_page_free(struct lpfc_hba *, void *, dma_addr_t);
-
 void *lpfc_mbuf_alloc(struct lpfc_hba *, int, dma_addr_t *);
 void lpfc_mbuf_free(struct lpfc_hba *, void *, dma_addr_t);
 
diff -uNr -X /home/hch/dontdiff lpfcdriver-2.6-8.0.6/lpfc_hbadisc.c lpfcdriver-2.6-8.0.6-hch/lpfc_hbadisc.c
--- lpfcdriver-2.6-8.0.6/lpfc_hbadisc.c	2004-07-16 20:59:54.000000000 +0200
+++ lpfcdriver-2.6-8.0.6-hch/lpfc_hbadisc.c	2004-07-17 20:57:30.000000000 +0200
@@ -2450,7 +2450,7 @@
 	return;
 }
 
-void
+static void
 lpfc_nodev_timeout(unsigned long ptr)
 {
 	struct lpfc_hba *phba;
diff -uNr -X /home/hch/dontdiff lpfcdriver-2.6-8.0.6/lpfc_mem.c lpfcdriver-2.6-8.0.6-hch/lpfc_mem.c
--- lpfcdriver-2.6-8.0.6/lpfc_mem.c	2004-07-16 20:59:54.000000000 +0200
+++ lpfcdriver-2.6-8.0.6-hch/lpfc_mem.c	2004-07-17 21:08:10.000000000 +0200
@@ -40,12 +40,8 @@
 static void lpfc_mem_safety_pool_destroy(struct lpfc_hba *);
 static void lpfc_mbuf_safety_pool_create(struct lpfc_hba *, uint32_t );
 static void lpfc_mbuf_safety_pool_destroy(struct lpfc_hba *);
-static void lpfc_page_safety_pool_create(struct lpfc_hba *, uint32_t );
-static void lpfc_page_safety_pool_destroy(struct lpfc_hba *);
 void *lpfc_mbuf_alloc(struct lpfc_hba *, int, dma_addr_t *);
 void lpfc_mbuf_free(struct lpfc_hba *, void *, dma_addr_t);
-void *lpfc_page_alloc(struct lpfc_hba *, int, dma_addr_t *);
-void lpfc_page_free(struct lpfc_hba *, void *, dma_addr_t);
 static void *lpfc_scsibuf_pool_alloc(int , void *);
 static void  lpfc_scsibuf_pool_free(void *, void *);
 
@@ -66,8 +62,6 @@
 
 	phba->lpfc_scsi_dma_ext_pool = 0;
 	phba->lpfc_mbuf_pool = 0;
-	phba->lpfc_page_pool = 0;
-
 
 	phba->lpfc_scsi_dma_ext_pool =
 		pci_pool_create("lpfc_scsi_dma_ext_pool",
@@ -83,21 +77,12 @@
 				8,
 				0);
 
-	phba->lpfc_page_pool =
-		pci_pool_create("lpfc_page_pool",
-				phba->pcidev,
-				LPFC_SCSI_PAGE_BUF_SZ,
-				8,
-				0);
-
-	if ((!phba->lpfc_scsi_dma_ext_pool) || (!phba->lpfc_mbuf_pool) ||
-	   (!phba->lpfc_page_pool)) {
+	if (!phba->lpfc_scsi_dma_ext_pool || !phba->lpfc_mbuf_pool)
 		lpfc_mem_free(phba);
 		return (0);
 	}
 
 	lpfc_mbuf_safety_pool_create(phba, LPFC_MBUF_POOL_SIZE);
-	lpfc_page_safety_pool_create(phba, LPFC_PAGE_POOL_SIZE);
 	lpfc_mem_safety_pool_create(phba, LPFC_MEM_POOL_SIZE);
 
 	return (1);
@@ -126,7 +111,6 @@
 	}
 
 	lpfc_mbuf_safety_pool_destroy(phba);
-	lpfc_page_safety_pool_destroy(phba);
 	lpfc_mem_safety_pool_destroy(phba);
 
 	if (phba->lpfc_scsi_dma_ext_pool)
@@ -134,11 +118,7 @@
 
 	if (phba->lpfc_mbuf_pool)
 		pci_pool_destroy(phba->lpfc_mbuf_pool);
-
-	if (phba->lpfc_page_pool)
-		pci_pool_destroy(phba->lpfc_page_pool);
-
-	return (1);
+	return 1;
 }
 
 void
@@ -232,51 +212,6 @@
 	kfree(pool->elements);
 }
 
-
-static void
-lpfc_page_safety_pool_create(struct lpfc_hba * phba, uint32_t count)
-{
-	int i;
-
-	struct lpfc_dma_pool *pool =
-		&(phba->lpfc_page_safety_pool);
-
-	pool->elements = kmalloc(sizeof(struct lpfc_dmabuf) * count,
-				 GFP_KERNEL);
-	pool->max_count = 0;
-	pool->current_count = 0;
-	for ( i=0; i<count; i++) {
-		pool->elements[i].virt =
-			pci_pool_alloc(phba->lpfc_page_pool,
-				       GFP_KERNEL,
-				       &(pool->elements[i].phys));
-
-		if (!pool->elements[i].virt)
-			break;
-		pool->max_count++;
-		pool->current_count++;
-	}
-}
-
-static void
-lpfc_page_safety_pool_destroy(struct lpfc_hba * phba)
-{
-	struct lpfc_dma_pool *pool =
-		&(phba->lpfc_page_safety_pool);
-	int i;
-
-	if ( pool->max_count != pool->current_count)
-		printk("Memory leaked in page safety pool \n");
-
-	for (i=0; i< pool->current_count; i++) {
-		pci_pool_free(phba->lpfc_page_pool,
-			      pool->elements[i].virt,
-			      pool->elements[i].phys);
-	}
-
-	kfree(pool->elements);
-}
-
 void *
 lpfc_mbuf_alloc(struct lpfc_hba * phba, int mem_flags, dma_addr_t * handle)
 {
@@ -315,44 +250,6 @@
 	return;
 }
 
-void *
-lpfc_page_alloc(struct lpfc_hba * phba, int mem_flags, dma_addr_t * handle)
-{
-	void *ret;
-	struct lpfc_dma_pool *pool =
-		&(phba->lpfc_page_safety_pool);
-
-	ret = pci_pool_alloc(phba->lpfc_page_pool, GFP_ATOMIC, handle);
-	/*
-	   If we are low in memory and is priority memory allocation
-	   use safety pool
-	*/
-	if ((!ret) && ( mem_flags & MEM_PRI)
-	    && (pool->current_count)) {
-		pool->current_count--;
-		ret = pool->elements[pool->current_count].virt;
-		*handle = pool->elements[pool->current_count].phys;
-	}
-	return ret;
-}
-
-void
-lpfc_page_free(struct lpfc_hba * phba, void *virt, dma_addr_t dma)
-{
-	struct lpfc_dma_pool *pool =
-		&(phba->lpfc_page_safety_pool);
-
-	if ( pool->current_count < pool->max_count) {
-		pool->elements[pool->current_count].virt = virt;
-		pool->elements[pool->current_count].phys = dma;
-		pool->current_count++;
-		return;
-	}
-
-	pci_pool_free(phba->lpfc_page_pool, virt, dma);
-	return;
-}
-
 static void *
 lpfc_scsibuf_pool_alloc(int gfp_flags, void *data) {
 	void * ret;
diff -uNr -X /home/hch/dontdiff lpfcdriver-2.6-8.0.6/lpfc_scsiport.c lpfcdriver-2.6-8.0.6-hch/lpfc_scsiport.c
--- lpfcdriver-2.6-8.0.6/lpfc_scsiport.c	2004-07-16 20:59:54.000000000 +0200
+++ lpfcdriver-2.6-8.0.6-hch/lpfc_scsiport.c	2004-07-17 20:56:01.000000000 +0200
@@ -185,7 +185,7 @@
 }
 
 /* This routine frees a scsi buffer, both DMAable and non-DMAable regions */
-void
+static void
 lpfc_free_scsi_buf(struct lpfc_scsi_buf * psb)
 {
 	struct lpfc_hba *phba;
@@ -1127,177 +1127,6 @@
 	return ret;
 }
 
-struct lpfc_scsi_buf *
-lpfc_build_scsi_cmd(struct lpfc_hba * phba,
-		    struct lpfc_nodelist * nlp, uint32_t scsi_cmd, uint64_t lun)
-{
-	struct lpfc_sli *psli;
-	struct lpfc_target *targetp;
-	struct lpfc_lun *lunp;
-	struct lpfc_dmabuf *mp;
-	struct lpfc_scsi_buf *lpfc_cmd;
-	struct lpfc_iocbq *piocbq;
-	IOCB_t *piocb;
-	struct fcp_cmnd *fcpCmnd;
-	struct ulp_bde64 *bpl;
-	uint32_t tgt, size;
-	struct scsi_cmnd *lnx_cmd;
-	struct scsi_device *scsi_dev;
-
-	tgt = nlp->nlp_sid;
-	lunp = lpfc_find_lun(phba, tgt, lun, 1);
-	lpfc_cmd = 0;
-	/* First see if the SCSI ID has an allocated struct lpfc_target */
-	if (lunp && lunp->pTarget) {
-		targetp = lunp->pTarget;
-		psli = &phba->sli;
-
-		/* Get a buffer to hold SCSI data */
-		mp = kmalloc(sizeof (struct lpfc_dmabuf), GFP_ATOMIC);
-		if (mp == 0) {
-			return (0);
-		}
-
-		INIT_LIST_HEAD(&mp->list);
-		/* Get resources to send a SCSI command */
-		lpfc_cmd = lpfc_get_scsi_buf(phba, GFP_ATOMIC);
-		if (lpfc_cmd == 0) {
-			kfree(mp);
-			return (0);
-		}
-		lpfc_cmd->pLun = lunp;
-		/* Internal-generated cmd, so we need to create a temporary
-		 * linux scsi_cmnd and scsi_device.
-		 * Also means when this internal cmd done, we need to free
-		 * this scsi_cmnd and scsi_device structures.
-		 */
-		lnx_cmd = kmalloc(sizeof(struct scsi_cmnd), GFP_ATOMIC);
-		if (lnx_cmd == 0) {
-			kfree(mp);
-			lpfc_free_scsi_buf(lpfc_cmd);
-			return (0);
-		}
-		scsi_dev = kmalloc(sizeof(struct scsi_device), GFP_ATOMIC);
-		if (scsi_dev == 0) {
-			kfree(mp);
-			kfree(lnx_cmd);
-			lpfc_free_scsi_buf(lpfc_cmd);
-			return (0);
-		}
-		scsi_dev->id = tgt;
-		scsi_dev->lun = lun;
-		scsi_dev->hostdata = lunp;
-		lnx_cmd->device = scsi_dev;
-		lpfc_cmd->pCmd = lnx_cmd;
-		lpfc_cmd->timeout = 30 + phba->fcp_timeout_offset;
-
-		/* Finish building BPL with the I/O dma ptrs.
-		 * setup FCP CMND, and setup IOCB.
-		 */
-
-		fcpCmnd = lpfc_cmd->fcp_cmnd;
-
-		putLunHigh(fcpCmnd->fcpLunMsl, lun);	/* LUN */
-		putLunLow(fcpCmnd->fcpLunLsl, lun);	/* LUN */
-
-		switch (scsi_cmd) {
-		case REPORT_LUNS:
-			size = LPFC_SCSI_PAGE_BUF_SZ;
-			fcpCmnd->fcpCdb[0] = scsi_cmd;
-			/* 0x1000 = LPFC_SCSI_PAGE_BUF_SZ */
-			fcpCmnd->fcpCdb[8] = 0x10;
-			fcpCmnd->fcpCdb[9] = 0x00;
-			fcpCmnd->fcpCntl3 = READ_DATA;
-			fcpCmnd->fcpDl = be32_to_cpu(LPFC_SCSI_PAGE_BUF_SZ);
-			/* Get a buffer to hold SCSI data */
-			if ((mp->virt =
-			     lpfc_page_alloc(phba, 0, &(mp->phys))) == 0) {
-				if (mp)
-					kfree(mp);
-				lpfc_free_scsi_buf(lpfc_cmd);
-				return (0);
-			}
-			break;
-		case INQUIRY:
-			fcpCmnd->fcpCdb[0] = scsi_cmd;	/* SCSI Inquiry
-							   Command */
-			fcpCmnd->fcpCdb[4] = 0xff;	/* allocation length */
-			fcpCmnd->fcpCntl3 = READ_DATA;
-			fcpCmnd->fcpDl = be32_to_cpu(LPFC_SCSI_BUF_SZ);
-			/* drop thru to get a buffer */
-		default:
-			size = LPFC_SCSI_BUF_SZ;
-			/* Get a buffer to hold SCSI data */
-			if ((mp->virt =
-			     lpfc_mbuf_alloc(phba, 0, &(mp->phys))) == 0) {
-				if (mp)
-					kfree(mp);
-				lpfc_free_scsi_buf(lpfc_cmd);
-				return (0);
-			}
-			break;
-		}
-
-		bpl = lpfc_cmd->fcp_bpl;
-		bpl += 2;	/* Bump past FCP CMND and FCP RSP */
-
-		/* no scatter-gather list case */
-		bpl->addrLow = le32_to_cpu(putPaddrLow(mp->phys));
-		bpl->addrHigh = le32_to_cpu(putPaddrHigh(mp->phys));
-		bpl->tus.f.bdeSize = size;
-		bpl->tus.f.bdeFlags = BUFF_USE_RCV;
-		bpl->tus.w = le32_to_cpu(bpl->tus.w);
-		bpl++;
-		bpl->addrHigh = 0;
-		bpl->addrLow = 0;
-		bpl->tus.w = 0;
-
-		piocbq = &lpfc_cmd->cur_iocbq;
-		piocb = &piocbq->iocb;
-		piocb->ulpCommand = CMD_FCP_IREAD64_CR;
-		piocb->ulpPU = PARM_READ_CHECK;
-		piocb->un.fcpi.fcpi_parm = size;
-		piocb->un.fcpi64.bdl.bdeSize += sizeof (struct ulp_bde64);
-		piocb->ulpBdeCount = 1;
-		piocb->ulpLe = 1;	/* Set the LE bit in the iocb */
-
-		/* Get an iotag and finish setup of IOCB  */
-		piocb->ulpIoTag = lpfc_sli_next_iotag(phba,
-					      &phba->sli.ring[psli->fcp_ring]);
-		piocb->ulpContext = nlp->nlp_rpi;
-		if (nlp->nlp_fcp_info & NLP_FCP_2_DEVICE) {
-			piocb->ulpFCP2Rcvy = 1;
-		}
-		piocb->ulpClass = (nlp->nlp_fcp_info & 0x0f);
-
-		/* ulpTimeout is only one byte */
-		if (lpfc_cmd->timeout > 0xff) {
-			/*
-			 * Do not timeout the command at the firmware level.
-			 * The driver will provide the timeout mechanism.
-			 */
-			piocb->ulpTimeout = 0;
-		} else {
-			piocb->ulpTimeout = lpfc_cmd->timeout;
-		}
-
-		/*
-		 * Setup driver timeout, in case the command does not complete
-		 * Driver timeout should be greater than ulpTimeout
-		 */
-
-		piocbq->drvrTimeout = lpfc_cmd->timeout + LPFC_DRVR_TIMEOUT;
-
-		/* set up iocb return path by setting the context fields
-		 * and the completion function.
-		 */
-		piocbq->context1 = lpfc_cmd;
-		piocbq->context2 = mp;
-
-	}
-	return (lpfc_cmd);
-}
-
 void
 lpfc_scsi_timeout_handler(unsigned long ptr)
 {

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [Emulex] Ready for next round...
  2004-07-17 20:17 ` 'Christoph Hellwig'
@ 2004-07-17 20:26   ` 'Christoph Hellwig'
  0 siblings, 0 replies; 17+ messages in thread
From: 'Christoph Hellwig' @ 2004-07-17 20:26 UTC (permalink / raw)
  To: Smart, James; +Cc: 'Christoph Hellwig', Linux SCSI Reflector

On Sat, Jul 17, 2004 at 09:17:35PM +0100, 'Christoph Hellwig' wrote:
> On Sat, Jul 17, 2004 at 07:26:32AM -0400, Smart, James wrote:
> > Christoph,
> > 
> > We've updated the driver on SourceForge again.  This addresses the rework of
> > the clk functions. Also rids the driver of Report Lun use.
> > 
> > I know this next week will probably be busy due to the OLS, but we would
> > appreciate comments any time that you can provide them.
> 
> Okay, this starts to look better.  There's lots of dead code again, see the
> patch below to remove it.  Also while the parameter rework in the last drop
> is already much better it still needs some more work I think.

Sorry, wrong patch.  The correct one is below.


diff -uNr -X /home/hch/dontdiff lpfcdriver-2.6-8.0.6/lpfc.h lpfcdriver-2.6-8.0.6-hch/lpfc.h
--- lpfcdriver-2.6-8.0.6/lpfc.h	2004-07-16 20:59:54.000000000 +0200
+++ lpfcdriver-2.6-8.0.6-hch/lpfc.h	2004-07-17 21:07:40.000000000 +0200
@@ -411,9 +411,7 @@
 	/* pci_mem_pools */
 	struct pci_pool *lpfc_scsi_dma_ext_pool;
 	struct pci_pool *lpfc_mbuf_pool;
-	struct pci_pool *lpfc_page_pool;
 	struct lpfc_dma_pool lpfc_mbuf_safety_pool;
-	struct lpfc_dma_pool lpfc_page_safety_pool;
 	mempool_t *scsibuf_mem_pool;
 
 	mempool_t *iocb_mem_pool;
diff -uNr -X /home/hch/dontdiff lpfcdriver-2.6-8.0.6/lpfc_crtn.h lpfcdriver-2.6-8.0.6-hch/lpfc_crtn.h
--- lpfcdriver-2.6-8.0.6/lpfc_crtn.h	2004-07-16 20:59:54.000000000 +0200
+++ lpfcdriver-2.6-8.0.6-hch/lpfc_crtn.h	2004-07-17 20:57:50.000000000 +0200
@@ -76,13 +76,9 @@
 void lpfc_disc_start(struct lpfc_hba *);
 void lpfc_disc_flush_list(struct lpfc_hba *);
 void lpfc_linkdown_timeout(unsigned long);
-void lpfc_nodev_timeout(unsigned long);
 void lpfc_establish_link_tmo(unsigned long);
 void lpfc_disc_timeout(unsigned long);
 struct lpfc_lun *lpfc_find_lun(struct lpfc_hba *, uint32_t, uint64_t, int);
-struct lpfc_scsi_buf *lpfc_build_scsi_cmd(struct lpfc_hba *,
-					  struct lpfc_nodelist *,
-					  uint32_t, uint64_t);
 void lpfc_set_failmask(struct lpfc_hba *, struct lpfc_nodelist *, uint32_t,
 		       uint32_t);
 
@@ -223,7 +219,6 @@
 			    uint16_t);
 void lpfc_mbox_timeout(unsigned long);
 
-void lpfc_free_scsi_buf(struct lpfc_scsi_buf *);
 void lpfc_map_fcp_cmnd_to_bpl(struct lpfc_hba *, struct lpfc_scsi_buf *);
 void lpfc_free_scsi_cmd(struct lpfc_scsi_buf *);
 uint32_t lpfc_os_timeout_transform(struct lpfc_hba *, uint32_t);
@@ -242,9 +237,6 @@
 void lpfc_sli_wake_iocb_high_priority(struct lpfc_hba * phba,
 				      struct lpfc_iocbq * queue1,
 				      struct lpfc_iocbq * queue2);
-void *lpfc_page_alloc(struct lpfc_hba *, int, dma_addr_t *);
-void lpfc_page_free(struct lpfc_hba *, void *, dma_addr_t);
-
 void *lpfc_mbuf_alloc(struct lpfc_hba *, int, dma_addr_t *);
 void lpfc_mbuf_free(struct lpfc_hba *, void *, dma_addr_t);
 
diff -uNr -X /home/hch/dontdiff lpfcdriver-2.6-8.0.6/lpfc_hbadisc.c lpfcdriver-2.6-8.0.6-hch/lpfc_hbadisc.c
--- lpfcdriver-2.6-8.0.6/lpfc_hbadisc.c	2004-07-16 20:59:54.000000000 +0200
+++ lpfcdriver-2.6-8.0.6-hch/lpfc_hbadisc.c	2004-07-17 20:57:30.000000000 +0200
@@ -2450,7 +2450,7 @@
 	return;
 }
 
-void
+static void
 lpfc_nodev_timeout(unsigned long ptr)
 {
 	struct lpfc_hba *phba;
diff -uNr -X /home/hch/dontdiff lpfcdriver-2.6-8.0.6/lpfc_mem.c lpfcdriver-2.6-8.0.6-hch/lpfc_mem.c
--- lpfcdriver-2.6-8.0.6/lpfc_mem.c	2004-07-16 20:59:54.000000000 +0200
+++ lpfcdriver-2.6-8.0.6-hch/lpfc_mem.c	2004-07-17 21:08:10.000000000 +0200
@@ -40,12 +40,8 @@
 static void lpfc_mem_safety_pool_destroy(struct lpfc_hba *);
 static void lpfc_mbuf_safety_pool_create(struct lpfc_hba *, uint32_t );
 static void lpfc_mbuf_safety_pool_destroy(struct lpfc_hba *);
-static void lpfc_page_safety_pool_create(struct lpfc_hba *, uint32_t );
-static void lpfc_page_safety_pool_destroy(struct lpfc_hba *);
 void *lpfc_mbuf_alloc(struct lpfc_hba *, int, dma_addr_t *);
 void lpfc_mbuf_free(struct lpfc_hba *, void *, dma_addr_t);
-void *lpfc_page_alloc(struct lpfc_hba *, int, dma_addr_t *);
-void lpfc_page_free(struct lpfc_hba *, void *, dma_addr_t);
 static void *lpfc_scsibuf_pool_alloc(int , void *);
 static void  lpfc_scsibuf_pool_free(void *, void *);
 
@@ -66,8 +62,6 @@
 
 	phba->lpfc_scsi_dma_ext_pool = 0;
 	phba->lpfc_mbuf_pool = 0;
-	phba->lpfc_page_pool = 0;
-
 
 	phba->lpfc_scsi_dma_ext_pool =
 		pci_pool_create("lpfc_scsi_dma_ext_pool",
@@ -83,21 +77,12 @@
 				8,
 				0);
 
-	phba->lpfc_page_pool =
-		pci_pool_create("lpfc_page_pool",
-				phba->pcidev,
-				LPFC_SCSI_PAGE_BUF_SZ,
-				8,
-				0);
-
-	if ((!phba->lpfc_scsi_dma_ext_pool) || (!phba->lpfc_mbuf_pool) ||
-	   (!phba->lpfc_page_pool)) {
+	if (!phba->lpfc_scsi_dma_ext_pool || !phba->lpfc_mbuf_pool) {
 		lpfc_mem_free(phba);
 		return (0);
 	}
 
 	lpfc_mbuf_safety_pool_create(phba, LPFC_MBUF_POOL_SIZE);
-	lpfc_page_safety_pool_create(phba, LPFC_PAGE_POOL_SIZE);
 	lpfc_mem_safety_pool_create(phba, LPFC_MEM_POOL_SIZE);
 
 	return (1);
@@ -126,7 +111,6 @@
 	}
 
 	lpfc_mbuf_safety_pool_destroy(phba);
-	lpfc_page_safety_pool_destroy(phba);
 	lpfc_mem_safety_pool_destroy(phba);
 
 	if (phba->lpfc_scsi_dma_ext_pool)
@@ -134,11 +118,7 @@
 
 	if (phba->lpfc_mbuf_pool)
 		pci_pool_destroy(phba->lpfc_mbuf_pool);
-
-	if (phba->lpfc_page_pool)
-		pci_pool_destroy(phba->lpfc_page_pool);
-
-	return (1);
+	return 1;
 }
 
 void
@@ -232,51 +212,6 @@
 	kfree(pool->elements);
 }
 
-
-static void
-lpfc_page_safety_pool_create(struct lpfc_hba * phba, uint32_t count)
-{
-	int i;
-
-	struct lpfc_dma_pool *pool =
-		&(phba->lpfc_page_safety_pool);
-
-	pool->elements = kmalloc(sizeof(struct lpfc_dmabuf) * count,
-				 GFP_KERNEL);
-	pool->max_count = 0;
-	pool->current_count = 0;
-	for ( i=0; i<count; i++) {
-		pool->elements[i].virt =
-			pci_pool_alloc(phba->lpfc_page_pool,
-				       GFP_KERNEL,
-				       &(pool->elements[i].phys));
-
-		if (!pool->elements[i].virt)
-			break;
-		pool->max_count++;
-		pool->current_count++;
-	}
-}
-
-static void
-lpfc_page_safety_pool_destroy(struct lpfc_hba * phba)
-{
-	struct lpfc_dma_pool *pool =
-		&(phba->lpfc_page_safety_pool);
-	int i;
-
-	if ( pool->max_count != pool->current_count)
-		printk("Memory leaked in page safety pool \n");
-
-	for (i=0; i< pool->current_count; i++) {
-		pci_pool_free(phba->lpfc_page_pool,
-			      pool->elements[i].virt,
-			      pool->elements[i].phys);
-	}
-
-	kfree(pool->elements);
-}
-
 void *
 lpfc_mbuf_alloc(struct lpfc_hba * phba, int mem_flags, dma_addr_t * handle)
 {
@@ -315,44 +250,6 @@
 	return;
 }
 
-void *
-lpfc_page_alloc(struct lpfc_hba * phba, int mem_flags, dma_addr_t * handle)
-{
-	void *ret;
-	struct lpfc_dma_pool *pool =
-		&(phba->lpfc_page_safety_pool);
-
-	ret = pci_pool_alloc(phba->lpfc_page_pool, GFP_ATOMIC, handle);
-	/*
-	   If we are low in memory and is priority memory allocation
-	   use safety pool
-	*/
-	if ((!ret) && ( mem_flags & MEM_PRI)
-	    && (pool->current_count)) {
-		pool->current_count--;
-		ret = pool->elements[pool->current_count].virt;
-		*handle = pool->elements[pool->current_count].phys;
-	}
-	return ret;
-}
-
-void
-lpfc_page_free(struct lpfc_hba * phba, void *virt, dma_addr_t dma)
-{
-	struct lpfc_dma_pool *pool =
-		&(phba->lpfc_page_safety_pool);
-
-	if ( pool->current_count < pool->max_count) {
-		pool->elements[pool->current_count].virt = virt;
-		pool->elements[pool->current_count].phys = dma;
-		pool->current_count++;
-		return;
-	}
-
-	pci_pool_free(phba->lpfc_page_pool, virt, dma);
-	return;
-}
-
 static void *
 lpfc_scsibuf_pool_alloc(int gfp_flags, void *data) {
 	void * ret;
diff -uNr -X /home/hch/dontdiff lpfcdriver-2.6-8.0.6/lpfc_scsiport.c lpfcdriver-2.6-8.0.6-hch/lpfc_scsiport.c
--- lpfcdriver-2.6-8.0.6/lpfc_scsiport.c	2004-07-16 20:59:54.000000000 +0200
+++ lpfcdriver-2.6-8.0.6-hch/lpfc_scsiport.c	2004-07-17 20:56:01.000000000 +0200
@@ -185,7 +185,7 @@
 }
 
 /* This routine frees a scsi buffer, both DMAable and non-DMAable regions */
-void
+static void
 lpfc_free_scsi_buf(struct lpfc_scsi_buf * psb)
 {
 	struct lpfc_hba *phba;
@@ -1127,177 +1127,6 @@
 	return ret;
 }
 
-struct lpfc_scsi_buf *
-lpfc_build_scsi_cmd(struct lpfc_hba * phba,
-		    struct lpfc_nodelist * nlp, uint32_t scsi_cmd, uint64_t lun)
-{
-	struct lpfc_sli *psli;
-	struct lpfc_target *targetp;
-	struct lpfc_lun *lunp;
-	struct lpfc_dmabuf *mp;
-	struct lpfc_scsi_buf *lpfc_cmd;
-	struct lpfc_iocbq *piocbq;
-	IOCB_t *piocb;
-	struct fcp_cmnd *fcpCmnd;
-	struct ulp_bde64 *bpl;
-	uint32_t tgt, size;
-	struct scsi_cmnd *lnx_cmd;
-	struct scsi_device *scsi_dev;
-
-	tgt = nlp->nlp_sid;
-	lunp = lpfc_find_lun(phba, tgt, lun, 1);
-	lpfc_cmd = 0;
-	/* First see if the SCSI ID has an allocated struct lpfc_target */
-	if (lunp && lunp->pTarget) {
-		targetp = lunp->pTarget;
-		psli = &phba->sli;
-
-		/* Get a buffer to hold SCSI data */
-		mp = kmalloc(sizeof (struct lpfc_dmabuf), GFP_ATOMIC);
-		if (mp == 0) {
-			return (0);
-		}
-
-		INIT_LIST_HEAD(&mp->list);
-		/* Get resources to send a SCSI command */
-		lpfc_cmd = lpfc_get_scsi_buf(phba, GFP_ATOMIC);
-		if (lpfc_cmd == 0) {
-			kfree(mp);
-			return (0);
-		}
-		lpfc_cmd->pLun = lunp;
-		/* Internal-generated cmd, so we need to create a temporary
-		 * linux scsi_cmnd and scsi_device.
-		 * Also means when this internal cmd done, we need to free
-		 * this scsi_cmnd and scsi_device structures.
-		 */
-		lnx_cmd = kmalloc(sizeof(struct scsi_cmnd), GFP_ATOMIC);
-		if (lnx_cmd == 0) {
-			kfree(mp);
-			lpfc_free_scsi_buf(lpfc_cmd);
-			return (0);
-		}
-		scsi_dev = kmalloc(sizeof(struct scsi_device), GFP_ATOMIC);
-		if (scsi_dev == 0) {
-			kfree(mp);
-			kfree(lnx_cmd);
-			lpfc_free_scsi_buf(lpfc_cmd);
-			return (0);
-		}
-		scsi_dev->id = tgt;
-		scsi_dev->lun = lun;
-		scsi_dev->hostdata = lunp;
-		lnx_cmd->device = scsi_dev;
-		lpfc_cmd->pCmd = lnx_cmd;
-		lpfc_cmd->timeout = 30 + phba->fcp_timeout_offset;
-
-		/* Finish building BPL with the I/O dma ptrs.
-		 * setup FCP CMND, and setup IOCB.
-		 */
-
-		fcpCmnd = lpfc_cmd->fcp_cmnd;
-
-		putLunHigh(fcpCmnd->fcpLunMsl, lun);	/* LUN */
-		putLunLow(fcpCmnd->fcpLunLsl, lun);	/* LUN */
-
-		switch (scsi_cmd) {
-		case REPORT_LUNS:
-			size = LPFC_SCSI_PAGE_BUF_SZ;
-			fcpCmnd->fcpCdb[0] = scsi_cmd;
-			/* 0x1000 = LPFC_SCSI_PAGE_BUF_SZ */
-			fcpCmnd->fcpCdb[8] = 0x10;
-			fcpCmnd->fcpCdb[9] = 0x00;
-			fcpCmnd->fcpCntl3 = READ_DATA;
-			fcpCmnd->fcpDl = be32_to_cpu(LPFC_SCSI_PAGE_BUF_SZ);
-			/* Get a buffer to hold SCSI data */
-			if ((mp->virt =
-			     lpfc_page_alloc(phba, 0, &(mp->phys))) == 0) {
-				if (mp)
-					kfree(mp);
-				lpfc_free_scsi_buf(lpfc_cmd);
-				return (0);
-			}
-			break;
-		case INQUIRY:
-			fcpCmnd->fcpCdb[0] = scsi_cmd;	/* SCSI Inquiry
-							   Command */
-			fcpCmnd->fcpCdb[4] = 0xff;	/* allocation length */
-			fcpCmnd->fcpCntl3 = READ_DATA;
-			fcpCmnd->fcpDl = be32_to_cpu(LPFC_SCSI_BUF_SZ);
-			/* drop thru to get a buffer */
-		default:
-			size = LPFC_SCSI_BUF_SZ;
-			/* Get a buffer to hold SCSI data */
-			if ((mp->virt =
-			     lpfc_mbuf_alloc(phba, 0, &(mp->phys))) == 0) {
-				if (mp)
-					kfree(mp);
-				lpfc_free_scsi_buf(lpfc_cmd);
-				return (0);
-			}
-			break;
-		}
-
-		bpl = lpfc_cmd->fcp_bpl;
-		bpl += 2;	/* Bump past FCP CMND and FCP RSP */
-
-		/* no scatter-gather list case */
-		bpl->addrLow = le32_to_cpu(putPaddrLow(mp->phys));
-		bpl->addrHigh = le32_to_cpu(putPaddrHigh(mp->phys));
-		bpl->tus.f.bdeSize = size;
-		bpl->tus.f.bdeFlags = BUFF_USE_RCV;
-		bpl->tus.w = le32_to_cpu(bpl->tus.w);
-		bpl++;
-		bpl->addrHigh = 0;
-		bpl->addrLow = 0;
-		bpl->tus.w = 0;
-
-		piocbq = &lpfc_cmd->cur_iocbq;
-		piocb = &piocbq->iocb;
-		piocb->ulpCommand = CMD_FCP_IREAD64_CR;
-		piocb->ulpPU = PARM_READ_CHECK;
-		piocb->un.fcpi.fcpi_parm = size;
-		piocb->un.fcpi64.bdl.bdeSize += sizeof (struct ulp_bde64);
-		piocb->ulpBdeCount = 1;
-		piocb->ulpLe = 1;	/* Set the LE bit in the iocb */
-
-		/* Get an iotag and finish setup of IOCB  */
-		piocb->ulpIoTag = lpfc_sli_next_iotag(phba,
-					      &phba->sli.ring[psli->fcp_ring]);
-		piocb->ulpContext = nlp->nlp_rpi;
-		if (nlp->nlp_fcp_info & NLP_FCP_2_DEVICE) {
-			piocb->ulpFCP2Rcvy = 1;
-		}
-		piocb->ulpClass = (nlp->nlp_fcp_info & 0x0f);
-
-		/* ulpTimeout is only one byte */
-		if (lpfc_cmd->timeout > 0xff) {
-			/*
-			 * Do not timeout the command at the firmware level.
-			 * The driver will provide the timeout mechanism.
-			 */
-			piocb->ulpTimeout = 0;
-		} else {
-			piocb->ulpTimeout = lpfc_cmd->timeout;
-		}
-
-		/*
-		 * Setup driver timeout, in case the command does not complete
-		 * Driver timeout should be greater than ulpTimeout
-		 */
-
-		piocbq->drvrTimeout = lpfc_cmd->timeout + LPFC_DRVR_TIMEOUT;
-
-		/* set up iocb return path by setting the context fields
-		 * and the completion function.
-		 */
-		piocbq->context1 = lpfc_cmd;
-		piocbq->context2 = mp;
-
-	}
-	return (lpfc_cmd);
-}
-
 void
 lpfc_scsi_timeout_handler(unsigned long ptr)
 {

^ permalink raw reply	[flat|nested] 17+ messages in thread

* RE: [Emulex] Ready for next round...
@ 2004-07-19 20:02 Ely, Paul
  0 siblings, 0 replies; 17+ messages in thread
From: Ely, Paul @ 2004-07-19 20:02 UTC (permalink / raw)
  To: 'Christoph Hellwig', Smart, James; +Cc: Linux SCSI Reflector

Christoph,

We have applied this patch to our source base and
tested it successfully.
 
Patch accepted for our 8.0.7 release.

Thanks,
 
Paul Ely
Emulex

> -----Original Message-----
> From: 'Christoph Hellwig' [mailto:hch@infradead.org]
> Sent: Saturday, July 17, 2004 4:27 PM
> To: Smart, James
> Cc: 'Christoph Hellwig'; Linux SCSI Reflector
> Subject: Re: [Emulex] Ready for next round...
> 
> 
> On Sat, Jul 17, 2004 at 09:17:35PM +0100, 'Christoph Hellwig' wrote:
> > On Sat, Jul 17, 2004 at 07:26:32AM -0400, Smart, James wrote:
> > > Christoph,
> > > 
> > > We've updated the driver on SourceForge again.  This 
> addresses the rework of
> > > the clk functions. Also rids the driver of Report Lun use.
> > > 
> > > I know this next week will probably be busy due to the 
> OLS, but we would
> > > appreciate comments any time that you can provide them.
> > 
> > Okay, this starts to look better.  There's lots of dead 
> code again, see the
> > patch below to remove it.  Also while the parameter rework 
> in the last drop
> > is already much better it still needs some more work I think.
> 
> Sorry, wrong patch.  The correct one is below.
> 
> 
> diff -uNr -X /home/hch/dontdiff lpfcdriver-2.6-8.0.6/lpfc.h 
> lpfcdriver-2.6-8.0.6-hch/lpfc.h
> --- lpfcdriver-2.6-8.0.6/lpfc.h	2004-07-16 
> 20:59:54.000000000 +0200
> +++ lpfcdriver-2.6-8.0.6-hch/lpfc.h	2004-07-17 
> 21:07:40.000000000 +0200
> @@ -411,9 +411,7 @@
>  	/* pci_mem_pools */
>  	struct pci_pool *lpfc_scsi_dma_ext_pool;
>  	struct pci_pool *lpfc_mbuf_pool;
> -	struct pci_pool *lpfc_page_pool;
>  	struct lpfc_dma_pool lpfc_mbuf_safety_pool;
> -	struct lpfc_dma_pool lpfc_page_safety_pool;
>  	mempool_t *scsibuf_mem_pool;
>  
>  	mempool_t *iocb_mem_pool;
> diff -uNr -X /home/hch/dontdiff 
> lpfcdriver-2.6-8.0.6/lpfc_crtn.h lpfcdriver-2.6-8.0.6-hch/lpfc_crtn.h
> --- lpfcdriver-2.6-8.0.6/lpfc_crtn.h	2004-07-16 
> 20:59:54.000000000 +0200
> +++ lpfcdriver-2.6-8.0.6-hch/lpfc_crtn.h	2004-07-17 
> 20:57:50.000000000 +0200
> @@ -76,13 +76,9 @@
>  void lpfc_disc_start(struct lpfc_hba *);
>  void lpfc_disc_flush_list(struct lpfc_hba *);
>  void lpfc_linkdown_timeout(unsigned long);
> -void lpfc_nodev_timeout(unsigned long);
>  void lpfc_establish_link_tmo(unsigned long);
>  void lpfc_disc_timeout(unsigned long);
>  struct lpfc_lun *lpfc_find_lun(struct lpfc_hba *, uint32_t, 
> uint64_t, int);
> -struct lpfc_scsi_buf *lpfc_build_scsi_cmd(struct lpfc_hba *,
> -					  struct lpfc_nodelist *,
> -					  uint32_t, uint64_t);
>  void lpfc_set_failmask(struct lpfc_hba *, struct 
> lpfc_nodelist *, uint32_t,
>  		       uint32_t);
>  
> @@ -223,7 +219,6 @@
>  			    uint16_t);
>  void lpfc_mbox_timeout(unsigned long);
>  
> -void lpfc_free_scsi_buf(struct lpfc_scsi_buf *);
>  void lpfc_map_fcp_cmnd_to_bpl(struct lpfc_hba *, struct 
> lpfc_scsi_buf *);
>  void lpfc_free_scsi_cmd(struct lpfc_scsi_buf *);
>  uint32_t lpfc_os_timeout_transform(struct lpfc_hba *, uint32_t);
> @@ -242,9 +237,6 @@
>  void lpfc_sli_wake_iocb_high_priority(struct lpfc_hba * phba,
>  				      struct lpfc_iocbq * queue1,
>  				      struct lpfc_iocbq * queue2);
> -void *lpfc_page_alloc(struct lpfc_hba *, int, dma_addr_t *);
> -void lpfc_page_free(struct lpfc_hba *, void *, dma_addr_t);
> -
>  void *lpfc_mbuf_alloc(struct lpfc_hba *, int, dma_addr_t *);
>  void lpfc_mbuf_free(struct lpfc_hba *, void *, dma_addr_t);
>  
> diff -uNr -X /home/hch/dontdiff 
> lpfcdriver-2.6-8.0.6/lpfc_hbadisc.c 
> lpfcdriver-2.6-8.0.6-hch/lpfc_hbadisc.c
> --- lpfcdriver-2.6-8.0.6/lpfc_hbadisc.c	2004-07-16 
> 20:59:54.000000000 +0200
> +++ lpfcdriver-2.6-8.0.6-hch/lpfc_hbadisc.c	2004-07-17 
> 20:57:30.000000000 +0200
> @@ -2450,7 +2450,7 @@
>  	return;
>  }
>  
> -void
> +static void
>  lpfc_nodev_timeout(unsigned long ptr)
>  {
>  	struct lpfc_hba *phba;
> diff -uNr -X /home/hch/dontdiff 
> lpfcdriver-2.6-8.0.6/lpfc_mem.c lpfcdriver-2.6-8.0.6-hch/lpfc_mem.c
> --- lpfcdriver-2.6-8.0.6/lpfc_mem.c	2004-07-16 
> 20:59:54.000000000 +0200
> +++ lpfcdriver-2.6-8.0.6-hch/lpfc_mem.c	2004-07-17 
> 21:08:10.000000000 +0200
> @@ -40,12 +40,8 @@
>  static void lpfc_mem_safety_pool_destroy(struct lpfc_hba *);
>  static void lpfc_mbuf_safety_pool_create(struct lpfc_hba *, 
> uint32_t );
>  static void lpfc_mbuf_safety_pool_destroy(struct lpfc_hba *);
> -static void lpfc_page_safety_pool_create(struct lpfc_hba *, 
> uint32_t );
> -static void lpfc_page_safety_pool_destroy(struct lpfc_hba *);
>  void *lpfc_mbuf_alloc(struct lpfc_hba *, int, dma_addr_t *);
>  void lpfc_mbuf_free(struct lpfc_hba *, void *, dma_addr_t);
> -void *lpfc_page_alloc(struct lpfc_hba *, int, dma_addr_t *);
> -void lpfc_page_free(struct lpfc_hba *, void *, dma_addr_t);
>  static void *lpfc_scsibuf_pool_alloc(int , void *);
>  static void  lpfc_scsibuf_pool_free(void *, void *);
>  
> @@ -66,8 +62,6 @@
>  
>  	phba->lpfc_scsi_dma_ext_pool = 0;
>  	phba->lpfc_mbuf_pool = 0;
> -	phba->lpfc_page_pool = 0;
> -
>  
>  	phba->lpfc_scsi_dma_ext_pool =
>  		pci_pool_create("lpfc_scsi_dma_ext_pool",
> @@ -83,21 +77,12 @@
>  				8,
>  				0);
>  
> -	phba->lpfc_page_pool =
> -		pci_pool_create("lpfc_page_pool",
> -				phba->pcidev,
> -				LPFC_SCSI_PAGE_BUF_SZ,
> -				8,
> -				0);
> -
> -	if ((!phba->lpfc_scsi_dma_ext_pool) || 
> (!phba->lpfc_mbuf_pool) ||
> -	   (!phba->lpfc_page_pool)) {
> +	if (!phba->lpfc_scsi_dma_ext_pool || !phba->lpfc_mbuf_pool) {
>  		lpfc_mem_free(phba);
>  		return (0);
>  	}
>  
>  	lpfc_mbuf_safety_pool_create(phba, LPFC_MBUF_POOL_SIZE);
> -	lpfc_page_safety_pool_create(phba, LPFC_PAGE_POOL_SIZE);
>  	lpfc_mem_safety_pool_create(phba, LPFC_MEM_POOL_SIZE);
>  
>  	return (1);
> @@ -126,7 +111,6 @@
>  	}
>  
>  	lpfc_mbuf_safety_pool_destroy(phba);
> -	lpfc_page_safety_pool_destroy(phba);
>  	lpfc_mem_safety_pool_destroy(phba);
>  
>  	if (phba->lpfc_scsi_dma_ext_pool)
> @@ -134,11 +118,7 @@
>  
>  	if (phba->lpfc_mbuf_pool)
>  		pci_pool_destroy(phba->lpfc_mbuf_pool);
> -
> -	if (phba->lpfc_page_pool)
> -		pci_pool_destroy(phba->lpfc_page_pool);
> -
> -	return (1);
> +	return 1;
>  }
>  
>  void
> @@ -232,51 +212,6 @@
>  	kfree(pool->elements);
>  }
>  
> -
> -static void
> -lpfc_page_safety_pool_create(struct lpfc_hba * phba, uint32_t count)
> -{
> -	int i;
> -
> -	struct lpfc_dma_pool *pool =
> -		&(phba->lpfc_page_safety_pool);
> -
> -	pool->elements = kmalloc(sizeof(struct lpfc_dmabuf) * count,
> -				 GFP_KERNEL);
> -	pool->max_count = 0;
> -	pool->current_count = 0;
> -	for ( i=0; i<count; i++) {
> -		pool->elements[i].virt =
> -			pci_pool_alloc(phba->lpfc_page_pool,
> -				       GFP_KERNEL,
> -				       &(pool->elements[i].phys));
> -
> -		if (!pool->elements[i].virt)
> -			break;
> -		pool->max_count++;
> -		pool->current_count++;
> -	}
> -}
> -
> -static void
> -lpfc_page_safety_pool_destroy(struct lpfc_hba * phba)
> -{
> -	struct lpfc_dma_pool *pool =
> -		&(phba->lpfc_page_safety_pool);
> -	int i;
> -
> -	if ( pool->max_count != pool->current_count)
> -		printk("Memory leaked in page safety pool \n");
> -
> -	for (i=0; i< pool->current_count; i++) {
> -		pci_pool_free(phba->lpfc_page_pool,
> -			      pool->elements[i].virt,
> -			      pool->elements[i].phys);
> -	}
> -
> -	kfree(pool->elements);
> -}
> -
>  void *
>  lpfc_mbuf_alloc(struct lpfc_hba * phba, int mem_flags, 
> dma_addr_t * handle)
>  {
> @@ -315,44 +250,6 @@
>  	return;
>  }
>  
> -void *
> -lpfc_page_alloc(struct lpfc_hba * phba, int mem_flags, 
> dma_addr_t * handle)
> -{
> -	void *ret;
> -	struct lpfc_dma_pool *pool =
> -		&(phba->lpfc_page_safety_pool);
> -
> -	ret = pci_pool_alloc(phba->lpfc_page_pool, GFP_ATOMIC, handle);
> -	/*
> -	   If we are low in memory and is priority memory allocation
> -	   use safety pool
> -	*/
> -	if ((!ret) && ( mem_flags & MEM_PRI)
> -	    && (pool->current_count)) {
> -		pool->current_count--;
> -		ret = pool->elements[pool->current_count].virt;
> -		*handle = pool->elements[pool->current_count].phys;
> -	}
> -	return ret;
> -}
> -
> -void
> -lpfc_page_free(struct lpfc_hba * phba, void *virt, dma_addr_t dma)
> -{
> -	struct lpfc_dma_pool *pool =
> -		&(phba->lpfc_page_safety_pool);
> -
> -	if ( pool->current_count < pool->max_count) {
> -		pool->elements[pool->current_count].virt = virt;
> -		pool->elements[pool->current_count].phys = dma;
> -		pool->current_count++;
> -		return;
> -	}
> -
> -	pci_pool_free(phba->lpfc_page_pool, virt, dma);
> -	return;
> -}
> -
>  static void *
>  lpfc_scsibuf_pool_alloc(int gfp_flags, void *data) {
>  	void * ret;
> diff -uNr -X /home/hch/dontdiff 
> lpfcdriver-2.6-8.0.6/lpfc_scsiport.c 
> lpfcdriver-2.6-8.0.6-hch/lpfc_scsiport.c
> --- lpfcdriver-2.6-8.0.6/lpfc_scsiport.c	2004-07-16 
> 20:59:54.000000000 +0200
> +++ lpfcdriver-2.6-8.0.6-hch/lpfc_scsiport.c	2004-07-17 
> 20:56:01.000000000 +0200
> @@ -185,7 +185,7 @@
>  }
>  
>  /* This routine frees a scsi buffer, both DMAable and 
> non-DMAable regions */
> -void
> +static void
>  lpfc_free_scsi_buf(struct lpfc_scsi_buf * psb)
>  {
>  	struct lpfc_hba *phba;
> @@ -1127,177 +1127,6 @@
>  	return ret;
>  }
>  
> -struct lpfc_scsi_buf *
> -lpfc_build_scsi_cmd(struct lpfc_hba * phba,
> -		    struct lpfc_nodelist * nlp, uint32_t 
> scsi_cmd, uint64_t lun)
> -{
> -	struct lpfc_sli *psli;
> -	struct lpfc_target *targetp;
> -	struct lpfc_lun *lunp;
> -	struct lpfc_dmabuf *mp;
> -	struct lpfc_scsi_buf *lpfc_cmd;
> -	struct lpfc_iocbq *piocbq;
> -	IOCB_t *piocb;
> -	struct fcp_cmnd *fcpCmnd;
> -	struct ulp_bde64 *bpl;
> -	uint32_t tgt, size;
> -	struct scsi_cmnd *lnx_cmd;
> -	struct scsi_device *scsi_dev;
> -
> -	tgt = nlp->nlp_sid;
> -	lunp = lpfc_find_lun(phba, tgt, lun, 1);
> -	lpfc_cmd = 0;
> -	/* First see if the SCSI ID has an allocated struct 
> lpfc_target */
> -	if (lunp && lunp->pTarget) {
> -		targetp = lunp->pTarget;
> -		psli = &phba->sli;
> -
> -		/* Get a buffer to hold SCSI data */
> -		mp = kmalloc(sizeof (struct lpfc_dmabuf), GFP_ATOMIC);
> -		if (mp == 0) {
> -			return (0);
> -		}
> -
> -		INIT_LIST_HEAD(&mp->list);
> -		/* Get resources to send a SCSI command */
> -		lpfc_cmd = lpfc_get_scsi_buf(phba, GFP_ATOMIC);
> -		if (lpfc_cmd == 0) {
> -			kfree(mp);
> -			return (0);
> -		}
> -		lpfc_cmd->pLun = lunp;
> -		/* Internal-generated cmd, so we need to create 
> a temporary
> -		 * linux scsi_cmnd and scsi_device.
> -		 * Also means when this internal cmd done, we 
> need to free
> -		 * this scsi_cmnd and scsi_device structures.
> -		 */
> -		lnx_cmd = kmalloc(sizeof(struct scsi_cmnd), GFP_ATOMIC);
> -		if (lnx_cmd == 0) {
> -			kfree(mp);
> -			lpfc_free_scsi_buf(lpfc_cmd);
> -			return (0);
> -		}
> -		scsi_dev = kmalloc(sizeof(struct scsi_device), 
> GFP_ATOMIC);
> -		if (scsi_dev == 0) {
> -			kfree(mp);
> -			kfree(lnx_cmd);
> -			lpfc_free_scsi_buf(lpfc_cmd);
> -			return (0);
> -		}
> -		scsi_dev->id = tgt;
> -		scsi_dev->lun = lun;
> -		scsi_dev->hostdata = lunp;
> -		lnx_cmd->device = scsi_dev;
> -		lpfc_cmd->pCmd = lnx_cmd;
> -		lpfc_cmd->timeout = 30 + phba->fcp_timeout_offset;
> -
> -		/* Finish building BPL with the I/O dma ptrs.
> -		 * setup FCP CMND, and setup IOCB.
> -		 */
> -
> -		fcpCmnd = lpfc_cmd->fcp_cmnd;
> -
> -		putLunHigh(fcpCmnd->fcpLunMsl, lun);	/* LUN */
> -		putLunLow(fcpCmnd->fcpLunLsl, lun);	/* LUN */
> -
> -		switch (scsi_cmd) {
> -		case REPORT_LUNS:
> -			size = LPFC_SCSI_PAGE_BUF_SZ;
> -			fcpCmnd->fcpCdb[0] = scsi_cmd;
> -			/* 0x1000 = LPFC_SCSI_PAGE_BUF_SZ */
> -			fcpCmnd->fcpCdb[8] = 0x10;
> -			fcpCmnd->fcpCdb[9] = 0x00;
> -			fcpCmnd->fcpCntl3 = READ_DATA;
> -			fcpCmnd->fcpDl = 
> be32_to_cpu(LPFC_SCSI_PAGE_BUF_SZ);
> -			/* Get a buffer to hold SCSI data */
> -			if ((mp->virt =
> -			     lpfc_page_alloc(phba, 0, 
> &(mp->phys))) == 0) {
> -				if (mp)
> -					kfree(mp);
> -				lpfc_free_scsi_buf(lpfc_cmd);
> -				return (0);
> -			}
> -			break;
> -		case INQUIRY:
> -			fcpCmnd->fcpCdb[0] = scsi_cmd;	/* SCSI Inquiry
> -							   Command */
> -			fcpCmnd->fcpCdb[4] = 0xff;	/* 
> allocation length */
> -			fcpCmnd->fcpCntl3 = READ_DATA;
> -			fcpCmnd->fcpDl = be32_to_cpu(LPFC_SCSI_BUF_SZ);
> -			/* drop thru to get a buffer */
> -		default:
> -			size = LPFC_SCSI_BUF_SZ;
> -			/* Get a buffer to hold SCSI data */
> -			if ((mp->virt =
> -			     lpfc_mbuf_alloc(phba, 0, 
> &(mp->phys))) == 0) {
> -				if (mp)
> -					kfree(mp);
> -				lpfc_free_scsi_buf(lpfc_cmd);
> -				return (0);
> -			}
> -			break;
> -		}
> -
> -		bpl = lpfc_cmd->fcp_bpl;
> -		bpl += 2;	/* Bump past FCP CMND and FCP RSP */
> -
> -		/* no scatter-gather list case */
> -		bpl->addrLow = le32_to_cpu(putPaddrLow(mp->phys));
> -		bpl->addrHigh = le32_to_cpu(putPaddrHigh(mp->phys));
> -		bpl->tus.f.bdeSize = size;
> -		bpl->tus.f.bdeFlags = BUFF_USE_RCV;
> -		bpl->tus.w = le32_to_cpu(bpl->tus.w);
> -		bpl++;
> -		bpl->addrHigh = 0;
> -		bpl->addrLow = 0;
> -		bpl->tus.w = 0;
> -
> -		piocbq = &lpfc_cmd->cur_iocbq;
> -		piocb = &piocbq->iocb;
> -		piocb->ulpCommand = CMD_FCP_IREAD64_CR;
> -		piocb->ulpPU = PARM_READ_CHECK;
> -		piocb->un.fcpi.fcpi_parm = size;
> -		piocb->un.fcpi64.bdl.bdeSize += sizeof (struct 
> ulp_bde64);
> -		piocb->ulpBdeCount = 1;
> -		piocb->ulpLe = 1;	/* Set the LE bit in the iocb */
> -
> -		/* Get an iotag and finish setup of IOCB  */
> -		piocb->ulpIoTag = lpfc_sli_next_iotag(phba,
> -					      
> &phba->sli.ring[psli->fcp_ring]);
> -		piocb->ulpContext = nlp->nlp_rpi;
> -		if (nlp->nlp_fcp_info & NLP_FCP_2_DEVICE) {
> -			piocb->ulpFCP2Rcvy = 1;
> -		}
> -		piocb->ulpClass = (nlp->nlp_fcp_info & 0x0f);
> -
> -		/* ulpTimeout is only one byte */
> -		if (lpfc_cmd->timeout > 0xff) {
> -			/*
> -			 * Do not timeout the command at the 
> firmware level.
> -			 * The driver will provide the timeout 
> mechanism.
> -			 */
> -			piocb->ulpTimeout = 0;
> -		} else {
> -			piocb->ulpTimeout = lpfc_cmd->timeout;
> -		}
> -
> -		/*
> -		 * Setup driver timeout, in case the command 
> does not complete
> -		 * Driver timeout should be greater than ulpTimeout
> -		 */
> -
> -		piocbq->drvrTimeout = lpfc_cmd->timeout + 
> LPFC_DRVR_TIMEOUT;
> -
> -		/* set up iocb return path by setting the context fields
> -		 * and the completion function.
> -		 */
> -		piocbq->context1 = lpfc_cmd;
> -		piocbq->context2 = mp;
> -
> -	}
> -	return (lpfc_cmd);
> -}
> -
>  void
>  lpfc_scsi_timeout_handler(unsigned long ptr)
>  {
> -
> To unsubscribe from this list: send the line "unsubscribe 
> linux-scsi" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

^ permalink raw reply	[flat|nested] 17+ messages in thread

end of thread, other threads:[~2004-07-19 20:03 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
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
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

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox