Sophie

Sophie

distrib > CentOS > 5 > x86_64 > by-pkgid > ea32411352494358b8d75a78402a4713 > files > 4537

kernel-2.6.18-238.19.1.el5.centos.plus.src.rpm

From: Rob Evers <revers@redhat.com>
Date: Wed, 21 Jul 2010 12:38:03 -0400
Subject: [scsi] megaraid_sas: update driver to version 4.27
Message-id: <20100721123404.30383.45339.sendpatchset@localhost.localdomain>
Patchwork-id: 26995
O-Subject: [RHEL5.6 PATCH 1/2] megaraid_sas: update driver to version 4.27
Bugzilla: 564249
RH-Acked-by: Tomas Henzl <thenzl@redhat.com>

https://bugzilla.redhat.com/show_bug.cgi?id=564249

Description provided by Bo Yang, LSI Megaraid maintainer.
1. Add the CTIO support to the driver
2. Add the Online controller reset support to the driver
3. driver will auto update the devices add/delete to the system without
   megaraid application installed.

Signed-off-by: Jarod Wilson <jarod@redhat.com>

diff --git a/Documentation/scsi/ChangeLog.megaraid_sas b/Documentation/scsi/ChangeLog.megaraid_sas
index a71b07b..7acc121 100644
--- a/Documentation/scsi/ChangeLog.megaraid_sas
+++ b/Documentation/scsi/ChangeLog.megaraid_sas
@@ -1,3 +1,56 @@
+1 Release Date    : Thur.  Feb. 18, 2010 09:12:45 PST 2009 -
+			(emaild-id:megaraidlinux@lsi.com)
+			Bo Yang
+
+2 Current Version : 00.00.04.27
+3 Older Version   : 00.00.04.17.1
+
+1.	Add the CTIO support to the driver.
+
+2.	Add the ontime controller reset to the driver.
+
+3.	megaraid application will look at the device support flag to decide if application will
+	do the ontime device add/delete.
+
+4.	Fixed some issiues: OS hang during MSM create device.
+
+1 Release Date    : Thur.  Oct 29, 2009 09:12:45 PST 2009 -
+			(emaild-id:megaraidlinux@lsi.com)
+			Bo Yang
+
+2 Current Version : 00.00.04.17.1
+3 Older Version   : 00.00.04.12
+
+1.	Add the pad_0 in mfi frame structure to 0 to fix the
+	context value larger than 32bit value issue.
+
+2.	Add the logic drive list to the driver.  Driver will
+	keep the logic drive list internal after driver load.
+
+3.	driver fixed the device update issue after get the AEN
+	PD delete/ADD, LD add/delete from FW.
+
+1 Release Date    : Tues.  July 28, 2009 10:12:45 PST 2009 -
+			(emaild-id:megaraidlinux@lsi.com)
+			Bo Yang
+
+2 Current Version : 00.00.04.12
+3 Older Version   : 00.00.04.10
+
+1.	Change the AEN sys PD update from scsi_scan to
+	scsi_add_device and scsi_remove_device.
+2.	Takeoff the debug print-out in aen_polling routine.
+
+1 Release Date    : Thur.  July 02, 2009 10:12:45 PST 2009 -
+			(emaild-id:megaraidlinux@lsi.com)
+			Bo Yang
+
+2 Current Version : 00.00.04.10
+3 Older Version   : 00.00.04.08
+
+1.	Add the 3 mins timeout during the controller initialize.
+2.	Add the fix for 64bit sense date errors.
+
 1 Release Date    : Tues. May 05, 2009 10:12:45 PST 2009 -
                         (emaild-id:megaraidlinux@lsi.com)
                         Bo Yang
diff --git a/drivers/scsi/megaraid/megaraid_sas.c b/drivers/scsi/megaraid/megaraid_sas.c
index 8965842..391d68d 100644
--- a/drivers/scsi/megaraid/megaraid_sas.c
+++ b/drivers/scsi/megaraid/megaraid_sas.c
@@ -1,27 +1,24 @@
 /*
  *
- *		Linux MegaRAID driver for SAS based RAID controllers
+ *Linux MegaRAID driver for SAS based RAID controllers
  *
- * Copyright (c) 2003-2005  LSI Corporation.
+ * Copyright (c) 2009  LSI Corporation.
  *
- *	   This program is free software; you can redistribute it and/or
- *	   modify it under the terms of the GNU General Public License
- *	   as published by the Free Software Foundation; either version
- *	   2 of the License, or (at your option) any later version.
+ *This program is free software; you can redistribute it and/or
+ *modify it under the terms of the GNU General Public License
+ *as published by the Free Software Foundation; either version 2
+ *of the License, or (at your option) any later version.
  *
- * FILE		: megaraid_sas.c
- * Version	: v00.00.04.17-RH1
+ *This program is distributed in the hope that it will be useful,
+ *but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *GNU General Public License for more details.
  *
- * Authors:
- *	(email-id : megaraidlinux@lsi.com)
- * 	Sreenivas Bagalkote
- * 	Sumant Patro
- *	Bo Yang
- *
- * List of supported controllers
- *
- * OEM	Product Name			VID	DID	SSVID	SSID
- * ---	------------			---	---	----	----
+ *You should have received a copy of the GNU General Public License
+ *along with this program; if not, write to the Free Software
+ *Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ * 
+ * Send feedback to <Bo.Yang@lsi.com>
  */
 
 #include <linux/kernel.h>
@@ -33,6 +30,7 @@
 #include <linux/spinlock.h>
 #include <linux/interrupt.h>
 #include <linux/delay.h>
+#include <linux/smp_lock.h>
 #include <linux/uio.h>
 #include <asm/uaccess.h>
 #include <linux/fs.h>
@@ -40,7 +38,6 @@
 #include <linux/blkdev.h>
 #include <linux/mutex.h>
 #include <linux/poll.h>
-#include <linux/smp_lock.h>
 
 #include <scsi/scsi.h>
 #include <scsi/scsi_cmnd.h>
@@ -49,10 +46,6 @@
 #include "megaraid_sas.h"
 
 /*
- * Modules parameters
- */
-
-/*
  * poll_mode_io:1- schedule complete completion from q cmd
  */
 static unsigned int poll_mode_io;
@@ -74,6 +67,8 @@ static struct pci_device_id megasas_pci_table[] = {
 	/* xscale IOP */
 	{PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1078R)},
 	/* ppc IOP */
+	{PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1078DE)},
+	/* ppc IOP */
 	{PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1078GEN2)},
 	/* gen2*/
 	{PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS0079GEN2)},
@@ -82,8 +77,6 @@ static struct pci_device_id megasas_pci_table[] = {
 	/* skinny*/
 	{PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS0071SKINNY)},
 	/* skinny*/
-	{PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1078DE)},
-	/* ppc IOP */
 	{PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_VERDE_ZCR)},
 	/* xscale IOP, vega */
 	{PCI_DEVICE(PCI_VENDOR_ID_DELL, PCI_DEVICE_ID_DELL_PERC5)},
@@ -99,13 +92,12 @@ static struct fasync_struct *megasas_async_queue;
 static DEFINE_MUTEX(megasas_async_queue_mutex);
 static DEFINE_MUTEX(megasas_poll_wait_mutex);
 
-
 static int megasas_poll_wait_aen;
-static DECLARE_WAIT_QUEUE_HEAD (megasas_poll_wait);
-extern void
-poll_wait(struct file *filp, wait_queue_head_t *q, poll_table *token);
-
+static DECLARE_WAIT_QUEUE_HEAD ( megasas_poll_wait );
 static u32 support_poll_for_event;
+static u32 support_device_change;
+
+/* define lock for aen poll */
 spinlock_t poll_aen_lock;
 
 static u32 megasas_dbg_lvl;
@@ -113,6 +105,11 @@ static u32 megasas_dbg_lvl;
 static void
 megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd,
 		     u8 alt_status);
+static int megasas_transition_to_ready(struct megasas_instance* instance);
+static int megasas_get_pd_list(struct megasas_instance *instance);
+static int megasas_issue_init_mfi(struct megasas_instance *instance);
+static int megasas_register_aen(struct megasas_instance *instance, u32 seq_num, u32 class_locale_word);
+
 /**
  * megasas_get_cmd -	Get a command from the free pool
  * @instance:		Adapter soft state
@@ -170,7 +167,7 @@ megasas_return_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd)
 static inline void
 megasas_enable_intr_xscale(struct megasas_register_set __iomem * regs)
 {
-	writel(1, &(regs)->outbound_intr_mask);
+	writel(0, &(regs)->outbound_intr_mask);
 
 	/* Dummy readl to force pci flush */
 	readl(&regs->outbound_intr_mask);
@@ -206,24 +203,27 @@ static int
 megasas_clear_intr_xscale(struct megasas_register_set __iomem * regs)
 {
 	u32 status;
+	u32 mfiStatus = 0;
 	/*
 	 * Check if it is our interrupt
 	 */
 	status = readl(&regs->outbound_intr_status);
 
-	if (!(status & MFI_OB_INTR_STATUS_MASK)) {
-		return 1;
-	}
+	if (status & MFI_OB_INTR_STATUS_MASK)
+		mfiStatus = MFI_INTR_FLAG_REPLY_MESSAGE;
+	if (status & MFI_XSCALE_OMR0_CHANGE_INTERRUPT)
+		mfiStatus |= MFI_INTR_FLAG_FIRMWARE_STATE_CHANGE;
 
 	/*
 	 * Clear the interrupt by writing back the same value
 	 */
-	writel(status, &regs->outbound_intr_status);
+	if (mfiStatus)
+		writel(status, &regs->outbound_intr_status);
 
 	/* Dummy readl to force pci flush */
 	readl(&regs->outbound_intr_status);
-
-	return 0;
+	
+	return mfiStatus;
 }
 
 /**
@@ -233,10 +233,69 @@ megasas_clear_intr_xscale(struct megasas_register_set __iomem * regs)
  * @regs :			MFI register set
  */
 static inline void 
-megasas_fire_cmd_xscale(struct megasas_instance *instance, dma_addr_t frame_phys_addr,u32 frame_count, struct megasas_register_set __iomem *regs)
+megasas_fire_cmd_xscale(struct megasas_instance *instance,
+		dma_addr_t frame_phys_addr,
+		u32 frame_count,
+		struct megasas_register_set __iomem *regs)
 {
+	unsigned long flags;
+	spin_lock_irqsave(&instance->hba_lock, flags);
 	writel((frame_phys_addr >> 3)|(frame_count),
 	       &(regs)->inbound_queue_port);
+	spin_unlock_irqrestore(&instance->hba_lock, flags);
+}
+
+/**
+ * megasas_adp_reset_xscale -	For controller reset
+ * @regs:				MFI register set
+ */
+static int 
+megasas_adp_reset_xscale(struct megasas_instance *instance, struct megasas_register_set __iomem * regs)
+{
+        u32 i;
+	u32 pcidata;
+	writel(MFI_ADP_RESET, &regs->inbound_doorbell);
+
+	for (i=0; i < 3; i++)
+		msleep(1000); /* sleep for 3 secs */
+	pcidata =0;
+	pci_read_config_dword(instance->pdev, MFI_1068_PCSR_OFFSET, &pcidata);
+	printk("pcidata = %x\n", pcidata);
+	if (pcidata & 0x2) {
+		printk("mfi 1068 offset read=%x\n", pcidata);
+		pcidata &= ~0x2;
+		pci_write_config_dword(instance->pdev, MFI_1068_PCSR_OFFSET, pcidata);
+
+		for (i=0; i<2; i++)
+			msleep(1000); /* need to wait 2 secs again */
+
+		pcidata =0;
+		pci_read_config_dword(instance->pdev, MFI_1068_FW_HANDSHAKE_OFFSET, &pcidata);
+		printk("mfi 1068 offset handshake read=%x\n", pcidata);
+		if ((pcidata & 0xffff0000) == MFI_1068_FW_READY) {
+			printk("mfi 1068 offset handshake=%x\n", pcidata);
+			pcidata = 0;
+			pci_write_config_dword(instance->pdev, MFI_1068_FW_HANDSHAKE_OFFSET, pcidata);
+		}
+	}
+	return 0;
+}
+
+/**
+ * megasas_check_reset_xscale -	For controller reset check
+ * @regs:				MFI register set
+ */
+static int 
+megasas_check_reset_xscale(struct megasas_instance *instance, struct megasas_register_set __iomem * regs)
+{
+	u32 consumer;
+	consumer = *instance->consumer;
+
+	if ((instance->adprecovery != MEGASAS_HBA_OPERATIONAL) && (*instance->consumer == MEGASAS_ADPRESET_INPROG_SIGN)) {
+		return 1;
+	}
+
+	return 0;
 }
 
 static struct megasas_instance_template megasas_instance_template_xscale = {
@@ -246,6 +305,8 @@ static struct megasas_instance_template megasas_instance_template_xscale = {
 	.disable_intr = megasas_disable_intr_xscale,
 	.clear_intr = megasas_clear_intr_xscale,
 	.read_fw_status_reg = megasas_read_fw_status_reg_xscale,
+	.adp_reset = megasas_adp_reset_xscale,
+	.check_reset = megasas_check_reset_xscale,
 };
 
 /**
@@ -267,14 +328,14 @@ megasas_enable_intr_ppc(struct megasas_register_set __iomem * regs)
 {
 	writel(0xFFFFFFFF, &(regs)->outbound_doorbell_clear);
     
-	writel(~0x80000004, &(regs)->outbound_intr_mask);
+	writel(~0x80000000, &(regs)->outbound_intr_mask);
 
 	/* Dummy readl to force pci flush */
 	readl(&regs->outbound_intr_mask);
 }
 
 /**
- * megasas_disable_intr_ppc -	Disables interrupt
+ * megasas_disable_intr_ppc -	Disable interrupt
  * @regs:			MFI register set
  */
 static inline void
@@ -310,7 +371,7 @@ megasas_clear_intr_ppc(struct megasas_register_set __iomem * regs)
 	status = readl(&regs->outbound_intr_status);
 
 	if (!(status & MFI_REPLY_1078_MESSAGE_INTERRUPT)) {
-		return 1;
+		return 0;
 	}
 
 	/*
@@ -321,7 +382,7 @@ megasas_clear_intr_ppc(struct megasas_register_set __iomem * regs)
 	/* Dummy readl to force pci flush */
 	readl(&regs->outbound_doorbell_clear);
 
-	return 0;
+	return 1;
 }
 /**
  * megasas_fire_cmd_ppc -	Sends command to the FW
@@ -330,10 +391,36 @@ megasas_clear_intr_ppc(struct megasas_register_set __iomem * regs)
  * @regs :			MFI register set
  */
 static inline void 
-megasas_fire_cmd_ppc(struct megasas_instance *instance, dma_addr_t frame_phys_addr, u32 frame_count, struct megasas_register_set __iomem *regs)
+megasas_fire_cmd_ppc(struct megasas_instance *instance,
+		dma_addr_t frame_phys_addr,
+		u32 frame_count,
+		struct megasas_register_set __iomem *regs)
 {
+	unsigned long flags;
+	spin_lock_irqsave(&instance->hba_lock, flags);
 	writel((frame_phys_addr | (frame_count<<1))|1, 
 			&(regs)->inbound_queue_port);
+	spin_unlock_irqrestore(&instance->hba_lock, flags);
+}
+
+/**
+ * megasas_adp_reset_ppc -	For controller reset
+ * @regs:				MFI register set
+ */
+static int 
+megasas_adp_reset_ppc(struct megasas_instance *instance, struct megasas_register_set __iomem * regs)
+{
+	return 0;
+}
+
+/**
+ * megasas_check_reset_ppc -	For controller reset check
+ * @regs:				MFI register set
+ */
+static int 
+megasas_check_reset_ppc(struct megasas_instance *instance, struct megasas_register_set __iomem * regs)
+{
+	return 0;
 }
 
 static struct megasas_instance_template megasas_instance_template_ppc = {
@@ -343,6 +430,8 @@ static struct megasas_instance_template megasas_instance_template_ppc = {
 	.disable_intr = megasas_disable_intr_ppc,
 	.clear_intr = megasas_clear_intr_ppc,
 	.read_fw_status_reg = megasas_read_fw_status_reg_ppc,
+	.adp_reset = megasas_adp_reset_ppc,
+	.check_reset = megasas_check_reset_ppc,
 };
 
 /**
@@ -399,7 +488,7 @@ megasas_clear_intr_skinny(struct megasas_register_set __iomem * regs)
 	status = readl(&regs->outbound_intr_status);
 
 	if (!(status & MFI_SKINNY_ENABLE_INTERRUPT_MASK)) {
-		return 1;
+		return 0;
 	}
 
 	/*
@@ -412,7 +501,7 @@ megasas_clear_intr_skinny(struct megasas_register_set __iomem * regs)
 	*/
 	readl(&regs->outbound_intr_status);
 
-	return 0;
+	return 1;
 }
 /**
  * megasas_fire_cmd_skinny -	Sends command to the FW
@@ -421,17 +510,40 @@ megasas_clear_intr_skinny(struct megasas_register_set __iomem * regs)
  * @regs :			MFI register set
  */
 static inline void 
-megasas_fire_cmd_skinny(struct megasas_instance *instance, dma_addr_t frame_phys_addr, u32 frame_count, struct megasas_register_set __iomem *regs)
+megasas_fire_cmd_skinny(struct megasas_instance *instance,
+			dma_addr_t frame_phys_addr,
+			u32 frame_count,
+			struct megasas_register_set __iomem *regs)
 {
 	unsigned long flags;
-	spin_lock_irqsave(&instance->fire_lock, flags);
+	spin_lock_irqsave(&instance->hba_lock, flags);
 	writel(0, &(regs)->inbound_high_queue_port);
 	writel((frame_phys_addr | (frame_count<<1))|1, 
 			&(regs)->inbound_low_queue_port);
-	spin_unlock_irqrestore(&instance->fire_lock, flags);
+	spin_unlock_irqrestore(&instance->hba_lock, flags);
 	/*msleep(5);*/
 }
 
+/**
+ * megasas_adp_reset_skinny -	For controller reset
+ * @regs:				MFI register set
+ */
+static int 
+megasas_adp_reset_skinny(struct megasas_instance *instance, struct megasas_register_set __iomem * regs)
+{
+	return 0;
+}
+
+/**
+ * megasas_check_reset_skinny -	For controller reset check
+ * @regs:				MFI register set
+ */
+static int 
+megasas_check_reset_skinny(struct megasas_instance *instance, struct megasas_register_set __iomem * regs)
+{
+	return 0;
+}
+
 static struct megasas_instance_template megasas_instance_template_skinny = {
 	
 	.fire_cmd = megasas_fire_cmd_skinny,
@@ -439,16 +551,14 @@ static struct megasas_instance_template megasas_instance_template_skinny = {
 	.disable_intr = megasas_disable_intr_skinny,
 	.clear_intr = megasas_clear_intr_skinny,
 	.read_fw_status_reg = megasas_read_fw_status_reg_skinny,
+	.adp_reset = megasas_adp_reset_skinny,
+	.check_reset = megasas_check_reset_skinny,
 };
 
-/**
-*	This is the end of set of functions & definitions
-* 	specific to ppc (deviceid : 0x60) controllers
-*/
 
 /**
 *	The following functions are defined for gen2 (deviceid : 0x78 0x79)
-* 	controllers
+*	controllers
 */
 
 /**
@@ -456,10 +566,10 @@ static struct megasas_instance_template megasas_instance_template_skinny = {
  * @regs:			MFI register set
  */
 static inline void
-megasas_enable_intr_gen2(struct megasas_register_set __iomem *regs)
+megasas_enable_intr_gen2(struct megasas_register_set __iomem * regs)
 {
 	writel(0xFFFFFFFF, &(regs)->outbound_doorbell_clear);
-
+    
 	/* write ~0x00000005 (4 & 1) to the intr mask*/
 	writel(~MFI_GEN2_ENABLE_INTERRUPT_MASK, &(regs)->outbound_intr_mask);
 
@@ -485,7 +595,7 @@ megasas_disable_intr_gen2(struct megasas_register_set __iomem * regs)
  * @regs:			MFI register set
  */
 static u32
-megasas_read_fw_status_reg_gen2(struct megasas_register_set __iomem *regs)
+megasas_read_fw_status_reg_gen2(struct megasas_register_set __iomem * regs)
 {
 	return readl(&(regs)->outbound_scratch_pad);
 }
@@ -494,28 +604,36 @@ megasas_read_fw_status_reg_gen2(struct megasas_register_set __iomem *regs)
  * megasas_clear_interrupt_gen2 -	Check & clear interrupt
  * @regs:				MFI register set
  */
-static int
-megasas_clear_intr_gen2(struct megasas_register_set __iomem *regs)
+static int 
+megasas_clear_intr_gen2(struct megasas_register_set __iomem * regs)
 {
-	u32 status;
-	/*
-	 * Check if it is our interrupt
-	 */
-	status = readl(&regs->outbound_intr_status);
+        u32 status;
+        u32 mfiStatus = 0;
+        /*
+         * Check if it is our interrupt
+         */
+        status = readl(&regs->outbound_intr_status);
 
-	if (!(status & MFI_GEN2_ENABLE_INTERRUPT_MASK)) {
-		return 1;
-	}
+        if (status & MFI_GEN2_ENABLE_INTERRUPT_MASK)
+        {
+                mfiStatus = MFI_INTR_FLAG_REPLY_MESSAGE;
+        }
+        if (status & MFI_G2_OUTBOUND_DOORBELL_CHANGE_INTERRUPT)
+        {
+                mfiStatus |= MFI_INTR_FLAG_FIRMWARE_STATE_CHANGE;
+        }
 
-	/*
-	 * Clear the interrupt by writing back the same value
-	 */
-	writel(status, &regs->outbound_doorbell_clear);
+        /*
+         * Clear the interrupt by writing back the same value
+         */
+        if (mfiStatus)
+                writel(status, &regs->outbound_doorbell_clear);
 
-	/* Dummy readl to force pci flush */
-	readl(&regs->outbound_intr_status);
+        /* Dummy readl to force pci flush */
+        readl(&regs->outbound_intr_status);
+
+        return mfiStatus;
 
-	return 0;
 }
 /**
  * megasas_fire_cmd_gen2 -	Sends command to the FW
@@ -523,31 +641,99 @@ megasas_clear_intr_gen2(struct megasas_register_set __iomem *regs)
  * @frame_count :		Number of frames for the command
  * @regs :			MFI register set
  */
-static inline void
-megasas_fire_cmd_gen2(struct megasas_instance *instance, dma_addr_t frame_phys_addr,
-			u32 frame_count, struct megasas_register_set __iomem *regs)
+static inline void 
+megasas_fire_cmd_gen2(struct megasas_instance *instance,
+			dma_addr_t frame_phys_addr,
+			u32 frame_count,
+			struct megasas_register_set __iomem *regs)
 {
 	unsigned long flags;
-	spin_lock_irqsave(&instance->fire_lock, flags);
+	spin_lock_irqsave(&instance->hba_lock, flags);
 	writel((frame_phys_addr | (frame_count<<1))|1, 
 			&(regs)->inbound_queue_port);
-	spin_unlock_irqrestore(&instance->fire_lock, flags);
+	spin_unlock_irqrestore(&instance->hba_lock, flags);
 }
 
-static struct megasas_instance_template megasas_instance_template_gen2 = {
+/**
+ * megasas_adp_reset_gen2 -     For controller reset
+ * @regs:                               MFI register set
+ */
+static int
+megasas_adp_reset_gen2(struct megasas_instance *instance, struct megasas_register_set __iomem * reg_set)
+{
+    u32                 retry = 0, delay = 0;
+    u32                 HostDiag;
+
+        writel(0, &reg_set->seq_offset);
+        writel(4, &reg_set->seq_offset);
+        writel(0xb, &reg_set->seq_offset);
+        writel(2, &reg_set->seq_offset);
+        writel(7, &reg_set->seq_offset);
+        writel(0xd, &reg_set->seq_offset);
+
+        msleep(1000);
 
+        HostDiag = (u32)readl(&reg_set->host_diag);
+
+        while ( !( HostDiag & DIAG_WRITE_ENABLE) )
+        {
+                msleep(100);
+                HostDiag = (u32)readl(&reg_set->host_diag);
+                printk("ADP_RESET_GEN2: retry time=%x, hostdiag=%x\n", retry, HostDiag);
+
+                if (retry++ >= 100)
+                        return 1;
+
+        }
+
+        printk("ADP_RESET_GEN2: HostDiag=%x\n", HostDiag);
+
+        writel((HostDiag | DIAG_RESET_ADAPTER), &reg_set->host_diag);
+
+        for (delay=0; delay<10; delay++)
+        {
+                msleep(1000);
+        }
+
+        HostDiag = (u32)readl(&reg_set->host_diag);
+        while ( ( HostDiag & DIAG_RESET_ADAPTER) )
+        {
+                msleep(100);
+                HostDiag = (u32)readl(&reg_set->host_diag);
+                printk("ADP_RESET_GEN2: retry time=%x, hostdiag=%x\n", retry, HostDiag);
+
+                if (retry++ >= 1000)
+                        return 1;
+
+        }
+        return 0;
+}
+
+/**
+ * megasas_check_reset_gen2 -   For controller reset check
+ * @regs:                               MFI register set
+ */
+static int
+megasas_check_reset_gen2(struct megasas_instance *instance, struct megasas_register_set __iomem * regs)
+{
+        return 0;
+}
+
+static struct megasas_instance_template megasas_instance_template_gen2 = {
+	
 	.fire_cmd = megasas_fire_cmd_gen2,
 	.enable_intr = megasas_enable_intr_gen2,
 	.disable_intr = megasas_disable_intr_gen2,
 	.clear_intr = megasas_clear_intr_gen2,
 	.read_fw_status_reg = megasas_read_fw_status_reg_gen2,
+        .adp_reset = megasas_adp_reset_gen2,
+        .check_reset = megasas_check_reset_gen2,
 };
 
 /**
- *      This is the end of set of functions & definitions
+*	This is the end of set of functions & definitions
  *      specific to gen2 (deviceid : 0x78, 0x79) controllers
- */
-
+*/
 
 /**
  * megasas_issue_polled -	Issues a polling command
@@ -570,7 +756,8 @@ megasas_issue_polled(struct megasas_instance *instance, struct megasas_cmd *cmd)
 	/*
 	 * Issue the frame using inbound queue port
 	 */
-	instance->instancet->fire_cmd(instance, cmd->frame_phys_addr ,0,instance->reg_set);
+	instance->instancet->fire_cmd(instance,
+			cmd->frame_phys_addr, 0, instance->reg_set);
 
 	/*
 	 * Wait for cmd_status to change
@@ -601,10 +788,10 @@ megasas_issue_blocked_cmd(struct megasas_instance *instance,
 {
 	cmd->cmd_status = ENODATA;
 
-	instance->instancet->fire_cmd(instance, cmd->frame_phys_addr ,0,instance->reg_set);
+	instance->instancet->fire_cmd(instance,
+			cmd->frame_phys_addr, 0, instance->reg_set);
 
-	wait_event_timeout(instance->int_cmd_wait_q, (cmd->cmd_status != ENODATA),
-		MEGASAS_INTERNAL_CMD_WAIT_TIME*HZ);
+	wait_event(instance->int_cmd_wait_q, cmd->cmd_status != ENODATA);
 
 	return 0;
 }
@@ -646,13 +833,15 @@ megasas_issue_blocked_abort_cmd(struct megasas_instance *instance,
 	cmd->sync_cmd = 1;
 	cmd->cmd_status = 0xFF;
 
-	instance->instancet->fire_cmd(instance, cmd->frame_phys_addr ,0,instance->reg_set);
+	instance->instancet->fire_cmd(instance,
+			cmd->frame_phys_addr, 0, instance->reg_set);
 
 	/*
 	 * Wait for this cmd to complete
 	 */
-	wait_event_timeout(instance->abort_cmd_wait_q, (cmd->cmd_status != 0xFF),
-		MEGASAS_INTERNAL_CMD_WAIT_TIME*HZ);
+	wait_event(instance->abort_cmd_wait_q, cmd->cmd_status != 0xFF);
+	cmd->sync_cmd = 0;
+
 
 	megasas_return_cmd(instance, cmd);
 	return 0;
@@ -754,9 +943,9 @@ megasas_make_sgl64(struct megasas_instance *instance, struct scsi_cmnd *scp,
 
 	return sge_count;
 }
-
+ 
 /**
- * megasas_make_sgl_kinny -	Prepares 64-bit IEEE SGL
+ * megasas_make_sgl_skinny - Prepares IEEE SGL
  * @instance:		Adapter soft state
  * @scp:		SCSI command from the mid-layer
  * @mfi_sgl:		SGL to be filled in
@@ -806,8 +995,8 @@ megasas_make_sgl_skinny(struct megasas_instance *instance, struct scsi_cmnd *scp
 
  /**
  * megasas_get_frame_count - Computes the number of frames
- * @sge_count		: number of sg elements
  * @frame_type		: type of frame- io or pthru frame
+ * @sge_count		: number of sg elements
  *
  * Returns the number of frames required for numnber of sge's (sge_count)
  */
@@ -914,16 +1103,16 @@ megasas_build_dcdb(struct megasas_instance *instance, struct scsi_cmnd *scp,
 
 	memcpy(pthru->cdb, scp->cmnd, scp->cmd_len);
 
-	/*
-	* If the command is for the tape device, set the
-	* pthru timeout to the os layer timeout value.
-	*/
-	if(scp->device->type == TYPE_TAPE) {
-		if((scp->timeout_per_command / HZ) > 0xFFFF)
-                    pthru->timeout = 0xFFFF;
-            	else
-                    pthru->timeout = scp->timeout_per_command / HZ;
-	}
+        /*
+         * If the command is for the tape device, set the
+         * pthru timeout to the os layer timeout value.
+         */
+        if(scp->device->type == TYPE_TAPE) {
+                if((scp->timeout_per_command / HZ) > 0xFFFF)
+                        pthru->timeout = 0xFFFF;
+                else
+                        pthru->timeout = scp->timeout_per_command / HZ;
+        }
 
 	/*
 	 * Construct SGL
@@ -932,6 +1121,7 @@ megasas_build_dcdb(struct megasas_instance *instance, struct scsi_cmnd *scp,
 		pthru->flags |= MFI_FRAME_SGL64;
 		pthru->sge_count = megasas_make_sgl_skinny(instance, scp,
 						      &pthru->sgl);
+
 	} else if (IS_DMA64) {
 		pthru->flags |= MFI_FRAME_SGL64;
 		pthru->sge_count = megasas_make_sgl64(instance, scp,
@@ -965,7 +1155,7 @@ megasas_build_dcdb(struct megasas_instance *instance, struct scsi_cmnd *scp,
  * megasas_build_ldio -	Prepares IOs to logical devices
  * @instance:		Adapter soft state
  * @scp:		SCSI command
- * @cmd:		Command to to be prepared
+ * @cmd:		Command to be prepared
  *
  * Frames (and accompanying SGLs) for regular SCSI IOs use this function.
  */
@@ -990,7 +1180,6 @@ megasas_build_ldio(struct megasas_instance *instance, struct scsi_cmnd *scp,
 		flags |= MFI_FRAME_IEEE;
 	}
 	
-
 	/*
 	 * Prepare the Logical IO frame: 2nd bit is zero for all read cmds
 	 */
@@ -1065,6 +1254,7 @@ megasas_build_ldio(struct megasas_instance *instance, struct scsi_cmnd *scp,
 		ldio->flags |= MFI_FRAME_SGL64;
 		ldio->sge_count = megasas_make_sgl_skinny(instance, scp,
 					      &ldio->sgl);
+
 	} else if (IS_DMA64) {
 		ldio->flags |= MFI_FRAME_SGL64;
 		ldio->sge_count = megasas_make_sgl64(instance, scp, &ldio->sgl);
@@ -1073,7 +1263,7 @@ megasas_build_ldio(struct megasas_instance *instance, struct scsi_cmnd *scp,
 
         if (ldio->sge_count > instance->max_num_sge) {
         	printk("megasas: build_ld_io  error, sge_count = %x\n", ldio->sge_count);
-	        return 0;
+                return 0;
 	}
 
 	/*
@@ -1087,7 +1277,8 @@ megasas_build_ldio(struct megasas_instance *instance, struct scsi_cmnd *scp,
 	 * Compute the total number of frames this command consumes. FW uses
 	 * this number to pull sufficient number of frames from host memory.
 	 */
-	cmd->frame_count = megasas_get_frame_count(instance, ldio->sge_count, IO_FRAME);
+	cmd->frame_count = megasas_get_frame_count(instance,
+			ldio->sge_count, IO_FRAME);
 
 	return cmd->frame_count;
 }
@@ -1192,13 +1383,25 @@ megasas_queue_command(struct scsi_cmnd *scmd, void (*done) (struct scsi_cmnd *))
 	u32 frame_count;
 	struct megasas_cmd *cmd;
 	struct megasas_instance *instance;
+	unsigned long flags;
 
 	instance = (struct megasas_instance *)
 	    scmd->device->host->hostdata;
 
-	/* Don't process if we have already declared adapter dead */
-	if (instance->hw_crit_error)
+        if (instance->issuepend_done == 0)
+                return SCSI_MLQUEUE_HOST_BUSY;
+
+	spin_lock_irqsave(&instance->hba_lock, flags);
+
+	//Don't process if we have already declared adapter dead
+	// If we are in middle of bringing up the HBA, send the busy status to mid-layer
+	// till the process is complete
+	if (instance->adprecovery != MEGASAS_HBA_OPERATIONAL) {
+		spin_unlock_irqrestore(&instance->hba_lock, flags);
 		return SCSI_MLQUEUE_HOST_BUSY;
+	}
+
+	spin_unlock_irqrestore(&instance->hba_lock, flags);
 
 	scmd->scsi_done = done;
 	scmd->result = 0;
@@ -1244,8 +1447,8 @@ megasas_queue_command(struct scsi_cmnd *scmd, void (*done) (struct scsi_cmnd *))
 	 */
 	atomic_inc(&instance->fw_outstanding);
 
-	instance->instancet->fire_cmd(instance, cmd->frame_phys_addr ,cmd->frame_count-1,instance->reg_set);
-
+	instance->instancet->fire_cmd(instance, cmd->frame_phys_addr,
+				cmd->frame_count-1, instance->reg_set);
 	/*
 	 * Check if we have pend cmds to be completed
 	 */
@@ -1296,7 +1499,6 @@ static int megasas_slave_configure(struct scsi_device *sdev)
 			sdev->timeout = 90 * HZ;
 			return 0;
 		}
-	
 		return -ENXIO;
 	}
 	
@@ -1307,18 +1509,34 @@ static int megasas_slave_configure(struct scsi_device *sdev)
 	return 0;
 }
 
+static void process_fw_state_change_wq(void *instance);
+
+static void megaraid_sas_kill_hba(struct megasas_instance *instance)
+{
+       if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0073SKINNY) ||
+               (instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0071SKINNY))
+       {
+               writel(MFI_STOP_ADP,
+                       &instance->reg_set->reserved_0[0]);
+       } else {
+               writel(MFI_STOP_ADP,
+                       &instance->reg_set->inbound_doorbell);
+       }
+}
+
 static int megasas_slave_alloc(struct scsi_device *sdev)
 {
 	u16		pd_index = 0;
 	struct megasas_instance *instance ;
 	instance = megasas_lookup_instance(sdev->host->host_no);
-
-	if (sdev->channel < MEGASAS_MAX_PD_CHANNELS && sdev->type == TYPE_DISK) {
+	if ((sdev->channel < MEGASAS_MAX_PD_CHANNELS) &&
+				(sdev->type == TYPE_DISK)) {
 		/*
 		 * Open the OS scan to the SYSTEM PD
 		 */
 		pd_index =
-		    (sdev->channel * MEGASAS_MAX_DEV_PER_CHANNEL) + sdev->id;
+			(sdev->channel * MEGASAS_MAX_DEV_PER_CHANNEL) +
+			sdev->id;
 		if ((instance->pd_list[pd_index].driveState ==
 			MR_PD_STATE_SYSTEM) &&
 			(instance->pd_list[pd_index].driveType ==
@@ -1331,7 +1549,6 @@ static int megasas_slave_alloc(struct scsi_device *sdev)
 	return 0;
 }
 
-
 /**
  * megasas_complete_cmd_dpc	 -	Returns FW's controller structure
  * @instance_addr:			Address of adapter soft state
@@ -1349,8 +1566,12 @@ static void megasas_complete_cmd_dpc(unsigned long instance_addr)
 	unsigned long flags;
 
 	/* If we have already declared adapter dead, donot complete cmds */
-	if (instance->hw_crit_error)
+	spin_lock_irqsave(&instance->hba_lock, flags);
+	if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR ) { 
+		spin_unlock_irqrestore(&instance->hba_lock, flags);
 		return;
+	}
+	spin_unlock_irqrestore(&instance->hba_lock, flags);
 
 	spin_lock_irqsave(&instance->completion_lock, flags);
 
@@ -1360,6 +1581,10 @@ static void megasas_complete_cmd_dpc(unsigned long instance_addr)
 	while (consumer != producer) {
 		context = instance->reply_queue[consumer];
 
+		if (context >= instance->max_fw_cmds) {
+			printk("ERROR ERROR: unexpected context value %x\n", context);
+			BUG();
+		}
 		cmd = instance->cmd_list[context];
 
 		megasas_complete_cmd(instance, cmd, DID_OK);
@@ -1371,7 +1596,6 @@ static void megasas_complete_cmd_dpc(unsigned long instance_addr)
 	}
 
 	*instance->consumer = producer;
-
 	spin_unlock_irqrestore(&instance->completion_lock, flags);
 
 	/*
@@ -1383,11 +1607,12 @@ static void megasas_complete_cmd_dpc(unsigned long instance_addr)
 
 		spin_lock_irqsave(instance->host->host_lock, flags);
 		instance->flag &= ~MEGASAS_FW_BUSY;
-		if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0073SKINNY) ||
-			(instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0071SKINNY)) {
+		if ((instance->pdev->device ==
+			PCI_DEVICE_ID_LSI_SAS0073SKINNY) ||
+			(instance->pdev->device ==
+			PCI_DEVICE_ID_LSI_SAS0071SKINNY)) {
 			instance->host->can_queue =
 				instance->max_fw_cmds - MEGASAS_SKINNY_INT_CMDS;
-			
 		} else 
 			instance->host->can_queue =
 				instance->max_fw_cmds - MEGASAS_INT_CMDS;
@@ -1408,8 +1633,81 @@ static void megasas_complete_cmd_dpc(unsigned long instance_addr)
 static int megasas_wait_for_outstanding(struct megasas_instance *instance)
 {
 	int i;
+	u32 reset_index;
 	u32 wait_time = MEGASAS_RESET_WAIT_TIME;
+	u8 adprecovery;
+	unsigned long flags;
+	struct list_head clist_local;
+	struct megasas_cmd *reset_cmd;
+
+	// If we are in-process if internal reset, we should wait for that process to
+	// complete
+	spin_lock_irqsave(&instance->hba_lock, flags);
+	adprecovery = instance->adprecovery;
+	spin_unlock_irqrestore(&instance->hba_lock, flags);
+
+	if (adprecovery != MEGASAS_HBA_OPERATIONAL) {
+
+		// We take the ownership of all the pending commands. These would be failed to the OS
+		// after a successful recovery from adapter internal reset condition.
+		INIT_LIST_HEAD(&clist_local);
+		spin_lock_irqsave(&instance->hba_lock, flags);
+		list_splice_init(&instance->internal_reset_pending_q, &clist_local);
+		spin_unlock_irqrestore(&instance->hba_lock, flags);
+
+		printk("megasas: HBA reset handler invoked while adapter internal reset in progress, wait till that's over...\n");
+		for (i = 0; i < wait_time; i++) {
+			msleep(1000);
+			// Are we there yet?
+			spin_lock_irqsave(&instance->hba_lock, flags);
+			adprecovery = instance->adprecovery;
+			spin_unlock_irqrestore(&instance->hba_lock, flags);
+			if (adprecovery == MEGASAS_HBA_OPERATIONAL)
+				break;
+		}
 
+		// Are we out of reset yet? If not, HBA is toasted :-(
+		if (adprecovery != MEGASAS_HBA_OPERATIONAL) {
+			printk("megasas: HBA reset handler timedout for internal reset. Stopping the HBA.\n");
+			spin_lock_irqsave(&instance->hba_lock, flags);
+			instance->adprecovery	= MEGASAS_HW_CRITICAL_ERROR;
+			spin_unlock_irqrestore(&instance->hba_lock, flags);
+			return FAILED;
+		}
+
+		printk("megasas: HBA internal reset condition discovered to be cleared.\n");
+
+		// Send the pending commands back to the OS with reset condition
+		reset_index	= 0;
+		while (!list_empty(&clist_local)) {
+			reset_cmd	= list_entry((&clist_local)->next, struct megasas_cmd, list);
+			list_del_init(&reset_cmd->list);
+			if (reset_cmd->scmd) {
+				reset_cmd->scmd->result = DID_RESET << 16;
+				printk("megasas: %d:%p reset scsi command [%02x], %#lx\n",
+					reset_index, reset_cmd, reset_cmd->scmd->cmnd[0], reset_cmd->scmd->serial_number);
+				reset_cmd->scmd->scsi_done(reset_cmd->scmd);
+				megasas_return_cmd(instance, reset_cmd);
+			}
+			else if (reset_cmd->sync_cmd) {
+				// Such commands have no timeout, we re-issue this guy again.
+				printk("megasas: %p synchronous command detected on the internal reset queue, re-issuing it.\n", reset_cmd);
+				reset_cmd->cmd_status = ENODATA;
+				instance->instancet->fire_cmd(instance, reset_cmd->frame_phys_addr ,0,instance->reg_set);
+			}
+			else {
+				printk("megasas: %p unexpected command on the internal reset defer list.\n", reset_cmd);
+			}
+			reset_index++;
+		}
+
+		printk("megaraid_sas: All pending commands have been cleared for reset condition.\n");
+
+		return SUCCESS;
+	}
+
+	// Kernel reset without internal reset in progress.
+	printk("megaraid_sas: HBA reset handler invoked without an internal reset condition.\n");
 	for (i = 0; i < wait_time; i++) {
 
 		int outstanding = atomic_read(&instance->fw_outstanding);
@@ -1418,10 +1716,12 @@ static int megasas_wait_for_outstanding(struct megasas_instance *instance)
 			break;
 
 		if (!(i % MEGASAS_RESET_NOTICE_INTERVAL)) {
+
 			printk(KERN_NOTICE "megasas: [%2d]waiting for %d "
 			       "commands to complete\n",i,outstanding);
+
 			/*
-			 * Call cmd completion routine. Cmd to be
+			 * Call cmd completion routine. Cmd to be 
 			 * be completed directly without depending on isr.
 			 */
 			megasas_complete_cmd_dpc((unsigned long)instance);
@@ -1431,13 +1731,15 @@ static int megasas_wait_for_outstanding(struct megasas_instance *instance)
 	}
 
 	if (atomic_read(&instance->fw_outstanding)) {
+		printk("megaraid_sas: pending commands remain even after reset handling.\n");
 		/*
 		* Send signal to FW to stop processing any pending cmds.
 		* The controller will be taken offline by the OS now.
 		*/
-		if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0073SKINNY) ||
-			(instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0071SKINNY))
-		{
+		if ((instance->pdev->device ==
+			PCI_DEVICE_ID_LSI_SAS0073SKINNY) ||
+			(instance->pdev->device ==
+			PCI_DEVICE_ID_LSI_SAS0071SKINNY)) {
 			writel(MFI_STOP_ADP,
 				&instance->reg_set->reserved_0[0]);
 		} else {
@@ -1445,10 +1747,14 @@ static int megasas_wait_for_outstanding(struct megasas_instance *instance)
 				&instance->reg_set->inbound_doorbell);
 		}
 		megasas_dump_pending_frames(instance);
-		instance->hw_crit_error = 1;
+		spin_lock_irqsave(&instance->hba_lock, flags);
+		instance->adprecovery	= MEGASAS_HW_CRITICAL_ERROR;
+		spin_unlock_irqrestore(&instance->hba_lock, flags);
 		return FAILED;
 	}
 
+	printk("megaraid_sas: no more pending commands remain after reset handling.\n");
+
 	return SUCCESS;
 }
 
@@ -1470,7 +1776,7 @@ static int megasas_generic_reset(struct scsi_cmnd *scmd)
 	scmd_printk(KERN_NOTICE, scmd, "megasas: RESET -%ld cmd=%x retries=%x\n",
 		 scmd->serial_number, scmd->cmnd[0], scmd->retries);
 
-	if (instance->hw_crit_error) {
+	if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR ) {
 		printk(KERN_ERR "megasas: cannot recover from previous reset "
 		       "failures\n");
 		return FAILED;
@@ -1613,11 +1919,11 @@ megasas_service_aen(struct megasas_instance *instance, struct megasas_cmd *cmd)
 	/*
 	 * Don't signal app if it is just an aborted previously registered aen
 	 */
-	if ((!cmd->abort_aen) && (instance->unload == 0)) {
+	if ((!cmd->abort_aen) && (instance->unload == 0 )) {
 		spin_lock_irqsave(&poll_aen_lock, flags);
 		megasas_poll_wait_aen = 1;
 		spin_unlock_irqrestore(&poll_aen_lock, flags);
-		wake_up(&megasas_poll_wait);
+		wake_up(&megasas_poll_wait);	
 		kill_fasync(&megasas_async_queue, SIGIO, POLL_IN);
 	}
 	else
@@ -1625,15 +1931,16 @@ megasas_service_aen(struct megasas_instance *instance, struct megasas_cmd *cmd)
 
 	instance->aen_cmd = NULL;
 	megasas_return_cmd(instance, cmd);
-	if (instance->unload == 0) {
+	if ((instance->unload == 0) && ((instance->issuepend_done == 1))) {
 		struct megasas_aen_event *ev;
 		ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
 		if (!ev) {
-			printk(KERN_ERR "%s: out of memory\n", __FUNCTION__);
+			printk(KERN_ERR "megasas_service_aen: out of memory\n");
 		} else {
 			ev->instance = instance;
+			instance->ev = ev;
 			INIT_WORK(&ev->hotplug_work, megasas_aen_polling, ev);
-			schedule_delayed_work(&ev->hotplug_work, 0);
+			 schedule_delayed_work(&ev->hotplug_work, 0);
 		}
 	}
 }
@@ -1724,8 +2031,7 @@ megasas_unmap_sgbuf(struct megasas_instance *instance, struct megasas_cmd *cmd)
 	opcode = cmd->frame->hdr.cmd;
 
 	if ((opcode == MFI_CMD_LD_READ) || (opcode == MFI_CMD_LD_WRITE)) {
-		if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0073SKINNY) ||
-		(instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0071SKINNY)) {
+		if (instance->flag_ieee) {
 			buf_h = cmd->frame->io.sgl.sge_skinny[0].phys_addr;
 
 		} else if (IS_DMA64)
@@ -1733,8 +2039,7 @@ megasas_unmap_sgbuf(struct megasas_instance *instance, struct megasas_cmd *cmd)
 		else
 			buf_h = cmd->frame->io.sgl.sge32[0].phys_addr;
 	} else {
-		if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0073SKINNY) ||
-		(instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0071SKINNY)) {
+		if (instance->flag_ieee) {
 			buf_h = cmd->frame->pthru.sgl.sge_skinny[0].phys_addr;
 
 		} else if (IS_DMA64)
@@ -1766,6 +2071,10 @@ megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd,
 	int exception = 0;
 	struct megasas_header *hdr = &cmd->frame->hdr;
 
+       // If the commands complete successfully, the retry counter should also be reset
+        // for future re-tries.
+        cmd->retry_for_fw_reset = 0;
+
 	if (cmd->scmd)
 		cmd->scmd->SCp.ptr = NULL;
 
@@ -1854,13 +2163,13 @@ megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd,
 	case MFI_CMD_SMP:
 	case MFI_CMD_STP:
 	case MFI_CMD_DCMD:
+
 		if (cmd->frame->dcmd.opcode == MR_DCMD_CTRL_EVENT_GET_INFO || 
 			cmd->frame->dcmd.opcode == MR_DCMD_CTRL_EVENT_GET) {
 			spin_lock_irqsave(&poll_aen_lock, flags);
 			megasas_poll_wait_aen = 0;
 			spin_unlock_irqrestore(&poll_aen_lock, flags);
 		}
-
 		/*
 		 * See if got an event notification
 		 */
@@ -1878,11 +2187,191 @@ megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd,
 		megasas_complete_abort(instance, cmd);
 		break;
 
-	default:
-		printk("megasas: Unknown command completed! [0x%X]\n",
-		       hdr->cmd);
-		break;
+	default:
+		printk("megasas: Unknown command completed! [0x%X]\n",
+		       hdr->cmd);
+		break;
+	}
+}
+
+ /**
+ * megasas_issue_pending_cmds_again -	issue all pending cmds
+ *                              	in FW again because of the fw reset
+ * @instance:				Adapter soft state
+ */
+static inline void
+megasas_issue_pending_cmds_again(struct megasas_instance *instance)
+{
+	struct megasas_cmd *cmd;
+	struct list_head clist_local;
+	union megasas_evt_class_locale class_locale;
+	unsigned long flags;
+	u32 seq_num;
+
+	INIT_LIST_HEAD(&clist_local);
+	spin_lock_irqsave(&instance->hba_lock, flags);
+	list_splice_init(&instance->internal_reset_pending_q, &clist_local);
+	spin_unlock_irqrestore(&instance->hba_lock, flags);
+
+	while (!list_empty(&clist_local)) {
+		cmd	= list_entry((&clist_local)->next, struct megasas_cmd, list);
+		list_del_init(&cmd->list);
+
+               if (cmd->sync_cmd || cmd->scmd) {
+                       printk("megaraid_sas: command %p, %p:%d detected to be pending while HBA reset.\n", cmd, cmd->scmd, cmd->sync_cmd);
+
+                       cmd->retry_for_fw_reset++;
+
+                       // If a command has continuously been tried multiple times and causing
+                       // a FW reset condition, no further recoveries should be performed on
+                       // the controller
+                       if (cmd->retry_for_fw_reset == 3) {
+                               printk("megaraid_sas: command %p, %p:%d was tried multiple times during adapter reset. Shutting down the HBA\n", cmd, cmd->scmd, cmd->sync_cmd);
+                               megaraid_sas_kill_hba(instance);
+
+				instance->adprecovery	= MEGASAS_HW_CRITICAL_ERROR;
+                               return;
+                       }
+               }
+
+		if (cmd->sync_cmd == 1) {
+			if (cmd->scmd) {
+				printk("megaraid_sas: unexpected SCSI command attached to internal command!\n");
+			}
+			printk("megasas: %p synchronous command detected on the internal reset queue, issue it again.\n", cmd);
+			cmd->cmd_status = ENODATA;
+			instance->instancet->fire_cmd(instance,cmd->frame_phys_addr ,0,instance->reg_set);
+		} else if (cmd->scmd) {
+			printk("megasas: %p scsi command [%02x], %#lx detected on the internal reset queue, issue it again.\n", cmd, cmd->scmd->cmnd[0], cmd->scmd->serial_number);
+			atomic_inc(&instance->fw_outstanding);
+			instance->instancet->fire_cmd(instance, cmd->frame_phys_addr ,cmd->frame_count-1,instance->reg_set);
+		}
+		else {
+			printk("megasas: %p unexpected command on the internal reset defer list while re-issue!!\n", cmd);
+		}
+	}
+
+	// Re-register AEN
+	if (instance->aen_cmd) {
+		printk("megaraid_sas: existing aen_cmd discovered in deferred processing, freeing...\n");
+		megasas_return_cmd(instance, instance->aen_cmd);
+		instance->aen_cmd	= NULL;
+	}
+
+	/*
+	* Initiate AEN (Asynchronous Event Notification)
+	*/
+	seq_num = instance->last_seq_num;
+	class_locale.members.reserved = 0;
+	class_locale.members.locale = MR_EVT_LOCALE_ALL;
+	class_locale.members.class = MR_EVT_CLASS_DEBUG;
+
+	megasas_register_aen(instance, seq_num, class_locale.word);
+}
+
+
+/**
+ * Move the internal reset pending commands to a deferred queue.
+ *
+ * We move the commands pending at internal reset time to a pending queue. This queue would
+ * be flushed after successful completion of the internal reset sequence.
+ * if the internal reset did not complete in time, the kernel reset handler would flush these
+ * commands.
+ **/
+static void megasas_internal_reset_defer_cmds(struct megasas_instance *instance)
+{
+	struct megasas_cmd *cmd;
+	int i;
+	u32 max_cmd = instance->max_fw_cmds;
+	u32 defer_index;
+	unsigned long flags;
+
+	defer_index	= 0;
+	spin_lock_irqsave(&instance->cmd_pool_lock, flags);
+	for (i = 0; i < max_cmd; i++) {
+		cmd = instance->cmd_list[i];
+		if (cmd->sync_cmd == 1 || cmd->scmd) {
+			printk("megasas: moving cmd[%d]:%p:%d:%p on the defer queue as internal reset in progress.\n",
+				defer_index, cmd, cmd->sync_cmd, cmd->scmd);
+			if (!list_empty(&cmd->list)) {
+				printk("megaraid_sas: ERROR while moving this cmd:%p, %d %p, it was discovered on some list?\n", cmd, cmd->sync_cmd, cmd->scmd);
+				list_del_init(&cmd->list);
+			}
+			defer_index++;
+			list_add_tail(&cmd->list, &instance->internal_reset_pending_q);
+		}
+	}
+	spin_unlock_irqrestore(&instance->cmd_pool_lock, flags);
+}
+
+static void process_fw_state_change_wq(void *arg)
+{
+        u32 wait;
+	unsigned long flags;
+
+	struct megasas_instance *instance = arg;
+        
+	if (instance->adprecovery != MEGASAS_ADPRESET_SM_INFAULT) {
+                printk("megaraid_sas: error, unexpected adapter recovery state %x in %s\n", instance->adprecovery, __FUNCTION__);
+                return;
+        }
+
+	if (instance->adprecovery == MEGASAS_ADPRESET_SM_INFAULT) {
+		printk("megaraid_sas: FW detected to be in fault state, restarting it...\n");
+
+		instance->instancet->disable_intr(instance->reg_set);
+                atomic_set(&instance->fw_outstanding, 0);
+
+                atomic_set(&instance->fw_reset_no_pci_access, 1);
+                instance->instancet->adp_reset(instance, instance->reg_set);
+                atomic_set(&instance->fw_reset_no_pci_access, 0 );
+
+		printk("megaraid_sas: FW was restarted successfully, initiating next stage...\n");
+
+		printk("megaraid_sas: HBA recovery state machine, state 2 starting...\n");
+
+                /*waitting for about 20 second before start the second init*/
+                for(wait = 0; wait < 30; wait++)
+                        msleep(1000);
+
+                if (megasas_transition_to_ready(instance))
+                {
+                        printk("megaraid_sas: out: controller is not in ready state\n");
+
+                        megaraid_sas_kill_hba(instance);
+			instance->adprecovery	= MEGASAS_HW_CRITICAL_ERROR;
+                        return ;
+                }
+
+                if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS1064R) ||
+                        (instance->pdev->device == PCI_DEVICE_ID_DELL_PERC5) ||
+                        (instance->pdev->device == PCI_DEVICE_ID_LSI_VERDE_ZCR))
+                {
+                        *instance->consumer = *instance->producer;
+                } else {
+                        *instance->consumer = 0;
+                        *instance->producer = 0;
+                }
+
+		// Transition the FW to operational state
+		megasas_issue_init_mfi(instance);
+
+		// Setting the adapter to OPERATIONAL at this point is very important. This would
+		// prevent other subsystems (reset, aen, and ioctls) to block till the recovery
+		// logic has run it's course.
+		spin_lock_irqsave(&instance->hba_lock, flags);
+		instance->adprecovery	= MEGASAS_HBA_OPERATIONAL;
+		spin_unlock_irqrestore(&instance->hba_lock, flags);
+		instance->instancet->enable_intr(instance->reg_set);
+
+		printk("megaraid_sas: second stage of reset complete, FW is ready now.\n");
+
+		megasas_issue_pending_cmds_again(instance);
+		instance->issuepend_done = 1;
+
+
 	}
+	return ;
 }
 
 /**
@@ -1891,24 +2380,70 @@ megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd,
  * @alt_status:				Alternate status to be returned to
  * 					SCSI mid-layer instead of the status
  * 					returned by the FW
+ * Note: this must be called with hba lock held
  */
 static int
 megasas_deplete_reply_queue(struct megasas_instance *instance, u8 alt_status)
 {
-	/*
-	 * Check if it is our interrupt
-	 * Clear the interrupt 
-	 */
-	if(instance->instancet->clear_intr(instance->reg_set))
+	u32 mfiStatus;
+	u32 fw_state;
+
+	// If the adapter is under a reset recovery, all interrupts coming from it must be acknowledged
+	// if the consumer pointer value indicates so.
+        if((mfiStatus = instance->instancet->check_reset(instance, instance->reg_set)) == 1) {
+                return IRQ_HANDLED;
+        }
+
+	// Clear the interrupt on the HBA
+	if((mfiStatus = instance->instancet->clear_intr(instance->reg_set)) == 0) {
 		return IRQ_NONE;
+	}
 
-	if (instance->hw_crit_error)
-		goto out_done;
-        /*
-	 * Schedule the tasklet for cmd completion
-	 */
+	instance->mfiStatus = mfiStatus;
+
+	// If the current soft state indicates an OPERATIONAL state _and_ now we have
+	// detected state change, this should be FW FAULT case.
+	if ((mfiStatus & MFI_INTR_FLAG_FIRMWARE_STATE_CHANGE)) {
+		fw_state = instance->instancet->read_fw_status_reg(instance->reg_set) & MFI_STATE_MASK;
+
+                if (fw_state != MFI_STATE_FAULT) {
+                        printk("megaraid_sas: fw state while internal state change operational, state:%x\n", fw_state);
+                }
+
+               	if ((fw_state == MFI_STATE_FAULT) && (instance->disableOnlineCtrlReset == 0)){
+			printk("megaraid_sas: adapter reset condition is detected, waiting for it to restart...\n");
+
+                       	if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS1064R) ||
+                               	(instance->pdev->device == PCI_DEVICE_ID_DELL_PERC5) ||
+                               	(instance->pdev->device == PCI_DEVICE_ID_LSI_VERDE_ZCR))
+                               	{
+					*instance->consumer	= MEGASAS_ADPRESET_INPROG_SIGN;
+                       	}
+
+
+			instance->instancet->disable_intr(instance->reg_set);
+			instance->adprecovery	= MEGASAS_ADPRESET_SM_INFAULT;    // indicates adapter restart stage 1 is in progress
+			instance->issuepend_done = 0;
+
+			// The pending commands are moved to a deferred list. We would pick commands up and
+			// re-issue once the reset processing is over.
+			atomic_set(&instance->fw_outstanding, 0);
+			megasas_internal_reset_defer_cmds(instance);
+
+			// Schedule a low-priorty thread to perform the function for current stage of
+			// adapter reset state machine.
+                       	printk("megaraid_sas: FW state detected, current:%x, reset stage:%d\n", fw_state, instance->adprecovery);
+			schedule_work(&instance->work_init);
+		}
+		else {
+			printk("megaraid_sas: fw state while internal state changes, state:%x, disableOCR=%x\n",
+				fw_state, instance->disableOnlineCtrlReset);
+		}
+		return IRQ_HANDLED;
+	}
+
+	// Schedule the tasklet for cmd completion
 	tasklet_schedule(&instance->isr_tasklet);
-out_done:
 	return IRQ_HANDLED;
 }
 
@@ -1917,8 +2452,20 @@ out_done:
  */
 static irqreturn_t megasas_isr(int irq, void *devp, struct pt_regs *regs)
 {
-	return megasas_deplete_reply_queue((struct megasas_instance *)devp,
-					   DID_OK);
+	struct megasas_instance *instance;
+	unsigned long flags;
+	irqreturn_t	rc;
+      
+	if ( atomic_read( &(( (struct megasas_instance *)devp)->fw_reset_no_pci_access )) )
+                return IRQ_HANDLED;
+
+	instance = (struct megasas_instance *)devp;
+
+	spin_lock_irqsave(&instance->hba_lock, flags);
+	rc =  megasas_deplete_reply_queue(instance, DID_OK);
+	spin_unlock_irqrestore(&instance->hba_lock, flags);
+
+	return rc;
 }
 
 /**
@@ -1960,13 +2507,17 @@ megasas_transition_to_ready(struct megasas_instance* instance)
 			/*
 			 * Set the CLR bit in inbound doorbell
 			 */
-			if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0073SKINNY) ||
-				(instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0071SKINNY))
-			{
-				writel(MFI_INIT_CLEAR_HANDSHAKE|MFI_INIT_HOTPLUG,
+			if ((instance->pdev->device ==
+				PCI_DEVICE_ID_LSI_SAS0073SKINNY) ||
+				(instance->pdev->device ==
+				PCI_DEVICE_ID_LSI_SAS0071SKINNY)) {
+
+				writel(
+				  MFI_INIT_CLEAR_HANDSHAKE|MFI_INIT_HOTPLUG,
 					&instance->reg_set->reserved_0[0]);
 			} else {
-				writel(MFI_INIT_CLEAR_HANDSHAKE|MFI_INIT_HOTPLUG,
+				writel(
+				    MFI_INIT_CLEAR_HANDSHAKE|MFI_INIT_HOTPLUG,
 					&instance->reg_set->inbound_doorbell);
 			}
 
@@ -1975,9 +2526,10 @@ megasas_transition_to_ready(struct megasas_instance* instance)
 			break;
 
 		case MFI_STATE_BOOT_MESSAGE_PENDING:
-			if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0073SKINNY) ||
-				(instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0071SKINNY))
-			{
+			if ((instance->pdev->device ==
+				PCI_DEVICE_ID_LSI_SAS0073SKINNY) ||
+			(instance->pdev->device ==
+				PCI_DEVICE_ID_LSI_SAS0071SKINNY)) {
 				writel(MFI_INIT_HOTPLUG,
 					&instance->reg_set->reserved_0[0]);
 			} else 
@@ -1993,12 +2545,15 @@ megasas_transition_to_ready(struct megasas_instance* instance)
 			 * Bring it to READY state; assuming max wait 10 secs
 			 */
 			instance->instancet->disable_intr(instance->reg_set);
-			if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0073SKINNY) ||
-				(instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0071SKINNY))
-			{
-				writel(MFI_RESET_FLAGS, &instance->reg_set->reserved_0[0]);
+			if ((instance->pdev->device ==
+				PCI_DEVICE_ID_LSI_SAS0073SKINNY) ||
+				(instance->pdev->device ==
+				PCI_DEVICE_ID_LSI_SAS0071SKINNY)) {
+				writel(MFI_RESET_FLAGS,
+					&instance->reg_set->reserved_0[0]);
 			} else 
-				writel(MFI_RESET_FLAGS, &instance->reg_set->inbound_doorbell);
+				writel(MFI_RESET_FLAGS,
+					&instance->reg_set->inbound_doorbell);
 
 			max_wait = MEGASAS_RESET_WAIT_TIME;
 			cur_state = MFI_STATE_OPERATIONAL;
@@ -2049,7 +2604,8 @@ megasas_transition_to_ready(struct megasas_instance* instance)
 		for (i = 0; i < (max_wait * 1000); i++) {
 			fw_state = instance->instancet->read_fw_status_reg(instance->reg_set) &  
 					MFI_STATE_MASK ;
-			curr_abs_state = instance->instancet->read_fw_status_reg(instance->reg_set);
+		curr_abs_state =
+		instance->instancet->read_fw_status_reg(instance->reg_set);
 
 			if (abs_state == curr_abs_state) {
 				msleep(1);
@@ -2065,7 +2621,7 @@ megasas_transition_to_ready(struct megasas_instance* instance)
 			       "in %d secs\n", fw_state, max_wait);
 			return -ENODEV;
 		}
-	};
+	}
  	printk(KERN_INFO "megasas: FW now in Ready state\n");
 
 	return 0;
@@ -2137,7 +2693,7 @@ static int megasas_create_frame_pool(struct megasas_instance *instance)
 	 */
 	sge_sz = (IS_DMA64) ? sizeof(struct megasas_sge64) :
 	    sizeof(struct megasas_sge32);
-		
+
 	if (instance->flag_ieee) {
 		sge_sz = sizeof(struct megasas_sge_skinny);
 	}
@@ -2147,6 +2703,7 @@ static int megasas_create_frame_pool(struct megasas_instance *instance)
 	 */
 	sgl_sz = sge_sz * instance->max_num_sge;
 	frame_count = (sgl_sz + MEGAMFI_FRAME_SIZE - 1) / MEGAMFI_FRAME_SIZE;
+	frame_count = 15;
 
 	/*
 	 * We need one extra frame for the MFI command
@@ -2204,6 +2761,12 @@ static int megasas_create_frame_pool(struct megasas_instance *instance)
 		}
 
 		cmd->frame->io.context = cmd->index;
+
+		/*
+		 * Initialize pad_0 to 0, otherwise it could corrupt
+		 * the value of context and cause FW crash
+		 */
+		cmd->frame->io.pad_0 = 0;
 	}
 
 	return 0;
@@ -2295,6 +2858,7 @@ static int megasas_alloc_cmds(struct megasas_instance *instance)
 		cmd = instance->cmd_list[i];
 		memset(cmd, 0, sizeof(struct megasas_cmd));
 		cmd->index = i;
+		cmd->scmd = NULL;
 		cmd->instance = instance;
 
 		list_add_tail(&cmd->list, &instance->cmd_pool);
@@ -2311,10 +2875,10 @@ static int megasas_alloc_cmds(struct megasas_instance *instance)
 	return 0;
 }
 
-/**
- * megasas_get_pd_list_info -   Returns FW's pd_list structure
- * @instance:                           Adapter soft state
- * @pd_list:                            pd_list structure
+/*
+ * megasas_get_pd_list_info -	Returns FW's pd_list structure
+ * @instance:				Adapter soft state
+ * @pd_list:				pd_list structure
  *
  * Issues an internal command (DCMD) to get the FW's controller PD
  * list structure.  This information is mainly used to find out SYSTEM
@@ -2323,85 +2887,90 @@ static int megasas_alloc_cmds(struct megasas_instance *instance)
 static int
 megasas_get_pd_list(struct megasas_instance *instance)
 {
-        int ret = 0, pd_index = 0;
-        struct megasas_cmd *cmd;
-        struct megasas_dcmd_frame *dcmd;
-        struct MR_PD_LIST *ci;
-        struct MR_PD_ADDRESS *pd_addr;
-        dma_addr_t ci_h = 0;
-
-        cmd = megasas_get_cmd(instance);
-
-        if (!cmd) {
-                printk(KERN_DEBUG "megasas (get_pd_list): Failed to get cmd\n");
-                return -ENOMEM;
-        }
+	int ret = 0, pd_index = 0;
+	struct megasas_cmd *cmd;
+	struct megasas_dcmd_frame *dcmd;
+	struct MR_PD_LIST *ci;
+	struct MR_PD_ADDRESS *pd_addr;
+	dma_addr_t ci_h = 0;
 
-        dcmd = &cmd->frame->dcmd;
+	cmd = megasas_get_cmd(instance);
 
-        ci = pci_alloc_consistent(instance->pdev,
-                                  MEGASAS_MAX_PD * sizeof(struct MR_PD_LIST), &ci_h);
+	if (!cmd) {
+		printk(KERN_DEBUG "megasas (get_pd_list): Failed to get cmd\n");
+		return -ENOMEM;
+	}
 
-        if (!ci) {
-                printk(KERN_DEBUG "Failed to alloc mem for pd_list\n");
-                megasas_return_cmd(instance, cmd);
-                return -ENOMEM;
-        }
+	dcmd = &cmd->frame->dcmd;
 
-        memset(ci, 0, sizeof(*ci));
-        memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
-
-        dcmd->mbox.b[0] = MR_PD_QUERY_TYPE_EXPOSED_TO_HOST;
-        dcmd->mbox.b[1] = 0;
-        dcmd->cmd = MFI_CMD_DCMD;
-        dcmd->cmd_status = 0xFF;
-        dcmd->sge_count = 1;
-        dcmd->flags = MFI_FRAME_DIR_READ;
-        dcmd->timeout = 0;
-        dcmd->data_xfer_len = MEGASAS_MAX_PD * sizeof(struct MR_PD_LIST);
-        dcmd->opcode = MR_DCMD_PD_LIST_QUERY;
-        dcmd->sgl.sge32[0].phys_addr = ci_h;
-        dcmd->sgl.sge32[0].length = MEGASAS_MAX_PD * sizeof(struct MR_PD_LIST);
-
-        if (!megasas_issue_polled(instance, cmd)) {
-                ret = 0;
-
-        } else {
-                ret = -1;
-        }
+	ci = pci_alloc_consistent(instance->pdev,
+				  MEGASAS_MAX_PD * sizeof(struct MR_PD_LIST), &ci_h);
 
-        /*
-        * the following function will get the instance PD LIST.
-        */
+	if (!ci) {
+		printk(KERN_DEBUG "Failed to alloc mem for pd_list\n");
+		megasas_return_cmd(instance, cmd);
+		return -ENOMEM;
+	}
+
+	memset(ci, 0, sizeof(*ci));
+	memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
+
+	dcmd->mbox.b[0] = MR_PD_QUERY_TYPE_EXPOSED_TO_HOST;
+	dcmd->mbox.b[1] = 0;
+	dcmd->cmd = MFI_CMD_DCMD;
+	dcmd->cmd_status = 0xFF;
+	dcmd->sge_count = 1;
+	dcmd->flags = MFI_FRAME_DIR_READ;
+	dcmd->timeout = 0;
+	dcmd->pad_0 = 0;
+	dcmd->data_xfer_len = MEGASAS_MAX_PD * sizeof(struct MR_PD_LIST);
+	dcmd->opcode = MR_DCMD_PD_LIST_QUERY;
+	dcmd->sgl.sge32[0].phys_addr = ci_h;
+	dcmd->sgl.sge32[0].length = MEGASAS_MAX_PD * sizeof(struct MR_PD_LIST);
+
+	if (!megasas_issue_polled(instance, cmd)) {
+		ret = 0;
 
-        pd_addr = ci->addr;
+	} else {
+		ret = -1;
+	}
 
-        if ( ret == 0 &&
-                (ci->count < (MEGASAS_MAX_PD_CHANNELS * MEGASAS_MAX_DEV_PER_CHANNEL))){
+	/*
+	* the following function will get the instance PD LIST.
+	*/
 
-                memset(instance->pd_list, 0, MEGASAS_MAX_PD * sizeof(struct megasas_pd_list));
+	pd_addr = ci->addr;
 
-                for (pd_index = 0; pd_index < ci->count; pd_index++) {
+	if ( ret == 0 &&
+		(ci->count <
+		  (MEGASAS_MAX_PD_CHANNELS * MEGASAS_MAX_DEV_PER_CHANNEL))) {
 
-                        instance->pd_list[pd_addr->deviceId].tid        =pd_addr->deviceId;
-                        instance->pd_list[pd_addr->deviceId].driveType  =pd_addr->scsiDevType;
-                        instance->pd_list[pd_addr->deviceId].driveState =MR_PD_STATE_SYSTEM;
+		memset(instance->pd_list, 0,
+			MEGASAS_MAX_PD * sizeof(struct megasas_pd_list));
 
-                        pd_addr++;
+		for (pd_index = 0; pd_index < ci->count; pd_index++) {
 
-                }
+			instance->pd_list[pd_addr->deviceId].tid	=
+							pd_addr->deviceId;
+			instance->pd_list[pd_addr->deviceId].driveType	=
+							pd_addr->scsiDevType;
+			instance->pd_list[pd_addr->deviceId].driveState	=
+							MR_PD_STATE_SYSTEM;
 
-        }
+			pd_addr++;
+		}
+
+	}
 
-	pci_free_consistent(instance->pdev, MEGASAS_MAX_PD * sizeof(struct MR_PD_LIST),
+	pci_free_consistent(instance->pdev,
+				MEGASAS_MAX_PD * sizeof(struct MR_PD_LIST),
 				ci, ci_h); 
-		
 
-        megasas_return_cmd(instance, cmd);
 
-        return ret;
-}
+	megasas_return_cmd(instance, cmd);
 
+	return ret;
+}
 /**
  * megasas_get_ld_list_info -	Returns FW's ld_list structure
  * @instance:				Adapter soft state
@@ -2462,7 +3031,7 @@ megasas_get_ld_list(struct megasas_instance *instance)
 	* the following function will get the instance PD LIST.
 	*/
 
-	if ( (ret == 0) && (ci->ldCount < (MAX_LOGICAL_DRIVES))){
+	if ( (ret == 0) && (ci->ldCount <= (MAX_LOGICAL_DRIVES))){
 		
 		memset(instance->ld_ids, 0xff, MEGASAS_MAX_LD_IDS);
 
@@ -2484,6 +3053,7 @@ megasas_get_ld_list(struct megasas_instance *instance)
 	return ret;
 }
 
+
 /**
  * megasas_get_controller_info -	Returns FW's controller structure
  * @instance:				Adapter soft state
@@ -2588,7 +3158,7 @@ megasas_issue_init_mfi(struct megasas_instance *instance)
 	memset(init_frame, 0, MEGAMFI_FRAME_SIZE);
 	memset(initq_info, 0, sizeof(struct megasas_init_queue_info));
 	init_frame->context = context;
-
+	
 	initq_info->reply_queue_entries = instance->max_fw_cmds + 1;
 	initq_info->reply_queue_start_phys_addr_lo = instance->reply_queue_h;
 
@@ -2600,12 +3170,12 @@ megasas_issue_init_mfi(struct megasas_instance *instance)
 	init_frame->queue_info_new_phys_addr_lo = initq_info_h;
 
 	init_frame->data_xfer_len = sizeof(struct megasas_init_queue_info);
-
+	
 	/*
-	 * disable the intr before firing the init frame to FW
-	 */
+	 * disable the intr before firing the init frame to FW 
+	 */	
 	instance->instancet->disable_intr(instance->reg_set);
-
+	
 	/*
 	 * Issue the init frame in polled mode
 	 */
@@ -2620,8 +3190,8 @@ megasas_issue_init_mfi(struct megasas_instance *instance)
 
 	return 0;
 
-fail_fw_init:
-	return -EINVAL;
+	fail_fw_init:
+		return -EINVAL;
 }
 
 /**
@@ -2630,7 +3200,6 @@ fail_fw_init:
  * @timer:		timer object to be initialized
  * @fn:			timer function
  * @interval:		time interval between timer function call
- *
  */
 static inline void
 megasas_start_timer(struct megasas_instance *instance,
@@ -2648,13 +3217,13 @@ megasas_start_timer(struct megasas_instance *instance,
  * megasas_io_completion_timer - Timer fn
  * @instance_addr:	Address of adapter soft state
  *
- * Schedules tasklet for cmd completion
+ * Schedules tasklet for cmd completion 
  * if poll_mode_io is set
  */
 static void
 megasas_io_completion_timer(unsigned long instance_addr)
 {
-	struct megasas_instance *instance =
+	struct megasas_instance *instance = 
 			(struct megasas_instance *)instance_addr;
 
 	if (atomic_read(&instance->fw_outstanding))
@@ -2689,10 +3258,15 @@ static int megasas_init_mfi(struct megasas_instance *instance)
 	if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS1078GEN2) ||
 		(instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0071SKINNY) ||
 		(instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0073SKINNY) ||
-		(instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0079GEN2)) {
+		(instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0079GEN2))
+	{
 		instance->base_addr = pci_resource_start(instance->pdev, 1);
+			printk("\n gen2: instance->base_addr = %x",
+				(unsigned int)instance->base_addr);
 	} else {
 		instance->base_addr = pci_resource_start(instance->pdev, 0);
+			printk("\n ppc: instance->base_addr = %x", 
+				(unsigned int)instance->base_addr);
 	}
 
 	if (pci_request_selected_regions(instance->pdev,
@@ -2713,8 +3287,8 @@ static int megasas_init_mfi(struct megasas_instance *instance)
 
 	switch(instance->pdev->device)
 	{
-		case PCI_DEVICE_ID_LSI_SAS1078R:
-		case PCI_DEVICE_ID_LSI_SAS1078DE:
+		case PCI_DEVICE_ID_LSI_SAS1078R:	
+		case PCI_DEVICE_ID_LSI_SAS1078DE:	
 			instance->instancet = &megasas_instance_template_ppc;
 			break;
 		case PCI_DEVICE_ID_LSI_SAS1078GEN2:
@@ -2742,7 +3316,6 @@ static int megasas_init_mfi(struct megasas_instance *instance)
 	 * Get various operational parameters from status register
 	 */
 	instance->max_fw_cmds = instance->instancet->read_fw_status_reg(reg_set) & 0x00FFFF;
-	
 	/*
 	 * Reduce the max supported cmds by 1. This is to ensure that the
 	 * reply_q_sz (1 more than the max cmd that driver may send)
@@ -2781,6 +3354,13 @@ static int megasas_init_mfi(struct megasas_instance *instance)
 	if (megasas_issue_init_mfi(instance))
 		goto fail_fw_init;
 
+	instance->fw_support_ieee = 0; 
+	instance->fw_support_ieee = (instance->instancet->read_fw_status_reg(reg_set) & 0x04000000); 
+
+	printk("megasas_init_mfi: fw_support_ieee=%d", instance->fw_support_ieee);
+	if (instance->fw_support_ieee)
+		instance->flag_ieee = 1;
+	
 	/** for passthrough
 	* the following function will get the PD LIST.
 	*/
@@ -2809,20 +3389,20 @@ static int megasas_init_mfi(struct megasas_instance *instance)
 		    ctrl_info->max_strips_per_io;
 		max_sectors_2 = ctrl_info->max_request_size;
 
-		tmp_sectors = (max_sectors_1 < max_sectors_2)
-		    ? max_sectors_1 : max_sectors_2;
+		tmp_sectors = min_t(u32, max_sectors_1 , max_sectors_2);
+                instance->disableOnlineCtrlReset = ctrl_info->properties.OnOffProperties.disableOnlineCtrlReset;
 	}
-
+ 
 	instance->max_sectors_per_req = instance->max_num_sge *
-						PAGE_SIZE / 512;
+		    PAGE_SIZE / 512;
 	if (tmp_sectors && (instance->max_sectors_per_req > tmp_sectors))
 		instance->max_sectors_per_req = tmp_sectors;
 
 	kfree(ctrl_info);
 
         /*
-	 * Setup tasklet for cmd completion
-	 */
+	* Setup tasklet for cmd completion
+	*/
 
 	tasklet_init(&instance->isr_tasklet, megasas_complete_cmd_dpc,
                         (unsigned long)instance);
@@ -2992,6 +3572,8 @@ megasas_register_aen(struct megasas_instance *instance, u32 seq_num,
 			 * Previously issued event registration includes
 			 * current request. Nothing to do.
 			 */
+			printk(KERN_INFO "%s[%d]: already registered\n",
+				__FUNCTION__, instance->host->host_no);
 			return 0;
 		} else {
 			curr_aen.members.locale |= prev_aen.members.locale;
@@ -3035,13 +3617,14 @@ megasas_register_aen(struct megasas_instance *instance, u32 seq_num,
 	dcmd->data_xfer_len = sizeof(struct megasas_evt_detail);
 	dcmd->opcode = MR_DCMD_CTRL_EVENT_WAIT;
 	dcmd->mbox.w[0] = seq_num;
+        instance->last_seq_num = seq_num;
 	dcmd->mbox.w[1] = curr_aen.word;
 	dcmd->sgl.sge32[0].phys_addr = (u32) instance->evt_detail_h;
 	dcmd->sgl.sge32[0].length = sizeof(struct megasas_evt_detail);
 	
 	if ( instance->aen_cmd != NULL ) {
-               megasas_return_cmd(instance, cmd);
-               return 0; 
+		megasas_return_cmd(instance, cmd);
+		return 0;
 	}
 
 	/*
@@ -3054,7 +3637,8 @@ megasas_register_aen(struct megasas_instance *instance, u32 seq_num,
 	/*
 	 * Issue the aen registration frame
 	 */
-	instance->instancet->fire_cmd(instance, cmd->frame_phys_addr ,0,instance->reg_set);
+	instance->instancet->fire_cmd(instance,
+			cmd->frame_phys_addr, 0, instance->reg_set);
 
 	return 0;
 }
@@ -3102,9 +3686,11 @@ static int megasas_io_attach(struct megasas_instance *instance)
 	host->unique_id = instance->unique_id;
 	if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0073SKINNY) ||
 		(instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0071SKINNY)) {
-		host->can_queue = instance->max_fw_cmds - MEGASAS_SKINNY_INT_CMDS;
+		host->can_queue =
+			instance->max_fw_cmds - MEGASAS_SKINNY_INT_CMDS;
 	} else 
-		host->can_queue = instance->max_fw_cmds - MEGASAS_INT_CMDS;
+		host->can_queue =
+			instance->max_fw_cmds - MEGASAS_INT_CMDS;
 	host->this_id = instance->init_id;
 	host->sg_tablesize = instance->max_num_sge;
 	host->max_sectors = instance->max_sectors_per_req;
@@ -3198,6 +3784,8 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
 	instance = (struct megasas_instance *)host->hostdata;
 	memset(instance, 0, sizeof(*instance));
 
+	atomic_set( &instance->fw_reset_no_pci_access, 0 );
+
 	instance->producer = pci_alloc_consistent(pdev, sizeof(u32),
 						  &instance->producer_h);
 	instance->consumer = pci_alloc_consistent(pdev, sizeof(u32),
@@ -3212,7 +3800,10 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
 	*instance->producer = 0;
 	*instance->consumer = 0;
 	instance->flag_ieee = 0;
-	megasas_poll_wait_aen = 0;	
+	instance->ev = NULL;
+ 	instance->issuepend_done = 1;
+	instance->adprecovery = MEGASAS_HBA_OPERATIONAL;
+	megasas_poll_wait_aen = 0;
 
 	instance->evt_detail = pci_alloc_consistent(pdev,
 						    sizeof(struct
@@ -3229,6 +3820,7 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
 	 * Initialize locks and queues
 	 */
 	INIT_LIST_HEAD(&instance->cmd_pool);
+	INIT_LIST_HEAD(&instance->internal_reset_pending_q);
 
 	atomic_set(&instance->fw_outstanding,0);
 
@@ -3236,12 +3828,12 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
 	init_waitqueue_head(&instance->abort_cmd_wait_q);
 
 	spin_lock_init(&instance->cmd_pool_lock);
-	spin_lock_init(&instance->fire_lock);
+	spin_lock_init(&instance->hba_lock);
 	spin_lock_init(&instance->completion_lock);
-
-	sema_init(&instance->aen_mutex, 1);
 	spin_lock_init(&poll_aen_lock);
 
+	sema_init(&instance->aen_mutex, 1);
+	
 	/*
 	 * Initialize PCI related and misc parameters
 	 */
@@ -3254,14 +3846,16 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
 		(instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0071SKINNY)) {
 		instance->flag_ieee = 1;
 		sema_init(&instance->ioctl_sem, MEGASAS_SKINNY_INT_CMDS);
-	
 	} else 
 		sema_init(&instance->ioctl_sem, MEGASAS_INT_CMDS);
 	
 	megasas_dbg_lvl = 0;
 	instance->flag = 0;
-	instance->unload = 1;
-	instance->last_time = 0;
+	instance->unload=1;
+	instance->last_time=0;
+	instance->disableOnlineCtrlReset = 1;
+
+	INIT_WORK(&instance->work_init, process_fw_state_change_wq, instance);
 
 	/*
 	 * Initialize MFI Firmware
@@ -3306,8 +3900,8 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
 	if (megasas_io_attach(instance))
 		goto fail_io_attach;
 
-	instance->unload = 0;
-	
+	instance->unload = 0 ;
+
 	return 0;
 
       fail_start_aen:
@@ -3354,6 +3948,9 @@ static void megasas_flush_cache(struct megasas_instance *instance)
 	struct megasas_cmd *cmd;
 	struct megasas_dcmd_frame *dcmd;
 
+	if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR)
+		return;
+
 	cmd = megasas_get_cmd(instance);
 
 	if (!cmd)
@@ -3391,6 +3988,9 @@ static void megasas_shutdown_controller(struct megasas_instance *instance,
 	struct megasas_cmd *cmd;
 	struct megasas_dcmd_frame *dcmd;
 
+	if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR)
+		return;
+
 	cmd = megasas_get_cmd(instance);
 
 	if (!cmd)
@@ -3423,7 +4023,7 @@ static void megasas_shutdown_controller(struct megasas_instance *instance,
 /**
  * megasas_suspend -	driver suspend entry point
  * @pdev:		PCI device structure
- * @state:		state
+ * @state:		PCI power state to suspend routine
  */
 static int __devinit
 megasas_suspend(struct pci_dev *pdev, pm_message_t state)
@@ -3432,20 +4032,30 @@ megasas_suspend(struct pci_dev *pdev, pm_message_t state)
 	struct megasas_instance *instance;
 
 	instance = pci_get_drvdata(pdev);
-	instance->unload = 1;
 	host = instance->host;
+	instance->unload = 1;
 
 	if (poll_mode_io)
 		del_timer_sync(&instance->io_completion_timer);
 
 	megasas_flush_cache(instance);
 	megasas_shutdown_controller(instance, MR_DCMD_HIBERNATE_SHUTDOWN);
+
+	/* cancel the delayed work if this work still in queue */
+	if (instance->ev != NULL) {
+		struct megasas_aen_event *ev = instance->ev;
+		cancel_delayed_work(&ev->hotplug_work);
+		flush_scheduled_work();
+		instance->ev = NULL;
+	}
+
 	tasklet_kill(&instance->isr_tasklet);
 
-	pci_set_drvdata(instance->pdev, instance);
+	pci_set_drvdata(instance->pdev, instance); 
 	instance->instancet->disable_intr(instance->reg_set);
 	free_irq(instance->pdev->irq, instance);
 
+	scsi_host_put(host);
 	pci_save_state(pdev);
 	pci_disable_device(pdev);
 
@@ -3464,7 +4074,7 @@ megasas_resume(struct pci_dev *pdev)
 	int rval;
 	struct Scsi_Host *host;
 	struct megasas_instance *instance;
-
+	
 	instance = pci_get_drvdata(pdev);
 	host = instance->host;
 	pci_set_power_state(pdev, PCI_D0);
@@ -3477,7 +4087,7 @@ megasas_resume(struct pci_dev *pdev)
 	rval = pci_enable_device_mem(pdev);
 
 	if (rval) {
-		printk(KERN_INFO "megasas: Enable device failed\n");
+		printk(KERN_ERR "megasas: Enable device failed\n");
 		return rval;
 	}
 
@@ -3493,7 +4103,7 @@ megasas_resume(struct pci_dev *pdev)
 	*instance->producer = 0;
 	*instance->consumer = 0;
 
-	atomic_set(&instance->fw_outstanding, 0);
+	atomic_set(&instance->fw_outstanding,0);
 
 	/*
 	 * We expect the FW state to be READY
@@ -3505,19 +4115,24 @@ megasas_resume(struct pci_dev *pdev)
 		goto fail_init_mfi;
 
 	tasklet_init(&instance->isr_tasklet, megasas_complete_cmd_dpc,
-		(unsigned long)instance);
+                        (unsigned long)instance);	
 	/*
 	 * Register IRQ
 	 */
 	if (request_irq(pdev->irq, megasas_isr, IRQF_SHARED,
-		"megasas", instance)) {
-		printk(KERN_DEBUG "megasas: Failed to register IRQ\n");
+		"megasas",instance)) {
+		printk(KERN_ERR "megasas: Failed to register IRQ\n");
 		goto fail_irq;
 	}
 
 	instance->instancet->enable_intr(instance->reg_set);
 
 	/*
+	 * Store instance in PCI softstate
+	 */
+	pci_set_drvdata(pdev, instance);
+
+	/*
 	 * Initiate AEN (Asynchronous Event Notification)
 	 */
 	if (megasas_start_aen(instance))
@@ -3529,11 +4144,11 @@ megasas_resume(struct pci_dev *pdev)
 				megasas_io_completion_timer,
 				MEGASAS_COMPLETION_TIMER_INTERVAL);
 	instance->unload = 0;
-
-	return 0;
-
-fail_irq:
-fail_init_mfi:
+	
+	return 0;	
+	
+      fail_irq:
+      fail_init_mfi:
 
 	if (instance->evt_detail)
 		pci_free_consistent(pdev, sizeof(struct megasas_evt_detail),
@@ -3547,8 +4162,8 @@ fail_init_mfi:
 		pci_free_consistent(pdev, sizeof(u32), instance->consumer,
 				    instance->consumer_h);
 	scsi_host_put(host);
-fail_set_dma_mask:
-fail_ready_state:
+      fail_set_dma_mask:
+      fail_ready_state:
 	pci_disable_device(pdev);
 
 	return -ENODEV;
@@ -3558,7 +4173,6 @@ fail_ready_state:
 #define megasas_suspend	NULL
 #define megasas_resume	NULL
 #endif
-
 /**
  * megasas_detach_one -	PCI hot"un"plug entry point
  * @pdev:		PCI device structure
@@ -3571,7 +4185,6 @@ static void __devexit megasas_detach_one(struct pci_dev *pdev)
 
 	instance = pci_get_drvdata(pdev);
 	instance->unload = 1;
-		
 	host = instance->host;
 
 	if (poll_mode_io)
@@ -3580,6 +4193,15 @@ static void __devexit megasas_detach_one(struct pci_dev *pdev)
 	scsi_remove_host(instance->host);
 	megasas_flush_cache(instance);
 	megasas_shutdown_controller(instance, MR_DCMD_CTRL_SHUTDOWN);
+
+	/* cancel the delayed work if this work still in queue*/
+	if (instance->ev != NULL) {
+		struct megasas_aen_event *ev = instance->ev;
+		cancel_delayed_work(&ev->hotplug_work);
+		flush_scheduled_work();
+		instance->ev = NULL;
+	}
+
 	tasklet_kill(&instance->isr_tasklet);
 
 	/*
@@ -3631,7 +4253,6 @@ static void megasas_shutdown(struct pci_dev *pdev)
 	instance->unload = 1;
 	megasas_flush_cache(instance);
 	megasas_shutdown_controller(instance, MR_DCMD_CTRL_SHUTDOWN);
-
 }
 
 /**
@@ -3649,6 +4270,17 @@ static int megasas_mgmt_open(struct inode *inode, struct file *filep)
 }
 
 /**
+ * megasas_mgmt_release - char node "release" entry point
+ */
+static int megasas_mgmt_release(struct inode *inode, struct file *filep)
+{
+	filep->private_data = NULL;
+	fasync_helper(-1, filep, 0, &megasas_async_queue);
+
+	return 0;
+}
+
+/**
  * megasas_mgmt_fasync -	Async notifier registration from applications
  *
  * This function adds the calling process to a driver global queue. When an
@@ -3678,7 +4310,7 @@ static int megasas_mgmt_fasync(int fd, struct file *filep, int mode)
  /**
  * megasas_mgmt_poll -  char node "poll" entry point
  * */
-static unsigned int megasas_mgmt_poll(struct file *file, poll_table *wait)
+static unsigned int megasas_mgmt_poll(struct file *file, poll_table *wait) 
 {
  	unsigned int mask;
 	unsigned long flags;
@@ -3788,7 +4420,7 @@ megasas_mgmt_fw_ioctl(struct megasas_instance *instance,
 		}
 
 		sense_ptr =
-		    (unsigned long *) ((unsigned long)cmd->frame + ioc->sense_off);
+                   (unsigned long *) ((unsigned long)cmd->frame + ioc->sense_off);
 		*sense_ptr = sense_handle;
 	}
 
@@ -3816,19 +4448,19 @@ megasas_mgmt_fw_ioctl(struct megasas_instance *instance,
 	 */
 	if (ioc->sense_len) {
 		/*
-		 * sense_ptr points to the location that has the user
+		 * sense_buff points to the location that has the user
 		 * sense buffer address
 		 */
-		sense_ptr = (unsigned long *) ((unsigned long)ioc->frame.raw +
-				ioc->sense_off);
 
+               sense_ptr = (unsigned long *) ((unsigned long)ioc->frame.raw +
+					ioc->sense_off);
 		if (copy_to_user((void __user *)((unsigned long)(*sense_ptr)),
-				 sense, ioc->sense_len)) {
-			printk(KERN_ERR "megasas: Failed to copy out to user "
-					"sense data\n");
-			error = -EFAULT;
-			goto out;
-		}
+                                 sense, ioc->sense_len)) {
+                        printk(KERN_ERR "megasas: Failed to copy out to user"
+                               "sense data\n");
+                        error = -EFAULT;
+                        goto out;
+                }
 	}
 
 	/*
@@ -3863,6 +4495,9 @@ static int megasas_mgmt_ioctl_fw(struct file *file, unsigned long arg)
 	struct megasas_iocpacket *ioc;
 	struct megasas_instance *instance;
 	int error;
+	int i;
+	unsigned long flags;
+	u32 wait_time = MEGASAS_RESET_WAIT_TIME;
 
 	ioc = kmalloc(sizeof(*ioc), GFP_KERNEL);
 	if (!ioc)
@@ -3878,8 +4513,8 @@ static int megasas_mgmt_ioctl_fw(struct file *file, unsigned long arg)
 		error = -ENODEV;
 		goto out_kfree_ioc;
 	}
-		
-	if (instance->hw_crit_error == 1) {
+
+	if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR) {
 		printk("Controller in crit error\n");
 		error = -ENODEV;
 		goto out_kfree_ioc;
@@ -3897,10 +4532,38 @@ static int megasas_mgmt_ioctl_fw(struct file *file, unsigned long arg)
 		error = -ERESTARTSYS;
 		goto out_kfree_ioc;
 	}
+
+	// If HBA is undergoing a reset recovery, wait for that to complete
+	// before issuing this command
+	for (i = 0; i < wait_time; i++) {
+
+		spin_lock_irqsave(&instance->hba_lock, flags);
+		if (instance->adprecovery == MEGASAS_HBA_OPERATIONAL) {
+			spin_unlock_irqrestore(&instance->hba_lock, flags);
+			break;
+		}
+		spin_unlock_irqrestore(&instance->hba_lock, flags);
+
+		if (!(i % MEGASAS_RESET_NOTICE_INTERVAL)) {
+			printk(KERN_NOTICE "megasas: waiting for controller reset to finish\n");
+		}
+
+		msleep(1000);
+	}
+
+	spin_lock_irqsave(&instance->hba_lock, flags);
+	if (instance->adprecovery != MEGASAS_HBA_OPERATIONAL) {
+		spin_unlock_irqrestore(&instance->hba_lock, flags);
+		printk("megaraid_sas: %s timed out while waiting for HBA to recover.\n", __FUNCTION__);
+		error = -ENODEV;
+		goto out_kfree_ioc;
+	}
+	spin_unlock_irqrestore(&instance->hba_lock, flags);
+
 	error = megasas_mgmt_fw_ioctl(instance, user_ioc, ioc);
 	up(&instance->ioctl_sem);
 
-      out_kfree_ioc:
+out_kfree_ioc:
 	kfree(ioc);
 	return error;
 }
@@ -3910,6 +4573,9 @@ static int megasas_mgmt_ioctl_aen(struct file *file, unsigned long arg)
 	struct megasas_instance *instance;
 	struct megasas_aen aen;
 	int error;
+	int i;
+	unsigned long flags;
+	u32 wait_time = MEGASAS_RESET_WAIT_TIME;
 
 	if (file->private_data != file) {
 		printk(KERN_DEBUG "megasas: fasync_helper was not "
@@ -3925,15 +4591,41 @@ static int megasas_mgmt_ioctl_aen(struct file *file, unsigned long arg)
 	if (!instance)
 		return -ENODEV;
 
-	if (instance->hw_crit_error == 1) {
-		error = -ENODEV;
+	if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR) {
+		return -ENODEV;
+       }
+
+   if (instance->unload == 1) {
+           return -ENODEV;
+   }
+
+
+	down(&instance->aen_mutex);
+	for (i = 0; i < wait_time; i++) {
+
+		spin_lock_irqsave(&instance->hba_lock, flags);
+		if (instance->adprecovery == MEGASAS_HBA_OPERATIONAL) {
+			spin_unlock_irqrestore(&instance->hba_lock, flags);
+			break;
+		}
+		spin_unlock_irqrestore(&instance->hba_lock, flags);
+
+		if (!(i % MEGASAS_RESET_NOTICE_INTERVAL)) {
+			printk(KERN_NOTICE "megasas: waiting for controller reset to finish\n");
+		}
+
+		msleep(1000);
 	}
 
-	if (instance->unload == 1) {
+	spin_lock_irqsave(&instance->hba_lock, flags);
+	if (instance->adprecovery != MEGASAS_HBA_OPERATIONAL) {
+		spin_unlock_irqrestore(&instance->hba_lock, flags);
+		printk("megaraid_sas: %s timed out while waiting for HBA to recover.\n", __FUNCTION__);
+		up(&instance->aen_mutex);
 		return -ENODEV;
 	}
+	spin_unlock_irqrestore(&instance->hba_lock, flags);
 
-	down(&instance->aen_mutex);
 	error = megasas_register_aen(instance, aen.seq_num,
 				     aen.class_locale_word);
 	up(&instance->aen_mutex);
@@ -4026,6 +4718,7 @@ megasas_mgmt_compat_ioctl(struct file *file, unsigned int cmd,
 static const struct file_operations megasas_mgmt_fops = {
 	.owner = THIS_MODULE,
 	.open = megasas_mgmt_open,
+	.release = megasas_mgmt_release,
 	.fasync = megasas_mgmt_fasync,
 	.unlocked_ioctl = megasas_mgmt_ioctl,
 	.poll = megasas_mgmt_poll,
@@ -4072,16 +4765,25 @@ static DRIVER_ATTR(release_date, S_IRUGO, megasas_sysfs_show_release_date,
 static ssize_t
 megasas_sysfs_show_support_poll_for_event(struct device_driver *dd, char *buf)
 {
-	return sprintf(buf, "%u\n", support_poll_for_event);
+	return sprintf(buf,"%u\n",support_poll_for_event);
 }
 
 static DRIVER_ATTR(support_poll_for_event, S_IRUGO,
 			megasas_sysfs_show_support_poll_for_event, NULL);
 
 static ssize_t
+megasas_sysfs_show_support_device_change(struct device_driver *dd, char *buf)
+{
+	return sprintf(buf, "%u\n", support_device_change);
+}
+
+static DRIVER_ATTR(support_device_change, S_IRUGO,
+			megasas_sysfs_show_support_device_change, NULL);
+
+static ssize_t
 megasas_sysfs_show_dbg_lvl(struct device_driver *dd, char *buf)
 {
-	return sprintf(buf, "%u\n", megasas_dbg_lvl);
+	return sprintf(buf,"%u\n",megasas_dbg_lvl);
 }
 
 static ssize_t
@@ -4101,19 +4803,19 @@ static DRIVER_ATTR(dbg_lvl, S_IRUGO|S_IWUSR, megasas_sysfs_show_dbg_lvl,
 static ssize_t
 megasas_sysfs_show_poll_mode_io(struct device_driver *dd, char *buf)
 {
-	return sprintf(buf, "%u\n", poll_mode_io);
+	return sprintf(buf,"%u\n",poll_mode_io);
 }
 
 static ssize_t
-megasas_sysfs_set_poll_mode_io(struct device_driver *dd, const char *buf,
-				size_t count)
+megasas_sysfs_set_poll_mode_io(struct device_driver *dd,
+				const char *buf, size_t count)
 {
 	int retval = count;
 	int tmp = poll_mode_io;
 	int i;
 	struct megasas_instance *instance;
 
-	if (sscanf(buf, "%u", &poll_mode_io) < 1) {
+	if(sscanf(buf,"%u",&poll_mode_io) < 1){
 		printk(KERN_ERR "megasas: could not set poll_mode_io\n");
 		retval = -EINVAL;
 	}
@@ -4151,11 +4853,7 @@ megasas_sysfs_set_poll_mode_io(struct device_driver *dd, const char *buf,
 out:
 	return retval;
 }
-
-static DRIVER_ATTR(poll_mode_io, S_IRUGO|S_IWUSR,
-			megasas_sysfs_show_poll_mode_io,
-			megasas_sysfs_set_poll_mode_io);
-
+ 
 static void 
 megasas_aen_polling(void *arg)
 {
@@ -4172,16 +4870,16 @@ megasas_aen_polling(void *arg)
 	int error;
 
 	if (!instance) {
-		printk(KERN_ERR "%s: invalid instance!\n", __FUNCTION__);
+		printk(KERN_ERR "invalid instance!\n");
 		kfree(ev);
 		return;
 	}
+	instance->ev = NULL;
 	host = instance->host;
 
 	if (instance->evt_detail) {
 
 		switch (instance->evt_detail->code) {
-		printk("EVENT received: event_code=%x!\n", instance->evt_detail->code);
 
 		case MR_EVT_PD_INSERTED:
 			if(megasas_get_pd_list(instance) == 0) {
@@ -4195,8 +4893,9 @@ megasas_aen_polling(void *arg)
 							scsi_add_device(host, i, j, 0);
 						}
 					} 
-					if (sdev1)
+					if (sdev1) {
 						scsi_device_put(sdev1);
+					}
 							
 				}
 			}
@@ -4228,8 +4927,8 @@ megasas_aen_polling(void *arg)
 			doscan = 0;
 			break;
 
-		case MR_EVT_CFG_CLEARED:
 		case MR_EVT_LD_OFFLINE:
+		case MR_EVT_CFG_CLEARED:
 		case MR_EVT_LD_DELETED:
 			megasas_get_ld_list(instance);
 			for (i=0; i < MEGASAS_MAX_LD_CHANNELS; i++) {
@@ -4279,25 +4978,23 @@ megasas_aen_polling(void *arg)
 			break;
 		}
 	} else {
-		printk(KERN_ERR "%s[%d]: invalid evt_detail!\n",
-			__FUNCTION__, instance->host->host_no);
+		printk(KERN_ERR "invalid evt_detail!\n");
 		kfree(ev);
 		return;
 	}
 
-	if (doscan) { /*keep this incase we need to use*/
-		printk(KERN_INFO "%s[%d]: scanning ...\n",
-			__FUNCTION__, instance->host->host_no);
+	if (doscan) {
+		printk(KERN_INFO "scanning ...\n");
 		megasas_get_pd_list(instance);
 		for (i=0; i < MEGASAS_MAX_PD_CHANNELS; i++) {
 			for (j = 0; j < MEGASAS_MAX_DEV_PER_CHANNEL; j++) {
-				pd_index = (i * MEGASAS_MAX_DEV_PER_CHANNEL) + j;
+				pd_index = i*MEGASAS_MAX_DEV_PER_CHANNEL + j;
 				sdev1 = scsi_device_lookup(host, i, j, 0);
-				if (instance->pd_list[pd_index].driveState == MR_PD_STATE_SYSTEM) {
+				if (instance->pd_list[pd_index].driveState ==
+							MR_PD_STATE_SYSTEM) {
 					if (!sdev1) {
 						scsi_add_device(host, i, j, 0);
-					}
-					if (sdev1) {
+					} else {
 						scsi_device_put(sdev1);
 					}
 				} else {
@@ -4317,8 +5014,7 @@ megasas_aen_polling(void *arg)
 				if (instance->ld_ids[ld_index] != 0xff) {
 					if (!sdev1) {
 						scsi_add_device(host, i+2, j, 0);
-					}
-					if (sdev1) {
+					} else {
 						scsi_device_put(sdev1);
 					}
 				} else {
@@ -4334,9 +5030,7 @@ megasas_aen_polling(void *arg)
 
 	seq_num = instance->evt_detail->seq_num + 1; 
 
-	/*
-	 * Register AEN with FW for latest sequence number plus 1
-	 */
+	/* Register AEN with FW for latest sequence number plus 1 */
 	class_locale.members.reserved = 0;
 	class_locale.members.locale = MR_EVT_LOCALE_ALL;
 	class_locale.members.class = MR_EVT_CLASS_DEBUG;
@@ -4351,12 +5045,16 @@ megasas_aen_polling(void *arg)
 	up(&instance->aen_mutex);
 
 	if(error)
-		printk(KERN_ERR "%s[%d]: register aen failed error %x\n",
-			__FUNCTION__, instance->host->host_no, error);
-	kfree(ev);
+		printk(KERN_ERR "register aen failed error %x\n", error);
 
+	kfree(ev);
 }
 
+
+static DRIVER_ATTR(poll_mode_io, S_IRUGO|S_IWUSR,
+		megasas_sysfs_show_poll_mode_io,
+		megasas_sysfs_set_poll_mode_io);
+
 /**
  * megasas_init - Driver load entry point
  */
@@ -4371,8 +5069,8 @@ static int __init megasas_init(void)
 	       MEGASAS_EXT_VERSION);
 
 	support_poll_for_event = 2;
-
-
+	support_device_change = 1;
+	
 	memset(&megasas_mgmt_info, 0, sizeof(megasas_mgmt_info));
 
 	/*
@@ -4407,7 +5105,7 @@ static int __init megasas_init(void)
 		goto err_dcf_rel_date;
 
 	rval = driver_create_file(&megasas_pci_driver.driver,
-				&driver_attr_support_poll_for_event);
+				  &driver_attr_support_poll_for_event);
 	if (rval)
 		goto err_dcf_support_poll_for_event;
 
@@ -4420,17 +5118,26 @@ static int __init megasas_init(void)
 				  &driver_attr_poll_mode_io);
 	if (rval)
 		goto err_dcf_poll_mode_io;
+	rval = driver_create_file(&megasas_pci_driver.driver,
+				&driver_attr_support_device_change);
+	if (rval)
+		goto err_dcf_support_device_change;
 
 	return rval;
+err_dcf_support_device_change:
+	driver_remove_file(&megasas_pci_driver.driver,
+			  &driver_attr_poll_mode_io);
 err_dcf_poll_mode_io:
 	driver_remove_file(&megasas_pci_driver.driver,
 			   &driver_attr_dbg_lvl);
 err_dcf_dbg_lvl:
 	driver_remove_file(&megasas_pci_driver.driver,
 			&driver_attr_support_poll_for_event);
+
 err_dcf_support_poll_for_event:
 	driver_remove_file(&megasas_pci_driver.driver,
-			   &driver_attr_release_date);
+		  &driver_attr_release_date);
+
 err_dcf_rel_date:
 	driver_remove_file(&megasas_pci_driver.driver, &driver_attr_version);
 err_dcf_attr_ver:
@@ -4445,16 +5152,17 @@ err_pcidrv:
  */
 static void __exit megasas_exit(void)
 {
+ 	driver_remove_file(&megasas_pci_driver.driver,
+			   &driver_attr_poll_mode_io);
 	driver_remove_file(&megasas_pci_driver.driver,
-			&driver_attr_poll_mode_io);
-	driver_remove_file(&megasas_pci_driver.driver,
-			&driver_attr_dbg_lvl);
+			   &driver_attr_dbg_lvl);
 	driver_remove_file(&megasas_pci_driver.driver,
-			&driver_attr_support_poll_for_event);
+			   &driver_attr_support_poll_for_event);
 	driver_remove_file(&megasas_pci_driver.driver,
-			&driver_attr_release_date);
+			&driver_attr_support_device_change);
 	driver_remove_file(&megasas_pci_driver.driver,
-			&driver_attr_version);
+			   &driver_attr_release_date);
+	driver_remove_file(&megasas_pci_driver.driver, &driver_attr_version);
 
 	pci_unregister_driver(&megasas_pci_driver);
 	unregister_chrdev(megasas_mgmt_majorno, "megaraid_sas_ioctl");
diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h
index 966a1cd..402e529 100644
--- a/drivers/scsi/megaraid/megaraid_sas.h
+++ b/drivers/scsi/megaraid/megaraid_sas.h
@@ -2,7 +2,7 @@
  *
  *		Linux MegaRAID driver for SAS based RAID controllers
  *
- * Copyright (c) 2003-2005  LSI Corporation.
+ * Copyright (c) 2003-2005  LSI Logic Corporation.
  *
  *		This program is free software; you can redistribute it and/or
  *		modify it under the terms of the GNU General Public License
@@ -18,18 +18,18 @@
 /*
  * MegaRAID SAS Driver meta data
  */
-#define MEGASAS_VERSION				"00.00.04.17-RH1"
-#define MEGASAS_RELDATE				"Nov. 25, 2009"
-#define MEGASAS_EXT_VERSION			"Wed. Nov. 25, 11:41:51 PST 2009"
+#define MEGASAS_VERSION				"00.00.04.27-RH1"
+#define MEGASAS_RELDATE				"Mar. 09, 2010"
+#define MEGASAS_EXT_VERSION			"Tues. Mar. 09 14:13:02 EST 2010"
 
 /*
  * Device IDs
  */
 #define	PCI_DEVICE_ID_LSI_SAS1078R		0x0060
 #define	PCI_DEVICE_ID_LSI_SAS1078DE		0x007C
+#define	PCI_DEVICE_ID_LSI_VERDE_ZCR		0x0413
 #define	PCI_DEVICE_ID_LSI_SAS1078GEN2		0x0078
 #define	PCI_DEVICE_ID_LSI_SAS0079GEN2		0x0079
-#define	PCI_DEVICE_ID_LSI_VERDE_ZCR		0x0413
 #define	PCI_DEVICE_ID_LSI_SAS0073SKINNY		0x0073
 #define	PCI_DEVICE_ID_LSI_SAS0071SKINNY		0x0071
 
@@ -60,6 +60,7 @@
 #define MFI_STATE_READY				0xB0000000
 #define MFI_STATE_OPERATIONAL			0xC0000000
 #define MFI_STATE_FAULT				0xF0000000
+#define  MFI_RESET_REQUIRED			0x00000001
 
 #define MEGAMFI_FRAME_SIZE			64
 
@@ -73,6 +74,13 @@
  * HOTPLUG	: Resume from Hotplug
  * MFI_STOP_ADP	: Send signal to FW to stop processing
  */
+
+#define WRITE_SEQUENCE_OFFSET		(0x0000000FC) // I20
+#define HOST_DIAGNOSTIC_OFFSET		(0x000000F8)  // I20
+#define DIAG_WRITE_ENABLE			(0x00000080)
+#define DIAG_RESET_ADAPTER			(0x00000004)
+
+#define MFI_ADP_RESET				0x00000040
 #define MFI_INIT_ABORT				0x00000001
 #define MFI_INIT_READY				0x00000002
 #define MFI_INIT_MFIMODE			0x00000004
@@ -96,7 +104,7 @@
 #define MFI_FRAME_DIR_WRITE			0x0008
 #define MFI_FRAME_DIR_READ			0x0010
 #define MFI_FRAME_DIR_BOTH			0x0018
-#define MFI_FRAME_IEEE                         	0x0020
+#define MFI_FRAME_IEEE				0x0020
 
 /*
  * Definition for cmd_status
@@ -285,6 +293,7 @@ enum MR_EVT_ARGS {
 	MR_EVT_ARGS_PD_PATHINFO,
 	MR_EVT_ARGS_PD_POWER_STATE,
 	MR_EVT_ARGS_GENERIC,
+
 };
 
 /*
@@ -319,8 +328,8 @@ enum MR_PD_STATE {
     MR_PD_STATE_ONLINE              = 0x18,
     MR_PD_STATE_COPYBACK            = 0x20,
     MR_PD_STATE_SYSTEM              = 0x40,
- };
-
+};
+ 
  /*
  * defines the physical drive address structure
  */
@@ -348,6 +357,22 @@ struct MR_PD_ADDRESS {
     u64     sasAddr[2];
 } __attribute__ ((packed));
 
+/*
+ * defines the physical drive list structure
+ */
+struct MR_PD_LIST {
+    u32             size;
+    u32             count;
+    struct MR_PD_ADDRESS   addr[1];
+} __attribute__ ((packed));
+
+
+struct megasas_pd_list {
+    u16             tid;
+    u8             driveType;
+    u8             driveState;
+} __attribute__ ((packed));
+
  /*
  * defines the logical drive reference structure
  */
@@ -376,22 +401,6 @@ struct MR_LD_LIST {
 } __attribute__ ((packed));
 
 /*
- * defines the physical drive list structure
- */
-struct MR_PD_LIST {
-    u32             size;
-    u32             count;
-    struct MR_PD_ADDRESS   addr[1];
-} __attribute__ ((packed));
-
-
-struct megasas_pd_list {
-    u16             tid;
-    u8             driveType;
-    u8             driveState;
-} __attribute__ ((packed));
-
-/*
  * SAS controller properties
  */
 struct megasas_ctrl_prop {
@@ -417,7 +426,45 @@ struct megasas_ctrl_prop {
 	u16 ecc_bucket_leak_rate;
 	u8 restore_hotspare_on_insertion;
 	u8 expose_encl_devices;
-	u8 reserved[38];
+        u8      maintainPdFailHistory;
+    u8      disallowHostRequestReordering;
+    u8      abortCCOnError;                 // set TRUE to abort CC on detecting an inconsistency
+    u8      loadBalanceMode;                // load balance mode (MR_LOAD_BALANCE_MODE)
+    u8      disableAutoDetectBackplane;     // 0 - use auto detect logic of backplanes like SGPIO, i2c SEP using h/w mechansim like GPIO pins
+                                            // 1 - disable auto detect SGPIO,
+                                            // 2 - disable i2c SEP auto detect
+                                            // 3 - disable both auto detect
+    u8      snapVDSpace;                    // % of source LD to be reserved for a VDs snapshot in snapshot repository, for metadata and user data
+                                            // 1=5%, 2=10%, 3=15% and so on
+
+    /*
+     * Add properties that can be controlled by a bit in the following structure.
+     */
+    struct {
+        u32     copyBackDisabled            : 1;     // set TRUE to disable copyBack (0=copback enabled)
+        u32     SMARTerEnabled              : 1;
+        u32     prCorrectUnconfiguredAreas  : 1;
+        u32     useFdeOnly                  : 1;
+        u32     disableNCQ                  : 1;
+       u32     SSDSMARTerEnabled           : 1;
+        u32     SSDPatrolReadEnabled        : 1;
+        u32     enableSpinDownUnconfigured  : 1;
+        u32     autoEnhancedImport          : 1;
+        u32     enableSecretKeyControl      : 1;
+        u32     disableOnlineCtrlReset      : 1;
+        u32     allowBootWithPinnedCache    : 1;
+        u32     disableSpinDownHS           : 1;
+        u32     enableJBOD                  : 1;
+        u32     reserved                    :18;
+    } OnOffProperties;
+    u8      autoSnapVDSpace;                // % of source LD to be reserved for auto snapshot in snapshot repository, for metadata and user data
+                                            // 1=5%, 2=10%, 3=15% and so on
+    u8      viewSpace;                      // snapshot writeable VIEWs capacity as a % of source LD capacity. 0=READ only
+                                            // 1=5%, 2=10%, 3=15% and so on
+        
+    u16     spinDownTime;                   // # of idle minutes before device is spun down (0=use FW defaults)
+
+    u8      reserved[24];
 
 } __attribute__ ((packed));
 
@@ -680,14 +727,16 @@ struct megasas_ctrl_info {
 #define MEGASAS_DEFAULT_CMD_PER_LUN		128
 #define MEGASAS_MAX_PD				(MEGASAS_MAX_PD_CHANNELS * \
 							MEGASAS_MAX_DEV_PER_CHANNEL)
-
 #define MEGASAS_MAX_LD_IDS			(MEGASAS_MAX_LD_CHANNELS * \
 							MEGASAS_MAX_DEV_PER_CHANNEL)
+
+
+
 #define MEGASAS_DBG_LVL				1
 #define MEGASAS_FW_BUSY				1
 /* Frame Type */
-#define IO_FRAME					0
-#define PTHRU_FRAME					1
+#define IO_FRAME				0
+#define PTHRU_FRAME				1
 
 /*
  * When SCSI mid-layer calls driver's reset routine, driver waits for
@@ -699,7 +748,9 @@ struct megasas_ctrl_info {
 #define MEGASAS_RESET_WAIT_TIME			180
 #define MEGASAS_INTERNAL_CMD_WAIT_TIME		180
 #define	MEGASAS_RESET_NOTICE_INTERVAL		5
+
 #define MEGASAS_IOCTL_CMD			0
+
 #define MEGASAS_DEFAULT_CMD_TIMEOUT		90
 
 /*
@@ -718,15 +769,24 @@ struct megasas_ctrl_info {
  */
 #define IS_DMA64				(sizeof(dma_addr_t) == 8)
 
+#define MFI_XSCALE_OMR0_CHANGE_INTERRUPT            0x00000001  /* MFI state change interrupt */
+
+#define MFI_INTR_FLAG_REPLY_MESSAGE                 0x00000001
+#define MFI_INTR_FLAG_FIRMWARE_STATE_CHANGE         0x00000002
+#define MFI_G2_OUTBOUND_DOORBELL_CHANGE_INTERRUPT 0x00000004  /* MFI state change interrrupt */
+
 #define MFI_OB_INTR_STATUS_MASK			0x00000002
 #define MFI_POLL_TIMEOUT_SECS			60
 #define MEGASAS_COMPLETION_TIMER_INTERVAL	(HZ/10)
 
 #define MFI_REPLY_1078_MESSAGE_INTERRUPT	0x80000000
-#define MFI_REPLY_GEN2_MESSAGE_INTERRUPT       0x00000001
-#define MFI_GEN2_ENABLE_INTERRUPT_MASK         (0x00000001 | 0x00000004)
+#define MFI_REPLY_GEN2_MESSAGE_INTERRUPT	0x00000001
+#define MFI_GEN2_ENABLE_INTERRUPT_MASK		0x00000001 
 #define MFI_REPLY_SKINNY_MESSAGE_INTERRUPT	0x40000000
-#define MFI_SKINNY_ENABLE_INTERRUPT_MASK	(0x00000001 | 0x00000008)
+#define MFI_SKINNY_ENABLE_INTERRUPT_MASK	(0x00000001)
+#define MFI_1068_PCSR_OFFSET			0x84
+#define MFI_1068_FW_HANDSHAKE_OFFSET		0x64
+#define MFI_1068_FW_READY			0xDDDD0000
 
 
 /*
@@ -770,7 +830,10 @@ struct megasas_register_set {
 	u32 	inbound_high_queue_port ;	/*00C4h*/
 
 	u32 	reserved_5;			/*00C8h*/
-	u32 	index_registers[820];		/*00CCh*/
+	u32		res_6[11];			/*CCh*/
+	u32		host_diag;
+	u32		seq_offset;
+	u32 	index_registers[807];		/*00CCh*/
 
 } __attribute__ ((packed));
 
@@ -787,7 +850,7 @@ struct megasas_sge64 {
 	u32 length;
 
 } __attribute__ ((packed));
-
+ 
 struct megasas_sge_skinny {
 
 	u64 phys_addr;
@@ -1233,19 +1296,22 @@ struct megasas_instance {
 	struct megasas_register_set __iomem *reg_set;
 
 	struct megasas_pd_list		pd_list[MEGASAS_MAX_PD];
+	u8     ld_ids[MEGASAS_MAX_LD_IDS];
 
 	s8 init_id;
 
 	u16 max_num_sge;
 	u16 max_fw_cmds;
 	u32 max_sectors_per_req;
+	struct megasas_aen_event *ev;
+	u32 cmd_per_lun;
 
 	struct megasas_cmd **cmd_list;
 	struct list_head cmd_pool;
 	spinlock_t cmd_pool_lock;
-	/* used to synch producer, consumer ptrs */
+	spinlock_t hba_lock;
 	spinlock_t completion_lock;
-	spinlock_t fire_lock;
+
 	struct dma_pool *frame_dma_pool;
 	struct dma_pool *sense_dma_pool;
 
@@ -1262,23 +1328,40 @@ struct megasas_instance {
 
 	struct pci_dev *pdev;
 	u32 unique_id;
+	u32 fw_support_ieee;
 
 	atomic_t fw_outstanding;
-	u32 hw_crit_error;
+	atomic_t fw_reset_no_pci_access;
 
+	
 	struct megasas_instance_template *instancet;
 	struct tasklet_struct isr_tasklet;
-	u8     ld_ids[MEGASAS_MAX_LD_IDS];
+	struct work_struct work_init;
 
 	u8 flag;
 	u8 unload;
 	u8 flag_ieee;
+	u8 issuepend_done;
+	u8 disableOnlineCtrlReset;
+	u8 adprecovery;
 	unsigned long last_time;
-	struct work_struct hotplug_work;
+	u32 mfiStatus;
+	u32 last_seq_num;
 
 	struct timer_list io_completion_timer;
+	struct list_head internal_reset_pending_q;
 };
 
+enum {
+	MEGASAS_HBA_OPERATIONAL			= 0,
+	MEGASAS_ADPRESET_SM_INFAULT		= 1,
+	MEGASAS_ADPRESET_SM_FW_RESET_SUCCESS	= 2,
+	MEGASAS_ADPRESET_SM_OPERATIONAL		= 3,
+	MEGASAS_HW_CRITICAL_ERROR		= 4,
+	MEGASAS_ADPRESET_INPROG_SIGN		= 0xDEADDEAD,
+};
+
+
  struct megasas_instance_template {
 	void (*fire_cmd)(struct megasas_instance *, dma_addr_t ,u32 ,struct megasas_register_set __iomem *);
 
@@ -1288,6 +1371,8 @@ struct megasas_instance {
 	int (*clear_intr)(struct megasas_register_set __iomem *);
 
 	u32 (*read_fw_status_reg)(struct megasas_register_set __iomem *);
+	int (*adp_reset)(struct megasas_instance *, struct megasas_register_set __iomem *);
+	int (*check_reset)(struct megasas_instance *, struct megasas_register_set __iomem *);
  };
 
 #define MEGASAS_IS_LOGICAL(scp)						\
@@ -1307,7 +1392,9 @@ struct megasas_cmd {
 	u32 index;
 	u8 sync_cmd;
 	u8 cmd_status;
-	u16 abort_aen;
+	u8 abort_aen;
+        u8 retry_for_fw_reset;
+
 
 	struct list_head list;
 	struct scsi_cmnd *scmd;