Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 89877e42827f16fa5f86b1df0c2860b1 > files > 2184

kernel-2.6.18-128.1.10.el5.src.rpm

From: Chip Coldwell <coldwell@redhat.com>
Subject: [RHEL-5.1 PATCH] bz227416 omnibus lpfc driver update
Date: Mon, 4 Jun 2007 16:06:48 -0400 (EDT)
Bugzilla: 227416
Message-Id: <Pine.LNX.4.64.0706041604180.26702@bogart.boston.redhat.com>
Changelog: [scsi] omnibus lpfc driver update



The patch brings RHEL-5 into line with the upstream driver (modulo
KABI).  Tested locally with iozone.  Changelog from Emulex is as
follows:

This patch updates to 8.1.10.9.

* Changed version number to 8.1.10.9
* Fix host_lock management in the ioctl paths (CR 24766)
* Automatically detect AMD chipset and reduce the DMA length to
  1024 bytes. (CR 23933)

* Changed version number to 8.1.10.8
* Change min cr_count value specified in comment to agree with
  setting (CR 24418)
* Removed hba queue depth calculation based on device PCI IDs
* Fixed check for dropped frames. (CR 24469)

* Changed version number to 8.1.10.7
* Fixed a memory leak in lpfc_sli_wake_mbox_wait. (CR 24339)
* Added support for 8G speed and Saturn HBAs.
* Use msleep instead of mdelay inside a loop to prevent soft lockup
  errors (CR 24502)
* Change rport dev_loss_tmo value when user change lpfc HBA's
  dev_loss_tmo. (CR 24487)
* Changed LPFC_HBA_GET_EVENT ioctl to allocate smaller data buffer.
  (CR 24178)
* Fixed recovery of rport after dev_loss_tmo. (CR 24459)
* Fixed name server query response handling. (CR 24468)
* Fixed false iocb timeout. (CR 23841)
* Update copyright year to 2007 for files changes this year.
* Fixup messages 0116, 0117, and 0128 to report ELS I/O tag.
* Cleanup: remove unused parameter to lpfc_cleanup.

* Changed version number to 8.1.10.6
* Fixed NULL pointer dereference during I/O with LIP. (CR 24371)
* Fixed system hangs due to leaked host_lock. (CR 23970 24177 24179)
* Don't process ERATT interrupts when issuing KILL_BOARD mbx command
  (CR 23986)
* Fixed a memory leak while initializing a bad HBA. (CR 24298)
* Fix offline window where more work can sneak in after clearing
  work_ha (CR 24163)
* Add ifdef around request_irq call to build on SLES 10 SP1
* Changed local loopback linkup message to a KERN_INFO message.
  (CR 23963)
* Added code to cleanup REG_LOGIN mailbox command when a LOGO is
  received. (CR 23785)
* Prevent freeing of iocb after IOCB_TIMEDOUT error. (CR 24098)
* Prevent destroying node if dev_loss_tmo called on a node whose
  discovery is completed. (CR 23785)

* Changed version number to 8.1.10.5
* Fixed bug check in add_timer (CR 24051)
* Fix system hang while running on systems with IOMMU (CR 23663)
* Error path fix in lpfc_mem_alloc
* Rework offline path to solve HBA reset issues (CR 23850)
* mbox interface should use MAILBOX_CMD_SIZE rather than
  sizeof(MAILBOX_t) (CR 23916)
* Fixed lpfc_ns_rsp to handle entire GID_FT response (CR 23967)
* Fix memory leaks in get/reset statistics and link attention
  paths (CR 23916)

* Change version number to 8.1.10.4
* Update copyright year to 2007
* Fix wwpn lookup in LPFC_HBA_RNID ioctl (CR 23740)
* Fix for PCI hot unplug hang while hhanyware running (CR 23718)
* Don't remove node during dev_loss_tmo if discovery is active
  (CR 23589)
* Modify ELS abort handling to prevent double completion
  (CR 23654)
* Fix memory leak in unsol CT path (CR 23691)
* Use msleep for long delays to prevent soft lockup bug check
  (CR 23678)
* Decrement txq_cnt rather than txcmplq_cnt when parsing the txq
  list (CR 23679)
* Fix recursive locking in the lpfc driver ioctl code. (CR 23645)
* Don't free mailbox structure if it's still on the mboxq list
  (CR 23638)
* Fix use after free issues with rports (CR 23375)

Patch below

Index: latest/drivers/scsi/lpfc/lpfc_attr.c
===================================================================
--- latest.orig/drivers/scsi/lpfc/lpfc_attr.c
+++ latest/drivers/scsi/lpfc/lpfc_attr.c
@@ -1,7 +1,7 @@
 /*******************************************************************
  * This file is part of the Emulex Linux Device Driver for         *
  * Fibre Channel Host Bus Adapters.                                *
- * Copyright (C) 2004-2006 Emulex.  All rights reserved.           *
+ * Copyright (C) 2004-2007 Emulex.  All rights reserved.           *
  * EMULEX and SLI are trademarks of Emulex.                        *
  * www.emulex.com                                                  *
  * Portions Copyright (C) 2004-2005 Christoph Hellwig              *
@@ -20,6 +20,7 @@
  *******************************************************************/
 
 #include <linux/ctype.h>
+#include <linux/delay.h>
 #include <linux/pci.h>
 #include <linux/interrupt.h>
 
@@ -213,6 +214,7 @@ lpfc_issue_lip(struct Scsi_Host *host)
 	int mbxstatus = MBXERR_ERROR;
 
 	if ((phba->fc_flag & FC_OFFLINE_MODE) ||
+	    (phba->fc_flag & FC_BLOCK_MGMT_IO) ||
 	    (phba->hba_state != LPFC_HBA_READY))
 		return -EPERM;
 
@@ -235,6 +237,7 @@ lpfc_issue_lip(struct Scsi_Host *host)
 						     phba->fc_ratov * 2);
 	}
 
+	lpfc_set_loopback_flag(phba);
 	if (mbxstatus == MBX_TIMEOUT)
 		pmboxq->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
 	else
@@ -247,19 +250,62 @@ lpfc_issue_lip(struct Scsi_Host *host)
 }
 
 static int
-lpfc_selective_reset(struct lpfc_hba *phba)
+lpfc_do_offline(struct lpfc_hba *phba, uint32_t type)
 {
 	struct completion online_compl;
+	struct lpfc_sli_ring *pring;
+	struct lpfc_sli *psli;
 	int status = 0;
+	int cnt = 0;
+	int i;
 
 	init_completion(&online_compl);
 	lpfc_workq_post_event(phba, &status, &online_compl,
-			      LPFC_EVT_OFFLINE);
+			      LPFC_EVT_OFFLINE_PREP);
 	wait_for_completion(&online_compl);
 
 	if (status != 0)
 		return -EIO;
 
+	psli = &phba->sli;
+
+	for (i = 0; i < psli->num_rings; i++) {
+		pring = &psli->ring[i];
+		/* The linkdown event takes 30 seconds to timeout. */
+		while (pring->txcmplq_cnt) {
+			msleep(10);
+			if (cnt++ > 3000) {
+				lpfc_printf_log(phba,
+					KERN_WARNING, LOG_INIT,
+					"%d:0466 Outstanding IO when "
+					"bringing Adapter offline\n",
+					phba->brd_no);
+				break;
+			}
+		}
+	}
+
+	init_completion(&online_compl);
+	lpfc_workq_post_event(phba, &status, &online_compl, type);
+	wait_for_completion(&online_compl);
+
+	if (status != 0)
+		return -EIO;
+
+	return 0;
+}
+
+static int
+lpfc_selective_reset(struct lpfc_hba *phba)
+{
+	struct completion online_compl;
+	int status = 0;
+
+	status = lpfc_do_offline(phba, LPFC_EVT_OFFLINE);
+
+	if (status != 0)
+		return status;
+
 	init_completion(&online_compl);
 	lpfc_workq_post_event(phba, &status, &online_compl,
 			      LPFC_EVT_ONLINE);
@@ -324,23 +370,19 @@ lpfc_board_mode_store(struct class_devic
 
 	init_completion(&online_compl);
 
-	if(strncmp(buf, "online", sizeof("online") - 1) == 0)
+	if(strncmp(buf, "online", sizeof("online") - 1) == 0) {
 		lpfc_workq_post_event(phba, &status, &online_compl,
 				      LPFC_EVT_ONLINE);
-	else if (strncmp(buf, "offline", sizeof("offline") - 1) == 0)
-		lpfc_workq_post_event(phba, &status, &online_compl,
-				      LPFC_EVT_OFFLINE);
+		wait_for_completion(&online_compl);
+	} else if (strncmp(buf, "offline", sizeof("offline") - 1) == 0)
+		status = lpfc_do_offline(phba, LPFC_EVT_OFFLINE);
 	else if (strncmp(buf, "warm", sizeof("warm") - 1) == 0)
-		lpfc_workq_post_event(phba, &status, &online_compl,
-				      LPFC_EVT_WARM_START);
- 	else if (strncmp(buf, "error", sizeof("error") - 1) == 0)
-		lpfc_workq_post_event(phba, &status, &online_compl,
-				      LPFC_EVT_KILL);
+		status = lpfc_do_offline(phba, LPFC_EVT_WARM_START);
+	else if (strncmp(buf, "error", sizeof("error") - 1) == 0)
+		status = lpfc_do_offline(phba, LPFC_EVT_KILL);
 	else
 		return -EINVAL;
 
-	wait_for_completion(&online_compl);
-
 	if (!status)
 		return strlen(buf);
 	else
@@ -645,9 +687,7 @@ lpfc_soft_wwpn_store(struct class_device
 	dev_printk(KERN_NOTICE, &phba->pcidev->dev,
 		   "lpfc%d: Reinitializing to use soft_wwpn\n", phba->brd_no);
 
-	init_completion(&online_compl);
-	lpfc_workq_post_event(phba, &stat1, &online_compl, LPFC_EVT_OFFLINE);
-	wait_for_completion(&online_compl);
+	stat1 = lpfc_do_offline(phba, LPFC_EVT_OFFLINE);
 	if (stat1)
 		lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
 			"%d:0463 lpfc_soft_wwpn attribute set failed to reinit "
@@ -789,6 +829,34 @@ lpfc_nodev_tmo_init(struct lpfc_hba *phb
 	return -EINVAL;
 }
 
+static void
+lpfc_update_rport_devloss_tmo(struct lpfc_hba *phba)
+{
+	struct lpfc_nodelist  *ndlp;
+	int i;
+	struct list_head *listp, *node_list[7];
+
+	node_list[0] = &phba->fc_npr_list;
+	node_list[1] = &phba->fc_nlpmap_list;
+	node_list[2] = &phba->fc_nlpunmap_list;
+	node_list[3] = &phba->fc_prli_list;
+	node_list[4] = &phba->fc_reglogin_list;
+	node_list[5] = &phba->fc_adisc_list;
+	node_list[6] = &phba->fc_plogi_list;
+
+	spin_lock_irq(phba->host->host_lock);
+	for (i = 0; i < 7; i++) {
+		listp = node_list[i];
+
+		list_for_each_entry(ndlp, listp, nlp_listp) {
+			if (ndlp->rport)
+				ndlp->rport->dev_loss_tmo =
+					phba->cfg_devloss_tmo;
+		}
+	}
+	spin_unlock_irq(phba->host->host_lock);
+}
+
 static int
 lpfc_nodev_tmo_set(struct lpfc_hba *phba, int val)
 {
@@ -804,6 +872,7 @@ lpfc_nodev_tmo_set(struct lpfc_hba *phba
 	if (val >= LPFC_MIN_DEVLOSS_TMO && val <= LPFC_MAX_DEVLOSS_TMO) {
 		phba->cfg_nodev_tmo = val;
 		phba->cfg_devloss_tmo = val;
+		lpfc_update_rport_devloss_tmo(phba);
 		return 0;
 	}
 
@@ -839,6 +908,7 @@ lpfc_devloss_tmo_set(struct lpfc_hba *ph
 		phba->cfg_nodev_tmo = val;
 		phba->cfg_devloss_tmo = val;
 		phba->dev_loss_tmo_changed = 1;
+		lpfc_update_rport_devloss_tmo(phba);
 		return 0;
 	}
 
@@ -931,9 +1001,10 @@ LPFC_ATTR_RW(topology, 0, 0, 6, "Select 
 #       1  = 1 Gigabaud
 #       2  = 2 Gigabaud
 #       4  = 4 Gigabaud
-# Value range is [0,4]. Default value is 0.
+#       8  = 8 Gigabaud
+# Value range is [0,8]. Default value is 0.
 */
-LPFC_ATTR_R(link_speed, 0, 0, 4, "Select link speed");
+LPFC_ATTR_R(link_speed, 0, 0, 8, "Select link speed");
 
 /*
 # lpfc_fcp_class:  Determines FC class to use for the FCP protocol.
@@ -958,7 +1029,7 @@ LPFC_ATTR_R(ack0, 0, 0, 1, "Enable ACK0 
 /*
 # lpfc_cr_delay & lpfc_cr_count: Default values for I/O colaesing
 # cr_delay (msec) or cr_count outstanding commands. cr_delay can take
-# value [0,63]. cr_count can take value [0,255]. Default value of cr_delay
+# value [0,63]. cr_count can take value [1,255]. Default value of cr_delay
 # is 0. Default value of cr_count is 1. The cr_count feature is disabled if
 # cr_delay is set to 0.
 */
@@ -1227,11 +1298,11 @@ sysfs_mbox_read(struct kobject *kobj, ch
 	struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
 	int rc;
 
-	if (off > sizeof(MAILBOX_t))
+	if (off > MAILBOX_CMD_SIZE)
 		return -ERANGE;
 
-	if ((count + off) > sizeof(MAILBOX_t))
-		count = sizeof(MAILBOX_t) - off;
+	if ((count + off) > MAILBOX_CMD_SIZE)
+		count = MAILBOX_CMD_SIZE - off;
 
 	if (off % 4 ||  count % 4 || (unsigned long)buf % 4)
 		return -EINVAL;
@@ -1307,6 +1378,12 @@ sysfs_mbox_read(struct kobject *kobj, ch
 			return -EPERM;
 		}
 
+		if (phba->fc_flag & FC_BLOCK_MGMT_IO) {
+			sysfs_mbox_idle(phba);
+			spin_unlock_irq(host->host_lock);
+			return  -EAGAIN;
+		}
+
 		if ((phba->fc_flag & FC_OFFLINE_MODE) ||
 		    (!(phba->sli.sli_flag & LPFC_SLI2_ACTIVE))){
 
@@ -1326,6 +1403,11 @@ sysfs_mbox_read(struct kobject *kobj, ch
 		}
 
 		if (rc != MBX_SUCCESS) {
+			if (rc == MBX_TIMEOUT) {
+				phba->sysfs_mbox.mbox->mbox_cmpl =
+					lpfc_sli_def_mbox_cmpl;
+				phba->sysfs_mbox.mbox = NULL;
+			}
 			sysfs_mbox_idle(phba);
 			spin_unlock_irq(host->host_lock);
 			return  (rc == MBX_TIMEOUT) ? -ETIME : -ENODEV;
@@ -1344,7 +1426,7 @@ sysfs_mbox_read(struct kobject *kobj, ch
 
 	phba->sysfs_mbox.offset = off + count;
 
-	if (phba->sysfs_mbox.offset == sizeof(MAILBOX_t))
+	if (phba->sysfs_mbox.offset == MAILBOX_CMD_SIZE)
 		sysfs_mbox_idle(phba);
 
 	spin_unlock_irq(phba->host->host_lock);
@@ -1358,7 +1440,7 @@ static struct bin_attribute sysfs_mbox_a
 		.mode = S_IRUSR | S_IWUSR,
 		.owner = THIS_MODULE,
 	},
-	.size = sizeof(MAILBOX_t),
+	.size = MAILBOX_CMD_SIZE,
 	.read = sysfs_mbox_read,
 	.write = sysfs_mbox_write,
 };
@@ -1494,6 +1576,9 @@ lpfc_get_host_speed(struct Scsi_Host *sh
 			case LA_4GHZ_LINK:
 				fc_host_speed(shost) = FC_PORTSPEED_4GBIT;
 			break;
+			case LA_8GHZ_LINK:
+				fc_host_speed(shost) = FC_PORTSPEED_8GBIT;
+			break;
 			default:
 				fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN;
 			break;
@@ -1546,6 +1631,9 @@ lpfc_get_stats(struct Scsi_Host *shost)
 	unsigned long seconds;
 	int rc = 0;
 
+	if (phba->fc_flag & FC_BLOCK_MGMT_IO)
+		return NULL;
+
 	pmboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
 	if (!pmboxq)
 		return NULL;
@@ -1631,6 +1719,8 @@ lpfc_get_stats(struct Scsi_Host *shost)
 	else
 		hs->seconds_since_last_reset = seconds - psli->stats_start;
 
+	mempool_free(pmboxq, phba->mbox_mem_pool);
+
 	return hs;
 }
 
@@ -1644,6 +1734,9 @@ lpfc_reset_stats(struct Scsi_Host *shost
 	MAILBOX_t *pmb;
 	int rc = 0;
 
+	if (phba->fc_flag & FC_BLOCK_MGMT_IO)
+		return;
+
 	pmboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
 	if (!pmboxq)
 		return;
@@ -1699,6 +1792,8 @@ lpfc_reset_stats(struct Scsi_Host *shost
 
 	psli->stats_start = get_seconds();
 
+	mempool_free(pmboxq, phba->mbox_mem_pool);
+
 	return;
 }
 
@@ -1895,25 +1990,8 @@ lpfc_get_cfgparam(struct lpfc_hba *phba)
 			sizeof(struct fcp_rsp) +
 			(phba->cfg_sg_seg_cnt * sizeof(struct ulp_bde64));
 
-	switch (phba->pcidev->device) {
-	case PCI_DEVICE_ID_LP101:
-	case PCI_DEVICE_ID_BSMB:
-	case PCI_DEVICE_ID_ZSMB:
-		phba->cfg_hba_queue_depth = LPFC_LP101_HBA_Q_DEPTH;
-		break;
-	case PCI_DEVICE_ID_RFLY:
-	case PCI_DEVICE_ID_PFLY:
-	case PCI_DEVICE_ID_BMID:
-	case PCI_DEVICE_ID_ZMID:
-	case PCI_DEVICE_ID_TFLY:
-		phba->cfg_hba_queue_depth = LPFC_LC_HBA_Q_DEPTH;
-		break;
-	default:
-		phba->cfg_hba_queue_depth = LPFC_DFT_HBA_Q_DEPTH;
-	}
 
-	if (phba->cfg_hba_queue_depth > lpfc_hba_queue_depth)
-		lpfc_hba_queue_depth_init(phba, lpfc_hba_queue_depth);
+	lpfc_hba_queue_depth_init(phba, lpfc_hba_queue_depth);
 
 	return;
 }
Index: latest/drivers/scsi/lpfc/lpfc_compat.h
===================================================================
--- latest.orig/drivers/scsi/lpfc/lpfc_compat.h
+++ latest/drivers/scsi/lpfc/lpfc_compat.h
@@ -1,7 +1,7 @@
 /*******************************************************************
  * This file is part of the Emulex Linux Device Driver for         *
  * Fibre Channel Host Bus Adapters.                                *
- * Copyright (C) 2004-2005 Emulex.  All rights reserved.           *
+ * Copyright (C) 2004-2007 Emulex.  All rights reserved.           *
  * EMULEX and SLI are trademarks of Emulex.                        *
  * www.emulex.com                                                  *
  *                                                                 *
@@ -32,6 +32,14 @@ using writel() and readl().
  *******************************************************************/
 #include <asm/byteorder.h>
 
+/*
+ * This definition is to support older versions of scsi_transport_fc which
+ * do not have 8Gig speed definition.
+ */
+#ifndef FC_PORTSPEED_8GBIT
+#define FC_PORTSPEED_8GBIT 0x10
+#endif
+
 #ifdef __BIG_ENDIAN
 
 static inline void
Index: latest/drivers/scsi/lpfc/lpfc_crtn.h
===================================================================
--- latest.orig/drivers/scsi/lpfc/lpfc_crtn.h
+++ latest/drivers/scsi/lpfc/lpfc_crtn.h
@@ -1,7 +1,7 @@
 /*******************************************************************
  * This file is part of the Emulex Linux Device Driver for         *
  * Fibre Channel Host Bus Adapters.                                *
- * Copyright (C) 2004-2006 Emulex.  All rights reserved.           *
+ * Copyright (C) 2004-2007 Emulex.  All rights reserved.           *
  * EMULEX and SLI are trademarks of Emulex.                        *
  * www.emulex.com                                                  *
  *                                                                 *
@@ -47,6 +47,8 @@ int lpfc_nlp_list(struct lpfc_hba *, str
 void lpfc_set_disctmo(struct lpfc_hba *);
 int lpfc_can_disctmo(struct lpfc_hba *);
 int lpfc_unreg_rpi(struct lpfc_hba *, struct lpfc_nodelist *);
+void lpfc_set_slim(struct lpfc_hba *, LPFC_MBOXQ_t *, uint32_t,
+		uint32_t value);
 int lpfc_check_sli_ndlp(struct lpfc_hba *, struct lpfc_sli_ring *,
 		    struct lpfc_iocbq *, struct lpfc_nodelist *);
 int lpfc_nlp_remove(struct lpfc_hba *, struct lpfc_nodelist *);
@@ -66,8 +68,7 @@ int lpfc_disc_state_machine(struct lpfc_
 
 int lpfc_check_sparm(struct lpfc_hba *, struct lpfc_nodelist *,
 		     struct serv_parm *, uint32_t);
-int lpfc_els_abort(struct lpfc_hba *, struct lpfc_nodelist * ndlp,
-			int);
+int lpfc_els_abort(struct lpfc_hba *, struct lpfc_nodelist * ndlp);
 int lpfc_els_abort_flogi(struct lpfc_hba *);
 int lpfc_initial_flogi(struct lpfc_hba *);
 int lpfc_issue_els_plogi(struct lpfc_hba *, uint32_t, uint8_t);
@@ -117,7 +118,10 @@ void lpfc_hba_init(struct lpfc_hba *, ui
 int lpfc_post_buffer(struct lpfc_hba *, struct lpfc_sli_ring *, int, int);
 void lpfc_decode_firmware_rev(struct lpfc_hba *, char *, int);
 int lpfc_online(struct lpfc_hba *);
-int lpfc_offline(struct lpfc_hba *);
+void lpfc_block_mgmt_io(struct lpfc_hba *);
+void lpfc_unblock_mgmt_io(struct lpfc_hba *);
+void lpfc_offline_prep(struct lpfc_hba *);
+void lpfc_offline(struct lpfc_hba *);
 
 int lpfc_sli_setup(struct lpfc_hba *);
 int lpfc_sli_queue_setup(struct lpfc_hba *);
@@ -166,8 +170,8 @@ int lpfc_sli_ringpostbuf_put(struct lpfc
 struct lpfc_dmabuf *lpfc_sli_ringpostbuf_get(struct lpfc_hba *,
 					     struct lpfc_sli_ring *,
 					     dma_addr_t);
-int lpfc_sli_issue_abort_iotag32(struct lpfc_hba *, struct lpfc_sli_ring *,
-				 struct lpfc_iocbq *);
+int lpfc_sli_issue_abort_iotag(struct lpfc_hba *, struct lpfc_sli_ring *,
+			       struct lpfc_iocbq *);
 int lpfc_sli_sum_iocb(struct lpfc_hba *, struct lpfc_sli_ring *, uint16_t,
 			  uint64_t, lpfc_ctx_cmd);
 int lpfc_sli_abort_iocb(struct lpfc_hba *, struct lpfc_sli_ring *, uint16_t,
Index: latest/drivers/scsi/lpfc/lpfc_ct.c
===================================================================
--- latest.orig/drivers/scsi/lpfc/lpfc_ct.c
+++ latest/drivers/scsi/lpfc/lpfc_ct.c
@@ -1,7 +1,7 @@
 /*******************************************************************
  * This file is part of the Emulex Linux Device Driver for         *
  * Fibre Channel Host Bus Adapters.                                *
- * Copyright (C) 2004-2006 Emulex.  All rights reserved.           *
+ * Copyright (C) 2004-2007 Emulex.  All rights reserved.           *
  * EMULEX and SLI are trademarks of Emulex.                        *
  * www.emulex.com                                                  *
  *                                                                 *
@@ -334,21 +334,22 @@ lpfc_ns_rsp(struct lpfc_hba * phba, stru
 
 	lpfc_set_disctmo(phba);
 
-	Cnt = Size  > FCELSSIZE ? FCELSSIZE : Size;
 
 	list_add_tail(&head, &mp->list);
 	list_for_each_entry_safe(mp, next_mp, &head, list) {
 		mlast = mp;
 
+		Cnt = Size  > FCELSSIZE ? FCELSSIZE : Size;
+
 		Size -= Cnt;
 
-		if (!ctptr)
+		if (!ctptr) {
 			ctptr = (uint32_t *) mlast->virt;
-		else
+		} else
 			Cnt -= 16;	/* subtract length of CT header */
 
 		/* Loop through entire NameServer list of DIDs */
-		while (Cnt) {
+		while (Cnt >= sizeof (uint32_t)) {
 
 			/* Get next DID from NameServer List */
 			CTentry = *ctptr++;
@@ -1038,6 +1039,9 @@ lpfc_fdmi_cmd(struct lpfc_hba * phba, st
 				case LA_4GHZ_LINK:
 					ae->un.PortSpeed = HBA_PORTSPEED_4GBIT;
 				break;
+				case LA_8GHZ_LINK:
+					ae->un.PortSpeed = HBA_PORTSPEED_8GBIT;
+				break;
 				default:
 					ae->un.PortSpeed =
 						HBA_PORTSPEED_UNKNOWN;
Index: latest/drivers/scsi/lpfc/lpfc_disc.h
===================================================================
--- latest.orig/drivers/scsi/lpfc/lpfc_disc.h
+++ latest/drivers/scsi/lpfc/lpfc_disc.h
@@ -1,7 +1,7 @@
 /*******************************************************************
  * This file is part of the Emulex Linux Device Driver for         *
  * Fibre Channel Host Bus Adapters.                                *
- * Copyright (C) 2004-2006 Emulex.  All rights reserved.           *
+ * Copyright (C) 2004-2007 Emulex.  All rights reserved.           *
  * EMULEX and SLI are trademarks of Emulex.                        *
  * www.emulex.com                                                  *
  *                                                                 *
@@ -31,6 +31,7 @@
 /* worker thread events */
 enum lpfc_work_type {
 	LPFC_EVT_ONLINE,
+	LPFC_EVT_OFFLINE_PREP,
 	LPFC_EVT_OFFLINE,
 	LPFC_EVT_WARM_START,
 	LPFC_EVT_KILL,
Index: latest/drivers/scsi/lpfc/lpfc_els.c
===================================================================
--- latest.orig/drivers/scsi/lpfc/lpfc_els.c
+++ latest/drivers/scsi/lpfc/lpfc_els.c
@@ -1,7 +1,7 @@
 /*******************************************************************
  * This file is part of the Emulex Linux Device Driver for         *
  * Fibre Channel Host Bus Adapters.                                *
- * Copyright (C) 2004-2006 Emulex.  All rights reserved.           *
+ * Copyright (C) 2004-2007 Emulex.  All rights reserved.           *
  * EMULEX and SLI are trademarks of Emulex.                        *
  * www.emulex.com                                                  *
  * Portions Copyright (C) 2004-2005 Christoph Hellwig              *
@@ -222,16 +222,16 @@ lpfc_prep_els_iocb(struct lpfc_hba * phb
 		/* Xmit ELS command <elsCmd> to remote NPORT <did> */
 		lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
 				"%d:0116 Xmit ELS command x%x to remote "
-				"NPORT x%x Data: x%x x%x\n",
+				"NPORT x%x I/O tag: x%x, HBA state: x%x\n",
 				phba->brd_no, elscmd,
-				did, icmd->ulpIoTag, phba->hba_state);
+				did, elsiocb->iotag, phba->hba_state);
 	} else {
 		/* Xmit ELS response <elsCmd> to remote NPORT <did> */
 		lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
 				"%d:0117 Xmit ELS response x%x to remote "
-				"NPORT x%x Data: x%x x%x\n",
+				"NPORT x%x I/O tag: x%x, size: x%x\n",
 				phba->brd_no, elscmd,
-				ndlp->nlp_DID, icmd->ulpIoTag, cmdSize);
+				ndlp->nlp_DID, elsiocb->iotag, cmdSize);
 	}
 
 	return elsiocb;
@@ -582,24 +582,8 @@ lpfc_els_abort_flogi(struct lpfc_hba * p
 		icmd = &iocb->iocb;
 		if (icmd->ulpCommand == CMD_ELS_REQUEST64_CR) {
 			ndlp = (struct lpfc_nodelist *)(iocb->context1);
-			if (ndlp && (ndlp->nlp_DID == Fabric_DID)) {
-				list_del(&iocb->list);
-				pring->txcmplq_cnt--;
-
-				if ((icmd->un.elsreq64.bdl.ulpIoTag32)) {
-					lpfc_sli_issue_abort_iotag32
-						(phba, pring, iocb);
-				}
-				if (iocb->iocb_cmpl) {
-					icmd->ulpStatus = IOSTAT_LOCAL_REJECT;
-					icmd->un.ulpWord[4] =
-					    IOERR_SLI_ABORTED;
-					spin_unlock_irq(phba->host->host_lock);
-					(iocb->iocb_cmpl) (phba, iocb, iocb);
-					spin_lock_irq(phba->host->host_lock);
-				} else
-					lpfc_sli_release_iocbq(phba, iocb);
-			}
+			if (ndlp && (ndlp->nlp_DID == Fabric_DID))
+				lpfc_sli_issue_abort_iotag(phba, pring, iocb);
 		}
 	}
 	spin_unlock_irq(phba->host->host_lock);
@@ -2017,10 +2001,9 @@ lpfc_els_rsp_acc(struct lpfc_hba * phba,
 
 	/* Xmit ELS ACC response tag <ulpIoTag> */
 	lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
-			"%d:0128 Xmit ELS ACC response tag x%x "
-			"Data: x%x x%x x%x x%x x%x\n",
-			phba->brd_no,
-			elsiocb->iocb.ulpIoTag,
+			"%d:0128 Xmit ELS ACC response tag x%x, XRI: x%x, "
+			"DID: x%x, nlp_flag: x%x nlp_state: x%x RPI: x%x\n",
+			phba->brd_no, elsiocb->iotag,
 			elsiocb->iocb.ulpContext, ndlp->nlp_DID,
 			ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi);
 
@@ -2734,6 +2717,7 @@ lpfc_els_rcv_flogi(struct lpfc_hba * phb
 			mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
 			rc = lpfc_sli_issue_mbox
 				(phba, mbox, (MBX_NOWAIT | MBX_STOP_IOCB));
+			lpfc_set_loopback_flag(phba);
 			if (rc == MBX_NOT_FINISHED) {
 				mempool_free( mbox, phba->mbox_mem_pool);
 			}
@@ -3246,9 +3230,8 @@ lpfc_els_timeout_handler(struct lpfc_hba
 	struct lpfc_iocbq *tmp_iocb, *piocb;
 	IOCB_t *cmd = NULL;
 	struct lpfc_dmabuf *pcmd;
-	struct list_head *dlp;
 	uint32_t *elscmd;
-	uint32_t els_command;
+	uint32_t els_command=0;
 	uint32_t timeout;
 	uint32_t remote_ID;
 
@@ -3263,17 +3246,20 @@ lpfc_els_timeout_handler(struct lpfc_hba
 	timeout = (uint32_t)(phba->fc_ratov << 1);
 
 	pring = &phba->sli.ring[LPFC_ELS_RING];
-	dlp = &pring->txcmplq;
 
 	list_for_each_entry_safe(piocb, tmp_iocb, &pring->txcmplq, list) {
 		cmd = &piocb->iocb;
 
-		if (piocb->iocb_flag & LPFC_IO_LIBDFC) {
+		if ((piocb->iocb_flag & LPFC_IO_LIBDFC) ||
+			(piocb->iocb.ulpCommand == CMD_ABORT_XRI_CN) ||
+			(piocb->iocb.ulpCommand == CMD_CLOSE_XRI_CN)) {
 			continue;
 		}
 		pcmd = (struct lpfc_dmabuf *) piocb->context2;
-		elscmd = (uint32_t *) (pcmd->virt);
-		els_command = *elscmd;
+		if (pcmd) {
+			elscmd = (uint32_t *) (pcmd->virt);
+			els_command = *elscmd;
+		}
 
 		if ((els_command == ELS_CMD_FARP)
 		    || (els_command == ELS_CMD_FARPR)) {
@@ -3289,19 +3275,12 @@ lpfc_els_timeout_handler(struct lpfc_hba
 			continue;
 		}
 
-		list_del(&piocb->list);
-		pring->txcmplq_cnt--;
-
 		if (cmd->ulpCommand == CMD_GEN_REQUEST64_CR) {
 			struct lpfc_nodelist *ndlp;
 			spin_unlock_irq(phba->host->host_lock);
 			ndlp = lpfc_findnode_rpi(phba, cmd->ulpContext);
 			spin_lock_irq(phba->host->host_lock);
 			remote_ID = ndlp->nlp_DID;
-			if (cmd->un.elsreq64.bdl.ulpIoTag32) {
-				lpfc_sli_issue_abort_iotag32(phba,
-					pring, piocb);
-			}
 		} else {
 			remote_ID = cmd->un.elsreq64.remoteID;
 		}
@@ -3313,17 +3292,7 @@ lpfc_els_timeout_handler(struct lpfc_hba
 				phba->brd_no, els_command,
 				remote_ID, cmd->ulpCommand, cmd->ulpIoTag);
 
-		/*
-		 * The iocb has timed out; abort it.
-		 */
-		if (piocb->iocb_cmpl) {
-			cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
-			cmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
-			spin_unlock_irq(phba->host->host_lock);
-			(piocb->iocb_cmpl) (phba, piocb, piocb);
-			spin_lock_irq(phba->host->host_lock);
-		} else
-			lpfc_sli_release_iocbq(phba, piocb);
+		lpfc_sli_issue_abort_iotag(phba, pring, piocb);
 	}
 	if (phba->sli.ring[LPFC_ELS_RING].txcmplq_cnt)
 		mod_timer(&phba->els_tmofunc, jiffies + HZ * timeout);
@@ -3337,9 +3306,6 @@ lpfc_els_flush_cmd(struct lpfc_hba * phb
 	struct lpfc_sli_ring *pring;
 	struct lpfc_iocbq *tmp_iocb, *piocb;
 	IOCB_t *cmd = NULL;
-	struct lpfc_dmabuf *pcmd;
-	uint32_t *elscmd;
-	uint32_t els_command;
 
 	pring = &phba->sli.ring[LPFC_ELS_RING];
 	spin_lock_irq(phba->host->host_lock);
@@ -3358,12 +3324,8 @@ lpfc_els_flush_cmd(struct lpfc_hba * phb
 			continue;
 		}
 
-		pcmd = (struct lpfc_dmabuf *) piocb->context2;
-		elscmd = (uint32_t *) (pcmd->virt);
-		els_command = *elscmd;
-
 		list_del(&piocb->list);
-		pring->txcmplq_cnt--;
+		pring->txq_cnt--;
 
 		cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
 		cmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
@@ -3382,22 +3344,8 @@ lpfc_els_flush_cmd(struct lpfc_hba * phb
 		if (piocb->iocb_flag & LPFC_IO_LIBDFC) {
 			continue;
 		}
-		pcmd = (struct lpfc_dmabuf *) piocb->context2;
-		elscmd = (uint32_t *) (pcmd->virt);
-		els_command = *elscmd;
-
-		list_del(&piocb->list);
-		pring->txcmplq_cnt--;
 
-		cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
-		cmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
-
-		if (piocb->iocb_cmpl) {
-			spin_unlock_irq(phba->host->host_lock);
-			(piocb->iocb_cmpl) (phba, piocb, piocb);
-			spin_lock_irq(phba->host->host_lock);
-		} else
-			lpfc_sli_release_iocbq(phba, piocb);
+		lpfc_sli_issue_abort_iotag(phba, pring, piocb);
 	}
 	spin_unlock_irq(phba->host->host_lock);
 	return;
Index: latest/drivers/scsi/lpfc/lpfc.h
===================================================================
--- latest.orig/drivers/scsi/lpfc/lpfc.h
+++ latest/drivers/scsi/lpfc/lpfc.h
@@ -1,7 +1,7 @@
 /*******************************************************************
  * This file is part of the Emulex Linux Device Driver for         *
  * Fibre Channel Host Bus Adapters.                                *
- * Copyright (C) 2004-2006 Emulex.  All rights reserved.           *
+ * Copyright (C) 2004-2007 Emulex.  All rights reserved.           *
  * EMULEX and SLI are trademarks of Emulex.                        *
  * www.emulex.com                                                  *
  * Portions Copyright (C) 2004-2005 Christoph Hellwig              *
@@ -27,10 +27,6 @@ struct lpfcdfc_host;
 					   requests */
 #define LPFC_MAX_NS_RETRY	3	/* Number of retry attempts to contact
 					   the NameServer  before giving up. */
-#define LPFC_DFT_HBA_Q_DEPTH	2048	/* max cmds per hba */
-#define LPFC_LC_HBA_Q_DEPTH	1024	/* max cmds per low cost hba */
-#define LPFC_LP101_HBA_Q_DEPTH	128	/* max cmds per low cost hba */
-
 #define LPFC_CMD_PER_LUN	3	/* max outstanding cmds per lun */
 #define LPFC_SG_SEG_CNT		64	/* sg element count per scsi cmnd */
 #define LPFC_IOCB_LIST_CNT	2250	/* list of IOCBs for fast-path usage. */
@@ -244,12 +240,17 @@ struct lpfc_hba {
 #define FC_FABRIC               0x100	/* We are fabric attached */
 #define FC_ESTABLISH_LINK       0x200	/* Reestablish Link */
 #define FC_RSCN_DISCOVERY       0x400	/* Authenticate all devices after RSCN*/
+#define FC_BLOCK_MGMT_IO        0x800   /* Don't allow mgmt mbx or iocb cmds */
 #define FC_LOADING		0x1000	/* HBA in process of loading drvr */
 #define FC_UNLOADING		0x2000	/* HBA in process of unloading drvr */
 #define FC_SCSI_SCAN_TMO        0x4000	/* scsi scan timer running */
 #define FC_ABORT_DISCOVERY      0x8000	/* we want to abort discovery */
 #define FC_NDISC_ACTIVE         0x10000	/* NPort discovery active */
 #define FC_BYPASSED_MODE        0x20000	/* NPort is in bypassed mode */
+#define FC_LOOPBACK_MODE        0x40000	/* NPort is in Loopback mode */
+					/* This flag is set while issuing */
+					/* INIT_LINK mailbox command */
+#define FC_IGNORE_ERATT         0x80000	/* intr handler should ignore ERATT */
 
 	uint32_t fc_topology;	/* link topology, from LINK INIT */
 
@@ -393,8 +394,16 @@ struct lpfc_hba {
 
 	struct fc_host_statistics link_stats;
 	struct lpfcdfc_host *dfc_host;
+	unsigned long pci_max_read;
 };
 
+static inline void
+lpfc_set_loopback_flag(struct lpfc_hba *phba) {
+	if (phba->cfg_topology == FLAGS_LOCAL_LB)
+		phba->fc_flag |= FC_LOOPBACK_MODE;
+	else
+		phba->fc_flag &= ~FC_LOOPBACK_MODE;
+}
 
 struct rnidrsp {
 	void *buf;
Index: latest/drivers/scsi/lpfc/lpfc_hbadisc.c
===================================================================
--- latest.orig/drivers/scsi/lpfc/lpfc_hbadisc.c
+++ latest/drivers/scsi/lpfc/lpfc_hbadisc.c
@@ -1,7 +1,7 @@
 /*******************************************************************
  * This file is part of the Emulex Linux Device Driver for         *
  * Fibre Channel Host Bus Adapters.                                *
- * Copyright (C) 2004-2006 Emulex.  All rights reserved.           *
+ * Copyright (C) 2004-2007 Emulex.  All rights reserved.           *
  * EMULEX and SLI are trademarks of Emulex.                        *
  * www.emulex.com                                                  *
  * Portions Copyright (C) 2004-2005 Christoph Hellwig              *
@@ -110,6 +110,9 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport
 		return;
 	}
 
+	if (ndlp->nlp_state == NLP_STE_MAPPED_NODE)
+		return;
+
 	name = (uint8_t *)&ndlp->nlp_portname;
 	phba = ndlp->nlp_phba;
 
@@ -148,11 +151,15 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport
 				ndlp->nlp_state, ndlp->nlp_rpi);
 	}
 
-	ndlp->rport = NULL;
-	rdata->pnode = NULL;
-
-	if (!(phba->fc_flag & FC_UNLOADING))
+	if (!(phba->fc_flag & FC_UNLOADING) &&
+	    !(ndlp->nlp_flag & NLP_DELAY_TMO) &&
+	    !(ndlp->nlp_flag & NLP_NPR_2B_DISC) &&
+	    (ndlp->nlp_state != NLP_STE_UNMAPPED_NODE))
 		lpfc_disc_state_machine(phba, ndlp, NULL, NLP_EVT_DEVICE_RM);
+	else {
+		rdata->pnode = NULL;
+		ndlp->rport = NULL;
+	}
 
 	return;
 }
@@ -183,29 +190,35 @@ lpfc_work_list_done(struct lpfc_hba * ph
 				*(int *)(evtp->evt_arg1)  = 0;
 			complete((struct completion *)(evtp->evt_arg2));
 			break;
-		case LPFC_EVT_OFFLINE:
+		case LPFC_EVT_OFFLINE_PREP:
 			if (phba->hba_state >= LPFC_LINK_DOWN)
-				lpfc_offline(phba);
+				lpfc_offline_prep(phba);
+			*(int *)(evtp->evt_arg1) = 0;
+			complete((struct completion *)(evtp->evt_arg2));
+			break;
+		case LPFC_EVT_OFFLINE:
+			lpfc_offline(phba);
 			lpfc_sli_brdrestart(phba);
 			*(int *)(evtp->evt_arg1) =
-				lpfc_sli_brdready(phba,HS_FFRDY | HS_MBRDY);
+				lpfc_sli_brdready(phba, HS_FFRDY | HS_MBRDY);
+			lpfc_unblock_mgmt_io(phba);
 			complete((struct completion *)(evtp->evt_arg2));
 			break;
 		case LPFC_EVT_WARM_START:
-			if (phba->hba_state >= LPFC_LINK_DOWN)
-				lpfc_offline(phba);
+			lpfc_offline(phba);
 			lpfc_reset_barrier(phba);
 			lpfc_sli_brdreset(phba);
 			lpfc_hba_down_post(phba);
 			*(int *)(evtp->evt_arg1) =
 				lpfc_sli_brdready(phba, HS_MBRDY);
+			lpfc_unblock_mgmt_io(phba);
 			complete((struct completion *)(evtp->evt_arg2));
 			break;
 		case LPFC_EVT_KILL:
-			if (phba->hba_state >= LPFC_LINK_DOWN)
-				lpfc_offline(phba);
+			lpfc_offline(phba);
 			*(int *)(evtp->evt_arg1)
 				= (phba->stopped) ? 0 : lpfc_sli_brdkill(phba);
+			lpfc_unblock_mgmt_io(phba);
 			complete((struct completion *)(evtp->evt_arg2));
 			break;
 		}
@@ -735,6 +748,9 @@ lpfc_mbx_process_link_up(struct lpfc_hba
 		case LA_4GHZ_LINK:
 			phba->fc_linkspeed = LA_4GHZ_LINK;
 			break;
+		case LA_8GHZ_LINK:
+			phba->fc_linkspeed = LA_8GHZ_LINK;
+			break;
 		default:
 			phba->fc_linkspeed = LA_UNKNW_LINK;
 			break;
@@ -890,12 +906,21 @@ lpfc_mbx_cmpl_read_la(struct lpfc_hba * 
 
 	if (la->attType == AT_LINK_UP) {
 		phba->fc_stat.LinkUp++;
-		lpfc_printf_log(phba, KERN_ERR, LOG_LINK_EVENT,
+		if (phba->fc_flag & FC_LOOPBACK_MODE) {
+			lpfc_printf_log(phba, KERN_INFO, LOG_LINK_EVENT,
+				"%d:1306 Link Up Event in loop back mode "
+				"x%x received Data: x%x x%x x%x x%x\n",
+				phba->brd_no, la->eventTag, phba->fc_eventTag,
+				la->granted_AL_PA, la->UlnkSpeed,
+				phba->alpa_map[0]);
+		} else {
+			lpfc_printf_log(phba, KERN_ERR, LOG_LINK_EVENT,
 				"%d:1303 Link Up Event x%x received "
 				"Data: x%x x%x x%x x%x\n",
 				phba->brd_no, la->eventTag, phba->fc_eventTag,
 				la->granted_AL_PA, la->UlnkSpeed,
 				phba->alpa_map[0]);
+		}
 		lpfc_mbx_process_link_up(phba, la);
 	} else {
 		phba->fc_stat.LinkDown++;
@@ -1331,9 +1356,7 @@ lpfc_nlp_list(struct lpfc_hba * phba, st
 			 * already. If we have, and it's a scsi entity, be
 			 * sure to unblock any attached scsi devices
 			 */
-			if ((!nlp->rport) || (nlp->rport->port_state ==
-					FC_PORTSTATE_BLOCKED))
-				lpfc_register_remote_port(phba, nlp);
+			lpfc_register_remote_port(phba, nlp);
 
 			/*
 			 * if we added to Mapped list, but the remote port
@@ -1570,16 +1593,6 @@ lpfc_freenode(struct lpfc_hba * phba, st
 
 	lpfc_nlp_list(phba, ndlp, NLP_JUST_DQ);
 
-	/*
-	 * if unloading the driver - just leave the remote port in place.
-	 * The driver unload will force the attached devices to detach
-	 * and flush cache's w/o generating flush errors.
-	 */
-	if ((ndlp->rport) && !(phba->fc_flag & FC_UNLOADING)) {
-		lpfc_unregister_remote_port(phba, ndlp);
-		ndlp->nlp_sid = NLP_NO_SID;
-	}
-
 	/* cleanup any ndlp on mbox q waiting for reglogin cmpl */
 	if ((mb = phba->sli.mbox_active)) {
 		if ((mb->mb.mbxCommand == MBX_REG_LOGIN64) &&
@@ -1604,7 +1617,7 @@ lpfc_freenode(struct lpfc_hba * phba, st
 	}
 	spin_unlock_irq(phba->host->host_lock);
 
-	lpfc_els_abort(phba,ndlp,0);
+	lpfc_els_abort(phba,ndlp);
 	spin_lock_irq(phba->host->host_lock);
 	ndlp->nlp_flag &= ~NLP_DELAY_TMO;
 	spin_unlock_irq(phba->host->host_lock);
@@ -1628,6 +1641,7 @@ lpfc_freenode(struct lpfc_hba * phba, st
 int
 lpfc_nlp_remove(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp)
 {
+	struct lpfc_rport_data *rdata;
 
 	if (ndlp->nlp_flag & NLP_DELAY_TMO) {
 		lpfc_cancel_retry_delay_tmo(phba, ndlp);
@@ -1639,6 +1653,13 @@ lpfc_nlp_remove(struct lpfc_hba * phba, 
 		spin_unlock_irq(phba->host->host_lock);
 	} else {
 		lpfc_freenode(phba, ndlp);
+
+		if ((ndlp->rport) && !(phba->fc_flag & FC_UNLOADING)) {
+			rdata = ndlp->rport->dd_data;
+			rdata->pnode = NULL;
+			ndlp->rport = NULL;
+		}
+
 		mempool_free( ndlp, phba->nlp_mem_pool);
 	}
 	return 0;
@@ -2221,6 +2242,7 @@ lpfc_disc_timeout_handler(struct lpfc_hb
 		initlinkmbox->mb.un.varInitLnk.lipsr_AL_PA = 0;
 		rc = lpfc_sli_issue_mbox(phba, initlinkmbox,
 					 (MBX_NOWAIT | MBX_STOP_IOCB));
+		lpfc_set_loopback_flag(phba);
 		if (rc == MBX_NOT_FINISHED)
 			mempool_free(initlinkmbox, phba->mbox_mem_pool);
 
Index: latest/drivers/scsi/lpfc/lpfc_hw.h
===================================================================
--- latest.orig/drivers/scsi/lpfc/lpfc_hw.h
+++ latest/drivers/scsi/lpfc/lpfc_hw.h
@@ -1,7 +1,7 @@
 /*******************************************************************
  * This file is part of the Emulex Linux Device Driver for         *
  * Fibre Channel Host Bus Adapters.                                *
- * Copyright (C) 2004-2006 Emulex.  All rights reserved.           *
+ * Copyright (C) 2004-2007 Emulex.  All rights reserved.           *
  * EMULEX and SLI are trademarks of Emulex.                        *
  * www.emulex.com                                                  *
  *                                                                 *
@@ -1078,6 +1078,8 @@ typedef struct {
 /* Start FireFly Register definitions */
 #define PCI_VENDOR_ID_EMULEX        0x10df
 #define PCI_DEVICE_ID_FIREFLY       0x1ae5
+#define PCI_DEVICE_ID_SAT_SMB       0xf011
+#define PCI_DEVICE_ID_SAT_MID       0xf015
 #define PCI_DEVICE_ID_RFLY          0xf095
 #define PCI_DEVICE_ID_PFLY          0xf098
 #define PCI_DEVICE_ID_LP101         0xf0a1
@@ -1089,6 +1091,9 @@ typedef struct {
 #define PCI_DEVICE_ID_NEPTUNE       0xf0f5
 #define PCI_DEVICE_ID_NEPTUNE_SCSP  0xf0f6
 #define PCI_DEVICE_ID_NEPTUNE_DCSP  0xf0f7
+#define PCI_DEVICE_ID_SAT           0xf100
+#define PCI_DEVICE_ID_SAT_SCSP      0xf111
+#define PCI_DEVICE_ID_SAT_DCSP      0xf112
 #define PCI_DEVICE_ID_SUPERFLY      0xf700
 #define PCI_DEVICE_ID_DRAGONFLY     0xf800
 #define PCI_DEVICE_ID_CENTAUR       0xf900
@@ -1098,6 +1103,7 @@ typedef struct {
 #define PCI_DEVICE_ID_LP10000S      0xfc00
 #define PCI_DEVICE_ID_LP11000S      0xfc10
 #define PCI_DEVICE_ID_LPE11000S     0xfc20
+#define PCI_DEVICE_ID_SAT_S         0xfc40
 #define PCI_DEVICE_ID_HELIOS        0xfd00
 #define PCI_DEVICE_ID_HELIOS_SCSP   0xfd11
 #define PCI_DEVICE_ID_HELIOS_DCSP   0xfd12
@@ -1118,6 +1124,7 @@ typedef struct {
 #define HELIOS_JEDEC_ID             0x0364
 #define ZEPHYR_JEDEC_ID             0x0577
 #define VIPER_JEDEC_ID              0x4838
+#define SATURN_JEDEC_ID             0x1004
 
 #define JEDEC_ID_MASK               0x0FFFF000
 #define JEDEC_ID_SHIFT              12
@@ -1357,6 +1364,7 @@ typedef struct {		/* FireFly BIU registe
 #define MBXERR_BAD_RCV_LENGTH       14
 #define MBXERR_DMA_ERROR            15
 #define MBXERR_ERROR                16
+#define MBXERR_UNKNOWN_CMD          18
 #define MBX_NOT_FINISHED           255
 
 #define MBX_BUSY                   0xffffff /* Attempted cmd to busy Mailbox */
@@ -1565,7 +1573,7 @@ typedef struct {
 #define LINK_SPEED_1G   1       /* 1 Gigabaud */
 #define LINK_SPEED_2G   2       /* 2 Gigabaud */
 #define LINK_SPEED_4G   4       /* 4 Gigabaud */
-#define LINK_SPEED_8G   8       /* 4 Gigabaud */
+#define LINK_SPEED_8G   8       /* 8 Gigabaud */
 #define LINK_SPEED_10G   16      /* 10 Gigabaud */
 
 } INIT_LINK_VAR;
@@ -2137,6 +2145,13 @@ typedef struct {
 	uint32_t rsvd1;
 } CLEAR_LA_VAR;
 
+/* Values needed to set MAX_DMA_LENGTH parameter */
+#define SLIM_VAR_MAX_DMA_LENGTH 0x100506
+#define SLIM_VAL_MAX_DMA_512    0x0
+#define SLIM_VAL_MAX_DMA_1024   0x1
+#define SLIM_VAL_MAX_DMA_2048   0x2
+#define SLIM_VAL_MAX_DMA_4096   0x3
+
 /* Structure for MB Command DUMP */
 
 typedef struct {
Index: latest/drivers/scsi/lpfc/lpfc_init.c
===================================================================
--- latest.orig/drivers/scsi/lpfc/lpfc_init.c
+++ latest/drivers/scsi/lpfc/lpfc_init.c
@@ -1,7 +1,7 @@
 /*******************************************************************
  * This file is part of the Emulex Linux Device Driver for         *
  * Fibre Channel Host Bus Adapters.                                *
- * Copyright (C) 2004-2006 Emulex.  All rights reserved.           *
+ * Copyright (C) 2004-2007 Emulex.  All rights reserved.           *
  * EMULEX and SLI are trademarks of Emulex.                        *
  * www.emulex.com                                                  *
  * Portions Copyright (C) 2004-2005 Christoph Hellwig              *
@@ -42,6 +42,7 @@
 #include "lpfc_crtn.h"
 #include "lpfc_version.h"
 #include "lpfc_ioctl.h"
+#include "lpfc_compat.h"
 
 static int lpfc_parse_vpd(struct lpfc_hba *, uint8_t *, int);
 static void lpfc_get_hba_model_desc(struct lpfc_hba *, uint8_t *, uint8_t *);
@@ -387,12 +388,12 @@ lpfc_config_port_post(struct lpfc_hba * 
 	 * Setup the ring 0 (els)  timeout handler
 	 */
 	timeout = phba->fc_ratov << 1;
-	phba->els_tmofunc.expires = jiffies + HZ * timeout;
-	add_timer(&phba->els_tmofunc);
+	mod_timer(&phba->els_tmofunc, jiffies + HZ * timeout);
 
 	lpfc_init_link(phba, pmb, phba->cfg_topology, phba->cfg_link_speed);
 	pmb->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
 	rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT);
+	lpfc_set_loopback_flag(phba);
 	if (rc != MBX_SUCCESS) {
 		lpfc_printf_log(phba,
 				KERN_ERR,
@@ -547,12 +548,15 @@ lpfc_handle_eratt(struct lpfc_hba * phba
 		 * There was a firmware error.  Take the hba offline and then
 		 * attempt to restart it.
 		 */
+		lpfc_offline_prep(phba);
 		lpfc_offline(phba);
 		lpfc_sli_brdrestart(phba);
 		if (lpfc_online(phba) == 0) {	/* Initialize the HBA */
 			mod_timer(&phba->fc_estabtmo, jiffies + HZ * 60);
+			lpfc_unblock_mgmt_io(phba);
 			return;
 		}
+		lpfc_unblock_mgmt_io(phba);
 	} else {
 		/* The if clause above forces this code path when the status
 		 * failure is a value other than FFER6.  Do not call the offline
@@ -570,7 +574,9 @@ lpfc_handle_eratt(struct lpfc_hba * phba
 				SCSI_NL_VID_TYPE_PCI | PCI_VENDOR_ID_EMULEX);
 
 		psli->sli_flag &= ~LPFC_SLI2_ACTIVE;
+		lpfc_offline_prep(phba);
 		lpfc_offline(phba);
+		lpfc_unblock_mgmt_io(phba);
 		phba->hba_state = LPFC_HBA_ERROR;
 		lpfc_hba_down_post(phba);
 	}
@@ -630,7 +636,7 @@ lpfc_handle_latt_free_mbuf:
 lpfc_handle_latt_free_mp:
 	kfree(mp);
 lpfc_handle_latt_free_pmb:
-	kfree(pmb);
+	mempool_free(pmb, phba->mbox_mem_pool);
 lpfc_handle_latt_err_exit:
 	/* Enable Link attention interrupts */
 	spin_lock_irq(phba->host->host_lock);
@@ -922,6 +928,24 @@ lpfc_get_hba_model_desc(struct lpfc_hba 
 		m = (typeof(m)){"LPe11000-S", max_speed,
 			"PCIe"};
 		break;
+	case PCI_DEVICE_ID_SAT:
+		m = (typeof(m)){"LPe12000", max_speed, "PCIe"};
+		break;
+	case PCI_DEVICE_ID_SAT_MID:
+		m = (typeof(m)){"LPe1250", max_speed, "PCIe"};
+		break;
+	case PCI_DEVICE_ID_SAT_SMB:
+		m = (typeof(m)){"LPe121", max_speed, "PCIe"};
+		break;
+	case PCI_DEVICE_ID_SAT_DCSP:
+		m = (typeof(m)){"LPe12002-SP", max_speed, "PCIe"};
+		break;
+	case PCI_DEVICE_ID_SAT_SCSP:
+		m = (typeof(m)){"LPe12000-SP", max_speed, "PCIe"};
+		break;
+	case PCI_DEVICE_ID_SAT_S:
+		m = (typeof(m)){"LPe12000-S", max_speed, "PCIe"};
+		break;
 	default:
 		m = (typeof(m)){ NULL };
 		break;
@@ -1171,7 +1195,7 @@ lpfc_hba_init(struct lpfc_hba *phba, uin
 }
 
 static void
-lpfc_cleanup(struct lpfc_hba * phba, uint32_t save_bind)
+lpfc_cleanup(struct lpfc_hba * phba)
 {
 	struct lpfc_nodelist *ndlp, *next_ndlp;
 
@@ -1299,60 +1323,90 @@ lpfc_online(struct lpfc_hba * phba)
 		       "%d:0458 Bring Adapter online\n",
 		       phba->brd_no);
 
-	if (!lpfc_sli_queue_setup(phba))
+	lpfc_block_mgmt_io(phba);
+
+	if (!lpfc_sli_queue_setup(phba)) {
+		lpfc_unblock_mgmt_io(phba);
 		return 1;
+	}
 
-	if (lpfc_sli_hba_setup(phba))	/* Initialize the HBA */
+	if (lpfc_sli_hba_setup(phba)) {	/* Initialize the HBA */
+		lpfc_unblock_mgmt_io(phba);
 		return 1;
+	}
 
 	spin_lock_irq(phba->host->host_lock);
 	phba->fc_flag &= ~FC_OFFLINE_MODE;
 	spin_unlock_irq(phba->host->host_lock);
 
+	lpfc_unblock_mgmt_io(phba);
 	return 0;
 }
 
-int
-lpfc_offline(struct lpfc_hba * phba)
+void
+lpfc_block_mgmt_io(struct lpfc_hba * phba)
 {
-	struct lpfc_sli_ring *pring;
-	struct lpfc_sli *psli;
 	unsigned long iflag;
-	int i;
-	int cnt = 0;
 
-	if (!phba)
-		return 0;
+	spin_lock_irqsave(phba->host->host_lock, iflag);
+	phba->fc_flag |= FC_BLOCK_MGMT_IO;
+	spin_unlock_irqrestore(phba->host->host_lock, iflag);
+}
+
+void
+lpfc_unblock_mgmt_io(struct lpfc_hba * phba)
+{
+	unsigned long iflag;
+
+	spin_lock_irqsave(phba->host->host_lock, iflag);
+	phba->fc_flag &= ~FC_BLOCK_MGMT_IO;
+	spin_unlock_irqrestore(phba->host->host_lock, iflag);
+}
+
+void
+lpfc_offline_prep(struct lpfc_hba * phba)
+{
+	struct lpfc_nodelist  *ndlp, *next_ndlp;
+	struct list_head *listp, *node_list[7];
+	int i;
 
 	if (phba->fc_flag & FC_OFFLINE_MODE)
-		return 0;
+		return;
 
-	psli = &phba->sli;
+	lpfc_block_mgmt_io(phba);
 
 	lpfc_linkdown(phba);
-	lpfc_sli_flush_mbox_queue(phba);
 
-	for (i = 0; i < psli->num_rings; i++) {
-		pring = &psli->ring[i];
-		/* The linkdown event takes 30 seconds to timeout. */
-		while (pring->txcmplq_cnt) {
-			mdelay(10);
-			if (cnt++ > 3000) {
-				lpfc_printf_log(phba,
-					KERN_WARNING, LOG_INIT,
-					"%d:0466 Outstanding IO when "
-					"bringing Adapter offline\n",
-					phba->brd_no);
-				break;
-			}
-		}
+	/* Issue an unreg_login to all nodes */
+	node_list[0] = &phba->fc_npr_list;  /* MUST do this list first */
+	node_list[1] = &phba->fc_nlpmap_list;
+	node_list[2] = &phba->fc_nlpunmap_list;
+	node_list[3] = &phba->fc_prli_list;
+	node_list[4] = &phba->fc_reglogin_list;
+	node_list[5] = &phba->fc_adisc_list;
+	node_list[6] = &phba->fc_plogi_list;
+	for (i = 0; i < 7; i++) {
+		listp = node_list[i];
+		if (list_empty(listp))
+			continue;
+
+		list_for_each_entry_safe(ndlp, next_ndlp, listp, nlp_listp)
+			lpfc_unreg_rpi(phba, ndlp);
 	}
 
+	lpfc_sli_flush_mbox_queue(phba);
+}
+
+void
+lpfc_offline(struct lpfc_hba * phba)
+{
+	unsigned long iflag;
+
+	if (phba->fc_flag & FC_OFFLINE_MODE)
+		return;
 
 	/* stop all timers associated with this hba */
 	lpfc_stop_timer(phba);
-	phba->work_hba_events = 0;
-	phba->work_ha = 0;
 
 	lpfc_printf_log(phba,
 		       KERN_WARNING,
@@ -1363,11 +1417,12 @@ lpfc_offline(struct lpfc_hba * phba)
 	/* Bring down the SLI Layer and cleanup.  The HBA is offline
 	   now.  */
 	lpfc_sli_hba_down(phba);
-	lpfc_cleanup(phba, 1);
+	lpfc_cleanup(phba);
 	spin_lock_irqsave(phba->host->host_lock, iflag);
+	phba->work_hba_events = 0;
+	phba->work_ha = 0;
 	phba->fc_flag |= FC_OFFLINE_MODE;
 	spin_unlock_irqrestore(phba->host->host_lock, iflag);
-	return 0;
 }
 
 /******************************************************************************
@@ -1404,6 +1459,31 @@ lpfc_scsi_free(struct lpfc_hba * phba)
 	return 0;
 }
 
+static void
+lpfc_setup_max_dma_length(struct lpfc_hba * phba)
+{
+	struct pci_dev *pdev = phba->pcidev;
+	struct pci_bus *bus = pdev->bus;
+	uint8_t rev;
+
+	while(bus) {
+		/*
+		 * 0x7450 == PCI_DEVICE_ID_AMD_8131_BRIDGE for 2.6 kernels
+		 * 0x7450 == PCI_DEVICE_ID_AMD_8131_APIC   for 2.4 kernels
+		 */
+		if ( bus->self &&
+			(bus->self->vendor == PCI_VENDOR_ID_AMD) &&
+			(bus->self->device == PCI_DEVICE_ID_AMD_8131_BRIDGE)) {
+				pci_read_config_byte(bus->self, 0x08, &rev);
+				if (rev == 0x13) {
+					phba->pci_max_read = 1024;
+					return;
+				}
+		}
+		bus = bus->parent;
+	}
+	return;
+}
 
 static int __devinit
 lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
@@ -1433,6 +1513,9 @@ lpfc_pci_probe_one(struct pci_dev *pdev,
 	phba->fc_flag |= FC_LOADING;
 	phba->pcidev = pdev;
 
+	/* Check if we need to change the DMA length */
+	lpfc_setup_max_dma_length(phba);
+
 	/* Assign an unused board number */
 	if (!idr_pre_get(&lpfc_hba_index, GFP_KERNEL))
 		goto out_put_host;
@@ -1686,6 +1769,8 @@ lpfc_pci_probe_one(struct pci_dev *pdev,
 	fc_host_supported_speeds(host) = 0;
 	if (phba->lmt & LMT_10Gb)
 		fc_host_supported_speeds(host) |= FC_PORTSPEED_10GBIT;
+	if (phba->lmt & LMT_8Gb)
+		fc_host_supported_speeds(host) |= FC_PORTSPEED_8GBIT;
 	if (phba->lmt & LMT_4Gb)
 		fc_host_supported_speeds(host) |= FC_PORTSPEED_4GBIT;
 	if (phba->lmt & LMT_2Gb)
@@ -1709,6 +1794,8 @@ lpfc_pci_probe_one(struct pci_dev *pdev,
 	return 0;
 
 out_free_irq:
+	if (phba->dfc_host)
+		lpfcdfc_host_del(phba->dfc_host);
 	lpfc_stop_timer(phba);
 	phba->work_hba_events = 0;
 	free_irq(phba->pcidev->irq, phba);
@@ -1784,7 +1871,7 @@ lpfc_pci_remove_one(struct pci_dev *pdev
 	free_irq(phba->pcidev->irq, phba);
 	pci_disable_msi(phba->pcidev);
 
-	lpfc_cleanup(phba, 0);
+	lpfc_cleanup(phba);
 	lpfc_stop_timer(phba);
 	phba->work_hba_events = 0;
 
@@ -1867,6 +1954,18 @@ static struct pci_device_id lpfc_id_tabl
 		PCI_ANY_ID, PCI_ANY_ID, },
 	{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_LPE11000S,
 		PCI_ANY_ID, PCI_ANY_ID, },
+	{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_SAT,
+		PCI_ANY_ID, PCI_ANY_ID, },
+	{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_SAT_MID,
+		PCI_ANY_ID, PCI_ANY_ID, },
+	{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_SAT_SMB,
+		PCI_ANY_ID, PCI_ANY_ID, },
+	{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_SAT_DCSP,
+		PCI_ANY_ID, PCI_ANY_ID, },
+	{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_SAT_SCSP,
+		PCI_ANY_ID, PCI_ANY_ID, },
+	{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_SAT_S,
+		PCI_ANY_ID, PCI_ANY_ID, },
 	{ 0 }
 };
 
Index: latest/drivers/scsi/lpfc/lpfc_ioctl.c
===================================================================
--- latest.orig/drivers/scsi/lpfc/lpfc_ioctl.c
+++ latest/drivers/scsi/lpfc/lpfc_ioctl.c
@@ -1,7 +1,7 @@
 /*******************************************************************
  * This file is part of the Emulex Linux Device Driver for         *
  * Fibre Channel Host Bus Adapters.                                *
- * Copyright (C) 2006 Emulex.  All rights reserved.                *
+ * Copyright (C) 2006-2007 Emulex.  All rights reserved.                *
  * EMULEX and SLI are trademarks of Emulex.                        *
  * www.emulex.com                                                  *
  *                                                                 *
@@ -169,11 +169,11 @@ lpfc_ioctl_hba_rnid(struct lpfc_hba * ph
 	if (idn.idType == LPFC_WWNN_TYPE)
 		pndl = lpfc_findnode_wwnn(phba,
 					NLP_SEARCH_MAPPED | NLP_SEARCH_UNMAPPED,
-					(struct lpfc_name *) &idn);
+					(struct lpfc_name *) idn.wwpn);
 	else
 		pndl = lpfc_findnode_wwpn(phba,
 					NLP_SEARCH_MAPPED | NLP_SEARCH_UNMAPPED,
-					(struct lpfc_name *) &idn);
+					(struct lpfc_name *) idn.wwpn);
 
 	if (!pndl)
 		return ENODEV;
@@ -303,12 +303,16 @@ lpfc_ioctl_timeout_iocb_cmpl(struct lpfc
 			     struct lpfc_iocbq * rsp_iocb_q)
 {
 	struct lpfc_timedout_iocb_ctxt *iocb_ctxt = cmd_iocb_q->context1;
+	unsigned long iflag;
 
 	if (!iocb_ctxt) {
 		if (cmd_iocb_q->context2)
 			lpfc_els_free_iocb(phba, cmd_iocb_q);
-		else
+		else {
+			spin_lock_irqsave(phba->host->host_lock, iflag);
 			lpfc_sli_release_iocbq(phba,cmd_iocb_q);
+			spin_unlock_irqrestore(phba->host->host_lock, iflag);
+		}
 		return;
 	}
 
@@ -332,10 +336,12 @@ lpfc_ioctl_timeout_iocb_cmpl(struct lpfc
 		kfree(iocb_ctxt->bmp);
 	}
 
+	spin_lock_irqsave(phba->host->host_lock, iflag);
 	lpfc_sli_release_iocbq(phba,cmd_iocb_q);
 
 	if (iocb_ctxt->rspiocbq)
 			lpfc_sli_release_iocbq(phba, iocb_ctxt->rspiocbq);
+	spin_unlock_irqrestore(phba->host->host_lock, iflag);
 
 	kfree(iocb_ctxt);
 }
@@ -361,6 +367,7 @@ lpfc_ioctl_send_els(struct lpfc_hba * ph
 	uint32_t cmdsize;
 	uint32_t rspsize;
 	uint32_t elscmd;
+	int iocb_status;
 
 	elscmd = *(uint32_t *)cip->lpfc_arg2;
 	cmdsize = cip->lpfc_arg4;
@@ -370,8 +377,12 @@ lpfc_ioctl_send_els(struct lpfc_hba * ph
 			   sizeof(struct nport_id)))
 		return EIO;
 
-	if ((rspiocbq = lpfc_sli_get_iocbq(phba)) == NULL)
+	spin_lock_irqsave(phba->host->host_lock, iflag);
+	if ((rspiocbq = lpfc_sli_get_iocbq(phba)) == NULL) {
+		spin_unlock_irqrestore(phba->host->host_lock, iflag);
 		return ENOMEM;
+	}
+	spin_unlock_irqrestore(phba->host->host_lock, iflag);
 
 	rsp = &rspiocbq->iocb;
 
@@ -410,7 +421,9 @@ lpfc_ioctl_send_els(struct lpfc_hba * ph
 		kfree(pndl);
 
 	if (cmdiocbq == NULL) {
+		spin_lock_irqsave(phba->host->host_lock, iflag);
 		lpfc_sli_release_iocbq(phba, rspiocbq);
+		spin_unlock_irqrestore(phba->host->host_lock, iflag);
 		return EIO;
 	}
 
@@ -468,8 +481,9 @@ lpfc_ioctl_send_els(struct lpfc_hba * ph
 	cmdiocbq->context2 = NULL;
 
 	spin_lock_irqsave(phba->host->host_lock, iflag);
-	rc = lpfc_sli_issue_iocb_wait(phba, pring, cmdiocbq, rspiocbq,
+	iocb_status = lpfc_sli_issue_iocb_wait(phba, pring, cmdiocbq, rspiocbq,
 				      (phba->fc_ratov*2) + LPFC_DRVR_TIMEOUT);
+	rc = iocb_status;
 
 	spin_unlock_irqrestore(phba->host->host_lock, iflag);
 	if (rc == IOCB_SUCCESS) {
@@ -532,7 +546,9 @@ lpfc_ioctl_send_els(struct lpfc_hba * ph
 	} else
 		cmdiocbq->context2 = (uint8_t *) pcmd;
 
-	lpfc_els_free_iocb(phba, cmdiocbq);
+	if (iocb_status != IOCB_TIMEDOUT)
+		lpfc_els_free_iocb(phba, cmdiocbq);
+
 	spin_lock_irqsave(phba->host->host_lock, iflag);
 	lpfc_sli_release_iocbq(phba, rspiocbq);
 	spin_unlock_irqrestore(phba->host->host_lock, iflag);
@@ -888,16 +904,14 @@ static inline void lpfcdfc_event_free(st
 	while(!list_empty(&evt->events_to_get)) {
 		ed = list_entry(evt->events_to_get.next, typeof(*ed), node);
 		list_del(&ed->node);
-		if(ed->data != NULL)
-			kfree(ed->data);
+		kfree(ed->data);
 		kfree(ed);
 	}
 
 	while(!list_empty(&evt->events_to_see)) {
 		ed = list_entry(evt->events_to_see.next, typeof(*ed), node);
 		list_del(&ed->node);
-		if(ed->data != NULL)
-			kfree(ed->data);
+		kfree(ed->data);
 		kfree(ed);
 	}
 
@@ -913,7 +927,7 @@ static inline void lpfcdfc_event_free(st
 static int
 lpfc_ioctl_hba_get_event(struct lpfc_hba * phba,
 			 struct lpfcCmdInput * cip,
-			 void *dataout, int data_size)
+			 void **dataout, int *data_size)
 {
 	uint32_t ev_mask   = ((uint32_t)(unsigned long)cip->lpfc_arg3 &
 			      FC_REG_EVENT_MASK);
@@ -971,13 +985,21 @@ lpfc_ioctl_hba_get_event(struct lpfc_hba
 		goto error_get_event_exit;
 	}
 
-	if(evt_dat->len > 0)
-		memcpy(dataout, evt_dat->data, evt_dat->len);
+	if (evt_dat->len > 0) {
+		*data_size = evt_dat->len;
+		*dataout = kmalloc(*data_size, GFP_KERNEL);
+		if (*dataout)
+			memcpy(*dataout, evt_dat->data, *data_size);
+		else
+			*data_size = 0;
 
+	} else
+		*data_size = 0;
 	ret_val = 0;
 
 error_get_event_exit:
 
+	kfree(evt_dat->data);
 	kfree(evt_dat);
 	mutex_lock(&lpfcdfc_lock);
 	lpfcdfc_event_unref(evt);
@@ -1039,7 +1061,8 @@ lpfc_ioctl_hba_set_event(struct lpfc_hba
 
 	evt->waiting = 1;
 	if (wait_event_interruptible(evt->wq,
-				     !list_empty(&evt->events_to_see))) {
+				     (!list_empty(&evt->events_to_see) ||
+					dfchba->blocked))) {
 		mutex_lock(&lpfcdfc_lock);
 		lpfcdfc_event_unref(evt); /* release ref */
 		lpfcdfc_event_unref(evt); /* delete */
@@ -1047,6 +1070,15 @@ lpfc_ioctl_hba_set_event(struct lpfc_hba
 		return EINTR;
 	}
 
+	mutex_lock(&lpfcdfc_lock);
+	if (dfchba->blocked) {
+		lpfcdfc_event_unref(evt);
+		lpfcdfc_event_unref(evt);
+		mutex_unlock(&lpfcdfc_lock);
+		return ENODEV;
+	}
+	mutex_unlock(&lpfcdfc_lock);
+
 	evt->wait_time_stamp = jiffies;
 	evt->waiting = 0;
 
@@ -1074,6 +1106,7 @@ lpfc_ioctl_loopback_mode(struct lpfc_hba
 	int rc = 0;
 
 	if ((phba->hba_state == LPFC_HBA_ERROR) ||
+	    (phba->fc_flag & FC_BLOCK_MGMT_IO) ||
 	    (!(psli->sli_flag & LPFC_SLI2_ACTIVE)))
 		return EACCES;
 
@@ -1123,6 +1156,7 @@ lpfc_ioctl_loopback_mode(struct lpfc_hba
 		if ((mbxstatus != MBX_SUCCESS) || (pmboxq->mb.mbxStatus))
 			rc = ENODEV;
 		else {
+			phba->fc_flag |= FC_LOOPBACK_MODE;
 			/* wait for the link attention interrupt */
 			msleep(100);
 
@@ -1176,7 +1210,10 @@ static int lpfcdfc_loop_self_reg(struct 
 	if ((status != MBX_SUCCESS) || (mbox->mb.mbxStatus)) {
 		lpfc_mbuf_free(phba, dmabuff->virt, dmabuff->phys);
 		kfree(dmabuff);
-		mempool_free(mbox, phba->mbox_mem_pool);
+		if (status == MBX_TIMEOUT)
+			mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
+		else
+			mempool_free(mbox, phba->mbox_mem_pool);
 		return ENODEV;
 	}
 
@@ -1247,8 +1284,10 @@ static int lpfcdfc_loop_get_xri(struct l
 	evt = lpfcdfc_event_new(FC_REG_CT_EVENT, current->pid,
 				SLI_CT_ELX_LOOPBACK);
 
+	spin_lock_irq(phba->host->host_lock);
 	cmdiocbq = lpfc_sli_get_iocbq(phba);
 	rspiocbq = lpfc_sli_get_iocbq(phba);
+	spin_unlock_irq(phba->host->host_lock);
 
 	dmabuf = kmalloc(sizeof (struct lpfc_dmabuf), GFP_KERNEL);
 	if (dmabuf) {
@@ -1353,10 +1392,12 @@ err_get_xri_exit:
 		kfree(dmabuf);
 	}
 
-	if (cmdiocbq)
+	spin_lock_irq(phba->host->host_lock);
+	if (cmdiocbq && (ret_val != IOCB_TIMEDOUT))
 		lpfc_sli_release_iocbq(phba, cmdiocbq);
 	if (rspiocbq)
 		lpfc_sli_release_iocbq(phba, rspiocbq);
+	spin_unlock_irq(phba->host->host_lock);
 
 	return ret_val;
 }
@@ -1378,7 +1419,10 @@ static int lpfcdfc_loop_post_rxbufs(stru
 	int ret_val = 0;
 	int i = 0;
 
+	spin_lock_irq(phba->host->host_lock);
 	cmdiocbq = lpfc_sli_get_iocbq(phba);
+	spin_unlock_irq(phba->host->host_lock);
+
 	rxbmp = kmalloc(sizeof (struct lpfc_dmabuf), GFP_KERNEL);
 	if (rxbmp != NULL) {
 		rxbmp->virt = lpfc_mbuf_alloc(phba, 0, &rxbmp->phys);
@@ -1462,8 +1506,10 @@ err_post_rxbufs_exit:
 		kfree(rxbmp);
 	}
 
+	spin_lock_irq(phba->host->host_lock);
 	if (cmdiocbq)
 		lpfc_sli_release_iocbq(phba, cmdiocbq);
+	spin_unlock_irq(phba->host->host_lock);
 
 	return ret_val;
 }
@@ -1495,8 +1541,9 @@ lpfc_ioctl_loopback_test(struct lpfc_hba
 	int rc = 0;
 
 	if ((phba->hba_state == LPFC_HBA_ERROR) ||
+	    (phba->fc_flag & FC_BLOCK_MGMT_IO) ||
 	    (!(psli->sli_flag & LPFC_SLI2_ACTIVE)))
-	        return EACCES;
+		return EACCES;
 
 	if ((size == 0) || (size > 80 * 4096))
 		return  ERANGE;
@@ -1528,8 +1575,11 @@ lpfc_ioctl_loopback_test(struct lpfc_hba
 	evt = lpfcdfc_event_new(FC_REG_CT_EVENT, current->pid,
 				SLI_CT_ELX_LOOPBACK);
 
+	spin_lock_irq(phba->host->host_lock);
 	cmdiocbq = lpfc_sli_get_iocbq(phba);
 	rspiocbq = lpfc_sli_get_iocbq(phba);
+	spin_unlock_irq(phba->host->host_lock);
+
 	txbmp = kmalloc(sizeof (struct lpfc_dmabuf), GFP_KERNEL);
 
 	if (txbmp) {
@@ -1651,11 +1701,13 @@ lpfc_ioctl_loopback_test(struct lpfc_hba
 err_loopback_test_exit:
 	lpfcdfc_loop_self_unreg(phba, rpi);
 
-	if (cmdiocbq != NULL)
+	spin_lock_irq(phba->host->host_lock);
+	if ((rc != IOCB_TIMEDOUT) && (cmdiocbq != NULL))
 		lpfc_sli_release_iocbq(phba, cmdiocbq);
 
 	if(rspiocbq != NULL)
 		lpfc_sli_release_iocbq(phba, rspiocbq);
+	spin_unlock_irq(phba->host->host_lock);
 
 	if (txbmp != NULL) {
 		if (txbpl != NULL) {
@@ -2131,10 +2183,15 @@ lpfcdfc_host_del (struct lpfcdfc_host * 
 	struct Scsi_Host * host;
 	struct lpfc_hba * phba = NULL;
 	struct lpfc_sli_ring_mask * prt = NULL;
+	struct lpfcdfc_event * evt;
 
 	mutex_lock(&lpfcdfc_lock);
 	dfchba->blocked = 1;
 
+	list_for_each_entry(evt, &dfchba->ev_waiters, node) {
+		wake_up_interruptible(&evt->wq);
+	}
+
 	while (dfchba->ref_count) {
 		mutex_unlock(&lpfcdfc_lock);
 		msleep(2000);
@@ -2186,8 +2243,9 @@ lpfcdfc_get_phba_by_inst(int inst)
 					return dfchba;
 				}
 			}
+			mutex_unlock(&lpfcdfc_lock);
 			lpfcdfc_host_del (dfchba);
-			break;
+			return NULL;
 		}
 	}
 	mutex_unlock(&lpfcdfc_lock);
@@ -2253,13 +2311,23 @@ lpfcdfc_do_ioctl(struct lpfcCmdInput *ci
 		total_mem = 4096;
 	}
 
-	dataout = kmalloc(total_mem, GFP_KERNEL);
-	if (!dataout && dfchba != NULL) {
-		mutex_lock(&lpfcdfc_lock);
-		if (dfchba)
-			dfchba->ref_count--;
-		mutex_unlock(&lpfcdfc_lock);
-		return ENOMEM;
+	/*
+	 * For LPFC_HBA_GET_EVENT allocate memory which is needed to store
+	 * event info. Allocating maximum possible buffer size (64KB) can fail
+	 * some times under heavy IO.
+	 */
+	if (cip->lpfc_cmd == LPFC_HBA_GET_EVENT) {
+		dataout = NULL;
+	} else {
+		dataout = kmalloc(total_mem, GFP_KERNEL);
+
+		if (!dataout && dfchba != NULL) {
+			mutex_lock(&lpfcdfc_lock);
+			if (dfchba)
+				dfchba->ref_count--;
+			mutex_unlock(&lpfcdfc_lock);
+			return ENOMEM;
+		}
 	}
 
 	switch (cip->lpfc_cmd) {
@@ -2285,7 +2353,12 @@ lpfcdfc_do_ioctl(struct lpfcCmdInput *ci
 		break;
 
 	case LPFC_HBA_GET_EVENT:
-		rc = lpfc_ioctl_hba_get_event(phba, cip, dataout, total_mem);
+		rc = lpfc_ioctl_hba_get_event(phba, cip, &dataout, &total_mem);
+		if ((total_mem) &&  (copy_to_user ((void __user *)
+			cip->lpfc_dataout, (uint8_t *) dataout, total_mem)))
+				rc = EIO;
+		/* This is to prevent copy_to_user at end of the function. */
+		cip->lpfc_outsz = 0;
 		break;
 
 	case LPFC_HBA_SET_EVENT:
Index: latest/drivers/scsi/lpfc/lpfc_mbox.c
===================================================================
--- latest.orig/drivers/scsi/lpfc/lpfc_mbox.c
+++ latest/drivers/scsi/lpfc/lpfc_mbox.c
@@ -1,7 +1,7 @@
 /*******************************************************************
  * This file is part of the Emulex Linux Device Driver for         *
  * Fibre Channel Host Bus Adapters.                                *
- * Copyright (C) 2004-2006 Emulex.  All rights reserved.           *
+ * Copyright (C) 2004-2007 Emulex.  All rights reserved.           *
  * EMULEX and SLI are trademarks of Emulex.                        *
  * www.emulex.com                                                  *
  * Portions Copyright (C) 2004-2005 Christoph Hellwig              *
@@ -212,6 +212,7 @@ lpfc_init_link(struct lpfc_hba * phba,
 			case LINK_SPEED_1G:
 			case LINK_SPEED_2G:
 			case LINK_SPEED_4G:
+			case LINK_SPEED_8G:
 				mb->un.varInitLnk.link_flags |=
 							FLAGS_LINK_SPEED;
 				mb->un.varInitLnk.link_speed = linkspeed;
@@ -295,6 +296,26 @@ lpfc_unreg_did(struct lpfc_hba * phba, u
 	return;
 }
 
+/***********************************************/
+/*                  command to write slim      */
+/***********************************************/
+void
+lpfc_set_slim(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb, uint32_t addr,
+		uint32_t value)
+{
+	MAILBOX_t *mb;
+
+	mb = &pmb->mb;
+	memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
+
+	mb->un.varWords[0] = addr;
+	mb->un.varWords[1] = value;
+
+	mb->mbxCommand = MBX_SET_SLIM;
+	mb->mbxOwner = OWN_HOST;
+	return;
+}
+
 /**********************************************/
 /*  lpfc_read_nv  Issue a READ CONFIG         */
 /*                mailbox command             */
Index: latest/drivers/scsi/lpfc/lpfc_mem.c
===================================================================
--- latest.orig/drivers/scsi/lpfc/lpfc_mem.c
+++ latest/drivers/scsi/lpfc/lpfc_mem.c
@@ -56,6 +56,9 @@ lpfc_mem_alloc(struct lpfc_hba * phba)
 
 	pool->elements = kmalloc(sizeof(struct lpfc_dmabuf) *
 					 LPFC_MBUF_POOL_SIZE, GFP_KERNEL);
+	if (!pool->elements)
+		goto fail_free_lpfc_mbuf_pool;
+
 	pool->max_count = 0;
 	pool->current_count = 0;
 	for ( i = 0; i < LPFC_MBUF_POOL_SIZE; i++) {
@@ -82,10 +85,11 @@ lpfc_mem_alloc(struct lpfc_hba * phba)
  fail_free_mbox_pool:
 	mempool_destroy(phba->mbox_mem_pool);
  fail_free_mbuf_pool:
-	while (--i)
+	while (i--)
 		pci_pool_free(phba->lpfc_mbuf_pool, pool->elements[i].virt,
 						 pool->elements[i].phys);
 	kfree(pool->elements);
+ fail_free_lpfc_mbuf_pool:
 	pci_pool_destroy(phba->lpfc_mbuf_pool);
  fail_free_dma_buf_pool:
 	pci_pool_destroy(phba->lpfc_scsi_dma_buf_pool);
Index: latest/drivers/scsi/lpfc/lpfc_nportdisc.c
===================================================================
--- latest.orig/drivers/scsi/lpfc/lpfc_nportdisc.c
+++ latest/drivers/scsi/lpfc/lpfc_nportdisc.c
@@ -1,7 +1,7 @@
 /*******************************************************************
  * This file is part of the Emulex Linux Device Driver for         *
  * Fibre Channel Host Bus Adapters.                                *
- * Copyright (C) 2004-2006 Emulex.  All rights reserved.           *
+ * Copyright (C) 2004-2007 Emulex.  All rights reserved.           *
  * EMULEX and SLI are trademarks of Emulex.                        *
  * www.emulex.com                                                  *
  * Portions Copyright (C) 2004-2005 Christoph Hellwig              *
@@ -168,8 +168,7 @@ lpfc_check_elscmpl_iocb(struct lpfc_hba 
  * routine effectively results in a "software abort".
  */
 int
-lpfc_els_abort(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp,
-	int send_abts)
+lpfc_els_abort(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp)
 {
 	struct lpfc_sli *psli;
 	struct lpfc_sli_ring *pring;
@@ -215,48 +214,17 @@ lpfc_els_abort(struct lpfc_hba * phba, s
 		spin_unlock_irq(phba->host->host_lock);
 	} while (found);
 
-	/* Everything on txcmplq will be returned by firmware
-	 * with a no rpi / linkdown / abort error.  For ring 0,
-	 * ELS discovery, we want to get rid of it right here.
-	 */
 	/* Next check the txcmplq */
-	do {
-		found = 0;
-		spin_lock_irq(phba->host->host_lock);
-		list_for_each_entry_safe(iocb, next_iocb, &pring->txcmplq,
-					 list) {
-			/* Check to see if iocb matches the nport we are looking
-			   for */
-			if ((lpfc_check_sli_ndlp (phba, pring, iocb, ndlp))) {
-				found = 1;
-				/* It matches, so deque and call compl with an
-				   error */
-				list_del(&iocb->list);
-				pring->txcmplq_cnt--;
-
-				icmd = &iocb->iocb;
-				/* If the driver is completing an ELS
-				 * command early, flush it out of the firmware.
-				 */
-				if (send_abts &&
-				   (icmd->ulpCommand == CMD_ELS_REQUEST64_CR) &&
-				   (icmd->un.elsreq64.bdl.ulpIoTag32)) {
-					lpfc_sli_issue_abort_iotag32(phba,
-							     pring, iocb);
-				}
-				if (iocb->iocb_cmpl) {
-					icmd->ulpStatus = IOSTAT_LOCAL_REJECT;
-					icmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
-					spin_unlock_irq(phba->host->host_lock);
-					(iocb->iocb_cmpl) (phba, iocb, iocb);
-					spin_lock_irq(phba->host->host_lock);
-				} else
-					lpfc_sli_release_iocbq(phba, iocb);
-				break;
-			}
+	spin_lock_irq(phba->host->host_lock);
+	list_for_each_entry_safe(iocb, next_iocb, &pring->txcmplq, list) {
+		/* Check to see if iocb matches the nport we are looking
+		   for */
+		if ((lpfc_check_sli_ndlp (phba, pring, iocb, ndlp))) {
+			icmd = &iocb->iocb;
+			lpfc_sli_issue_abort_iotag(phba, pring, iocb);
 		}
-		spin_unlock_irq(phba->host->host_lock);
-	} while(found);
+	}
+	spin_unlock_irq(phba->host->host_lock);
 
 	/* If we are delaying issuing an ELS command, cancel it */
 	if (ndlp->nlp_flag & NLP_DELAY_TMO)
@@ -404,7 +372,7 @@ lpfc_rcv_plogi(struct lpfc_hba * phba,
 	 */
 	if (ndlp->nlp_state == NLP_STE_PLOGI_ISSUE) {
 		/* software abort outstanding PLOGI */
-		lpfc_els_abort(phba, ndlp, 1);
+		lpfc_els_abort(phba, ndlp);
 	}
 
 	lpfc_els_rsp_acc(phba, ELS_CMD_PLOGI, cmdiocb, ndlp, mbox, 0);
@@ -697,7 +665,7 @@ lpfc_rcv_logo_plogi_issue(struct lpfc_hb
 	cmdiocb = (struct lpfc_iocbq *) arg;
 
 	/* software abort outstanding PLOGI */
-	lpfc_els_abort(phba, ndlp, 1);
+	lpfc_els_abort(phba, ndlp);
 
 	lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_LOGO);
 	return ndlp->nlp_state;
@@ -712,7 +680,7 @@ lpfc_rcv_els_plogi_issue(struct lpfc_hba
 	cmdiocb = (struct lpfc_iocbq *) arg;
 
 	/* software abort outstanding PLOGI */
-	lpfc_els_abort(phba, ndlp, 1);
+	lpfc_els_abort(phba, ndlp);
 
 	if (evt == NLP_EVT_RCV_LOGO) {
 		lpfc_els_rsp_acc(phba, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0);
@@ -855,7 +823,7 @@ lpfc_device_rm_plogi_issue(struct lpfc_h
 	}
 	else {
 		/* software abort outstanding PLOGI */
-		lpfc_els_abort(phba, ndlp, 1);
+		lpfc_els_abort(phba, ndlp);
 
 		lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
 		return NLP_STE_FREED_NODE;
@@ -868,7 +836,7 @@ lpfc_device_recov_plogi_issue(struct lpf
 			    uint32_t evt)
 {
 	/* software abort outstanding PLOGI */
-	lpfc_els_abort(phba, ndlp, 1);
+	lpfc_els_abort(phba, ndlp);
 
 	ndlp->nlp_prev_state = NLP_STE_PLOGI_ISSUE;
 	ndlp->nlp_state = NLP_STE_NPR_NODE;
@@ -888,7 +856,7 @@ lpfc_rcv_plogi_adisc_issue(struct lpfc_h
 	struct lpfc_iocbq *cmdiocb;
 
 	/* software abort outstanding ADISC */
-	lpfc_els_abort(phba, ndlp, 1);
+	lpfc_els_abort(phba, ndlp);
 
 	cmdiocb = (struct lpfc_iocbq *) arg;
 
@@ -926,7 +894,7 @@ lpfc_rcv_logo_adisc_issue(struct lpfc_hb
 	cmdiocb = (struct lpfc_iocbq *) arg;
 
 	/* software abort outstanding ADISC */
-	lpfc_els_abort(phba, ndlp, 0);
+	lpfc_els_abort(phba, ndlp);
 
 	lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_LOGO);
 	return ndlp->nlp_state;
@@ -1016,7 +984,7 @@ lpfc_device_rm_adisc_issue(struct lpfc_h
 	}
 	else {
 		/* software abort outstanding ADISC */
-		lpfc_els_abort(phba, ndlp, 1);
+		lpfc_els_abort(phba, ndlp);
 
 		lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
 		return NLP_STE_FREED_NODE;
@@ -1029,7 +997,7 @@ lpfc_device_recov_adisc_issue(struct lpf
 			    uint32_t evt)
 {
 	/* software abort outstanding ADISC */
-	lpfc_els_abort(phba, ndlp, 1);
+	lpfc_els_abort(phba, ndlp);
 
 	ndlp->nlp_prev_state = NLP_STE_ADISC_ISSUE;
 	ndlp->nlp_state = NLP_STE_NPR_NODE;
@@ -1074,9 +1042,36 @@ lpfc_rcv_logo_reglogin_issue(struct lpfc
 			     uint32_t evt)
 {
 	struct lpfc_iocbq *cmdiocb;
+	LPFC_MBOXQ_t	  *mb;
+	LPFC_MBOXQ_t	  *nextmb;
+	struct lpfc_dmabuf *mp;
 
 	cmdiocb = (struct lpfc_iocbq *) arg;
 
+	/* cleanup any ndlp on mbox q waiting for reglogin cmpl */
+	if ((mb = phba->sli.mbox_active)) {
+		if ((mb->mb.mbxCommand == MBX_REG_LOGIN64) &&
+		   (ndlp == (struct lpfc_nodelist *) mb->context2)) {
+			mb->context2 = NULL;
+			mb->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
+		}
+	}
+
+	spin_lock_irq(phba->host->host_lock);
+	list_for_each_entry_safe(mb, nextmb, &phba->sli.mboxq, list) {
+		if ((mb->mb.mbxCommand == MBX_REG_LOGIN64) &&
+		   (ndlp == (struct lpfc_nodelist *) mb->context2)) {
+			mp = (struct lpfc_dmabuf *) (mb->context1);
+			if (mp) {
+				lpfc_mbuf_free(phba, mp->virt, mp->phys);
+				kfree(mp);
+			}
+			list_del(&mb->list);
+			mempool_free(mb, phba->mbox_mem_pool);
+		}
+	}
+	spin_unlock_irq(phba->host->host_lock);
+
 	lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_LOGO);
 	return ndlp->nlp_state;
 }
@@ -1230,7 +1225,7 @@ lpfc_rcv_logo_prli_issue(struct lpfc_hba
 	cmdiocb = (struct lpfc_iocbq *) arg;
 
 	/* Software abort outstanding PRLI before sending acc */
-	lpfc_els_abort(phba, ndlp, 1);
+	lpfc_els_abort(phba, ndlp);
 
 	lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_LOGO);
 	return ndlp->nlp_state;
@@ -1330,7 +1325,7 @@ lpfc_device_rm_prli_issue(struct lpfc_hb
 	}
 	else {
 		/* software abort outstanding PLOGI */
-		lpfc_els_abort(phba, ndlp, 1);
+		lpfc_els_abort(phba, ndlp);
 
 		lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
 		return NLP_STE_FREED_NODE;
@@ -1359,7 +1354,7 @@ lpfc_device_recov_prli_issue(struct lpfc
 			   struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
 {
 	/* software abort outstanding PRLI */
-	lpfc_els_abort(phba, ndlp, 1);
+	lpfc_els_abort(phba, ndlp);
 
 	ndlp->nlp_prev_state = NLP_STE_PRLI_ISSUE;
 	ndlp->nlp_state = NLP_STE_NPR_NODE;
Index: latest/drivers/scsi/lpfc/lpfc_scsi.c
===================================================================
--- latest.orig/drivers/scsi/lpfc/lpfc_scsi.c
+++ latest/drivers/scsi/lpfc/lpfc_scsi.c
@@ -1,7 +1,7 @@
 /*******************************************************************
  * This file is part of the Emulex Linux Device Driver for         *
  * Fibre Channel Host Bus Adapters.                                *
- * Copyright (C) 2004-2006 Emulex.  All rights reserved.           *
+ * Copyright (C) 2004-2007 Emulex.  All rights reserved.           *
  * EMULEX and SLI are trademarks of Emulex.                        *
  * www.emulex.com                                                  *
  * Portions Copyright (C) 2004-2005 Christoph Hellwig              *
@@ -146,6 +146,10 @@ lpfc_get_scsi_buf(struct lpfc_hba * phba
 
 	spin_lock_irqsave(&phba->scsi_buf_list_lock, iflag);
 	list_remove_head(scsi_buf_list, lpfc_cmd, struct lpfc_scsi_buf, list);
+	if (lpfc_cmd) {
+		lpfc_cmd->seg_cnt = 0;
+		lpfc_cmd->nonsg_phys = 0;
+	}
 	spin_unlock_irqrestore(&phba->scsi_buf_list_lock, iflag);
 	return  lpfc_cmd;
 }
@@ -288,13 +292,13 @@ lpfc_scsi_unprep_dma_buf(struct lpfc_hba
 }
 
 static void
-lpfc_handle_fcp_err(struct lpfc_scsi_buf *lpfc_cmd)
+lpfc_handle_fcp_err(struct lpfc_scsi_buf *lpfc_cmd, struct lpfc_iocbq *rsp_iocb)
 {
 	struct scsi_cmnd *cmnd = lpfc_cmd->pCmd;
 	struct fcp_cmnd *fcpcmd = lpfc_cmd->fcp_cmnd;
 	struct fcp_rsp *fcprsp = lpfc_cmd->fcp_rsp;
 	struct lpfc_hba *phba = lpfc_cmd->scsi_hba;
-	uint32_t fcpi_parm = lpfc_cmd->cur_iocbq.iocb.un.fcpi.fcpi_parm;
+	uint32_t fcpi_parm = rsp_iocb->iocb.un.fcpi.fcpi_parm;
 	uint32_t resp_info = fcprsp->rspStatus2;
 	uint32_t scsi_status = fcprsp->rspStatus3;
 	uint32_t *lp;
@@ -356,6 +360,24 @@ lpfc_handle_fcp_err(struct lpfc_scsi_buf
 				fcpi_parm, cmnd->cmnd[0], cmnd->underflow);
 
 		/*
+		 * If there is an under run check if under run reported by
+		 * storage array is same as the under run reported by HBA.
+		 * If this is not same, there is a dropped frame.
+		 */
+		if ((cmnd->sc_data_direction == DMA_FROM_DEVICE) &&
+			fcpi_parm &&
+			(cmnd->resid != fcpi_parm)) {
+			lpfc_printf_log(phba, KERN_WARNING,
+				LOG_FCP | LOG_FCP_ERROR,
+				"%d:0735 FCP Read Check Error and Underrun "
+				"Data: x%x x%x x%x x%x\n", phba->brd_no,
+				be32_to_cpu(fcpcmd->fcpDl),
+				cmnd->resid,
+				fcpi_parm, cmnd->cmnd[0]);
+			cmnd->resid = cmnd->request_bufflen;
+			host_status = DID_ERROR;
+		}
+		/*
 		 * The cmnd->underflow is the minimum number of bytes that must
 		 * be transfered for this command.  Provided a sense condition
 		 * is not present, make sure the actual amount transferred is at
@@ -435,7 +457,7 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba 
 		switch (lpfc_cmd->status) {
 		case IOSTAT_FCP_RSP_ERROR:
 			/* Call FCP RSP handler to determine result */
-			lpfc_handle_fcp_err(lpfc_cmd);
+			lpfc_handle_fcp_err(lpfc_cmd,pIocbOut);
 			break;
 		case IOSTAT_NPORT_BSY:
 		case IOSTAT_FABRIC_BSY:
@@ -466,10 +488,10 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba 
 
 	result = cmd->result;
 	sdev = cmd->device;
+	lpfc_scsi_unprep_dma_buf(phba, lpfc_cmd);
 	cmd->scsi_done(cmd);
 
 	if (phba->cfg_poll & ENABLE_FCP_RING_POLLING) {
-		lpfc_scsi_unprep_dma_buf(phba, lpfc_cmd);
 		lpfc_release_scsi_buf(phba, lpfc_cmd);
 		return;
 	}
@@ -527,7 +549,6 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba 
 		}
 	}
 
-	lpfc_scsi_unprep_dma_buf(phba, lpfc_cmd);
 	lpfc_release_scsi_buf(phba, lpfc_cmd);
 }
 
@@ -670,6 +691,18 @@ lpfc_scsi_prep_task_mgmt_cmd(struct lpfc
 	return (1);
 }
 
+static void
+lpfc_tskmgmt_def_cmpl(struct lpfc_hba *phba,
+			struct lpfc_iocbq *cmdiocbq,
+			struct lpfc_iocbq *rspiocbq)
+{
+	struct lpfc_scsi_buf *lpfc_cmd =
+		(struct lpfc_scsi_buf *) cmdiocbq->context1;
+	if (lpfc_cmd)
+		lpfc_release_scsi_buf(phba, lpfc_cmd);
+	return;
+}
+
 static int
 lpfc_scsi_tgt_reset(struct lpfc_scsi_buf * lpfc_cmd, struct lpfc_hba * phba,
 		    unsigned  tgt_id, unsigned int lun,
@@ -706,8 +739,9 @@ lpfc_scsi_tgt_reset(struct lpfc_scsi_buf
 				       &phba->sli.ring[phba->sli.fcp_ring],
 				       iocbq, iocbqrsp, lpfc_cmd->timeout);
 	if (ret != IOCB_SUCCESS) {
+		if (ret == IOCB_TIMEDOUT)
+			iocbq->iocb_cmpl = lpfc_tskmgmt_def_cmpl;
 		lpfc_cmd->status = IOSTAT_DRIVER_REJECT;
-		ret = FAILED;
 	} else {
 		ret = SUCCESS;
 		lpfc_cmd->result = iocbqrsp->iocb.un.ulpWord[4];
@@ -984,6 +1018,7 @@ lpfc_reset_lun_handler(struct scsi_cmnd 
 	struct lpfc_nodelist *pnode = rdata->pnode;
 	uint32_t cmd_result = 0, cmd_status = 0;
 	int ret = FAILED;
+	int iocb_status = IOCB_SUCCESS;
 	int cnt, loopcnt;
 
 	lpfc_block_error_handler(cmnd);
@@ -995,7 +1030,7 @@ lpfc_reset_lun_handler(struct scsi_cmnd 
 	 */
 	while ( 1 ) {
 		if (!pnode)
-			return FAILED;
+			goto out;
 
 		if (pnode->nlp_state != NLP_STE_MAPPED_NODE) {
 			spin_unlock_irq(phba->host->host_lock);
@@ -1013,7 +1048,7 @@ lpfc_reset_lun_handler(struct scsi_cmnd 
 			}
 			pnode = rdata->pnode;
 			if (!pnode)
-				return FAILED;
+				goto out;
 		}
 		if (pnode->nlp_state == NLP_STE_MAPPED_NODE)
 			break;
@@ -1044,12 +1079,17 @@ lpfc_reset_lun_handler(struct scsi_cmnd 
 			"Data: x%x x%x\n", phba->brd_no, cmnd->device->id,
 			cmnd->device->lun, pnode->nlp_rpi, pnode->nlp_flag);
 
-	ret = lpfc_sli_issue_iocb_wait(phba,
+	iocb_status = lpfc_sli_issue_iocb_wait(phba,
 				       &phba->sli.ring[phba->sli.fcp_ring],
 				       iocbq, iocbqrsp, lpfc_cmd->timeout);
-	if (ret == IOCB_SUCCESS)
-		ret = SUCCESS;
 
+	if (iocb_status == IOCB_TIMEDOUT)
+		iocbq->iocb_cmpl = lpfc_tskmgmt_def_cmpl;
+
+	if (iocb_status == IOCB_SUCCESS)
+		ret = SUCCESS;
+	else
+		ret = iocb_status;
 
 	cmd_result = iocbqrsp->iocb.un.ulpWord[4];
 	cmd_status = iocbqrsp->iocb.ulpStatus;
@@ -1093,8 +1133,9 @@ lpfc_reset_lun_handler(struct scsi_cmnd 
 	}
 
 out_free_scsi_buf:
-	lpfc_release_scsi_buf(phba, lpfc_cmd);
-
+	if (iocb_status != IOCB_TIMEDOUT) {
+		lpfc_release_scsi_buf(phba, lpfc_cmd);
+	}
 	lpfc_printf_log(phba, KERN_ERR, LOG_FCP,
 			"%d:0713 SCSI layer issued LUN reset (%d, %d) "
 			"Data: x%x x%x x%x\n",
@@ -1152,13 +1193,17 @@ lpfc_reset_bus_handler(struct scsi_cmnd 
 				"%d:0700 Bus Reset on target %d failed\n",
 				phba->brd_no, i);
 			err_count++;
+			break;
 		}
 	}
 
+	if (ret != IOCB_TIMEDOUT)
+		lpfc_release_scsi_buf(phba, lpfc_cmd);
+
 	if (err_count == 0)
 		ret = SUCCESS;
-
-	lpfc_release_scsi_buf(phba, lpfc_cmd);
+	else
+		ret = FAILED;
 
 	/*
 	 * All outstanding txcmplq I/Os should have been aborted by
Index: latest/drivers/scsi/lpfc/lpfc_sli.c
===================================================================
--- latest.orig/drivers/scsi/lpfc/lpfc_sli.c
+++ latest/drivers/scsi/lpfc/lpfc_sli.c
@@ -1,7 +1,7 @@
 /*******************************************************************
  * This file is part of the Emulex Linux Device Driver for         *
  * Fibre Channel Host Bus Adapters.                                *
- * Copyright (C) 2004-2006 Emulex.  All rights reserved.           *
+ * Copyright (C) 2004-2007 Emulex.  All rights reserved.           *
  * EMULEX and SLI are trademarks of Emulex.                        *
  * www.emulex.com                                                  *
  * Portions Copyright (C) 2004-2005 Christoph Hellwig              *
@@ -528,6 +528,7 @@ lpfc_sli_wake_mbox_wait(struct lpfc_hba 
 	 * If pdone_q is empty, the driver thread gave up waiting and
 	 * continued running.
 	 */
+	pmboxq->mbox_flag |= LPFC_MBX_WAKE;
 	pdone_q = (wait_queue_head_t *) pmboxq->context1;
 	if (pdone_q)
 		wake_up_interruptible(pdone_q);
@@ -538,11 +539,32 @@ void
 lpfc_sli_def_mbox_cmpl(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
 {
 	struct lpfc_dmabuf *mp;
+	uint16_t rpi;
+	int rc;
+
 	mp = (struct lpfc_dmabuf *) (pmb->context1);
+
 	if (mp) {
 		lpfc_mbuf_free(phba, mp->virt, mp->phys);
 		kfree(mp);
 	}
+
+	/*
+	 * If a REG_LOGIN succeeded  after node is destroyed or node
+	 * is in re-discovery driver need to cleanup the RPI.
+	 */
+	if (!(phba->fc_flag & FC_UNLOADING) &&
+		(pmb->mb.mbxCommand == MBX_REG_LOGIN64) &&
+		(!pmb->mb.mbxStatus)) {
+
+		rpi = pmb->mb.un.varWords[0];
+		lpfc_unreg_login(phba, rpi, pmb);
+		pmb->mbox_cmpl=lpfc_sli_def_mbox_cmpl;
+		rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT);
+		if (rc != MBX_NOT_FINISHED)
+			return;
+	}
+
 	mempool_free( pmb, phba->mbox_mem_pool);
 	return;
 }
@@ -833,6 +855,14 @@ lpfc_sli_process_sol_iocb(struct lpfc_hb
 			 * All other are passed to the completion callback.
 			 */
 			if (pring->ringno == LPFC_ELS_RING) {
+				if (cmdiocbp->iocb_flag & LPFC_DRIVER_ABORTED) {
+					cmdiocbp->iocb_flag &=
+						~LPFC_DRIVER_ABORTED;
+					saveq->iocb.ulpStatus =
+						IOSTAT_LOCAL_REJECT;
+					saveq->iocb.un.ulpWord[4] =
+						IOERR_SLI_ABORTED;
+				}
 				spin_unlock_irqrestore(phba->host->host_lock,
 						       iflag);
 				(cmdiocbp->iocb_cmpl) (phba, cmdiocbp, saveq);
@@ -1588,6 +1618,7 @@ void lpfc_reset_barrier(struct lpfc_hba 
 	hc_copy = readl(phba->HCregaddr);
 	writel((hc_copy & ~HC_ERINT_ENA), phba->HCregaddr);
 	readl(phba->HCregaddr); /* flush */
+	phba->fc_flag |= FC_IGNORE_ERATT;
 
 	if (readl(phba->HAregaddr) & HA_ERATT) {
 		/* Clear Chip error bit */
@@ -1630,6 +1661,7 @@ clear_errat:
 	}
 
 restore_hc:
+	phba->fc_flag &= ~FC_IGNORE_ERATT;
 	writel(hc_copy, phba->HCregaddr);
 	readl(phba->HCregaddr); /* flush */
 }
@@ -1665,6 +1697,7 @@ lpfc_sli_brdkill(struct lpfc_hba * phba)
 	status &= ~HC_ERINT_ENA;
 	writel(status, phba->HCregaddr);
 	readl(phba->HCregaddr); /* flush */
+	phba->fc_flag |= FC_IGNORE_ERATT;
 	spin_unlock_irq(phba->host->host_lock);
 
 	lpfc_kill_board(phba, pmb);
@@ -1674,6 +1707,9 @@ lpfc_sli_brdkill(struct lpfc_hba * phba)
 	if (retval != MBX_SUCCESS) {
 		if (retval != MBX_BUSY)
 			mempool_free(pmb, phba->mbox_mem_pool);
+		spin_lock_irq(phba->host->host_lock);
+		phba->fc_flag &= ~FC_IGNORE_ERATT;
+		spin_unlock_irq(phba->host->host_lock);
 		return 1;
 	}
 
@@ -1700,6 +1736,7 @@ lpfc_sli_brdkill(struct lpfc_hba * phba)
 	}
 	spin_lock_irq(phba->host->host_lock);
 	psli->sli_flag &= ~LPFC_SLI_MBOX_ACTIVE;
+	phba->fc_flag &= ~FC_IGNORE_ERATT;
 	spin_unlock_irq(phba->host->host_lock);
 
 	psli->mbox_active = NULL;
@@ -1966,6 +2003,29 @@ lpfc_sli_hba_setup(struct lpfc_hba * phb
 	if (!done)
 		goto lpfc_sli_hba_setup_error;
 
+	if (phba->pci_max_read) {
+		lpfc_set_slim(phba, pmb, SLIM_VAR_MAX_DMA_LENGTH,
+			SLIM_VAL_MAX_DMA_1024);
+		if (lpfc_sli_issue_mbox(phba, pmb, MBX_POLL) != MBX_SUCCESS)
+			if (pmb->mb.mbxStatus != MBXERR_UNKNOWN_CMD) {
+				lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+					"%d:0443 Adapter failed to set maximum"
+					" DMA length mbxStatus x%x \n",
+					phba->brd_no, pmb->mb.mbxStatus);
+			} else {
+				lpfc_printf_log(phba, KERN_WARNING, LOG_INIT,
+					"%d:0444 Adapter does not support "
+					"setting maximum DMA length mbxStatus "
+					"x%x \n", phba->brd_no,
+					pmb->mb.mbxStatus);
+			}
+		else
+				lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
+					"%d:0445 Adapter set maximum"
+					" DMA length to 1024 bytes.\n",
+					phba->brd_no);
+	}
+
 	rc = lpfc_sli_ring_map(phba, pmb);
 
 	if (rc)
@@ -2316,9 +2376,7 @@ lpfc_sli_issue_mbox(struct lpfc_hba * ph
 			spin_unlock_irqrestore(phba->host->host_lock,
 					       drvr_flag);
 
-			/* Can be in interrupt context, do not sleep */
-			/* (or might be called with interrupts disabled) */
-			mdelay(1);
+			msleep(1);
 
 			spin_lock_irqsave(phba->host->host_lock, drvr_flag);
 
@@ -2760,85 +2818,81 @@ lpfc_sli_ringpostbuf_get(struct lpfc_hba
 }
 
 static void
-lpfc_sli_abort_elsreq_cmpl(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
-			   struct lpfc_iocbq * rspiocb)
+lpfc_sli_abort_els_cmpl(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
+			struct lpfc_iocbq * rspiocb)
 {
-	struct lpfc_dmabuf *buf_ptr, *buf_ptr1;
-	/* Free the resources associated with the ELS_REQUEST64 IOCB the driver
-	 * just aborted.
-	 * In this case, context2  = cmd,  context2->next = rsp, context3 = bpl
-	 */
-	if (cmdiocb->context2) {
-		buf_ptr1 = (struct lpfc_dmabuf *) cmdiocb->context2;
-
-		/* Free the response IOCB before completing the abort
-		   command.  */
-		buf_ptr = NULL;
-		list_remove_head((&buf_ptr1->list), buf_ptr,
-				 struct lpfc_dmabuf, list);
-		if (buf_ptr) {
-			lpfc_mbuf_free(phba, buf_ptr->virt, buf_ptr->phys);
-			kfree(buf_ptr);
-		}
-		lpfc_mbuf_free(phba, buf_ptr1->virt, buf_ptr1->phys);
-		kfree(buf_ptr1);
-	}
-
-	if (cmdiocb->context3) {
-		buf_ptr = (struct lpfc_dmabuf *) cmdiocb->context3;
-		lpfc_mbuf_free(phba, buf_ptr->virt, buf_ptr->phys);
-		kfree(buf_ptr);
-	}
-
+	spin_lock_irq(phba->host->host_lock);
 	lpfc_sli_release_iocbq(phba, cmdiocb);
+	spin_unlock_irq(phba->host->host_lock);
 	return;
 }
 
 int
-lpfc_sli_issue_abort_iotag32(struct lpfc_hba * phba,
-			     struct lpfc_sli_ring * pring,
-			     struct lpfc_iocbq * cmdiocb)
+lpfc_sli_issue_abort_iotag(struct lpfc_hba * phba,
+			   struct lpfc_sli_ring * pring,
+			   struct lpfc_iocbq * cmdiocb)
 {
 	struct lpfc_iocbq *abtsiocbp;
 	IOCB_t *icmd = NULL;
 	IOCB_t *iabt = NULL;
+	int retval = IOCB_ERROR;
+
+	/* There are certain command types we don't want
+	 * to abort.
+	 */
+	icmd = &cmdiocb->iocb;
+	if ((icmd->ulpCommand == CMD_ABORT_XRI_CN) ||
+	    (icmd->ulpCommand == CMD_CLOSE_XRI_CN))
+		return 0;
+
+	/* If we're unloading, interrupts are disabled so we
+	 * need to cleanup the iocb here.
+	 */
+	if (phba->fc_flag & FC_UNLOADING)
+		goto abort_iotag_exit;
 
 	/* issue ABTS for this IOCB based on iotag */
 	abtsiocbp = lpfc_sli_get_iocbq(phba);
 	if (abtsiocbp == NULL)
 		return 0;
 
+	/* This signals the response to set the correct status
+	 * before calling the completion handler.
+	 */
+	cmdiocb->iocb_flag |= LPFC_DRIVER_ABORTED;
+
 	iabt = &abtsiocbp->iocb;
-	icmd = &cmdiocb->iocb;
-	switch (icmd->ulpCommand) {
-	case CMD_ELS_REQUEST64_CR:
-		/* Even though we abort the ELS command, the firmware may access
-		 * the BPL or other resources before it processes our
-		 * ABORT_MXRI64. Thus we must delay reusing the cmdiocb
-		 * resources till the actual abort request completes.
-		 */
-		abtsiocbp->context1 = (void *)((unsigned long)icmd->ulpCommand);
-		abtsiocbp->context2 = cmdiocb->context2;
-		abtsiocbp->context3 = cmdiocb->context3;
-		cmdiocb->context2 = NULL;
-		cmdiocb->context3 = NULL;
-		abtsiocbp->iocb_cmpl = lpfc_sli_abort_elsreq_cmpl;
-		break;
-	default:
-		lpfc_sli_release_iocbq(phba, abtsiocbp);
-		return 0;
-	}
+	iabt->un.acxri.abortType = ABORT_TYPE_ABTS;
+	iabt->un.acxri.abortContextTag = icmd->ulpContext;
+	iabt->un.acxri.abortIoTag = icmd->ulpIoTag;
+	iabt->ulpLe = 1;
+	iabt->ulpClass = icmd->ulpClass;
 
-	iabt->un.amxri.abortType = ABORT_TYPE_ABTS;
-	iabt->un.amxri.iotag32 = icmd->un.elsreq64.bdl.ulpIoTag32;
+	if (phba->hba_state >= LPFC_LINK_UP)
+		iabt->ulpCommand = CMD_ABORT_XRI_CN;
+	else
+		iabt->ulpCommand = CMD_CLOSE_XRI_CN;
 
-	iabt->ulpLe = 1;
-	iabt->ulpClass = CLASS3;
-	iabt->ulpCommand = CMD_ABORT_MXRI64_CN;
+	abtsiocbp->iocb_cmpl = lpfc_sli_abort_els_cmpl;
+	retval = lpfc_sli_issue_iocb(phba, pring, abtsiocbp, 0);
 
-	if (lpfc_sli_issue_iocb(phba, pring, abtsiocbp, 0) == IOCB_ERROR) {
-		lpfc_sli_release_iocbq(phba, abtsiocbp);
-		return 0;
+abort_iotag_exit:
+
+	/* If we could not issue an abort dequeue the iocb and handle
+	 * the completion here.
+	 */
+	if (retval == IOCB_ERROR) {
+		list_del(&cmdiocb->list);
+		pring->txcmplq_cnt--;
+
+		if (cmdiocb->iocb_cmpl) {
+			icmd->ulpStatus = IOSTAT_LOCAL_REJECT;
+			icmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
+			spin_unlock_irq(phba->host->host_lock);
+			(cmdiocb->iocb_cmpl) (phba, cmdiocb, cmdiocb);
+			spin_lock_irq(phba->host->host_lock);
+		} else
+			lpfc_sli_release_iocbq(phba, cmdiocb);
 	}
 
 	return 1;
@@ -3035,22 +3089,22 @@ lpfc_sli_issue_iocb_wait(struct lpfc_hba
 				timeout_req);
 		spin_lock_irq(phba->host->host_lock);
 
-		if (timeleft == 0) {
+		if (piocb->iocb_flag & LPFC_IO_WAKE) {
+			lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
+					"%d:0331 IOCB wake signaled\n",
+					phba->brd_no);
+		} else if (timeleft == 0) {
 			lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
 					"%d:0338 IOCB wait timeout error - no "
 					"wake response Data x%x\n",
 					phba->brd_no, timeout);
 			retval = IOCB_TIMEDOUT;
-		} else if (!(piocb->iocb_flag & LPFC_IO_WAKE)) {
+		} else {
 			lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
 					"%d:0330 IOCB wake NOT set, "
 					"Data x%x x%lx\n", phba->brd_no,
 					timeout, (timeleft / jiffies));
 			retval = IOCB_TIMEDOUT;
-		} else {
-			lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
-					"%d:0331 IOCB wake signaled\n",
-					phba->brd_no);
 		}
 	} else {
 		lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
@@ -3079,8 +3133,6 @@ lpfc_sli_issue_mbox_wait(struct lpfc_hba
 			 uint32_t timeout)
 {
 	DECLARE_WAIT_QUEUE_HEAD_ONSTACK(done_q);
-	DECLARE_WAITQUEUE(wq_entry, current);
-	uint32_t timeleft = 0;
 	int retval;
 
 	/* The caller must leave context1 empty. */
@@ -3093,27 +3145,25 @@ lpfc_sli_issue_mbox_wait(struct lpfc_hba
 	/* setup context field to pass wait_queue pointer to wake function  */
 	pmboxq->context1 = &done_q;
 
-	/* start to sleep before we wait, to avoid races */
-	set_current_state(TASK_INTERRUPTIBLE);
-	add_wait_queue(&done_q, &wq_entry);
-
 	/* now issue the command */
 	retval = lpfc_sli_issue_mbox(phba, pmboxq, MBX_NOWAIT);
 
 	if (retval == MBX_BUSY || retval == MBX_SUCCESS) {
-		timeleft = schedule_timeout(timeout * HZ);
+		wait_event_interruptible_timeout(done_q,
+				pmboxq->mbox_flag & LPFC_MBX_WAKE,
+				timeout * HZ);
+
 		pmboxq->context1 = NULL;
-		/* if schedule_timeout returns 0, we timed out and were not
-		   woken up */
-		if ((timeleft == 0) || signal_pending(current))
-			retval = MBX_TIMEOUT;
-		else
+		/*
+		 * if LPFC_MBX_WAKE flag is set the mailbox is completed
+		 * else do not free the resources.
+		 */
+		if (pmboxq->mbox_flag & LPFC_MBX_WAKE)
 			retval = MBX_SUCCESS;
+		else
+			retval = MBX_TIMEOUT;
 	}
 
-
-	set_current_state(TASK_RUNNING);
-	remove_wait_queue(&done_q, &wq_entry);
 	return retval;
 }
 
@@ -3172,6 +3222,11 @@ lpfc_intr_handler(int irq, void *dev_id,
 	 */
 	spin_lock(phba->host->host_lock);
 	ha_copy = readl(phba->HAregaddr);
+	/* If somebody is waiting to handle an eratt don't process it
+	 * here.  The brdkill function will do this.
+	 */
+	if (phba->fc_flag & FC_IGNORE_ERATT)
+		ha_copy &= ~HA_ERATT;
 	writel((ha_copy & ~(HA_LATT | HA_ERATT)), phba->HAregaddr);
 	readl(phba->HAregaddr); /* flush */
 	spin_unlock(phba->host->host_lock);
Index: latest/drivers/scsi/lpfc/lpfc_sli.h
===================================================================
--- latest.orig/drivers/scsi/lpfc/lpfc_sli.h
+++ latest/drivers/scsi/lpfc/lpfc_sli.h
@@ -1,7 +1,7 @@
 /*******************************************************************
  * This file is part of the Emulex Linux Device Driver for         *
  * Fibre Channel Host Bus Adapters.                                *
- * Copyright (C) 2004-2006 Emulex.  All rights reserved.           *
+ * Copyright (C) 2004-2007 Emulex.  All rights reserved.           *
  * EMULEX and SLI are trademarks of Emulex.                        *
  * www.emulex.com                                                  *
  *                                                                 *
@@ -39,9 +39,10 @@ struct lpfc_iocbq {
 	IOCB_t iocb;		/* IOCB cmd */
 	uint8_t retry;		/* retry counter for IOCB cmd - if needed */
 	uint8_t iocb_flag;
-#define LPFC_IO_LIBDFC	1	/* libdfc iocb */
-#define LPFC_IO_WAKE	2	/* High Priority Queue signal flag */
-#define LPFC_IO_FCP	4	/* FCP command -- iocbq in scsi_buf */
+#define LPFC_IO_LIBDFC		1	/* libdfc iocb */
+#define LPFC_IO_WAKE		2	/* High Priority Queue signal flag */
+#define LPFC_IO_FCP		4	/* FCP command -- iocbq in scsi_buf */
+#define LPFC_DRIVER_ABORTED	8	/* driver aborted this request */
 
 	uint8_t abort_count;
 	uint8_t rsvd2;
@@ -67,6 +68,8 @@ struct lpfc_iocbq {
 #define IOCB_ERROR          2
 #define IOCB_TIMEDOUT       3
 
+#define LPFC_MBX_WAKE	1
+
 typedef struct lpfcMboxq {
 	/* MBOXQs are used in single linked lists */
 	struct list_head list;	/* ptr to next mailbox command */
@@ -75,6 +78,7 @@ typedef struct lpfcMboxq {
 	void *context2;		/* caller context information */
 
 	void (*mbox_cmpl) (struct lpfc_hba *, struct lpfcMboxq *);
+	uint8_t mbox_flag;
 
 } LPFC_MBOXQ_t;
 
Index: latest/drivers/scsi/lpfc/lpfc_version.h
===================================================================
--- latest.orig/drivers/scsi/lpfc/lpfc_version.h
+++ latest/drivers/scsi/lpfc/lpfc_version.h
@@ -1,7 +1,7 @@
 /*******************************************************************
  * This file is part of the Emulex Linux Device Driver for         *
  * Fibre Channel Host Bus Adapters.                                *
- * Copyright (C) 2004-2006 Emulex.  All rights reserved.           *
+ * Copyright (C) 2004-2007 Emulex.  All rights reserved.           *
  * EMULEX and SLI are trademarks of Emulex.                        *
  * www.emulex.com                                                  *
  *                                                                 *
@@ -18,12 +18,12 @@
  * included with this package.                                     *
  *******************************************************************/
 
-#define LPFC_DRIVER_VERSION "8.1.10.3"
+#define LPFC_DRIVER_VERSION "8.1.10.9"
 
 #define LPFC_DRIVER_NAME "lpfc"
 
 #define LPFC_MODULE_DESC "Emulex LightPulse Fibre Channel SCSI driver " \
 		LPFC_DRIVER_VERSION
-#define LPFC_COPYRIGHT "Copyright(c) 2004-2006 Emulex.  All rights reserved."
+#define LPFC_COPYRIGHT "Copyright(c) 2004-2007 Emulex.  All rights reserved."
 
 #define DFC_API_VERSION "0.0.0"