[kernel] r19615 - in dists/squeeze/linux-2.6/debian: . patches/features/all/megaraid_sas patches/series

Ben Hutchings benh at alioth.debian.org
Sun Dec 16 23:23:22 UTC 2012


Author: benh
Date: Sun Dec 16 23:23:22 2012
New Revision: 19615

Log:
megaraid_sas: Backport changes up to Linux 3.0.56 (Closes: #666108)

Added:
   dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/
   dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0006-megaraid_sas-infrastructure-to-get-pds-from-fw.patch
   dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0007-megaraid_sas-add-the-support-for-updating-the-os-after-adding-removing-the-devices-from-fw.patch
   dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0008-megaraid_sas-add-the-logical-drive-list-to-driver.patch
   dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0009-megaraid_sas-driver-fixed-the-device-update-issue.patch
   dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0010-megaraid_sas-add-the-ieee-sge-support-to-sas2-controller.patch
   dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0011-megaraid_sas-add-online-controller-reset-to-megaraid-sas-drive.patch
   dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0012-megaraid_sas-rename-megaraid_sas.c-to-megaraid_sas_base.c.patch
   dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0013-megaraid_sas-add-msi-x-support-and-msix_disable-module-parameter.patch
   dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0014-megaraid_sas-make-driver-pci-legacy-i-o-port-free-driver.patch
   dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0015-megaraid_sas-use-lowest-memory-bar-for-sr-iov-vf-support.patch
   dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0016-megaraid_sas-add-struct-megasas_instance_template-changes.patch
   dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0017-megaraid_sas-add-9565-9285-specific-code.patch
   dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0018-megaraid_sas-fix-instance-access-in-megasas_reset_timer.patch
   dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0019-megaraid_sas-tape-drive-support-fix.patch
   dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0020-megaraid_sas-report-system-pds-to-os.patch
   dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0021-megaraid_sas-use-the-firmware-boot-timeout-when-waiting-for-commands.patch
   dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0022-megaraid_sas-update-version-number-and-documentation.patch
   dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0023-megaraid_sas-zero-pad_0-in-mfi-structure.patch
   dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0024-megaraid_sas-version-and-documentation-update.patch
   dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0025-megaraid_sas-support-devices-update-flag.patch
   dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0026-megaraid_sas-add-input-parameter-for-max_sectors.patch
   dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0027-megaraid_sas-add-three-times-online-controller-reset.patch
   dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0028-megaraid_sas-version-and-documentation-update.patch
   dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0029-megaraid_sas-update-gpl-headers.patch
   dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0030-megaraid_sas-fix-failure-gotos.patch
   dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0031-megaraid_sas-add-missing-check_and_restore_queue_depth-call.patch
   dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0032-megaraid_sas-enable-msi-x-before-calling-megasas_init_fw.patch
   dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0033-megaraid_sas-call-tasklet_schedule-for-msi-x.patch
   dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0034-megaraid_sas-fix-probe_one-to-clear-msi-x-flags-in-kdump.patch
   dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0035-megaraid_sas-fix-megasas_build_dcdb_fusion-to-not-filter-by-type_disk.patch
   dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0036-megaraid_sas-fix-megasas_build_dcdb_fusion-to-use-correct-lun-field.patch
   dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0037-megaraid_sas-add-cfg_cleared-aen.patch
   dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0038-megaraid_sas-fix-tasklet_init-call.patch
   dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0039-megaraid_sas-fix-fault-state-handling.patch
   dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0040-megaraid_sas-fix-max_sectors-for-ieee-sgl.patch
   dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0041-megaraid_sas-fix-imr-ocr-support-to-work-correctly.patch
   dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0042-megaraid_sas-documentation-update.patch
   dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0043-megaraid_sas-add-9565-9285-specific-code-version-bump.patch
   dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0044-megaraid_sas-version-and-changelog-update.patch
   dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0045-megaraid_sas-remove-msi-x-black-list-use-mfi_reg_state-instead.patch
   dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0046-megaraid_sas-remove-un-used-function.patch
   dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0047-megaraid_sas-check-mfi_reg_state.fault.resetadapter.patch
   dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0048-megaraid_sas-disable-interrupts-free_irq-in-megasas_shutdown.patch
   dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0049-megaraid_sas-fix-bug-where-aens-could-be-lost-in-probe-and-resume.patch
   dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0050-megaraid_sas-convert-6-10-12-byte-cdb-s-for-fastpath-io.patch
   dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0051-megaraid_sas-add-1078-ocr-support.patch
   dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0052-megaraid_sas-version-and-changelog-update.patch
   dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0053-megaraid_sas-move-poll_aen_lock-initializer.patch
   dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0054-megaraid_sas-cosmetic-changes.patch
Modified:
   dists/squeeze/linux-2.6/debian/changelog
   dists/squeeze/linux-2.6/debian/patches/series/47

Modified: dists/squeeze/linux-2.6/debian/changelog
==============================================================================
--- dists/squeeze/linux-2.6/debian/changelog	Sun Dec 16 22:31:39 2012	(r19614)
+++ dists/squeeze/linux-2.6/debian/changelog	Sun Dec 16 23:23:22 2012	(r19615)
@@ -8,6 +8,9 @@
   * nfsv4: Fix kernel panic when mounting NFSv4 (Closes: #695872)
   * hpsa: Backport changes up to Linux 3.2.35 (Closes: #690100)
 
+  [ Jonathan Nieder ]
+  * megaraid_sas: Backport changes up to Linux 3.0.56 (Closes: #666108)
+
  -- Ben Hutchings <ben at decadent.org.uk>  Mon, 08 Oct 2012 00:26:11 +0100
 
 linux-2.6 (2.6.32-46) stable; urgency=high

Added: dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0006-megaraid_sas-infrastructure-to-get-pds-from-fw.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0006-megaraid_sas-infrastructure-to-get-pds-from-fw.patch	Sun Dec 16 23:23:22 2012	(r19615)
@@ -0,0 +1,273 @@
+From c8055e5e18540af704c3202fa9e90729bba6ffc4 Mon Sep 17 00:00:00 2001
+From: "Yang, Bo" <Bo.Yang at lsi.com>
+Date: Tue, 6 Oct 2009 14:27:54 -0600
+Subject: [PATCH 06/53] [SCSI] megaraid_sas: infrastructure to get PDs from FW
+
+commit 81e403ce3c6a34cd705bf54d4cdeefdeb7068a8d upstream.
+
+Add system PDs to OS.  Driver implemented the get_pd_list function to
+get the system PD from FW.
+
+Signed-off-by: Bo Yang <bo.yang at lsi.com>
+Signed-off-by: James Bottomley <James.Bottomley at suse.de>
+Signed-off-by: Jonathan Nieder <jrnieder at gmail.com>
+---
+ drivers/scsi/megaraid/megaraid_sas.c | 96 ++++++++++++++++++++++++++++++++++++
+ drivers/scsi/megaraid/megaraid_sas.h | 88 ++++++++++++++++++++++++++++++++-
+ 2 files changed, 182 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/scsi/megaraid/megaraid_sas.c b/drivers/scsi/megaraid/megaraid_sas.c
+index 28b27ce1a914..38abd98a1ffb 100644
+--- a/drivers/scsi/megaraid/megaraid_sas.c
++++ b/drivers/scsi/megaraid/megaraid_sas.c
+@@ -2057,6 +2057,98 @@ 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
++ *
++ * Issues an internal command (DCMD) to get the FW's controller PD
++ * list structure.  This information is mainly used to find out SYSTEM
++ * supported by the FW.
++ */
++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;
++	}
++
++	dcmd = &cmd->frame->dcmd;
++
++	ci = pci_alloc_consistent(instance->pdev,
++		  MEGASAS_MAX_PD * sizeof(struct MR_PD_LIST), &ci_h);
++
++	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->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;
++	}
++
++	/*
++	* the following function will get the instance PD LIST.
++	*/
++
++	pd_addr = ci->addr;
++
++	if ( ret == 0 &&
++		(ci->count <
++		  (MEGASAS_MAX_PD_CHANNELS * MEGASAS_MAX_DEV_PER_CHANNEL))) {
++
++		memset(instance->pd_list, 0,
++			MEGASAS_MAX_PD * sizeof(struct megasas_pd_list));
++
++		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),
++				ci, ci_h);
++	megasas_return_cmd(instance, cmd);
++
++	return ret;
++}
++
++
+ /**
+  * megasas_get_controller_info -	Returns FW's controller structure
+  * @instance:				Adapter soft state
+@@ -2347,6 +2439,10 @@ static int megasas_init_mfi(struct megasas_instance *instance)
+ 	if (megasas_issue_init_mfi(instance))
+ 		goto fail_fw_init;
+ 
++	memset(instance->pd_list, 0 ,
++		(MEGASAS_MAX_PD * sizeof(struct megasas_pd_list)));
++	megasas_get_pd_list(instance);
++
+ 	ctrl_info = kmalloc(sizeof(struct megasas_ctrl_info), GFP_KERNEL);
+ 
+ 	/*
+diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h
+index 3b1eed1bbbe0..dc88ea79b0db 100644
+--- a/drivers/scsi/megaraid/megaraid_sas.h
++++ b/drivers/scsi/megaraid/megaraid_sas.h
+@@ -133,6 +133,7 @@
+ #define MR_DCMD_CLUSTER				0x08000000
+ #define MR_DCMD_CLUSTER_RESET_ALL		0x08010100
+ #define MR_DCMD_CLUSTER_RESET_LD		0x08010200
++#define MR_DCMD_PD_LIST_QUERY                   0x02010100
+ 
+ /*
+  * MFI command completion codes
+@@ -253,9 +254,89 @@ enum MR_EVT_ARGS {
+ 	MR_EVT_ARGS_STR,
+ 	MR_EVT_ARGS_TIME,
+ 	MR_EVT_ARGS_ECC,
++	MR_EVT_ARGS_LD_PROP,
++	MR_EVT_ARGS_PD_SPARE,
++	MR_EVT_ARGS_PD_INDEX,
++	MR_EVT_ARGS_DIAG_PASS,
++	MR_EVT_ARGS_DIAG_FAIL,
++	MR_EVT_ARGS_PD_LBA_LBA,
++	MR_EVT_ARGS_PORT_PHY,
++	MR_EVT_ARGS_PD_MISSING,
++	MR_EVT_ARGS_PD_ADDRESS,
++	MR_EVT_ARGS_BITMAP,
++	MR_EVT_ARGS_CONNECTOR,
++	MR_EVT_ARGS_PD_PD,
++	MR_EVT_ARGS_PD_FRU,
++	MR_EVT_ARGS_PD_PATHINFO,
++	MR_EVT_ARGS_PD_POWER_STATE,
++	MR_EVT_ARGS_GENERIC,
++};
+ 
++/*
++ * define constants for device list query options
++ */
++enum MR_PD_QUERY_TYPE {
++	MR_PD_QUERY_TYPE_ALL                = 0,
++	MR_PD_QUERY_TYPE_STATE              = 1,
++	MR_PD_QUERY_TYPE_POWER_STATE        = 2,
++	MR_PD_QUERY_TYPE_MEDIA_TYPE         = 3,
++	MR_PD_QUERY_TYPE_SPEED              = 4,
++	MR_PD_QUERY_TYPE_EXPOSED_TO_HOST    = 5,
+ };
+ 
++enum MR_PD_STATE {
++	MR_PD_STATE_UNCONFIGURED_GOOD   = 0x00,
++	MR_PD_STATE_UNCONFIGURED_BAD    = 0x01,
++	MR_PD_STATE_HOT_SPARE           = 0x02,
++	MR_PD_STATE_OFFLINE             = 0x10,
++	MR_PD_STATE_FAILED              = 0x11,
++	MR_PD_STATE_REBUILD             = 0x14,
++	MR_PD_STATE_ONLINE              = 0x18,
++	MR_PD_STATE_COPYBACK            = 0x20,
++	MR_PD_STATE_SYSTEM              = 0x40,
++ };
++
++
++ /*
++ * defines the physical drive address structure
++ */
++struct MR_PD_ADDRESS {
++	u16     deviceId;
++	u16     enclDeviceId;
++
++	union {
++		struct {
++			u8  enclIndex;
++			u8  slotNumber;
++		} mrPdAddress;
++		struct {
++			u8  enclPosition;
++			u8  enclConnectorIndex;
++		} mrEnclAddress;
++	};
++	u8      scsiDevType;
++	union {
++		u8      connectedPortBitmap;
++		u8      connectedPortNumbers;
++	};
++	u64     sasAddr[2];
++} __packed;
++
++/*
++ * defines the physical drive list structure
++ */
++struct MR_PD_LIST {
++	u32             size;
++	u32             count;
++	struct MR_PD_ADDRESS   addr[1];
++} __packed;
++
++struct megasas_pd_list {
++	u16             tid;
++	u8             driveType;
++	u8             driveState;
++} __packed;
++
+ /*
+  * SAS controller properties
+  */
+@@ -284,7 +365,7 @@ struct megasas_ctrl_prop {
+ 	u8 expose_encl_devices;
+ 	u8 reserved[38];
+ 
+-} __attribute__ ((packed));
++} __packed;
+ 
+ /*
+  * SAS controller information
+@@ -527,7 +608,7 @@ struct megasas_ctrl_info {
+ 
+ 	u8 pad[0x800 - 0x6a0];
+ 
+-} __attribute__ ((packed));
++} __packed;
+ 
+ /*
+  * ===============================
+@@ -542,6 +623,8 @@ struct megasas_ctrl_info {
+ #define MEGASAS_DEFAULT_INIT_ID			-1
+ #define MEGASAS_MAX_LUN				8
+ #define MEGASAS_MAX_LD				64
++#define MEGASAS_MAX_PD                          (MEGASAS_MAX_PD_CHANNELS * \
++						MEGASAS_MAX_DEV_PER_CHANNEL)
+ 
+ #define MEGASAS_DBG_LVL				1
+ 
+@@ -1079,6 +1162,7 @@ struct megasas_instance {
+ 	unsigned long base_addr;
+ 	struct megasas_register_set __iomem *reg_set;
+ 
++	struct megasas_pd_list          pd_list[MEGASAS_MAX_PD];
+ 	s8 init_id;
+ 
+ 	u16 max_num_sge;
+-- 
+1.8.0
+
+

Added: dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0007-megaraid_sas-add-the-support-for-updating-the-os-after-adding-removing-the-devices-from-fw.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0007-megaraid_sas-add-the-support-for-updating-the-os-after-adding-removing-the-devices-from-fw.patch	Sun Dec 16 23:23:22 2012	(r19615)
@@ -0,0 +1,255 @@
+From c7d26f96f235b911dfbeab7fa31aeab64d436825 Mon Sep 17 00:00:00 2001
+From: "Yang, Bo" <Bo.Yang at lsi.com>
+Date: Tue, 6 Oct 2009 14:50:17 -0600
+Subject: [PATCH 07/53] [SCSI] megaraid_sas: Add the support for updating the  OS after adding/removing the devices from FW
+
+commit 7e8a75f4dfbff173977b2f58799c3eceb7b09afd upstream.
+
+Driver will update the OS devices after adding and deleting the device
+from FW.  When driver receive add or delete AEN from FW, driver will
+send the DCMD cmd to get the System PD list from FW.  Then driver will
+check if this device already in the OS: If add event and OS don't have
+the device (but it is in the list), driver add the device to OS,
+otherwise driver will not add.  If remove event, driver will check the
+list, if is not in the list, but OS have the device, driver will
+remove the device.
+
+Signed-off-by: Bo Yang <bo.yang at lsi.com>
+Signed-off-by: James Bottomley <James.Bottomley at suse.de>
+Signed-off-by: Jonathan Nieder <jrnieder at gmail.com>
+---
+ drivers/scsi/megaraid/megaraid_sas.c | 125 ++++++++++++++++++++++++++++++++++-
+ drivers/scsi/megaraid/megaraid_sas.h |  17 +++++
+ 2 files changed, 141 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/scsi/megaraid/megaraid_sas.c b/drivers/scsi/megaraid/megaraid_sas.c
+index 38abd98a1ffb..b690c8ca75cc 100644
+--- a/drivers/scsi/megaraid/megaraid_sas.c
++++ b/drivers/scsi/megaraid/megaraid_sas.c
+@@ -1402,6 +1402,8 @@ megasas_bios_param(struct scsi_device *sdev, struct block_device *bdev,
+ 	return 0;
+ }
+ 
++static void megasas_aen_polling(struct work_struct *work);
++
+ /**
+  * megasas_service_aen -	Processes an event notification
+  * @instance:			Adapter soft state
+@@ -1433,6 +1435,20 @@ megasas_service_aen(struct megasas_instance *instance, struct megasas_cmd *cmd)
+ 
+ 	instance->aen_cmd = NULL;
+ 	megasas_return_cmd(instance, cmd);
++
++	if (instance->unload == 0) {
++		struct megasas_aen_event *ev;
++		ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
++		if (!ev) {
++			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);
++			schedule_delayed_work(
++				(struct delayed_work *)&ev->hotplug_work, 0);
++		}
++	}
+ }
+ 
+ /*
+@@ -1952,6 +1968,7 @@ static int megasas_create_frame_pool(struct megasas_instance *instance)
+ 		}
+ 
+ 		cmd->frame->io.context = cmd->index;
++		cmd->frame->io.pad_0 = 0;
+ 	}
+ 
+ 	return 0;
+@@ -2148,7 +2165,6 @@ megasas_get_pd_list(struct megasas_instance *instance)
+ 	return ret;
+ }
+ 
+-
+ /**
+  * megasas_get_controller_info -	Returns FW's controller structure
+  * @instance:				Adapter soft state
+@@ -2857,6 +2873,7 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ 	*instance->producer = 0;
+ 	*instance->consumer = 0;
+ 	megasas_poll_wait_aen = 0;
++	instance->ev = NULL;
+ 
+ 	instance->evt_detail = pci_alloc_consistent(pdev,
+ 						    sizeof(struct
+@@ -3079,6 +3096,16 @@ megasas_suspend(struct pci_dev *pdev, pm_message_t state)
+ 
+ 	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(
++			(struct delayed_work *)&ev->hotplug_work);
++		flush_scheduled_work();
++		instance->ev = NULL;
++	}
++
+ 	tasklet_kill(&instance->isr_tasklet);
+ 
+ 	pci_set_drvdata(instance->pdev, instance);
+@@ -3219,6 +3246,16 @@ 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(
++			(struct delayed_work *)&ev->hotplug_work);
++		flush_scheduled_work();
++		instance->ev = NULL;
++	}
++
+ 	tasklet_kill(&instance->isr_tasklet);
+ 
+ 	/*
+@@ -3814,6 +3851,92 @@ out:
+ 	return retval;
+ }
+ 
++static void
++megasas_aen_polling(struct work_struct *work)
++{
++	struct megasas_aen_event *ev =
++		container_of(work, struct megasas_aen_event, hotplug_work);
++	struct megasas_instance *instance = ev->instance;
++	union megasas_evt_class_locale class_locale;
++	struct  Scsi_Host *host;
++	struct  scsi_device *sdev1;
++	u16     pd_index = 0;
++	int     i, j, doscan = 0;
++	u32 seq_num;
++	int error;
++
++	if (!instance) {
++		printk(KERN_ERR "invalid instance!\n");
++		kfree(ev);
++		return;
++	}
++	instance->ev = NULL;
++	host = instance->host;
++	if (instance->evt_detail) {
++
++		switch (instance->evt_detail->code) {
++		case MR_EVT_PD_INSERTED:
++		case MR_EVT_PD_REMOVED:
++		case MR_EVT_CTRL_HOST_BUS_SCAN_REQUESTED:
++			doscan = 1;
++			break;
++		default:
++			doscan = 0;
++			break;
++		}
++	} else {
++		printk(KERN_ERR "invalid evt_detail!\n");
++		kfree(ev);
++		return;
++	}
++
++	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;
++				sdev1 = scsi_device_lookup(host, i, j, 0);
++				if (instance->pd_list[pd_index].driveState ==
++							MR_PD_STATE_SYSTEM) {
++					if (!sdev1) {
++						scsi_add_device(host, i, j, 0);
++					}
++					if (sdev1)
++						scsi_device_put(sdev1);
++				} else {
++					if (sdev1) {
++						scsi_remove_device(sdev1);
++						scsi_device_put(sdev1);
++					}
++				}
++			}
++		}
++	}
++
++	if ( instance->aen_cmd != NULL ) {
++		kfree(ev);
++		return ;
++	}
++
++	seq_num = instance->evt_detail->seq_num + 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;
++	mutex_lock(&instance->aen_mutex);
++	error = megasas_register_aen(instance, seq_num,
++					class_locale.word);
++	mutex_unlock(&instance->aen_mutex);
++
++	if (error)
++		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);
+diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h
+index dc88ea79b0db..b0a85fc72d8d 100644
+--- a/drivers/scsi/megaraid/megaraid_sas.h
++++ b/drivers/scsi/megaraid/megaraid_sas.h
+@@ -284,6 +284,17 @@ enum MR_PD_QUERY_TYPE {
+ 	MR_PD_QUERY_TYPE_EXPOSED_TO_HOST    = 5,
+ };
+ 
++#define MR_EVT_CFG_CLEARED                              0x0004
++#define MR_EVT_LD_STATE_CHANGE                          0x0051
++#define MR_EVT_PD_INSERTED                              0x005b
++#define MR_EVT_PD_REMOVED                               0x0070
++#define MR_EVT_LD_CREATED                               0x008a
++#define MR_EVT_LD_DELETED                               0x008b
++#define MR_EVT_FOREIGN_CFG_IMPORTED                     0x00db
++#define MR_EVT_LD_OFFLINE                               0x00fc
++#define MR_EVT_CTRL_HOST_BUS_SCAN_REQUESTED             0x0152
++#define MAX_LOGICAL_DRIVES				64
++
+ enum MR_PD_STATE {
+ 	MR_PD_STATE_UNCONFIGURED_GOOD   = 0x00,
+ 	MR_PD_STATE_UNCONFIGURED_BAD    = 0x01,
+@@ -1149,6 +1160,11 @@ struct megasas_evt_detail {
+ 
+ } __attribute__ ((packed));
+ 
++struct megasas_aen_event {
++	struct work_struct hotplug_work;
++	struct megasas_instance *instance;
++};
++
+ struct megasas_instance {
+ 
+ 	u32 *producer;
+@@ -1168,6 +1184,7 @@ struct megasas_instance {
+ 	u16 max_num_sge;
+ 	u16 max_fw_cmds;
+ 	u32 max_sectors_per_req;
++	struct megasas_aen_event *ev;
+ 
+ 	struct megasas_cmd **cmd_list;
+ 	struct list_head cmd_pool;
+-- 
+1.8.0
+
+

Added: dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0008-megaraid_sas-add-the-logical-drive-list-to-driver.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0008-megaraid_sas-add-the-logical-drive-list-to-driver.patch	Sun Dec 16 23:23:22 2012	(r19615)
@@ -0,0 +1,212 @@
+From 9b1a265b1f243f1f9dad1b4883f8b123b3ff023b Mon Sep 17 00:00:00 2001
+From: "Yang, Bo" <Bo.Yang at lsi.com>
+Date: Sun, 6 Dec 2009 08:30:19 -0700
+Subject: [PATCH 08/53] [SCSI] megaraid_sas: add the logical drive list to  driver
+
+commit bdc6fb8d69fab7b4b7f70823e3932bd8e4cfd7db upstream.
+
+Driver issue the get ld list to fw to get the logic drive list.
+Driver will keep the logic drive list for the internal use after
+driver load.
+
+Signed-off-by: Bo Yang <bo.yang at lsi.com>
+Signed-off-by: James Bottomley <James.Bottomley at suse.de>
+Signed-off-by: Jonathan Nieder <jrnieder at gmail.com>
+---
+ drivers/scsi/megaraid/megaraid_sas.c | 95 ++++++++++++++++++++++++++++++++++++
+ drivers/scsi/megaraid/megaraid_sas.h | 30 ++++++++++++
+ 2 files changed, 125 insertions(+)
+
+diff --git a/drivers/scsi/megaraid/megaraid_sas.c b/drivers/scsi/megaraid/megaraid_sas.c
+index b690c8ca75cc..3a35e27e1ab8 100644
+--- a/drivers/scsi/megaraid/megaraid_sas.c
++++ b/drivers/scsi/megaraid/megaraid_sas.c
+@@ -817,6 +817,12 @@ megasas_build_dcdb(struct megasas_instance *instance, struct scsi_cmnd *scp,
+ 		pthru->sge_count = megasas_make_sgl32(instance, scp,
+ 						      &pthru->sgl);
+ 
++	if (pthru->sge_count > instance->max_num_sge) {
++		printk(KERN_ERR "megasas: DCDB two many SGE NUM=%x\n",
++			pthru->sge_count);
++		return 0;
++	}
++
+ 	/*
+ 	 * Sense info specific
+ 	 */
+@@ -935,6 +941,12 @@ megasas_build_ldio(struct megasas_instance *instance, struct scsi_cmnd *scp,
+ 	} else
+ 		ldio->sge_count = megasas_make_sgl32(instance, scp, &ldio->sgl);
+ 
++	if (ldio->sge_count > instance->max_num_sge) {
++		printk(KERN_ERR "megasas: build_ld_io: sge_count = %x\n",
++			ldio->sge_count);
++		return 0;
++	}
++
+ 	/*
+ 	 * Sense info specific
+ 	 */
+@@ -2165,6 +2177,86 @@ megasas_get_pd_list(struct megasas_instance *instance)
+ 	return ret;
+ }
+ 
++/*
++ * megasas_get_ld_list_info -	Returns FW's ld_list structure
++ * @instance:				Adapter soft state
++ * @ld_list:				ld_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
++ * supported by the FW.
++ */
++static int
++megasas_get_ld_list(struct megasas_instance *instance)
++{
++	int ret = 0, ld_index = 0, ids = 0;
++	struct megasas_cmd *cmd;
++	struct megasas_dcmd_frame *dcmd;
++	struct MR_LD_LIST *ci;
++	dma_addr_t ci_h = 0;
++
++	cmd = megasas_get_cmd(instance);
++
++	if (!cmd) {
++		printk(KERN_DEBUG "megasas_get_ld_list: Failed to get cmd\n");
++		return -ENOMEM;
++	}
++
++	dcmd = &cmd->frame->dcmd;
++
++	ci = pci_alloc_consistent(instance->pdev,
++				sizeof(struct MR_LD_LIST),
++				&ci_h);
++
++	if (!ci) {
++		printk(KERN_DEBUG "Failed to alloc mem in get_ld_list\n");
++		megasas_return_cmd(instance, cmd);
++		return -ENOMEM;
++	}
++
++	memset(ci, 0, sizeof(*ci));
++	memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
++
++	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 = sizeof(struct MR_LD_LIST);
++	dcmd->opcode = MR_DCMD_LD_GET_LIST;
++	dcmd->sgl.sge32[0].phys_addr = ci_h;
++	dcmd->sgl.sge32[0].length = sizeof(struct MR_LD_LIST);
++	dcmd->pad_0  = 0;
++
++	if (!megasas_issue_polled(instance, cmd)) {
++		ret = 0;
++	} else {
++		ret = -1;
++	}
++
++	/* the following function will get the instance PD LIST */
++
++	if ((ret == 0) && (ci->ldCount < MAX_LOGICAL_DRIVES)) {
++		memset(instance->ld_ids, 0xff, MEGASAS_MAX_LD_IDS);
++
++		for (ld_index = 0; ld_index < ci->ldCount; ld_index++) {
++			if (ci->ldList[ld_index].state != 0) {
++				ids = ci->ldList[ld_index].ref.targetId;
++				instance->ld_ids[ids] =
++					ci->ldList[ld_index].ref.targetId;
++			}
++		}
++	}
++
++	pci_free_consistent(instance->pdev,
++				sizeof(struct MR_LD_LIST),
++				ci,
++				ci_h);
++
++	megasas_return_cmd(instance, cmd);
++	return ret;
++}
++
+ /**
+  * megasas_get_controller_info -	Returns FW's controller structure
+  * @instance:				Adapter soft state
+@@ -2459,6 +2551,9 @@ static int megasas_init_mfi(struct megasas_instance *instance)
+ 		(MEGASAS_MAX_PD * sizeof(struct megasas_pd_list)));
+ 	megasas_get_pd_list(instance);
+ 
++	memset(instance->ld_ids, 0xff, MEGASAS_MAX_LD_IDS);
++	megasas_get_ld_list(instance);
++
+ 	ctrl_info = kmalloc(sizeof(struct megasas_ctrl_info), GFP_KERNEL);
+ 
+ 	/*
+diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h
+index b0a85fc72d8d..29cd2c877952 100644
+--- a/drivers/scsi/megaraid/megaraid_sas.h
++++ b/drivers/scsi/megaraid/megaraid_sas.h
+@@ -116,6 +116,7 @@
+ #define MFI_CMD_STP				0x08
+ 
+ #define MR_DCMD_CTRL_GET_INFO			0x01010000
++#define MR_DCMD_LD_GET_LIST			0x03010000
+ 
+ #define MR_DCMD_CTRL_CACHE_FLUSH		0x01101000
+ #define MR_FLUSH_CTRL_CACHE			0x01
+@@ -348,6 +349,32 @@ struct megasas_pd_list {
+ 	u8             driveState;
+ } __packed;
+ 
++ /*
++ * defines the logical drive reference structure
++ */
++union  MR_LD_REF {
++	struct {
++		u8      targetId;
++		u8      reserved;
++		u16     seqNum;
++	};
++	u32     ref;
++} __packed;
++
++/*
++ * defines the logical drive list structure
++ */
++struct MR_LD_LIST {
++	u32     ldCount;
++	u32     reserved;
++	struct {
++		union MR_LD_REF   ref;
++		u8          state;
++		u8          reserved[3];
++		u64         size;
++	} ldList[MAX_LOGICAL_DRIVES];
++} __packed;
++
+ /*
+  * SAS controller properties
+  */
+@@ -636,6 +663,8 @@ struct megasas_ctrl_info {
+ #define MEGASAS_MAX_LD				64
+ #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
+ 
+@@ -1179,6 +1208,7 @@ 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;
+-- 
+1.8.0
+
+

Added: dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0009-megaraid_sas-driver-fixed-the-device-update-issue.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0009-megaraid_sas-driver-fixed-the-device-update-issue.patch	Sun Dec 16 23:23:22 2012	(r19615)
@@ -0,0 +1,190 @@
+From b3d3d3e77c8850222a5a210855e0e7b3d0a2ac71 Mon Sep 17 00:00:00 2001
+From: "Yang, Bo" <Bo.Yang at lsi.com>
+Date: Sun, 6 Dec 2009 08:39:25 -0700
+Subject: [PATCH 09/53] [SCSI] megaraid_sas: driver fixed the device update  issue
+
+commit c978684254d11e3768c5a0b2780302fb0cada29c upstream.
+
+driver fixed the device update issue after get the AEN PD delete/ADD
+and LD add/delete from FW.
+
+Signed-off-by: Bo Yang <bo.yang at lsi.com>
+Signed-off-by: James Bottomley <James.Bottomley at suse.de>
+Signed-off-by: Jonathan Nieder <jrnieder at gmail.com>
+---
+ drivers/scsi/megaraid/megaraid_sas.c | 142 +++++++++++++++++++++++++++++++++++
+ 1 file changed, 142 insertions(+)
+
+diff --git a/drivers/scsi/megaraid/megaraid_sas.c b/drivers/scsi/megaraid/megaraid_sas.c
+index 3a35e27e1ab8..c7e1e40ad24a 100644
+--- a/drivers/scsi/megaraid/megaraid_sas.c
++++ b/drivers/scsi/megaraid/megaraid_sas.c
+@@ -3956,6 +3956,7 @@ megasas_aen_polling(struct work_struct *work)
+ 	struct  Scsi_Host *host;
+ 	struct  scsi_device *sdev1;
+ 	u16     pd_index = 0;
++	u16	ld_index = 0;
+ 	int     i, j, doscan = 0;
+ 	u32 seq_num;
+ 	int error;
+@@ -3971,8 +3972,124 @@ megasas_aen_polling(struct work_struct *work)
+ 
+ 		switch (instance->evt_detail->code) {
+ 		case MR_EVT_PD_INSERTED:
++			if (megasas_get_pd_list(instance) == 0) {
++			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;
++
++				sdev1 =
++				scsi_device_lookup(host, i, j, 0);
++
++				if (instance->pd_list[pd_index].driveState
++						== MR_PD_STATE_SYSTEM) {
++						if (!sdev1) {
++						scsi_add_device(host, i, j, 0);
++						}
++
++					if (sdev1)
++						scsi_device_put(sdev1);
++					}
++				}
++			}
++			}
++			doscan = 0;
++			break;
++
+ 		case MR_EVT_PD_REMOVED:
++			if (megasas_get_pd_list(instance) == 0) {
++			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;
++
++				sdev1 =
++				scsi_device_lookup(host, i, j, 0);
++
++				if (instance->pd_list[pd_index].driveState
++					== MR_PD_STATE_SYSTEM) {
++					if (sdev1) {
++						scsi_device_put(sdev1);
++					}
++				} else {
++					if (sdev1) {
++						scsi_remove_device(sdev1);
++						scsi_device_put(sdev1);
++					}
++				}
++				}
++			}
++			}
++			doscan = 0;
++			break;
++
++		case MR_EVT_LD_OFFLINE:
++		case MR_EVT_LD_DELETED:
++			megasas_get_ld_list(instance);
++			for (i = 0; i < MEGASAS_MAX_LD_CHANNELS; i++) {
++				for (j = 0;
++				j < MEGASAS_MAX_DEV_PER_CHANNEL;
++				j++) {
++
++				ld_index =
++				(i * MEGASAS_MAX_DEV_PER_CHANNEL) + j;
++
++				sdev1 = scsi_device_lookup(host,
++					i + MEGASAS_MAX_LD_CHANNELS,
++					j,
++					0);
++
++				if (instance->ld_ids[ld_index] != 0xff) {
++					if (sdev1) {
++						scsi_device_put(sdev1);
++					}
++				} else {
++					if (sdev1) {
++						scsi_remove_device(sdev1);
++						scsi_device_put(sdev1);
++					}
++				}
++				}
++			}
++			doscan = 0;
++			break;
++		case MR_EVT_LD_CREATED:
++			megasas_get_ld_list(instance);
++			for (i = 0; i < MEGASAS_MAX_LD_CHANNELS; i++) {
++				for (j = 0;
++					j < MEGASAS_MAX_DEV_PER_CHANNEL;
++					j++) {
++					ld_index =
++					(i * MEGASAS_MAX_DEV_PER_CHANNEL) + j;
++
++					sdev1 = scsi_device_lookup(host,
++						i+MEGASAS_MAX_LD_CHANNELS,
++						j, 0);
++
++					if (instance->ld_ids[ld_index] !=
++								0xff) {
++						if (!sdev1) {
++							scsi_add_device(host,
++								i + 2,
++								j, 0);
++						}
++					}
++					if (sdev1) {
++						scsi_device_put(sdev1);
++					}
++				}
++			}
++			doscan = 0;
++			break;
+ 		case MR_EVT_CTRL_HOST_BUS_SCAN_REQUESTED:
++		case MR_EVT_FOREIGN_CFG_IMPORTED:
+ 			doscan = 1;
+ 			break;
+ 		default:
+@@ -4007,6 +4124,31 @@ megasas_aen_polling(struct work_struct *work)
+ 				}
+ 			}
+ 		}
++
++		megasas_get_ld_list(instance);
++		for (i = 0; i < MEGASAS_MAX_LD_CHANNELS; i++) {
++			for (j = 0; j < MEGASAS_MAX_DEV_PER_CHANNEL; j++) {
++				ld_index =
++				(i * MEGASAS_MAX_DEV_PER_CHANNEL) + j;
++
++				sdev1 = scsi_device_lookup(host,
++					i+MEGASAS_MAX_LD_CHANNELS, j, 0);
++				if (instance->ld_ids[ld_index] != 0xff) {
++					if (!sdev1) {
++						scsi_add_device(host,
++								i+2,
++								j, 0);
++					} else {
++						scsi_device_put(sdev1);
++					}
++				} else {
++					if (sdev1) {
++						scsi_remove_device(sdev1);
++						scsi_device_put(sdev1);
++					}
++				}
++			}
++		}
+ 	}
+ 
+ 	if ( instance->aen_cmd != NULL ) {
+-- 
+1.8.0
+
+

Added: dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0010-megaraid_sas-add-the-ieee-sge-support-to-sas2-controller.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0010-megaraid_sas-add-the-ieee-sge-support-to-sas2-controller.patch	Sun Dec 16 23:23:22 2012	(r19615)
@@ -0,0 +1,246 @@
+From 10ff204feef80b5d19d325573dfd0fa35aa4f800 Mon Sep 17 00:00:00 2001
+From: "Yang, Bo" <Bo.Yang at lsi.com>
+Date: Tue, 6 Oct 2009 14:43:28 -0600
+Subject: [PATCH 10/53] [SCSI] megaraid_sas: add the IEEE SGE support to SAS2  controller
+
+commit f4c9a1317d32bb0af7546ef0c1dcc3be52dc8d0a upstream.
+
+To increase the performance, megaraid sas driver added the IEEE SGE
+support to support SAS2 controller.
+
+Signed-off-by: Bo Yang <bo.yang at lsi.com>
+Signed-off-by: James Bottomley <James.Bottomley at suse.de>
+Signed-off-by: Jonathan Nieder <jrnieder at gmail.com>
+---
+ drivers/scsi/megaraid/megaraid_sas.c | 80 ++++++++++++++++++++++++++++++++----
+ drivers/scsi/megaraid/megaraid_sas.h |  9 ++++
+ 2 files changed, 82 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/scsi/megaraid/megaraid_sas.c b/drivers/scsi/megaraid/megaraid_sas.c
+index c7e1e40ad24a..2b9e3c68c3e7 100644
+--- a/drivers/scsi/megaraid/megaraid_sas.c
++++ b/drivers/scsi/megaraid/megaraid_sas.c
+@@ -712,6 +712,35 @@ megasas_make_sgl64(struct megasas_instance *instance, struct scsi_cmnd *scp,
+ 	return sge_count;
+ }
+ 
++/**
++ * 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
++ *
++ * If successful, this function returns the number of SG elements. Otherwise,
++ * it returnes -1.
++ */
++static int
++megasas_make_sgl_skinny(struct megasas_instance *instance,
++		struct scsi_cmnd *scp, union megasas_sgl *mfi_sgl)
++{
++	int i;
++	int sge_count;
++	struct scatterlist *os_sgl;
++
++	sge_count = scsi_dma_map(scp);
++
++	if (sge_count) {
++		scsi_for_each_sg(scp, os_sgl, sge_count, i) {
++			mfi_sgl->sge_skinny[i].length = sg_dma_len(os_sgl);
++			mfi_sgl->sge_skinny[i].phys_addr =
++						sg_dma_address(os_sgl);
++		}
++	}
++	return sge_count;
++}
++
+  /**
+  * megasas_get_frame_count - Computes the number of frames
+  * @frame_type		: type of frame- io or pthru frame
+@@ -720,7 +749,8 @@ megasas_make_sgl64(struct megasas_instance *instance, struct scsi_cmnd *scp,
+  * Returns the number of frames required for numnber of sge's (sge_count)
+  */
+ 
+-static u32 megasas_get_frame_count(u8 sge_count, u8 frame_type)
++static u32 megasas_get_frame_count(struct megasas_instance *instance,
++			u8 sge_count, u8 frame_type)
+ {
+ 	int num_cnt;
+ 	int sge_bytes;
+@@ -730,6 +760,10 @@ static u32 megasas_get_frame_count(u8 sge_count, u8 frame_type)
+ 	sge_sz = (IS_DMA64) ? sizeof(struct megasas_sge64) :
+ 	    sizeof(struct megasas_sge32);
+ 
++	if (instance->flag_ieee) {
++		sge_sz = sizeof(struct megasas_sge_skinny);
++	}
++
+ 	/*
+ 	 * Main frame can contain 2 SGEs for 64-bit SGLs and
+ 	 * 3 SGEs for 32-bit SGLs for ldio &
+@@ -737,12 +771,16 @@ static u32 megasas_get_frame_count(u8 sge_count, u8 frame_type)
+ 	 * 2 SGEs for 32-bit SGLs for pthru frame
+ 	 */
+ 	if (unlikely(frame_type == PTHRU_FRAME)) {
+-		if (IS_DMA64)
++		if (instance->flag_ieee == 1) {
++			num_cnt = sge_count - 1;
++		} else if (IS_DMA64)
+ 			num_cnt = sge_count - 1;
+ 		else
+ 			num_cnt = sge_count - 2;
+ 	} else {
+-		if (IS_DMA64)
++		if (instance->flag_ieee == 1) {
++			num_cnt = sge_count - 1;
++		} else if (IS_DMA64)
+ 			num_cnt = sge_count - 2;
+ 		else
+ 			num_cnt = sge_count - 3;
+@@ -791,6 +829,10 @@ megasas_build_dcdb(struct megasas_instance *instance, struct scsi_cmnd *scp,
+ 	else if (scp->sc_data_direction == PCI_DMA_NONE)
+ 		flags = MFI_FRAME_DIR_NONE;
+ 
++	if (instance->flag_ieee == 1) {
++		flags |= MFI_FRAME_IEEE;
++	}
++
+ 	/*
+ 	 * Prepare the DCDB frame
+ 	 */
+@@ -809,7 +851,11 @@ megasas_build_dcdb(struct megasas_instance *instance, struct scsi_cmnd *scp,
+ 	/*
+ 	 * Construct SGL
+ 	 */
+-	if (IS_DMA64) {
++	if (instance->flag_ieee == 1) {
++		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,
+ 						      &pthru->sgl);
+@@ -834,7 +880,7 @@ megasas_build_dcdb(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(pthru->sge_count,
++	cmd->frame_count = megasas_get_frame_count(instance, pthru->sge_count,
+ 							PTHRU_FRAME);
+ 
+ 	return cmd->frame_count;
+@@ -865,6 +911,10 @@ megasas_build_ldio(struct megasas_instance *instance, struct scsi_cmnd *scp,
+ 	else if (scp->sc_data_direction == PCI_DMA_FROMDEVICE)
+ 		flags = MFI_FRAME_DIR_READ;
+ 
++	if (instance->flag_ieee == 1) {
++		flags |= MFI_FRAME_IEEE;
++	}
++
+ 	/*
+ 	 * Prepare the Logical IO frame: 2nd bit is zero for all read cmds
+ 	 */
+@@ -935,7 +985,11 @@ megasas_build_ldio(struct megasas_instance *instance, struct scsi_cmnd *scp,
+ 	/*
+ 	 * Construct SGL
+ 	 */
+-	if (IS_DMA64) {
++	if (instance->flag_ieee) {
++		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);
+ 	} else
+@@ -958,7 +1012,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(ldio->sge_count, IO_FRAME);
++	cmd->frame_count = megasas_get_frame_count(instance,
++			ldio->sge_count, IO_FRAME);
+ 
+ 	return cmd->frame_count;
+ }
+@@ -1918,6 +1973,10 @@ 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);
++	}
++
+ 	/*
+ 	 * Calculated the number of 64byte frames required for SGL
+ 	 */
+@@ -2797,6 +2856,11 @@ megasas_register_aen(struct megasas_instance *instance, u32 seq_num,
+ 	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;
++	}
++
+ 	/*
+ 	 * Store reference to the cmd used to register for AEN. When an
+ 	 * application wants us to register for AEN, we have to abort this
+@@ -2968,6 +3032,7 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ 	*instance->producer = 0;
+ 	*instance->consumer = 0;
+ 	megasas_poll_wait_aen = 0;
++	instance->flag_ieee = 0;
+ 	instance->ev = NULL;
+ 
+ 	instance->evt_detail = pci_alloc_consistent(pdev,
+@@ -3008,6 +3073,7 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ 
+ 	if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0073SKINNY) ||
+ 		(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);
+diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h
+index 29cd2c877952..a22d8d48b7dd 100644
+--- a/drivers/scsi/megaraid/megaraid_sas.h
++++ b/drivers/scsi/megaraid/megaraid_sas.h
+@@ -96,6 +96,7 @@
+ #define MFI_FRAME_DIR_WRITE			0x0008
+ #define MFI_FRAME_DIR_READ			0x0010
+ #define MFI_FRAME_DIR_BOTH			0x0018
++#define MFI_FRAME_IEEE                          0x0020
+ 
+ /*
+  * Definition for cmd_status
+@@ -772,10 +773,17 @@ struct megasas_sge64 {
+ 
+ } __attribute__ ((packed));
+ 
++struct megasas_sge_skinny {
++	u64 phys_addr;
++	u32 length;
++	u32 flag;
++} __packed;
++
+ union megasas_sgl {
+ 
+ 	struct megasas_sge32 sge32[1];
+ 	struct megasas_sge64 sge64[1];
++	struct megasas_sge_skinny sge_skinny[1];
+ 
+ } __attribute__ ((packed));
+ 
+@@ -1248,6 +1256,7 @@ struct megasas_instance {
+ 
+ 	u8 flag;
+ 	u8 unload;
++	u8 flag_ieee;
+ 	unsigned long last_time;
+ 
+ 	struct timer_list io_completion_timer;
+-- 
+1.8.0
+
+

Added: dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0011-megaraid_sas-add-online-controller-reset-to-megaraid-sas-drive.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0011-megaraid_sas-add-online-controller-reset-to-megaraid-sas-drive.patch	Sun Dec 16 23:23:22 2012	(r19615)
@@ -0,0 +1,1391 @@
+From dd7927ad22329bf32c0a8a8d1168b370c89b7594 Mon Sep 17 00:00:00 2001
+From: bo yang <boyang1288 at gmail.com>
+Date: Wed, 22 Sep 2010 22:36:29 -0400
+Subject: [PATCH 11/53] [SCSI] megaraid_sas: Add Online Controller Reset to  MegaRAID SAS drive
+
+commit 39a985547cbfcbb0b23667b69b8ae82a6cf312ac upstream.
+
+To add the Online controller reset support, driver need to do:
+a). reset the controller chips -- Xscale and Gen2 which will change
+the function calls and add the reset function related to this two
+chips.
+b). during the reset, driver will store the pending cmds which not
+returned by FW to driver's pending queue.  Driver will re-issue those
+pending cmds again to FW after the OCR finished.
+c). In driver's timeout routine, driver will report to OS as reset.
+Also driver's queue routine will block the cmds until the OCR
+finished.
+d). in Driver's ISR routine, if driver get the FW state as state
+change, FW in Failure status and FW support online controller
+reset (OCR), driver will start to do the controller reset.
+e). In driver's IOCTL routine, the application cmds will wait for the
+OCR to finish, then issue the cmds to FW.
+
+Signed-off-by: Bo Yang <bo.yang at lsi.com>
+Signed-off-by: James Bottomley <James.Bottomley at suse.de>
+Signed-off-by: Jonathan Nieder <jrnieder at gmail.com>
+---
+ drivers/scsi/megaraid/megaraid_sas.c | 756 ++++++++++++++++++++++++++++++++---
+ drivers/scsi/megaraid/megaraid_sas.h |  88 +++-
+ 2 files changed, 787 insertions(+), 57 deletions(-)
+
+diff --git a/drivers/scsi/megaraid/megaraid_sas.c b/drivers/scsi/megaraid/megaraid_sas.c
+index 2b9e3c68c3e7..72c925d9e0f3 100644
+--- a/drivers/scsi/megaraid/megaraid_sas.c
++++ b/drivers/scsi/megaraid/megaraid_sas.c
+@@ -61,6 +61,11 @@ MODULE_VERSION(MEGASAS_VERSION);
+ MODULE_AUTHOR("megaraidlinux at lsi.com");
+ MODULE_DESCRIPTION("LSI MegaRAID SAS Driver");
+ 
++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);
+ /*
+  * PCI ID table for all supported controllers
+  */
+@@ -163,7 +168,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);
+@@ -199,24 +204,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;
+ }
+ 
+ /**
+@@ -231,8 +239,69 @@ megasas_fire_cmd_xscale(struct megasas_instance *instance,
+ 		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(KERN_NOTICE "pcidata = %x\n", pcidata);
++	if (pcidata & 0x2) {
++		printk(KERN_NOTICE "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(KERN_NOTICE "1068 offset handshake read=%x\n", pcidata);
++		if ((pcidata & 0xffff0000) == MFI_1068_FW_READY) {
++			printk(KERN_NOTICE "1068 offset pcidt=%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 = {
+@@ -242,6 +311,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,
+ };
+ 
+ /**
+@@ -263,7 +334,7 @@ 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);
+@@ -306,7 +377,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;
+ 	}
+ 
+ 	/*
+@@ -317,7 +388,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
+@@ -331,10 +402,34 @@ megasas_fire_cmd_ppc(struct megasas_instance *instance,
+ 		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 = {
+ 	
+ 	.fire_cmd = megasas_fire_cmd_ppc,
+@@ -342,6 +437,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,
+ };
+ 
+ /**
+@@ -396,7 +493,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;
+ 	}
+ 
+ 	/*
+@@ -409,7 +506,7 @@ megasas_clear_intr_skinny(struct megasas_register_set __iomem *regs)
+ 	*/
+ 	readl(&regs->outbound_intr_status);
+ 
+-	return 0;
++	return 1;
+ }
+ 
+ /**
+@@ -425,11 +522,33 @@ megasas_fire_cmd_skinny(struct megasas_instance *instance,
+ 			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);
++}
++
++/**
++ * 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 = {
+@@ -439,6 +558,8 @@ 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,
+ };
+ 
+ 
+@@ -494,23 +615,29 @@ static int
+ megasas_clear_intr_gen2(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_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);
++	if (mfiStatus)
++		writel(status, &regs->outbound_doorbell_clear);
+ 
+ 	/* Dummy readl to force pci flush */
+ 	readl(&regs->outbound_intr_status);
+ 
+-	return 0;
++	return mfiStatus;
+ }
+ /**
+  * megasas_fire_cmd_gen2 -     Sends command to the FW
+@@ -524,8 +651,74 @@ megasas_fire_cmd_gen2(struct megasas_instance *instance,
+ 			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_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 ;
++	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(KERN_NOTICE "RESETGEN2: retry=%x, hostdiag=%x\n",
++					retry, HostDiag);
++
++		if (retry++ >= 100)
++			return 1;
++
++	}
++
++	printk(KERN_NOTICE "ADP_RESET_GEN2: HostDiag=%x\n", HostDiag);
++
++	writel((HostDiag | DIAG_RESET_ADAPTER), &reg_set->host_diag);
++
++	ssleep(10);
++
++	HostDiag = (u32)readl(&reg_set->host_diag);
++	while ( ( HostDiag & DIAG_RESET_ADAPTER) ) {
++		msleep(100);
++		HostDiag = (u32)readl(&reg_set->host_diag);
++		printk(KERN_NOTICE "RESET_GEN2: retry=%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 = {
+@@ -535,11 +728,13 @@ static struct megasas_instance_template megasas_instance_template_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
+-* 	specific to ppc (deviceid : 0x60) controllers
++*       specific to gen2 (deviceid : 0x78, 0x79) controllers
+ */
+ 
+ /**
+@@ -598,8 +793,7 @@ megasas_issue_blocked_cmd(struct megasas_instance *instance,
+ 	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;
+ }
+@@ -647,8 +841,8 @@ megasas_issue_blocked_abort_cmd(struct megasas_instance *instance,
+ 	/*
+ 	 * 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;
+@@ -1118,14 +1312,22 @@ 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);
++	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;
+ 
+@@ -1209,6 +1411,18 @@ static int megasas_slave_configure(struct scsi_device *sdev)
+ 	return 0;
+ }
+ 
++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);
++	}
++}
++
+ /**
+  * megasas_complete_cmd_dpc	 -	Returns FW's controller structure
+  * @instance_addr:			Address of adapter soft state
+@@ -1226,7 +1440,7 @@ 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)
++	if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR )
+ 		return;
+ 
+ 	spin_lock_irqsave(&instance->completion_lock, flags);
+@@ -1236,6 +1450,11 @@ 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(KERN_ERR "Unexpected context value %x\n",
++				context);
++			BUG();
++		}
+ 
+ 		cmd = instance->cmd_list[context];
+ 
+@@ -1285,7 +1504,76 @@ 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;
++
++	spin_lock_irqsave(&instance->hba_lock, flags);
++	adprecovery = instance->adprecovery;
++	spin_unlock_irqrestore(&instance->hba_lock, flags);
++
++	if (adprecovery != MEGASAS_HBA_OPERATIONAL) {
++
++		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(KERN_NOTICE "megasas: HBA reset wait ...\n");
++		for (i = 0; i < wait_time; i++) {
++			msleep(1000);
++			spin_lock_irqsave(&instance->hba_lock, flags);
++			adprecovery = instance->adprecovery;
++			spin_unlock_irqrestore(&instance->hba_lock, flags);
++			if (adprecovery == MEGASAS_HBA_OPERATIONAL)
++				break;
++		}
++
++		if (adprecovery != MEGASAS_HBA_OPERATIONAL) {
++			printk(KERN_NOTICE "megasas: reset: Stopping HBA.\n");
++			spin_lock_irqsave(&instance->hba_lock, flags);
++			instance->adprecovery	= MEGASAS_HW_CRITICAL_ERROR;
++			spin_unlock_irqrestore(&instance->hba_lock, flags);
++			return FAILED;
++		}
++
++		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(KERN_NOTICE "%d:%p reset [%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) {
++				printk(KERN_NOTICE "megasas:%p synch cmds"
++						"reset queue\n",
++						reset_cmd);
++
++				reset_cmd->cmd_status = ENODATA;
++				instance->instancet->fire_cmd(instance,
++						reset_cmd->frame_phys_addr,
++						0, instance->reg_set);
++			} else {
++				printk(KERN_NOTICE "megasas: %p unexpected"
++					"cmds lst\n",
++					reset_cmd);
++			}
++			reset_index++;
++		}
++
++		return SUCCESS;
++	}
+ 
+ 	for (i = 0; i < wait_time; i++) {
+ 
+@@ -1308,6 +1596,7 @@ static int megasas_wait_for_outstanding(struct megasas_instance *instance)
+ 	}
+ 
+ 	if (atomic_read(&instance->fw_outstanding)) {
++		printk(KERN_NOTICE "megaraid_sas: pending cmds after reset\n");
+ 		/*
+ 		* Send signal to FW to stop processing any pending cmds.
+ 		* The controller will be taken offline by the OS now.
+@@ -1323,10 +1612,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(KERN_NOTICE "megaraid_sas: no pending cmds after reset\n");
++
+ 	return SUCCESS;
+ }
+ 
+@@ -1348,7 +1641,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;
+@@ -1503,7 +1796,8 @@ 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) {
+@@ -1597,6 +1891,9 @@ megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd,
+ 	struct megasas_header *hdr = &cmd->frame->hdr;
+ 	unsigned long flags;
+ 
++	/* flag for the retry reset */
++	cmd->retry_for_fw_reset = 0;
++
+ 	if (cmd->scmd)
+ 		cmd->scmd->SCp.ptr = NULL;
+ 
+@@ -1717,39 +2014,301 @@ megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd,
+ }
+ 
+ /**
++ * 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(KERN_NOTICE "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 (cmd->retry_for_fw_reset == 3) {
++				printk(KERN_NOTICE "megaraid_sas: cmd %p, %p:%d"
++					"was tried multiple times during 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(KERN_NOTICE "megaraid_sas: unexpected"
++					"cmd attached to internal command!\n");
++			}
++			printk(KERN_NOTICE "megasas: %p synchronous cmd"
++						"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(KERN_NOTICE "megasas: %p scsi cmd [%02x],%#lx"
++			"detected on the internal queue, issue 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(KERN_NOTICE "megasas: %p unexpected cmd on the"
++				"internal reset defer list while re-issue!!\n",
++				cmd);
++		}
++	}
++
++	if (instance->aen_cmd) {
++		printk(KERN_NOTICE "megaraid_sas: aen_cmd in def process\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(KERN_NOTICE "megasas: moving cmd[%d]:%p:%d:%p"
++					"on the defer queue as internal\n",
++				defer_index, cmd, cmd->sync_cmd, cmd->scmd);
++
++			if (!list_empty(&cmd->list)) {
++				printk(KERN_NOTICE "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(struct work_struct *work)
++{
++	struct megasas_instance *instance =
++		container_of(work, struct megasas_instance, work_init);
++	u32 wait;
++	unsigned long flags;
++
++	if (instance->adprecovery != MEGASAS_ADPRESET_SM_INFAULT) {
++		printk(KERN_NOTICE "megaraid_sas: error, recovery st %x \n",
++				instance->adprecovery);
++		return ;
++	}
++
++	if (instance->adprecovery == MEGASAS_ADPRESET_SM_INFAULT) {
++		printk(KERN_NOTICE "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(KERN_NOTICE "megaraid_sas: FW restarted successfully,"
++					"initiating next stage...\n");
++
++		printk(KERN_NOTICE "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(KERN_NOTICE "megaraid_sas:adapter not ready\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;
++		}
++
++		megasas_issue_init_mfi(instance);
++
++		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);
++
++		megasas_issue_pending_cmds_again(instance);
++		instance->issuepend_done = 1;
++	}
++	return ;
++}
++
++/**
+  * megasas_deplete_reply_queue -	Processes all completed commands
+  * @instance:				Adapter soft state
+  * @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)
++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 ((mfiStatus = instance->instancet->check_reset(instance,
++					instance->reg_set)) == 1) {
++		return IRQ_HANDLED;
++	}
++
++	if ((mfiStatus = instance->instancet->clear_intr(
++						instance->reg_set)
++						) == 0) {
+ 		return IRQ_NONE;
++	}
++
++	instance->mfiStatus = mfiStatus;
++
++	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(KERN_NOTICE "megaraid_sas: fw state:%x\n",
++						fw_state);
++		}
++
++		if ((fw_state == MFI_STATE_FAULT) &&
++				(instance->disableOnlineCtrlReset == 0)) {
++			printk(KERN_NOTICE "megaraid_sas: wait adp 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;
++			instance->issuepend_done = 0;
++
++			atomic_set(&instance->fw_outstanding, 0);
++			megasas_internal_reset_defer_cmds(instance);
++
++			printk(KERN_NOTICE "megasas: fwState=%x, stage:%d\n",
++					fw_state, instance->adprecovery);
++
++			schedule_work(&instance->work_init);
++			return IRQ_HANDLED;
++
++		} else {
++			printk(KERN_NOTICE "megasas: fwstate:%x, dis_OCR=%x\n",
++				fw_state, instance->disableOnlineCtrlReset);
++		}
++	}
+ 
+-	if (instance->hw_crit_error)
+-		goto out_done;
+-        /*
+-	 * Schedule the tasklet for cmd completion
+-	 */
+ 	tasklet_schedule(&instance->isr_tasklet);
+-out_done:
+ 	return IRQ_HANDLED;
+ }
+-
+ /**
+  * megasas_isr - isr entry point
+  */
+ static irqreturn_t megasas_isr(int irq, void *devp)
+ {
+-	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;
+ }
+ 
+ /**
+@@ -1900,7 +2459,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;
+@@ -1982,6 +2541,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
+@@ -2129,6 +2689,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);
+@@ -2295,7 +2856,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);
+ 
+ 		for (ld_index = 0; ld_index < ci->ldCount; ld_index++) {
+@@ -2606,6 +3167,21 @@ 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(KERN_NOTICE "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.
++	*/
++
+ 	memset(instance->pd_list, 0 ,
+ 		(MEGASAS_MAX_PD * sizeof(struct megasas_pd_list)));
+ 	megasas_get_pd_list(instance);
+@@ -2632,6 +3208,8 @@ static int megasas_init_mfi(struct megasas_instance *instance)
+ 		max_sectors_2 = ctrl_info->max_request_size;
+ 
+ 		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 *
+@@ -2849,6 +3427,7 @@ megasas_register_aen(struct megasas_instance *instance, u32 seq_num,
+ 	dcmd->sge_count = 1;
+ 	dcmd->flags = MFI_FRAME_DIR_READ;
+ 	dcmd->timeout = 0;
++	instance->last_seq_num = seq_num;
+ 	dcmd->data_xfer_len = sizeof(struct megasas_evt_detail);
+ 	dcmd->opcode = MR_DCMD_CTRL_EVENT_WAIT;
+ 	dcmd->mbox.w[0] = seq_num;
+@@ -3017,6 +3596,7 @@ 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);
+@@ -3034,6 +3614,9 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ 	megasas_poll_wait_aen = 0;
+ 	instance->flag_ieee = 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
+@@ -3050,6 +3633,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);
+ 
+@@ -3057,7 +3641,7 @@ 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);
+ 	spin_lock_init(&poll_aen_lock);
+ 
+@@ -3082,6 +3666,9 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ 	instance->flag = 0;
+ 	instance->unload = 1;
+ 	instance->last_time = 0;
++	instance->disableOnlineCtrlReset = 1;
++
++	INIT_WORK(&instance->work_init, process_fw_state_change_wq);
+ 
+ 	/*
+ 	 * Initialize MFI Firmware
+@@ -3173,6 +3760,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)
+@@ -3209,6 +3799,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)
+@@ -3716,6 +4309,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)
+@@ -3732,8 +4328,8 @@ static int megasas_mgmt_ioctl_fw(struct file *file, unsigned long arg)
+ 		goto out_kfree_ioc;
+ 	}
+ 
+-	if (instance->hw_crit_error == 1) {
+-		printk(KERN_DEBUG "Controller in Crit ERROR\n");
++	if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR) {
++		printk(KERN_ERR "Controller in crit error\n");
+ 		error = -ENODEV;
+ 		goto out_kfree_ioc;
+ 	}
+@@ -3750,6 +4346,35 @@ static int megasas_mgmt_ioctl_fw(struct file *file, unsigned long arg)
+ 		error = -ERESTARTSYS;
+ 		goto out_kfree_ioc;
+ 	}
++
++	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(KERN_ERR "megaraid_sas: timed out while"
++			"waiting for HBA to recover\n");
++		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);
+ 
+@@ -3763,6 +4388,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 "
+@@ -3778,14 +4406,42 @@ 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;
+ 	}
+ 
++	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(KERN_ERR "megaraid_sas: timed out while waiting"
++				"for HBA to recover.\n");
++		return -ENODEV;
++	}
++	spin_unlock_irqrestore(&instance->hba_lock, flags);
++
+ 	mutex_lock(&instance->aen_mutex);
+ 	error = megasas_register_aen(instance, aen.seq_num,
+ 				     aen.class_locale_word);
+diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h
+index a22d8d48b7dd..a231aa811e56 100644
+--- a/drivers/scsi/megaraid/megaraid_sas.h
++++ b/drivers/scsi/megaraid/megaraid_sas.h
+@@ -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,12 @@
+  * 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
+@@ -402,8 +409,40 @@ 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;
++	u8 loadBalanceMode;
++	u8 disableAutoDetectBackplane;
+ 
++	u8 snapVDSpace;
++
++	/*
++	* Add properties that can be controlled by
++	* a bit in the following structure.
++	*/
++
++	struct {
++		u32     copyBackDisabled            : 1;
++		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;
++	u8 viewSpace;
++	u16 spinDownTime;
++	u8  reserved[24];
+ } __packed;
+ 
+ /*
+@@ -704,6 +743,12 @@ struct megasas_ctrl_info {
+  */
+ #define IS_DMA64				(sizeof(dma_addr_t) == 8)
+ 
++#define MFI_XSCALE_OMR0_CHANGE_INTERRUPT		0x00000001
++
++#define MFI_INTR_FLAG_REPLY_MESSAGE			0x00000001
++#define MFI_INTR_FLAG_FIRMWARE_STATE_CHANGE		0x00000002
++#define MFI_G2_OUTBOUND_DOORBELL_CHANGE_INTERRUPT	0x00000004
++
+ #define MFI_OB_INTR_STATUS_MASK			0x00000002
+ #define MFI_POLL_TIMEOUT_SECS			60
+ #define MEGASAS_COMPLETION_TIMER_INTERVAL      (HZ/10)
+@@ -714,6 +759,9 @@ struct megasas_ctrl_info {
+ #define MFI_REPLY_SKINNY_MESSAGE_INTERRUPT	0x40000000
+ #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
+ /*
+ * register set for both 1068 and 1078 controllers
+ * structure extended for 1078 registers
+@@ -755,8 +803,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));
+ 
+ struct megasas_sge32 {
+@@ -1226,11 +1276,12 @@ struct megasas_instance {
+ 
+ 	struct megasas_cmd **cmd_list;
+ 	struct list_head cmd_pool;
++	/* used to sync fire the cmd to fw */
+ 	spinlock_t cmd_pool_lock;
++	/* used to sync fire the cmd to fw */
++	spinlock_t hba_lock;
+ 	/* used to synch producer, consumer ptrs in dpc */
+ 	spinlock_t completion_lock;
+-	/* used to sync fire the cmd to fw */
+-	spinlock_t fire_lock;
+ 	struct dma_pool *frame_dma_pool;
+ 	struct dma_pool *sense_dma_pool;
+ 
+@@ -1247,19 +1298,36 @@ 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;
++	struct work_struct work_init;
+ 
+ 	u8 flag;
+ 	u8 unload;
+ 	u8 flag_ieee;
++	u8 issuepend_done;
++	u8 disableOnlineCtrlReset;
++	u8 adprecovery;
+ 	unsigned long last_time;
++	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 {
+@@ -1272,6 +1340,10 @@ struct megasas_instance_template {
+ 	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)						\
+@@ -1291,7 +1363,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;
+-- 
+1.8.0
+
+

Added: dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0012-megaraid_sas-rename-megaraid_sas.c-to-megaraid_sas_base.c.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0012-megaraid_sas-rename-megaraid_sas.c-to-megaraid_sas_base.c.patch	Sun Dec 16 23:23:22 2012	(r19615)
@@ -0,0 +1,10056 @@
+From cdbbdbaf9a0935163a8ba6c1210f3468dd6c1ae3 Mon Sep 17 00:00:00 2001
+From: adam radford <aradford at gmail.com>
+Date: Tue, 14 Dec 2010 19:17:17 -0800
+Subject: [PATCH 12/53] [SCSI] megaraid_sas: Rename megaraid_sas.c to  megaraid_sas_base.c
+
+commit 0d49016bbab4fe9164710b1d4bbae116b89b7f7e upstream.
+
+This patch renames megaraid_sas.c to megaraid_sas_base.c to facilitate
+other files in the compile.
+
+Signed-off-by: Adam Radford <aradford at gmail.com>
+Signed-off-by: James Bottomley <James.Bottomley at suse.de>
+Signed-off-by: Jonathan Nieder <jrnieder at gmail.com>
+---
+ drivers/scsi/megaraid/Makefile            |    1 +
+ drivers/scsi/megaraid/megaraid_sas.c      | 5005 -----------------------------
+ drivers/scsi/megaraid/megaraid_sas_base.c | 5005 +++++++++++++++++++++++++++++
+ 3 files changed, 5006 insertions(+), 5005 deletions(-)
+ delete mode 100644 drivers/scsi/megaraid/megaraid_sas.c
+ create mode 100644 drivers/scsi/megaraid/megaraid_sas_base.c
+
+diff --git a/drivers/scsi/megaraid/Makefile b/drivers/scsi/megaraid/Makefile
+index f469915b97c3..6613a2ceea03 100644
+--- a/drivers/scsi/megaraid/Makefile
++++ b/drivers/scsi/megaraid/Makefile
+@@ -1,3 +1,4 @@
+ obj-$(CONFIG_MEGARAID_MM)	+= megaraid_mm.o
+ obj-$(CONFIG_MEGARAID_MAILBOX)	+= megaraid_mbox.o
+ obj-$(CONFIG_MEGARAID_SAS)	+= megaraid_sas.o
++megaraid_sas-objs := megaraid_sas_base.o
+diff --git a/drivers/scsi/megaraid/megaraid_sas.c b/drivers/scsi/megaraid/megaraid_sas.c
+deleted file mode 100644
+index 72c925d9e0f3..000000000000
+--- a/drivers/scsi/megaraid/megaraid_sas.c
++++ /dev/null
+@@ -1,5005 +0,0 @@
+-/*
+- *
+- *		Linux MegaRAID driver for SAS based RAID controllers
+- *
+- * Copyright (c) 2003-2005  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.
+- *
+- * FILE		: megaraid_sas.c
+- * Version     : v00.00.04.01-rc1
+- *
+- * Authors:
+- *	(email-id : megaraidlinux at lsi.com)
+- * 	Sreenivas Bagalkote
+- * 	Sumant Patro
+- *	Bo Yang
+- *
+- * List of supported controllers
+- *
+- * OEM	Product Name			VID	DID	SSVID	SSID
+- * ---	------------			---	---	----	----
+- */
+-
+-#include <linux/kernel.h>
+-#include <linux/types.h>
+-#include <linux/pci.h>
+-#include <linux/list.h>
+-#include <linux/moduleparam.h>
+-#include <linux/module.h>
+-#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>
+-#include <linux/compat.h>
+-#include <linux/blkdev.h>
+-#include <linux/mutex.h>
+-#include <linux/poll.h>
+-
+-#include <scsi/scsi.h>
+-#include <scsi/scsi_cmnd.h>
+-#include <scsi/scsi_device.h>
+-#include <scsi/scsi_host.h>
+-#include "megaraid_sas.h"
+-
+-/*
+- * poll_mode_io:1- schedule complete completion from q cmd
+- */
+-static unsigned int poll_mode_io;
+-module_param_named(poll_mode_io, poll_mode_io, int, 0);
+-MODULE_PARM_DESC(poll_mode_io,
+-	"Complete cmds from IO path, (default=0)");
+-
+-MODULE_LICENSE("GPL");
+-MODULE_VERSION(MEGASAS_VERSION);
+-MODULE_AUTHOR("megaraidlinux at lsi.com");
+-MODULE_DESCRIPTION("LSI MegaRAID SAS Driver");
+-
+-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);
+-/*
+- * PCI ID table for all supported controllers
+- */
+-static struct pci_device_id megasas_pci_table[] = {
+-
+-	{PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1064R)},
+-	/* 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)},
+-	/* gen2*/
+-	{PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS0073SKINNY)},
+-	/* 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_VERDE_ZCR)},
+-	/* xscale IOP, vega */
+-	{PCI_DEVICE(PCI_VENDOR_ID_DELL, PCI_DEVICE_ID_DELL_PERC5)},
+-	/* xscale IOP */
+-	{}
+-};
+-
+-MODULE_DEVICE_TABLE(pci, megasas_pci_table);
+-
+-static int megasas_mgmt_majorno;
+-static struct megasas_mgmt_info megasas_mgmt_info;
+-static struct fasync_struct *megasas_async_queue;
+-static DEFINE_MUTEX(megasas_async_queue_mutex);
+-
+-static int megasas_poll_wait_aen;
+-static DECLARE_WAIT_QUEUE_HEAD(megasas_poll_wait);
+-static u32 support_poll_for_event;
+-static u32 megasas_dbg_lvl;
+-
+-/* define lock for aen poll */
+-spinlock_t poll_aen_lock;
+-
+-static void
+-megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd,
+-		     u8 alt_status);
+-
+-/**
+- * megasas_get_cmd -	Get a command from the free pool
+- * @instance:		Adapter soft state
+- *
+- * Returns a free command from the pool
+- */
+-static struct megasas_cmd *megasas_get_cmd(struct megasas_instance
+-						  *instance)
+-{
+-	unsigned long flags;
+-	struct megasas_cmd *cmd = NULL;
+-
+-	spin_lock_irqsave(&instance->cmd_pool_lock, flags);
+-
+-	if (!list_empty(&instance->cmd_pool)) {
+-		cmd = list_entry((&instance->cmd_pool)->next,
+-				 struct megasas_cmd, list);
+-		list_del_init(&cmd->list);
+-	} else {
+-		printk(KERN_ERR "megasas: Command pool empty!\n");
+-	}
+-
+-	spin_unlock_irqrestore(&instance->cmd_pool_lock, flags);
+-	return cmd;
+-}
+-
+-/**
+- * megasas_return_cmd -	Return a cmd to free command pool
+- * @instance:		Adapter soft state
+- * @cmd:		Command packet to be returned to free command pool
+- */
+-static inline void
+-megasas_return_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd)
+-{
+-	unsigned long flags;
+-
+-	spin_lock_irqsave(&instance->cmd_pool_lock, flags);
+-
+-	cmd->scmd = NULL;
+-	list_add_tail(&cmd->list, &instance->cmd_pool);
+-
+-	spin_unlock_irqrestore(&instance->cmd_pool_lock, flags);
+-}
+-
+-
+-/**
+-*	The following functions are defined for xscale 
+-*	(deviceid : 1064R, PERC5) controllers
+-*/
+-
+-/**
+- * megasas_enable_intr_xscale -	Enables interrupts
+- * @regs:			MFI register set
+- */
+-static inline void
+-megasas_enable_intr_xscale(struct megasas_register_set __iomem * regs)
+-{
+-	writel(0, &(regs)->outbound_intr_mask);
+-
+-	/* Dummy readl to force pci flush */
+-	readl(&regs->outbound_intr_mask);
+-}
+-
+-/**
+- * megasas_disable_intr_xscale -Disables interrupt
+- * @regs:			MFI register set
+- */
+-static inline void
+-megasas_disable_intr_xscale(struct megasas_register_set __iomem * regs)
+-{
+-	u32 mask = 0x1f;
+-	writel(mask, &regs->outbound_intr_mask);
+-	/* Dummy readl to force pci flush */
+-	readl(&regs->outbound_intr_mask);
+-}
+-
+-/**
+- * megasas_read_fw_status_reg_xscale - returns the current FW status value
+- * @regs:			MFI register set
+- */
+-static u32
+-megasas_read_fw_status_reg_xscale(struct megasas_register_set __iomem * regs)
+-{
+-	return readl(&(regs)->outbound_msg_0);
+-}
+-/**
+- * megasas_clear_interrupt_xscale -	Check & clear interrupt
+- * @regs:				MFI register set
+- */
+-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)
+-		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
+-	 */
+-	if (mfiStatus)
+-		writel(status, &regs->outbound_intr_status);
+-
+-	/* Dummy readl to force pci flush */
+-	readl(&regs->outbound_intr_status);
+-
+-	return mfiStatus;
+-}
+-
+-/**
+- * megasas_fire_cmd_xscale -	Sends command to the FW
+- * @frame_phys_addr :		Physical address of cmd
+- * @frame_count :		Number of frames for the command
+- * @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)
+-{
+-	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(KERN_NOTICE "pcidata = %x\n", pcidata);
+-	if (pcidata & 0x2) {
+-		printk(KERN_NOTICE "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(KERN_NOTICE "1068 offset handshake read=%x\n", pcidata);
+-		if ((pcidata & 0xffff0000) == MFI_1068_FW_READY) {
+-			printk(KERN_NOTICE "1068 offset pcidt=%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 = {
+-
+-	.fire_cmd = megasas_fire_cmd_xscale,
+-	.enable_intr = megasas_enable_intr_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,
+-};
+-
+-/**
+-*	This is the end of set of functions & definitions specific 
+-*	to xscale (deviceid : 1064R, PERC5) controllers
+-*/
+-
+-/**
+-*	The following functions are defined for ppc (deviceid : 0x60) 
+-* 	controllers
+-*/
+-
+-/**
+- * megasas_enable_intr_ppc -	Enables interrupts
+- * @regs:			MFI register set
+- */
+-static inline void
+-megasas_enable_intr_ppc(struct megasas_register_set __iomem * regs)
+-{
+-	writel(0xFFFFFFFF, &(regs)->outbound_doorbell_clear);
+-    
+-	writel(~0x80000000, &(regs)->outbound_intr_mask);
+-
+-	/* Dummy readl to force pci flush */
+-	readl(&regs->outbound_intr_mask);
+-}
+-
+-/**
+- * megasas_disable_intr_ppc -	Disable interrupt
+- * @regs:			MFI register set
+- */
+-static inline void
+-megasas_disable_intr_ppc(struct megasas_register_set __iomem * regs)
+-{
+-	u32 mask = 0xFFFFFFFF;
+-	writel(mask, &regs->outbound_intr_mask);
+-	/* Dummy readl to force pci flush */
+-	readl(&regs->outbound_intr_mask);
+-}
+-
+-/**
+- * megasas_read_fw_status_reg_ppc - returns the current FW status value
+- * @regs:			MFI register set
+- */
+-static u32
+-megasas_read_fw_status_reg_ppc(struct megasas_register_set __iomem * regs)
+-{
+-	return readl(&(regs)->outbound_scratch_pad);
+-}
+-
+-/**
+- * megasas_clear_interrupt_ppc -	Check & clear interrupt
+- * @regs:				MFI register set
+- */
+-static int 
+-megasas_clear_intr_ppc(struct megasas_register_set __iomem * regs)
+-{
+-	u32 status;
+-	/*
+-	 * Check if it is our interrupt
+-	 */
+-	status = readl(&regs->outbound_intr_status);
+-
+-	if (!(status & MFI_REPLY_1078_MESSAGE_INTERRUPT)) {
+-		return 0;
+-	}
+-
+-	/*
+-	 * Clear the interrupt by writing back the same value
+-	 */
+-	writel(status, &regs->outbound_doorbell_clear);
+-
+-	/* Dummy readl to force pci flush */
+-	readl(&regs->outbound_doorbell_clear);
+-
+-	return 1;
+-}
+-/**
+- * megasas_fire_cmd_ppc -	Sends command to the FW
+- * @frame_phys_addr :		Physical address of cmd
+- * @frame_count :		Number of frames for the command
+- * @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)
+-{
+-	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 = {
+-	
+-	.fire_cmd = megasas_fire_cmd_ppc,
+-	.enable_intr = megasas_enable_intr_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,
+-};
+-
+-/**
+- * megasas_enable_intr_skinny -	Enables interrupts
+- * @regs:			MFI register set
+- */
+-static inline void
+-megasas_enable_intr_skinny(struct megasas_register_set __iomem *regs)
+-{
+-	writel(0xFFFFFFFF, &(regs)->outbound_intr_mask);
+-
+-	writel(~MFI_SKINNY_ENABLE_INTERRUPT_MASK, &(regs)->outbound_intr_mask);
+-
+-	/* Dummy readl to force pci flush */
+-	readl(&regs->outbound_intr_mask);
+-}
+-
+-/**
+- * megasas_disable_intr_skinny -	Disables interrupt
+- * @regs:			MFI register set
+- */
+-static inline void
+-megasas_disable_intr_skinny(struct megasas_register_set __iomem *regs)
+-{
+-	u32 mask = 0xFFFFFFFF;
+-	writel(mask, &regs->outbound_intr_mask);
+-	/* Dummy readl to force pci flush */
+-	readl(&regs->outbound_intr_mask);
+-}
+-
+-/**
+- * megasas_read_fw_status_reg_skinny - returns the current FW status value
+- * @regs:			MFI register set
+- */
+-static u32
+-megasas_read_fw_status_reg_skinny(struct megasas_register_set __iomem *regs)
+-{
+-	return readl(&(regs)->outbound_scratch_pad);
+-}
+-
+-/**
+- * megasas_clear_interrupt_skinny -	Check & clear interrupt
+- * @regs:				MFI register set
+- */
+-static int
+-megasas_clear_intr_skinny(struct megasas_register_set __iomem *regs)
+-{
+-	u32 status;
+-	/*
+-	 * Check if it is our interrupt
+-	 */
+-	status = readl(&regs->outbound_intr_status);
+-
+-	if (!(status & MFI_SKINNY_ENABLE_INTERRUPT_MASK)) {
+-		return 0;
+-	}
+-
+-	/*
+-	 * Clear the interrupt by writing back the same value
+-	 */
+-	writel(status, &regs->outbound_intr_status);
+-
+-	/*
+-	* dummy read to flush PCI
+-	*/
+-	readl(&regs->outbound_intr_status);
+-
+-	return 1;
+-}
+-
+-/**
+- * megasas_fire_cmd_skinny -	Sends command to the FW
+- * @frame_phys_addr :		Physical address of cmd
+- * @frame_count :		Number of frames for the command
+- * @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)
+-{
+-	unsigned long 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->hba_lock, flags);
+-}
+-
+-/**
+- * 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,
+-	.enable_intr = megasas_enable_intr_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,
+-};
+-
+-
+-/**
+-*	The following functions are defined for gen2 (deviceid : 0x78 0x79)
+-*	controllers
+-*/
+-
+-/**
+- * megasas_enable_intr_gen2 -  Enables interrupts
+- * @regs:                      MFI register set
+- */
+-static inline void
+-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);
+-
+-	/* Dummy readl to force pci flush */
+-	readl(&regs->outbound_intr_mask);
+-}
+-
+-/**
+- * megasas_disable_intr_gen2 - Disables interrupt
+- * @regs:                      MFI register set
+- */
+-static inline void
+-megasas_disable_intr_gen2(struct megasas_register_set __iomem *regs)
+-{
+-	u32 mask = 0xFFFFFFFF;
+-	writel(mask, &regs->outbound_intr_mask);
+-	/* Dummy readl to force pci flush */
+-	readl(&regs->outbound_intr_mask);
+-}
+-
+-/**
+- * megasas_read_fw_status_reg_gen2 - returns the current FW status value
+- * @regs:                      MFI register set
+- */
+-static u32
+-megasas_read_fw_status_reg_gen2(struct megasas_register_set __iomem *regs)
+-{
+-	return readl(&(regs)->outbound_scratch_pad);
+-}
+-
+-/**
+- * megasas_clear_interrupt_gen2 -      Check & clear interrupt
+- * @regs:                              MFI register set
+- */
+-static int
+-megasas_clear_intr_gen2(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_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
+-	 */
+-	if (mfiStatus)
+-		writel(status, &regs->outbound_doorbell_clear);
+-
+-	/* Dummy readl to force pci flush */
+-	readl(&regs->outbound_intr_status);
+-
+-	return mfiStatus;
+-}
+-/**
+- * megasas_fire_cmd_gen2 -     Sends command to the FW
+- * @frame_phys_addr :          Physical address of cmd
+- * @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)
+-{
+-	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_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 ;
+-	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(KERN_NOTICE "RESETGEN2: retry=%x, hostdiag=%x\n",
+-					retry, HostDiag);
+-
+-		if (retry++ >= 100)
+-			return 1;
+-
+-	}
+-
+-	printk(KERN_NOTICE "ADP_RESET_GEN2: HostDiag=%x\n", HostDiag);
+-
+-	writel((HostDiag | DIAG_RESET_ADAPTER), &reg_set->host_diag);
+-
+-	ssleep(10);
+-
+-	HostDiag = (u32)readl(&reg_set->host_diag);
+-	while ( ( HostDiag & DIAG_RESET_ADAPTER) ) {
+-		msleep(100);
+-		HostDiag = (u32)readl(&reg_set->host_diag);
+-		printk(KERN_NOTICE "RESET_GEN2: retry=%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
+-*       specific to gen2 (deviceid : 0x78, 0x79) controllers
+-*/
+-
+-/**
+- * megasas_issue_polled -	Issues a polling command
+- * @instance:			Adapter soft state
+- * @cmd:			Command packet to be issued 
+- *
+- * For polling, MFI requires the cmd_status to be set to 0xFF before posting.
+- */
+-static int
+-megasas_issue_polled(struct megasas_instance *instance, struct megasas_cmd *cmd)
+-{
+-	int i;
+-	u32 msecs = MFI_POLL_TIMEOUT_SECS * 1000;
+-
+-	struct megasas_header *frame_hdr = &cmd->frame->hdr;
+-
+-	frame_hdr->cmd_status = 0xFF;
+-	frame_hdr->flags |= MFI_FRAME_DONT_POST_IN_REPLY_QUEUE;
+-
+-	/*
+-	 * Issue the frame using inbound queue port
+-	 */
+-	instance->instancet->fire_cmd(instance,
+-			cmd->frame_phys_addr, 0, instance->reg_set);
+-
+-	/*
+-	 * Wait for cmd_status to change
+-	 */
+-	for (i = 0; (i < msecs) && (frame_hdr->cmd_status == 0xff); i++) {
+-		rmb();
+-		msleep(1);
+-	}
+-
+-	if (frame_hdr->cmd_status == 0xff)
+-		return -ETIME;
+-
+-	return 0;
+-}
+-
+-/**
+- * megasas_issue_blocked_cmd -	Synchronous wrapper around regular FW cmds
+- * @instance:			Adapter soft state
+- * @cmd:			Command to be issued
+- *
+- * This function waits on an event for the command to be returned from ISR.
+- * Max wait time is MEGASAS_INTERNAL_CMD_WAIT_TIME secs
+- * Used to issue ioctl commands.
+- */
+-static int
+-megasas_issue_blocked_cmd(struct megasas_instance *instance,
+-			  struct megasas_cmd *cmd)
+-{
+-	cmd->cmd_status = ENODATA;
+-
+-	instance->instancet->fire_cmd(instance,
+-			cmd->frame_phys_addr, 0, instance->reg_set);
+-
+-	wait_event(instance->int_cmd_wait_q, cmd->cmd_status != ENODATA);
+-
+-	return 0;
+-}
+-
+-/**
+- * megasas_issue_blocked_abort_cmd -	Aborts previously issued cmd
+- * @instance:				Adapter soft state
+- * @cmd_to_abort:			Previously issued cmd to be aborted
+- *
+- * MFI firmware can abort previously issued AEN comamnd (automatic event
+- * notification). The megasas_issue_blocked_abort_cmd() issues such abort
+- * cmd and waits for return status.
+- * Max wait time is MEGASAS_INTERNAL_CMD_WAIT_TIME secs
+- */
+-static int
+-megasas_issue_blocked_abort_cmd(struct megasas_instance *instance,
+-				struct megasas_cmd *cmd_to_abort)
+-{
+-	struct megasas_cmd *cmd;
+-	struct megasas_abort_frame *abort_fr;
+-
+-	cmd = megasas_get_cmd(instance);
+-
+-	if (!cmd)
+-		return -1;
+-
+-	abort_fr = &cmd->frame->abort;
+-
+-	/*
+-	 * Prepare and issue the abort frame
+-	 */
+-	abort_fr->cmd = MFI_CMD_ABORT;
+-	abort_fr->cmd_status = 0xFF;
+-	abort_fr->flags = 0;
+-	abort_fr->abort_context = cmd_to_abort->index;
+-	abort_fr->abort_mfi_phys_addr_lo = cmd_to_abort->frame_phys_addr;
+-	abort_fr->abort_mfi_phys_addr_hi = 0;
+-
+-	cmd->sync_cmd = 1;
+-	cmd->cmd_status = 0xFF;
+-
+-	instance->instancet->fire_cmd(instance,
+-			cmd->frame_phys_addr, 0, instance->reg_set);
+-
+-	/*
+-	 * Wait for this cmd to complete
+-	 */
+-	wait_event(instance->abort_cmd_wait_q, cmd->cmd_status != 0xFF);
+-	cmd->sync_cmd = 0;
+-
+-	megasas_return_cmd(instance, cmd);
+-	return 0;
+-}
+-
+-/**
+- * megasas_make_sgl32 -	Prepares 32-bit SGL
+- * @instance:		Adapter soft state
+- * @scp:		SCSI command from the mid-layer
+- * @mfi_sgl:		SGL to be filled in
+- *
+- * If successful, this function returns the number of SG elements. Otherwise,
+- * it returnes -1.
+- */
+-static int
+-megasas_make_sgl32(struct megasas_instance *instance, struct scsi_cmnd *scp,
+-		   union megasas_sgl *mfi_sgl)
+-{
+-	int i;
+-	int sge_count;
+-	struct scatterlist *os_sgl;
+-
+-	sge_count = scsi_dma_map(scp);
+-	BUG_ON(sge_count < 0);
+-
+-	if (sge_count) {
+-		scsi_for_each_sg(scp, os_sgl, sge_count, i) {
+-			mfi_sgl->sge32[i].length = sg_dma_len(os_sgl);
+-			mfi_sgl->sge32[i].phys_addr = sg_dma_address(os_sgl);
+-		}
+-	}
+-	return sge_count;
+-}
+-
+-/**
+- * megasas_make_sgl64 -	Prepares 64-bit SGL
+- * @instance:		Adapter soft state
+- * @scp:		SCSI command from the mid-layer
+- * @mfi_sgl:		SGL to be filled in
+- *
+- * If successful, this function returns the number of SG elements. Otherwise,
+- * it returnes -1.
+- */
+-static int
+-megasas_make_sgl64(struct megasas_instance *instance, struct scsi_cmnd *scp,
+-		   union megasas_sgl *mfi_sgl)
+-{
+-	int i;
+-	int sge_count;
+-	struct scatterlist *os_sgl;
+-
+-	sge_count = scsi_dma_map(scp);
+-	BUG_ON(sge_count < 0);
+-
+-	if (sge_count) {
+-		scsi_for_each_sg(scp, os_sgl, sge_count, i) {
+-			mfi_sgl->sge64[i].length = sg_dma_len(os_sgl);
+-			mfi_sgl->sge64[i].phys_addr = sg_dma_address(os_sgl);
+-		}
+-	}
+-	return sge_count;
+-}
+-
+-/**
+- * 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
+- *
+- * If successful, this function returns the number of SG elements. Otherwise,
+- * it returnes -1.
+- */
+-static int
+-megasas_make_sgl_skinny(struct megasas_instance *instance,
+-		struct scsi_cmnd *scp, union megasas_sgl *mfi_sgl)
+-{
+-	int i;
+-	int sge_count;
+-	struct scatterlist *os_sgl;
+-
+-	sge_count = scsi_dma_map(scp);
+-
+-	if (sge_count) {
+-		scsi_for_each_sg(scp, os_sgl, sge_count, i) {
+-			mfi_sgl->sge_skinny[i].length = sg_dma_len(os_sgl);
+-			mfi_sgl->sge_skinny[i].phys_addr =
+-						sg_dma_address(os_sgl);
+-		}
+-	}
+-	return sge_count;
+-}
+-
+- /**
+- * megasas_get_frame_count - Computes the number of frames
+- * @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)
+- */
+-
+-static u32 megasas_get_frame_count(struct megasas_instance *instance,
+-			u8 sge_count, u8 frame_type)
+-{
+-	int num_cnt;
+-	int sge_bytes;
+-	u32 sge_sz;
+-	u32 frame_count=0;
+-
+-	sge_sz = (IS_DMA64) ? sizeof(struct megasas_sge64) :
+-	    sizeof(struct megasas_sge32);
+-
+-	if (instance->flag_ieee) {
+-		sge_sz = sizeof(struct megasas_sge_skinny);
+-	}
+-
+-	/*
+-	 * Main frame can contain 2 SGEs for 64-bit SGLs and
+-	 * 3 SGEs for 32-bit SGLs for ldio &
+-	 * 1 SGEs for 64-bit SGLs and
+-	 * 2 SGEs for 32-bit SGLs for pthru frame
+-	 */
+-	if (unlikely(frame_type == PTHRU_FRAME)) {
+-		if (instance->flag_ieee == 1) {
+-			num_cnt = sge_count - 1;
+-		} else if (IS_DMA64)
+-			num_cnt = sge_count - 1;
+-		else
+-			num_cnt = sge_count - 2;
+-	} else {
+-		if (instance->flag_ieee == 1) {
+-			num_cnt = sge_count - 1;
+-		} else if (IS_DMA64)
+-			num_cnt = sge_count - 2;
+-		else
+-			num_cnt = sge_count - 3;
+-	}
+-
+-	if(num_cnt>0){
+-		sge_bytes = sge_sz * num_cnt;
+-
+-		frame_count = (sge_bytes / MEGAMFI_FRAME_SIZE) +
+-		    ((sge_bytes % MEGAMFI_FRAME_SIZE) ? 1 : 0) ;
+-	}
+-	/* Main frame */
+-	frame_count +=1;
+-
+-	if (frame_count > 7)
+-		frame_count = 8;
+-	return frame_count;
+-}
+-
+-/**
+- * megasas_build_dcdb -	Prepares a direct cdb (DCDB) command
+- * @instance:		Adapter soft state
+- * @scp:		SCSI command
+- * @cmd:		Command to be prepared in
+- *
+- * This function prepares CDB commands. These are typcially pass-through
+- * commands to the devices.
+- */
+-static int
+-megasas_build_dcdb(struct megasas_instance *instance, struct scsi_cmnd *scp,
+-		   struct megasas_cmd *cmd)
+-{
+-	u32 is_logical;
+-	u32 device_id;
+-	u16 flags = 0;
+-	struct megasas_pthru_frame *pthru;
+-
+-	is_logical = MEGASAS_IS_LOGICAL(scp);
+-	device_id = MEGASAS_DEV_INDEX(instance, scp);
+-	pthru = (struct megasas_pthru_frame *)cmd->frame;
+-
+-	if (scp->sc_data_direction == PCI_DMA_TODEVICE)
+-		flags = MFI_FRAME_DIR_WRITE;
+-	else if (scp->sc_data_direction == PCI_DMA_FROMDEVICE)
+-		flags = MFI_FRAME_DIR_READ;
+-	else if (scp->sc_data_direction == PCI_DMA_NONE)
+-		flags = MFI_FRAME_DIR_NONE;
+-
+-	if (instance->flag_ieee == 1) {
+-		flags |= MFI_FRAME_IEEE;
+-	}
+-
+-	/*
+-	 * Prepare the DCDB frame
+-	 */
+-	pthru->cmd = (is_logical) ? MFI_CMD_LD_SCSI_IO : MFI_CMD_PD_SCSI_IO;
+-	pthru->cmd_status = 0x0;
+-	pthru->scsi_status = 0x0;
+-	pthru->target_id = device_id;
+-	pthru->lun = scp->device->lun;
+-	pthru->cdb_len = scp->cmd_len;
+-	pthru->timeout = 0;
+-	pthru->flags = flags;
+-	pthru->data_xfer_len = scsi_bufflen(scp);
+-
+-	memcpy(pthru->cdb, scp->cmnd, scp->cmd_len);
+-
+-	/*
+-	 * Construct SGL
+-	 */
+-	if (instance->flag_ieee == 1) {
+-		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,
+-						      &pthru->sgl);
+-	} else
+-		pthru->sge_count = megasas_make_sgl32(instance, scp,
+-						      &pthru->sgl);
+-
+-	if (pthru->sge_count > instance->max_num_sge) {
+-		printk(KERN_ERR "megasas: DCDB two many SGE NUM=%x\n",
+-			pthru->sge_count);
+-		return 0;
+-	}
+-
+-	/*
+-	 * Sense info specific
+-	 */
+-	pthru->sense_len = SCSI_SENSE_BUFFERSIZE;
+-	pthru->sense_buf_phys_addr_hi = 0;
+-	pthru->sense_buf_phys_addr_lo = cmd->sense_phys_addr;
+-
+-	/*
+-	 * 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, pthru->sge_count,
+-							PTHRU_FRAME);
+-
+-	return cmd->frame_count;
+-}
+-
+-/**
+- * megasas_build_ldio -	Prepares IOs to logical devices
+- * @instance:		Adapter soft state
+- * @scp:		SCSI command
+- * @cmd:		Command to be prepared
+- *
+- * Frames (and accompanying SGLs) for regular SCSI IOs use this function.
+- */
+-static int
+-megasas_build_ldio(struct megasas_instance *instance, struct scsi_cmnd *scp,
+-		   struct megasas_cmd *cmd)
+-{
+-	u32 device_id;
+-	u8 sc = scp->cmnd[0];
+-	u16 flags = 0;
+-	struct megasas_io_frame *ldio;
+-
+-	device_id = MEGASAS_DEV_INDEX(instance, scp);
+-	ldio = (struct megasas_io_frame *)cmd->frame;
+-
+-	if (scp->sc_data_direction == PCI_DMA_TODEVICE)
+-		flags = MFI_FRAME_DIR_WRITE;
+-	else if (scp->sc_data_direction == PCI_DMA_FROMDEVICE)
+-		flags = MFI_FRAME_DIR_READ;
+-
+-	if (instance->flag_ieee == 1) {
+-		flags |= MFI_FRAME_IEEE;
+-	}
+-
+-	/*
+-	 * Prepare the Logical IO frame: 2nd bit is zero for all read cmds
+-	 */
+-	ldio->cmd = (sc & 0x02) ? MFI_CMD_LD_WRITE : MFI_CMD_LD_READ;
+-	ldio->cmd_status = 0x0;
+-	ldio->scsi_status = 0x0;
+-	ldio->target_id = device_id;
+-	ldio->timeout = 0;
+-	ldio->reserved_0 = 0;
+-	ldio->pad_0 = 0;
+-	ldio->flags = flags;
+-	ldio->start_lba_hi = 0;
+-	ldio->access_byte = (scp->cmd_len != 6) ? scp->cmnd[1] : 0;
+-
+-	/*
+-	 * 6-byte READ(0x08) or WRITE(0x0A) cdb
+-	 */
+-	if (scp->cmd_len == 6) {
+-		ldio->lba_count = (u32) scp->cmnd[4];
+-		ldio->start_lba_lo = ((u32) scp->cmnd[1] << 16) |
+-		    ((u32) scp->cmnd[2] << 8) | (u32) scp->cmnd[3];
+-
+-		ldio->start_lba_lo &= 0x1FFFFF;
+-	}
+-
+-	/*
+-	 * 10-byte READ(0x28) or WRITE(0x2A) cdb
+-	 */
+-	else if (scp->cmd_len == 10) {
+-		ldio->lba_count = (u32) scp->cmnd[8] |
+-		    ((u32) scp->cmnd[7] << 8);
+-		ldio->start_lba_lo = ((u32) scp->cmnd[2] << 24) |
+-		    ((u32) scp->cmnd[3] << 16) |
+-		    ((u32) scp->cmnd[4] << 8) | (u32) scp->cmnd[5];
+-	}
+-
+-	/*
+-	 * 12-byte READ(0xA8) or WRITE(0xAA) cdb
+-	 */
+-	else if (scp->cmd_len == 12) {
+-		ldio->lba_count = ((u32) scp->cmnd[6] << 24) |
+-		    ((u32) scp->cmnd[7] << 16) |
+-		    ((u32) scp->cmnd[8] << 8) | (u32) scp->cmnd[9];
+-
+-		ldio->start_lba_lo = ((u32) scp->cmnd[2] << 24) |
+-		    ((u32) scp->cmnd[3] << 16) |
+-		    ((u32) scp->cmnd[4] << 8) | (u32) scp->cmnd[5];
+-	}
+-
+-	/*
+-	 * 16-byte READ(0x88) or WRITE(0x8A) cdb
+-	 */
+-	else if (scp->cmd_len == 16) {
+-		ldio->lba_count = ((u32) scp->cmnd[10] << 24) |
+-		    ((u32) scp->cmnd[11] << 16) |
+-		    ((u32) scp->cmnd[12] << 8) | (u32) scp->cmnd[13];
+-
+-		ldio->start_lba_lo = ((u32) scp->cmnd[6] << 24) |
+-		    ((u32) scp->cmnd[7] << 16) |
+-		    ((u32) scp->cmnd[8] << 8) | (u32) scp->cmnd[9];
+-
+-		ldio->start_lba_hi = ((u32) scp->cmnd[2] << 24) |
+-		    ((u32) scp->cmnd[3] << 16) |
+-		    ((u32) scp->cmnd[4] << 8) | (u32) scp->cmnd[5];
+-
+-	}
+-
+-	/*
+-	 * Construct SGL
+-	 */
+-	if (instance->flag_ieee) {
+-		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);
+-	} else
+-		ldio->sge_count = megasas_make_sgl32(instance, scp, &ldio->sgl);
+-
+-	if (ldio->sge_count > instance->max_num_sge) {
+-		printk(KERN_ERR "megasas: build_ld_io: sge_count = %x\n",
+-			ldio->sge_count);
+-		return 0;
+-	}
+-
+-	/*
+-	 * Sense info specific
+-	 */
+-	ldio->sense_len = SCSI_SENSE_BUFFERSIZE;
+-	ldio->sense_buf_phys_addr_hi = 0;
+-	ldio->sense_buf_phys_addr_lo = cmd->sense_phys_addr;
+-
+-	/*
+-	 * 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);
+-
+-	return cmd->frame_count;
+-}
+-
+-/**
+- * megasas_is_ldio -		Checks if the cmd is for logical drive
+- * @scmd:			SCSI command
+- *	
+- * Called by megasas_queue_command to find out if the command to be queued
+- * is a logical drive command	
+- */
+-static inline int megasas_is_ldio(struct scsi_cmnd *cmd)
+-{
+-	if (!MEGASAS_IS_LOGICAL(cmd))
+-		return 0;
+-	switch (cmd->cmnd[0]) {
+-	case READ_10:
+-	case WRITE_10:
+-	case READ_12:
+-	case WRITE_12:
+-	case READ_6:
+-	case WRITE_6:
+-	case READ_16:
+-	case WRITE_16:
+-		return 1;
+-	default:
+-		return 0;
+-	}
+-}
+-
+- /**
+- * megasas_dump_pending_frames -	Dumps the frame address of all pending cmds
+- *                              	in FW
+- * @instance:				Adapter soft state
+- */
+-static inline void
+-megasas_dump_pending_frames(struct megasas_instance *instance)
+-{
+-	struct megasas_cmd *cmd;
+-	int i,n;
+-	union megasas_sgl *mfi_sgl;
+-	struct megasas_io_frame *ldio;
+-	struct megasas_pthru_frame *pthru;
+-	u32 sgcount;
+-	u32 max_cmd = instance->max_fw_cmds;
+-
+-	printk(KERN_ERR "\nmegasas[%d]: Dumping Frame Phys Address of all pending cmds in FW\n",instance->host->host_no);
+-	printk(KERN_ERR "megasas[%d]: Total OS Pending cmds : %d\n",instance->host->host_no,atomic_read(&instance->fw_outstanding));
+-	if (IS_DMA64)
+-		printk(KERN_ERR "\nmegasas[%d]: 64 bit SGLs were sent to FW\n",instance->host->host_no);
+-	else
+-		printk(KERN_ERR "\nmegasas[%d]: 32 bit SGLs were sent to FW\n",instance->host->host_no);
+-
+-	printk(KERN_ERR "megasas[%d]: Pending OS cmds in FW : \n",instance->host->host_no);
+-	for (i = 0; i < max_cmd; i++) {
+-		cmd = instance->cmd_list[i];
+-		if(!cmd->scmd)
+-			continue;
+-		printk(KERN_ERR "megasas[%d]: Frame addr :0x%08lx : ",instance->host->host_no,(unsigned long)cmd->frame_phys_addr);
+-		if (megasas_is_ldio(cmd->scmd)){
+-			ldio = (struct megasas_io_frame *)cmd->frame;
+-			mfi_sgl = &ldio->sgl;
+-			sgcount = ldio->sge_count;
+-			printk(KERN_ERR "megasas[%d]: frame count : 0x%x, Cmd : 0x%x, Tgt id : 0x%x, lba lo : 0x%x, lba_hi : 0x%x, sense_buf addr : 0x%x,sge count : 0x%x\n",instance->host->host_no, cmd->frame_count,ldio->cmd,ldio->target_id, ldio->start_lba_lo,ldio->start_lba_hi,ldio->sense_buf_phys_addr_lo,sgcount);
+-		}
+-		else {
+-			pthru = (struct megasas_pthru_frame *) cmd->frame;
+-			mfi_sgl = &pthru->sgl;
+-			sgcount = pthru->sge_count;
+-			printk(KERN_ERR "megasas[%d]: frame count : 0x%x, Cmd : 0x%x, Tgt id : 0x%x, lun : 0x%x, cdb_len : 0x%x, data xfer len : 0x%x, sense_buf addr : 0x%x,sge count : 0x%x\n",instance->host->host_no,cmd->frame_count,pthru->cmd,pthru->target_id,pthru->lun,pthru->cdb_len , pthru->data_xfer_len,pthru->sense_buf_phys_addr_lo,sgcount);
+-		}
+-	if(megasas_dbg_lvl & MEGASAS_DBG_LVL){
+-		for (n = 0; n < sgcount; n++){
+-			if (IS_DMA64)
+-				printk(KERN_ERR "megasas: sgl len : 0x%x, sgl addr : 0x%08lx ",mfi_sgl->sge64[n].length , (unsigned long)mfi_sgl->sge64[n].phys_addr) ;
+-			else
+-				printk(KERN_ERR "megasas: sgl len : 0x%x, sgl addr : 0x%x ",mfi_sgl->sge32[n].length , mfi_sgl->sge32[n].phys_addr) ;
+-			}
+-		}
+-		printk(KERN_ERR "\n");
+-	} /*for max_cmd*/
+-	printk(KERN_ERR "\nmegasas[%d]: Pending Internal cmds in FW : \n",instance->host->host_no);
+-	for (i = 0; i < max_cmd; i++) {
+-
+-		cmd = instance->cmd_list[i];
+-
+-		if(cmd->sync_cmd == 1){
+-			printk(KERN_ERR "0x%08lx : ", (unsigned long)cmd->frame_phys_addr);
+-		}
+-	}
+-	printk(KERN_ERR "megasas[%d]: Dumping Done.\n\n",instance->host->host_no);
+-}
+-
+-/**
+- * megasas_queue_command -	Queue entry point
+- * @scmd:			SCSI command to be queued
+- * @done:			Callback entry point
+- */
+-static int
+-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;
+-
+-	if (instance->issuepend_done == 0)
+-		return SCSI_MLQUEUE_HOST_BUSY;
+-
+-	spin_lock_irqsave(&instance->hba_lock, flags);
+-	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;
+-
+-	if (MEGASAS_IS_LOGICAL(scmd) &&
+-	    (scmd->device->id >= MEGASAS_MAX_LD || scmd->device->lun)) {
+-		scmd->result = DID_BAD_TARGET << 16;
+-		goto out_done;
+-	}
+-
+-	switch (scmd->cmnd[0]) {
+-	case SYNCHRONIZE_CACHE:
+-		/*
+-		 * FW takes care of flush cache on its own
+-		 * No need to send it down
+-		 */
+-		scmd->result = DID_OK << 16;
+-		goto out_done;
+-	default:
+-		break;
+-	}
+-
+-	cmd = megasas_get_cmd(instance);
+-	if (!cmd)
+-		return SCSI_MLQUEUE_HOST_BUSY;
+-
+-	/*
+-	 * Logical drive command
+-	 */
+-	if (megasas_is_ldio(scmd))
+-		frame_count = megasas_build_ldio(instance, scmd, cmd);
+-	else
+-		frame_count = megasas_build_dcdb(instance, scmd, cmd);
+-
+-	if (!frame_count)
+-		goto out_return_cmd;
+-
+-	cmd->scmd = scmd;
+-	scmd->SCp.ptr = (char *)cmd;
+-
+-	/*
+-	 * Issue the command to the FW
+-	 */
+-	atomic_inc(&instance->fw_outstanding);
+-
+-	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
+-	 */
+-	if (poll_mode_io && atomic_read(&instance->fw_outstanding))
+-		tasklet_schedule(&instance->isr_tasklet);
+-
+-
+-	return 0;
+-
+- out_return_cmd:
+-	megasas_return_cmd(instance, cmd);
+- out_done:
+-	done(scmd);
+-	return 0;
+-}
+-
+-static int megasas_slave_configure(struct scsi_device *sdev)
+-{
+-	/*
+-	 * Don't export physical disk devices to the disk driver.
+-	 *
+-	 * FIXME: Currently we don't export them to the midlayer at all.
+-	 * 	  That will be fixed once LSI engineers have audited the
+-	 * 	  firmware for possible issues.
+-	 */
+-	if (sdev->channel < MEGASAS_MAX_PD_CHANNELS && sdev->type == TYPE_DISK)
+-		return -ENXIO;
+-
+-	/*
+-	 * The RAID firmware may require extended timeouts.
+-	 */
+-	if (sdev->channel >= MEGASAS_MAX_PD_CHANNELS)
+-		blk_queue_rq_timeout(sdev->request_queue,
+-				     MEGASAS_DEFAULT_CMD_TIMEOUT * HZ);
+-	return 0;
+-}
+-
+-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);
+-	}
+-}
+-
+-/**
+- * megasas_complete_cmd_dpc	 -	Returns FW's controller structure
+- * @instance_addr:			Address of adapter soft state
+- *
+- * Tasklet to complete cmds
+- */
+-static void megasas_complete_cmd_dpc(unsigned long instance_addr)
+-{
+-	u32 producer;
+-	u32 consumer;
+-	u32 context;
+-	struct megasas_cmd *cmd;
+-	struct megasas_instance *instance =
+-				(struct megasas_instance *)instance_addr;
+-	unsigned long flags;
+-
+-	/* If we have already declared adapter dead, donot complete cmds */
+-	if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR )
+-		return;
+-
+-	spin_lock_irqsave(&instance->completion_lock, flags);
+-
+-	producer = *instance->producer;
+-	consumer = *instance->consumer;
+-
+-	while (consumer != producer) {
+-		context = instance->reply_queue[consumer];
+-		if (context >= instance->max_fw_cmds) {
+-			printk(KERN_ERR "Unexpected context value %x\n",
+-				context);
+-			BUG();
+-		}
+-
+-		cmd = instance->cmd_list[context];
+-
+-		megasas_complete_cmd(instance, cmd, DID_OK);
+-
+-		consumer++;
+-		if (consumer == (instance->max_fw_cmds + 1)) {
+-			consumer = 0;
+-		}
+-	}
+-
+-	*instance->consumer = producer;
+-
+-	spin_unlock_irqrestore(&instance->completion_lock, flags);
+-
+-	/*
+-	 * Check if we can restore can_queue
+-	 */
+-	if (instance->flag & MEGASAS_FW_BUSY
+-		&& time_after(jiffies, instance->last_time + 5 * HZ)
+-		&& atomic_read(&instance->fw_outstanding) < 17) {
+-
+-		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)) {
+-			instance->host->can_queue =
+-				instance->max_fw_cmds - MEGASAS_SKINNY_INT_CMDS;
+-		} else
+-			instance->host->can_queue =
+-				instance->max_fw_cmds - MEGASAS_INT_CMDS;
+-
+-		spin_unlock_irqrestore(instance->host->host_lock, flags);
+-	}
+-}
+-
+-/**
+- * megasas_wait_for_outstanding -	Wait for all outstanding cmds
+- * @instance:				Adapter soft state
+- *
+- * This function waits for upto MEGASAS_RESET_WAIT_TIME seconds for FW to
+- * complete all its outstanding commands. Returns error if one or more IOs
+- * are pending after this time period. It also marks the controller dead.
+- */
+-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;
+-
+-	spin_lock_irqsave(&instance->hba_lock, flags);
+-	adprecovery = instance->adprecovery;
+-	spin_unlock_irqrestore(&instance->hba_lock, flags);
+-
+-	if (adprecovery != MEGASAS_HBA_OPERATIONAL) {
+-
+-		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(KERN_NOTICE "megasas: HBA reset wait ...\n");
+-		for (i = 0; i < wait_time; i++) {
+-			msleep(1000);
+-			spin_lock_irqsave(&instance->hba_lock, flags);
+-			adprecovery = instance->adprecovery;
+-			spin_unlock_irqrestore(&instance->hba_lock, flags);
+-			if (adprecovery == MEGASAS_HBA_OPERATIONAL)
+-				break;
+-		}
+-
+-		if (adprecovery != MEGASAS_HBA_OPERATIONAL) {
+-			printk(KERN_NOTICE "megasas: reset: Stopping HBA.\n");
+-			spin_lock_irqsave(&instance->hba_lock, flags);
+-			instance->adprecovery	= MEGASAS_HW_CRITICAL_ERROR;
+-			spin_unlock_irqrestore(&instance->hba_lock, flags);
+-			return FAILED;
+-		}
+-
+-		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(KERN_NOTICE "%d:%p reset [%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) {
+-				printk(KERN_NOTICE "megasas:%p synch cmds"
+-						"reset queue\n",
+-						reset_cmd);
+-
+-				reset_cmd->cmd_status = ENODATA;
+-				instance->instancet->fire_cmd(instance,
+-						reset_cmd->frame_phys_addr,
+-						0, instance->reg_set);
+-			} else {
+-				printk(KERN_NOTICE "megasas: %p unexpected"
+-					"cmds lst\n",
+-					reset_cmd);
+-			}
+-			reset_index++;
+-		}
+-
+-		return SUCCESS;
+-	}
+-
+-	for (i = 0; i < wait_time; i++) {
+-
+-		int outstanding = atomic_read(&instance->fw_outstanding);
+-
+-		if (!outstanding)
+-			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
+-			 * be completed directly without depending on isr.
+-			 */
+-			megasas_complete_cmd_dpc((unsigned long)instance);
+-		}
+-
+-		msleep(1000);
+-	}
+-
+-	if (atomic_read(&instance->fw_outstanding)) {
+-		printk(KERN_NOTICE "megaraid_sas: pending cmds after reset\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)) {
+-			writel(MFI_STOP_ADP,
+-				&instance->reg_set->reserved_0[0]);
+-		} else {
+-			writel(MFI_STOP_ADP,
+-				&instance->reg_set->inbound_doorbell);
+-		}
+-		megasas_dump_pending_frames(instance);
+-		spin_lock_irqsave(&instance->hba_lock, flags);
+-		instance->adprecovery	= MEGASAS_HW_CRITICAL_ERROR;
+-		spin_unlock_irqrestore(&instance->hba_lock, flags);
+-		return FAILED;
+-	}
+-
+-	printk(KERN_NOTICE "megaraid_sas: no pending cmds after reset\n");
+-
+-	return SUCCESS;
+-}
+-
+-/**
+- * megasas_generic_reset -	Generic reset routine
+- * @scmd:			Mid-layer SCSI command
+- *
+- * This routine implements a generic reset handler for device, bus and host
+- * reset requests. Device, bus and host specific reset handlers can use this
+- * function after they do their specific tasks.
+- */
+-static int megasas_generic_reset(struct scsi_cmnd *scmd)
+-{
+-	int ret_val;
+-	struct megasas_instance *instance;
+-
+-	instance = (struct megasas_instance *)scmd->device->host->hostdata;
+-
+-	scmd_printk(KERN_NOTICE, scmd, "megasas: RESET -%ld cmd=%x retries=%x\n",
+-		 scmd->serial_number, scmd->cmnd[0], scmd->retries);
+-
+-	if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR) {
+-		printk(KERN_ERR "megasas: cannot recover from previous reset "
+-		       "failures\n");
+-		return FAILED;
+-	}
+-
+-	ret_val = megasas_wait_for_outstanding(instance);
+-	if (ret_val == SUCCESS)
+-		printk(KERN_NOTICE "megasas: reset successful \n");
+-	else
+-		printk(KERN_ERR "megasas: failed to do reset\n");
+-
+-	return ret_val;
+-}
+-
+-/**
+- * megasas_reset_timer - quiesce the adapter if required
+- * @scmd:		scsi cmnd
+- *
+- * Sets the FW busy flag and reduces the host->can_queue if the
+- * cmd has not been completed within the timeout period.
+- */
+-static enum
+-blk_eh_timer_return megasas_reset_timer(struct scsi_cmnd *scmd)
+-{
+-	struct megasas_cmd *cmd = (struct megasas_cmd *)scmd->SCp.ptr;
+-	struct megasas_instance *instance;
+-	unsigned long flags;
+-
+-	if (time_after(jiffies, scmd->jiffies_at_alloc +
+-				(MEGASAS_DEFAULT_CMD_TIMEOUT * 2) * HZ)) {
+-		return BLK_EH_NOT_HANDLED;
+-	}
+-
+-	instance = cmd->instance;
+-	if (!(instance->flag & MEGASAS_FW_BUSY)) {
+-		/* FW is busy, throttle IO */
+-		spin_lock_irqsave(instance->host->host_lock, flags);
+-
+-		instance->host->can_queue = 16;
+-		instance->last_time = jiffies;
+-		instance->flag |= MEGASAS_FW_BUSY;
+-
+-		spin_unlock_irqrestore(instance->host->host_lock, flags);
+-	}
+-	return BLK_EH_RESET_TIMER;
+-}
+-
+-/**
+- * megasas_reset_device -	Device reset handler entry point
+- */
+-static int megasas_reset_device(struct scsi_cmnd *scmd)
+-{
+-	int ret;
+-
+-	/*
+-	 * First wait for all commands to complete
+-	 */
+-	ret = megasas_generic_reset(scmd);
+-
+-	return ret;
+-}
+-
+-/**
+- * megasas_reset_bus_host -	Bus & host reset handler entry point
+- */
+-static int megasas_reset_bus_host(struct scsi_cmnd *scmd)
+-{
+-	int ret;
+-
+-	/*
+-	 * First wait for all commands to complete
+-	 */
+-	ret = megasas_generic_reset(scmd);
+-
+-	return ret;
+-}
+-
+-/**
+- * megasas_bios_param - Returns disk geometry for a disk
+- * @sdev: 		device handle
+- * @bdev:		block device
+- * @capacity:		drive capacity
+- * @geom:		geometry parameters
+- */
+-static int
+-megasas_bios_param(struct scsi_device *sdev, struct block_device *bdev,
+-		 sector_t capacity, int geom[])
+-{
+-	int heads;
+-	int sectors;
+-	sector_t cylinders;
+-	unsigned long tmp;
+-	/* Default heads (64) & sectors (32) */
+-	heads = 64;
+-	sectors = 32;
+-
+-	tmp = heads * sectors;
+-	cylinders = capacity;
+-
+-	sector_div(cylinders, tmp);
+-
+-	/*
+-	 * Handle extended translation size for logical drives > 1Gb
+-	 */
+-
+-	if (capacity >= 0x200000) {
+-		heads = 255;
+-		sectors = 63;
+-		tmp = heads*sectors;
+-		cylinders = capacity;
+-		sector_div(cylinders, tmp);
+-	}
+-
+-	geom[0] = heads;
+-	geom[1] = sectors;
+-	geom[2] = cylinders;
+-
+-	return 0;
+-}
+-
+-static void megasas_aen_polling(struct work_struct *work);
+-
+-/**
+- * megasas_service_aen -	Processes an event notification
+- * @instance:			Adapter soft state
+- * @cmd:			AEN command completed by the ISR
+- *
+- * For AEN, driver sends a command down to FW that is held by the FW till an
+- * event occurs. When an event of interest occurs, FW completes the command
+- * that it was previously holding.
+- *
+- * This routines sends SIGIO signal to processes that have registered with the
+- * driver for AEN.
+- */
+-static void
+-megasas_service_aen(struct megasas_instance *instance, struct megasas_cmd *cmd)
+-{
+-	unsigned long flags;
+-	/*
+-	 * Don't signal app if it is just an aborted previously registered aen
+-	 */
+-	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);
+-		kill_fasync(&megasas_async_queue, SIGIO, POLL_IN);
+-	}
+-	else
+-		cmd->abort_aen = 0;
+-
+-	instance->aen_cmd = NULL;
+-	megasas_return_cmd(instance, cmd);
+-
+-	if ((instance->unload == 0) &&
+-		((instance->issuepend_done == 1))) {
+-		struct megasas_aen_event *ev;
+-		ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
+-		if (!ev) {
+-			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);
+-			schedule_delayed_work(
+-				(struct delayed_work *)&ev->hotplug_work, 0);
+-		}
+-	}
+-}
+-
+-/*
+- * Scsi host template for megaraid_sas driver
+- */
+-static struct scsi_host_template megasas_template = {
+-
+-	.module = THIS_MODULE,
+-	.name = "LSI SAS based MegaRAID driver",
+-	.proc_name = "megaraid_sas",
+-	.slave_configure = megasas_slave_configure,
+-	.queuecommand = megasas_queue_command,
+-	.eh_device_reset_handler = megasas_reset_device,
+-	.eh_bus_reset_handler = megasas_reset_bus_host,
+-	.eh_host_reset_handler = megasas_reset_bus_host,
+-	.eh_timed_out = megasas_reset_timer,
+-	.bios_param = megasas_bios_param,
+-	.use_clustering = ENABLE_CLUSTERING,
+-};
+-
+-/**
+- * megasas_complete_int_cmd -	Completes an internal command
+- * @instance:			Adapter soft state
+- * @cmd:			Command to be completed
+- *
+- * The megasas_issue_blocked_cmd() function waits for a command to complete
+- * after it issues a command. This function wakes up that waiting routine by
+- * calling wake_up() on the wait queue.
+- */
+-static void
+-megasas_complete_int_cmd(struct megasas_instance *instance,
+-			 struct megasas_cmd *cmd)
+-{
+-	cmd->cmd_status = cmd->frame->io.cmd_status;
+-
+-	if (cmd->cmd_status == ENODATA) {
+-		cmd->cmd_status = 0;
+-	}
+-	wake_up(&instance->int_cmd_wait_q);
+-}
+-
+-/**
+- * megasas_complete_abort -	Completes aborting a command
+- * @instance:			Adapter soft state
+- * @cmd:			Cmd that was issued to abort another cmd
+- *
+- * The megasas_issue_blocked_abort_cmd() function waits on abort_cmd_wait_q 
+- * after it issues an abort on a previously issued command. This function 
+- * wakes up all functions waiting on the same wait queue.
+- */
+-static void
+-megasas_complete_abort(struct megasas_instance *instance,
+-		       struct megasas_cmd *cmd)
+-{
+-	if (cmd->sync_cmd) {
+-		cmd->sync_cmd = 0;
+-		cmd->cmd_status = 0;
+-		wake_up(&instance->abort_cmd_wait_q);
+-	}
+-
+-	return;
+-}
+-
+-/**
+- * megasas_complete_cmd -	Completes a command
+- * @instance:			Adapter soft state
+- * @cmd:			Command to be completed
+- * @alt_status:			If non-zero, use this value as status to 
+- * 				SCSI mid-layer instead of the value returned
+- * 				by the FW. This should be used if caller wants
+- * 				an alternate status (as in the case of aborted
+- * 				commands)
+- */
+-static void
+-megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd,
+-		     u8 alt_status)
+-{
+-	int exception = 0;
+-	struct megasas_header *hdr = &cmd->frame->hdr;
+-	unsigned long flags;
+-
+-	/* flag for the retry reset */
+-	cmd->retry_for_fw_reset = 0;
+-
+-	if (cmd->scmd)
+-		cmd->scmd->SCp.ptr = NULL;
+-
+-	switch (hdr->cmd) {
+-
+-	case MFI_CMD_PD_SCSI_IO:
+-	case MFI_CMD_LD_SCSI_IO:
+-
+-		/*
+-		 * MFI_CMD_PD_SCSI_IO and MFI_CMD_LD_SCSI_IO could have been
+-		 * issued either through an IO path or an IOCTL path. If it
+-		 * was via IOCTL, we will send it to internal completion.
+-		 */
+-		if (cmd->sync_cmd) {
+-			cmd->sync_cmd = 0;
+-			megasas_complete_int_cmd(instance, cmd);
+-			break;
+-		}
+-
+-	case MFI_CMD_LD_READ:
+-	case MFI_CMD_LD_WRITE:
+-
+-		if (alt_status) {
+-			cmd->scmd->result = alt_status << 16;
+-			exception = 1;
+-		}
+-
+-		if (exception) {
+-
+-			atomic_dec(&instance->fw_outstanding);
+-
+-			scsi_dma_unmap(cmd->scmd);
+-			cmd->scmd->scsi_done(cmd->scmd);
+-			megasas_return_cmd(instance, cmd);
+-
+-			break;
+-		}
+-
+-		switch (hdr->cmd_status) {
+-
+-		case MFI_STAT_OK:
+-			cmd->scmd->result = DID_OK << 16;
+-			break;
+-
+-		case MFI_STAT_SCSI_IO_FAILED:
+-		case MFI_STAT_LD_INIT_IN_PROGRESS:
+-			cmd->scmd->result =
+-			    (DID_ERROR << 16) | hdr->scsi_status;
+-			break;
+-
+-		case MFI_STAT_SCSI_DONE_WITH_ERROR:
+-
+-			cmd->scmd->result = (DID_OK << 16) | hdr->scsi_status;
+-
+-			if (hdr->scsi_status == SAM_STAT_CHECK_CONDITION) {
+-				memset(cmd->scmd->sense_buffer, 0,
+-				       SCSI_SENSE_BUFFERSIZE);
+-				memcpy(cmd->scmd->sense_buffer, cmd->sense,
+-				       hdr->sense_len);
+-
+-				cmd->scmd->result |= DRIVER_SENSE << 24;
+-			}
+-
+-			break;
+-
+-		case MFI_STAT_LD_OFFLINE:
+-		case MFI_STAT_DEVICE_NOT_FOUND:
+-			cmd->scmd->result = DID_BAD_TARGET << 16;
+-			break;
+-
+-		default:
+-			printk(KERN_DEBUG "megasas: MFI FW status %#x\n",
+-			       hdr->cmd_status);
+-			cmd->scmd->result = DID_ERROR << 16;
+-			break;
+-		}
+-
+-		atomic_dec(&instance->fw_outstanding);
+-
+-		scsi_dma_unmap(cmd->scmd);
+-		cmd->scmd->scsi_done(cmd->scmd);
+-		megasas_return_cmd(instance, cmd);
+-
+-		break;
+-
+-	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
+-		 */
+-		if (cmd->frame->dcmd.opcode == MR_DCMD_CTRL_EVENT_WAIT)
+-			megasas_service_aen(instance, cmd);
+-		else
+-			megasas_complete_int_cmd(instance, cmd);
+-
+-		break;
+-
+-	case MFI_CMD_ABORT:
+-		/*
+-		 * Cmd issued to abort another cmd returned
+-		 */
+-		megasas_complete_abort(instance, 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(KERN_NOTICE "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 (cmd->retry_for_fw_reset == 3) {
+-				printk(KERN_NOTICE "megaraid_sas: cmd %p, %p:%d"
+-					"was tried multiple times during 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(KERN_NOTICE "megaraid_sas: unexpected"
+-					"cmd attached to internal command!\n");
+-			}
+-			printk(KERN_NOTICE "megasas: %p synchronous cmd"
+-						"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(KERN_NOTICE "megasas: %p scsi cmd [%02x],%#lx"
+-			"detected on the internal queue, issue 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(KERN_NOTICE "megasas: %p unexpected cmd on the"
+-				"internal reset defer list while re-issue!!\n",
+-				cmd);
+-		}
+-	}
+-
+-	if (instance->aen_cmd) {
+-		printk(KERN_NOTICE "megaraid_sas: aen_cmd in def process\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(KERN_NOTICE "megasas: moving cmd[%d]:%p:%d:%p"
+-					"on the defer queue as internal\n",
+-				defer_index, cmd, cmd->sync_cmd, cmd->scmd);
+-
+-			if (!list_empty(&cmd->list)) {
+-				printk(KERN_NOTICE "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(struct work_struct *work)
+-{
+-	struct megasas_instance *instance =
+-		container_of(work, struct megasas_instance, work_init);
+-	u32 wait;
+-	unsigned long flags;
+-
+-	if (instance->adprecovery != MEGASAS_ADPRESET_SM_INFAULT) {
+-		printk(KERN_NOTICE "megaraid_sas: error, recovery st %x \n",
+-				instance->adprecovery);
+-		return ;
+-	}
+-
+-	if (instance->adprecovery == MEGASAS_ADPRESET_SM_INFAULT) {
+-		printk(KERN_NOTICE "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(KERN_NOTICE "megaraid_sas: FW restarted successfully,"
+-					"initiating next stage...\n");
+-
+-		printk(KERN_NOTICE "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(KERN_NOTICE "megaraid_sas:adapter not ready\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;
+-		}
+-
+-		megasas_issue_init_mfi(instance);
+-
+-		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);
+-
+-		megasas_issue_pending_cmds_again(instance);
+-		instance->issuepend_done = 1;
+-	}
+-	return ;
+-}
+-
+-/**
+- * megasas_deplete_reply_queue -	Processes all completed commands
+- * @instance:				Adapter soft state
+- * @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)
+-{
+-	u32 mfiStatus;
+-	u32 fw_state;
+-
+-	if ((mfiStatus = instance->instancet->check_reset(instance,
+-					instance->reg_set)) == 1) {
+-		return IRQ_HANDLED;
+-	}
+-
+-	if ((mfiStatus = instance->instancet->clear_intr(
+-						instance->reg_set)
+-						) == 0) {
+-		return IRQ_NONE;
+-	}
+-
+-	instance->mfiStatus = mfiStatus;
+-
+-	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(KERN_NOTICE "megaraid_sas: fw state:%x\n",
+-						fw_state);
+-		}
+-
+-		if ((fw_state == MFI_STATE_FAULT) &&
+-				(instance->disableOnlineCtrlReset == 0)) {
+-			printk(KERN_NOTICE "megaraid_sas: wait adp 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;
+-			instance->issuepend_done = 0;
+-
+-			atomic_set(&instance->fw_outstanding, 0);
+-			megasas_internal_reset_defer_cmds(instance);
+-
+-			printk(KERN_NOTICE "megasas: fwState=%x, stage:%d\n",
+-					fw_state, instance->adprecovery);
+-
+-			schedule_work(&instance->work_init);
+-			return IRQ_HANDLED;
+-
+-		} else {
+-			printk(KERN_NOTICE "megasas: fwstate:%x, dis_OCR=%x\n",
+-				fw_state, instance->disableOnlineCtrlReset);
+-		}
+-	}
+-
+-	tasklet_schedule(&instance->isr_tasklet);
+-	return IRQ_HANDLED;
+-}
+-/**
+- * megasas_isr - isr entry point
+- */
+-static irqreturn_t megasas_isr(int irq, void *devp)
+-{
+-	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;
+-}
+-
+-/**
+- * megasas_transition_to_ready -	Move the FW to READY state
+- * @instance:				Adapter soft state
+- *
+- * During the initialization, FW passes can potentially be in any one of
+- * several possible states. If the FW in operational, waiting-for-handshake
+- * states, driver must take steps to bring it to ready state. Otherwise, it
+- * has to wait for the ready state.
+- */
+-static int
+-megasas_transition_to_ready(struct megasas_instance* instance)
+-{
+-	int i;
+-	u8 max_wait;
+-	u32 fw_state;
+-	u32 cur_state;
+-
+-	fw_state = instance->instancet->read_fw_status_reg(instance->reg_set) & MFI_STATE_MASK;
+-
+-	if (fw_state != MFI_STATE_READY)
+- 		printk(KERN_INFO "megasas: Waiting for FW to come to ready"
+- 		       " state\n");
+-
+-	while (fw_state != MFI_STATE_READY) {
+-
+-		switch (fw_state) {
+-
+-		case MFI_STATE_FAULT:
+-
+-			printk(KERN_DEBUG "megasas: FW in FAULT state!!\n");
+-			return -ENODEV;
+-
+-		case MFI_STATE_WAIT_HANDSHAKE:
+-			/*
+-			 * 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,
+-				  &instance->reg_set->reserved_0[0]);
+-			} else {
+-				writel(
+-				    MFI_INIT_CLEAR_HANDSHAKE|MFI_INIT_HOTPLUG,
+-					&instance->reg_set->inbound_doorbell);
+-			}
+-
+-			max_wait = 2;
+-			cur_state = MFI_STATE_WAIT_HANDSHAKE;
+-			break;
+-
+-		case MFI_STATE_BOOT_MESSAGE_PENDING:
+-			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
+-				writel(MFI_INIT_HOTPLUG,
+-					&instance->reg_set->inbound_doorbell);
+-
+-			max_wait = 10;
+-			cur_state = MFI_STATE_BOOT_MESSAGE_PENDING;
+-			break;
+-
+-		case MFI_STATE_OPERATIONAL:
+-			/*
+-			 * 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]);
+-			} else
+-				writel(MFI_RESET_FLAGS,
+-					&instance->reg_set->inbound_doorbell);
+-
+-			max_wait = 60;
+-			cur_state = MFI_STATE_OPERATIONAL;
+-			break;
+-
+-		case MFI_STATE_UNDEFINED:
+-			/*
+-			 * This state should not last for more than 2 seconds
+-			 */
+-			max_wait = 2;
+-			cur_state = MFI_STATE_UNDEFINED;
+-			break;
+-
+-		case MFI_STATE_BB_INIT:
+-			max_wait = 2;
+-			cur_state = MFI_STATE_BB_INIT;
+-			break;
+-
+-		case MFI_STATE_FW_INIT:
+-			max_wait = 20;
+-			cur_state = MFI_STATE_FW_INIT;
+-			break;
+-
+-		case MFI_STATE_FW_INIT_2:
+-			max_wait = 20;
+-			cur_state = MFI_STATE_FW_INIT_2;
+-			break;
+-
+-		case MFI_STATE_DEVICE_SCAN:
+-			max_wait = 20;
+-			cur_state = MFI_STATE_DEVICE_SCAN;
+-			break;
+-
+-		case MFI_STATE_FLUSH_CACHE:
+-			max_wait = 20;
+-			cur_state = MFI_STATE_FLUSH_CACHE;
+-			break;
+-
+-		default:
+-			printk(KERN_DEBUG "megasas: Unknown state 0x%x\n",
+-			       fw_state);
+-			return -ENODEV;
+-		}
+-
+-		/*
+-		 * The cur_state should not last for more than max_wait secs
+-		 */
+-		for (i = 0; i < (max_wait * 1000); i++) {
+-			fw_state = instance->instancet->read_fw_status_reg(instance->reg_set) &  
+-					MFI_STATE_MASK ;
+-
+-			if (fw_state == cur_state) {
+-				msleep(1);
+-			} else
+-				break;
+-		}
+-
+-		/*
+-		 * Return error if fw_state hasn't changed after max_wait
+-		 */
+-		if (fw_state == cur_state) {
+-			printk(KERN_DEBUG "FW state [%d] hasn't changed "
+-			       "in %d secs\n", fw_state, max_wait);
+-			return -ENODEV;
+-		}
+-	}
+- 	printk(KERN_INFO "megasas: FW now in Ready state\n");
+-
+-	return 0;
+-}
+-
+-/**
+- * megasas_teardown_frame_pool -	Destroy the cmd frame DMA pool
+- * @instance:				Adapter soft state
+- */
+-static void megasas_teardown_frame_pool(struct megasas_instance *instance)
+-{
+-	int i;
+-	u32 max_cmd = instance->max_fw_cmds;
+-	struct megasas_cmd *cmd;
+-
+-	if (!instance->frame_dma_pool)
+-		return;
+-
+-	/*
+-	 * Return all frames to pool
+-	 */
+-	for (i = 0; i < max_cmd; i++) {
+-
+-		cmd = instance->cmd_list[i];
+-
+-		if (cmd->frame)
+-			pci_pool_free(instance->frame_dma_pool, cmd->frame,
+-				      cmd->frame_phys_addr);
+-
+-		if (cmd->sense)
+-			pci_pool_free(instance->sense_dma_pool, cmd->sense,
+-				      cmd->sense_phys_addr);
+-	}
+-
+-	/*
+-	 * Now destroy the pool itself
+-	 */
+-	pci_pool_destroy(instance->frame_dma_pool);
+-	pci_pool_destroy(instance->sense_dma_pool);
+-
+-	instance->frame_dma_pool = NULL;
+-	instance->sense_dma_pool = NULL;
+-}
+-
+-/**
+- * megasas_create_frame_pool -	Creates DMA pool for cmd frames
+- * @instance:			Adapter soft state
+- *
+- * Each command packet has an embedded DMA memory buffer that is used for
+- * filling MFI frame and the SG list that immediately follows the frame. This
+- * function creates those DMA memory buffers for each command packet by using
+- * PCI pool facility.
+- */
+-static int megasas_create_frame_pool(struct megasas_instance *instance)
+-{
+-	int i;
+-	u32 max_cmd;
+-	u32 sge_sz;
+-	u32 sgl_sz;
+-	u32 total_sz;
+-	u32 frame_count;
+-	struct megasas_cmd *cmd;
+-
+-	max_cmd = instance->max_fw_cmds;
+-
+-	/*
+-	 * Size of our frame is 64 bytes for MFI frame, followed by max SG
+-	 * elements and finally SCSI_SENSE_BUFFERSIZE bytes for sense buffer
+-	 */
+-	sge_sz = (IS_DMA64) ? sizeof(struct megasas_sge64) :
+-	    sizeof(struct megasas_sge32);
+-
+-	if (instance->flag_ieee) {
+-		sge_sz = sizeof(struct megasas_sge_skinny);
+-	}
+-
+-	/*
+-	 * Calculated the number of 64byte frames required for SGL
+-	 */
+-	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
+-	 */
+-	frame_count++;
+-
+-	total_sz = MEGAMFI_FRAME_SIZE * frame_count;
+-	/*
+-	 * Use DMA pool facility provided by PCI layer
+-	 */
+-	instance->frame_dma_pool = pci_pool_create("megasas frame pool",
+-						   instance->pdev, total_sz, 64,
+-						   0);
+-
+-	if (!instance->frame_dma_pool) {
+-		printk(KERN_DEBUG "megasas: failed to setup frame pool\n");
+-		return -ENOMEM;
+-	}
+-
+-	instance->sense_dma_pool = pci_pool_create("megasas sense pool",
+-						   instance->pdev, 128, 4, 0);
+-
+-	if (!instance->sense_dma_pool) {
+-		printk(KERN_DEBUG "megasas: failed to setup sense pool\n");
+-
+-		pci_pool_destroy(instance->frame_dma_pool);
+-		instance->frame_dma_pool = NULL;
+-
+-		return -ENOMEM;
+-	}
+-
+-	/*
+-	 * Allocate and attach a frame to each of the commands in cmd_list.
+-	 * By making cmd->index as the context instead of the &cmd, we can
+-	 * always use 32bit context regardless of the architecture
+-	 */
+-	for (i = 0; i < max_cmd; i++) {
+-
+-		cmd = instance->cmd_list[i];
+-
+-		cmd->frame = pci_pool_alloc(instance->frame_dma_pool,
+-					    GFP_KERNEL, &cmd->frame_phys_addr);
+-
+-		cmd->sense = pci_pool_alloc(instance->sense_dma_pool,
+-					    GFP_KERNEL, &cmd->sense_phys_addr);
+-
+-		/*
+-		 * megasas_teardown_frame_pool() takes care of freeing
+-		 * whatever has been allocated
+-		 */
+-		if (!cmd->frame || !cmd->sense) {
+-			printk(KERN_DEBUG "megasas: pci_pool_alloc failed \n");
+-			megasas_teardown_frame_pool(instance);
+-			return -ENOMEM;
+-		}
+-
+-		cmd->frame->io.context = cmd->index;
+-		cmd->frame->io.pad_0 = 0;
+-	}
+-
+-	return 0;
+-}
+-
+-/**
+- * megasas_free_cmds -	Free all the cmds in the free cmd pool
+- * @instance:		Adapter soft state
+- */
+-static void megasas_free_cmds(struct megasas_instance *instance)
+-{
+-	int i;
+-	/* First free the MFI frame pool */
+-	megasas_teardown_frame_pool(instance);
+-
+-	/* Free all the commands in the cmd_list */
+-	for (i = 0; i < instance->max_fw_cmds; i++)
+-		kfree(instance->cmd_list[i]);
+-
+-	/* Free the cmd_list buffer itself */
+-	kfree(instance->cmd_list);
+-	instance->cmd_list = NULL;
+-
+-	INIT_LIST_HEAD(&instance->cmd_pool);
+-}
+-
+-/**
+- * megasas_alloc_cmds -	Allocates the command packets
+- * @instance:		Adapter soft state
+- *
+- * Each command that is issued to the FW, whether IO commands from the OS or
+- * internal commands like IOCTLs, are wrapped in local data structure called
+- * megasas_cmd. The frame embedded in this megasas_cmd is actually issued to
+- * the FW.
+- *
+- * Each frame has a 32-bit field called context (tag). This context is used
+- * to get back the megasas_cmd from the frame when a frame gets completed in
+- * the ISR. Typically the address of the megasas_cmd itself would be used as
+- * the context. But we wanted to keep the differences between 32 and 64 bit
+- * systems to the mininum. We always use 32 bit integers for the context. In
+- * this driver, the 32 bit values are the indices into an array cmd_list.
+- * This array is used only to look up the megasas_cmd given the context. The
+- * free commands themselves are maintained in a linked list called cmd_pool.
+- */
+-static int megasas_alloc_cmds(struct megasas_instance *instance)
+-{
+-	int i;
+-	int j;
+-	u32 max_cmd;
+-	struct megasas_cmd *cmd;
+-
+-	max_cmd = instance->max_fw_cmds;
+-
+-	/*
+-	 * instance->cmd_list is an array of struct megasas_cmd pointers.
+-	 * Allocate the dynamic array first and then allocate individual
+-	 * commands.
+-	 */
+-	instance->cmd_list = kcalloc(max_cmd, sizeof(struct megasas_cmd*), GFP_KERNEL);
+-
+-	if (!instance->cmd_list) {
+-		printk(KERN_DEBUG "megasas: out of memory\n");
+-		return -ENOMEM;
+-	}
+-
+-
+-	for (i = 0; i < max_cmd; i++) {
+-		instance->cmd_list[i] = kmalloc(sizeof(struct megasas_cmd),
+-						GFP_KERNEL);
+-
+-		if (!instance->cmd_list[i]) {
+-
+-			for (j = 0; j < i; j++)
+-				kfree(instance->cmd_list[j]);
+-
+-			kfree(instance->cmd_list);
+-			instance->cmd_list = NULL;
+-
+-			return -ENOMEM;
+-		}
+-	}
+-
+-	/*
+-	 * Add all the commands to command pool (instance->cmd_pool)
+-	 */
+-	for (i = 0; i < max_cmd; i++) {
+-		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);
+-	}
+-
+-	/*
+-	 * Create a frame pool and assign one frame to each cmd
+-	 */
+-	if (megasas_create_frame_pool(instance)) {
+-		printk(KERN_DEBUG "megasas: Error creating frame DMA pool\n");
+-		megasas_free_cmds(instance);
+-	}
+-
+-	return 0;
+-}
+-
+-/*
+- * 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
+- * supported by the FW.
+- */
+-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;
+-	}
+-
+-	dcmd = &cmd->frame->dcmd;
+-
+-	ci = pci_alloc_consistent(instance->pdev,
+-		  MEGASAS_MAX_PD * sizeof(struct MR_PD_LIST), &ci_h);
+-
+-	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->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;
+-	}
+-
+-	/*
+-	* the following function will get the instance PD LIST.
+-	*/
+-
+-	pd_addr = ci->addr;
+-
+-	if ( ret == 0 &&
+-		(ci->count <
+-		  (MEGASAS_MAX_PD_CHANNELS * MEGASAS_MAX_DEV_PER_CHANNEL))) {
+-
+-		memset(instance->pd_list, 0,
+-			MEGASAS_MAX_PD * sizeof(struct megasas_pd_list));
+-
+-		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),
+-				ci, ci_h);
+-	megasas_return_cmd(instance, cmd);
+-
+-	return ret;
+-}
+-
+-/*
+- * megasas_get_ld_list_info -	Returns FW's ld_list structure
+- * @instance:				Adapter soft state
+- * @ld_list:				ld_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
+- * supported by the FW.
+- */
+-static int
+-megasas_get_ld_list(struct megasas_instance *instance)
+-{
+-	int ret = 0, ld_index = 0, ids = 0;
+-	struct megasas_cmd *cmd;
+-	struct megasas_dcmd_frame *dcmd;
+-	struct MR_LD_LIST *ci;
+-	dma_addr_t ci_h = 0;
+-
+-	cmd = megasas_get_cmd(instance);
+-
+-	if (!cmd) {
+-		printk(KERN_DEBUG "megasas_get_ld_list: Failed to get cmd\n");
+-		return -ENOMEM;
+-	}
+-
+-	dcmd = &cmd->frame->dcmd;
+-
+-	ci = pci_alloc_consistent(instance->pdev,
+-				sizeof(struct MR_LD_LIST),
+-				&ci_h);
+-
+-	if (!ci) {
+-		printk(KERN_DEBUG "Failed to alloc mem in get_ld_list\n");
+-		megasas_return_cmd(instance, cmd);
+-		return -ENOMEM;
+-	}
+-
+-	memset(ci, 0, sizeof(*ci));
+-	memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
+-
+-	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 = sizeof(struct MR_LD_LIST);
+-	dcmd->opcode = MR_DCMD_LD_GET_LIST;
+-	dcmd->sgl.sge32[0].phys_addr = ci_h;
+-	dcmd->sgl.sge32[0].length = sizeof(struct MR_LD_LIST);
+-	dcmd->pad_0  = 0;
+-
+-	if (!megasas_issue_polled(instance, cmd)) {
+-		ret = 0;
+-	} else {
+-		ret = -1;
+-	}
+-
+-	/* the following function will get the instance PD LIST */
+-
+-	if ((ret == 0) && (ci->ldCount <= MAX_LOGICAL_DRIVES)) {
+-		memset(instance->ld_ids, 0xff, MEGASAS_MAX_LD_IDS);
+-
+-		for (ld_index = 0; ld_index < ci->ldCount; ld_index++) {
+-			if (ci->ldList[ld_index].state != 0) {
+-				ids = ci->ldList[ld_index].ref.targetId;
+-				instance->ld_ids[ids] =
+-					ci->ldList[ld_index].ref.targetId;
+-			}
+-		}
+-	}
+-
+-	pci_free_consistent(instance->pdev,
+-				sizeof(struct MR_LD_LIST),
+-				ci,
+-				ci_h);
+-
+-	megasas_return_cmd(instance, cmd);
+-	return ret;
+-}
+-
+-/**
+- * megasas_get_controller_info -	Returns FW's controller structure
+- * @instance:				Adapter soft state
+- * @ctrl_info:				Controller information structure
+- *
+- * Issues an internal command (DCMD) to get the FW's controller structure.
+- * This information is mainly used to find out the maximum IO transfer per
+- * command supported by the FW.
+- */
+-static int
+-megasas_get_ctrl_info(struct megasas_instance *instance,
+-		      struct megasas_ctrl_info *ctrl_info)
+-{
+-	int ret = 0;
+-	struct megasas_cmd *cmd;
+-	struct megasas_dcmd_frame *dcmd;
+-	struct megasas_ctrl_info *ci;
+-	dma_addr_t ci_h = 0;
+-
+-	cmd = megasas_get_cmd(instance);
+-
+-	if (!cmd) {
+-		printk(KERN_DEBUG "megasas: Failed to get a free cmd\n");
+-		return -ENOMEM;
+-	}
+-
+-	dcmd = &cmd->frame->dcmd;
+-
+-	ci = pci_alloc_consistent(instance->pdev,
+-				  sizeof(struct megasas_ctrl_info), &ci_h);
+-
+-	if (!ci) {
+-		printk(KERN_DEBUG "Failed to alloc mem for ctrl info\n");
+-		megasas_return_cmd(instance, cmd);
+-		return -ENOMEM;
+-	}
+-
+-	memset(ci, 0, sizeof(*ci));
+-	memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
+-
+-	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 = sizeof(struct megasas_ctrl_info);
+-	dcmd->opcode = MR_DCMD_CTRL_GET_INFO;
+-	dcmd->sgl.sge32[0].phys_addr = ci_h;
+-	dcmd->sgl.sge32[0].length = sizeof(struct megasas_ctrl_info);
+-
+-	if (!megasas_issue_polled(instance, cmd)) {
+-		ret = 0;
+-		memcpy(ctrl_info, ci, sizeof(struct megasas_ctrl_info));
+-	} else {
+-		ret = -1;
+-	}
+-
+-	pci_free_consistent(instance->pdev, sizeof(struct megasas_ctrl_info),
+-			    ci, ci_h);
+-
+-	megasas_return_cmd(instance, cmd);
+-	return ret;
+-}
+-
+-/**
+- * megasas_issue_init_mfi -	Initializes the FW
+- * @instance:		Adapter soft state
+- *
+- * Issues the INIT MFI cmd
+- */
+-static int
+-megasas_issue_init_mfi(struct megasas_instance *instance)
+-{
+-	u32 context;
+-
+-	struct megasas_cmd *cmd;
+-
+-	struct megasas_init_frame *init_frame;
+-	struct megasas_init_queue_info *initq_info;
+-	dma_addr_t init_frame_h;
+-	dma_addr_t initq_info_h;
+-
+-	/*
+-	 * Prepare a init frame. Note the init frame points to queue info
+-	 * structure. Each frame has SGL allocated after first 64 bytes. For
+-	 * this frame - since we don't need any SGL - we use SGL's space as
+-	 * queue info structure
+-	 *
+-	 * We will not get a NULL command below. We just created the pool.
+-	 */
+-	cmd = megasas_get_cmd(instance);
+-
+-	init_frame = (struct megasas_init_frame *)cmd->frame;
+-	initq_info = (struct megasas_init_queue_info *)
+-		((unsigned long)init_frame + 64);
+-
+-	init_frame_h = cmd->frame_phys_addr;
+-	initq_info_h = init_frame_h + 64;
+-
+-	context = init_frame->context;
+-	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;
+-
+-	initq_info->producer_index_phys_addr_lo = instance->producer_h;
+-	initq_info->consumer_index_phys_addr_lo = instance->consumer_h;
+-
+-	init_frame->cmd = MFI_CMD_INIT;
+-	init_frame->cmd_status = 0xFF;
+-	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
+-	 */
+-	instance->instancet->disable_intr(instance->reg_set);
+-
+-	/*
+-	 * Issue the init frame in polled mode
+-	 */
+-
+-	if (megasas_issue_polled(instance, cmd)) {
+-		printk(KERN_ERR "megasas: Failed to init firmware\n");
+-		megasas_return_cmd(instance, cmd);
+-		goto fail_fw_init;
+-	}
+-
+-	megasas_return_cmd(instance, cmd);
+-
+-	return 0;
+-
+-fail_fw_init:
+-	return -EINVAL;
+-}
+-
+-/**
+- * megasas_start_timer - Initializes a timer object
+- * @instance:		Adapter soft state
+- * @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,
+-			struct timer_list *timer,
+-			void *fn, unsigned long interval)
+-{
+-	init_timer(timer);
+-	timer->expires = jiffies + interval;
+-	timer->data = (unsigned long)instance;
+-	timer->function = fn;
+-	add_timer(timer);
+-}
+-
+-/**
+- * megasas_io_completion_timer - Timer fn
+- * @instance_addr:	Address of adapter soft state
+- *
+- * 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_addr;
+-
+-	if (atomic_read(&instance->fw_outstanding))
+-		tasklet_schedule(&instance->isr_tasklet);
+-
+-	/* Restart timer */
+-	if (poll_mode_io)
+-		mod_timer(&instance->io_completion_timer,
+-			jiffies + MEGASAS_COMPLETION_TIMER_INTERVAL);
+-}
+-
+-/**
+- * megasas_init_mfi -	Initializes the FW
+- * @instance:		Adapter soft state
+- *
+- * This is the main function for initializing MFI firmware.
+- */
+-static int megasas_init_mfi(struct megasas_instance *instance)
+-{
+-	u32 context_sz;
+-	u32 reply_q_sz;
+-	u32 max_sectors_1;
+-	u32 max_sectors_2;
+-	u32 tmp_sectors;
+-	struct megasas_register_set __iomem *reg_set;
+-	struct megasas_ctrl_info *ctrl_info;
+-	/*
+-	 * Map the message registers
+-	 */
+-	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->base_addr = pci_resource_start(instance->pdev, 1);
+-	} else {
+-		instance->base_addr = pci_resource_start(instance->pdev, 0);
+-	}
+-
+-	if (pci_request_regions(instance->pdev, "megasas: LSI")) {
+-		printk(KERN_DEBUG "megasas: IO memory region busy!\n");
+-		return -EBUSY;
+-	}
+-
+-	instance->reg_set = ioremap_nocache(instance->base_addr, 8192);
+-
+-	if (!instance->reg_set) {
+-		printk(KERN_DEBUG "megasas: Failed to map IO mem\n");
+-		goto fail_ioremap;
+-	}
+-
+-	reg_set = instance->reg_set;
+-
+-	switch(instance->pdev->device)
+-	{
+-		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:
+-		case PCI_DEVICE_ID_LSI_SAS0079GEN2:
+-			instance->instancet = &megasas_instance_template_gen2;
+-			break;
+-		case PCI_DEVICE_ID_LSI_SAS0073SKINNY:
+-		case PCI_DEVICE_ID_LSI_SAS0071SKINNY:
+-			instance->instancet = &megasas_instance_template_skinny;
+-			break;
+-		case PCI_DEVICE_ID_LSI_SAS1064R:
+-		case PCI_DEVICE_ID_DELL_PERC5:
+-		default:
+-			instance->instancet = &megasas_instance_template_xscale;
+-			break;
+-	}
+-
+-	/*
+-	 * We expect the FW state to be READY
+-	 */
+-	if (megasas_transition_to_ready(instance))
+-		goto fail_ready_state;
+-
+-	/*
+-	 * 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)
+-	 * does not exceed max cmds that the FW can support
+-	 */
+-	instance->max_fw_cmds = instance->max_fw_cmds-1;
+-	instance->max_num_sge = (instance->instancet->read_fw_status_reg(reg_set) & 0xFF0000) >> 
+-					0x10;
+-	/*
+-	 * Create a pool of commands
+-	 */
+-	if (megasas_alloc_cmds(instance))
+-		goto fail_alloc_cmds;
+-
+-	/*
+-	 * Allocate memory for reply queue. Length of reply queue should
+-	 * be _one_ more than the maximum commands handled by the firmware.
+-	 *
+-	 * Note: When FW completes commands, it places corresponding contex
+-	 * values in this circular reply queue. This circular queue is a fairly
+-	 * typical producer-consumer queue. FW is the producer (of completed
+-	 * commands) and the driver is the consumer.
+-	 */
+-	context_sz = sizeof(u32);
+-	reply_q_sz = context_sz * (instance->max_fw_cmds + 1);
+-
+-	instance->reply_queue = pci_alloc_consistent(instance->pdev,
+-						     reply_q_sz,
+-						     &instance->reply_queue_h);
+-
+-	if (!instance->reply_queue) {
+-		printk(KERN_DEBUG "megasas: Out of DMA mem for reply queue\n");
+-		goto fail_reply_queue;
+-	}
+-
+-	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(KERN_NOTICE "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.
+-	*/
+-
+-	memset(instance->pd_list, 0 ,
+-		(MEGASAS_MAX_PD * sizeof(struct megasas_pd_list)));
+-	megasas_get_pd_list(instance);
+-
+-	memset(instance->ld_ids, 0xff, MEGASAS_MAX_LD_IDS);
+-	megasas_get_ld_list(instance);
+-
+-	ctrl_info = kmalloc(sizeof(struct megasas_ctrl_info), GFP_KERNEL);
+-
+-	/*
+-	 * Compute the max allowed sectors per IO: The controller info has two
+-	 * limits on max sectors. Driver should use the minimum of these two.
+-	 *
+-	 * 1 << stripe_sz_ops.min = max sectors per strip
+-	 *
+-	 * Note that older firmwares ( < FW ver 30) didn't report information
+-	 * to calculate max_sectors_1. So the number ended up as zero always.
+-	 */
+-	tmp_sectors = 0;
+-	if (ctrl_info && !megasas_get_ctrl_info(instance, ctrl_info)) {
+-
+-		max_sectors_1 = (1 << ctrl_info->stripe_sz_ops.min) *
+-		    ctrl_info->max_strips_per_io;
+-		max_sectors_2 = ctrl_info->max_request_size;
+-
+-		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;
+-	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
+-	*/
+-
+-	tasklet_init(&instance->isr_tasklet, megasas_complete_cmd_dpc,
+-		(unsigned long)instance);
+-
+-	/* Initialize the cmd completion timer */
+-	if (poll_mode_io)
+-		megasas_start_timer(instance, &instance->io_completion_timer,
+-				megasas_io_completion_timer,
+-				MEGASAS_COMPLETION_TIMER_INTERVAL);
+-	return 0;
+-
+-      fail_fw_init:
+-
+-	pci_free_consistent(instance->pdev, reply_q_sz,
+-			    instance->reply_queue, instance->reply_queue_h);
+-      fail_reply_queue:
+-	megasas_free_cmds(instance);
+-
+-      fail_alloc_cmds:
+-      fail_ready_state:
+-	iounmap(instance->reg_set);
+-
+-      fail_ioremap:
+-	pci_release_regions(instance->pdev);
+-
+-	return -EINVAL;
+-}
+-
+-/**
+- * megasas_release_mfi -	Reverses the FW initialization
+- * @intance:			Adapter soft state
+- */
+-static void megasas_release_mfi(struct megasas_instance *instance)
+-{
+-	u32 reply_q_sz = sizeof(u32) * (instance->max_fw_cmds + 1);
+-
+-	pci_free_consistent(instance->pdev, reply_q_sz,
+-			    instance->reply_queue, instance->reply_queue_h);
+-
+-	megasas_free_cmds(instance);
+-
+-	iounmap(instance->reg_set);
+-
+-	pci_release_regions(instance->pdev);
+-}
+-
+-/**
+- * megasas_get_seq_num -	Gets latest event sequence numbers
+- * @instance:			Adapter soft state
+- * @eli:			FW event log sequence numbers information
+- *
+- * FW maintains a log of all events in a non-volatile area. Upper layers would
+- * usually find out the latest sequence number of the events, the seq number at
+- * the boot etc. They would "read" all the events below the latest seq number
+- * by issuing a direct fw cmd (DCMD). For the future events (beyond latest seq
+- * number), they would subsribe to AEN (asynchronous event notification) and
+- * wait for the events to happen.
+- */
+-static int
+-megasas_get_seq_num(struct megasas_instance *instance,
+-		    struct megasas_evt_log_info *eli)
+-{
+-	struct megasas_cmd *cmd;
+-	struct megasas_dcmd_frame *dcmd;
+-	struct megasas_evt_log_info *el_info;
+-	dma_addr_t el_info_h = 0;
+-
+-	cmd = megasas_get_cmd(instance);
+-
+-	if (!cmd) {
+-		return -ENOMEM;
+-	}
+-
+-	dcmd = &cmd->frame->dcmd;
+-	el_info = pci_alloc_consistent(instance->pdev,
+-				       sizeof(struct megasas_evt_log_info),
+-				       &el_info_h);
+-
+-	if (!el_info) {
+-		megasas_return_cmd(instance, cmd);
+-		return -ENOMEM;
+-	}
+-
+-	memset(el_info, 0, sizeof(*el_info));
+-	memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
+-
+-	dcmd->cmd = MFI_CMD_DCMD;
+-	dcmd->cmd_status = 0x0;
+-	dcmd->sge_count = 1;
+-	dcmd->flags = MFI_FRAME_DIR_READ;
+-	dcmd->timeout = 0;
+-	dcmd->data_xfer_len = sizeof(struct megasas_evt_log_info);
+-	dcmd->opcode = MR_DCMD_CTRL_EVENT_GET_INFO;
+-	dcmd->sgl.sge32[0].phys_addr = el_info_h;
+-	dcmd->sgl.sge32[0].length = sizeof(struct megasas_evt_log_info);
+-
+-	megasas_issue_blocked_cmd(instance, cmd);
+-
+-	/*
+-	 * Copy the data back into callers buffer
+-	 */
+-	memcpy(eli, el_info, sizeof(struct megasas_evt_log_info));
+-
+-	pci_free_consistent(instance->pdev, sizeof(struct megasas_evt_log_info),
+-			    el_info, el_info_h);
+-
+-	megasas_return_cmd(instance, cmd);
+-
+-	return 0;
+-}
+-
+-/**
+- * megasas_register_aen -	Registers for asynchronous event notification
+- * @instance:			Adapter soft state
+- * @seq_num:			The starting sequence number
+- * @class_locale:		Class of the event
+- *
+- * This function subscribes for AEN for events beyond the @seq_num. It requests
+- * to be notified if and only if the event is of type @class_locale
+- */
+-static int
+-megasas_register_aen(struct megasas_instance *instance, u32 seq_num,
+-		     u32 class_locale_word)
+-{
+-	int ret_val;
+-	struct megasas_cmd *cmd;
+-	struct megasas_dcmd_frame *dcmd;
+-	union megasas_evt_class_locale curr_aen;
+-	union megasas_evt_class_locale prev_aen;
+-
+-	/*
+-	 * If there an AEN pending already (aen_cmd), check if the
+-	 * class_locale of that pending AEN is inclusive of the new
+-	 * AEN request we currently have. If it is, then we don't have
+-	 * to do anything. In other words, whichever events the current
+-	 * AEN request is subscribing to, have already been subscribed
+-	 * to.
+-	 *
+-	 * If the old_cmd is _not_ inclusive, then we have to abort
+-	 * that command, form a class_locale that is superset of both
+-	 * old and current and re-issue to the FW
+-	 */
+-
+-	curr_aen.word = class_locale_word;
+-
+-	if (instance->aen_cmd) {
+-
+-		prev_aen.word = instance->aen_cmd->frame->dcmd.mbox.w[1];
+-
+-		/*
+-		 * A class whose enum value is smaller is inclusive of all
+-		 * higher values. If a PROGRESS (= -1) was previously
+-		 * registered, then a new registration requests for higher
+-		 * classes need not be sent to FW. They are automatically
+-		 * included.
+-		 *
+-		 * Locale numbers don't have such hierarchy. They are bitmap
+-		 * values
+-		 */
+-		if ((prev_aen.members.class <= curr_aen.members.class) &&
+-		    !((prev_aen.members.locale & curr_aen.members.locale) ^
+-		      curr_aen.members.locale)) {
+-			/*
+-			 * Previously issued event registration includes
+-			 * current request. Nothing to do.
+-			 */
+-			return 0;
+-		} else {
+-			curr_aen.members.locale |= prev_aen.members.locale;
+-
+-			if (prev_aen.members.class < curr_aen.members.class)
+-				curr_aen.members.class = prev_aen.members.class;
+-
+-			instance->aen_cmd->abort_aen = 1;
+-			ret_val = megasas_issue_blocked_abort_cmd(instance,
+-								  instance->
+-								  aen_cmd);
+-
+-			if (ret_val) {
+-				printk(KERN_DEBUG "megasas: Failed to abort "
+-				       "previous AEN command\n");
+-				return ret_val;
+-			}
+-		}
+-	}
+-
+-	cmd = megasas_get_cmd(instance);
+-
+-	if (!cmd)
+-		return -ENOMEM;
+-
+-	dcmd = &cmd->frame->dcmd;
+-
+-	memset(instance->evt_detail, 0, sizeof(struct megasas_evt_detail));
+-
+-	/*
+-	 * Prepare DCMD for aen registration
+-	 */
+-	memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
+-
+-	dcmd->cmd = MFI_CMD_DCMD;
+-	dcmd->cmd_status = 0x0;
+-	dcmd->sge_count = 1;
+-	dcmd->flags = MFI_FRAME_DIR_READ;
+-	dcmd->timeout = 0;
+-	instance->last_seq_num = seq_num;
+-	dcmd->data_xfer_len = sizeof(struct megasas_evt_detail);
+-	dcmd->opcode = MR_DCMD_CTRL_EVENT_WAIT;
+-	dcmd->mbox.w[0] = 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;
+-	}
+-
+-	/*
+-	 * Store reference to the cmd used to register for AEN. When an
+-	 * application wants us to register for AEN, we have to abort this
+-	 * cmd and re-register with a new EVENT LOCALE supplied by that app
+-	 */
+-	instance->aen_cmd = cmd;
+-
+-	/*
+-	 * Issue the aen registration frame
+-	 */
+-	instance->instancet->fire_cmd(instance,
+-			cmd->frame_phys_addr, 0, instance->reg_set);
+-
+-	return 0;
+-}
+-
+-/**
+- * megasas_start_aen -	Subscribes to AEN during driver load time
+- * @instance:		Adapter soft state
+- */
+-static int megasas_start_aen(struct megasas_instance *instance)
+-{
+-	struct megasas_evt_log_info eli;
+-	union megasas_evt_class_locale class_locale;
+-
+-	/*
+-	 * Get the latest sequence number from FW
+-	 */
+-	memset(&eli, 0, sizeof(eli));
+-
+-	if (megasas_get_seq_num(instance, &eli))
+-		return -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;
+-
+-	return megasas_register_aen(instance, eli.newest_seq_num + 1,
+-				    class_locale.word);
+-}
+-
+-/**
+- * megasas_io_attach -	Attaches this driver to SCSI mid-layer
+- * @instance:		Adapter soft state
+- */
+-static int megasas_io_attach(struct megasas_instance *instance)
+-{
+-	struct Scsi_Host *host = instance->host;
+-
+-	/*
+-	 * Export parameters required by SCSI mid-layer
+-	 */
+-	host->irq = instance->pdev->irq;
+-	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;
+-	} else
+-		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;
+-	host->cmd_per_lun = 128;
+-	host->max_channel = MEGASAS_MAX_CHANNELS - 1;
+-	host->max_id = MEGASAS_MAX_DEV_PER_CHANNEL;
+-	host->max_lun = MEGASAS_MAX_LUN;
+-	host->max_cmd_len = 16;
+-
+-	/*
+-	 * Notify the mid-layer about the new controller
+-	 */
+-	if (scsi_add_host(host, &instance->pdev->dev)) {
+-		printk(KERN_DEBUG "megasas: scsi_add_host failed\n");
+-		return -ENODEV;
+-	}
+-
+-	/*
+-	 * Trigger SCSI to scan our drives
+-	 */
+-	scsi_scan_host(host);
+-	return 0;
+-}
+-
+-static int
+-megasas_set_dma_mask(struct pci_dev *pdev)
+-{
+-	/*
+-	 * All our contollers are capable of performing 64-bit DMA
+-	 */
+-	if (IS_DMA64) {
+-		if (pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) != 0) {
+-
+-			if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) != 0)
+-				goto fail_set_dma_mask;
+-		}
+-	} else {
+-		if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) != 0)
+-			goto fail_set_dma_mask;
+-	}
+-	return 0;
+-
+-fail_set_dma_mask:
+-	return 1;
+-}
+-
+-/**
+- * megasas_probe_one -	PCI hotplug entry point
+- * @pdev:		PCI device structure
+- * @id:			PCI ids of supported hotplugged adapter	
+- */
+-static int __devinit
+-megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
+-{
+-	int rval;
+-	struct Scsi_Host *host;
+-	struct megasas_instance *instance;
+-
+-	/*
+-	 * Announce PCI information
+-	 */
+-	printk(KERN_INFO "megasas: %#4.04x:%#4.04x:%#4.04x:%#4.04x: ",
+-	       pdev->vendor, pdev->device, pdev->subsystem_vendor,
+-	       pdev->subsystem_device);
+-
+-	printk("bus %d:slot %d:func %d\n",
+-	       pdev->bus->number, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn));
+-
+-	/*
+-	 * PCI prepping: enable device set bus mastering and dma mask
+-	 */
+-	rval = pci_enable_device(pdev);
+-
+-	if (rval) {
+-		return rval;
+-	}
+-
+-	pci_set_master(pdev);
+-
+-	if (megasas_set_dma_mask(pdev))
+-		goto fail_set_dma_mask;
+-
+-	host = scsi_host_alloc(&megasas_template,
+-			       sizeof(struct megasas_instance));
+-
+-	if (!host) {
+-		printk(KERN_DEBUG "megasas: scsi_host_alloc failed\n");
+-		goto fail_alloc_instance;
+-	}
+-
+-	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),
+-						  &instance->consumer_h);
+-
+-	if (!instance->producer || !instance->consumer) {
+-		printk(KERN_DEBUG "megasas: Failed to allocate memory for "
+-		       "producer, consumer\n");
+-		goto fail_alloc_dma_buf;
+-	}
+-
+-	*instance->producer = 0;
+-	*instance->consumer = 0;
+-	megasas_poll_wait_aen = 0;
+-	instance->flag_ieee = 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
+-							   megasas_evt_detail),
+-						    &instance->evt_detail_h);
+-
+-	if (!instance->evt_detail) {
+-		printk(KERN_DEBUG "megasas: Failed to allocate memory for "
+-		       "event detail structure\n");
+-		goto fail_alloc_dma_buf;
+-	}
+-
+-	/*
+-	 * Initialize locks and queues
+-	 */
+-	INIT_LIST_HEAD(&instance->cmd_pool);
+-	INIT_LIST_HEAD(&instance->internal_reset_pending_q);
+-
+-	atomic_set(&instance->fw_outstanding,0);
+-
+-	init_waitqueue_head(&instance->int_cmd_wait_q);
+-	init_waitqueue_head(&instance->abort_cmd_wait_q);
+-
+-	spin_lock_init(&instance->cmd_pool_lock);
+-	spin_lock_init(&instance->hba_lock);
+-	spin_lock_init(&instance->completion_lock);
+-	spin_lock_init(&poll_aen_lock);
+-
+-	mutex_init(&instance->aen_mutex);
+-
+-	/*
+-	 * Initialize PCI related and misc parameters
+-	 */
+-	instance->pdev = pdev;
+-	instance->host = host;
+-	instance->unique_id = pdev->bus->number << 8 | pdev->devfn;
+-	instance->init_id = MEGASAS_DEFAULT_INIT_ID;
+-
+-	if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0073SKINNY) ||
+-		(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->disableOnlineCtrlReset = 1;
+-
+-	INIT_WORK(&instance->work_init, process_fw_state_change_wq);
+-
+-	/*
+-	 * Initialize MFI Firmware
+-	 */
+-	if (megasas_init_mfi(instance))
+-		goto fail_init_mfi;
+-
+-	/*
+-	 * Register IRQ
+-	 */
+-	if (request_irq(pdev->irq, megasas_isr, IRQF_SHARED, "megasas", instance)) {
+-		printk(KERN_DEBUG "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);
+-
+-	/*
+-	 * Add this controller to megasas_mgmt_info structure so that it
+-	 * can be exported to management applications
+-	 */
+-	megasas_mgmt_info.count++;
+-	megasas_mgmt_info.instance[megasas_mgmt_info.max_index] = instance;
+-	megasas_mgmt_info.max_index++;
+-
+-	/*
+-	 * Initiate AEN (Asynchronous Event Notification)
+-	 */
+-	if (megasas_start_aen(instance)) {
+-		printk(KERN_DEBUG "megasas: start aen failed\n");
+-		goto fail_start_aen;
+-	}
+-
+-	/*
+-	 * Register with SCSI mid-layer
+-	 */
+-	if (megasas_io_attach(instance))
+-		goto fail_io_attach;
+-
+-	instance->unload = 0;
+-	return 0;
+-
+-      fail_start_aen:
+-      fail_io_attach:
+-	megasas_mgmt_info.count--;
+-	megasas_mgmt_info.instance[megasas_mgmt_info.max_index] = NULL;
+-	megasas_mgmt_info.max_index--;
+-
+-	pci_set_drvdata(pdev, NULL);
+-	instance->instancet->disable_intr(instance->reg_set);
+-	free_irq(instance->pdev->irq, instance);
+-
+-	megasas_release_mfi(instance);
+-
+-      fail_irq:
+-      fail_init_mfi:
+-      fail_alloc_dma_buf:
+-	if (instance->evt_detail)
+-		pci_free_consistent(pdev, sizeof(struct megasas_evt_detail),
+-				    instance->evt_detail,
+-				    instance->evt_detail_h);
+-
+-	if (instance->producer)
+-		pci_free_consistent(pdev, sizeof(u32), instance->producer,
+-				    instance->producer_h);
+-	if (instance->consumer)
+-		pci_free_consistent(pdev, sizeof(u32), instance->consumer,
+-				    instance->consumer_h);
+-	scsi_host_put(host);
+-
+-      fail_alloc_instance:
+-      fail_set_dma_mask:
+-	pci_disable_device(pdev);
+-
+-	return -ENODEV;
+-}
+-
+-/**
+- * megasas_flush_cache -	Requests FW to flush all its caches
+- * @instance:			Adapter soft state
+- */
+-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)
+-		return;
+-
+-	dcmd = &cmd->frame->dcmd;
+-
+-	memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
+-
+-	dcmd->cmd = MFI_CMD_DCMD;
+-	dcmd->cmd_status = 0x0;
+-	dcmd->sge_count = 0;
+-	dcmd->flags = MFI_FRAME_DIR_NONE;
+-	dcmd->timeout = 0;
+-	dcmd->data_xfer_len = 0;
+-	dcmd->opcode = MR_DCMD_CTRL_CACHE_FLUSH;
+-	dcmd->mbox.b[0] = MR_FLUSH_CTRL_CACHE | MR_FLUSH_DISK_CACHE;
+-
+-	megasas_issue_blocked_cmd(instance, cmd);
+-
+-	megasas_return_cmd(instance, cmd);
+-
+-	return;
+-}
+-
+-/**
+- * megasas_shutdown_controller -	Instructs FW to shutdown the controller
+- * @instance:				Adapter soft state
+- * @opcode:				Shutdown/Hibernate
+- */
+-static void megasas_shutdown_controller(struct megasas_instance *instance,
+-					u32 opcode)
+-{
+-	struct megasas_cmd *cmd;
+-	struct megasas_dcmd_frame *dcmd;
+-
+-	if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR)
+-		return;
+-
+-	cmd = megasas_get_cmd(instance);
+-
+-	if (!cmd)
+-		return;
+-
+-	if (instance->aen_cmd)
+-		megasas_issue_blocked_abort_cmd(instance, instance->aen_cmd);
+-
+-	dcmd = &cmd->frame->dcmd;
+-
+-	memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
+-
+-	dcmd->cmd = MFI_CMD_DCMD;
+-	dcmd->cmd_status = 0x0;
+-	dcmd->sge_count = 0;
+-	dcmd->flags = MFI_FRAME_DIR_NONE;
+-	dcmd->timeout = 0;
+-	dcmd->data_xfer_len = 0;
+-	dcmd->opcode = opcode;
+-
+-	megasas_issue_blocked_cmd(instance, cmd);
+-
+-	megasas_return_cmd(instance, cmd);
+-
+-	return;
+-}
+-
+-#ifdef CONFIG_PM
+-/**
+- * megasas_suspend -	driver suspend entry point
+- * @pdev:		PCI device structure
+- * @state:		PCI power state to suspend routine
+- */
+-static int
+-megasas_suspend(struct pci_dev *pdev, pm_message_t state)
+-{
+-	struct Scsi_Host *host;
+-	struct megasas_instance *instance;
+-
+-	instance = pci_get_drvdata(pdev);
+-	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(
+-			(struct delayed_work *)&ev->hotplug_work);
+-		flush_scheduled_work();
+-		instance->ev = NULL;
+-	}
+-
+-	tasklet_kill(&instance->isr_tasklet);
+-
+-	pci_set_drvdata(instance->pdev, instance);
+-	instance->instancet->disable_intr(instance->reg_set);
+-	free_irq(instance->pdev->irq, instance);
+-
+-	pci_save_state(pdev);
+-	pci_disable_device(pdev);
+-
+-	pci_set_power_state(pdev, pci_choose_state(pdev, state));
+-
+-	return 0;
+-}
+-
+-/**
+- * megasas_resume-      driver resume entry point
+- * @pdev:               PCI device structure
+- */
+-static int
+-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);
+-	pci_enable_wake(pdev, PCI_D0, 0);
+-	pci_restore_state(pdev);
+-
+-	/*
+-	 * PCI prepping: enable device set bus mastering and dma mask
+-	 */
+-	rval = pci_enable_device(pdev);
+-
+-	if (rval) {
+-		printk(KERN_ERR "megasas: Enable device failed\n");
+-		return rval;
+-	}
+-
+-	pci_set_master(pdev);
+-
+-	if (megasas_set_dma_mask(pdev))
+-		goto fail_set_dma_mask;
+-
+-	/*
+-	 * Initialize MFI Firmware
+-	 */
+-
+-	*instance->producer = 0;
+-	*instance->consumer = 0;
+-
+-	atomic_set(&instance->fw_outstanding, 0);
+-
+-	/*
+-	 * We expect the FW state to be READY
+-	 */
+-	if (megasas_transition_to_ready(instance))
+-		goto fail_ready_state;
+-
+-	if (megasas_issue_init_mfi(instance))
+-		goto fail_init_mfi;
+-
+-	tasklet_init(&instance->isr_tasklet, megasas_complete_cmd_dpc,
+-			(unsigned long)instance);
+-
+-	/*
+-	 * Register IRQ
+-	 */
+-	if (request_irq(pdev->irq, megasas_isr, IRQF_SHARED,
+-		"megasas", instance)) {
+-		printk(KERN_ERR "megasas: Failed to register IRQ\n");
+-		goto fail_irq;
+-	}
+-
+-	instance->instancet->enable_intr(instance->reg_set);
+-
+-	/*
+-	 * Initiate AEN (Asynchronous Event Notification)
+-	 */
+-	if (megasas_start_aen(instance))
+-		printk(KERN_ERR "megasas: Start AEN failed\n");
+-
+-	/* Initialize the cmd completion timer */
+-	if (poll_mode_io)
+-		megasas_start_timer(instance, &instance->io_completion_timer,
+-				megasas_io_completion_timer,
+-				MEGASAS_COMPLETION_TIMER_INTERVAL);
+-	instance->unload = 0;
+-
+-	return 0;
+-
+-fail_irq:
+-fail_init_mfi:
+-	if (instance->evt_detail)
+-		pci_free_consistent(pdev, sizeof(struct megasas_evt_detail),
+-				instance->evt_detail,
+-				instance->evt_detail_h);
+-
+-	if (instance->producer)
+-		pci_free_consistent(pdev, sizeof(u32), instance->producer,
+-				instance->producer_h);
+-	if (instance->consumer)
+-		pci_free_consistent(pdev, sizeof(u32), instance->consumer,
+-				instance->consumer_h);
+-	scsi_host_put(host);
+-
+-fail_set_dma_mask:
+-fail_ready_state:
+-
+-	pci_disable_device(pdev);
+-
+-	return -ENODEV;
+-}
+-#else
+-#define megasas_suspend	NULL
+-#define megasas_resume	NULL
+-#endif
+-
+-/**
+- * megasas_detach_one -	PCI hot"un"plug entry point
+- * @pdev:		PCI device structure
+- */
+-static void __devexit megasas_detach_one(struct pci_dev *pdev)
+-{
+-	int i;
+-	struct Scsi_Host *host;
+-	struct megasas_instance *instance;
+-
+-	instance = pci_get_drvdata(pdev);
+-	instance->unload = 1;
+-	host = instance->host;
+-
+-	if (poll_mode_io)
+-		del_timer_sync(&instance->io_completion_timer);
+-
+-	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(
+-			(struct delayed_work *)&ev->hotplug_work);
+-		flush_scheduled_work();
+-		instance->ev = NULL;
+-	}
+-
+-	tasklet_kill(&instance->isr_tasklet);
+-
+-	/*
+-	 * Take the instance off the instance array. Note that we will not
+-	 * decrement the max_index. We let this array be sparse array
+-	 */
+-	for (i = 0; i < megasas_mgmt_info.max_index; i++) {
+-		if (megasas_mgmt_info.instance[i] == instance) {
+-			megasas_mgmt_info.count--;
+-			megasas_mgmt_info.instance[i] = NULL;
+-
+-			break;
+-		}
+-	}
+-
+-	pci_set_drvdata(instance->pdev, NULL);
+-
+-	instance->instancet->disable_intr(instance->reg_set);
+-
+-	free_irq(instance->pdev->irq, instance);
+-
+-	megasas_release_mfi(instance);
+-
+-	pci_free_consistent(pdev, sizeof(struct megasas_evt_detail),
+-			    instance->evt_detail, instance->evt_detail_h);
+-
+-	pci_free_consistent(pdev, sizeof(u32), instance->producer,
+-			    instance->producer_h);
+-
+-	pci_free_consistent(pdev, sizeof(u32), instance->consumer,
+-			    instance->consumer_h);
+-
+-	scsi_host_put(host);
+-
+-	pci_set_drvdata(pdev, NULL);
+-
+-	pci_disable_device(pdev);
+-
+-	return;
+-}
+-
+-/**
+- * megasas_shutdown -	Shutdown entry point
+- * @device:		Generic device structure
+- */
+-static void megasas_shutdown(struct pci_dev *pdev)
+-{
+-	struct megasas_instance *instance = pci_get_drvdata(pdev);
+-	instance->unload = 1;
+-	megasas_flush_cache(instance);
+-	megasas_shutdown_controller(instance, MR_DCMD_CTRL_SHUTDOWN);
+-}
+-
+-/**
+- * megasas_mgmt_open -	char node "open" entry point
+- */
+-static int megasas_mgmt_open(struct inode *inode, struct file *filep)
+-{
+-	cycle_kernel_lock();
+-	/*
+-	 * Allow only those users with admin rights
+-	 */
+-	if (!capable(CAP_SYS_ADMIN))
+-		return -EACCES;
+-
+-	return 0;
+-}
+-
+-/**
+- * megasas_mgmt_fasync -	Async notifier registration from applications
+- *
+- * This function adds the calling process to a driver global queue. When an
+- * event occurs, SIGIO will be sent to all processes in this queue.
+- */
+-static int megasas_mgmt_fasync(int fd, struct file *filep, int mode)
+-{
+-	int rc;
+-
+-	mutex_lock(&megasas_async_queue_mutex);
+-
+-	rc = fasync_helper(fd, filep, mode, &megasas_async_queue);
+-
+-	mutex_unlock(&megasas_async_queue_mutex);
+-
+-	if (rc >= 0) {
+-		/* For sanity check when we get ioctl */
+-		filep->private_data = filep;
+-		return 0;
+-	}
+-
+-	printk(KERN_DEBUG "megasas: fasync_helper failed [%d]\n", rc);
+-
+-	return rc;
+-}
+-
+-/**
+- * megasas_mgmt_poll -  char node "poll" entry point
+- * */
+-static unsigned int megasas_mgmt_poll(struct file *file, poll_table *wait)
+-{
+-	unsigned int mask;
+-	unsigned long flags;
+-	poll_wait(file, &megasas_poll_wait, wait);
+-	spin_lock_irqsave(&poll_aen_lock, flags);
+-	if (megasas_poll_wait_aen)
+-		mask =   (POLLIN | POLLRDNORM);
+-	else
+-		mask = 0;
+-	spin_unlock_irqrestore(&poll_aen_lock, flags);
+-	return mask;
+-}
+-
+-/**
+- * megasas_mgmt_fw_ioctl -	Issues management ioctls to FW
+- * @instance:			Adapter soft state
+- * @argp:			User's ioctl packet
+- */
+-static int
+-megasas_mgmt_fw_ioctl(struct megasas_instance *instance,
+-		      struct megasas_iocpacket __user * user_ioc,
+-		      struct megasas_iocpacket *ioc)
+-{
+-	struct megasas_sge32 *kern_sge32;
+-	struct megasas_cmd *cmd;
+-	void *kbuff_arr[MAX_IOCTL_SGE];
+-	dma_addr_t buf_handle = 0;
+-	int error = 0, i;
+-	void *sense = NULL;
+-	dma_addr_t sense_handle;
+-	unsigned long *sense_ptr;
+-
+-	memset(kbuff_arr, 0, sizeof(kbuff_arr));
+-
+-	if (ioc->sge_count > MAX_IOCTL_SGE) {
+-		printk(KERN_DEBUG "megasas: SGE count [%d] >  max limit [%d]\n",
+-		       ioc->sge_count, MAX_IOCTL_SGE);
+-		return -EINVAL;
+-	}
+-
+-	cmd = megasas_get_cmd(instance);
+-	if (!cmd) {
+-		printk(KERN_DEBUG "megasas: Failed to get a cmd packet\n");
+-		return -ENOMEM;
+-	}
+-
+-	/*
+-	 * User's IOCTL packet has 2 frames (maximum). Copy those two
+-	 * frames into our cmd's frames. cmd->frame's context will get
+-	 * overwritten when we copy from user's frames. So set that value
+-	 * alone separately
+-	 */
+-	memcpy(cmd->frame, ioc->frame.raw, 2 * MEGAMFI_FRAME_SIZE);
+-	cmd->frame->hdr.context = cmd->index;
+-	cmd->frame->hdr.pad_0 = 0;
+-
+-	/*
+-	 * The management interface between applications and the fw uses
+-	 * MFI frames. E.g, RAID configuration changes, LD property changes
+-	 * etc are accomplishes through different kinds of MFI frames. The
+-	 * driver needs to care only about substituting user buffers with
+-	 * kernel buffers in SGLs. The location of SGL is embedded in the
+-	 * struct iocpacket itself.
+-	 */
+-	kern_sge32 = (struct megasas_sge32 *)
+-	    ((unsigned long)cmd->frame + ioc->sgl_off);
+-
+-	/*
+-	 * For each user buffer, create a mirror buffer and copy in
+-	 */
+-	for (i = 0; i < ioc->sge_count; i++) {
+-		if (!ioc->sgl[i].iov_len)
+-			continue;
+-
+-		kbuff_arr[i] = dma_alloc_coherent(&instance->pdev->dev,
+-						    ioc->sgl[i].iov_len,
+-						    &buf_handle, GFP_KERNEL);
+-		if (!kbuff_arr[i]) {
+-			printk(KERN_DEBUG "megasas: Failed to alloc "
+-			       "kernel SGL buffer for IOCTL \n");
+-			error = -ENOMEM;
+-			goto out;
+-		}
+-
+-		/*
+-		 * We don't change the dma_coherent_mask, so
+-		 * pci_alloc_consistent only returns 32bit addresses
+-		 */
+-		kern_sge32[i].phys_addr = (u32) buf_handle;
+-		kern_sge32[i].length = ioc->sgl[i].iov_len;
+-
+-		/*
+-		 * We created a kernel buffer corresponding to the
+-		 * user buffer. Now copy in from the user buffer
+-		 */
+-		if (copy_from_user(kbuff_arr[i], ioc->sgl[i].iov_base,
+-				   (u32) (ioc->sgl[i].iov_len))) {
+-			error = -EFAULT;
+-			goto out;
+-		}
+-	}
+-
+-	if (ioc->sense_len) {
+-		sense = dma_alloc_coherent(&instance->pdev->dev, ioc->sense_len,
+-					     &sense_handle, GFP_KERNEL);
+-		if (!sense) {
+-			error = -ENOMEM;
+-			goto out;
+-		}
+-
+-		sense_ptr =
+-		(unsigned long *) ((unsigned long)cmd->frame + ioc->sense_off);
+-		*sense_ptr = sense_handle;
+-	}
+-
+-	/*
+-	 * Set the sync_cmd flag so that the ISR knows not to complete this
+-	 * cmd to the SCSI mid-layer
+-	 */
+-	cmd->sync_cmd = 1;
+-	megasas_issue_blocked_cmd(instance, cmd);
+-	cmd->sync_cmd = 0;
+-
+-	/*
+-	 * copy out the kernel buffers to user buffers
+-	 */
+-	for (i = 0; i < ioc->sge_count; i++) {
+-		if (copy_to_user(ioc->sgl[i].iov_base, kbuff_arr[i],
+-				 ioc->sgl[i].iov_len)) {
+-			error = -EFAULT;
+-			goto out;
+-		}
+-	}
+-
+-	/*
+-	 * copy out the sense
+-	 */
+-	if (ioc->sense_len) {
+-		/*
+-		 * sense_ptr points to the location that has the user
+-		 * sense buffer address
+-		 */
+-		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;
+-		}
+-	}
+-
+-	/*
+-	 * copy the status codes returned by the fw
+-	 */
+-	if (copy_to_user(&user_ioc->frame.hdr.cmd_status,
+-			 &cmd->frame->hdr.cmd_status, sizeof(u8))) {
+-		printk(KERN_DEBUG "megasas: Error copying out cmd_status\n");
+-		error = -EFAULT;
+-	}
+-
+-      out:
+-	if (sense) {
+-		dma_free_coherent(&instance->pdev->dev, ioc->sense_len,
+-				    sense, sense_handle);
+-	}
+-
+-	for (i = 0; i < ioc->sge_count && kbuff_arr[i]; i++) {
+-		dma_free_coherent(&instance->pdev->dev,
+-				    kern_sge32[i].length,
+-				    kbuff_arr[i], kern_sge32[i].phys_addr);
+-	}
+-
+-	megasas_return_cmd(instance, cmd);
+-	return error;
+-}
+-
+-static struct megasas_instance *megasas_lookup_instance(u16 host_no)
+-{
+-	int i;
+-
+-	for (i = 0; i < megasas_mgmt_info.max_index; i++) {
+-
+-		if ((megasas_mgmt_info.instance[i]) &&
+-		    (megasas_mgmt_info.instance[i]->host->host_no == host_no))
+-			return megasas_mgmt_info.instance[i];
+-	}
+-
+-	return NULL;
+-}
+-
+-static int megasas_mgmt_ioctl_fw(struct file *file, unsigned long arg)
+-{
+-	struct megasas_iocpacket __user *user_ioc =
+-	    (struct megasas_iocpacket __user *)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)
+-		return -ENOMEM;
+-
+-	if (copy_from_user(ioc, user_ioc, sizeof(*ioc))) {
+-		error = -EFAULT;
+-		goto out_kfree_ioc;
+-	}
+-
+-	instance = megasas_lookup_instance(ioc->host_no);
+-	if (!instance) {
+-		error = -ENODEV;
+-		goto out_kfree_ioc;
+-	}
+-
+-	if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR) {
+-		printk(KERN_ERR "Controller in crit error\n");
+-		error = -ENODEV;
+-		goto out_kfree_ioc;
+-	}
+-
+-	if (instance->unload == 1) {
+-		error = -ENODEV;
+-		goto out_kfree_ioc;
+-	}
+-
+-	/*
+-	 * We will allow only MEGASAS_INT_CMDS number of parallel ioctl cmds
+-	 */
+-	if (down_interruptible(&instance->ioctl_sem)) {
+-		error = -ERESTARTSYS;
+-		goto out_kfree_ioc;
+-	}
+-
+-	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(KERN_ERR "megaraid_sas: timed out while"
+-			"waiting for HBA to recover\n");
+-		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:
+-	kfree(ioc);
+-	return error;
+-}
+-
+-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 "
+-		       "called first\n");
+-		return -EINVAL;
+-	}
+-
+-	if (copy_from_user(&aen, (void __user *)arg, sizeof(aen)))
+-		return -EFAULT;
+-
+-	instance = megasas_lookup_instance(aen.host_no);
+-
+-	if (!instance)
+-		return -ENODEV;
+-
+-	if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR) {
+-		return -ENODEV;
+-	}
+-
+-	if (instance->unload == 1) {
+-		return -ENODEV;
+-	}
+-
+-	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(KERN_ERR "megaraid_sas: timed out while waiting"
+-				"for HBA to recover.\n");
+-		return -ENODEV;
+-	}
+-	spin_unlock_irqrestore(&instance->hba_lock, flags);
+-
+-	mutex_lock(&instance->aen_mutex);
+-	error = megasas_register_aen(instance, aen.seq_num,
+-				     aen.class_locale_word);
+-	mutex_unlock(&instance->aen_mutex);
+-	return error;
+-}
+-
+-/**
+- * megasas_mgmt_ioctl -	char node ioctl entry point
+- */
+-static long
+-megasas_mgmt_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+-{
+-	switch (cmd) {
+-	case MEGASAS_IOC_FIRMWARE:
+-		return megasas_mgmt_ioctl_fw(file, arg);
+-
+-	case MEGASAS_IOC_GET_AEN:
+-		return megasas_mgmt_ioctl_aen(file, arg);
+-	}
+-
+-	return -ENOTTY;
+-}
+-
+-#ifdef CONFIG_COMPAT
+-static int megasas_mgmt_compat_ioctl_fw(struct file *file, unsigned long arg)
+-{
+-	struct compat_megasas_iocpacket __user *cioc =
+-	    (struct compat_megasas_iocpacket __user *)arg;
+-	struct megasas_iocpacket __user *ioc =
+-	    compat_alloc_user_space(sizeof(struct megasas_iocpacket));
+-	int i;
+-	int error = 0;
+-	compat_uptr_t ptr;
+-
+-	if (clear_user(ioc, sizeof(*ioc)))
+-		return -EFAULT;
+-
+-	if (copy_in_user(&ioc->host_no, &cioc->host_no, sizeof(u16)) ||
+-	    copy_in_user(&ioc->sgl_off, &cioc->sgl_off, sizeof(u32)) ||
+-	    copy_in_user(&ioc->sense_off, &cioc->sense_off, sizeof(u32)) ||
+-	    copy_in_user(&ioc->sense_len, &cioc->sense_len, sizeof(u32)) ||
+-	    copy_in_user(ioc->frame.raw, cioc->frame.raw, 128) ||
+-	    copy_in_user(&ioc->sge_count, &cioc->sge_count, sizeof(u32)))
+-		return -EFAULT;
+-
+-	/*
+-	 * The sense_ptr is used in megasas_mgmt_fw_ioctl only when
+-	 * sense_len is not null, so prepare the 64bit value under
+-	 * the same condition.
+-	 */
+-	if (ioc->sense_len) {
+-		void __user **sense_ioc_ptr =
+-			(void __user **)(ioc->frame.raw + ioc->sense_off);
+-		compat_uptr_t *sense_cioc_ptr =
+-			(compat_uptr_t *)(cioc->frame.raw + cioc->sense_off);
+-		if (get_user(ptr, sense_cioc_ptr) ||
+-		    put_user(compat_ptr(ptr), sense_ioc_ptr))
+-			return -EFAULT;
+-	}
+-
+-	for (i = 0; i < MAX_IOCTL_SGE; i++) {
+-		if (get_user(ptr, &cioc->sgl[i].iov_base) ||
+-		    put_user(compat_ptr(ptr), &ioc->sgl[i].iov_base) ||
+-		    copy_in_user(&ioc->sgl[i].iov_len,
+-				 &cioc->sgl[i].iov_len, sizeof(compat_size_t)))
+-			return -EFAULT;
+-	}
+-
+-	error = megasas_mgmt_ioctl_fw(file, (unsigned long)ioc);
+-
+-	if (copy_in_user(&cioc->frame.hdr.cmd_status,
+-			 &ioc->frame.hdr.cmd_status, sizeof(u8))) {
+-		printk(KERN_DEBUG "megasas: error copy_in_user cmd_status\n");
+-		return -EFAULT;
+-	}
+-	return error;
+-}
+-
+-static long
+-megasas_mgmt_compat_ioctl(struct file *file, unsigned int cmd,
+-			  unsigned long arg)
+-{
+-	switch (cmd) {
+-	case MEGASAS_IOC_FIRMWARE32:
+-		return megasas_mgmt_compat_ioctl_fw(file, arg);
+-	case MEGASAS_IOC_GET_AEN:
+-		return megasas_mgmt_ioctl_aen(file, arg);
+-	}
+-
+-	return -ENOTTY;
+-}
+-#endif
+-
+-/*
+- * File operations structure for management interface
+- */
+-static const struct file_operations megasas_mgmt_fops = {
+-	.owner = THIS_MODULE,
+-	.open = megasas_mgmt_open,
+-	.fasync = megasas_mgmt_fasync,
+-	.unlocked_ioctl = megasas_mgmt_ioctl,
+-	.poll = megasas_mgmt_poll,
+-#ifdef CONFIG_COMPAT
+-	.compat_ioctl = megasas_mgmt_compat_ioctl,
+-#endif
+-};
+-
+-/*
+- * PCI hotplug support registration structure
+- */
+-static struct pci_driver megasas_pci_driver = {
+-
+-	.name = "megaraid_sas",
+-	.id_table = megasas_pci_table,
+-	.probe = megasas_probe_one,
+-	.remove = __devexit_p(megasas_detach_one),
+-	.suspend = megasas_suspend,
+-	.resume = megasas_resume,
+-	.shutdown = megasas_shutdown,
+-};
+-
+-/*
+- * Sysfs driver attributes
+- */
+-static ssize_t megasas_sysfs_show_version(struct device_driver *dd, char *buf)
+-{
+-	return snprintf(buf, strlen(MEGASAS_VERSION) + 2, "%s\n",
+-			MEGASAS_VERSION);
+-}
+-
+-static DRIVER_ATTR(version, S_IRUGO, megasas_sysfs_show_version, NULL);
+-
+-static ssize_t
+-megasas_sysfs_show_release_date(struct device_driver *dd, char *buf)
+-{
+-	return snprintf(buf, strlen(MEGASAS_RELDATE) + 2, "%s\n",
+-			MEGASAS_RELDATE);
+-}
+-
+-static DRIVER_ATTR(release_date, S_IRUGO, megasas_sysfs_show_release_date,
+-		   NULL);
+-
+-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);
+-}
+-
+-static DRIVER_ATTR(support_poll_for_event, S_IRUGO,
+-			megasas_sysfs_show_support_poll_for_event, NULL);
+-
+-static ssize_t
+-megasas_sysfs_show_dbg_lvl(struct device_driver *dd, char *buf)
+-{
+-	return sprintf(buf, "%u\n", megasas_dbg_lvl);
+-}
+-
+-static ssize_t
+-megasas_sysfs_set_dbg_lvl(struct device_driver *dd, const char *buf, size_t count)
+-{
+-	int retval = count;
+-	if(sscanf(buf,"%u",&megasas_dbg_lvl)<1){
+-		printk(KERN_ERR "megasas: could not set dbg_lvl\n");
+-		retval = -EINVAL;
+-	}
+-	return retval;
+-}
+-
+-static DRIVER_ATTR(dbg_lvl, S_IRUGO|S_IWUSR, megasas_sysfs_show_dbg_lvl,
+-		megasas_sysfs_set_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);
+-}
+-
+-static ssize_t
+-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) {
+-		printk(KERN_ERR "megasas: could not set poll_mode_io\n");
+-		retval = -EINVAL;
+-	}
+-
+-	/*
+-	 * Check if poll_mode_io is already set or is same as previous value
+-	 */
+-	if ((tmp && poll_mode_io) || (tmp == poll_mode_io))
+-		goto out;
+-
+-	if (poll_mode_io) {
+-		/*
+-		 * Start timers for all adapters
+-		 */
+-		for (i = 0; i < megasas_mgmt_info.max_index; i++) {
+-			instance = megasas_mgmt_info.instance[i];
+-			if (instance) {
+-				megasas_start_timer(instance,
+-					&instance->io_completion_timer,
+-					megasas_io_completion_timer,
+-					MEGASAS_COMPLETION_TIMER_INTERVAL);
+-			}
+-		}
+-	} else {
+-		/*
+-		 * Delete timers for all adapters
+-		 */
+-		for (i = 0; i < megasas_mgmt_info.max_index; i++) {
+-			instance = megasas_mgmt_info.instance[i];
+-			if (instance)
+-				del_timer_sync(&instance->io_completion_timer);
+-		}
+-	}
+-
+-out:
+-	return retval;
+-}
+-
+-static void
+-megasas_aen_polling(struct work_struct *work)
+-{
+-	struct megasas_aen_event *ev =
+-		container_of(work, struct megasas_aen_event, hotplug_work);
+-	struct megasas_instance *instance = ev->instance;
+-	union megasas_evt_class_locale class_locale;
+-	struct  Scsi_Host *host;
+-	struct  scsi_device *sdev1;
+-	u16     pd_index = 0;
+-	u16	ld_index = 0;
+-	int     i, j, doscan = 0;
+-	u32 seq_num;
+-	int error;
+-
+-	if (!instance) {
+-		printk(KERN_ERR "invalid instance!\n");
+-		kfree(ev);
+-		return;
+-	}
+-	instance->ev = NULL;
+-	host = instance->host;
+-	if (instance->evt_detail) {
+-
+-		switch (instance->evt_detail->code) {
+-		case MR_EVT_PD_INSERTED:
+-			if (megasas_get_pd_list(instance) == 0) {
+-			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;
+-
+-				sdev1 =
+-				scsi_device_lookup(host, i, j, 0);
+-
+-				if (instance->pd_list[pd_index].driveState
+-						== MR_PD_STATE_SYSTEM) {
+-						if (!sdev1) {
+-						scsi_add_device(host, i, j, 0);
+-						}
+-
+-					if (sdev1)
+-						scsi_device_put(sdev1);
+-					}
+-				}
+-			}
+-			}
+-			doscan = 0;
+-			break;
+-
+-		case MR_EVT_PD_REMOVED:
+-			if (megasas_get_pd_list(instance) == 0) {
+-			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;
+-
+-				sdev1 =
+-				scsi_device_lookup(host, i, j, 0);
+-
+-				if (instance->pd_list[pd_index].driveState
+-					== MR_PD_STATE_SYSTEM) {
+-					if (sdev1) {
+-						scsi_device_put(sdev1);
+-					}
+-				} else {
+-					if (sdev1) {
+-						scsi_remove_device(sdev1);
+-						scsi_device_put(sdev1);
+-					}
+-				}
+-				}
+-			}
+-			}
+-			doscan = 0;
+-			break;
+-
+-		case MR_EVT_LD_OFFLINE:
+-		case MR_EVT_LD_DELETED:
+-			megasas_get_ld_list(instance);
+-			for (i = 0; i < MEGASAS_MAX_LD_CHANNELS; i++) {
+-				for (j = 0;
+-				j < MEGASAS_MAX_DEV_PER_CHANNEL;
+-				j++) {
+-
+-				ld_index =
+-				(i * MEGASAS_MAX_DEV_PER_CHANNEL) + j;
+-
+-				sdev1 = scsi_device_lookup(host,
+-					i + MEGASAS_MAX_LD_CHANNELS,
+-					j,
+-					0);
+-
+-				if (instance->ld_ids[ld_index] != 0xff) {
+-					if (sdev1) {
+-						scsi_device_put(sdev1);
+-					}
+-				} else {
+-					if (sdev1) {
+-						scsi_remove_device(sdev1);
+-						scsi_device_put(sdev1);
+-					}
+-				}
+-				}
+-			}
+-			doscan = 0;
+-			break;
+-		case MR_EVT_LD_CREATED:
+-			megasas_get_ld_list(instance);
+-			for (i = 0; i < MEGASAS_MAX_LD_CHANNELS; i++) {
+-				for (j = 0;
+-					j < MEGASAS_MAX_DEV_PER_CHANNEL;
+-					j++) {
+-					ld_index =
+-					(i * MEGASAS_MAX_DEV_PER_CHANNEL) + j;
+-
+-					sdev1 = scsi_device_lookup(host,
+-						i+MEGASAS_MAX_LD_CHANNELS,
+-						j, 0);
+-
+-					if (instance->ld_ids[ld_index] !=
+-								0xff) {
+-						if (!sdev1) {
+-							scsi_add_device(host,
+-								i + 2,
+-								j, 0);
+-						}
+-					}
+-					if (sdev1) {
+-						scsi_device_put(sdev1);
+-					}
+-				}
+-			}
+-			doscan = 0;
+-			break;
+-		case MR_EVT_CTRL_HOST_BUS_SCAN_REQUESTED:
+-		case MR_EVT_FOREIGN_CFG_IMPORTED:
+-			doscan = 1;
+-			break;
+-		default:
+-			doscan = 0;
+-			break;
+-		}
+-	} else {
+-		printk(KERN_ERR "invalid evt_detail!\n");
+-		kfree(ev);
+-		return;
+-	}
+-
+-	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;
+-				sdev1 = scsi_device_lookup(host, i, j, 0);
+-				if (instance->pd_list[pd_index].driveState ==
+-							MR_PD_STATE_SYSTEM) {
+-					if (!sdev1) {
+-						scsi_add_device(host, i, j, 0);
+-					}
+-					if (sdev1)
+-						scsi_device_put(sdev1);
+-				} else {
+-					if (sdev1) {
+-						scsi_remove_device(sdev1);
+-						scsi_device_put(sdev1);
+-					}
+-				}
+-			}
+-		}
+-
+-		megasas_get_ld_list(instance);
+-		for (i = 0; i < MEGASAS_MAX_LD_CHANNELS; i++) {
+-			for (j = 0; j < MEGASAS_MAX_DEV_PER_CHANNEL; j++) {
+-				ld_index =
+-				(i * MEGASAS_MAX_DEV_PER_CHANNEL) + j;
+-
+-				sdev1 = scsi_device_lookup(host,
+-					i+MEGASAS_MAX_LD_CHANNELS, j, 0);
+-				if (instance->ld_ids[ld_index] != 0xff) {
+-					if (!sdev1) {
+-						scsi_add_device(host,
+-								i+2,
+-								j, 0);
+-					} else {
+-						scsi_device_put(sdev1);
+-					}
+-				} else {
+-					if (sdev1) {
+-						scsi_remove_device(sdev1);
+-						scsi_device_put(sdev1);
+-					}
+-				}
+-			}
+-		}
+-	}
+-
+-	if ( instance->aen_cmd != NULL ) {
+-		kfree(ev);
+-		return ;
+-	}
+-
+-	seq_num = instance->evt_detail->seq_num + 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;
+-	mutex_lock(&instance->aen_mutex);
+-	error = megasas_register_aen(instance, seq_num,
+-					class_locale.word);
+-	mutex_unlock(&instance->aen_mutex);
+-
+-	if (error)
+-		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
+- */
+-static int __init megasas_init(void)
+-{
+-	int rval;
+-
+-	/*
+-	 * Announce driver version and other information
+-	 */
+-	printk(KERN_INFO "megasas: %s %s\n", MEGASAS_VERSION,
+-	       MEGASAS_EXT_VERSION);
+-
+-	support_poll_for_event = 2;
+-
+-	memset(&megasas_mgmt_info, 0, sizeof(megasas_mgmt_info));
+-
+-	/*
+-	 * Register character device node
+-	 */
+-	rval = register_chrdev(0, "megaraid_sas_ioctl", &megasas_mgmt_fops);
+-
+-	if (rval < 0) {
+-		printk(KERN_DEBUG "megasas: failed to open device node\n");
+-		return rval;
+-	}
+-
+-	megasas_mgmt_majorno = rval;
+-
+-	/*
+-	 * Register ourselves as PCI hotplug module
+-	 */
+-	rval = pci_register_driver(&megasas_pci_driver);
+-
+-	if (rval) {
+-		printk(KERN_DEBUG "megasas: PCI hotplug regisration failed \n");
+-		goto err_pcidrv;
+-	}
+-
+-	rval = driver_create_file(&megasas_pci_driver.driver,
+-				  &driver_attr_version);
+-	if (rval)
+-		goto err_dcf_attr_ver;
+-	rval = driver_create_file(&megasas_pci_driver.driver,
+-				  &driver_attr_release_date);
+-	if (rval)
+-		goto err_dcf_rel_date;
+-
+-	rval = driver_create_file(&megasas_pci_driver.driver,
+-				&driver_attr_support_poll_for_event);
+-	if (rval)
+-		goto err_dcf_support_poll_for_event;
+-
+-	rval = driver_create_file(&megasas_pci_driver.driver,
+-				  &driver_attr_dbg_lvl);
+-	if (rval)
+-		goto err_dcf_dbg_lvl;
+-	rval = driver_create_file(&megasas_pci_driver.driver,
+-				  &driver_attr_poll_mode_io);
+-	if (rval)
+-		goto err_dcf_poll_mode_io;
+-
+-	return rval;
+-
+-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);
+-
+-err_dcf_rel_date:
+-	driver_remove_file(&megasas_pci_driver.driver, &driver_attr_version);
+-err_dcf_attr_ver:
+-	pci_unregister_driver(&megasas_pci_driver);
+-err_pcidrv:
+-	unregister_chrdev(megasas_mgmt_majorno, "megaraid_sas_ioctl");
+-  	return rval;
+-}
+-
+-/**
+- * megasas_exit - Driver unload entry point
+- */
+-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_dbg_lvl);
+-	driver_remove_file(&megasas_pci_driver.driver,
+-			   &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");
+-}
+-
+-module_init(megasas_init);
+-module_exit(megasas_exit);
+diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c
+new file mode 100644
+index 000000000000..a18ae3cba87e
+--- /dev/null
++++ b/drivers/scsi/megaraid/megaraid_sas_base.c
+@@ -0,0 +1,5005 @@
++/*
++ *
++ *		Linux MegaRAID driver for SAS based RAID controllers
++ *
++ * Copyright (c) 2003-2005  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.
++ *
++ * FILE		: megaraid_sas.c
++ * Version     : v00.00.04.01-rc1
++ *
++ * Authors:
++ *	(email-id : megaraidlinux at lsi.com)
++ * 	Sreenivas Bagalkote
++ * 	Sumant Patro
++ *	Bo Yang
++ *
++ * List of supported controllers
++ *
++ * OEM	Product Name			VID	DID	SSVID	SSID
++ * ---	------------			---	---	----	----
++ */
++
++#include <linux/kernel.h>
++#include <linux/types.h>
++#include <linux/pci.h>
++#include <linux/list.h>
++#include <linux/moduleparam.h>
++#include <linux/module.h>
++#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>
++#include <linux/compat.h>
++#include <linux/blkdev.h>
++#include <linux/mutex.h>
++#include <linux/poll.h>
++
++#include <scsi/scsi.h>
++#include <scsi/scsi_cmnd.h>
++#include <scsi/scsi_device.h>
++#include <scsi/scsi_host.h>
++#include "megaraid_sas.h"
++
++/*
++ * poll_mode_io:1- schedule complete completion from q cmd
++ */
++static unsigned int poll_mode_io;
++module_param_named(poll_mode_io, poll_mode_io, int, 0);
++MODULE_PARM_DESC(poll_mode_io,
++	"Complete cmds from IO path, (default=0)");
++
++MODULE_LICENSE("GPL");
++MODULE_VERSION(MEGASAS_VERSION);
++MODULE_AUTHOR("megaraidlinux at lsi.com");
++MODULE_DESCRIPTION("LSI MegaRAID SAS Driver");
++
++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);
++/*
++ * PCI ID table for all supported controllers
++ */
++static struct pci_device_id megasas_pci_table[] = {
++
++	{PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1064R)},
++	/* 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)},
++	/* gen2*/
++	{PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS0073SKINNY)},
++	/* 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_VERDE_ZCR)},
++	/* xscale IOP, vega */
++	{PCI_DEVICE(PCI_VENDOR_ID_DELL, PCI_DEVICE_ID_DELL_PERC5)},
++	/* xscale IOP */
++	{}
++};
++
++MODULE_DEVICE_TABLE(pci, megasas_pci_table);
++
++static int megasas_mgmt_majorno;
++static struct megasas_mgmt_info megasas_mgmt_info;
++static struct fasync_struct *megasas_async_queue;
++static DEFINE_MUTEX(megasas_async_queue_mutex);
++
++static int megasas_poll_wait_aen;
++static DECLARE_WAIT_QUEUE_HEAD(megasas_poll_wait);
++static u32 support_poll_for_event;
++static u32 megasas_dbg_lvl;
++
++/* define lock for aen poll */
++spinlock_t poll_aen_lock;
++
++static void
++megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd,
++		     u8 alt_status);
++
++/**
++ * megasas_get_cmd -	Get a command from the free pool
++ * @instance:		Adapter soft state
++ *
++ * Returns a free command from the pool
++ */
++static struct megasas_cmd *megasas_get_cmd(struct megasas_instance
++						  *instance)
++{
++	unsigned long flags;
++	struct megasas_cmd *cmd = NULL;
++
++	spin_lock_irqsave(&instance->cmd_pool_lock, flags);
++
++	if (!list_empty(&instance->cmd_pool)) {
++		cmd = list_entry((&instance->cmd_pool)->next,
++				 struct megasas_cmd, list);
++		list_del_init(&cmd->list);
++	} else {
++		printk(KERN_ERR "megasas: Command pool empty!\n");
++	}
++
++	spin_unlock_irqrestore(&instance->cmd_pool_lock, flags);
++	return cmd;
++}
++
++/**
++ * megasas_return_cmd -	Return a cmd to free command pool
++ * @instance:		Adapter soft state
++ * @cmd:		Command packet to be returned to free command pool
++ */
++static inline void
++megasas_return_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd)
++{
++	unsigned long flags;
++
++	spin_lock_irqsave(&instance->cmd_pool_lock, flags);
++
++	cmd->scmd = NULL;
++	list_add_tail(&cmd->list, &instance->cmd_pool);
++
++	spin_unlock_irqrestore(&instance->cmd_pool_lock, flags);
++}
++
++
++/**
++*	The following functions are defined for xscale
++*	(deviceid : 1064R, PERC5) controllers
++*/
++
++/**
++ * megasas_enable_intr_xscale -	Enables interrupts
++ * @regs:			MFI register set
++ */
++static inline void
++megasas_enable_intr_xscale(struct megasas_register_set __iomem * regs)
++{
++	writel(0, &(regs)->outbound_intr_mask);
++
++	/* Dummy readl to force pci flush */
++	readl(&regs->outbound_intr_mask);
++}
++
++/**
++ * megasas_disable_intr_xscale -Disables interrupt
++ * @regs:			MFI register set
++ */
++static inline void
++megasas_disable_intr_xscale(struct megasas_register_set __iomem * regs)
++{
++	u32 mask = 0x1f;
++	writel(mask, &regs->outbound_intr_mask);
++	/* Dummy readl to force pci flush */
++	readl(&regs->outbound_intr_mask);
++}
++
++/**
++ * megasas_read_fw_status_reg_xscale - returns the current FW status value
++ * @regs:			MFI register set
++ */
++static u32
++megasas_read_fw_status_reg_xscale(struct megasas_register_set __iomem * regs)
++{
++	return readl(&(regs)->outbound_msg_0);
++}
++/**
++ * megasas_clear_interrupt_xscale -	Check & clear interrupt
++ * @regs:				MFI register set
++ */
++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)
++		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
++	 */
++	if (mfiStatus)
++		writel(status, &regs->outbound_intr_status);
++
++	/* Dummy readl to force pci flush */
++	readl(&regs->outbound_intr_status);
++
++	return mfiStatus;
++}
++
++/**
++ * megasas_fire_cmd_xscale -	Sends command to the FW
++ * @frame_phys_addr :		Physical address of cmd
++ * @frame_count :		Number of frames for the command
++ * @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)
++{
++	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(KERN_NOTICE "pcidata = %x\n", pcidata);
++	if (pcidata & 0x2) {
++		printk(KERN_NOTICE "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(KERN_NOTICE "1068 offset handshake read=%x\n", pcidata);
++		if ((pcidata & 0xffff0000) == MFI_1068_FW_READY) {
++			printk(KERN_NOTICE "1068 offset pcidt=%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 = {
++
++	.fire_cmd = megasas_fire_cmd_xscale,
++	.enable_intr = megasas_enable_intr_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,
++};
++
++/**
++*	This is the end of set of functions & definitions specific
++*	to xscale (deviceid : 1064R, PERC5) controllers
++*/
++
++/**
++*	The following functions are defined for ppc (deviceid : 0x60)
++* 	controllers
++*/
++
++/**
++ * megasas_enable_intr_ppc -	Enables interrupts
++ * @regs:			MFI register set
++ */
++static inline void
++megasas_enable_intr_ppc(struct megasas_register_set __iomem * regs)
++{
++	writel(0xFFFFFFFF, &(regs)->outbound_doorbell_clear);
++
++	writel(~0x80000000, &(regs)->outbound_intr_mask);
++
++	/* Dummy readl to force pci flush */
++	readl(&regs->outbound_intr_mask);
++}
++
++/**
++ * megasas_disable_intr_ppc -	Disable interrupt
++ * @regs:			MFI register set
++ */
++static inline void
++megasas_disable_intr_ppc(struct megasas_register_set __iomem * regs)
++{
++	u32 mask = 0xFFFFFFFF;
++	writel(mask, &regs->outbound_intr_mask);
++	/* Dummy readl to force pci flush */
++	readl(&regs->outbound_intr_mask);
++}
++
++/**
++ * megasas_read_fw_status_reg_ppc - returns the current FW status value
++ * @regs:			MFI register set
++ */
++static u32
++megasas_read_fw_status_reg_ppc(struct megasas_register_set __iomem * regs)
++{
++	return readl(&(regs)->outbound_scratch_pad);
++}
++
++/**
++ * megasas_clear_interrupt_ppc -	Check & clear interrupt
++ * @regs:				MFI register set
++ */
++static int
++megasas_clear_intr_ppc(struct megasas_register_set __iomem * regs)
++{
++	u32 status;
++	/*
++	 * Check if it is our interrupt
++	 */
++	status = readl(&regs->outbound_intr_status);
++
++	if (!(status & MFI_REPLY_1078_MESSAGE_INTERRUPT)) {
++		return 0;
++	}
++
++	/*
++	 * Clear the interrupt by writing back the same value
++	 */
++	writel(status, &regs->outbound_doorbell_clear);
++
++	/* Dummy readl to force pci flush */
++	readl(&regs->outbound_doorbell_clear);
++
++	return 1;
++}
++/**
++ * megasas_fire_cmd_ppc -	Sends command to the FW
++ * @frame_phys_addr :		Physical address of cmd
++ * @frame_count :		Number of frames for the command
++ * @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)
++{
++	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 = {
++
++	.fire_cmd = megasas_fire_cmd_ppc,
++	.enable_intr = megasas_enable_intr_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,
++};
++
++/**
++ * megasas_enable_intr_skinny -	Enables interrupts
++ * @regs:			MFI register set
++ */
++static inline void
++megasas_enable_intr_skinny(struct megasas_register_set __iomem *regs)
++{
++	writel(0xFFFFFFFF, &(regs)->outbound_intr_mask);
++
++	writel(~MFI_SKINNY_ENABLE_INTERRUPT_MASK, &(regs)->outbound_intr_mask);
++
++	/* Dummy readl to force pci flush */
++	readl(&regs->outbound_intr_mask);
++}
++
++/**
++ * megasas_disable_intr_skinny -	Disables interrupt
++ * @regs:			MFI register set
++ */
++static inline void
++megasas_disable_intr_skinny(struct megasas_register_set __iomem *regs)
++{
++	u32 mask = 0xFFFFFFFF;
++	writel(mask, &regs->outbound_intr_mask);
++	/* Dummy readl to force pci flush */
++	readl(&regs->outbound_intr_mask);
++}
++
++/**
++ * megasas_read_fw_status_reg_skinny - returns the current FW status value
++ * @regs:			MFI register set
++ */
++static u32
++megasas_read_fw_status_reg_skinny(struct megasas_register_set __iomem *regs)
++{
++	return readl(&(regs)->outbound_scratch_pad);
++}
++
++/**
++ * megasas_clear_interrupt_skinny -	Check & clear interrupt
++ * @regs:				MFI register set
++ */
++static int
++megasas_clear_intr_skinny(struct megasas_register_set __iomem *regs)
++{
++	u32 status;
++	/*
++	 * Check if it is our interrupt
++	 */
++	status = readl(&regs->outbound_intr_status);
++
++	if (!(status & MFI_SKINNY_ENABLE_INTERRUPT_MASK)) {
++		return 0;
++	}
++
++	/*
++	 * Clear the interrupt by writing back the same value
++	 */
++	writel(status, &regs->outbound_intr_status);
++
++	/*
++	* dummy read to flush PCI
++	*/
++	readl(&regs->outbound_intr_status);
++
++	return 1;
++}
++
++/**
++ * megasas_fire_cmd_skinny -	Sends command to the FW
++ * @frame_phys_addr :		Physical address of cmd
++ * @frame_count :		Number of frames for the command
++ * @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)
++{
++	unsigned long 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->hba_lock, flags);
++}
++
++/**
++ * 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,
++	.enable_intr = megasas_enable_intr_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,
++};
++
++
++/**
++*	The following functions are defined for gen2 (deviceid : 0x78 0x79)
++*	controllers
++*/
++
++/**
++ * megasas_enable_intr_gen2 -  Enables interrupts
++ * @regs:                      MFI register set
++ */
++static inline void
++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);
++
++	/* Dummy readl to force pci flush */
++	readl(&regs->outbound_intr_mask);
++}
++
++/**
++ * megasas_disable_intr_gen2 - Disables interrupt
++ * @regs:                      MFI register set
++ */
++static inline void
++megasas_disable_intr_gen2(struct megasas_register_set __iomem *regs)
++{
++	u32 mask = 0xFFFFFFFF;
++	writel(mask, &regs->outbound_intr_mask);
++	/* Dummy readl to force pci flush */
++	readl(&regs->outbound_intr_mask);
++}
++
++/**
++ * megasas_read_fw_status_reg_gen2 - returns the current FW status value
++ * @regs:                      MFI register set
++ */
++static u32
++megasas_read_fw_status_reg_gen2(struct megasas_register_set __iomem *regs)
++{
++	return readl(&(regs)->outbound_scratch_pad);
++}
++
++/**
++ * megasas_clear_interrupt_gen2 -      Check & clear interrupt
++ * @regs:                              MFI register set
++ */
++static int
++megasas_clear_intr_gen2(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_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
++	 */
++	if (mfiStatus)
++		writel(status, &regs->outbound_doorbell_clear);
++
++	/* Dummy readl to force pci flush */
++	readl(&regs->outbound_intr_status);
++
++	return mfiStatus;
++}
++/**
++ * megasas_fire_cmd_gen2 -     Sends command to the FW
++ * @frame_phys_addr :          Physical address of cmd
++ * @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)
++{
++	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_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 ;
++	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(KERN_NOTICE "RESETGEN2: retry=%x, hostdiag=%x\n",
++					retry, HostDiag);
++
++		if (retry++ >= 100)
++			return 1;
++
++	}
++
++	printk(KERN_NOTICE "ADP_RESET_GEN2: HostDiag=%x\n", HostDiag);
++
++	writel((HostDiag | DIAG_RESET_ADAPTER), &reg_set->host_diag);
++
++	ssleep(10);
++
++	HostDiag = (u32)readl(&reg_set->host_diag);
++	while ( ( HostDiag & DIAG_RESET_ADAPTER) ) {
++		msleep(100);
++		HostDiag = (u32)readl(&reg_set->host_diag);
++		printk(KERN_NOTICE "RESET_GEN2: retry=%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
++*       specific to gen2 (deviceid : 0x78, 0x79) controllers
++*/
++
++/**
++ * megasas_issue_polled -	Issues a polling command
++ * @instance:			Adapter soft state
++ * @cmd:			Command packet to be issued
++ *
++ * For polling, MFI requires the cmd_status to be set to 0xFF before posting.
++ */
++static int
++megasas_issue_polled(struct megasas_instance *instance, struct megasas_cmd *cmd)
++{
++	int i;
++	u32 msecs = MFI_POLL_TIMEOUT_SECS * 1000;
++
++	struct megasas_header *frame_hdr = &cmd->frame->hdr;
++
++	frame_hdr->cmd_status = 0xFF;
++	frame_hdr->flags |= MFI_FRAME_DONT_POST_IN_REPLY_QUEUE;
++
++	/*
++	 * Issue the frame using inbound queue port
++	 */
++	instance->instancet->fire_cmd(instance,
++			cmd->frame_phys_addr, 0, instance->reg_set);
++
++	/*
++	 * Wait for cmd_status to change
++	 */
++	for (i = 0; (i < msecs) && (frame_hdr->cmd_status == 0xff); i++) {
++		rmb();
++		msleep(1);
++	}
++
++	if (frame_hdr->cmd_status == 0xff)
++		return -ETIME;
++
++	return 0;
++}
++
++/**
++ * megasas_issue_blocked_cmd -	Synchronous wrapper around regular FW cmds
++ * @instance:			Adapter soft state
++ * @cmd:			Command to be issued
++ *
++ * This function waits on an event for the command to be returned from ISR.
++ * Max wait time is MEGASAS_INTERNAL_CMD_WAIT_TIME secs
++ * Used to issue ioctl commands.
++ */
++static int
++megasas_issue_blocked_cmd(struct megasas_instance *instance,
++			  struct megasas_cmd *cmd)
++{
++	cmd->cmd_status = ENODATA;
++
++	instance->instancet->fire_cmd(instance,
++			cmd->frame_phys_addr, 0, instance->reg_set);
++
++	wait_event(instance->int_cmd_wait_q, cmd->cmd_status != ENODATA);
++
++	return 0;
++}
++
++/**
++ * megasas_issue_blocked_abort_cmd -	Aborts previously issued cmd
++ * @instance:				Adapter soft state
++ * @cmd_to_abort:			Previously issued cmd to be aborted
++ *
++ * MFI firmware can abort previously issued AEN comamnd (automatic event
++ * notification). The megasas_issue_blocked_abort_cmd() issues such abort
++ * cmd and waits for return status.
++ * Max wait time is MEGASAS_INTERNAL_CMD_WAIT_TIME secs
++ */
++static int
++megasas_issue_blocked_abort_cmd(struct megasas_instance *instance,
++				struct megasas_cmd *cmd_to_abort)
++{
++	struct megasas_cmd *cmd;
++	struct megasas_abort_frame *abort_fr;
++
++	cmd = megasas_get_cmd(instance);
++
++	if (!cmd)
++		return -1;
++
++	abort_fr = &cmd->frame->abort;
++
++	/*
++	 * Prepare and issue the abort frame
++	 */
++	abort_fr->cmd = MFI_CMD_ABORT;
++	abort_fr->cmd_status = 0xFF;
++	abort_fr->flags = 0;
++	abort_fr->abort_context = cmd_to_abort->index;
++	abort_fr->abort_mfi_phys_addr_lo = cmd_to_abort->frame_phys_addr;
++	abort_fr->abort_mfi_phys_addr_hi = 0;
++
++	cmd->sync_cmd = 1;
++	cmd->cmd_status = 0xFF;
++
++	instance->instancet->fire_cmd(instance,
++			cmd->frame_phys_addr, 0, instance->reg_set);
++
++	/*
++	 * Wait for this cmd to complete
++	 */
++	wait_event(instance->abort_cmd_wait_q, cmd->cmd_status != 0xFF);
++	cmd->sync_cmd = 0;
++
++	megasas_return_cmd(instance, cmd);
++	return 0;
++}
++
++/**
++ * megasas_make_sgl32 -	Prepares 32-bit SGL
++ * @instance:		Adapter soft state
++ * @scp:		SCSI command from the mid-layer
++ * @mfi_sgl:		SGL to be filled in
++ *
++ * If successful, this function returns the number of SG elements. Otherwise,
++ * it returnes -1.
++ */
++static int
++megasas_make_sgl32(struct megasas_instance *instance, struct scsi_cmnd *scp,
++		   union megasas_sgl *mfi_sgl)
++{
++	int i;
++	int sge_count;
++	struct scatterlist *os_sgl;
++
++	sge_count = scsi_dma_map(scp);
++	BUG_ON(sge_count < 0);
++
++	if (sge_count) {
++		scsi_for_each_sg(scp, os_sgl, sge_count, i) {
++			mfi_sgl->sge32[i].length = sg_dma_len(os_sgl);
++			mfi_sgl->sge32[i].phys_addr = sg_dma_address(os_sgl);
++		}
++	}
++	return sge_count;
++}
++
++/**
++ * megasas_make_sgl64 -	Prepares 64-bit SGL
++ * @instance:		Adapter soft state
++ * @scp:		SCSI command from the mid-layer
++ * @mfi_sgl:		SGL to be filled in
++ *
++ * If successful, this function returns the number of SG elements. Otherwise,
++ * it returnes -1.
++ */
++static int
++megasas_make_sgl64(struct megasas_instance *instance, struct scsi_cmnd *scp,
++		   union megasas_sgl *mfi_sgl)
++{
++	int i;
++	int sge_count;
++	struct scatterlist *os_sgl;
++
++	sge_count = scsi_dma_map(scp);
++	BUG_ON(sge_count < 0);
++
++	if (sge_count) {
++		scsi_for_each_sg(scp, os_sgl, sge_count, i) {
++			mfi_sgl->sge64[i].length = sg_dma_len(os_sgl);
++			mfi_sgl->sge64[i].phys_addr = sg_dma_address(os_sgl);
++		}
++	}
++	return sge_count;
++}
++
++/**
++ * 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
++ *
++ * If successful, this function returns the number of SG elements. Otherwise,
++ * it returnes -1.
++ */
++static int
++megasas_make_sgl_skinny(struct megasas_instance *instance,
++		struct scsi_cmnd *scp, union megasas_sgl *mfi_sgl)
++{
++	int i;
++	int sge_count;
++	struct scatterlist *os_sgl;
++
++	sge_count = scsi_dma_map(scp);
++
++	if (sge_count) {
++		scsi_for_each_sg(scp, os_sgl, sge_count, i) {
++			mfi_sgl->sge_skinny[i].length = sg_dma_len(os_sgl);
++			mfi_sgl->sge_skinny[i].phys_addr =
++						sg_dma_address(os_sgl);
++		}
++	}
++	return sge_count;
++}
++
++ /**
++ * megasas_get_frame_count - Computes the number of frames
++ * @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)
++ */
++
++static u32 megasas_get_frame_count(struct megasas_instance *instance,
++			u8 sge_count, u8 frame_type)
++{
++	int num_cnt;
++	int sge_bytes;
++	u32 sge_sz;
++	u32 frame_count=0;
++
++	sge_sz = (IS_DMA64) ? sizeof(struct megasas_sge64) :
++	    sizeof(struct megasas_sge32);
++
++	if (instance->flag_ieee) {
++		sge_sz = sizeof(struct megasas_sge_skinny);
++	}
++
++	/*
++	 * Main frame can contain 2 SGEs for 64-bit SGLs and
++	 * 3 SGEs for 32-bit SGLs for ldio &
++	 * 1 SGEs for 64-bit SGLs and
++	 * 2 SGEs for 32-bit SGLs for pthru frame
++	 */
++	if (unlikely(frame_type == PTHRU_FRAME)) {
++		if (instance->flag_ieee == 1) {
++			num_cnt = sge_count - 1;
++		} else if (IS_DMA64)
++			num_cnt = sge_count - 1;
++		else
++			num_cnt = sge_count - 2;
++	} else {
++		if (instance->flag_ieee == 1) {
++			num_cnt = sge_count - 1;
++		} else if (IS_DMA64)
++			num_cnt = sge_count - 2;
++		else
++			num_cnt = sge_count - 3;
++	}
++
++	if(num_cnt>0){
++		sge_bytes = sge_sz * num_cnt;
++
++		frame_count = (sge_bytes / MEGAMFI_FRAME_SIZE) +
++		    ((sge_bytes % MEGAMFI_FRAME_SIZE) ? 1 : 0) ;
++	}
++	/* Main frame */
++	frame_count +=1;
++
++	if (frame_count > 7)
++		frame_count = 8;
++	return frame_count;
++}
++
++/**
++ * megasas_build_dcdb -	Prepares a direct cdb (DCDB) command
++ * @instance:		Adapter soft state
++ * @scp:		SCSI command
++ * @cmd:		Command to be prepared in
++ *
++ * This function prepares CDB commands. These are typcially pass-through
++ * commands to the devices.
++ */
++static int
++megasas_build_dcdb(struct megasas_instance *instance, struct scsi_cmnd *scp,
++		   struct megasas_cmd *cmd)
++{
++	u32 is_logical;
++	u32 device_id;
++	u16 flags = 0;
++	struct megasas_pthru_frame *pthru;
++
++	is_logical = MEGASAS_IS_LOGICAL(scp);
++	device_id = MEGASAS_DEV_INDEX(instance, scp);
++	pthru = (struct megasas_pthru_frame *)cmd->frame;
++
++	if (scp->sc_data_direction == PCI_DMA_TODEVICE)
++		flags = MFI_FRAME_DIR_WRITE;
++	else if (scp->sc_data_direction == PCI_DMA_FROMDEVICE)
++		flags = MFI_FRAME_DIR_READ;
++	else if (scp->sc_data_direction == PCI_DMA_NONE)
++		flags = MFI_FRAME_DIR_NONE;
++
++	if (instance->flag_ieee == 1) {
++		flags |= MFI_FRAME_IEEE;
++	}
++
++	/*
++	 * Prepare the DCDB frame
++	 */
++	pthru->cmd = (is_logical) ? MFI_CMD_LD_SCSI_IO : MFI_CMD_PD_SCSI_IO;
++	pthru->cmd_status = 0x0;
++	pthru->scsi_status = 0x0;
++	pthru->target_id = device_id;
++	pthru->lun = scp->device->lun;
++	pthru->cdb_len = scp->cmd_len;
++	pthru->timeout = 0;
++	pthru->flags = flags;
++	pthru->data_xfer_len = scsi_bufflen(scp);
++
++	memcpy(pthru->cdb, scp->cmnd, scp->cmd_len);
++
++	/*
++	 * Construct SGL
++	 */
++	if (instance->flag_ieee == 1) {
++		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,
++						      &pthru->sgl);
++	} else
++		pthru->sge_count = megasas_make_sgl32(instance, scp,
++						      &pthru->sgl);
++
++	if (pthru->sge_count > instance->max_num_sge) {
++		printk(KERN_ERR "megasas: DCDB two many SGE NUM=%x\n",
++			pthru->sge_count);
++		return 0;
++	}
++
++	/*
++	 * Sense info specific
++	 */
++	pthru->sense_len = SCSI_SENSE_BUFFERSIZE;
++	pthru->sense_buf_phys_addr_hi = 0;
++	pthru->sense_buf_phys_addr_lo = cmd->sense_phys_addr;
++
++	/*
++	 * 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, pthru->sge_count,
++							PTHRU_FRAME);
++
++	return cmd->frame_count;
++}
++
++/**
++ * megasas_build_ldio -	Prepares IOs to logical devices
++ * @instance:		Adapter soft state
++ * @scp:		SCSI command
++ * @cmd:		Command to be prepared
++ *
++ * Frames (and accompanying SGLs) for regular SCSI IOs use this function.
++ */
++static int
++megasas_build_ldio(struct megasas_instance *instance, struct scsi_cmnd *scp,
++		   struct megasas_cmd *cmd)
++{
++	u32 device_id;
++	u8 sc = scp->cmnd[0];
++	u16 flags = 0;
++	struct megasas_io_frame *ldio;
++
++	device_id = MEGASAS_DEV_INDEX(instance, scp);
++	ldio = (struct megasas_io_frame *)cmd->frame;
++
++	if (scp->sc_data_direction == PCI_DMA_TODEVICE)
++		flags = MFI_FRAME_DIR_WRITE;
++	else if (scp->sc_data_direction == PCI_DMA_FROMDEVICE)
++		flags = MFI_FRAME_DIR_READ;
++
++	if (instance->flag_ieee == 1) {
++		flags |= MFI_FRAME_IEEE;
++	}
++
++	/*
++	 * Prepare the Logical IO frame: 2nd bit is zero for all read cmds
++	 */
++	ldio->cmd = (sc & 0x02) ? MFI_CMD_LD_WRITE : MFI_CMD_LD_READ;
++	ldio->cmd_status = 0x0;
++	ldio->scsi_status = 0x0;
++	ldio->target_id = device_id;
++	ldio->timeout = 0;
++	ldio->reserved_0 = 0;
++	ldio->pad_0 = 0;
++	ldio->flags = flags;
++	ldio->start_lba_hi = 0;
++	ldio->access_byte = (scp->cmd_len != 6) ? scp->cmnd[1] : 0;
++
++	/*
++	 * 6-byte READ(0x08) or WRITE(0x0A) cdb
++	 */
++	if (scp->cmd_len == 6) {
++		ldio->lba_count = (u32) scp->cmnd[4];
++		ldio->start_lba_lo = ((u32) scp->cmnd[1] << 16) |
++		    ((u32) scp->cmnd[2] << 8) | (u32) scp->cmnd[3];
++
++		ldio->start_lba_lo &= 0x1FFFFF;
++	}
++
++	/*
++	 * 10-byte READ(0x28) or WRITE(0x2A) cdb
++	 */
++	else if (scp->cmd_len == 10) {
++		ldio->lba_count = (u32) scp->cmnd[8] |
++		    ((u32) scp->cmnd[7] << 8);
++		ldio->start_lba_lo = ((u32) scp->cmnd[2] << 24) |
++		    ((u32) scp->cmnd[3] << 16) |
++		    ((u32) scp->cmnd[4] << 8) | (u32) scp->cmnd[5];
++	}
++
++	/*
++	 * 12-byte READ(0xA8) or WRITE(0xAA) cdb
++	 */
++	else if (scp->cmd_len == 12) {
++		ldio->lba_count = ((u32) scp->cmnd[6] << 24) |
++		    ((u32) scp->cmnd[7] << 16) |
++		    ((u32) scp->cmnd[8] << 8) | (u32) scp->cmnd[9];
++
++		ldio->start_lba_lo = ((u32) scp->cmnd[2] << 24) |
++		    ((u32) scp->cmnd[3] << 16) |
++		    ((u32) scp->cmnd[4] << 8) | (u32) scp->cmnd[5];
++	}
++
++	/*
++	 * 16-byte READ(0x88) or WRITE(0x8A) cdb
++	 */
++	else if (scp->cmd_len == 16) {
++		ldio->lba_count = ((u32) scp->cmnd[10] << 24) |
++		    ((u32) scp->cmnd[11] << 16) |
++		    ((u32) scp->cmnd[12] << 8) | (u32) scp->cmnd[13];
++
++		ldio->start_lba_lo = ((u32) scp->cmnd[6] << 24) |
++		    ((u32) scp->cmnd[7] << 16) |
++		    ((u32) scp->cmnd[8] << 8) | (u32) scp->cmnd[9];
++
++		ldio->start_lba_hi = ((u32) scp->cmnd[2] << 24) |
++		    ((u32) scp->cmnd[3] << 16) |
++		    ((u32) scp->cmnd[4] << 8) | (u32) scp->cmnd[5];
++
++	}
++
++	/*
++	 * Construct SGL
++	 */
++	if (instance->flag_ieee) {
++		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);
++	} else
++		ldio->sge_count = megasas_make_sgl32(instance, scp, &ldio->sgl);
++
++	if (ldio->sge_count > instance->max_num_sge) {
++		printk(KERN_ERR "megasas: build_ld_io: sge_count = %x\n",
++			ldio->sge_count);
++		return 0;
++	}
++
++	/*
++	 * Sense info specific
++	 */
++	ldio->sense_len = SCSI_SENSE_BUFFERSIZE;
++	ldio->sense_buf_phys_addr_hi = 0;
++	ldio->sense_buf_phys_addr_lo = cmd->sense_phys_addr;
++
++	/*
++	 * 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);
++
++	return cmd->frame_count;
++}
++
++/**
++ * megasas_is_ldio -		Checks if the cmd is for logical drive
++ * @scmd:			SCSI command
++ *
++ * Called by megasas_queue_command to find out if the command to be queued
++ * is a logical drive command
++ */
++static inline int megasas_is_ldio(struct scsi_cmnd *cmd)
++{
++	if (!MEGASAS_IS_LOGICAL(cmd))
++		return 0;
++	switch (cmd->cmnd[0]) {
++	case READ_10:
++	case WRITE_10:
++	case READ_12:
++	case WRITE_12:
++	case READ_6:
++	case WRITE_6:
++	case READ_16:
++	case WRITE_16:
++		return 1;
++	default:
++		return 0;
++	}
++}
++
++ /**
++ * megasas_dump_pending_frames -	Dumps the frame address of all pending cmds
++ *                              	in FW
++ * @instance:				Adapter soft state
++ */
++static inline void
++megasas_dump_pending_frames(struct megasas_instance *instance)
++{
++	struct megasas_cmd *cmd;
++	int i,n;
++	union megasas_sgl *mfi_sgl;
++	struct megasas_io_frame *ldio;
++	struct megasas_pthru_frame *pthru;
++	u32 sgcount;
++	u32 max_cmd = instance->max_fw_cmds;
++
++	printk(KERN_ERR "\nmegasas[%d]: Dumping Frame Phys Address of all pending cmds in FW\n",instance->host->host_no);
++	printk(KERN_ERR "megasas[%d]: Total OS Pending cmds : %d\n",instance->host->host_no,atomic_read(&instance->fw_outstanding));
++	if (IS_DMA64)
++		printk(KERN_ERR "\nmegasas[%d]: 64 bit SGLs were sent to FW\n",instance->host->host_no);
++	else
++		printk(KERN_ERR "\nmegasas[%d]: 32 bit SGLs were sent to FW\n",instance->host->host_no);
++
++	printk(KERN_ERR "megasas[%d]: Pending OS cmds in FW : \n",instance->host->host_no);
++	for (i = 0; i < max_cmd; i++) {
++		cmd = instance->cmd_list[i];
++		if(!cmd->scmd)
++			continue;
++		printk(KERN_ERR "megasas[%d]: Frame addr :0x%08lx : ",instance->host->host_no,(unsigned long)cmd->frame_phys_addr);
++		if (megasas_is_ldio(cmd->scmd)){
++			ldio = (struct megasas_io_frame *)cmd->frame;
++			mfi_sgl = &ldio->sgl;
++			sgcount = ldio->sge_count;
++			printk(KERN_ERR "megasas[%d]: frame count : 0x%x, Cmd : 0x%x, Tgt id : 0x%x, lba lo : 0x%x, lba_hi : 0x%x, sense_buf addr : 0x%x,sge count : 0x%x\n",instance->host->host_no, cmd->frame_count,ldio->cmd,ldio->target_id, ldio->start_lba_lo,ldio->start_lba_hi,ldio->sense_buf_phys_addr_lo,sgcount);
++		}
++		else {
++			pthru = (struct megasas_pthru_frame *) cmd->frame;
++			mfi_sgl = &pthru->sgl;
++			sgcount = pthru->sge_count;
++			printk(KERN_ERR "megasas[%d]: frame count : 0x%x, Cmd : 0x%x, Tgt id : 0x%x, lun : 0x%x, cdb_len : 0x%x, data xfer len : 0x%x, sense_buf addr : 0x%x,sge count : 0x%x\n",instance->host->host_no,cmd->frame_count,pthru->cmd,pthru->target_id,pthru->lun,pthru->cdb_len , pthru->data_xfer_len,pthru->sense_buf_phys_addr_lo,sgcount);
++		}
++	if(megasas_dbg_lvl & MEGASAS_DBG_LVL){
++		for (n = 0; n < sgcount; n++){
++			if (IS_DMA64)
++				printk(KERN_ERR "megasas: sgl len : 0x%x, sgl addr : 0x%08lx ",mfi_sgl->sge64[n].length , (unsigned long)mfi_sgl->sge64[n].phys_addr) ;
++			else
++				printk(KERN_ERR "megasas: sgl len : 0x%x, sgl addr : 0x%x ",mfi_sgl->sge32[n].length , mfi_sgl->sge32[n].phys_addr) ;
++			}
++		}
++		printk(KERN_ERR "\n");
++	} /*for max_cmd*/
++	printk(KERN_ERR "\nmegasas[%d]: Pending Internal cmds in FW : \n",instance->host->host_no);
++	for (i = 0; i < max_cmd; i++) {
++
++		cmd = instance->cmd_list[i];
++
++		if(cmd->sync_cmd == 1){
++			printk(KERN_ERR "0x%08lx : ", (unsigned long)cmd->frame_phys_addr);
++		}
++	}
++	printk(KERN_ERR "megasas[%d]: Dumping Done.\n\n",instance->host->host_no);
++}
++
++/**
++ * megasas_queue_command -	Queue entry point
++ * @scmd:			SCSI command to be queued
++ * @done:			Callback entry point
++ */
++static int
++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;
++
++	if (instance->issuepend_done == 0)
++		return SCSI_MLQUEUE_HOST_BUSY;
++
++	spin_lock_irqsave(&instance->hba_lock, flags);
++	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;
++
++	if (MEGASAS_IS_LOGICAL(scmd) &&
++	    (scmd->device->id >= MEGASAS_MAX_LD || scmd->device->lun)) {
++		scmd->result = DID_BAD_TARGET << 16;
++		goto out_done;
++	}
++
++	switch (scmd->cmnd[0]) {
++	case SYNCHRONIZE_CACHE:
++		/*
++		 * FW takes care of flush cache on its own
++		 * No need to send it down
++		 */
++		scmd->result = DID_OK << 16;
++		goto out_done;
++	default:
++		break;
++	}
++
++	cmd = megasas_get_cmd(instance);
++	if (!cmd)
++		return SCSI_MLQUEUE_HOST_BUSY;
++
++	/*
++	 * Logical drive command
++	 */
++	if (megasas_is_ldio(scmd))
++		frame_count = megasas_build_ldio(instance, scmd, cmd);
++	else
++		frame_count = megasas_build_dcdb(instance, scmd, cmd);
++
++	if (!frame_count)
++		goto out_return_cmd;
++
++	cmd->scmd = scmd;
++	scmd->SCp.ptr = (char *)cmd;
++
++	/*
++	 * Issue the command to the FW
++	 */
++	atomic_inc(&instance->fw_outstanding);
++
++	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
++	 */
++	if (poll_mode_io && atomic_read(&instance->fw_outstanding))
++		tasklet_schedule(&instance->isr_tasklet);
++
++
++	return 0;
++
++ out_return_cmd:
++	megasas_return_cmd(instance, cmd);
++ out_done:
++	done(scmd);
++	return 0;
++}
++
++static int megasas_slave_configure(struct scsi_device *sdev)
++{
++	/*
++	 * Don't export physical disk devices to the disk driver.
++	 *
++	 * FIXME: Currently we don't export them to the midlayer at all.
++	 * 	  That will be fixed once LSI engineers have audited the
++	 * 	  firmware for possible issues.
++	 */
++	if (sdev->channel < MEGASAS_MAX_PD_CHANNELS && sdev->type == TYPE_DISK)
++		return -ENXIO;
++
++	/*
++	 * The RAID firmware may require extended timeouts.
++	 */
++	if (sdev->channel >= MEGASAS_MAX_PD_CHANNELS)
++		blk_queue_rq_timeout(sdev->request_queue,
++				     MEGASAS_DEFAULT_CMD_TIMEOUT * HZ);
++	return 0;
++}
++
++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);
++	}
++}
++
++/**
++ * megasas_complete_cmd_dpc	 -	Returns FW's controller structure
++ * @instance_addr:			Address of adapter soft state
++ *
++ * Tasklet to complete cmds
++ */
++static void megasas_complete_cmd_dpc(unsigned long instance_addr)
++{
++	u32 producer;
++	u32 consumer;
++	u32 context;
++	struct megasas_cmd *cmd;
++	struct megasas_instance *instance =
++				(struct megasas_instance *)instance_addr;
++	unsigned long flags;
++
++	/* If we have already declared adapter dead, donot complete cmds */
++	if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR )
++		return;
++
++	spin_lock_irqsave(&instance->completion_lock, flags);
++
++	producer = *instance->producer;
++	consumer = *instance->consumer;
++
++	while (consumer != producer) {
++		context = instance->reply_queue[consumer];
++		if (context >= instance->max_fw_cmds) {
++			printk(KERN_ERR "Unexpected context value %x\n",
++				context);
++			BUG();
++		}
++
++		cmd = instance->cmd_list[context];
++
++		megasas_complete_cmd(instance, cmd, DID_OK);
++
++		consumer++;
++		if (consumer == (instance->max_fw_cmds + 1)) {
++			consumer = 0;
++		}
++	}
++
++	*instance->consumer = producer;
++
++	spin_unlock_irqrestore(&instance->completion_lock, flags);
++
++	/*
++	 * Check if we can restore can_queue
++	 */
++	if (instance->flag & MEGASAS_FW_BUSY
++		&& time_after(jiffies, instance->last_time + 5 * HZ)
++		&& atomic_read(&instance->fw_outstanding) < 17) {
++
++		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)) {
++			instance->host->can_queue =
++				instance->max_fw_cmds - MEGASAS_SKINNY_INT_CMDS;
++		} else
++			instance->host->can_queue =
++				instance->max_fw_cmds - MEGASAS_INT_CMDS;
++
++		spin_unlock_irqrestore(instance->host->host_lock, flags);
++	}
++}
++
++/**
++ * megasas_wait_for_outstanding -	Wait for all outstanding cmds
++ * @instance:				Adapter soft state
++ *
++ * This function waits for upto MEGASAS_RESET_WAIT_TIME seconds for FW to
++ * complete all its outstanding commands. Returns error if one or more IOs
++ * are pending after this time period. It also marks the controller dead.
++ */
++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;
++
++	spin_lock_irqsave(&instance->hba_lock, flags);
++	adprecovery = instance->adprecovery;
++	spin_unlock_irqrestore(&instance->hba_lock, flags);
++
++	if (adprecovery != MEGASAS_HBA_OPERATIONAL) {
++
++		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(KERN_NOTICE "megasas: HBA reset wait ...\n");
++		for (i = 0; i < wait_time; i++) {
++			msleep(1000);
++			spin_lock_irqsave(&instance->hba_lock, flags);
++			adprecovery = instance->adprecovery;
++			spin_unlock_irqrestore(&instance->hba_lock, flags);
++			if (adprecovery == MEGASAS_HBA_OPERATIONAL)
++				break;
++		}
++
++		if (adprecovery != MEGASAS_HBA_OPERATIONAL) {
++			printk(KERN_NOTICE "megasas: reset: Stopping HBA.\n");
++			spin_lock_irqsave(&instance->hba_lock, flags);
++			instance->adprecovery	= MEGASAS_HW_CRITICAL_ERROR;
++			spin_unlock_irqrestore(&instance->hba_lock, flags);
++			return FAILED;
++		}
++
++		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(KERN_NOTICE "%d:%p reset [%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) {
++				printk(KERN_NOTICE "megasas:%p synch cmds"
++						"reset queue\n",
++						reset_cmd);
++
++				reset_cmd->cmd_status = ENODATA;
++				instance->instancet->fire_cmd(instance,
++						reset_cmd->frame_phys_addr,
++						0, instance->reg_set);
++			} else {
++				printk(KERN_NOTICE "megasas: %p unexpected"
++					"cmds lst\n",
++					reset_cmd);
++			}
++			reset_index++;
++		}
++
++		return SUCCESS;
++	}
++
++	for (i = 0; i < wait_time; i++) {
++
++		int outstanding = atomic_read(&instance->fw_outstanding);
++
++		if (!outstanding)
++			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
++			 * be completed directly without depending on isr.
++			 */
++			megasas_complete_cmd_dpc((unsigned long)instance);
++		}
++
++		msleep(1000);
++	}
++
++	if (atomic_read(&instance->fw_outstanding)) {
++		printk(KERN_NOTICE "megaraid_sas: pending cmds after reset\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)) {
++			writel(MFI_STOP_ADP,
++				&instance->reg_set->reserved_0[0]);
++		} else {
++			writel(MFI_STOP_ADP,
++				&instance->reg_set->inbound_doorbell);
++		}
++		megasas_dump_pending_frames(instance);
++		spin_lock_irqsave(&instance->hba_lock, flags);
++		instance->adprecovery	= MEGASAS_HW_CRITICAL_ERROR;
++		spin_unlock_irqrestore(&instance->hba_lock, flags);
++		return FAILED;
++	}
++
++	printk(KERN_NOTICE "megaraid_sas: no pending cmds after reset\n");
++
++	return SUCCESS;
++}
++
++/**
++ * megasas_generic_reset -	Generic reset routine
++ * @scmd:			Mid-layer SCSI command
++ *
++ * This routine implements a generic reset handler for device, bus and host
++ * reset requests. Device, bus and host specific reset handlers can use this
++ * function after they do their specific tasks.
++ */
++static int megasas_generic_reset(struct scsi_cmnd *scmd)
++{
++	int ret_val;
++	struct megasas_instance *instance;
++
++	instance = (struct megasas_instance *)scmd->device->host->hostdata;
++
++	scmd_printk(KERN_NOTICE, scmd, "megasas: RESET -%ld cmd=%x retries=%x\n",
++		 scmd->serial_number, scmd->cmnd[0], scmd->retries);
++
++	if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR) {
++		printk(KERN_ERR "megasas: cannot recover from previous reset "
++		       "failures\n");
++		return FAILED;
++	}
++
++	ret_val = megasas_wait_for_outstanding(instance);
++	if (ret_val == SUCCESS)
++		printk(KERN_NOTICE "megasas: reset successful \n");
++	else
++		printk(KERN_ERR "megasas: failed to do reset\n");
++
++	return ret_val;
++}
++
++/**
++ * megasas_reset_timer - quiesce the adapter if required
++ * @scmd:		scsi cmnd
++ *
++ * Sets the FW busy flag and reduces the host->can_queue if the
++ * cmd has not been completed within the timeout period.
++ */
++static enum
++blk_eh_timer_return megasas_reset_timer(struct scsi_cmnd *scmd)
++{
++	struct megasas_cmd *cmd = (struct megasas_cmd *)scmd->SCp.ptr;
++	struct megasas_instance *instance;
++	unsigned long flags;
++
++	if (time_after(jiffies, scmd->jiffies_at_alloc +
++				(MEGASAS_DEFAULT_CMD_TIMEOUT * 2) * HZ)) {
++		return BLK_EH_NOT_HANDLED;
++	}
++
++	instance = cmd->instance;
++	if (!(instance->flag & MEGASAS_FW_BUSY)) {
++		/* FW is busy, throttle IO */
++		spin_lock_irqsave(instance->host->host_lock, flags);
++
++		instance->host->can_queue = 16;
++		instance->last_time = jiffies;
++		instance->flag |= MEGASAS_FW_BUSY;
++
++		spin_unlock_irqrestore(instance->host->host_lock, flags);
++	}
++	return BLK_EH_RESET_TIMER;
++}
++
++/**
++ * megasas_reset_device -	Device reset handler entry point
++ */
++static int megasas_reset_device(struct scsi_cmnd *scmd)
++{
++	int ret;
++
++	/*
++	 * First wait for all commands to complete
++	 */
++	ret = megasas_generic_reset(scmd);
++
++	return ret;
++}
++
++/**
++ * megasas_reset_bus_host -	Bus & host reset handler entry point
++ */
++static int megasas_reset_bus_host(struct scsi_cmnd *scmd)
++{
++	int ret;
++
++	/*
++	 * First wait for all commands to complete
++	 */
++	ret = megasas_generic_reset(scmd);
++
++	return ret;
++}
++
++/**
++ * megasas_bios_param - Returns disk geometry for a disk
++ * @sdev: 		device handle
++ * @bdev:		block device
++ * @capacity:		drive capacity
++ * @geom:		geometry parameters
++ */
++static int
++megasas_bios_param(struct scsi_device *sdev, struct block_device *bdev,
++		 sector_t capacity, int geom[])
++{
++	int heads;
++	int sectors;
++	sector_t cylinders;
++	unsigned long tmp;
++	/* Default heads (64) & sectors (32) */
++	heads = 64;
++	sectors = 32;
++
++	tmp = heads * sectors;
++	cylinders = capacity;
++
++	sector_div(cylinders, tmp);
++
++	/*
++	 * Handle extended translation size for logical drives > 1Gb
++	 */
++
++	if (capacity >= 0x200000) {
++		heads = 255;
++		sectors = 63;
++		tmp = heads*sectors;
++		cylinders = capacity;
++		sector_div(cylinders, tmp);
++	}
++
++	geom[0] = heads;
++	geom[1] = sectors;
++	geom[2] = cylinders;
++
++	return 0;
++}
++
++static void megasas_aen_polling(struct work_struct *work);
++
++/**
++ * megasas_service_aen -	Processes an event notification
++ * @instance:			Adapter soft state
++ * @cmd:			AEN command completed by the ISR
++ *
++ * For AEN, driver sends a command down to FW that is held by the FW till an
++ * event occurs. When an event of interest occurs, FW completes the command
++ * that it was previously holding.
++ *
++ * This routines sends SIGIO signal to processes that have registered with the
++ * driver for AEN.
++ */
++static void
++megasas_service_aen(struct megasas_instance *instance, struct megasas_cmd *cmd)
++{
++	unsigned long flags;
++	/*
++	 * Don't signal app if it is just an aborted previously registered aen
++	 */
++	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);
++		kill_fasync(&megasas_async_queue, SIGIO, POLL_IN);
++	}
++	else
++		cmd->abort_aen = 0;
++
++	instance->aen_cmd = NULL;
++	megasas_return_cmd(instance, cmd);
++
++	if ((instance->unload == 0) &&
++		((instance->issuepend_done == 1))) {
++		struct megasas_aen_event *ev;
++		ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
++		if (!ev) {
++			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);
++			schedule_delayed_work(
++				(struct delayed_work *)&ev->hotplug_work, 0);
++		}
++	}
++}
++
++/*
++ * Scsi host template for megaraid_sas driver
++ */
++static struct scsi_host_template megasas_template = {
++
++	.module = THIS_MODULE,
++	.name = "LSI SAS based MegaRAID driver",
++	.proc_name = "megaraid_sas",
++	.slave_configure = megasas_slave_configure,
++	.queuecommand = megasas_queue_command,
++	.eh_device_reset_handler = megasas_reset_device,
++	.eh_bus_reset_handler = megasas_reset_bus_host,
++	.eh_host_reset_handler = megasas_reset_bus_host,
++	.eh_timed_out = megasas_reset_timer,
++	.bios_param = megasas_bios_param,
++	.use_clustering = ENABLE_CLUSTERING,
++};
++
++/**
++ * megasas_complete_int_cmd -	Completes an internal command
++ * @instance:			Adapter soft state
++ * @cmd:			Command to be completed
++ *
++ * The megasas_issue_blocked_cmd() function waits for a command to complete
++ * after it issues a command. This function wakes up that waiting routine by
++ * calling wake_up() on the wait queue.
++ */
++static void
++megasas_complete_int_cmd(struct megasas_instance *instance,
++			 struct megasas_cmd *cmd)
++{
++	cmd->cmd_status = cmd->frame->io.cmd_status;
++
++	if (cmd->cmd_status == ENODATA) {
++		cmd->cmd_status = 0;
++	}
++	wake_up(&instance->int_cmd_wait_q);
++}
++
++/**
++ * megasas_complete_abort -	Completes aborting a command
++ * @instance:			Adapter soft state
++ * @cmd:			Cmd that was issued to abort another cmd
++ *
++ * The megasas_issue_blocked_abort_cmd() function waits on abort_cmd_wait_q
++ * after it issues an abort on a previously issued command. This function
++ * wakes up all functions waiting on the same wait queue.
++ */
++static void
++megasas_complete_abort(struct megasas_instance *instance,
++		       struct megasas_cmd *cmd)
++{
++	if (cmd->sync_cmd) {
++		cmd->sync_cmd = 0;
++		cmd->cmd_status = 0;
++		wake_up(&instance->abort_cmd_wait_q);
++	}
++
++	return;
++}
++
++/**
++ * megasas_complete_cmd -	Completes a command
++ * @instance:			Adapter soft state
++ * @cmd:			Command to be completed
++ * @alt_status:			If non-zero, use this value as status to
++ * 				SCSI mid-layer instead of the value returned
++ * 				by the FW. This should be used if caller wants
++ * 				an alternate status (as in the case of aborted
++ * 				commands)
++ */
++static void
++megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd,
++		     u8 alt_status)
++{
++	int exception = 0;
++	struct megasas_header *hdr = &cmd->frame->hdr;
++	unsigned long flags;
++
++	/* flag for the retry reset */
++	cmd->retry_for_fw_reset = 0;
++
++	if (cmd->scmd)
++		cmd->scmd->SCp.ptr = NULL;
++
++	switch (hdr->cmd) {
++
++	case MFI_CMD_PD_SCSI_IO:
++	case MFI_CMD_LD_SCSI_IO:
++
++		/*
++		 * MFI_CMD_PD_SCSI_IO and MFI_CMD_LD_SCSI_IO could have been
++		 * issued either through an IO path or an IOCTL path. If it
++		 * was via IOCTL, we will send it to internal completion.
++		 */
++		if (cmd->sync_cmd) {
++			cmd->sync_cmd = 0;
++			megasas_complete_int_cmd(instance, cmd);
++			break;
++		}
++
++	case MFI_CMD_LD_READ:
++	case MFI_CMD_LD_WRITE:
++
++		if (alt_status) {
++			cmd->scmd->result = alt_status << 16;
++			exception = 1;
++		}
++
++		if (exception) {
++
++			atomic_dec(&instance->fw_outstanding);
++
++			scsi_dma_unmap(cmd->scmd);
++			cmd->scmd->scsi_done(cmd->scmd);
++			megasas_return_cmd(instance, cmd);
++
++			break;
++		}
++
++		switch (hdr->cmd_status) {
++
++		case MFI_STAT_OK:
++			cmd->scmd->result = DID_OK << 16;
++			break;
++
++		case MFI_STAT_SCSI_IO_FAILED:
++		case MFI_STAT_LD_INIT_IN_PROGRESS:
++			cmd->scmd->result =
++			    (DID_ERROR << 16) | hdr->scsi_status;
++			break;
++
++		case MFI_STAT_SCSI_DONE_WITH_ERROR:
++
++			cmd->scmd->result = (DID_OK << 16) | hdr->scsi_status;
++
++			if (hdr->scsi_status == SAM_STAT_CHECK_CONDITION) {
++				memset(cmd->scmd->sense_buffer, 0,
++				       SCSI_SENSE_BUFFERSIZE);
++				memcpy(cmd->scmd->sense_buffer, cmd->sense,
++				       hdr->sense_len);
++
++				cmd->scmd->result |= DRIVER_SENSE << 24;
++			}
++
++			break;
++
++		case MFI_STAT_LD_OFFLINE:
++		case MFI_STAT_DEVICE_NOT_FOUND:
++			cmd->scmd->result = DID_BAD_TARGET << 16;
++			break;
++
++		default:
++			printk(KERN_DEBUG "megasas: MFI FW status %#x\n",
++			       hdr->cmd_status);
++			cmd->scmd->result = DID_ERROR << 16;
++			break;
++		}
++
++		atomic_dec(&instance->fw_outstanding);
++
++		scsi_dma_unmap(cmd->scmd);
++		cmd->scmd->scsi_done(cmd->scmd);
++		megasas_return_cmd(instance, cmd);
++
++		break;
++
++	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
++		 */
++		if (cmd->frame->dcmd.opcode == MR_DCMD_CTRL_EVENT_WAIT)
++			megasas_service_aen(instance, cmd);
++		else
++			megasas_complete_int_cmd(instance, cmd);
++
++		break;
++
++	case MFI_CMD_ABORT:
++		/*
++		 * Cmd issued to abort another cmd returned
++		 */
++		megasas_complete_abort(instance, 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(KERN_NOTICE "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 (cmd->retry_for_fw_reset == 3) {
++				printk(KERN_NOTICE "megaraid_sas: cmd %p, %p:%d"
++					"was tried multiple times during 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(KERN_NOTICE "megaraid_sas: unexpected"
++					"cmd attached to internal command!\n");
++			}
++			printk(KERN_NOTICE "megasas: %p synchronous cmd"
++						"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(KERN_NOTICE "megasas: %p scsi cmd [%02x],%#lx"
++			"detected on the internal queue, issue 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(KERN_NOTICE "megasas: %p unexpected cmd on the"
++				"internal reset defer list while re-issue!!\n",
++				cmd);
++		}
++	}
++
++	if (instance->aen_cmd) {
++		printk(KERN_NOTICE "megaraid_sas: aen_cmd in def process\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(KERN_NOTICE "megasas: moving cmd[%d]:%p:%d:%p"
++					"on the defer queue as internal\n",
++				defer_index, cmd, cmd->sync_cmd, cmd->scmd);
++
++			if (!list_empty(&cmd->list)) {
++				printk(KERN_NOTICE "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(struct work_struct *work)
++{
++	struct megasas_instance *instance =
++		container_of(work, struct megasas_instance, work_init);
++	u32 wait;
++	unsigned long flags;
++
++	if (instance->adprecovery != MEGASAS_ADPRESET_SM_INFAULT) {
++		printk(KERN_NOTICE "megaraid_sas: error, recovery st %x \n",
++				instance->adprecovery);
++		return ;
++	}
++
++	if (instance->adprecovery == MEGASAS_ADPRESET_SM_INFAULT) {
++		printk(KERN_NOTICE "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(KERN_NOTICE "megaraid_sas: FW restarted successfully,"
++					"initiating next stage...\n");
++
++		printk(KERN_NOTICE "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(KERN_NOTICE "megaraid_sas:adapter not ready\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;
++		}
++
++		megasas_issue_init_mfi(instance);
++
++		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);
++
++		megasas_issue_pending_cmds_again(instance);
++		instance->issuepend_done = 1;
++	}
++	return ;
++}
++
++/**
++ * megasas_deplete_reply_queue -	Processes all completed commands
++ * @instance:				Adapter soft state
++ * @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)
++{
++	u32 mfiStatus;
++	u32 fw_state;
++
++	if ((mfiStatus = instance->instancet->check_reset(instance,
++					instance->reg_set)) == 1) {
++		return IRQ_HANDLED;
++	}
++
++	if ((mfiStatus = instance->instancet->clear_intr(
++						instance->reg_set)
++						) == 0) {
++		return IRQ_NONE;
++	}
++
++	instance->mfiStatus = mfiStatus;
++
++	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(KERN_NOTICE "megaraid_sas: fw state:%x\n",
++						fw_state);
++		}
++
++		if ((fw_state == MFI_STATE_FAULT) &&
++				(instance->disableOnlineCtrlReset == 0)) {
++			printk(KERN_NOTICE "megaraid_sas: wait adp 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;
++			instance->issuepend_done = 0;
++
++			atomic_set(&instance->fw_outstanding, 0);
++			megasas_internal_reset_defer_cmds(instance);
++
++			printk(KERN_NOTICE "megasas: fwState=%x, stage:%d\n",
++					fw_state, instance->adprecovery);
++
++			schedule_work(&instance->work_init);
++			return IRQ_HANDLED;
++
++		} else {
++			printk(KERN_NOTICE "megasas: fwstate:%x, dis_OCR=%x\n",
++				fw_state, instance->disableOnlineCtrlReset);
++		}
++	}
++
++	tasklet_schedule(&instance->isr_tasklet);
++	return IRQ_HANDLED;
++}
++/**
++ * megasas_isr - isr entry point
++ */
++static irqreturn_t megasas_isr(int irq, void *devp)
++{
++	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;
++}
++
++/**
++ * megasas_transition_to_ready -	Move the FW to READY state
++ * @instance:				Adapter soft state
++ *
++ * During the initialization, FW passes can potentially be in any one of
++ * several possible states. If the FW in operational, waiting-for-handshake
++ * states, driver must take steps to bring it to ready state. Otherwise, it
++ * has to wait for the ready state.
++ */
++static int
++megasas_transition_to_ready(struct megasas_instance* instance)
++{
++	int i;
++	u8 max_wait;
++	u32 fw_state;
++	u32 cur_state;
++
++	fw_state = instance->instancet->read_fw_status_reg(instance->reg_set) & MFI_STATE_MASK;
++
++	if (fw_state != MFI_STATE_READY)
++		printk(KERN_INFO "megasas: Waiting for FW to come to ready"
++		       " state\n");
++
++	while (fw_state != MFI_STATE_READY) {
++
++		switch (fw_state) {
++
++		case MFI_STATE_FAULT:
++
++			printk(KERN_DEBUG "megasas: FW in FAULT state!!\n");
++			return -ENODEV;
++
++		case MFI_STATE_WAIT_HANDSHAKE:
++			/*
++			 * 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,
++				  &instance->reg_set->reserved_0[0]);
++			} else {
++				writel(
++				    MFI_INIT_CLEAR_HANDSHAKE|MFI_INIT_HOTPLUG,
++					&instance->reg_set->inbound_doorbell);
++			}
++
++			max_wait = 2;
++			cur_state = MFI_STATE_WAIT_HANDSHAKE;
++			break;
++
++		case MFI_STATE_BOOT_MESSAGE_PENDING:
++			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
++				writel(MFI_INIT_HOTPLUG,
++					&instance->reg_set->inbound_doorbell);
++
++			max_wait = 10;
++			cur_state = MFI_STATE_BOOT_MESSAGE_PENDING;
++			break;
++
++		case MFI_STATE_OPERATIONAL:
++			/*
++			 * 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]);
++			} else
++				writel(MFI_RESET_FLAGS,
++					&instance->reg_set->inbound_doorbell);
++
++			max_wait = 60;
++			cur_state = MFI_STATE_OPERATIONAL;
++			break;
++
++		case MFI_STATE_UNDEFINED:
++			/*
++			 * This state should not last for more than 2 seconds
++			 */
++			max_wait = 2;
++			cur_state = MFI_STATE_UNDEFINED;
++			break;
++
++		case MFI_STATE_BB_INIT:
++			max_wait = 2;
++			cur_state = MFI_STATE_BB_INIT;
++			break;
++
++		case MFI_STATE_FW_INIT:
++			max_wait = 20;
++			cur_state = MFI_STATE_FW_INIT;
++			break;
++
++		case MFI_STATE_FW_INIT_2:
++			max_wait = 20;
++			cur_state = MFI_STATE_FW_INIT_2;
++			break;
++
++		case MFI_STATE_DEVICE_SCAN:
++			max_wait = 20;
++			cur_state = MFI_STATE_DEVICE_SCAN;
++			break;
++
++		case MFI_STATE_FLUSH_CACHE:
++			max_wait = 20;
++			cur_state = MFI_STATE_FLUSH_CACHE;
++			break;
++
++		default:
++			printk(KERN_DEBUG "megasas: Unknown state 0x%x\n",
++			       fw_state);
++			return -ENODEV;
++		}
++
++		/*
++		 * The cur_state should not last for more than max_wait secs
++		 */
++		for (i = 0; i < (max_wait * 1000); i++) {
++			fw_state = instance->instancet->read_fw_status_reg(instance->reg_set) &
++					MFI_STATE_MASK ;
++
++			if (fw_state == cur_state) {
++				msleep(1);
++			} else
++				break;
++		}
++
++		/*
++		 * Return error if fw_state hasn't changed after max_wait
++		 */
++		if (fw_state == cur_state) {
++			printk(KERN_DEBUG "FW state [%d] hasn't changed "
++			       "in %d secs\n", fw_state, max_wait);
++			return -ENODEV;
++		}
++	}
++	printk(KERN_INFO "megasas: FW now in Ready state\n");
++
++	return 0;
++}
++
++/**
++ * megasas_teardown_frame_pool -	Destroy the cmd frame DMA pool
++ * @instance:				Adapter soft state
++ */
++static void megasas_teardown_frame_pool(struct megasas_instance *instance)
++{
++	int i;
++	u32 max_cmd = instance->max_fw_cmds;
++	struct megasas_cmd *cmd;
++
++	if (!instance->frame_dma_pool)
++		return;
++
++	/*
++	 * Return all frames to pool
++	 */
++	for (i = 0; i < max_cmd; i++) {
++
++		cmd = instance->cmd_list[i];
++
++		if (cmd->frame)
++			pci_pool_free(instance->frame_dma_pool, cmd->frame,
++				      cmd->frame_phys_addr);
++
++		if (cmd->sense)
++			pci_pool_free(instance->sense_dma_pool, cmd->sense,
++				      cmd->sense_phys_addr);
++	}
++
++	/*
++	 * Now destroy the pool itself
++	 */
++	pci_pool_destroy(instance->frame_dma_pool);
++	pci_pool_destroy(instance->sense_dma_pool);
++
++	instance->frame_dma_pool = NULL;
++	instance->sense_dma_pool = NULL;
++}
++
++/**
++ * megasas_create_frame_pool -	Creates DMA pool for cmd frames
++ * @instance:			Adapter soft state
++ *
++ * Each command packet has an embedded DMA memory buffer that is used for
++ * filling MFI frame and the SG list that immediately follows the frame. This
++ * function creates those DMA memory buffers for each command packet by using
++ * PCI pool facility.
++ */
++static int megasas_create_frame_pool(struct megasas_instance *instance)
++{
++	int i;
++	u32 max_cmd;
++	u32 sge_sz;
++	u32 sgl_sz;
++	u32 total_sz;
++	u32 frame_count;
++	struct megasas_cmd *cmd;
++
++	max_cmd = instance->max_fw_cmds;
++
++	/*
++	 * Size of our frame is 64 bytes for MFI frame, followed by max SG
++	 * elements and finally SCSI_SENSE_BUFFERSIZE bytes for sense buffer
++	 */
++	sge_sz = (IS_DMA64) ? sizeof(struct megasas_sge64) :
++	    sizeof(struct megasas_sge32);
++
++	if (instance->flag_ieee) {
++		sge_sz = sizeof(struct megasas_sge_skinny);
++	}
++
++	/*
++	 * Calculated the number of 64byte frames required for SGL
++	 */
++	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
++	 */
++	frame_count++;
++
++	total_sz = MEGAMFI_FRAME_SIZE * frame_count;
++	/*
++	 * Use DMA pool facility provided by PCI layer
++	 */
++	instance->frame_dma_pool = pci_pool_create("megasas frame pool",
++						   instance->pdev, total_sz, 64,
++						   0);
++
++	if (!instance->frame_dma_pool) {
++		printk(KERN_DEBUG "megasas: failed to setup frame pool\n");
++		return -ENOMEM;
++	}
++
++	instance->sense_dma_pool = pci_pool_create("megasas sense pool",
++						   instance->pdev, 128, 4, 0);
++
++	if (!instance->sense_dma_pool) {
++		printk(KERN_DEBUG "megasas: failed to setup sense pool\n");
++
++		pci_pool_destroy(instance->frame_dma_pool);
++		instance->frame_dma_pool = NULL;
++
++		return -ENOMEM;
++	}
++
++	/*
++	 * Allocate and attach a frame to each of the commands in cmd_list.
++	 * By making cmd->index as the context instead of the &cmd, we can
++	 * always use 32bit context regardless of the architecture
++	 */
++	for (i = 0; i < max_cmd; i++) {
++
++		cmd = instance->cmd_list[i];
++
++		cmd->frame = pci_pool_alloc(instance->frame_dma_pool,
++					    GFP_KERNEL, &cmd->frame_phys_addr);
++
++		cmd->sense = pci_pool_alloc(instance->sense_dma_pool,
++					    GFP_KERNEL, &cmd->sense_phys_addr);
++
++		/*
++		 * megasas_teardown_frame_pool() takes care of freeing
++		 * whatever has been allocated
++		 */
++		if (!cmd->frame || !cmd->sense) {
++			printk(KERN_DEBUG "megasas: pci_pool_alloc failed \n");
++			megasas_teardown_frame_pool(instance);
++			return -ENOMEM;
++		}
++
++		cmd->frame->io.context = cmd->index;
++		cmd->frame->io.pad_0 = 0;
++	}
++
++	return 0;
++}
++
++/**
++ * megasas_free_cmds -	Free all the cmds in the free cmd pool
++ * @instance:		Adapter soft state
++ */
++static void megasas_free_cmds(struct megasas_instance *instance)
++{
++	int i;
++	/* First free the MFI frame pool */
++	megasas_teardown_frame_pool(instance);
++
++	/* Free all the commands in the cmd_list */
++	for (i = 0; i < instance->max_fw_cmds; i++)
++		kfree(instance->cmd_list[i]);
++
++	/* Free the cmd_list buffer itself */
++	kfree(instance->cmd_list);
++	instance->cmd_list = NULL;
++
++	INIT_LIST_HEAD(&instance->cmd_pool);
++}
++
++/**
++ * megasas_alloc_cmds -	Allocates the command packets
++ * @instance:		Adapter soft state
++ *
++ * Each command that is issued to the FW, whether IO commands from the OS or
++ * internal commands like IOCTLs, are wrapped in local data structure called
++ * megasas_cmd. The frame embedded in this megasas_cmd is actually issued to
++ * the FW.
++ *
++ * Each frame has a 32-bit field called context (tag). This context is used
++ * to get back the megasas_cmd from the frame when a frame gets completed in
++ * the ISR. Typically the address of the megasas_cmd itself would be used as
++ * the context. But we wanted to keep the differences between 32 and 64 bit
++ * systems to the mininum. We always use 32 bit integers for the context. In
++ * this driver, the 32 bit values are the indices into an array cmd_list.
++ * This array is used only to look up the megasas_cmd given the context. The
++ * free commands themselves are maintained in a linked list called cmd_pool.
++ */
++static int megasas_alloc_cmds(struct megasas_instance *instance)
++{
++	int i;
++	int j;
++	u32 max_cmd;
++	struct megasas_cmd *cmd;
++
++	max_cmd = instance->max_fw_cmds;
++
++	/*
++	 * instance->cmd_list is an array of struct megasas_cmd pointers.
++	 * Allocate the dynamic array first and then allocate individual
++	 * commands.
++	 */
++	instance->cmd_list = kcalloc(max_cmd, sizeof(struct megasas_cmd*), GFP_KERNEL);
++
++	if (!instance->cmd_list) {
++		printk(KERN_DEBUG "megasas: out of memory\n");
++		return -ENOMEM;
++	}
++
++
++	for (i = 0; i < max_cmd; i++) {
++		instance->cmd_list[i] = kmalloc(sizeof(struct megasas_cmd),
++						GFP_KERNEL);
++
++		if (!instance->cmd_list[i]) {
++
++			for (j = 0; j < i; j++)
++				kfree(instance->cmd_list[j]);
++
++			kfree(instance->cmd_list);
++			instance->cmd_list = NULL;
++
++			return -ENOMEM;
++		}
++	}
++
++	/*
++	 * Add all the commands to command pool (instance->cmd_pool)
++	 */
++	for (i = 0; i < max_cmd; i++) {
++		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);
++	}
++
++	/*
++	 * Create a frame pool and assign one frame to each cmd
++	 */
++	if (megasas_create_frame_pool(instance)) {
++		printk(KERN_DEBUG "megasas: Error creating frame DMA pool\n");
++		megasas_free_cmds(instance);
++	}
++
++	return 0;
++}
++
++/*
++ * 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
++ * supported by the FW.
++ */
++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;
++	}
++
++	dcmd = &cmd->frame->dcmd;
++
++	ci = pci_alloc_consistent(instance->pdev,
++		  MEGASAS_MAX_PD * sizeof(struct MR_PD_LIST), &ci_h);
++
++	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->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;
++	}
++
++	/*
++	* the following function will get the instance PD LIST.
++	*/
++
++	pd_addr = ci->addr;
++
++	if ( ret == 0 &&
++		(ci->count <
++		  (MEGASAS_MAX_PD_CHANNELS * MEGASAS_MAX_DEV_PER_CHANNEL))) {
++
++		memset(instance->pd_list, 0,
++			MEGASAS_MAX_PD * sizeof(struct megasas_pd_list));
++
++		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),
++				ci, ci_h);
++	megasas_return_cmd(instance, cmd);
++
++	return ret;
++}
++
++/*
++ * megasas_get_ld_list_info -	Returns FW's ld_list structure
++ * @instance:				Adapter soft state
++ * @ld_list:				ld_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
++ * supported by the FW.
++ */
++static int
++megasas_get_ld_list(struct megasas_instance *instance)
++{
++	int ret = 0, ld_index = 0, ids = 0;
++	struct megasas_cmd *cmd;
++	struct megasas_dcmd_frame *dcmd;
++	struct MR_LD_LIST *ci;
++	dma_addr_t ci_h = 0;
++
++	cmd = megasas_get_cmd(instance);
++
++	if (!cmd) {
++		printk(KERN_DEBUG "megasas_get_ld_list: Failed to get cmd\n");
++		return -ENOMEM;
++	}
++
++	dcmd = &cmd->frame->dcmd;
++
++	ci = pci_alloc_consistent(instance->pdev,
++				sizeof(struct MR_LD_LIST),
++				&ci_h);
++
++	if (!ci) {
++		printk(KERN_DEBUG "Failed to alloc mem in get_ld_list\n");
++		megasas_return_cmd(instance, cmd);
++		return -ENOMEM;
++	}
++
++	memset(ci, 0, sizeof(*ci));
++	memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
++
++	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 = sizeof(struct MR_LD_LIST);
++	dcmd->opcode = MR_DCMD_LD_GET_LIST;
++	dcmd->sgl.sge32[0].phys_addr = ci_h;
++	dcmd->sgl.sge32[0].length = sizeof(struct MR_LD_LIST);
++	dcmd->pad_0  = 0;
++
++	if (!megasas_issue_polled(instance, cmd)) {
++		ret = 0;
++	} else {
++		ret = -1;
++	}
++
++	/* the following function will get the instance PD LIST */
++
++	if ((ret == 0) && (ci->ldCount <= MAX_LOGICAL_DRIVES)) {
++		memset(instance->ld_ids, 0xff, MEGASAS_MAX_LD_IDS);
++
++		for (ld_index = 0; ld_index < ci->ldCount; ld_index++) {
++			if (ci->ldList[ld_index].state != 0) {
++				ids = ci->ldList[ld_index].ref.targetId;
++				instance->ld_ids[ids] =
++					ci->ldList[ld_index].ref.targetId;
++			}
++		}
++	}
++
++	pci_free_consistent(instance->pdev,
++				sizeof(struct MR_LD_LIST),
++				ci,
++				ci_h);
++
++	megasas_return_cmd(instance, cmd);
++	return ret;
++}
++
++/**
++ * megasas_get_controller_info -	Returns FW's controller structure
++ * @instance:				Adapter soft state
++ * @ctrl_info:				Controller information structure
++ *
++ * Issues an internal command (DCMD) to get the FW's controller structure.
++ * This information is mainly used to find out the maximum IO transfer per
++ * command supported by the FW.
++ */
++static int
++megasas_get_ctrl_info(struct megasas_instance *instance,
++		      struct megasas_ctrl_info *ctrl_info)
++{
++	int ret = 0;
++	struct megasas_cmd *cmd;
++	struct megasas_dcmd_frame *dcmd;
++	struct megasas_ctrl_info *ci;
++	dma_addr_t ci_h = 0;
++
++	cmd = megasas_get_cmd(instance);
++
++	if (!cmd) {
++		printk(KERN_DEBUG "megasas: Failed to get a free cmd\n");
++		return -ENOMEM;
++	}
++
++	dcmd = &cmd->frame->dcmd;
++
++	ci = pci_alloc_consistent(instance->pdev,
++				  sizeof(struct megasas_ctrl_info), &ci_h);
++
++	if (!ci) {
++		printk(KERN_DEBUG "Failed to alloc mem for ctrl info\n");
++		megasas_return_cmd(instance, cmd);
++		return -ENOMEM;
++	}
++
++	memset(ci, 0, sizeof(*ci));
++	memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
++
++	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 = sizeof(struct megasas_ctrl_info);
++	dcmd->opcode = MR_DCMD_CTRL_GET_INFO;
++	dcmd->sgl.sge32[0].phys_addr = ci_h;
++	dcmd->sgl.sge32[0].length = sizeof(struct megasas_ctrl_info);
++
++	if (!megasas_issue_polled(instance, cmd)) {
++		ret = 0;
++		memcpy(ctrl_info, ci, sizeof(struct megasas_ctrl_info));
++	} else {
++		ret = -1;
++	}
++
++	pci_free_consistent(instance->pdev, sizeof(struct megasas_ctrl_info),
++			    ci, ci_h);
++
++	megasas_return_cmd(instance, cmd);
++	return ret;
++}
++
++/**
++ * megasas_issue_init_mfi -	Initializes the FW
++ * @instance:		Adapter soft state
++ *
++ * Issues the INIT MFI cmd
++ */
++static int
++megasas_issue_init_mfi(struct megasas_instance *instance)
++{
++	u32 context;
++
++	struct megasas_cmd *cmd;
++
++	struct megasas_init_frame *init_frame;
++	struct megasas_init_queue_info *initq_info;
++	dma_addr_t init_frame_h;
++	dma_addr_t initq_info_h;
++
++	/*
++	 * Prepare a init frame. Note the init frame points to queue info
++	 * structure. Each frame has SGL allocated after first 64 bytes. For
++	 * this frame - since we don't need any SGL - we use SGL's space as
++	 * queue info structure
++	 *
++	 * We will not get a NULL command below. We just created the pool.
++	 */
++	cmd = megasas_get_cmd(instance);
++
++	init_frame = (struct megasas_init_frame *)cmd->frame;
++	initq_info = (struct megasas_init_queue_info *)
++		((unsigned long)init_frame + 64);
++
++	init_frame_h = cmd->frame_phys_addr;
++	initq_info_h = init_frame_h + 64;
++
++	context = init_frame->context;
++	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;
++
++	initq_info->producer_index_phys_addr_lo = instance->producer_h;
++	initq_info->consumer_index_phys_addr_lo = instance->consumer_h;
++
++	init_frame->cmd = MFI_CMD_INIT;
++	init_frame->cmd_status = 0xFF;
++	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
++	 */
++	instance->instancet->disable_intr(instance->reg_set);
++
++	/*
++	 * Issue the init frame in polled mode
++	 */
++
++	if (megasas_issue_polled(instance, cmd)) {
++		printk(KERN_ERR "megasas: Failed to init firmware\n");
++		megasas_return_cmd(instance, cmd);
++		goto fail_fw_init;
++	}
++
++	megasas_return_cmd(instance, cmd);
++
++	return 0;
++
++fail_fw_init:
++	return -EINVAL;
++}
++
++/**
++ * megasas_start_timer - Initializes a timer object
++ * @instance:		Adapter soft state
++ * @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,
++			struct timer_list *timer,
++			void *fn, unsigned long interval)
++{
++	init_timer(timer);
++	timer->expires = jiffies + interval;
++	timer->data = (unsigned long)instance;
++	timer->function = fn;
++	add_timer(timer);
++}
++
++/**
++ * megasas_io_completion_timer - Timer fn
++ * @instance_addr:	Address of adapter soft state
++ *
++ * 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_addr;
++
++	if (atomic_read(&instance->fw_outstanding))
++		tasklet_schedule(&instance->isr_tasklet);
++
++	/* Restart timer */
++	if (poll_mode_io)
++		mod_timer(&instance->io_completion_timer,
++			jiffies + MEGASAS_COMPLETION_TIMER_INTERVAL);
++}
++
++/**
++ * megasas_init_mfi -	Initializes the FW
++ * @instance:		Adapter soft state
++ *
++ * This is the main function for initializing MFI firmware.
++ */
++static int megasas_init_mfi(struct megasas_instance *instance)
++{
++	u32 context_sz;
++	u32 reply_q_sz;
++	u32 max_sectors_1;
++	u32 max_sectors_2;
++	u32 tmp_sectors;
++	struct megasas_register_set __iomem *reg_set;
++	struct megasas_ctrl_info *ctrl_info;
++	/*
++	 * Map the message registers
++	 */
++	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->base_addr = pci_resource_start(instance->pdev, 1);
++	} else {
++		instance->base_addr = pci_resource_start(instance->pdev, 0);
++	}
++
++	if (pci_request_regions(instance->pdev, "megasas: LSI")) {
++		printk(KERN_DEBUG "megasas: IO memory region busy!\n");
++		return -EBUSY;
++	}
++
++	instance->reg_set = ioremap_nocache(instance->base_addr, 8192);
++
++	if (!instance->reg_set) {
++		printk(KERN_DEBUG "megasas: Failed to map IO mem\n");
++		goto fail_ioremap;
++	}
++
++	reg_set = instance->reg_set;
++
++	switch(instance->pdev->device)
++	{
++		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:
++		case PCI_DEVICE_ID_LSI_SAS0079GEN2:
++			instance->instancet = &megasas_instance_template_gen2;
++			break;
++		case PCI_DEVICE_ID_LSI_SAS0073SKINNY:
++		case PCI_DEVICE_ID_LSI_SAS0071SKINNY:
++			instance->instancet = &megasas_instance_template_skinny;
++			break;
++		case PCI_DEVICE_ID_LSI_SAS1064R:
++		case PCI_DEVICE_ID_DELL_PERC5:
++		default:
++			instance->instancet = &megasas_instance_template_xscale;
++			break;
++	}
++
++	/*
++	 * We expect the FW state to be READY
++	 */
++	if (megasas_transition_to_ready(instance))
++		goto fail_ready_state;
++
++	/*
++	 * 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)
++	 * does not exceed max cmds that the FW can support
++	 */
++	instance->max_fw_cmds = instance->max_fw_cmds-1;
++	instance->max_num_sge = (instance->instancet->read_fw_status_reg(reg_set) & 0xFF0000) >>
++					0x10;
++	/*
++	 * Create a pool of commands
++	 */
++	if (megasas_alloc_cmds(instance))
++		goto fail_alloc_cmds;
++
++	/*
++	 * Allocate memory for reply queue. Length of reply queue should
++	 * be _one_ more than the maximum commands handled by the firmware.
++	 *
++	 * Note: When FW completes commands, it places corresponding contex
++	 * values in this circular reply queue. This circular queue is a fairly
++	 * typical producer-consumer queue. FW is the producer (of completed
++	 * commands) and the driver is the consumer.
++	 */
++	context_sz = sizeof(u32);
++	reply_q_sz = context_sz * (instance->max_fw_cmds + 1);
++
++	instance->reply_queue = pci_alloc_consistent(instance->pdev,
++						     reply_q_sz,
++						     &instance->reply_queue_h);
++
++	if (!instance->reply_queue) {
++		printk(KERN_DEBUG "megasas: Out of DMA mem for reply queue\n");
++		goto fail_reply_queue;
++	}
++
++	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(KERN_NOTICE "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.
++	*/
++
++	memset(instance->pd_list, 0 ,
++		(MEGASAS_MAX_PD * sizeof(struct megasas_pd_list)));
++	megasas_get_pd_list(instance);
++
++	memset(instance->ld_ids, 0xff, MEGASAS_MAX_LD_IDS);
++	megasas_get_ld_list(instance);
++
++	ctrl_info = kmalloc(sizeof(struct megasas_ctrl_info), GFP_KERNEL);
++
++	/*
++	 * Compute the max allowed sectors per IO: The controller info has two
++	 * limits on max sectors. Driver should use the minimum of these two.
++	 *
++	 * 1 << stripe_sz_ops.min = max sectors per strip
++	 *
++	 * Note that older firmwares ( < FW ver 30) didn't report information
++	 * to calculate max_sectors_1. So the number ended up as zero always.
++	 */
++	tmp_sectors = 0;
++	if (ctrl_info && !megasas_get_ctrl_info(instance, ctrl_info)) {
++
++		max_sectors_1 = (1 << ctrl_info->stripe_sz_ops.min) *
++		    ctrl_info->max_strips_per_io;
++		max_sectors_2 = ctrl_info->max_request_size;
++
++		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;
++	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
++	*/
++
++	tasklet_init(&instance->isr_tasklet, megasas_complete_cmd_dpc,
++		(unsigned long)instance);
++
++	/* Initialize the cmd completion timer */
++	if (poll_mode_io)
++		megasas_start_timer(instance, &instance->io_completion_timer,
++				megasas_io_completion_timer,
++				MEGASAS_COMPLETION_TIMER_INTERVAL);
++	return 0;
++
++      fail_fw_init:
++
++	pci_free_consistent(instance->pdev, reply_q_sz,
++			    instance->reply_queue, instance->reply_queue_h);
++      fail_reply_queue:
++	megasas_free_cmds(instance);
++
++      fail_alloc_cmds:
++      fail_ready_state:
++	iounmap(instance->reg_set);
++
++      fail_ioremap:
++	pci_release_regions(instance->pdev);
++
++	return -EINVAL;
++}
++
++/**
++ * megasas_release_mfi -	Reverses the FW initialization
++ * @intance:			Adapter soft state
++ */
++static void megasas_release_mfi(struct megasas_instance *instance)
++{
++	u32 reply_q_sz = sizeof(u32) * (instance->max_fw_cmds + 1);
++
++	pci_free_consistent(instance->pdev, reply_q_sz,
++			    instance->reply_queue, instance->reply_queue_h);
++
++	megasas_free_cmds(instance);
++
++	iounmap(instance->reg_set);
++
++	pci_release_regions(instance->pdev);
++}
++
++/**
++ * megasas_get_seq_num -	Gets latest event sequence numbers
++ * @instance:			Adapter soft state
++ * @eli:			FW event log sequence numbers information
++ *
++ * FW maintains a log of all events in a non-volatile area. Upper layers would
++ * usually find out the latest sequence number of the events, the seq number at
++ * the boot etc. They would "read" all the events below the latest seq number
++ * by issuing a direct fw cmd (DCMD). For the future events (beyond latest seq
++ * number), they would subsribe to AEN (asynchronous event notification) and
++ * wait for the events to happen.
++ */
++static int
++megasas_get_seq_num(struct megasas_instance *instance,
++		    struct megasas_evt_log_info *eli)
++{
++	struct megasas_cmd *cmd;
++	struct megasas_dcmd_frame *dcmd;
++	struct megasas_evt_log_info *el_info;
++	dma_addr_t el_info_h = 0;
++
++	cmd = megasas_get_cmd(instance);
++
++	if (!cmd) {
++		return -ENOMEM;
++	}
++
++	dcmd = &cmd->frame->dcmd;
++	el_info = pci_alloc_consistent(instance->pdev,
++				       sizeof(struct megasas_evt_log_info),
++				       &el_info_h);
++
++	if (!el_info) {
++		megasas_return_cmd(instance, cmd);
++		return -ENOMEM;
++	}
++
++	memset(el_info, 0, sizeof(*el_info));
++	memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
++
++	dcmd->cmd = MFI_CMD_DCMD;
++	dcmd->cmd_status = 0x0;
++	dcmd->sge_count = 1;
++	dcmd->flags = MFI_FRAME_DIR_READ;
++	dcmd->timeout = 0;
++	dcmd->data_xfer_len = sizeof(struct megasas_evt_log_info);
++	dcmd->opcode = MR_DCMD_CTRL_EVENT_GET_INFO;
++	dcmd->sgl.sge32[0].phys_addr = el_info_h;
++	dcmd->sgl.sge32[0].length = sizeof(struct megasas_evt_log_info);
++
++	megasas_issue_blocked_cmd(instance, cmd);
++
++	/*
++	 * Copy the data back into callers buffer
++	 */
++	memcpy(eli, el_info, sizeof(struct megasas_evt_log_info));
++
++	pci_free_consistent(instance->pdev, sizeof(struct megasas_evt_log_info),
++			    el_info, el_info_h);
++
++	megasas_return_cmd(instance, cmd);
++
++	return 0;
++}
++
++/**
++ * megasas_register_aen -	Registers for asynchronous event notification
++ * @instance:			Adapter soft state
++ * @seq_num:			The starting sequence number
++ * @class_locale:		Class of the event
++ *
++ * This function subscribes for AEN for events beyond the @seq_num. It requests
++ * to be notified if and only if the event is of type @class_locale
++ */
++static int
++megasas_register_aen(struct megasas_instance *instance, u32 seq_num,
++		     u32 class_locale_word)
++{
++	int ret_val;
++	struct megasas_cmd *cmd;
++	struct megasas_dcmd_frame *dcmd;
++	union megasas_evt_class_locale curr_aen;
++	union megasas_evt_class_locale prev_aen;
++
++	/*
++	 * If there an AEN pending already (aen_cmd), check if the
++	 * class_locale of that pending AEN is inclusive of the new
++	 * AEN request we currently have. If it is, then we don't have
++	 * to do anything. In other words, whichever events the current
++	 * AEN request is subscribing to, have already been subscribed
++	 * to.
++	 *
++	 * If the old_cmd is _not_ inclusive, then we have to abort
++	 * that command, form a class_locale that is superset of both
++	 * old and current and re-issue to the FW
++	 */
++
++	curr_aen.word = class_locale_word;
++
++	if (instance->aen_cmd) {
++
++		prev_aen.word = instance->aen_cmd->frame->dcmd.mbox.w[1];
++
++		/*
++		 * A class whose enum value is smaller is inclusive of all
++		 * higher values. If a PROGRESS (= -1) was previously
++		 * registered, then a new registration requests for higher
++		 * classes need not be sent to FW. They are automatically
++		 * included.
++		 *
++		 * Locale numbers don't have such hierarchy. They are bitmap
++		 * values
++		 */
++		if ((prev_aen.members.class <= curr_aen.members.class) &&
++		    !((prev_aen.members.locale & curr_aen.members.locale) ^
++		      curr_aen.members.locale)) {
++			/*
++			 * Previously issued event registration includes
++			 * current request. Nothing to do.
++			 */
++			return 0;
++		} else {
++			curr_aen.members.locale |= prev_aen.members.locale;
++
++			if (prev_aen.members.class < curr_aen.members.class)
++				curr_aen.members.class = prev_aen.members.class;
++
++			instance->aen_cmd->abort_aen = 1;
++			ret_val = megasas_issue_blocked_abort_cmd(instance,
++								  instance->
++								  aen_cmd);
++
++			if (ret_val) {
++				printk(KERN_DEBUG "megasas: Failed to abort "
++				       "previous AEN command\n");
++				return ret_val;
++			}
++		}
++	}
++
++	cmd = megasas_get_cmd(instance);
++
++	if (!cmd)
++		return -ENOMEM;
++
++	dcmd = &cmd->frame->dcmd;
++
++	memset(instance->evt_detail, 0, sizeof(struct megasas_evt_detail));
++
++	/*
++	 * Prepare DCMD for aen registration
++	 */
++	memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
++
++	dcmd->cmd = MFI_CMD_DCMD;
++	dcmd->cmd_status = 0x0;
++	dcmd->sge_count = 1;
++	dcmd->flags = MFI_FRAME_DIR_READ;
++	dcmd->timeout = 0;
++	instance->last_seq_num = seq_num;
++	dcmd->data_xfer_len = sizeof(struct megasas_evt_detail);
++	dcmd->opcode = MR_DCMD_CTRL_EVENT_WAIT;
++	dcmd->mbox.w[0] = 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;
++	}
++
++	/*
++	 * Store reference to the cmd used to register for AEN. When an
++	 * application wants us to register for AEN, we have to abort this
++	 * cmd and re-register with a new EVENT LOCALE supplied by that app
++	 */
++	instance->aen_cmd = cmd;
++
++	/*
++	 * Issue the aen registration frame
++	 */
++	instance->instancet->fire_cmd(instance,
++			cmd->frame_phys_addr, 0, instance->reg_set);
++
++	return 0;
++}
++
++/**
++ * megasas_start_aen -	Subscribes to AEN during driver load time
++ * @instance:		Adapter soft state
++ */
++static int megasas_start_aen(struct megasas_instance *instance)
++{
++	struct megasas_evt_log_info eli;
++	union megasas_evt_class_locale class_locale;
++
++	/*
++	 * Get the latest sequence number from FW
++	 */
++	memset(&eli, 0, sizeof(eli));
++
++	if (megasas_get_seq_num(instance, &eli))
++		return -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;
++
++	return megasas_register_aen(instance, eli.newest_seq_num + 1,
++				    class_locale.word);
++}
++
++/**
++ * megasas_io_attach -	Attaches this driver to SCSI mid-layer
++ * @instance:		Adapter soft state
++ */
++static int megasas_io_attach(struct megasas_instance *instance)
++{
++	struct Scsi_Host *host = instance->host;
++
++	/*
++	 * Export parameters required by SCSI mid-layer
++	 */
++	host->irq = instance->pdev->irq;
++	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;
++	} else
++		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;
++	host->cmd_per_lun = 128;
++	host->max_channel = MEGASAS_MAX_CHANNELS - 1;
++	host->max_id = MEGASAS_MAX_DEV_PER_CHANNEL;
++	host->max_lun = MEGASAS_MAX_LUN;
++	host->max_cmd_len = 16;
++
++	/*
++	 * Notify the mid-layer about the new controller
++	 */
++	if (scsi_add_host(host, &instance->pdev->dev)) {
++		printk(KERN_DEBUG "megasas: scsi_add_host failed\n");
++		return -ENODEV;
++	}
++
++	/*
++	 * Trigger SCSI to scan our drives
++	 */
++	scsi_scan_host(host);
++	return 0;
++}
++
++static int
++megasas_set_dma_mask(struct pci_dev *pdev)
++{
++	/*
++	 * All our contollers are capable of performing 64-bit DMA
++	 */
++	if (IS_DMA64) {
++		if (pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) != 0) {
++
++			if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) != 0)
++				goto fail_set_dma_mask;
++		}
++	} else {
++		if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) != 0)
++			goto fail_set_dma_mask;
++	}
++	return 0;
++
++fail_set_dma_mask:
++	return 1;
++}
++
++/**
++ * megasas_probe_one -	PCI hotplug entry point
++ * @pdev:		PCI device structure
++ * @id:			PCI ids of supported hotplugged adapter
++ */
++static int __devinit
++megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
++{
++	int rval;
++	struct Scsi_Host *host;
++	struct megasas_instance *instance;
++
++	/*
++	 * Announce PCI information
++	 */
++	printk(KERN_INFO "megasas: %#4.04x:%#4.04x:%#4.04x:%#4.04x: ",
++	       pdev->vendor, pdev->device, pdev->subsystem_vendor,
++	       pdev->subsystem_device);
++
++	printk("bus %d:slot %d:func %d\n",
++	       pdev->bus->number, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn));
++
++	/*
++	 * PCI prepping: enable device set bus mastering and dma mask
++	 */
++	rval = pci_enable_device(pdev);
++
++	if (rval) {
++		return rval;
++	}
++
++	pci_set_master(pdev);
++
++	if (megasas_set_dma_mask(pdev))
++		goto fail_set_dma_mask;
++
++	host = scsi_host_alloc(&megasas_template,
++			       sizeof(struct megasas_instance));
++
++	if (!host) {
++		printk(KERN_DEBUG "megasas: scsi_host_alloc failed\n");
++		goto fail_alloc_instance;
++	}
++
++	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),
++						  &instance->consumer_h);
++
++	if (!instance->producer || !instance->consumer) {
++		printk(KERN_DEBUG "megasas: Failed to allocate memory for "
++		       "producer, consumer\n");
++		goto fail_alloc_dma_buf;
++	}
++
++	*instance->producer = 0;
++	*instance->consumer = 0;
++	megasas_poll_wait_aen = 0;
++	instance->flag_ieee = 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
++							   megasas_evt_detail),
++						    &instance->evt_detail_h);
++
++	if (!instance->evt_detail) {
++		printk(KERN_DEBUG "megasas: Failed to allocate memory for "
++		       "event detail structure\n");
++		goto fail_alloc_dma_buf;
++	}
++
++	/*
++	 * Initialize locks and queues
++	 */
++	INIT_LIST_HEAD(&instance->cmd_pool);
++	INIT_LIST_HEAD(&instance->internal_reset_pending_q);
++
++	atomic_set(&instance->fw_outstanding,0);
++
++	init_waitqueue_head(&instance->int_cmd_wait_q);
++	init_waitqueue_head(&instance->abort_cmd_wait_q);
++
++	spin_lock_init(&instance->cmd_pool_lock);
++	spin_lock_init(&instance->hba_lock);
++	spin_lock_init(&instance->completion_lock);
++	spin_lock_init(&poll_aen_lock);
++
++	mutex_init(&instance->aen_mutex);
++
++	/*
++	 * Initialize PCI related and misc parameters
++	 */
++	instance->pdev = pdev;
++	instance->host = host;
++	instance->unique_id = pdev->bus->number << 8 | pdev->devfn;
++	instance->init_id = MEGASAS_DEFAULT_INIT_ID;
++
++	if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0073SKINNY) ||
++		(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->disableOnlineCtrlReset = 1;
++
++	INIT_WORK(&instance->work_init, process_fw_state_change_wq);
++
++	/*
++	 * Initialize MFI Firmware
++	 */
++	if (megasas_init_mfi(instance))
++		goto fail_init_mfi;
++
++	/*
++	 * Register IRQ
++	 */
++	if (request_irq(pdev->irq, megasas_isr, IRQF_SHARED, "megasas", instance)) {
++		printk(KERN_DEBUG "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);
++
++	/*
++	 * Add this controller to megasas_mgmt_info structure so that it
++	 * can be exported to management applications
++	 */
++	megasas_mgmt_info.count++;
++	megasas_mgmt_info.instance[megasas_mgmt_info.max_index] = instance;
++	megasas_mgmt_info.max_index++;
++
++	/*
++	 * Initiate AEN (Asynchronous Event Notification)
++	 */
++	if (megasas_start_aen(instance)) {
++		printk(KERN_DEBUG "megasas: start aen failed\n");
++		goto fail_start_aen;
++	}
++
++	/*
++	 * Register with SCSI mid-layer
++	 */
++	if (megasas_io_attach(instance))
++		goto fail_io_attach;
++
++	instance->unload = 0;
++	return 0;
++
++      fail_start_aen:
++      fail_io_attach:
++	megasas_mgmt_info.count--;
++	megasas_mgmt_info.instance[megasas_mgmt_info.max_index] = NULL;
++	megasas_mgmt_info.max_index--;
++
++	pci_set_drvdata(pdev, NULL);
++	instance->instancet->disable_intr(instance->reg_set);
++	free_irq(instance->pdev->irq, instance);
++
++	megasas_release_mfi(instance);
++
++      fail_irq:
++      fail_init_mfi:
++      fail_alloc_dma_buf:
++	if (instance->evt_detail)
++		pci_free_consistent(pdev, sizeof(struct megasas_evt_detail),
++				    instance->evt_detail,
++				    instance->evt_detail_h);
++
++	if (instance->producer)
++		pci_free_consistent(pdev, sizeof(u32), instance->producer,
++				    instance->producer_h);
++	if (instance->consumer)
++		pci_free_consistent(pdev, sizeof(u32), instance->consumer,
++				    instance->consumer_h);
++	scsi_host_put(host);
++
++      fail_alloc_instance:
++      fail_set_dma_mask:
++	pci_disable_device(pdev);
++
++	return -ENODEV;
++}
++
++/**
++ * megasas_flush_cache -	Requests FW to flush all its caches
++ * @instance:			Adapter soft state
++ */
++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)
++		return;
++
++	dcmd = &cmd->frame->dcmd;
++
++	memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
++
++	dcmd->cmd = MFI_CMD_DCMD;
++	dcmd->cmd_status = 0x0;
++	dcmd->sge_count = 0;
++	dcmd->flags = MFI_FRAME_DIR_NONE;
++	dcmd->timeout = 0;
++	dcmd->data_xfer_len = 0;
++	dcmd->opcode = MR_DCMD_CTRL_CACHE_FLUSH;
++	dcmd->mbox.b[0] = MR_FLUSH_CTRL_CACHE | MR_FLUSH_DISK_CACHE;
++
++	megasas_issue_blocked_cmd(instance, cmd);
++
++	megasas_return_cmd(instance, cmd);
++
++	return;
++}
++
++/**
++ * megasas_shutdown_controller -	Instructs FW to shutdown the controller
++ * @instance:				Adapter soft state
++ * @opcode:				Shutdown/Hibernate
++ */
++static void megasas_shutdown_controller(struct megasas_instance *instance,
++					u32 opcode)
++{
++	struct megasas_cmd *cmd;
++	struct megasas_dcmd_frame *dcmd;
++
++	if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR)
++		return;
++
++	cmd = megasas_get_cmd(instance);
++
++	if (!cmd)
++		return;
++
++	if (instance->aen_cmd)
++		megasas_issue_blocked_abort_cmd(instance, instance->aen_cmd);
++
++	dcmd = &cmd->frame->dcmd;
++
++	memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
++
++	dcmd->cmd = MFI_CMD_DCMD;
++	dcmd->cmd_status = 0x0;
++	dcmd->sge_count = 0;
++	dcmd->flags = MFI_FRAME_DIR_NONE;
++	dcmd->timeout = 0;
++	dcmd->data_xfer_len = 0;
++	dcmd->opcode = opcode;
++
++	megasas_issue_blocked_cmd(instance, cmd);
++
++	megasas_return_cmd(instance, cmd);
++
++	return;
++}
++
++#ifdef CONFIG_PM
++/**
++ * megasas_suspend -	driver suspend entry point
++ * @pdev:		PCI device structure
++ * @state:		PCI power state to suspend routine
++ */
++static int
++megasas_suspend(struct pci_dev *pdev, pm_message_t state)
++{
++	struct Scsi_Host *host;
++	struct megasas_instance *instance;
++
++	instance = pci_get_drvdata(pdev);
++	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(
++			(struct delayed_work *)&ev->hotplug_work);
++		flush_scheduled_work();
++		instance->ev = NULL;
++	}
++
++	tasklet_kill(&instance->isr_tasklet);
++
++	pci_set_drvdata(instance->pdev, instance);
++	instance->instancet->disable_intr(instance->reg_set);
++	free_irq(instance->pdev->irq, instance);
++
++	pci_save_state(pdev);
++	pci_disable_device(pdev);
++
++	pci_set_power_state(pdev, pci_choose_state(pdev, state));
++
++	return 0;
++}
++
++/**
++ * megasas_resume-      driver resume entry point
++ * @pdev:               PCI device structure
++ */
++static int
++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);
++	pci_enable_wake(pdev, PCI_D0, 0);
++	pci_restore_state(pdev);
++
++	/*
++	 * PCI prepping: enable device set bus mastering and dma mask
++	 */
++	rval = pci_enable_device(pdev);
++
++	if (rval) {
++		printk(KERN_ERR "megasas: Enable device failed\n");
++		return rval;
++	}
++
++	pci_set_master(pdev);
++
++	if (megasas_set_dma_mask(pdev))
++		goto fail_set_dma_mask;
++
++	/*
++	 * Initialize MFI Firmware
++	 */
++
++	*instance->producer = 0;
++	*instance->consumer = 0;
++
++	atomic_set(&instance->fw_outstanding, 0);
++
++	/*
++	 * We expect the FW state to be READY
++	 */
++	if (megasas_transition_to_ready(instance))
++		goto fail_ready_state;
++
++	if (megasas_issue_init_mfi(instance))
++		goto fail_init_mfi;
++
++	tasklet_init(&instance->isr_tasklet, megasas_complete_cmd_dpc,
++			(unsigned long)instance);
++
++	/*
++	 * Register IRQ
++	 */
++	if (request_irq(pdev->irq, megasas_isr, IRQF_SHARED,
++		"megasas", instance)) {
++		printk(KERN_ERR "megasas: Failed to register IRQ\n");
++		goto fail_irq;
++	}
++
++	instance->instancet->enable_intr(instance->reg_set);
++
++	/*
++	 * Initiate AEN (Asynchronous Event Notification)
++	 */
++	if (megasas_start_aen(instance))
++		printk(KERN_ERR "megasas: Start AEN failed\n");
++
++	/* Initialize the cmd completion timer */
++	if (poll_mode_io)
++		megasas_start_timer(instance, &instance->io_completion_timer,
++				megasas_io_completion_timer,
++				MEGASAS_COMPLETION_TIMER_INTERVAL);
++	instance->unload = 0;
++
++	return 0;
++
++fail_irq:
++fail_init_mfi:
++	if (instance->evt_detail)
++		pci_free_consistent(pdev, sizeof(struct megasas_evt_detail),
++				instance->evt_detail,
++				instance->evt_detail_h);
++
++	if (instance->producer)
++		pci_free_consistent(pdev, sizeof(u32), instance->producer,
++				instance->producer_h);
++	if (instance->consumer)
++		pci_free_consistent(pdev, sizeof(u32), instance->consumer,
++				instance->consumer_h);
++	scsi_host_put(host);
++
++fail_set_dma_mask:
++fail_ready_state:
++
++	pci_disable_device(pdev);
++
++	return -ENODEV;
++}
++#else
++#define megasas_suspend	NULL
++#define megasas_resume	NULL
++#endif
++
++/**
++ * megasas_detach_one -	PCI hot"un"plug entry point
++ * @pdev:		PCI device structure
++ */
++static void __devexit megasas_detach_one(struct pci_dev *pdev)
++{
++	int i;
++	struct Scsi_Host *host;
++	struct megasas_instance *instance;
++
++	instance = pci_get_drvdata(pdev);
++	instance->unload = 1;
++	host = instance->host;
++
++	if (poll_mode_io)
++		del_timer_sync(&instance->io_completion_timer);
++
++	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(
++			(struct delayed_work *)&ev->hotplug_work);
++		flush_scheduled_work();
++		instance->ev = NULL;
++	}
++
++	tasklet_kill(&instance->isr_tasklet);
++
++	/*
++	 * Take the instance off the instance array. Note that we will not
++	 * decrement the max_index. We let this array be sparse array
++	 */
++	for (i = 0; i < megasas_mgmt_info.max_index; i++) {
++		if (megasas_mgmt_info.instance[i] == instance) {
++			megasas_mgmt_info.count--;
++			megasas_mgmt_info.instance[i] = NULL;
++
++			break;
++		}
++	}
++
++	pci_set_drvdata(instance->pdev, NULL);
++
++	instance->instancet->disable_intr(instance->reg_set);
++
++	free_irq(instance->pdev->irq, instance);
++
++	megasas_release_mfi(instance);
++
++	pci_free_consistent(pdev, sizeof(struct megasas_evt_detail),
++			    instance->evt_detail, instance->evt_detail_h);
++
++	pci_free_consistent(pdev, sizeof(u32), instance->producer,
++			    instance->producer_h);
++
++	pci_free_consistent(pdev, sizeof(u32), instance->consumer,
++			    instance->consumer_h);
++
++	scsi_host_put(host);
++
++	pci_set_drvdata(pdev, NULL);
++
++	pci_disable_device(pdev);
++
++	return;
++}
++
++/**
++ * megasas_shutdown -	Shutdown entry point
++ * @device:		Generic device structure
++ */
++static void megasas_shutdown(struct pci_dev *pdev)
++{
++	struct megasas_instance *instance = pci_get_drvdata(pdev);
++	instance->unload = 1;
++	megasas_flush_cache(instance);
++	megasas_shutdown_controller(instance, MR_DCMD_CTRL_SHUTDOWN);
++}
++
++/**
++ * megasas_mgmt_open -	char node "open" entry point
++ */
++static int megasas_mgmt_open(struct inode *inode, struct file *filep)
++{
++	cycle_kernel_lock();
++	/*
++	 * Allow only those users with admin rights
++	 */
++	if (!capable(CAP_SYS_ADMIN))
++		return -EACCES;
++
++	return 0;
++}
++
++/**
++ * megasas_mgmt_fasync -	Async notifier registration from applications
++ *
++ * This function adds the calling process to a driver global queue. When an
++ * event occurs, SIGIO will be sent to all processes in this queue.
++ */
++static int megasas_mgmt_fasync(int fd, struct file *filep, int mode)
++{
++	int rc;
++
++	mutex_lock(&megasas_async_queue_mutex);
++
++	rc = fasync_helper(fd, filep, mode, &megasas_async_queue);
++
++	mutex_unlock(&megasas_async_queue_mutex);
++
++	if (rc >= 0) {
++		/* For sanity check when we get ioctl */
++		filep->private_data = filep;
++		return 0;
++	}
++
++	printk(KERN_DEBUG "megasas: fasync_helper failed [%d]\n", rc);
++
++	return rc;
++}
++
++/**
++ * megasas_mgmt_poll -  char node "poll" entry point
++ * */
++static unsigned int megasas_mgmt_poll(struct file *file, poll_table *wait)
++{
++	unsigned int mask;
++	unsigned long flags;
++	poll_wait(file, &megasas_poll_wait, wait);
++	spin_lock_irqsave(&poll_aen_lock, flags);
++	if (megasas_poll_wait_aen)
++		mask =   (POLLIN | POLLRDNORM);
++	else
++		mask = 0;
++	spin_unlock_irqrestore(&poll_aen_lock, flags);
++	return mask;
++}
++
++/**
++ * megasas_mgmt_fw_ioctl -	Issues management ioctls to FW
++ * @instance:			Adapter soft state
++ * @argp:			User's ioctl packet
++ */
++static int
++megasas_mgmt_fw_ioctl(struct megasas_instance *instance,
++		      struct megasas_iocpacket __user * user_ioc,
++		      struct megasas_iocpacket *ioc)
++{
++	struct megasas_sge32 *kern_sge32;
++	struct megasas_cmd *cmd;
++	void *kbuff_arr[MAX_IOCTL_SGE];
++	dma_addr_t buf_handle = 0;
++	int error = 0, i;
++	void *sense = NULL;
++	dma_addr_t sense_handle;
++	unsigned long *sense_ptr;
++
++	memset(kbuff_arr, 0, sizeof(kbuff_arr));
++
++	if (ioc->sge_count > MAX_IOCTL_SGE) {
++		printk(KERN_DEBUG "megasas: SGE count [%d] >  max limit [%d]\n",
++		       ioc->sge_count, MAX_IOCTL_SGE);
++		return -EINVAL;
++	}
++
++	cmd = megasas_get_cmd(instance);
++	if (!cmd) {
++		printk(KERN_DEBUG "megasas: Failed to get a cmd packet\n");
++		return -ENOMEM;
++	}
++
++	/*
++	 * User's IOCTL packet has 2 frames (maximum). Copy those two
++	 * frames into our cmd's frames. cmd->frame's context will get
++	 * overwritten when we copy from user's frames. So set that value
++	 * alone separately
++	 */
++	memcpy(cmd->frame, ioc->frame.raw, 2 * MEGAMFI_FRAME_SIZE);
++	cmd->frame->hdr.context = cmd->index;
++	cmd->frame->hdr.pad_0 = 0;
++
++	/*
++	 * The management interface between applications and the fw uses
++	 * MFI frames. E.g, RAID configuration changes, LD property changes
++	 * etc are accomplishes through different kinds of MFI frames. The
++	 * driver needs to care only about substituting user buffers with
++	 * kernel buffers in SGLs. The location of SGL is embedded in the
++	 * struct iocpacket itself.
++	 */
++	kern_sge32 = (struct megasas_sge32 *)
++	    ((unsigned long)cmd->frame + ioc->sgl_off);
++
++	/*
++	 * For each user buffer, create a mirror buffer and copy in
++	 */
++	for (i = 0; i < ioc->sge_count; i++) {
++		if (!ioc->sgl[i].iov_len)
++			continue;
++
++		kbuff_arr[i] = dma_alloc_coherent(&instance->pdev->dev,
++						    ioc->sgl[i].iov_len,
++						    &buf_handle, GFP_KERNEL);
++		if (!kbuff_arr[i]) {
++			printk(KERN_DEBUG "megasas: Failed to alloc "
++			       "kernel SGL buffer for IOCTL \n");
++			error = -ENOMEM;
++			goto out;
++		}
++
++		/*
++		 * We don't change the dma_coherent_mask, so
++		 * pci_alloc_consistent only returns 32bit addresses
++		 */
++		kern_sge32[i].phys_addr = (u32) buf_handle;
++		kern_sge32[i].length = ioc->sgl[i].iov_len;
++
++		/*
++		 * We created a kernel buffer corresponding to the
++		 * user buffer. Now copy in from the user buffer
++		 */
++		if (copy_from_user(kbuff_arr[i], ioc->sgl[i].iov_base,
++				   (u32) (ioc->sgl[i].iov_len))) {
++			error = -EFAULT;
++			goto out;
++		}
++	}
++
++	if (ioc->sense_len) {
++		sense = dma_alloc_coherent(&instance->pdev->dev, ioc->sense_len,
++					     &sense_handle, GFP_KERNEL);
++		if (!sense) {
++			error = -ENOMEM;
++			goto out;
++		}
++
++		sense_ptr =
++		(unsigned long *) ((unsigned long)cmd->frame + ioc->sense_off);
++		*sense_ptr = sense_handle;
++	}
++
++	/*
++	 * Set the sync_cmd flag so that the ISR knows not to complete this
++	 * cmd to the SCSI mid-layer
++	 */
++	cmd->sync_cmd = 1;
++	megasas_issue_blocked_cmd(instance, cmd);
++	cmd->sync_cmd = 0;
++
++	/*
++	 * copy out the kernel buffers to user buffers
++	 */
++	for (i = 0; i < ioc->sge_count; i++) {
++		if (copy_to_user(ioc->sgl[i].iov_base, kbuff_arr[i],
++				 ioc->sgl[i].iov_len)) {
++			error = -EFAULT;
++			goto out;
++		}
++	}
++
++	/*
++	 * copy out the sense
++	 */
++	if (ioc->sense_len) {
++		/*
++		 * sense_ptr points to the location that has the user
++		 * sense buffer address
++		 */
++		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;
++		}
++	}
++
++	/*
++	 * copy the status codes returned by the fw
++	 */
++	if (copy_to_user(&user_ioc->frame.hdr.cmd_status,
++			 &cmd->frame->hdr.cmd_status, sizeof(u8))) {
++		printk(KERN_DEBUG "megasas: Error copying out cmd_status\n");
++		error = -EFAULT;
++	}
++
++      out:
++	if (sense) {
++		dma_free_coherent(&instance->pdev->dev, ioc->sense_len,
++				    sense, sense_handle);
++	}
++
++	for (i = 0; i < ioc->sge_count && kbuff_arr[i]; i++) {
++		dma_free_coherent(&instance->pdev->dev,
++				    kern_sge32[i].length,
++				    kbuff_arr[i], kern_sge32[i].phys_addr);
++	}
++
++	megasas_return_cmd(instance, cmd);
++	return error;
++}
++
++static struct megasas_instance *megasas_lookup_instance(u16 host_no)
++{
++	int i;
++
++	for (i = 0; i < megasas_mgmt_info.max_index; i++) {
++
++		if ((megasas_mgmt_info.instance[i]) &&
++		    (megasas_mgmt_info.instance[i]->host->host_no == host_no))
++			return megasas_mgmt_info.instance[i];
++	}
++
++	return NULL;
++}
++
++static int megasas_mgmt_ioctl_fw(struct file *file, unsigned long arg)
++{
++	struct megasas_iocpacket __user *user_ioc =
++	    (struct megasas_iocpacket __user *)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)
++		return -ENOMEM;
++
++	if (copy_from_user(ioc, user_ioc, sizeof(*ioc))) {
++		error = -EFAULT;
++		goto out_kfree_ioc;
++	}
++
++	instance = megasas_lookup_instance(ioc->host_no);
++	if (!instance) {
++		error = -ENODEV;
++		goto out_kfree_ioc;
++	}
++
++	if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR) {
++		printk(KERN_ERR "Controller in crit error\n");
++		error = -ENODEV;
++		goto out_kfree_ioc;
++	}
++
++	if (instance->unload == 1) {
++		error = -ENODEV;
++		goto out_kfree_ioc;
++	}
++
++	/*
++	 * We will allow only MEGASAS_INT_CMDS number of parallel ioctl cmds
++	 */
++	if (down_interruptible(&instance->ioctl_sem)) {
++		error = -ERESTARTSYS;
++		goto out_kfree_ioc;
++	}
++
++	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(KERN_ERR "megaraid_sas: timed out while"
++			"waiting for HBA to recover\n");
++		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:
++	kfree(ioc);
++	return error;
++}
++
++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 "
++		       "called first\n");
++		return -EINVAL;
++	}
++
++	if (copy_from_user(&aen, (void __user *)arg, sizeof(aen)))
++		return -EFAULT;
++
++	instance = megasas_lookup_instance(aen.host_no);
++
++	if (!instance)
++		return -ENODEV;
++
++	if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR) {
++		return -ENODEV;
++	}
++
++	if (instance->unload == 1) {
++		return -ENODEV;
++	}
++
++	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(KERN_ERR "megaraid_sas: timed out while waiting"
++				"for HBA to recover.\n");
++		return -ENODEV;
++	}
++	spin_unlock_irqrestore(&instance->hba_lock, flags);
++
++	mutex_lock(&instance->aen_mutex);
++	error = megasas_register_aen(instance, aen.seq_num,
++				     aen.class_locale_word);
++	mutex_unlock(&instance->aen_mutex);
++	return error;
++}
++
++/**
++ * megasas_mgmt_ioctl -	char node ioctl entry point
++ */
++static long
++megasas_mgmt_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
++{
++	switch (cmd) {
++	case MEGASAS_IOC_FIRMWARE:
++		return megasas_mgmt_ioctl_fw(file, arg);
++
++	case MEGASAS_IOC_GET_AEN:
++		return megasas_mgmt_ioctl_aen(file, arg);
++	}
++
++	return -ENOTTY;
++}
++
++#ifdef CONFIG_COMPAT
++static int megasas_mgmt_compat_ioctl_fw(struct file *file, unsigned long arg)
++{
++	struct compat_megasas_iocpacket __user *cioc =
++	    (struct compat_megasas_iocpacket __user *)arg;
++	struct megasas_iocpacket __user *ioc =
++	    compat_alloc_user_space(sizeof(struct megasas_iocpacket));
++	int i;
++	int error = 0;
++	compat_uptr_t ptr;
++
++	if (clear_user(ioc, sizeof(*ioc)))
++		return -EFAULT;
++
++	if (copy_in_user(&ioc->host_no, &cioc->host_no, sizeof(u16)) ||
++	    copy_in_user(&ioc->sgl_off, &cioc->sgl_off, sizeof(u32)) ||
++	    copy_in_user(&ioc->sense_off, &cioc->sense_off, sizeof(u32)) ||
++	    copy_in_user(&ioc->sense_len, &cioc->sense_len, sizeof(u32)) ||
++	    copy_in_user(ioc->frame.raw, cioc->frame.raw, 128) ||
++	    copy_in_user(&ioc->sge_count, &cioc->sge_count, sizeof(u32)))
++		return -EFAULT;
++
++	/*
++	 * The sense_ptr is used in megasas_mgmt_fw_ioctl only when
++	 * sense_len is not null, so prepare the 64bit value under
++	 * the same condition.
++	 */
++	if (ioc->sense_len) {
++		void __user **sense_ioc_ptr =
++			(void __user **)(ioc->frame.raw + ioc->sense_off);
++		compat_uptr_t *sense_cioc_ptr =
++			(compat_uptr_t *)(cioc->frame.raw + cioc->sense_off);
++		if (get_user(ptr, sense_cioc_ptr) ||
++		    put_user(compat_ptr(ptr), sense_ioc_ptr))
++			return -EFAULT;
++	}
++
++	for (i = 0; i < MAX_IOCTL_SGE; i++) {
++		if (get_user(ptr, &cioc->sgl[i].iov_base) ||
++		    put_user(compat_ptr(ptr), &ioc->sgl[i].iov_base) ||
++		    copy_in_user(&ioc->sgl[i].iov_len,
++				 &cioc->sgl[i].iov_len, sizeof(compat_size_t)))
++			return -EFAULT;
++	}
++
++	error = megasas_mgmt_ioctl_fw(file, (unsigned long)ioc);
++
++	if (copy_in_user(&cioc->frame.hdr.cmd_status,
++			 &ioc->frame.hdr.cmd_status, sizeof(u8))) {
++		printk(KERN_DEBUG "megasas: error copy_in_user cmd_status\n");
++		return -EFAULT;
++	}
++	return error;
++}
++
++static long
++megasas_mgmt_compat_ioctl(struct file *file, unsigned int cmd,
++			  unsigned long arg)
++{
++	switch (cmd) {
++	case MEGASAS_IOC_FIRMWARE32:
++		return megasas_mgmt_compat_ioctl_fw(file, arg);
++	case MEGASAS_IOC_GET_AEN:
++		return megasas_mgmt_ioctl_aen(file, arg);
++	}
++
++	return -ENOTTY;
++}
++#endif
++
++/*
++ * File operations structure for management interface
++ */
++static const struct file_operations megasas_mgmt_fops = {
++	.owner = THIS_MODULE,
++	.open = megasas_mgmt_open,
++	.fasync = megasas_mgmt_fasync,
++	.unlocked_ioctl = megasas_mgmt_ioctl,
++	.poll = megasas_mgmt_poll,
++#ifdef CONFIG_COMPAT
++	.compat_ioctl = megasas_mgmt_compat_ioctl,
++#endif
++};
++
++/*
++ * PCI hotplug support registration structure
++ */
++static struct pci_driver megasas_pci_driver = {
++
++	.name = "megaraid_sas",
++	.id_table = megasas_pci_table,
++	.probe = megasas_probe_one,
++	.remove = __devexit_p(megasas_detach_one),
++	.suspend = megasas_suspend,
++	.resume = megasas_resume,
++	.shutdown = megasas_shutdown,
++};
++
++/*
++ * Sysfs driver attributes
++ */
++static ssize_t megasas_sysfs_show_version(struct device_driver *dd, char *buf)
++{
++	return snprintf(buf, strlen(MEGASAS_VERSION) + 2, "%s\n",
++			MEGASAS_VERSION);
++}
++
++static DRIVER_ATTR(version, S_IRUGO, megasas_sysfs_show_version, NULL);
++
++static ssize_t
++megasas_sysfs_show_release_date(struct device_driver *dd, char *buf)
++{
++	return snprintf(buf, strlen(MEGASAS_RELDATE) + 2, "%s\n",
++			MEGASAS_RELDATE);
++}
++
++static DRIVER_ATTR(release_date, S_IRUGO, megasas_sysfs_show_release_date,
++		   NULL);
++
++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);
++}
++
++static DRIVER_ATTR(support_poll_for_event, S_IRUGO,
++			megasas_sysfs_show_support_poll_for_event, NULL);
++
++static ssize_t
++megasas_sysfs_show_dbg_lvl(struct device_driver *dd, char *buf)
++{
++	return sprintf(buf, "%u\n", megasas_dbg_lvl);
++}
++
++static ssize_t
++megasas_sysfs_set_dbg_lvl(struct device_driver *dd, const char *buf, size_t count)
++{
++	int retval = count;
++	if(sscanf(buf,"%u",&megasas_dbg_lvl)<1){
++		printk(KERN_ERR "megasas: could not set dbg_lvl\n");
++		retval = -EINVAL;
++	}
++	return retval;
++}
++
++static DRIVER_ATTR(dbg_lvl, S_IRUGO|S_IWUSR, megasas_sysfs_show_dbg_lvl,
++		megasas_sysfs_set_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);
++}
++
++static ssize_t
++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) {
++		printk(KERN_ERR "megasas: could not set poll_mode_io\n");
++		retval = -EINVAL;
++	}
++
++	/*
++	 * Check if poll_mode_io is already set or is same as previous value
++	 */
++	if ((tmp && poll_mode_io) || (tmp == poll_mode_io))
++		goto out;
++
++	if (poll_mode_io) {
++		/*
++		 * Start timers for all adapters
++		 */
++		for (i = 0; i < megasas_mgmt_info.max_index; i++) {
++			instance = megasas_mgmt_info.instance[i];
++			if (instance) {
++				megasas_start_timer(instance,
++					&instance->io_completion_timer,
++					megasas_io_completion_timer,
++					MEGASAS_COMPLETION_TIMER_INTERVAL);
++			}
++		}
++	} else {
++		/*
++		 * Delete timers for all adapters
++		 */
++		for (i = 0; i < megasas_mgmt_info.max_index; i++) {
++			instance = megasas_mgmt_info.instance[i];
++			if (instance)
++				del_timer_sync(&instance->io_completion_timer);
++		}
++	}
++
++out:
++	return retval;
++}
++
++static void
++megasas_aen_polling(struct work_struct *work)
++{
++	struct megasas_aen_event *ev =
++		container_of(work, struct megasas_aen_event, hotplug_work);
++	struct megasas_instance *instance = ev->instance;
++	union megasas_evt_class_locale class_locale;
++	struct  Scsi_Host *host;
++	struct  scsi_device *sdev1;
++	u16     pd_index = 0;
++	u16	ld_index = 0;
++	int     i, j, doscan = 0;
++	u32 seq_num;
++	int error;
++
++	if (!instance) {
++		printk(KERN_ERR "invalid instance!\n");
++		kfree(ev);
++		return;
++	}
++	instance->ev = NULL;
++	host = instance->host;
++	if (instance->evt_detail) {
++
++		switch (instance->evt_detail->code) {
++		case MR_EVT_PD_INSERTED:
++			if (megasas_get_pd_list(instance) == 0) {
++			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;
++
++				sdev1 =
++				scsi_device_lookup(host, i, j, 0);
++
++				if (instance->pd_list[pd_index].driveState
++						== MR_PD_STATE_SYSTEM) {
++						if (!sdev1) {
++						scsi_add_device(host, i, j, 0);
++						}
++
++					if (sdev1)
++						scsi_device_put(sdev1);
++					}
++				}
++			}
++			}
++			doscan = 0;
++			break;
++
++		case MR_EVT_PD_REMOVED:
++			if (megasas_get_pd_list(instance) == 0) {
++			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;
++
++				sdev1 =
++				scsi_device_lookup(host, i, j, 0);
++
++				if (instance->pd_list[pd_index].driveState
++					== MR_PD_STATE_SYSTEM) {
++					if (sdev1) {
++						scsi_device_put(sdev1);
++					}
++				} else {
++					if (sdev1) {
++						scsi_remove_device(sdev1);
++						scsi_device_put(sdev1);
++					}
++				}
++				}
++			}
++			}
++			doscan = 0;
++			break;
++
++		case MR_EVT_LD_OFFLINE:
++		case MR_EVT_LD_DELETED:
++			megasas_get_ld_list(instance);
++			for (i = 0; i < MEGASAS_MAX_LD_CHANNELS; i++) {
++				for (j = 0;
++				j < MEGASAS_MAX_DEV_PER_CHANNEL;
++				j++) {
++
++				ld_index =
++				(i * MEGASAS_MAX_DEV_PER_CHANNEL) + j;
++
++				sdev1 = scsi_device_lookup(host,
++					i + MEGASAS_MAX_LD_CHANNELS,
++					j,
++					0);
++
++				if (instance->ld_ids[ld_index] != 0xff) {
++					if (sdev1) {
++						scsi_device_put(sdev1);
++					}
++				} else {
++					if (sdev1) {
++						scsi_remove_device(sdev1);
++						scsi_device_put(sdev1);
++					}
++				}
++				}
++			}
++			doscan = 0;
++			break;
++		case MR_EVT_LD_CREATED:
++			megasas_get_ld_list(instance);
++			for (i = 0; i < MEGASAS_MAX_LD_CHANNELS; i++) {
++				for (j = 0;
++					j < MEGASAS_MAX_DEV_PER_CHANNEL;
++					j++) {
++					ld_index =
++					(i * MEGASAS_MAX_DEV_PER_CHANNEL) + j;
++
++					sdev1 = scsi_device_lookup(host,
++						i+MEGASAS_MAX_LD_CHANNELS,
++						j, 0);
++
++					if (instance->ld_ids[ld_index] !=
++								0xff) {
++						if (!sdev1) {
++							scsi_add_device(host,
++								i + 2,
++								j, 0);
++						}
++					}
++					if (sdev1) {
++						scsi_device_put(sdev1);
++					}
++				}
++			}
++			doscan = 0;
++			break;
++		case MR_EVT_CTRL_HOST_BUS_SCAN_REQUESTED:
++		case MR_EVT_FOREIGN_CFG_IMPORTED:
++			doscan = 1;
++			break;
++		default:
++			doscan = 0;
++			break;
++		}
++	} else {
++		printk(KERN_ERR "invalid evt_detail!\n");
++		kfree(ev);
++		return;
++	}
++
++	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;
++				sdev1 = scsi_device_lookup(host, i, j, 0);
++				if (instance->pd_list[pd_index].driveState ==
++							MR_PD_STATE_SYSTEM) {
++					if (!sdev1) {
++						scsi_add_device(host, i, j, 0);
++					}
++					if (sdev1)
++						scsi_device_put(sdev1);
++				} else {
++					if (sdev1) {
++						scsi_remove_device(sdev1);
++						scsi_device_put(sdev1);
++					}
++				}
++			}
++		}
++
++		megasas_get_ld_list(instance);
++		for (i = 0; i < MEGASAS_MAX_LD_CHANNELS; i++) {
++			for (j = 0; j < MEGASAS_MAX_DEV_PER_CHANNEL; j++) {
++				ld_index =
++				(i * MEGASAS_MAX_DEV_PER_CHANNEL) + j;
++
++				sdev1 = scsi_device_lookup(host,
++					i+MEGASAS_MAX_LD_CHANNELS, j, 0);
++				if (instance->ld_ids[ld_index] != 0xff) {
++					if (!sdev1) {
++						scsi_add_device(host,
++								i+2,
++								j, 0);
++					} else {
++						scsi_device_put(sdev1);
++					}
++				} else {
++					if (sdev1) {
++						scsi_remove_device(sdev1);
++						scsi_device_put(sdev1);
++					}
++				}
++			}
++		}
++	}
++
++	if ( instance->aen_cmd != NULL ) {
++		kfree(ev);
++		return ;
++	}
++
++	seq_num = instance->evt_detail->seq_num + 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;
++	mutex_lock(&instance->aen_mutex);
++	error = megasas_register_aen(instance, seq_num,
++					class_locale.word);
++	mutex_unlock(&instance->aen_mutex);
++
++	if (error)
++		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
++ */
++static int __init megasas_init(void)
++{
++	int rval;
++
++	/*
++	 * Announce driver version and other information
++	 */
++	printk(KERN_INFO "megasas: %s %s\n", MEGASAS_VERSION,
++	       MEGASAS_EXT_VERSION);
++
++	support_poll_for_event = 2;
++
++	memset(&megasas_mgmt_info, 0, sizeof(megasas_mgmt_info));
++
++	/*
++	 * Register character device node
++	 */
++	rval = register_chrdev(0, "megaraid_sas_ioctl", &megasas_mgmt_fops);
++
++	if (rval < 0) {
++		printk(KERN_DEBUG "megasas: failed to open device node\n");
++		return rval;
++	}
++
++	megasas_mgmt_majorno = rval;
++
++	/*
++	 * Register ourselves as PCI hotplug module
++	 */
++	rval = pci_register_driver(&megasas_pci_driver);
++
++	if (rval) {
++		printk(KERN_DEBUG "megasas: PCI hotplug regisration failed \n");
++		goto err_pcidrv;
++	}
++
++	rval = driver_create_file(&megasas_pci_driver.driver,
++				  &driver_attr_version);
++	if (rval)
++		goto err_dcf_attr_ver;
++	rval = driver_create_file(&megasas_pci_driver.driver,
++				  &driver_attr_release_date);
++	if (rval)
++		goto err_dcf_rel_date;
++
++	rval = driver_create_file(&megasas_pci_driver.driver,
++				&driver_attr_support_poll_for_event);
++	if (rval)
++		goto err_dcf_support_poll_for_event;
++
++	rval = driver_create_file(&megasas_pci_driver.driver,
++				  &driver_attr_dbg_lvl);
++	if (rval)
++		goto err_dcf_dbg_lvl;
++	rval = driver_create_file(&megasas_pci_driver.driver,
++				  &driver_attr_poll_mode_io);
++	if (rval)
++		goto err_dcf_poll_mode_io;
++
++	return rval;
++
++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);
++
++err_dcf_rel_date:
++	driver_remove_file(&megasas_pci_driver.driver, &driver_attr_version);
++err_dcf_attr_ver:
++	pci_unregister_driver(&megasas_pci_driver);
++err_pcidrv:
++	unregister_chrdev(megasas_mgmt_majorno, "megaraid_sas_ioctl");
++	return rval;
++}
++
++/**
++ * megasas_exit - Driver unload entry point
++ */
++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_dbg_lvl);
++	driver_remove_file(&megasas_pci_driver.driver,
++			   &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");
++}
++
++module_init(megasas_init);
++module_exit(megasas_exit);
+-- 
+1.8.0
+
+

Added: dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0013-megaraid_sas-add-msi-x-support-and-msix_disable-module-parameter.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0013-megaraid_sas-add-msi-x-support-and-msix_disable-module-parameter.patch	Sun Dec 16 23:23:22 2012	(r19615)
@@ -0,0 +1,129 @@
+From cd97f4f1a3c388667115057585c95c16c17321cd Mon Sep 17 00:00:00 2001
+From: adam radford <aradford at gmail.com>
+Date: Tue, 21 Dec 2010 10:17:40 -0800
+Subject: [PATCH 13/53] [SCSI] megaraid_sas: Add MSI-X support and  msix_disable module parameter
+
+commit 80d9da98b4034edd31f6bacdb96c7489c4460173 upstream.
+
+This patch adds MSI-X support and 'msix_disable' module parameter to
+the megaraid_sas driver.
+
+Signed-off-by: Adam Radford <aradford at gmail.com>
+Signed-off-by: James Bottomley <James.Bottomley at suse.de>
+Signed-off-by: Jonathan Nieder <jrnieder at gmail.com>
+---
+ drivers/scsi/megaraid/megaraid_sas.h      |  3 +++
+ drivers/scsi/megaraid/megaraid_sas_base.c | 41 +++++++++++++++++++++++++------
+ 2 files changed, 37 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h
+index a231aa811e56..4a6253d92b7e 100644
+--- a/drivers/scsi/megaraid/megaraid_sas.h
++++ b/drivers/scsi/megaraid/megaraid_sas.h
+@@ -1319,6 +1319,9 @@ struct megasas_instance {
+ 
+ 	struct timer_list io_completion_timer;
+ 	struct list_head internal_reset_pending_q;
++
++	u8	msi_flag;
++	struct msix_entry msixentry;
+ };
+ 
+ enum {
+diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c
+index a18ae3cba87e..e5738869272c 100644
+--- a/drivers/scsi/megaraid/megaraid_sas_base.c
++++ b/drivers/scsi/megaraid/megaraid_sas_base.c
+@@ -56,6 +56,10 @@ module_param_named(poll_mode_io, poll_mode_io, int, 0);
+ MODULE_PARM_DESC(poll_mode_io,
+ 	"Complete cmds from IO path, (default=0)");
+ 
++static int msix_disable;
++module_param(msix_disable, int, S_IRUGO);
++MODULE_PARM_DESC(msix_disable, "Disable MSI-X interrupt handling. Default: 0");
++
+ MODULE_LICENSE("GPL");
+ MODULE_VERSION(MEGASAS_VERSION);
+ MODULE_AUTHOR("megaraidlinux at lsi.com");
+@@ -3676,10 +3680,20 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ 	if (megasas_init_mfi(instance))
+ 		goto fail_init_mfi;
+ 
++	/* Try to enable MSI-X */
++	if ((instance->pdev->device != PCI_DEVICE_ID_LSI_SAS1078R) &&
++	    (instance->pdev->device != PCI_DEVICE_ID_LSI_SAS1078DE) &&
++	    (instance->pdev->device != PCI_DEVICE_ID_LSI_VERDE_ZCR) &&
++	    !msix_disable && !pci_enable_msix(instance->pdev,
++					      &instance->msixentry, 1))
++		instance->msi_flag = 1;
++
+ 	/*
+ 	 * Register IRQ
+ 	 */
+-	if (request_irq(pdev->irq, megasas_isr, IRQF_SHARED, "megasas", instance)) {
++	if (request_irq(instance->msi_flag ? instance->msixentry.vector :
++			pdev->irq, megasas_isr,
++			IRQF_SHARED, "megasas", instance)) {
+ 		printk(KERN_DEBUG "megasas: Failed to register IRQ\n");
+ 		goto fail_irq;
+ 	}
+@@ -3724,8 +3738,10 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ 
+ 	pci_set_drvdata(pdev, NULL);
+ 	instance->instancet->disable_intr(instance->reg_set);
+-	free_irq(instance->pdev->irq, instance);
+-
++	free_irq(instance->msi_flag ? instance->msixentry.vector :
++		 instance->pdev->irq, instance);
++	if (instance->msi_flag)
++		pci_disable_msix(instance->pdev);
+ 	megasas_release_mfi(instance);
+ 
+       fail_irq:
+@@ -3864,7 +3880,10 @@ megasas_suspend(struct pci_dev *pdev, pm_message_t state)
+ 
+ 	pci_set_drvdata(instance->pdev, instance);
+ 	instance->instancet->disable_intr(instance->reg_set);
+-	free_irq(instance->pdev->irq, instance);
++	free_irq(instance->msi_flag ? instance->msixentry.vector :
++		 instance->pdev->irq, instance);
++	if (instance->msi_flag)
++		pci_disable_msix(instance->pdev);
+ 
+ 	pci_save_state(pdev);
+ 	pci_disable_device(pdev);
+@@ -3927,11 +3946,16 @@ megasas_resume(struct pci_dev *pdev)
+ 	tasklet_init(&instance->isr_tasklet, megasas_complete_cmd_dpc,
+ 			(unsigned long)instance);
+ 
++	/* Now re-enable MSI-X */
++	if (instance->msi_flag)
++		pci_enable_msix(instance->pdev, &instance->msixentry, 1);
++
+ 	/*
+ 	 * Register IRQ
+ 	 */
+-	if (request_irq(pdev->irq, megasas_isr, IRQF_SHARED,
+-		"megasas", instance)) {
++	if (request_irq(instance->msi_flag ? instance->msixentry.vector :
++			pdev->irq, megasas_isr,
++			IRQF_SHARED, "megasas", instance)) {
+ 		printk(KERN_ERR "megasas: Failed to register IRQ\n");
+ 		goto fail_irq;
+ 	}
+@@ -4029,7 +4053,10 @@ static void __devexit megasas_detach_one(struct pci_dev *pdev)
+ 
+ 	instance->instancet->disable_intr(instance->reg_set);
+ 
+-	free_irq(instance->pdev->irq, instance);
++	free_irq(instance->msi_flag ? instance->msixentry.vector :
++		 instance->pdev->irq, instance);
++	if (instance->msi_flag)
++		pci_disable_msix(instance->pdev);
+ 
+ 	megasas_release_mfi(instance);
+ 
+-- 
+1.8.0
+
+

Added: dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0014-megaraid_sas-make-driver-pci-legacy-i-o-port-free-driver.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0014-megaraid_sas-make-driver-pci-legacy-i-o-port-free-driver.patch	Sun Dec 16 23:23:22 2012	(r19615)
@@ -0,0 +1,94 @@
+From 473ac59f82dc5fdf24c06fee2b4b0be1c89fb958 Mon Sep 17 00:00:00 2001
+From: Noriyuki Fujii <n-fujii at np.css.fujitsu.com>
+Date: Fri, 20 Nov 2009 16:27:20 +0900
+Subject: [PATCH 14/53] [SCSI] megaraid_sas: make driver PCI legacy I/O port  free driver
+
+commit aeab3fd7b865bc4086a80a83cfdd67dded3b41a0 upstream.
+
+On the large servers, I/O port resource may not be assigned to all
+the PCI devices since it is limited (to 64KB on Intel Architecture[1])
+and it may also be fragmented (I/O base register of PCI-to-PCI bridge
+will usually be aligned to a 4KB boundary[2]).
+If no I/O port resource is assigned to devices, those devices do not
+work.
+
+[1] Some machines support 64KB I/O port space per PCI segment.
+[2] Some P2P bridges support optional 1KB aligned I/O base.
+
+Therefore, I made a patch for MegaRAID SAS driver to make PCI legacy
+I/O port free.  I have also tested the patch and it had no problem.
+
+The way to make PCI legacy I/O port free is the same as Fusion-MPT
+driver's and it has been merged into 2.6.30.4.
+
+This has already been fixed in e1000 and lpfc.
+
+As a result of the above, the driver can handle its device even when
+there are a huge number of PCI devices being used on the system and no
+I/O port region assigned to the device.
+
+Signed-off-by: Noriyuki Fujii <n-fujii at np.css.fujitsu.com>
+Acked-by: "Yang, Bo" <Bo.Yang at lsi.com>
+Signed-off-by: James Bottomley <James.Bottomley at suse.de>
+Signed-off-by: Jonathan Nieder <jrnieder at gmail.com>
+---
+ drivers/scsi/megaraid/megaraid_sas_base.c | 14 +++++++++-----
+ 1 file changed, 9 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c
+index e5738869272c..58442f4b3ae1 100644
+--- a/drivers/scsi/megaraid/megaraid_sas_base.c
++++ b/drivers/scsi/megaraid/megaraid_sas_base.c
+@@ -3088,7 +3088,9 @@ static int megasas_init_mfi(struct megasas_instance *instance)
+ 		instance->base_addr = pci_resource_start(instance->pdev, 0);
+ 	}
+ 
+-	if (pci_request_regions(instance->pdev, "megasas: LSI")) {
++	if (pci_request_selected_regions(instance->pdev,
++		pci_select_bars(instance->pdev, IORESOURCE_MEM),
++		"megasas: LSI")) {
+ 		printk(KERN_DEBUG "megasas: IO memory region busy!\n");
+ 		return -EBUSY;
+ 	}
+@@ -3249,7 +3251,8 @@ static int megasas_init_mfi(struct megasas_instance *instance)
+ 	iounmap(instance->reg_set);
+ 
+       fail_ioremap:
+-	pci_release_regions(instance->pdev);
++	pci_release_selected_regions(instance->pdev,
++		pci_select_bars(instance->pdev, IORESOURCE_MEM));
+ 
+ 	return -EINVAL;
+ }
+@@ -3269,7 +3272,8 @@ static void megasas_release_mfi(struct megasas_instance *instance)
+ 
+ 	iounmap(instance->reg_set);
+ 
+-	pci_release_regions(instance->pdev);
++	pci_release_selected_regions(instance->pdev,
++		pci_select_bars(instance->pdev, IORESOURCE_MEM));
+ }
+ 
+ /**
+@@ -3579,7 +3583,7 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ 	/*
+ 	 * PCI prepping: enable device set bus mastering and dma mask
+ 	 */
+-	rval = pci_enable_device(pdev);
++	rval = pci_enable_device_mem(pdev);
+ 
+ 	if (rval) {
+ 		return rval;
+@@ -3913,7 +3917,7 @@ megasas_resume(struct pci_dev *pdev)
+ 	/*
+ 	 * PCI prepping: enable device set bus mastering and dma mask
+ 	 */
+-	rval = pci_enable_device(pdev);
++	rval = pci_enable_device_mem(pdev);
+ 
+ 	if (rval) {
+ 		printk(KERN_ERR "megasas: Enable device failed\n");
+-- 
+1.8.0
+
+

Added: dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0015-megaraid_sas-use-lowest-memory-bar-for-sr-iov-vf-support.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0015-megaraid_sas-use-lowest-memory-bar-for-sr-iov-vf-support.patch	Sun Dec 16 23:23:22 2012	(r19615)
@@ -0,0 +1,88 @@
+From a80b25ee54c8660c6e2486d34726a721c32be57c Mon Sep 17 00:00:00 2001
+From: adam radford <aradford at gmail.com>
+Date: Tue, 14 Dec 2010 18:56:07 -0800
+Subject: [PATCH 15/53] [SCSI] megaraid_sas: Use lowest memory bar for SR-IOV  VF support
+
+commit b6d5d8808b4c563a56414a4c4c6d652b5f87c088 upstream.
+
+The following patch modifies the megaraid_sas driver to select the
+lowest memory bar available so the driver will work in SR-IOV VF
+environments where the memory bar mapping changes.
+
+Signed-off-by: Adam Radford <aradford at gmail.com>
+Signed-off-by: James Bottomley <James.Bottomley at suse.de>
+Signed-off-by: Jonathan Nieder <jrnieder at gmail.com>
+---
+ drivers/scsi/megaraid/megaraid_sas.h      |  1 +
+ drivers/scsi/megaraid/megaraid_sas_base.c | 27 +++++++++------------------
+ 2 files changed, 10 insertions(+), 18 deletions(-)
+
+diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h
+index 4a6253d92b7e..83c6e3aa6f43 100644
+--- a/drivers/scsi/megaraid/megaraid_sas.h
++++ b/drivers/scsi/megaraid/megaraid_sas.h
+@@ -1322,6 +1322,7 @@ struct megasas_instance {
+ 
+ 	u8	msi_flag;
+ 	struct msix_entry msixentry;
++	unsigned long bar;
+ };
+ 
+ enum {
+diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c
+index 58442f4b3ae1..e019480cd64b 100644
+--- a/drivers/scsi/megaraid/megaraid_sas_base.c
++++ b/drivers/scsi/megaraid/megaraid_sas_base.c
+@@ -3076,21 +3076,14 @@ static int megasas_init_mfi(struct megasas_instance *instance)
+ 	u32 tmp_sectors;
+ 	struct megasas_register_set __iomem *reg_set;
+ 	struct megasas_ctrl_info *ctrl_info;
+-	/*
+-	 * Map the message registers
+-	 */
+-	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->base_addr = pci_resource_start(instance->pdev, 1);
+-	} else {
+-		instance->base_addr = pci_resource_start(instance->pdev, 0);
+-	}
++	unsigned long bar_list;
+ 
+-	if (pci_request_selected_regions(instance->pdev,
+-		pci_select_bars(instance->pdev, IORESOURCE_MEM),
+-		"megasas: LSI")) {
++	/* Find first memory bar */
++	bar_list = pci_select_bars(instance->pdev, IORESOURCE_MEM);
++	instance->bar = find_first_bit(&bar_list, sizeof(unsigned long));
++	instance->base_addr = pci_resource_start(instance->pdev, instance->bar);
++	if (pci_request_selected_regions(instance->pdev, instance->bar,
++					 "megasas: LSI")) {
+ 		printk(KERN_DEBUG "megasas: IO memory region busy!\n");
+ 		return -EBUSY;
+ 	}
+@@ -3251,8 +3244,7 @@ static int megasas_init_mfi(struct megasas_instance *instance)
+ 	iounmap(instance->reg_set);
+ 
+       fail_ioremap:
+-	pci_release_selected_regions(instance->pdev,
+-		pci_select_bars(instance->pdev, IORESOURCE_MEM));
++	pci_release_selected_regions(instance->pdev, instance->bar);
+ 
+ 	return -EINVAL;
+ }
+@@ -3272,8 +3264,7 @@ static void megasas_release_mfi(struct megasas_instance *instance)
+ 
+ 	iounmap(instance->reg_set);
+ 
+-	pci_release_selected_regions(instance->pdev,
+-		pci_select_bars(instance->pdev, IORESOURCE_MEM));
++	pci_release_selected_regions(instance->pdev, instance->bar);
+ }
+ 
+ /**
+-- 
+1.8.0
+
+

Added: dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0016-megaraid_sas-add-struct-megasas_instance_template-changes.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0016-megaraid_sas-add-struct-megasas_instance_template-changes.patch	Sun Dec 16 23:23:22 2012	(r19615)
@@ -0,0 +1,454 @@
+From b6c1cb051e831fe75110c9e6055b46b45e57f058 Mon Sep 17 00:00:00 2001
+From: adam radford <aradford at gmail.com>
+Date: Tue, 21 Dec 2010 10:23:23 -0800
+Subject: [PATCH 16/53] [SCSI] megaraid_sas: Add struct  megasas_instance_template changes
+
+commit cd50ba8ede5cd3c4606a8e5d163913da5ff36ad7 upstream.
+
+The following patch adds struct megasas_instance_template changes to
+the megaraid_sas driver, and changes all code to use the new instance
+entries:
+
+   irqreturn_t (*service_isr )(int irq, void *devp);
+   void (*tasklet)(unsigned long);
+   u32 (*init_adapter)(struct megasas_instance *);
+   u32 (*build_and_issue_cmd) (struct megasas_instance *, struct scsi_cmnd *);
+   void (*issue_dcmd) (struct megasas_instance *instance,
+                              struct megasas_cmd *cmd);
+
+Signed-off-by: Adam Radford <aradford at gmail.com>
+Signed-off-by: James Bottomley <James.Bottomley at suse.de>
+Signed-off-by: Jonathan Nieder <jrnieder at gmail.com>
+---
+ drivers/scsi/megaraid/megaraid_sas.h      |   7 +
+ drivers/scsi/megaraid/megaraid_sas_base.c | 278 +++++++++++++++++++-----------
+ 2 files changed, 180 insertions(+), 105 deletions(-)
+
+diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h
+index 83c6e3aa6f43..0663f2efda12 100644
+--- a/drivers/scsi/megaraid/megaraid_sas.h
++++ b/drivers/scsi/megaraid/megaraid_sas.h
+@@ -1348,6 +1348,13 @@ struct megasas_instance_template {
+ 		struct megasas_register_set __iomem *);
+ 	int (*check_reset)(struct megasas_instance *, \
+ 		struct megasas_register_set __iomem *);
++	irqreturn_t (*service_isr)(int irq, void *devp);
++	void (*tasklet)(unsigned long);
++	u32 (*init_adapter)(struct megasas_instance *);
++	u32 (*build_and_issue_cmd) (struct megasas_instance *,
++				    struct scsi_cmnd *);
++	void (*issue_dcmd) (struct megasas_instance *instance,
++			    struct megasas_cmd *cmd);
+ };
+ 
+ #define MEGASAS_IS_LOGICAL(scp)						\
+diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c
+index e019480cd64b..7f2b199b82c2 100644
+--- a/drivers/scsi/megaraid/megaraid_sas_base.c
++++ b/drivers/scsi/megaraid/megaraid_sas_base.c
+@@ -114,6 +114,20 @@ spinlock_t poll_aen_lock;
+ static void
+ megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd,
+ 		     u8 alt_status);
++static irqreturn_t megasas_isr(int irq, void *devp);
++static u32
++megasas_init_adapter_mfi(struct megasas_instance *instance);
++u32
++megasas_build_and_issue_cmd(struct megasas_instance *instance,
++			    struct scsi_cmnd *scmd);
++static void megasas_complete_cmd_dpc(unsigned long instance_addr);
++
++void
++megasas_issue_dcmd(struct megasas_instance *instance, struct megasas_cmd *cmd)
++{
++	instance->instancet->fire_cmd(instance,
++		cmd->frame_phys_addr, 0, instance->reg_set);
++}
+ 
+ /**
+  * megasas_get_cmd -	Get a command from the free pool
+@@ -317,6 +331,11 @@ static struct megasas_instance_template megasas_instance_template_xscale = {
+ 	.read_fw_status_reg = megasas_read_fw_status_reg_xscale,
+ 	.adp_reset = megasas_adp_reset_xscale,
+ 	.check_reset = megasas_check_reset_xscale,
++	.service_isr = megasas_isr,
++	.tasklet = megasas_complete_cmd_dpc,
++	.init_adapter = megasas_init_adapter_mfi,
++	.build_and_issue_cmd = megasas_build_and_issue_cmd,
++	.issue_dcmd = megasas_issue_dcmd,
+ };
+ 
+ /**
+@@ -443,6 +462,11 @@ static struct megasas_instance_template megasas_instance_template_ppc = {
+ 	.read_fw_status_reg = megasas_read_fw_status_reg_ppc,
+ 	.adp_reset = megasas_adp_reset_ppc,
+ 	.check_reset = megasas_check_reset_ppc,
++	.service_isr = megasas_isr,
++	.tasklet = megasas_complete_cmd_dpc,
++	.init_adapter = megasas_init_adapter_mfi,
++	.build_and_issue_cmd = megasas_build_and_issue_cmd,
++	.issue_dcmd = megasas_issue_dcmd,
+ };
+ 
+ /**
+@@ -564,6 +588,11 @@ static struct megasas_instance_template megasas_instance_template_skinny = {
+ 	.read_fw_status_reg = megasas_read_fw_status_reg_skinny,
+ 	.adp_reset = megasas_adp_reset_skinny,
+ 	.check_reset = megasas_check_reset_skinny,
++	.service_isr = megasas_isr,
++	.tasklet = megasas_complete_cmd_dpc,
++	.init_adapter = megasas_init_adapter_mfi,
++	.build_and_issue_cmd = megasas_build_and_issue_cmd,
++	.issue_dcmd = megasas_issue_dcmd,
+ };
+ 
+ 
+@@ -734,6 +763,11 @@ static struct megasas_instance_template megasas_instance_template_gen2 = {
+ 	.read_fw_status_reg = megasas_read_fw_status_reg_gen2,
+ 	.adp_reset = megasas_adp_reset_gen2,
+ 	.check_reset = megasas_check_reset_gen2,
++	.service_isr = megasas_isr,
++	.tasklet = megasas_complete_cmd_dpc,
++	.init_adapter = megasas_init_adapter_mfi,
++	.build_and_issue_cmd = megasas_build_and_issue_cmd,
++	.issue_dcmd = megasas_issue_dcmd,
+ };
+ 
+ /**
+@@ -1305,6 +1339,51 @@ megasas_dump_pending_frames(struct megasas_instance *instance)
+ 	printk(KERN_ERR "megasas[%d]: Dumping Done.\n\n",instance->host->host_no);
+ }
+ 
++u32
++megasas_build_and_issue_cmd(struct megasas_instance *instance,
++			    struct scsi_cmnd *scmd)
++{
++	struct megasas_cmd *cmd;
++	u32 frame_count;
++
++	cmd = megasas_get_cmd(instance);
++	if (!cmd)
++		return SCSI_MLQUEUE_HOST_BUSY;
++
++	/*
++	 * Logical drive command
++	 */
++	if (megasas_is_ldio(scmd))
++		frame_count = megasas_build_ldio(instance, scmd, cmd);
++	else
++		frame_count = megasas_build_dcdb(instance, scmd, cmd);
++
++	if (!frame_count)
++		goto out_return_cmd;
++
++	cmd->scmd = scmd;
++	scmd->SCp.ptr = (char *)cmd;
++
++	/*
++	 * Issue the command to the FW
++	 */
++	atomic_inc(&instance->fw_outstanding);
++
++	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
++	 */
++	if (poll_mode_io && atomic_read(&instance->fw_outstanding))
++		tasklet_schedule(&instance->isr_tasklet);
++
++	return 0;
++out_return_cmd:
++	megasas_return_cmd(instance, cmd);
++	return 1;
++}
++
++
+ /**
+  * megasas_queue_command -	Queue entry point
+  * @scmd:			SCSI command to be queued
+@@ -1313,8 +1392,6 @@ megasas_dump_pending_frames(struct megasas_instance *instance)
+ static int
+ 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;
+ 
+@@ -1353,42 +1430,13 @@ megasas_queue_command(struct scsi_cmnd *scmd, void (*done) (struct scsi_cmnd *))
+ 		break;
+ 	}
+ 
+-	cmd = megasas_get_cmd(instance);
+-	if (!cmd)
++	if (instance->instancet->build_and_issue_cmd(instance, scmd)) {
++		printk(KERN_ERR "megasas: Err returned from build_and_issue_cmd\n");
+ 		return SCSI_MLQUEUE_HOST_BUSY;
+-
+-	/*
+-	 * Logical drive command
+-	 */
+-	if (megasas_is_ldio(scmd))
+-		frame_count = megasas_build_ldio(instance, scmd, cmd);
+-	else
+-		frame_count = megasas_build_dcdb(instance, scmd, cmd);
+-
+-	if (!frame_count)
+-		goto out_return_cmd;
+-
+-	cmd->scmd = scmd;
+-	scmd->SCp.ptr = (char *)cmd;
+-
+-	/*
+-	 * Issue the command to the FW
+-	 */
+-	atomic_inc(&instance->fw_outstanding);
+-
+-	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
+-	 */
+-	if (poll_mode_io && atomic_read(&instance->fw_outstanding))
+-		tasklet_schedule(&instance->isr_tasklet);
+-
++	}
+ 
+ 	return 0;
+ 
+- out_return_cmd:
+-	megasas_return_cmd(instance, cmd);
+  out_done:
+ 	done(scmd);
+ 	return 0;
+@@ -3061,69 +3109,15 @@ megasas_io_completion_timer(unsigned long instance_addr)
+ 			jiffies + MEGASAS_COMPLETION_TIMER_INTERVAL);
+ }
+ 
+-/**
+- * megasas_init_mfi -	Initializes the FW
+- * @instance:		Adapter soft state
+- *
+- * This is the main function for initializing MFI firmware.
+- */
+-static int megasas_init_mfi(struct megasas_instance *instance)
++static u32
++megasas_init_adapter_mfi(struct megasas_instance *instance)
+ {
++	struct megasas_register_set __iomem *reg_set;
+ 	u32 context_sz;
+ 	u32 reply_q_sz;
+-	u32 max_sectors_1;
+-	u32 max_sectors_2;
+-	u32 tmp_sectors;
+-	struct megasas_register_set __iomem *reg_set;
+-	struct megasas_ctrl_info *ctrl_info;
+-	unsigned long bar_list;
+-
+-	/* Find first memory bar */
+-	bar_list = pci_select_bars(instance->pdev, IORESOURCE_MEM);
+-	instance->bar = find_first_bit(&bar_list, sizeof(unsigned long));
+-	instance->base_addr = pci_resource_start(instance->pdev, instance->bar);
+-	if (pci_request_selected_regions(instance->pdev, instance->bar,
+-					 "megasas: LSI")) {
+-		printk(KERN_DEBUG "megasas: IO memory region busy!\n");
+-		return -EBUSY;
+-	}
+-
+-	instance->reg_set = ioremap_nocache(instance->base_addr, 8192);
+-
+-	if (!instance->reg_set) {
+-		printk(KERN_DEBUG "megasas: Failed to map IO mem\n");
+-		goto fail_ioremap;
+-	}
+ 
+ 	reg_set = instance->reg_set;
+ 
+-	switch(instance->pdev->device)
+-	{
+-		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:
+-		case PCI_DEVICE_ID_LSI_SAS0079GEN2:
+-			instance->instancet = &megasas_instance_template_gen2;
+-			break;
+-		case PCI_DEVICE_ID_LSI_SAS0073SKINNY:
+-		case PCI_DEVICE_ID_LSI_SAS0071SKINNY:
+-			instance->instancet = &megasas_instance_template_skinny;
+-			break;
+-		case PCI_DEVICE_ID_LSI_SAS1064R:
+-		case PCI_DEVICE_ID_DELL_PERC5:
+-		default:
+-			instance->instancet = &megasas_instance_template_xscale;
+-			break;
+-	}
+-
+-	/*
+-	 * We expect the FW state to be READY
+-	 */
+-	if (megasas_transition_to_ready(instance))
+-		goto fail_ready_state;
+-
+ 	/*
+ 	 * Get various operational parameters from status register
+ 	 */
+@@ -3177,6 +3171,87 @@ static int megasas_init_mfi(struct megasas_instance *instance)
+ 	if (instance->fw_support_ieee)
+ 		instance->flag_ieee = 1;
+ 
++	return 0;
++
++fail_fw_init:
++
++	pci_free_consistent(instance->pdev, reply_q_sz,
++			    instance->reply_queue, instance->reply_queue_h);
++fail_reply_queue:
++	megasas_free_cmds(instance);
++
++fail_alloc_cmds:
++	iounmap(instance->reg_set);
++	return 1;
++}
++
++/**
++ * megasas_init_fw -	Initializes the FW
++ * @instance:		Adapter soft state
++ *
++ * This is the main function for initializing firmware
++ */
++
++static int megasas_init_fw(struct megasas_instance *instance)
++{
++	u32 max_sectors_1;
++	u32 max_sectors_2;
++	u32 tmp_sectors;
++	struct megasas_register_set __iomem *reg_set;
++	struct megasas_ctrl_info *ctrl_info;
++	unsigned long bar_list;
++
++	/* Find first memory bar */
++	bar_list = pci_select_bars(instance->pdev, IORESOURCE_MEM);
++	instance->bar = find_first_bit(&bar_list, sizeof(unsigned long));
++	instance->base_addr = pci_resource_start(instance->pdev, instance->bar);
++	if (pci_request_selected_regions(instance->pdev, instance->bar,
++					 "megasas: LSI")) {
++		printk(KERN_DEBUG "megasas: IO memory region busy!\n");
++		return -EBUSY;
++	}
++
++	instance->reg_set = ioremap_nocache(instance->base_addr, 8192);
++
++	if (!instance->reg_set) {
++		printk(KERN_DEBUG "megasas: Failed to map IO mem\n");
++		goto fail_ioremap;
++	}
++
++	reg_set = instance->reg_set;
++
++	switch (instance->pdev->device) {
++	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:
++	case PCI_DEVICE_ID_LSI_SAS0079GEN2:
++		instance->instancet = &megasas_instance_template_gen2;
++		break;
++	case PCI_DEVICE_ID_LSI_SAS0073SKINNY:
++	case PCI_DEVICE_ID_LSI_SAS0071SKINNY:
++		instance->instancet = &megasas_instance_template_skinny;
++		break;
++	case PCI_DEVICE_ID_LSI_SAS1064R:
++	case PCI_DEVICE_ID_DELL_PERC5:
++	default:
++		instance->instancet = &megasas_instance_template_xscale;
++		break;
++	}
++
++	/*
++	 * We expect the FW state to be READY
++	 */
++	if (megasas_transition_to_ready(instance))
++		goto fail_ready_state;
++
++	/* Get operational params, sge flags, send init cmd to controller */
++	if (instance->instancet->init_adapter(instance))
++		return -ENODEV;
++
++	printk(KERN_ERR "megasas: INIT adapter done\n");
++
+ 	/** for passthrough
+ 	* the following function will get the PD LIST.
+ 	*/
+@@ -3232,15 +3307,7 @@ static int megasas_init_mfi(struct megasas_instance *instance)
+ 				MEGASAS_COMPLETION_TIMER_INTERVAL);
+ 	return 0;
+ 
+-      fail_fw_init:
+-
+-	pci_free_consistent(instance->pdev, reply_q_sz,
+-			    instance->reply_queue, instance->reply_queue_h);
+-      fail_reply_queue:
+-	megasas_free_cmds(instance);
+-
+-      fail_alloc_cmds:
+-      fail_ready_state:
++fail_ready_state:
+ 	iounmap(instance->reg_set);
+ 
+       fail_ioremap:
+@@ -3672,7 +3739,7 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ 	/*
+ 	 * Initialize MFI Firmware
+ 	 */
+-	if (megasas_init_mfi(instance))
++	if (megasas_init_fw(instance))
+ 		goto fail_init_mfi;
+ 
+ 	/* Try to enable MSI-X */
+@@ -3687,7 +3754,7 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ 	 * Register IRQ
+ 	 */
+ 	if (request_irq(instance->msi_flag ? instance->msixentry.vector :
+-			pdev->irq, megasas_isr,
++			pdev->irq, instance->instancet->service_isr,
+ 			IRQF_SHARED, "megasas", instance)) {
+ 		printk(KERN_DEBUG "megasas: Failed to register IRQ\n");
+ 		goto fail_irq;
+@@ -3737,7 +3804,6 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ 		 instance->pdev->irq, instance);
+ 	if (instance->msi_flag)
+ 		pci_disable_msix(instance->pdev);
+-	megasas_release_mfi(instance);
+ 
+       fail_irq:
+       fail_init_mfi:
+@@ -3747,9 +3813,11 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ 				    instance->evt_detail,
+ 				    instance->evt_detail_h);
+ 
+-	if (instance->producer)
++	if (instance->producer) {
+ 		pci_free_consistent(pdev, sizeof(u32), instance->producer,
+ 				    instance->producer_h);
++		megasas_release_mfi(instance);
++	}
+ 	if (instance->consumer)
+ 		pci_free_consistent(pdev, sizeof(u32), instance->consumer,
+ 				    instance->consumer_h);
+@@ -3949,7 +4017,7 @@ megasas_resume(struct pci_dev *pdev)
+ 	 * Register IRQ
+ 	 */
+ 	if (request_irq(instance->msi_flag ? instance->msixentry.vector :
+-			pdev->irq, megasas_isr,
++			pdev->irq, instance->instancet->service_isr,
+ 			IRQF_SHARED, "megasas", instance)) {
+ 		printk(KERN_ERR "megasas: Failed to register IRQ\n");
+ 		goto fail_irq;
+-- 
+1.8.0
+
+

Added: dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0017-megaraid_sas-add-9565-9285-specific-code.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0017-megaraid_sas-add-9565-9285-specific-code.patch	Sun Dec 16 23:23:22 2012	(r19615)
@@ -0,0 +1,4352 @@
+From 8638045828d99252418c6dc7972a89fc5185242c Mon Sep 17 00:00:00 2001
+From: adam radford <aradford at gmail.com>
+Date: Tue, 21 Dec 2010 13:34:31 -0800
+Subject: [PATCH 17/53] [SCSI] megaraid_sas: Add 9565/9285 specific code
+
+commit 9c915a8c99bce637226aa09cb05fc18486b229cb upstream.
+
+This patch adds MegaRAID 9265/9285 (Device id 0x5b) specific code
+
+Signed-off-by: Adam Radford <aradford at gmail.com>
+Signed-off-by: James Bottomley <James.Bottomley at suse.de>
+Signed-off-by: Jonathan Nieder <jrnieder at gmail.com>
+---
+ drivers/scsi/megaraid/Makefile              |    3 +-
+ drivers/scsi/megaraid/megaraid_sas.h        |   32 +-
+ drivers/scsi/megaraid/megaraid_sas_base.c   |  362 +++--
+ drivers/scsi/megaraid/megaraid_sas_fp.c     |  516 ++++++
+ drivers/scsi/megaraid/megaraid_sas_fusion.c | 2248 +++++++++++++++++++++++++++
+ drivers/scsi/megaraid/megaraid_sas_fusion.h |  695 +++++++++
+ 6 files changed, 3748 insertions(+), 108 deletions(-)
+ create mode 100644 drivers/scsi/megaraid/megaraid_sas_fp.c
+ create mode 100644 drivers/scsi/megaraid/megaraid_sas_fusion.c
+ create mode 100644 drivers/scsi/megaraid/megaraid_sas_fusion.h
+
+diff --git a/drivers/scsi/megaraid/Makefile b/drivers/scsi/megaraid/Makefile
+index 6613a2ceea03..5826ed509e3e 100644
+--- a/drivers/scsi/megaraid/Makefile
++++ b/drivers/scsi/megaraid/Makefile
+@@ -1,4 +1,5 @@
+ obj-$(CONFIG_MEGARAID_MM)	+= megaraid_mm.o
+ obj-$(CONFIG_MEGARAID_MAILBOX)	+= megaraid_mbox.o
+ obj-$(CONFIG_MEGARAID_SAS)	+= megaraid_sas.o
+-megaraid_sas-objs := megaraid_sas_base.o
++megaraid_sas-objs := megaraid_sas_base.o megaraid_sas_fusion.o \
++	megaraid_sas_fp.o
+diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h
+index 0663f2efda12..887f33ebcf21 100644
+--- a/drivers/scsi/megaraid/megaraid_sas.h
++++ b/drivers/scsi/megaraid/megaraid_sas.h
+@@ -32,6 +32,7 @@
+ #define	PCI_DEVICE_ID_LSI_SAS0079GEN2		0x0079
+ #define	PCI_DEVICE_ID_LSI_SAS0073SKINNY		0x0073
+ #define	PCI_DEVICE_ID_LSI_SAS0071SKINNY		0x0071
++#define	PCI_DEVICE_ID_LSI_FUSION		0x005b
+ 
+ /*
+  * =====================================
+@@ -421,7 +422,6 @@ struct megasas_ctrl_prop {
+ 	* Add properties that can be controlled by
+ 	* a bit in the following structure.
+ 	*/
+-
+ 	struct {
+ 		u32     copyBackDisabled            : 1;
+ 		u32     SMARTerEnabled              : 1;
+@@ -701,6 +701,7 @@ struct megasas_ctrl_info {
+ #define MEGASAS_DEFAULT_INIT_ID			-1
+ #define MEGASAS_MAX_LUN				8
+ #define MEGASAS_MAX_LD				64
++#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 * \
+@@ -768,7 +769,10 @@ struct megasas_ctrl_info {
+ */
+  
+ struct megasas_register_set {
+-	u32 	reserved_0[4];			/*0000h*/
++	u32	doorbell;                       /*0000h*/
++	u32	fusion_seq_offset;		/*0004h*/
++	u32	fusion_host_diag;		/*0008h*/
++	u32	reserved_01;			/*000Ch*/
+ 
+ 	u32 	inbound_msg_0;			/*0010h*/
+ 	u32 	inbound_msg_1;			/*0014h*/
+@@ -788,15 +792,18 @@ struct megasas_register_set {
+ 	u32 	inbound_queue_port;		/*0040h*/
+ 	u32 	outbound_queue_port;		/*0044h*/
+ 
+-	u32 	reserved_2[22];			/*0048h*/
++	u32	reserved_2[9];			/*0048h*/
++	u32	reply_post_host_index;		/*006Ch*/
++	u32	reserved_2_2[12];		/*0070h*/
+ 
+ 	u32 	outbound_doorbell_clear;	/*00A0h*/
+ 
+ 	u32 	reserved_3[3];			/*00A4h*/
+ 
+ 	u32 	outbound_scratch_pad ;		/*00B0h*/
++	u32	outbound_scratch_pad_2;         /*00B4h*/
+ 
+-	u32 	reserved_4[3];			/*00B4h*/
++	u32	reserved_4[2];			/*00B8h*/
+ 
+ 	u32 	inbound_low_queue_port ;	/*00C0h*/
+ 
+@@ -1271,6 +1278,9 @@ struct megasas_instance {
+ 
+ 	u16 max_num_sge;
+ 	u16 max_fw_cmds;
++	/* For Fusion its num IOCTL cmds, for others MFI based its
++	   max_fw_cmds */
++	u16 max_mfi_cmds;
+ 	u32 max_sectors_per_req;
+ 	struct megasas_aen_event *ev;
+ 
+@@ -1320,9 +1330,15 @@ struct megasas_instance {
+ 	struct timer_list io_completion_timer;
+ 	struct list_head internal_reset_pending_q;
+ 
++	/* Ptr to hba specfic information */
++	void *ctrl_context;
+ 	u8	msi_flag;
+ 	struct msix_entry msixentry;
++	u64 map_id;
++	struct megasas_cmd *map_update_cmd;
+ 	unsigned long bar;
++	long reset_flags;
++	struct mutex reset_mutex;
+ };
+ 
+ enum {
+@@ -1381,7 +1397,13 @@ struct megasas_cmd {
+ 	struct list_head list;
+ 	struct scsi_cmnd *scmd;
+ 	struct megasas_instance *instance;
+-	u32 frame_count;
++	union {
++		struct {
++			u16 smid;
++			u16 resvd;
++		} context;
++		u32 frame_count;
++	};
+ };
+ 
+ #define MAX_MGMT_ADAPTERS		1024
+diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c
+index 7f2b199b82c2..d532b330e03f 100644
+--- a/drivers/scsi/megaraid/megaraid_sas_base.c
++++ b/drivers/scsi/megaraid/megaraid_sas_base.c
+@@ -46,6 +46,7 @@
+ #include <scsi/scsi_cmnd.h>
+ #include <scsi/scsi_device.h>
+ #include <scsi/scsi_host.h>
++#include "megaraid_sas_fusion.h"
+ #include "megaraid_sas.h"
+ 
+ /*
+@@ -65,7 +66,7 @@ MODULE_VERSION(MEGASAS_VERSION);
+ MODULE_AUTHOR("megaraidlinux at lsi.com");
+ MODULE_DESCRIPTION("LSI MegaRAID SAS Driver");
+ 
+-static int megasas_transition_to_ready(struct megasas_instance *instance);
++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,
+@@ -93,6 +94,8 @@ static struct pci_device_id megasas_pci_table[] = {
+ 	/* xscale IOP, vega */
+ 	{PCI_DEVICE(PCI_VENDOR_ID_DELL, PCI_DEVICE_ID_DELL_PERC5)},
+ 	/* xscale IOP */
++	{PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FUSION)},
++	/* Fusion */
+ 	{}
+ };
+ 
+@@ -106,14 +109,15 @@ static DEFINE_MUTEX(megasas_async_queue_mutex);
+ static int megasas_poll_wait_aen;
+ static DECLARE_WAIT_QUEUE_HEAD(megasas_poll_wait);
+ static u32 support_poll_for_event;
+-static u32 megasas_dbg_lvl;
++u32 megasas_dbg_lvl;
+ 
+ /* define lock for aen poll */
+ spinlock_t poll_aen_lock;
+ 
+-static void
++void
+ megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd,
+ 		     u8 alt_status);
++
+ static irqreturn_t megasas_isr(int irq, void *devp);
+ static u32
+ megasas_init_adapter_mfi(struct megasas_instance *instance);
+@@ -121,6 +125,23 @@ u32
+ megasas_build_and_issue_cmd(struct megasas_instance *instance,
+ 			    struct scsi_cmnd *scmd);
+ static void megasas_complete_cmd_dpc(unsigned long instance_addr);
++void
++megasas_release_fusion(struct megasas_instance *instance);
++int
++megasas_ioc_init_fusion(struct megasas_instance *instance);
++void
++megasas_free_cmds_fusion(struct megasas_instance *instance);
++u8
++megasas_get_map_info(struct megasas_instance *instance);
++int
++megasas_sync_map_info(struct megasas_instance *instance);
++int
++wait_and_poll(struct megasas_instance *instance, struct megasas_cmd *cmd);
++void megasas_reset_reply_desc(struct megasas_instance *instance);
++u8 MR_ValidateMapInfo(struct MR_FW_RAID_MAP_ALL *map,
++		      struct LD_LOAD_BALANCE_INFO *lbInfo);
++int megasas_reset_fusion(struct Scsi_Host *shost);
++void megasas_fusion_ocr_wq(struct work_struct *work);
+ 
+ void
+ megasas_issue_dcmd(struct megasas_instance *instance, struct megasas_cmd *cmd)
+@@ -135,7 +156,7 @@ megasas_issue_dcmd(struct megasas_instance *instance, struct megasas_cmd *cmd)
+  *
+  * Returns a free command from the pool
+  */
+-static struct megasas_cmd *megasas_get_cmd(struct megasas_instance
++struct megasas_cmd *megasas_get_cmd(struct megasas_instance
+ 						  *instance)
+ {
+ 	unsigned long flags;
+@@ -160,7 +181,7 @@ static struct megasas_cmd *megasas_get_cmd(struct megasas_instance
+  * @instance:		Adapter soft state
+  * @cmd:		Command packet to be returned to free command pool
+  */
+-static inline void
++inline void
+ megasas_return_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd)
+ {
+ 	unsigned long flags;
+@@ -168,6 +189,7 @@ megasas_return_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd)
+ 	spin_lock_irqsave(&instance->cmd_pool_lock, flags);
+ 
+ 	cmd->scmd = NULL;
++	cmd->frame_count = 0;
+ 	list_add_tail(&cmd->list, &instance->cmd_pool);
+ 
+ 	spin_unlock_irqrestore(&instance->cmd_pool_lock, flags);
+@@ -775,6 +797,11 @@ static struct megasas_instance_template megasas_instance_template_gen2 = {
+ *       specific to gen2 (deviceid : 0x78, 0x79) controllers
+ */
+ 
++/*
++ * Template added for TB (Fusion)
++ */
++extern struct megasas_instance_template megasas_instance_template_fusion;
++
+ /**
+  * megasas_issue_polled -	Issues a polling command
+  * @instance:			Adapter soft state
+@@ -782,11 +809,9 @@ static struct megasas_instance_template megasas_instance_template_gen2 = {
+  *
+  * For polling, MFI requires the cmd_status to be set to 0xFF before posting.
+  */
+-static int
++int
+ megasas_issue_polled(struct megasas_instance *instance, struct megasas_cmd *cmd)
+ {
+-	int i;
+-	u32 msecs = MFI_POLL_TIMEOUT_SECS * 1000;
+ 
+ 	struct megasas_header *frame_hdr = &cmd->frame->hdr;
+ 
+@@ -796,21 +821,12 @@ 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->issue_dcmd(instance, cmd);
+ 
+ 	/*
+ 	 * Wait for cmd_status to change
+ 	 */
+-	for (i = 0; (i < msecs) && (frame_hdr->cmd_status == 0xff); i++) {
+-		rmb();
+-		msleep(1);
+-	}
+-
+-	if (frame_hdr->cmd_status == 0xff)
+-		return -ETIME;
+-
+-	return 0;
++	return wait_and_poll(instance, cmd);
+ }
+ 
+ /**
+@@ -828,8 +844,7 @@ 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->issue_dcmd(instance, cmd);
+ 
+ 	wait_event(instance->int_cmd_wait_q, cmd->cmd_status != ENODATA);
+ 
+@@ -873,8 +888,7 @@ 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->issue_dcmd(instance, cmd);
+ 
+ 	/*
+ 	 * Wait for this cmd to complete
+@@ -1257,7 +1271,7 @@ megasas_build_ldio(struct megasas_instance *instance, struct scsi_cmnd *scp,
+  * Called by megasas_queue_command to find out if the command to be queued
+  * is a logical drive command
+  */
+-static inline int megasas_is_ldio(struct scsi_cmnd *cmd)
++inline int megasas_is_ldio(struct scsi_cmnd *cmd)
+ {
+ 	if (!MEGASAS_IS_LOGICAL(cmd))
+ 		return 0;
+@@ -1463,15 +1477,44 @@ static int megasas_slave_configure(struct scsi_device *sdev)
+ 	return 0;
+ }
+ 
+-static void megaraid_sas_kill_hba(struct megasas_instance *instance)
++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]);
++	    (instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0071SKINNY) ||
++	    (instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION)) {
++		writel(MFI_STOP_ADP, &instance->reg_set->doorbell);
+ 	} else {
+-		writel(MFI_STOP_ADP,
+-			&instance->reg_set->inbound_doorbell);
++		writel(MFI_STOP_ADP, &instance->reg_set->inbound_doorbell);
++	}
++}
++
++ /**
++  * megasas_check_and_restore_queue_depth - Check if queue depth needs to be
++  *					restored to max value
++  * @instance:			Adapter soft state
++  *
++  */
++void
++megasas_check_and_restore_queue_depth(struct megasas_instance *instance)
++{
++	unsigned long flags;
++	if (instance->flag & MEGASAS_FW_BUSY
++		&& time_after(jiffies, instance->last_time + 5 * HZ)
++		&& atomic_read(&instance->fw_outstanding) < 17) {
++
++		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)) {
++			instance->host->can_queue =
++				instance->max_fw_cmds - MEGASAS_SKINNY_INT_CMDS;
++		} else
++			instance->host->can_queue =
++				instance->max_fw_cmds - MEGASAS_INT_CMDS;
++
++		spin_unlock_irqrestore(instance->host->host_lock, flags);
+ 	}
+ }
+ 
+@@ -1525,24 +1568,7 @@ static void megasas_complete_cmd_dpc(unsigned long instance_addr)
+ 	/*
+ 	 * Check if we can restore can_queue
+ 	 */
+-	if (instance->flag & MEGASAS_FW_BUSY
+-		&& time_after(jiffies, instance->last_time + 5 * HZ)
+-		&& atomic_read(&instance->fw_outstanding) < 17) {
+-
+-		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)) {
+-			instance->host->can_queue =
+-				instance->max_fw_cmds - MEGASAS_SKINNY_INT_CMDS;
+-		} else
+-			instance->host->can_queue =
+-				instance->max_fw_cmds - MEGASAS_INT_CMDS;
+-
+-		spin_unlock_irqrestore(instance->host->host_lock, flags);
+-	}
++	megasas_check_and_restore_queue_depth(instance);
+ }
+ 
+ /**
+@@ -1658,7 +1684,7 @@ static int megasas_wait_for_outstanding(struct megasas_instance *instance)
+ 			(instance->pdev->device ==
+ 			PCI_DEVICE_ID_LSI_SAS0071SKINNY)) {
+ 			writel(MFI_STOP_ADP,
+-				&instance->reg_set->reserved_0[0]);
++				&instance->reg_set->doorbell);
+ 		} else {
+ 			writel(MFI_STOP_ADP,
+ 				&instance->reg_set->inbound_doorbell);
+@@ -1762,11 +1788,16 @@ static int megasas_reset_device(struct scsi_cmnd *scmd)
+ static int megasas_reset_bus_host(struct scsi_cmnd *scmd)
+ {
+ 	int ret;
++	struct megasas_instance *instance;
++	instance = (struct megasas_instance *)scmd->device->host->hostdata;
+ 
+ 	/*
+ 	 * First wait for all commands to complete
+ 	 */
+-	ret = megasas_generic_reset(scmd);
++	if (instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION)
++		ret = megasas_reset_fusion(scmd->device->host);
++	else
++		ret = megasas_generic_reset(scmd);
+ 
+ 	return ret;
+ }
+@@ -1935,13 +1966,14 @@ megasas_complete_abort(struct megasas_instance *instance,
+  * 				an alternate status (as in the case of aborted
+  * 				commands)
+  */
+-static void
++void
+ megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd,
+ 		     u8 alt_status)
+ {
+ 	int exception = 0;
+ 	struct megasas_header *hdr = &cmd->frame->hdr;
+ 	unsigned long flags;
++	struct fusion_context *fusion = instance->ctrl_context;
+ 
+ 	/* flag for the retry reset */
+ 	cmd->retry_for_fw_reset = 0;
+@@ -2034,6 +2066,37 @@ megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd,
+ 	case MFI_CMD_SMP:
+ 	case MFI_CMD_STP:
+ 	case MFI_CMD_DCMD:
++		/* Check for LD map update */
++		if ((cmd->frame->dcmd.opcode == MR_DCMD_LD_MAP_GET_INFO) &&
++		    (cmd->frame->dcmd.mbox.b[1] == 1)) {
++			spin_lock_irqsave(instance->host->host_lock, flags);
++			if (cmd->frame->hdr.cmd_status != 0) {
++				if (cmd->frame->hdr.cmd_status !=
++				    MFI_STAT_NOT_FOUND)
++					printk(KERN_WARNING "megasas: map sync"
++					       "failed, status = 0x%x.\n",
++					       cmd->frame->hdr.cmd_status);
++				else {
++					megasas_return_cmd(instance, cmd);
++					spin_unlock_irqrestore(
++						instance->host->host_lock,
++						flags);
++					break;
++				}
++			} else
++				instance->map_id++;
++			megasas_return_cmd(instance, cmd);
++			if (MR_ValidateMapInfo(
++				    fusion->ld_map[(instance->map_id & 1)],
++				    fusion->load_balance_info))
++				fusion->fast_path_io = 1;
++			else
++				fusion->fast_path_io = 0;
++			megasas_sync_map_info(instance);
++			spin_unlock_irqrestore(instance->host->host_lock,
++					       flags);
++			break;
++		}
+ 		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);
+@@ -2372,7 +2435,7 @@ static irqreturn_t megasas_isr(int irq, void *devp)
+  * states, driver must take steps to bring it to ready state. Otherwise, it
+  * has to wait for the ready state.
+  */
+-static int
++int
+ megasas_transition_to_ready(struct megasas_instance* instance)
+ {
+ 	int i;
+@@ -2402,11 +2465,12 @@ megasas_transition_to_ready(struct megasas_instance* instance)
+ 			if ((instance->pdev->device ==
+ 				PCI_DEVICE_ID_LSI_SAS0073SKINNY) ||
+ 				(instance->pdev->device ==
+-				PCI_DEVICE_ID_LSI_SAS0071SKINNY)) {
+-
++				 PCI_DEVICE_ID_LSI_SAS0071SKINNY) ||
++				(instance->pdev->device ==
++				 PCI_DEVICE_ID_LSI_FUSION)) {
+ 				writel(
+ 				  MFI_INIT_CLEAR_HANDSHAKE|MFI_INIT_HOTPLUG,
+-				  &instance->reg_set->reserved_0[0]);
++				  &instance->reg_set->doorbell);
+ 			} else {
+ 				writel(
+ 				    MFI_INIT_CLEAR_HANDSHAKE|MFI_INIT_HOTPLUG,
+@@ -2419,11 +2483,13 @@ megasas_transition_to_ready(struct megasas_instance* instance)
+ 
+ 		case MFI_STATE_BOOT_MESSAGE_PENDING:
+ 			if ((instance->pdev->device ==
+-				PCI_DEVICE_ID_LSI_SAS0073SKINNY) ||
+-			(instance->pdev->device ==
+-				PCI_DEVICE_ID_LSI_SAS0071SKINNY)) {
++			     PCI_DEVICE_ID_LSI_SAS0073SKINNY) ||
++				(instance->pdev->device ==
++				 PCI_DEVICE_ID_LSI_SAS0071SKINNY) ||
++			    (instance->pdev->device ==
++			     PCI_DEVICE_ID_LSI_FUSION)) {
+ 				writel(MFI_INIT_HOTPLUG,
+-				&instance->reg_set->reserved_0[0]);
++				       &instance->reg_set->doorbell);
+ 			} else
+ 				writel(MFI_INIT_HOTPLUG,
+ 					&instance->reg_set->inbound_doorbell);
+@@ -2440,9 +2506,23 @@ megasas_transition_to_ready(struct megasas_instance* instance)
+ 			if ((instance->pdev->device ==
+ 				PCI_DEVICE_ID_LSI_SAS0073SKINNY) ||
+ 				(instance->pdev->device ==
+-				PCI_DEVICE_ID_LSI_SAS0071SKINNY)) {
++				PCI_DEVICE_ID_LSI_SAS0071SKINNY)  ||
++				(instance->pdev->device
++					== PCI_DEVICE_ID_LSI_FUSION)) {
+ 				writel(MFI_RESET_FLAGS,
+-					&instance->reg_set->reserved_0[0]);
++					&instance->reg_set->doorbell);
++				if (instance->pdev->device ==
++				    PCI_DEVICE_ID_LSI_FUSION) {
++					for (i = 0; i < (10 * 1000); i += 20) {
++						if (readl(
++							    &instance->
++							    reg_set->
++							    doorbell) & 1)
++							msleep(20);
++						else
++							break;
++					}
++				}
+ 			} else
+ 				writel(MFI_RESET_FLAGS,
+ 					&instance->reg_set->inbound_doorbell);
+@@ -2524,7 +2604,7 @@ megasas_transition_to_ready(struct megasas_instance* instance)
+ static void megasas_teardown_frame_pool(struct megasas_instance *instance)
+ {
+ 	int i;
+-	u32 max_cmd = instance->max_fw_cmds;
++	u32 max_cmd = instance->max_mfi_cmds;
+ 	struct megasas_cmd *cmd;
+ 
+ 	if (!instance->frame_dma_pool)
+@@ -2575,7 +2655,7 @@ static int megasas_create_frame_pool(struct megasas_instance *instance)
+ 	u32 frame_count;
+ 	struct megasas_cmd *cmd;
+ 
+-	max_cmd = instance->max_fw_cmds;
++	max_cmd = instance->max_mfi_cmds;
+ 
+ 	/*
+ 	 * Size of our frame is 64 bytes for MFI frame, followed by max SG
+@@ -2661,14 +2741,15 @@ static int megasas_create_frame_pool(struct megasas_instance *instance)
+  * megasas_free_cmds -	Free all the cmds in the free cmd pool
+  * @instance:		Adapter soft state
+  */
+-static void megasas_free_cmds(struct megasas_instance *instance)
++void megasas_free_cmds(struct megasas_instance *instance)
+ {
+ 	int i;
+ 	/* First free the MFI frame pool */
+ 	megasas_teardown_frame_pool(instance);
+ 
+ 	/* Free all the commands in the cmd_list */
+-	for (i = 0; i < instance->max_fw_cmds; i++)
++	for (i = 0; i < instance->max_mfi_cmds; i++)
++
+ 		kfree(instance->cmd_list[i]);
+ 
+ 	/* Free the cmd_list buffer itself */
+@@ -2696,14 +2777,14 @@ static void megasas_free_cmds(struct megasas_instance *instance)
+  * This array is used only to look up the megasas_cmd given the context. The
+  * free commands themselves are maintained in a linked list called cmd_pool.
+  */
+-static int megasas_alloc_cmds(struct megasas_instance *instance)
++int megasas_alloc_cmds(struct megasas_instance *instance)
+ {
+ 	int i;
+ 	int j;
+ 	u32 max_cmd;
+ 	struct megasas_cmd *cmd;
+ 
+-	max_cmd = instance->max_fw_cmds;
++	max_cmd = instance->max_mfi_cmds;
+ 
+ 	/*
+ 	 * instance->cmd_list is an array of struct megasas_cmd pointers.
+@@ -2717,6 +2798,7 @@ static int megasas_alloc_cmds(struct megasas_instance *instance)
+ 		return -ENOMEM;
+ 	}
+ 
++	memset(instance->cmd_list, 0, sizeof(struct megasas_cmd *) *max_cmd);
+ 
+ 	for (i = 0; i < max_cmd; i++) {
+ 		instance->cmd_list[i] = kmalloc(sizeof(struct megasas_cmd),
+@@ -3128,6 +3210,7 @@ megasas_init_adapter_mfi(struct megasas_instance *instance)
+ 	 * does not exceed max cmds that the FW can support
+ 	 */
+ 	instance->max_fw_cmds = instance->max_fw_cmds-1;
++	instance->max_mfi_cmds = instance->max_fw_cmds;
+ 	instance->max_num_sge = (instance->instancet->read_fw_status_reg(reg_set) & 0xFF0000) >>
+ 					0x10;
+ 	/*
+@@ -3221,6 +3304,9 @@ static int megasas_init_fw(struct megasas_instance *instance)
+ 	reg_set = instance->reg_set;
+ 
+ 	switch (instance->pdev->device) {
++	case PCI_DEVICE_ID_LSI_FUSION:
++		instance->instancet = &megasas_instance_template_fusion;
++		break;
+ 	case PCI_DEVICE_ID_LSI_SAS1078R:
+ 	case PCI_DEVICE_ID_LSI_SAS1078DE:
+ 		instance->instancet = &megasas_instance_template_ppc;
+@@ -3322,9 +3408,10 @@ fail_ready_state:
+  */
+ static void megasas_release_mfi(struct megasas_instance *instance)
+ {
+-	u32 reply_q_sz = sizeof(u32) * (instance->max_fw_cmds + 1);
++	u32 reply_q_sz = sizeof(u32) *(instance->max_mfi_cmds + 1);
+ 
+-	pci_free_consistent(instance->pdev, reply_q_sz,
++	if (instance->reply_queue)
++		pci_free_consistent(instance->pdev, reply_q_sz,
+ 			    instance->reply_queue, instance->reply_queue_h);
+ 
+ 	megasas_free_cmds(instance);
+@@ -3516,8 +3603,7 @@ 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->issue_dcmd(instance, cmd);
+ 
+ 	return 0;
+ }
+@@ -3573,12 +3659,18 @@ static int megasas_io_attach(struct megasas_instance *instance)
+ 	host->this_id = instance->init_id;
+ 	host->sg_tablesize = instance->max_num_sge;
+ 	host->max_sectors = instance->max_sectors_per_req;
+-	host->cmd_per_lun = 128;
++	host->cmd_per_lun = MEGASAS_DEFAULT_CMD_PER_LUN;
+ 	host->max_channel = MEGASAS_MAX_CHANNELS - 1;
+ 	host->max_id = MEGASAS_MAX_DEV_PER_CHANNEL;
+ 	host->max_lun = MEGASAS_MAX_LUN;
+ 	host->max_cmd_len = 16;
+ 
++	/* Fusion only supports host reset */
++	if (instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION) {
++		host->hostt->eh_device_reset_handler = NULL;
++		host->hostt->eh_bus_reset_handler = NULL;
++	}
++
+ 	/*
+ 	 * Notify the mid-layer about the new controller
+ 	 */
+@@ -3663,20 +3755,45 @@ 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->pdev = pdev;
+ 
+-	instance->producer = pci_alloc_consistent(pdev, sizeof(u32),
+-						  &instance->producer_h);
+-	instance->consumer = pci_alloc_consistent(pdev, sizeof(u32),
+-						  &instance->consumer_h);
++	switch (instance->pdev->device) {
++	case PCI_DEVICE_ID_LSI_FUSION:
++	{
++		struct fusion_context *fusion;
+ 
+-	if (!instance->producer || !instance->consumer) {
+-		printk(KERN_DEBUG "megasas: Failed to allocate memory for "
+-		       "producer, consumer\n");
+-		goto fail_alloc_dma_buf;
++		instance->ctrl_context =
++			kzalloc(sizeof(struct fusion_context), GFP_KERNEL);
++		if (!instance->ctrl_context) {
++			printk(KERN_DEBUG "megasas: Failed to allocate "
++			       "memory for Fusion context info\n");
++			goto fail_alloc_dma_buf;
++		}
++		fusion = instance->ctrl_context;
++		INIT_LIST_HEAD(&fusion->cmd_pool);
++		spin_lock_init(&fusion->cmd_pool_lock);
++	}
++	break;
++	default: /* For all other supported controllers */
++
++		instance->producer =
++			pci_alloc_consistent(pdev, sizeof(u32),
++					     &instance->producer_h);
++		instance->consumer =
++			pci_alloc_consistent(pdev, sizeof(u32),
++					     &instance->consumer_h);
++
++		if (!instance->producer || !instance->consumer) {
++			printk(KERN_DEBUG "megasas: Failed to allocate"
++			       "memory for producer, consumer\n");
++			goto fail_alloc_dma_buf;
++		}
++
++		*instance->producer = 0;
++		*instance->consumer = 0;
++		break;
+ 	}
+ 
+-	*instance->producer = 0;
+-	*instance->consumer = 0;
+ 	megasas_poll_wait_aen = 0;
+ 	instance->flag_ieee = 0;
+ 	instance->ev = NULL;
+@@ -3712,11 +3829,11 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ 	spin_lock_init(&poll_aen_lock);
+ 
+ 	mutex_init(&instance->aen_mutex);
++	mutex_init(&instance->reset_mutex);
+ 
+ 	/*
+ 	 * Initialize PCI related and misc parameters
+ 	 */
+-	instance->pdev = pdev;
+ 	instance->host = host;
+ 	instance->unique_id = pdev->bus->number << 8 | pdev->devfn;
+ 	instance->init_id = MEGASAS_DEFAULT_INIT_ID;
+@@ -3734,7 +3851,10 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ 	instance->last_time = 0;
+ 	instance->disableOnlineCtrlReset = 1;
+ 
+-	INIT_WORK(&instance->work_init, process_fw_state_change_wq);
++	if (instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION)
++		INIT_WORK(&instance->work_init, megasas_fusion_ocr_wq);
++	else
++		INIT_WORK(&instance->work_init, process_fw_state_change_wq);
+ 
+ 	/*
+ 	 * Initialize MFI Firmware
+@@ -3817,6 +3937,8 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ 		pci_free_consistent(pdev, sizeof(u32), instance->producer,
+ 				    instance->producer_h);
+ 		megasas_release_mfi(instance);
++	} else {
++		megasas_release_fusion(instance);
+ 	}
+ 	if (instance->consumer)
+ 		pci_free_consistent(pdev, sizeof(u32), instance->consumer,
+@@ -3888,7 +4010,9 @@ static void megasas_shutdown_controller(struct megasas_instance *instance,
+ 
+ 	if (instance->aen_cmd)
+ 		megasas_issue_blocked_abort_cmd(instance, instance->aen_cmd);
+-
++	if (instance->map_update_cmd)
++		megasas_issue_blocked_abort_cmd(instance,
++						instance->map_update_cmd);
+ 	dcmd = &cmd->frame->dcmd;
+ 
+ 	memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
+@@ -3992,9 +4116,6 @@ megasas_resume(struct pci_dev *pdev)
+ 	 * Initialize MFI Firmware
+ 	 */
+ 
+-	*instance->producer = 0;
+-	*instance->consumer = 0;
+-
+ 	atomic_set(&instance->fw_outstanding, 0);
+ 
+ 	/*
+@@ -4003,11 +4124,29 @@ megasas_resume(struct pci_dev *pdev)
+ 	if (megasas_transition_to_ready(instance))
+ 		goto fail_ready_state;
+ 
+-	if (megasas_issue_init_mfi(instance))
+-		goto fail_init_mfi;
++	switch (instance->pdev->device) {
++	case PCI_DEVICE_ID_LSI_FUSION:
++	{
++		megasas_reset_reply_desc(instance);
++		if (megasas_ioc_init_fusion(instance)) {
++			megasas_free_cmds(instance);
++			megasas_free_cmds_fusion(instance);
++			goto fail_init_mfi;
++		}
++		if (!megasas_get_map_info(instance))
++			megasas_sync_map_info(instance);
++	}
++	break;
++	default:
++		*instance->producer = 0;
++		*instance->consumer = 0;
++		if (megasas_issue_init_mfi(instance))
++			goto fail_init_mfi;
++		break;
++	}
+ 
+-	tasklet_init(&instance->isr_tasklet, megasas_complete_cmd_dpc,
+-			(unsigned long)instance);
++	tasklet_init(&instance->isr_tasklet, instance->instancet->tasklet,
++		     (unsigned long)instance);
+ 
+ 	/* Now re-enable MSI-X */
+ 	if (instance->msi_flag)
+@@ -4076,10 +4215,12 @@ static void __devexit megasas_detach_one(struct pci_dev *pdev)
+ 	int i;
+ 	struct Scsi_Host *host;
+ 	struct megasas_instance *instance;
++	struct fusion_context *fusion;
+ 
+ 	instance = pci_get_drvdata(pdev);
+ 	instance->unload = 1;
+ 	host = instance->host;
++	fusion = instance->ctrl_context;
+ 
+ 	if (poll_mode_io)
+ 		del_timer_sync(&instance->io_completion_timer);
+@@ -4121,16 +4262,32 @@ static void __devexit megasas_detach_one(struct pci_dev *pdev)
+ 	if (instance->msi_flag)
+ 		pci_disable_msix(instance->pdev);
+ 
+-	megasas_release_mfi(instance);
+-
+-	pci_free_consistent(pdev, sizeof(struct megasas_evt_detail),
+-			    instance->evt_detail, instance->evt_detail_h);
+-
+-	pci_free_consistent(pdev, sizeof(u32), instance->producer,
+-			    instance->producer_h);
+-
+-	pci_free_consistent(pdev, sizeof(u32), instance->consumer,
+-			    instance->consumer_h);
++	switch (instance->pdev->device) {
++	case PCI_DEVICE_ID_LSI_FUSION:
++		megasas_release_fusion(instance);
++		for (i = 0; i < 2 ; i++)
++			if (fusion->ld_map[i])
++				dma_free_coherent(&instance->pdev->dev,
++						  fusion->map_sz,
++						  fusion->ld_map[i],
++						  fusion->
++						  ld_map_phys[i]);
++		kfree(instance->ctrl_context);
++		break;
++	default:
++		megasas_release_mfi(instance);
++		pci_free_consistent(pdev,
++				    sizeof(struct megasas_evt_detail),
++				    instance->evt_detail,
++				    instance->evt_detail_h);
++		pci_free_consistent(pdev, sizeof(u32),
++				    instance->producer,
++				    instance->producer_h);
++		pci_free_consistent(pdev, sizeof(u32),
++				    instance->consumer,
++				    instance->consumer_h);
++		break;
++	}
+ 
+ 	scsi_host_put(host);
+ 
+@@ -4902,6 +5059,7 @@ megasas_aen_polling(struct work_struct *work)
+ 			break;
+ 		case MR_EVT_CTRL_HOST_BUS_SCAN_REQUESTED:
+ 		case MR_EVT_FOREIGN_CFG_IMPORTED:
++		case MR_EVT_LD_STATE_CHANGE:
+ 			doscan = 1;
+ 			break;
+ 		default:
+diff --git a/drivers/scsi/megaraid/megaraid_sas_fp.c b/drivers/scsi/megaraid/megaraid_sas_fp.c
+new file mode 100644
+index 000000000000..53fa96ae2b3e
+--- /dev/null
++++ b/drivers/scsi/megaraid/megaraid_sas_fp.c
+@@ -0,0 +1,516 @@
++/*
++ *  Linux MegaRAID driver for SAS based RAID controllers
++ *
++ *  Copyright (c) 2009-2011  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 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.
++ *
++ *  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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ *
++ *  FILE: megaraid_sas_fp.c
++ *
++ *  Authors: LSI Corporation
++ *           Sumant Patro
++ *           Varad Talamacki
++ *           Manoj Jose
++ *
++ *  Send feedback to: <megaraidlinux at lsi.com>
++ *
++ *  Mail to: LSI Corporation, 1621 Barber Lane, Milpitas, CA 95035
++ *     ATTN: Linuxraid
++ */
++
++#include <linux/kernel.h>
++#include <linux/types.h>
++#include <linux/pci.h>
++#include <linux/list.h>
++#include <linux/moduleparam.h>
++#include <linux/module.h>
++#include <linux/spinlock.h>
++#include <linux/interrupt.h>
++#include <linux/delay.h>
++#include <linux/smp_lock.h>
++#include <linux/uio.h>
++#include <linux/uaccess.h>
++#include <linux/fs.h>
++#include <linux/compat.h>
++#include <linux/blkdev.h>
++#include <linux/poll.h>
++
++#include <scsi/scsi.h>
++#include <scsi/scsi_cmnd.h>
++#include <scsi/scsi_device.h>
++#include <scsi/scsi_host.h>
++
++#include "megaraid_sas_fusion.h"
++#include <asm/div64.h>
++
++#define ABS_DIFF(a, b)   (((a) > (b)) ? ((a) - (b)) : ((b) - (a)))
++#define MR_LD_STATE_OPTIMAL 3
++#define FALSE 0
++#define TRUE 1
++
++/* Prototypes */
++void
++mr_update_load_balance_params(struct MR_FW_RAID_MAP_ALL *map,
++			      struct LD_LOAD_BALANCE_INFO *lbInfo);
++
++u32 mega_mod64(u64 dividend, u32 divisor)
++{
++	u64 d;
++	u32 remainder;
++
++	if (!divisor)
++		printk(KERN_ERR "megasas : DIVISOR is zero, in div fn\n");
++	d = dividend;
++	remainder = do_div(d, divisor);
++	return remainder;
++}
++
++/**
++ * @param dividend    : Dividend
++ * @param divisor    : Divisor
++ *
++ * @return quotient
++ **/
++u64 mega_div64_32(uint64_t dividend, uint32_t divisor)
++{
++	u32 remainder;
++	u64 d;
++
++	if (!divisor)
++		printk(KERN_ERR "megasas : DIVISOR is zero in mod fn\n");
++
++	d = dividend;
++	remainder = do_div(d, divisor);
++
++	return d;
++}
++
++struct MR_LD_RAID *MR_LdRaidGet(u32 ld, struct MR_FW_RAID_MAP_ALL *map)
++{
++	return &map->raidMap.ldSpanMap[ld].ldRaid;
++}
++
++static struct MR_SPAN_BLOCK_INFO *MR_LdSpanInfoGet(u32 ld,
++						   struct MR_FW_RAID_MAP_ALL
++						   *map)
++{
++	return &map->raidMap.ldSpanMap[ld].spanBlock[0];
++}
++
++static u8 MR_LdDataArmGet(u32 ld, u32 armIdx, struct MR_FW_RAID_MAP_ALL *map)
++{
++	return map->raidMap.ldSpanMap[ld].dataArmMap[armIdx];
++}
++
++static u16 MR_ArPdGet(u32 ar, u32 arm, struct MR_FW_RAID_MAP_ALL *map)
++{
++	return map->raidMap.arMapInfo[ar].pd[arm];
++}
++
++static u16 MR_LdSpanArrayGet(u32 ld, u32 span, struct MR_FW_RAID_MAP_ALL *map)
++{
++	return map->raidMap.ldSpanMap[ld].spanBlock[span].span.arrayRef;
++}
++
++static u16 MR_PdDevHandleGet(u32 pd, struct MR_FW_RAID_MAP_ALL *map)
++{
++	return map->raidMap.devHndlInfo[pd].curDevHdl;
++}
++
++u16 MR_GetLDTgtId(u32 ld, struct MR_FW_RAID_MAP_ALL *map)
++{
++	return map->raidMap.ldSpanMap[ld].ldRaid.targetId;
++}
++
++u16 MR_TargetIdToLdGet(u32 ldTgtId, struct MR_FW_RAID_MAP_ALL *map)
++{
++	return map->raidMap.ldTgtIdToLd[ldTgtId];
++}
++
++static struct MR_LD_SPAN *MR_LdSpanPtrGet(u32 ld, u32 span,
++					  struct MR_FW_RAID_MAP_ALL *map)
++{
++	return &map->raidMap.ldSpanMap[ld].spanBlock[span].span;
++}
++
++/*
++ * This function will validate Map info data provided by FW
++ */
++u8 MR_ValidateMapInfo(struct MR_FW_RAID_MAP_ALL *map,
++		      struct LD_LOAD_BALANCE_INFO *lbInfo)
++{
++	struct MR_FW_RAID_MAP *pFwRaidMap = &map->raidMap;
++
++	if (pFwRaidMap->totalSize !=
++	    (sizeof(struct MR_FW_RAID_MAP) -sizeof(struct MR_LD_SPAN_MAP) +
++	     (sizeof(struct MR_LD_SPAN_MAP) *pFwRaidMap->ldCount))) {
++		printk(KERN_ERR "megasas: map info structure size 0x%x is not matching with ld count\n",
++		       (unsigned int)((sizeof(struct MR_FW_RAID_MAP) -
++				       sizeof(struct MR_LD_SPAN_MAP)) +
++				      (sizeof(struct MR_LD_SPAN_MAP) *
++				       pFwRaidMap->ldCount)));
++		printk(KERN_ERR "megasas: span map %x, pFwRaidMap->totalSize "
++		       ": %x\n", (unsigned int)sizeof(struct MR_LD_SPAN_MAP),
++		       pFwRaidMap->totalSize);
++		return 0;
++	}
++
++	mr_update_load_balance_params(map, lbInfo);
++
++	return 1;
++}
++
++u32 MR_GetSpanBlock(u32 ld, u64 row, u64 *span_blk,
++		    struct MR_FW_RAID_MAP_ALL *map, int *div_error)
++{
++	struct MR_SPAN_BLOCK_INFO *pSpanBlock = MR_LdSpanInfoGet(ld, map);
++	struct MR_QUAD_ELEMENT    *quad;
++	struct MR_LD_RAID         *raid = MR_LdRaidGet(ld, map);
++	u32                span, j;
++
++	for (span = 0; span < raid->spanDepth; span++, pSpanBlock++) {
++
++		for (j = 0; j < pSpanBlock->block_span_info.noElements; j++) {
++			quad = &pSpanBlock->block_span_info.quad[j];
++
++			if (quad->diff == 0) {
++				*div_error = 1;
++				return span;
++			}
++			if (quad->logStart <= row  &&  row <= quad->logEnd  &&
++			    (mega_mod64(row-quad->logStart, quad->diff)) == 0) {
++				if (span_blk != NULL) {
++					u64  blk, debugBlk;
++					blk =
++						mega_div64_32(
++							(row-quad->logStart),
++							quad->diff);
++					debugBlk = blk;
++
++					blk = (blk + quad->offsetInSpan) <<
++						raid->stripeShift;
++					*span_blk = blk;
++				}
++				return span;
++			}
++		}
++	}
++	return span;
++}
++
++/*
++******************************************************************************
++*
++* This routine calculates the arm, span and block for the specified stripe and
++* reference in stripe.
++*
++* Inputs :
++*
++*    ld   - Logical drive number
++*    stripRow        - Stripe number
++*    stripRef    - Reference in stripe
++*
++* Outputs :
++*
++*    span          - Span number
++*    block         - Absolute Block number in the physical disk
++*/
++u8 MR_GetPhyParams(u32 ld, u64 stripRow, u16 stripRef, u64 *pdBlock,
++		   u16 *pDevHandle, struct RAID_CONTEXT *pRAID_Context,
++		   struct MR_FW_RAID_MAP_ALL *map)
++{
++	struct MR_LD_RAID  *raid = MR_LdRaidGet(ld, map);
++	u32         pd, arRef;
++	u8          physArm, span;
++	u64         row;
++	u8	    retval = TRUE;
++	int	    error_code = 0;
++
++	row =  mega_div64_32(stripRow, raid->rowDataSize);
++
++	if (raid->level == 6) {
++		/* logical arm within row */
++		u32 logArm =  mega_mod64(stripRow, raid->rowDataSize);
++		u32 rowMod, armQ, arm;
++
++		if (raid->rowSize == 0)
++			return FALSE;
++		/* get logical row mod */
++		rowMod = mega_mod64(row, raid->rowSize);
++		armQ = raid->rowSize-1-rowMod; /* index of Q drive */
++		arm = armQ+1+logArm; /* data always logically follows Q */
++		if (arm >= raid->rowSize) /* handle wrap condition */
++			arm -= raid->rowSize;
++		physArm = (u8)arm;
++	} else  {
++		if (raid->modFactor == 0)
++			return FALSE;
++		physArm = MR_LdDataArmGet(ld,  mega_mod64(stripRow,
++							  raid->modFactor),
++					  map);
++	}
++
++	if (raid->spanDepth == 1) {
++		span = 0;
++		*pdBlock = row << raid->stripeShift;
++	} else {
++		span = (u8)MR_GetSpanBlock(ld, row, pdBlock, map, &error_code);
++		if (error_code == 1)
++			return FALSE;
++	}
++
++	/* Get the array on which this span is present */
++	arRef       = MR_LdSpanArrayGet(ld, span, map);
++	pd          = MR_ArPdGet(arRef, physArm, map); /* Get the pd */
++
++	if (pd != MR_PD_INVALID)
++		/* Get dev handle from Pd. */
++		*pDevHandle = MR_PdDevHandleGet(pd, map);
++	else {
++		*pDevHandle = MR_PD_INVALID; /* set dev handle as invalid. */
++		if (raid->level >= 5)
++			pRAID_Context->regLockFlags = REGION_TYPE_EXCLUSIVE;
++		else if (raid->level == 1) {
++			/* Get alternate Pd. */
++			pd = MR_ArPdGet(arRef, physArm + 1, map);
++			if (pd != MR_PD_INVALID)
++				/* Get dev handle from Pd */
++				*pDevHandle = MR_PdDevHandleGet(pd, map);
++		}
++		retval = FALSE;
++	}
++
++	*pdBlock += stripRef + MR_LdSpanPtrGet(ld, span, map)->startBlk;
++	pRAID_Context->spanArm = (span << RAID_CTX_SPANARM_SPAN_SHIFT) |
++		physArm;
++	return retval;
++}
++
++/*
++******************************************************************************
++*
++* MR_BuildRaidContext function
++*
++* This function will initiate command processing.  The start/end row and strip
++* information is calculated then the lock is acquired.
++* This function will return 0 if region lock was acquired OR return num strips
++*/
++u8
++MR_BuildRaidContext(struct IO_REQUEST_INFO *io_info,
++		    struct RAID_CONTEXT *pRAID_Context,
++		    struct MR_FW_RAID_MAP_ALL *map)
++{
++	struct MR_LD_RAID  *raid;
++	u32         ld, stripSize, stripe_mask;
++	u64         endLba, endStrip, endRow, start_row, start_strip;
++	u64         regStart;
++	u32         regSize;
++	u8          num_strips, numRows;
++	u16         ref_in_start_stripe, ref_in_end_stripe;
++	u64         ldStartBlock;
++	u32         numBlocks, ldTgtId;
++	u8          isRead;
++	u8	    retval = 0;
++
++	ldStartBlock = io_info->ldStartBlock;
++	numBlocks = io_info->numBlocks;
++	ldTgtId = io_info->ldTgtId;
++	isRead = io_info->isRead;
++
++	ld = MR_TargetIdToLdGet(ldTgtId, map);
++	raid = MR_LdRaidGet(ld, map);
++
++	stripSize = 1 << raid->stripeShift;
++	stripe_mask = stripSize-1;
++	/*
++	 * calculate starting row and stripe, and number of strips and rows
++	 */
++	start_strip         = ldStartBlock >> raid->stripeShift;
++	ref_in_start_stripe = (u16)(ldStartBlock & stripe_mask);
++	endLba              = ldStartBlock + numBlocks - 1;
++	ref_in_end_stripe   = (u16)(endLba & stripe_mask);
++	endStrip            = endLba >> raid->stripeShift;
++	num_strips          = (u8)(endStrip - start_strip + 1); /* End strip */
++	if (raid->rowDataSize == 0)
++		return FALSE;
++	start_row           =  mega_div64_32(start_strip, raid->rowDataSize);
++	endRow              =  mega_div64_32(endStrip, raid->rowDataSize);
++	numRows             = (u8)(endRow - start_row + 1);
++
++	/*
++	 * calculate region info.
++	 */
++
++	/* assume region is at the start of the first row */
++	regStart            = start_row << raid->stripeShift;
++	/* assume this IO needs the full row - we'll adjust if not true */
++	regSize             = stripSize;
++
++	/* If IO spans more than 1 strip, fp is not possible
++	   FP is not possible for writes on non-0 raid levels
++	   FP is not possible if LD is not capable */
++	if (num_strips > 1 || (!isRead && raid->level != 0) ||
++	    !raid->capability.fpCapable) {
++		io_info->fpOkForIo = FALSE;
++	} else {
++		io_info->fpOkForIo = TRUE;
++	}
++
++	if (numRows == 1) {
++		/* single-strip IOs can always lock only the data needed */
++		if (num_strips == 1) {
++			regStart += ref_in_start_stripe;
++			regSize = numBlocks;
++		}
++		/* multi-strip IOs always need to full stripe locked */
++	} else {
++		if (start_strip == (start_row + 1) * raid->rowDataSize - 1) {
++			/* If the start strip is the last in the start row */
++			regStart += ref_in_start_stripe;
++			regSize = stripSize - ref_in_start_stripe;
++			/* initialize count to sectors from startref to end
++			   of strip */
++		}
++
++		if (numRows > 2)
++			/* Add complete rows in the middle of the transfer */
++			regSize += (numRows-2) << raid->stripeShift;
++
++		/* if IO ends within first strip of last row */
++		if (endStrip == endRow*raid->rowDataSize)
++			regSize += ref_in_end_stripe+1;
++		else
++			regSize += stripSize;
++	}
++
++	pRAID_Context->timeoutValue     = map->raidMap.fpPdIoTimeoutSec;
++	pRAID_Context->regLockFlags     = (isRead) ? REGION_TYPE_SHARED_READ :
++		raid->regTypeReqOnWrite;
++	pRAID_Context->VirtualDiskTgtId = raid->targetId;
++	pRAID_Context->regLockRowLBA    = regStart;
++	pRAID_Context->regLockLength    = regSize;
++	pRAID_Context->configSeqNum	= raid->seqNum;
++
++	/*Get Phy Params only if FP capable, or else leave it to MR firmware
++	  to do the calculation.*/
++	if (io_info->fpOkForIo) {
++		retval = MR_GetPhyParams(ld, start_strip, ref_in_start_stripe,
++					 &io_info->pdBlock,
++					 &io_info->devHandle, pRAID_Context,
++					 map);
++		/* If IO on an invalid Pd, then FP i snot possible */
++		if (io_info->devHandle == MR_PD_INVALID)
++			io_info->fpOkForIo = FALSE;
++		return retval;
++	} else if (isRead) {
++		uint stripIdx;
++		for (stripIdx = 0; stripIdx < num_strips; stripIdx++) {
++			if (!MR_GetPhyParams(ld, start_strip + stripIdx,
++					     ref_in_start_stripe,
++					     &io_info->pdBlock,
++					     &io_info->devHandle,
++					     pRAID_Context, map))
++				return TRUE;
++		}
++	}
++	return TRUE;
++}
++
++void
++mr_update_load_balance_params(struct MR_FW_RAID_MAP_ALL *map,
++			      struct LD_LOAD_BALANCE_INFO *lbInfo)
++{
++	int ldCount;
++	u16 ld;
++	struct MR_LD_RAID *raid;
++
++	for (ldCount = 0; ldCount < MAX_LOGICAL_DRIVES; ldCount++) {
++		ld = MR_TargetIdToLdGet(ldCount, map);
++		if (ld >= MAX_LOGICAL_DRIVES) {
++			lbInfo[ldCount].loadBalanceFlag = 0;
++			continue;
++		}
++
++		raid = MR_LdRaidGet(ld, map);
++
++		/* Two drive Optimal RAID 1 */
++		if ((raid->level == 1)  &&  (raid->rowSize == 2) &&
++		    (raid->spanDepth == 1) && raid->ldState ==
++		    MR_LD_STATE_OPTIMAL) {
++			u32 pd, arRef;
++
++			lbInfo[ldCount].loadBalanceFlag = 1;
++
++			/* Get the array on which this span is present */
++			arRef = MR_LdSpanArrayGet(ld, 0, map);
++
++			/* Get the Pd */
++			pd = MR_ArPdGet(arRef, 0, map);
++			/* Get dev handle from Pd */
++			lbInfo[ldCount].raid1DevHandle[0] =
++				MR_PdDevHandleGet(pd, map);
++			/* Get the Pd */
++			pd = MR_ArPdGet(arRef, 1, map);
++
++			/* Get the dev handle from Pd */
++			lbInfo[ldCount].raid1DevHandle[1] =
++				MR_PdDevHandleGet(pd, map);
++		} else
++			lbInfo[ldCount].loadBalanceFlag = 0;
++	}
++}
++
++u8 megasas_get_best_arm(struct LD_LOAD_BALANCE_INFO *lbInfo, u8 arm, u64 block,
++			u32 count)
++{
++	u16     pend0, pend1;
++	u64     diff0, diff1;
++	u8      bestArm;
++
++	/* get the pending cmds for the data and mirror arms */
++	pend0 = atomic_read(&lbInfo->scsi_pending_cmds[0]);
++	pend1 = atomic_read(&lbInfo->scsi_pending_cmds[1]);
++
++	/* Determine the disk whose head is nearer to the req. block */
++	diff0 = ABS_DIFF(block, lbInfo->last_accessed_block[0]);
++	diff1 = ABS_DIFF(block, lbInfo->last_accessed_block[1]);
++	bestArm = (diff0 <= diff1 ? 0 : 1);
++
++	if ((bestArm == arm && pend0 > pend1 + 16)  ||
++	    (bestArm != arm && pend1 > pend0 + 16))
++		bestArm ^= 1;
++
++	/* Update the last accessed block on the correct pd */
++	lbInfo->last_accessed_block[bestArm] = block + count - 1;
++
++	return bestArm;
++}
++
++u16 get_updated_dev_handle(struct LD_LOAD_BALANCE_INFO *lbInfo,
++			   struct IO_REQUEST_INFO *io_info)
++{
++	u8 arm, old_arm;
++	u16 devHandle;
++
++	old_arm = lbInfo->raid1DevHandle[0] == io_info->devHandle ? 0 : 1;
++
++	/* get best new arm */
++	arm  = megasas_get_best_arm(lbInfo, old_arm, io_info->ldStartBlock,
++				    io_info->numBlocks);
++	devHandle = lbInfo->raid1DevHandle[arm];
++	atomic_inc(&lbInfo->scsi_pending_cmds[arm]);
++
++	return devHandle;
++}
+diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.c b/drivers/scsi/megaraid/megaraid_sas_fusion.c
+new file mode 100644
+index 000000000000..c1e09d5a6196
+--- /dev/null
++++ b/drivers/scsi/megaraid/megaraid_sas_fusion.c
+@@ -0,0 +1,2248 @@
++/*
++ *  Linux MegaRAID driver for SAS based RAID controllers
++ *
++ *  Copyright (c) 2009-2011  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 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.
++ *
++ *  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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ *
++ *  FILE: megaraid_sas_fusion.c
++ *
++ *  Authors: LSI Corporation
++ *           Sumant Patro
++ *           Adam Radford <linuxraid at lsi.com>
++ *
++ *  Send feedback to: <megaraidlinux at lsi.com>
++ *
++ *  Mail to: LSI Corporation, 1621 Barber Lane, Milpitas, CA 95035
++ *     ATTN: Linuxraid
++ */
++
++#include <linux/kernel.h>
++#include <linux/types.h>
++#include <linux/pci.h>
++#include <linux/list.h>
++#include <linux/moduleparam.h>
++#include <linux/module.h>
++#include <linux/spinlock.h>
++#include <linux/interrupt.h>
++#include <linux/delay.h>
++#include <linux/smp_lock.h>
++#include <linux/uio.h>
++#include <linux/uaccess.h>
++#include <linux/fs.h>
++#include <linux/compat.h>
++#include <linux/blkdev.h>
++#include <linux/mutex.h>
++#include <linux/poll.h>
++
++#include <scsi/scsi.h>
++#include <scsi/scsi_cmnd.h>
++#include <scsi/scsi_device.h>
++#include <scsi/scsi_host.h>
++
++#include "megaraid_sas_fusion.h"
++#include "megaraid_sas.h"
++
++extern void megasas_free_cmds(struct megasas_instance *instance);
++extern struct megasas_cmd *megasas_get_cmd(struct megasas_instance
++					   *instance);
++extern void
++megasas_complete_cmd(struct megasas_instance *instance,
++		     struct megasas_cmd *cmd, u8 alt_status);
++int megasas_is_ldio(struct scsi_cmnd *cmd);
++int
++wait_and_poll(struct megasas_instance *instance, struct megasas_cmd *cmd);
++
++void
++megasas_return_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd);
++int megasas_alloc_cmds(struct megasas_instance *instance);
++int
++megasas_clear_intr_fusion(struct megasas_register_set __iomem *regs);
++int
++megasas_issue_polled(struct megasas_instance *instance,
++		     struct megasas_cmd *cmd);
++
++u8
++MR_BuildRaidContext(struct IO_REQUEST_INFO *io_info,
++		    struct RAID_CONTEXT *pRAID_Context,
++		    struct MR_FW_RAID_MAP_ALL *map);
++u16 MR_TargetIdToLdGet(u32 ldTgtId, struct MR_FW_RAID_MAP_ALL *map);
++struct MR_LD_RAID *MR_LdRaidGet(u32 ld, struct MR_FW_RAID_MAP_ALL *map);
++
++u16 MR_GetLDTgtId(u32 ld, struct MR_FW_RAID_MAP_ALL *map);
++u8 MR_ValidateMapInfo(struct MR_FW_RAID_MAP_ALL *map,
++		      struct LD_LOAD_BALANCE_INFO *lbInfo);
++u16 get_updated_dev_handle(struct LD_LOAD_BALANCE_INFO *lbInfo,
++			   struct IO_REQUEST_INFO *in_info);
++int megasas_transition_to_ready(struct megasas_instance *instance);
++void megaraid_sas_kill_hba(struct megasas_instance *instance);
++
++extern u32 megasas_dbg_lvl;
++
++/**
++ * megasas_enable_intr_fusion -	Enables interrupts
++ * @regs:			MFI register set
++ */
++void
++megasas_enable_intr_fusion(struct megasas_register_set __iomem *regs)
++{
++	writel(~MFI_FUSION_ENABLE_INTERRUPT_MASK, &(regs)->outbound_intr_mask);
++
++	/* Dummy readl to force pci flush */
++	readl(&regs->outbound_intr_mask);
++}
++
++/**
++ * megasas_disable_intr_fusion - Disables interrupt
++ * @regs:			 MFI register set
++ */
++void
++megasas_disable_intr_fusion(struct megasas_register_set __iomem *regs)
++{
++	u32 mask = 0xFFFFFFFF;
++	u32 status;
++
++	writel(mask, &regs->outbound_intr_mask);
++	/* Dummy readl to force pci flush */
++	status = readl(&regs->outbound_intr_mask);
++}
++
++int
++megasas_clear_intr_fusion(struct megasas_register_set __iomem *regs)
++{
++	u32 status;
++	/*
++	 * Check if it is our interrupt
++	 */
++	status = readl(&regs->outbound_intr_status);
++
++	if (status & 1) {
++		writel(status, &regs->outbound_intr_status);
++		readl(&regs->outbound_intr_status);
++		return 1;
++	}
++	if (!(status & MFI_FUSION_ENABLE_INTERRUPT_MASK))
++		return 0;
++
++	/*
++	 * dummy read to flush PCI
++	 */
++	readl(&regs->outbound_intr_status);
++
++	return 1;
++}
++
++/**
++ * megasas_get_cmd_fusion -	Get a command from the free pool
++ * @instance:		Adapter soft state
++ *
++ * Returns a free command from the pool
++ */
++struct megasas_cmd_fusion *megasas_get_cmd_fusion(struct megasas_instance
++						  *instance)
++{
++	unsigned long flags;
++	struct fusion_context *fusion =
++		(struct fusion_context *)instance->ctrl_context;
++	struct megasas_cmd_fusion *cmd = NULL;
++
++	spin_lock_irqsave(&fusion->cmd_pool_lock, flags);
++
++	if (!list_empty(&fusion->cmd_pool)) {
++		cmd = list_entry((&fusion->cmd_pool)->next,
++				 struct megasas_cmd_fusion, list);
++		list_del_init(&cmd->list);
++	} else {
++		printk(KERN_ERR "megasas: Command pool (fusion) empty!\n");
++	}
++
++	spin_unlock_irqrestore(&fusion->cmd_pool_lock, flags);
++	return cmd;
++}
++
++/**
++ * megasas_return_cmd_fusion -	Return a cmd to free command pool
++ * @instance:		Adapter soft state
++ * @cmd:		Command packet to be returned to free command pool
++ */
++static inline void
++megasas_return_cmd_fusion(struct megasas_instance *instance,
++			  struct megasas_cmd_fusion *cmd)
++{
++	unsigned long flags;
++	struct fusion_context *fusion =
++		(struct fusion_context *)instance->ctrl_context;
++
++	spin_lock_irqsave(&fusion->cmd_pool_lock, flags);
++
++	cmd->scmd = NULL;
++	cmd->sync_cmd_idx = (u32)ULONG_MAX;
++	list_add_tail(&cmd->list, &fusion->cmd_pool);
++
++	spin_unlock_irqrestore(&fusion->cmd_pool_lock, flags);
++}
++
++/**
++ * megasas_teardown_frame_pool_fusion -	Destroy the cmd frame DMA pool
++ * @instance:				Adapter soft state
++ */
++static void megasas_teardown_frame_pool_fusion(
++	struct megasas_instance *instance)
++{
++	int i;
++	struct fusion_context *fusion = instance->ctrl_context;
++
++	u16 max_cmd = instance->max_fw_cmds;
++
++	struct megasas_cmd_fusion *cmd;
++
++	if (!fusion->sg_dma_pool || !fusion->sense_dma_pool) {
++		printk(KERN_ERR "megasas: dma pool is null. SG Pool %p, "
++		       "sense pool : %p\n", fusion->sg_dma_pool,
++		       fusion->sense_dma_pool);
++		return;
++	}
++
++	/*
++	 * Return all frames to pool
++	 */
++	for (i = 0; i < max_cmd; i++) {
++
++		cmd = fusion->cmd_list[i];
++
++		if (cmd->sg_frame)
++			pci_pool_free(fusion->sg_dma_pool, cmd->sg_frame,
++				      cmd->sg_frame_phys_addr);
++
++		if (cmd->sense)
++			pci_pool_free(fusion->sense_dma_pool, cmd->sense,
++				      cmd->sense_phys_addr);
++	}
++
++	/*
++	 * Now destroy the pool itself
++	 */
++	pci_pool_destroy(fusion->sg_dma_pool);
++	pci_pool_destroy(fusion->sense_dma_pool);
++
++	fusion->sg_dma_pool = NULL;
++	fusion->sense_dma_pool = NULL;
++}
++
++/**
++ * megasas_free_cmds_fusion -	Free all the cmds in the free cmd pool
++ * @instance:		Adapter soft state
++ */
++void
++megasas_free_cmds_fusion(struct megasas_instance *instance)
++{
++	int i;
++	struct fusion_context *fusion = instance->ctrl_context;
++
++	u32 max_cmds, req_sz, reply_sz, io_frames_sz;
++
++
++	req_sz = fusion->request_alloc_sz;
++	reply_sz = fusion->reply_alloc_sz;
++	io_frames_sz = fusion->io_frames_alloc_sz;
++
++	max_cmds = instance->max_fw_cmds;
++
++	/* Free descriptors and request Frames memory */
++	if (fusion->req_frames_desc)
++		dma_free_coherent(&instance->pdev->dev, req_sz,
++				  fusion->req_frames_desc,
++				  fusion->req_frames_desc_phys);
++
++	if (fusion->reply_frames_desc) {
++		pci_pool_free(fusion->reply_frames_desc_pool,
++			      fusion->reply_frames_desc,
++			      fusion->reply_frames_desc_phys);
++		pci_pool_destroy(fusion->reply_frames_desc_pool);
++	}
++
++	if (fusion->io_request_frames) {
++		pci_pool_free(fusion->io_request_frames_pool,
++			      fusion->io_request_frames,
++			      fusion->io_request_frames_phys);
++		pci_pool_destroy(fusion->io_request_frames_pool);
++	}
++
++	/* Free the Fusion frame pool */
++	megasas_teardown_frame_pool_fusion(instance);
++
++	/* Free all the commands in the cmd_list */
++	for (i = 0; i < max_cmds; i++)
++		kfree(fusion->cmd_list[i]);
++
++	/* Free the cmd_list buffer itself */
++	kfree(fusion->cmd_list);
++	fusion->cmd_list = NULL;
++
++	INIT_LIST_HEAD(&fusion->cmd_pool);
++}
++
++/**
++ * megasas_create_frame_pool_fusion -	Creates DMA pool for cmd frames
++ * @instance:			Adapter soft state
++ *
++ */
++static int megasas_create_frame_pool_fusion(struct megasas_instance *instance)
++{
++	int i;
++	u32 max_cmd;
++	struct fusion_context *fusion;
++	struct megasas_cmd_fusion *cmd;
++	u32 total_sz_chain_frame;
++
++	fusion = instance->ctrl_context;
++	max_cmd = instance->max_fw_cmds;
++
++	total_sz_chain_frame = MEGASAS_MAX_SZ_CHAIN_FRAME;
++
++	/*
++	 * Use DMA pool facility provided by PCI layer
++	 */
++
++	fusion->sg_dma_pool = pci_pool_create("megasas sg pool fusion",
++					      instance->pdev,
++					      total_sz_chain_frame, 4,
++					      0);
++	if (!fusion->sg_dma_pool) {
++		printk(KERN_DEBUG "megasas: failed to setup request pool "
++		       "fusion\n");
++		return -ENOMEM;
++	}
++	fusion->sense_dma_pool = pci_pool_create("megasas sense pool fusion",
++						 instance->pdev,
++						 SCSI_SENSE_BUFFERSIZE, 64, 0);
++
++	if (!fusion->sense_dma_pool) {
++		printk(KERN_DEBUG "megasas: failed to setup sense pool "
++		       "fusion\n");
++		pci_pool_destroy(fusion->sg_dma_pool);
++		fusion->sg_dma_pool = NULL;
++		return -ENOMEM;
++	}
++
++	/*
++	 * Allocate and attach a frame to each of the commands in cmd_list
++	 */
++	for (i = 0; i < max_cmd; i++) {
++
++		cmd = fusion->cmd_list[i];
++
++		cmd->sg_frame = pci_pool_alloc(fusion->sg_dma_pool,
++					       GFP_KERNEL,
++					       &cmd->sg_frame_phys_addr);
++
++		cmd->sense = pci_pool_alloc(fusion->sense_dma_pool,
++					    GFP_KERNEL, &cmd->sense_phys_addr);
++		/*
++		 * megasas_teardown_frame_pool_fusion() takes care of freeing
++		 * whatever has been allocated
++		 */
++		if (!cmd->sg_frame || !cmd->sense) {
++			printk(KERN_DEBUG "megasas: pci_pool_alloc failed\n");
++			megasas_teardown_frame_pool_fusion(instance);
++			return -ENOMEM;
++		}
++	}
++	return 0;
++}
++
++/**
++ * megasas_alloc_cmds_fusion -	Allocates the command packets
++ * @instance:		Adapter soft state
++ *
++ *
++ * Each frame has a 32-bit field called context. This context is used to get
++ * back the megasas_cmd_fusion from the frame when a frame gets completed
++ * In this driver, the 32 bit values are the indices into an array cmd_list.
++ * This array is used only to look up the megasas_cmd_fusion given the context.
++ * The free commands themselves are maintained in a linked list called cmd_pool.
++ *
++ * cmds are formed in the io_request and sg_frame members of the
++ * megasas_cmd_fusion. The context field is used to get a request descriptor
++ * and is used as SMID of the cmd.
++ * SMID value range is from 1 to max_fw_cmds.
++ */
++int
++megasas_alloc_cmds_fusion(struct megasas_instance *instance)
++{
++	int i, j;
++	u32 max_cmd, io_frames_sz;
++	struct fusion_context *fusion;
++	struct megasas_cmd_fusion *cmd;
++	union MPI2_REPLY_DESCRIPTORS_UNION *reply_desc;
++	u32 offset;
++	dma_addr_t io_req_base_phys;
++	u8 *io_req_base;
++
++	fusion = instance->ctrl_context;
++
++	max_cmd = instance->max_fw_cmds;
++
++	fusion->req_frames_desc =
++		dma_alloc_coherent(&instance->pdev->dev,
++				   fusion->request_alloc_sz,
++				   &fusion->req_frames_desc_phys, GFP_KERNEL);
++
++	if (!fusion->req_frames_desc) {
++		printk(KERN_ERR "megasas; Could not allocate memory for "
++		       "request_frames\n");
++		goto fail_req_desc;
++	}
++
++	fusion->reply_frames_desc_pool =
++		pci_pool_create("reply_frames pool", instance->pdev,
++				fusion->reply_alloc_sz, 16, 0);
++
++	if (!fusion->reply_frames_desc_pool) {
++		printk(KERN_ERR "megasas; Could not allocate memory for "
++		       "reply_frame pool\n");
++		goto fail_reply_desc;
++	}
++
++	fusion->reply_frames_desc =
++		pci_pool_alloc(fusion->reply_frames_desc_pool, GFP_KERNEL,
++			       &fusion->reply_frames_desc_phys);
++	if (!fusion->reply_frames_desc) {
++		printk(KERN_ERR "megasas; Could not allocate memory for "
++		       "reply_frame pool\n");
++		pci_pool_destroy(fusion->reply_frames_desc_pool);
++		goto fail_reply_desc;
++	}
++
++	reply_desc = fusion->reply_frames_desc;
++	for (i = 0; i < fusion->reply_q_depth; i++, reply_desc++)
++		reply_desc->Words = ULLONG_MAX;
++
++	io_frames_sz = fusion->io_frames_alloc_sz;
++
++	fusion->io_request_frames_pool =
++		pci_pool_create("io_request_frames pool", instance->pdev,
++				fusion->io_frames_alloc_sz, 16, 0);
++
++	if (!fusion->io_request_frames_pool) {
++		printk(KERN_ERR "megasas: Could not allocate memory for "
++		       "io_request_frame pool\n");
++		goto fail_io_frames;
++	}
++
++	fusion->io_request_frames =
++		pci_pool_alloc(fusion->io_request_frames_pool, GFP_KERNEL,
++			       &fusion->io_request_frames_phys);
++	if (!fusion->io_request_frames) {
++		printk(KERN_ERR "megasas: Could not allocate memory for "
++		       "io_request_frames frames\n");
++		pci_pool_destroy(fusion->io_request_frames_pool);
++		goto fail_io_frames;
++	}
++
++	/*
++	 * fusion->cmd_list is an array of struct megasas_cmd_fusion pointers.
++	 * Allocate the dynamic array first and then allocate individual
++	 * commands.
++	 */
++	fusion->cmd_list = kmalloc(sizeof(struct megasas_cmd_fusion *)
++				   *max_cmd, GFP_KERNEL);
++
++	if (!fusion->cmd_list) {
++		printk(KERN_DEBUG "megasas: out of memory. Could not alloc "
++		       "memory for cmd_list_fusion\n");
++		goto fail_cmd_list;
++	}
++
++	memset(fusion->cmd_list, 0, sizeof(struct megasas_cmd_fusion *)
++	       *max_cmd);
++
++	max_cmd = instance->max_fw_cmds;
++	for (i = 0; i < max_cmd; i++) {
++		fusion->cmd_list[i] = kmalloc(sizeof(struct megasas_cmd_fusion),
++					      GFP_KERNEL);
++		if (!fusion->cmd_list[i]) {
++			printk(KERN_ERR "Could not alloc cmd list fusion\n");
++
++			for (j = 0; j < i; j++)
++				kfree(fusion->cmd_list[j]);
++
++			kfree(fusion->cmd_list);
++			fusion->cmd_list = NULL;
++			goto fail_cmd_list;
++		}
++	}
++
++	/* The first 256 bytes (SMID 0) is not used. Don't add to cmd list */
++	io_req_base = fusion->io_request_frames +
++		MEGA_MPI2_RAID_DEFAULT_IO_FRAME_SIZE;
++	io_req_base_phys = fusion->io_request_frames_phys +
++		MEGA_MPI2_RAID_DEFAULT_IO_FRAME_SIZE;
++
++	/*
++	 * Add all the commands to command pool (fusion->cmd_pool)
++	 */
++
++	/* SMID 0 is reserved. Set SMID/index from 1 */
++	for (i = 0; i < max_cmd; i++) {
++		cmd = fusion->cmd_list[i];
++		offset = MEGA_MPI2_RAID_DEFAULT_IO_FRAME_SIZE * i;
++		memset(cmd, 0, sizeof(struct megasas_cmd_fusion));
++		cmd->index = i + 1;
++		cmd->scmd = NULL;
++		cmd->sync_cmd_idx = (u32)ULONG_MAX; /* Set to Invalid */
++		cmd->instance = instance;
++		cmd->io_request =
++			(struct MPI2_RAID_SCSI_IO_REQUEST *)
++		  (io_req_base + offset);
++		memset(cmd->io_request, 0,
++		       sizeof(struct MPI2_RAID_SCSI_IO_REQUEST));
++		cmd->io_request_phys_addr = io_req_base_phys + offset;
++
++		list_add_tail(&cmd->list, &fusion->cmd_pool);
++	}
++
++	/*
++	 * Create a frame pool and assign one frame to each cmd
++	 */
++	if (megasas_create_frame_pool_fusion(instance)) {
++		printk(KERN_DEBUG "megasas: Error creating frame DMA pool\n");
++		megasas_free_cmds_fusion(instance);
++		goto fail_req_desc;
++	}
++
++	return 0;
++
++fail_cmd_list:
++	pci_pool_free(fusion->io_request_frames_pool, fusion->io_request_frames,
++		      fusion->io_request_frames_phys);
++	pci_pool_destroy(fusion->io_request_frames_pool);
++fail_io_frames:
++	dma_free_coherent(&instance->pdev->dev, fusion->request_alloc_sz,
++			  fusion->reply_frames_desc,
++			  fusion->reply_frames_desc_phys);
++	pci_pool_free(fusion->reply_frames_desc_pool,
++		      fusion->reply_frames_desc,
++		      fusion->reply_frames_desc_phys);
++	pci_pool_destroy(fusion->reply_frames_desc_pool);
++
++fail_reply_desc:
++	dma_free_coherent(&instance->pdev->dev, fusion->request_alloc_sz,
++			  fusion->req_frames_desc,
++			  fusion->req_frames_desc_phys);
++fail_req_desc:
++	return -ENOMEM;
++}
++
++/**
++ * wait_and_poll -	Issues a polling command
++ * @instance:			Adapter soft state
++ * @cmd:			Command packet to be issued
++ *
++ * For polling, MFI requires the cmd_status to be set to 0xFF before posting.
++ */
++int
++wait_and_poll(struct megasas_instance *instance, struct megasas_cmd *cmd)
++{
++	int i;
++	struct megasas_header *frame_hdr = &cmd->frame->hdr;
++
++	u32 msecs = MFI_POLL_TIMEOUT_SECS * 1000;
++
++	/*
++	 * Wait for cmd_status to change
++	 */
++	for (i = 0; (i < msecs) && (frame_hdr->cmd_status == 0xff); i += 20) {
++		rmb();
++		msleep(20);
++	}
++
++	if (frame_hdr->cmd_status == 0xff)
++		return -ETIME;
++
++	return 0;
++}
++
++/**
++ * megasas_ioc_init_fusion -	Initializes the FW
++ * @instance:		Adapter soft state
++ *
++ * Issues the IOC Init cmd
++ */
++int
++megasas_ioc_init_fusion(struct megasas_instance *instance)
++{
++	struct megasas_init_frame *init_frame;
++	struct MPI2_IOC_INIT_REQUEST *IOCInitMessage;
++	dma_addr_t	ioc_init_handle;
++	u32 context;
++	struct megasas_cmd *cmd;
++	u8 ret;
++	struct fusion_context *fusion;
++	union MEGASAS_REQUEST_DESCRIPTOR_UNION *req_desc;
++	int i;
++	struct megasas_header *frame_hdr;
++
++	fusion = instance->ctrl_context;
++
++	cmd = megasas_get_cmd(instance);
++
++	if (!cmd) {
++		printk(KERN_ERR "Could not allocate cmd for INIT Frame\n");
++		ret = 1;
++		goto fail_get_cmd;
++	}
++
++	IOCInitMessage =
++	  dma_alloc_coherent(&instance->pdev->dev,
++			     sizeof(struct MPI2_IOC_INIT_REQUEST),
++			     &ioc_init_handle, GFP_KERNEL);
++
++	if (!IOCInitMessage) {
++		printk(KERN_ERR "Could not allocate memory for "
++		       "IOCInitMessage\n");
++		ret = 1;
++		goto fail_fw_init;
++	}
++
++	memset(IOCInitMessage, 0, sizeof(struct MPI2_IOC_INIT_REQUEST));
++
++	IOCInitMessage->Function = MPI2_FUNCTION_IOC_INIT;
++	IOCInitMessage->WhoInit	= MPI2_WHOINIT_HOST_DRIVER;
++	IOCInitMessage->MsgVersion = MPI2_VERSION;
++	IOCInitMessage->HeaderVersion = MPI2_HEADER_VERSION;
++	IOCInitMessage->SystemRequestFrameSize =
++		MEGA_MPI2_RAID_DEFAULT_IO_FRAME_SIZE / 4;
++
++	IOCInitMessage->ReplyDescriptorPostQueueDepth = fusion->reply_q_depth;
++	IOCInitMessage->ReplyDescriptorPostQueueAddress	=
++		fusion->reply_frames_desc_phys;
++	IOCInitMessage->SystemRequestFrameBaseAddress =
++		fusion->io_request_frames_phys;
++
++	init_frame = (struct megasas_init_frame *)cmd->frame;
++	memset(init_frame, 0, MEGAMFI_FRAME_SIZE);
++
++	frame_hdr = &cmd->frame->hdr;
++	context = init_frame->context;
++	init_frame->context = context;
++
++	frame_hdr->cmd_status = 0xFF;
++	frame_hdr->flags |= MFI_FRAME_DONT_POST_IN_REPLY_QUEUE;
++
++	init_frame->cmd	= MFI_CMD_INIT;
++	init_frame->cmd_status = 0xFF;
++
++	init_frame->queue_info_new_phys_addr_lo = ioc_init_handle;
++	init_frame->data_xfer_len = sizeof(struct MPI2_IOC_INIT_REQUEST);
++
++	req_desc =
++	  (union MEGASAS_REQUEST_DESCRIPTOR_UNION *)fusion->req_frames_desc;
++
++	req_desc->Words = cmd->frame_phys_addr;
++	req_desc->MFAIo.RequestFlags =
++		(MEGASAS_REQ_DESCRIPT_FLAGS_MFA <<
++		 MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
++
++	/*
++	 * disable the intr before firing the init frame
++	 */
++	instance->instancet->disable_intr(instance->reg_set);
++
++	for (i = 0; i < (10 * 1000); i += 20) {
++		if (readl(&instance->reg_set->doorbell) & 1)
++			msleep(20);
++		else
++			break;
++	}
++
++	instance->instancet->fire_cmd(instance, req_desc->u.low,
++				      req_desc->u.high, instance->reg_set);
++
++	wait_and_poll(instance, cmd);
++
++	frame_hdr = &cmd->frame->hdr;
++	if (frame_hdr->cmd_status != 0) {
++		ret = 1;
++		goto fail_fw_init;
++	}
++	printk(KERN_ERR "megasas:IOC Init cmd success\n");
++
++	ret = 0;
++
++fail_fw_init:
++	megasas_return_cmd(instance, cmd);
++	if (IOCInitMessage)
++		dma_free_coherent(&instance->pdev->dev,
++				  sizeof(struct MPI2_IOC_INIT_REQUEST),
++				  IOCInitMessage, ioc_init_handle);
++fail_get_cmd:
++	return ret;
++}
++
++/*
++ * megasas_return_cmd_for_smid -	Returns a cmd_fusion for a SMID
++ * @instance:				Adapter soft state
++ *
++ */
++void
++megasas_return_cmd_for_smid(struct megasas_instance *instance, u16 smid)
++{
++	struct fusion_context *fusion;
++	struct megasas_cmd_fusion *cmd;
++
++	fusion = instance->ctrl_context;
++	cmd = fusion->cmd_list[smid - 1];
++	megasas_return_cmd_fusion(instance, cmd);
++}
++
++/*
++ * megasas_get_ld_map_info -	Returns FW's ld_map structure
++ * @instance:				Adapter soft state
++ * @pend:				Pend the command or not
++ * Issues an internal command (DCMD) to get the FW's controller PD
++ * list structure.  This information is mainly used to find out SYSTEM
++ * supported by the FW.
++ */
++static int
++megasas_get_ld_map_info(struct megasas_instance *instance)
++{
++	int ret = 0;
++	struct megasas_cmd *cmd;
++	struct megasas_dcmd_frame *dcmd;
++	struct MR_FW_RAID_MAP_ALL *ci;
++	dma_addr_t ci_h = 0;
++	u32 size_map_info;
++	struct fusion_context *fusion;
++
++	cmd = megasas_get_cmd(instance);
++
++	if (!cmd) {
++		printk(KERN_DEBUG "megasas: Failed to get cmd for map info.\n");
++		return -ENOMEM;
++	}
++
++	fusion = instance->ctrl_context;
++
++	if (!fusion) {
++		megasas_return_cmd(instance, cmd);
++		return 1;
++	}
++
++	dcmd = &cmd->frame->dcmd;
++
++	size_map_info = sizeof(struct MR_FW_RAID_MAP) +
++		(sizeof(struct MR_LD_SPAN_MAP) *(MAX_LOGICAL_DRIVES - 1));
++
++	ci = fusion->ld_map[(instance->map_id & 1)];
++	ci_h = fusion->ld_map_phys[(instance->map_id & 1)];
++
++	if (!ci) {
++		printk(KERN_DEBUG "Failed to alloc mem for ld_map_info\n");
++		megasas_return_cmd(instance, cmd);
++		return -ENOMEM;
++	}
++
++	memset(ci, 0, sizeof(*ci));
++	memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
++
++	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 = size_map_info;
++	dcmd->opcode = MR_DCMD_LD_MAP_GET_INFO;
++	dcmd->sgl.sge32[0].phys_addr = ci_h;
++	dcmd->sgl.sge32[0].length = size_map_info;
++
++	if (!megasas_issue_polled(instance, cmd))
++		ret = 0;
++	else {
++		printk(KERN_ERR "megasas: Get LD Map Info Failed\n");
++		ret = -1;
++	}
++
++	megasas_return_cmd(instance, cmd);
++
++	return ret;
++}
++
++u8
++megasas_get_map_info(struct megasas_instance *instance)
++{
++	struct fusion_context *fusion = instance->ctrl_context;
++
++	fusion->fast_path_io = 0;
++	if (!megasas_get_ld_map_info(instance)) {
++		if (MR_ValidateMapInfo(fusion->ld_map[(instance->map_id & 1)],
++				       fusion->load_balance_info)) {
++			fusion->fast_path_io = 1;
++			return 0;
++		}
++	}
++	return 1;
++}
++
++/*
++ * megasas_sync_map_info -	Returns FW's ld_map structure
++ * @instance:				Adapter soft state
++ *
++ * Issues an internal command (DCMD) to get the FW's controller PD
++ * list structure.  This information is mainly used to find out SYSTEM
++ * supported by the FW.
++ */
++int
++megasas_sync_map_info(struct megasas_instance *instance)
++{
++	int ret = 0, i;
++	struct megasas_cmd *cmd;
++	struct megasas_dcmd_frame *dcmd;
++	u32 size_sync_info, num_lds;
++	struct fusion_context *fusion;
++	struct MR_LD_TARGET_SYNC *ci = NULL;
++	struct MR_FW_RAID_MAP_ALL *map;
++	struct MR_LD_RAID  *raid;
++	struct MR_LD_TARGET_SYNC *ld_sync;
++	dma_addr_t ci_h = 0;
++	u32 size_map_info;
++
++	cmd = megasas_get_cmd(instance);
++
++	if (!cmd) {
++		printk(KERN_DEBUG "megasas: Failed to get cmd for sync"
++		       "info.\n");
++		return -ENOMEM;
++	}
++
++	fusion = instance->ctrl_context;
++
++	if (!fusion) {
++		megasas_return_cmd(instance, cmd);
++		return 1;
++	}
++
++	map = fusion->ld_map[instance->map_id & 1];
++
++	num_lds = map->raidMap.ldCount;
++
++	dcmd = &cmd->frame->dcmd;
++
++	size_sync_info = sizeof(struct MR_LD_TARGET_SYNC) *num_lds;
++
++	memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
++
++	ci = (struct MR_LD_TARGET_SYNC *)
++	  fusion->ld_map[(instance->map_id - 1) & 1];
++	memset(ci, 0, sizeof(struct MR_FW_RAID_MAP_ALL));
++
++	ci_h = fusion->ld_map_phys[(instance->map_id - 1) & 1];
++
++	ld_sync = (struct MR_LD_TARGET_SYNC *)ci;
++
++	for (i = 0; i < num_lds; i++, ld_sync++) {
++		raid = MR_LdRaidGet(i, map);
++		ld_sync->targetId = MR_GetLDTgtId(i, map);
++		ld_sync->seqNum = raid->seqNum;
++	}
++
++	size_map_info = sizeof(struct MR_FW_RAID_MAP) +
++		(sizeof(struct MR_LD_SPAN_MAP) *(MAX_LOGICAL_DRIVES - 1));
++
++	dcmd->cmd = MFI_CMD_DCMD;
++	dcmd->cmd_status = 0xFF;
++	dcmd->sge_count = 1;
++	dcmd->flags = MFI_FRAME_DIR_WRITE;
++	dcmd->timeout = 0;
++	dcmd->pad_0 = 0;
++	dcmd->data_xfer_len = size_map_info;
++	dcmd->mbox.b[0] = num_lds;
++	dcmd->mbox.b[1] = MEGASAS_DCMD_MBOX_PEND_FLAG;
++	dcmd->opcode = MR_DCMD_LD_MAP_GET_INFO;
++	dcmd->sgl.sge32[0].phys_addr = ci_h;
++	dcmd->sgl.sge32[0].length = size_map_info;
++
++	instance->map_update_cmd = cmd;
++
++	instance->instancet->issue_dcmd(instance, cmd);
++
++	return ret;
++}
++
++/**
++ * megasas_init_adapter_fusion -	Initializes the FW
++ * @instance:		Adapter soft state
++ *
++ * This is the main function for initializing firmware.
++ */
++u32
++megasas_init_adapter_fusion(struct megasas_instance *instance)
++{
++	struct megasas_register_set __iomem *reg_set;
++	struct fusion_context *fusion;
++	u32 max_cmd;
++	int i = 0;
++
++	fusion = instance->ctrl_context;
++
++	reg_set = instance->reg_set;
++
++	/*
++	 * Get various operational parameters from status register
++	 */
++	instance->max_fw_cmds =
++		instance->instancet->read_fw_status_reg(reg_set) & 0x00FFFF;
++	instance->max_fw_cmds = min(instance->max_fw_cmds, (u16)1008);
++
++	/*
++	 * 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)
++	 * does not exceed max cmds that the FW can support
++	 */
++	instance->max_fw_cmds = instance->max_fw_cmds-1;
++	/* Only internal cmds (DCMD) need to have MFI frames */
++	instance->max_mfi_cmds = MEGASAS_INT_CMDS;
++
++	max_cmd = instance->max_fw_cmds;
++
++	fusion->reply_q_depth = ((max_cmd + 1 + 15)/16)*16;
++
++	fusion->request_alloc_sz =
++		sizeof(union MEGASAS_REQUEST_DESCRIPTOR_UNION) *max_cmd;
++	fusion->reply_alloc_sz = sizeof(union MPI2_REPLY_DESCRIPTORS_UNION)
++		*(fusion->reply_q_depth);
++	fusion->io_frames_alloc_sz = MEGA_MPI2_RAID_DEFAULT_IO_FRAME_SIZE +
++		(MEGA_MPI2_RAID_DEFAULT_IO_FRAME_SIZE *
++		 (max_cmd + 1)); /* Extra 1 for SMID 0 */
++
++	fusion->max_sge_in_main_msg =
++	  (MEGA_MPI2_RAID_DEFAULT_IO_FRAME_SIZE -
++	   offsetof(struct MPI2_RAID_SCSI_IO_REQUEST, SGL))/16;
++
++	fusion->max_sge_in_chain =
++		MEGASAS_MAX_SZ_CHAIN_FRAME / sizeof(union MPI2_SGE_IO_UNION);
++
++	instance->max_num_sge = fusion->max_sge_in_main_msg +
++		fusion->max_sge_in_chain - 2;
++
++	/* Used for pass thru MFI frame (DCMD) */
++	fusion->chain_offset_mfi_pthru =
++		offsetof(struct MPI2_RAID_SCSI_IO_REQUEST, SGL)/16;
++
++	fusion->chain_offset_io_request =
++		(MEGA_MPI2_RAID_DEFAULT_IO_FRAME_SIZE -
++		 sizeof(union MPI2_SGE_IO_UNION))/16;
++
++	fusion->last_reply_idx = 0;
++
++	/*
++	 * Allocate memory for descriptors
++	 * Create a pool of commands
++	 */
++	if (megasas_alloc_cmds(instance))
++		goto fail_alloc_mfi_cmds;
++	if (megasas_alloc_cmds_fusion(instance))
++		goto fail_alloc_cmds;
++
++	if (megasas_ioc_init_fusion(instance))
++		goto fail_ioc_init;
++
++	instance->flag_ieee = 1;
++
++	fusion->map_sz =  sizeof(struct MR_FW_RAID_MAP) +
++	  (sizeof(struct MR_LD_SPAN_MAP) *(MAX_LOGICAL_DRIVES - 1));
++
++	fusion->fast_path_io = 0;
++
++	for (i = 0; i < 2; i++) {
++		fusion->ld_map[i] = dma_alloc_coherent(&instance->pdev->dev,
++						       fusion->map_sz,
++						       &fusion->ld_map_phys[i],
++						       GFP_KERNEL);
++		if (!fusion->ld_map[i]) {
++			printk(KERN_ERR "megasas: Could not allocate memory "
++			       "for map info\n");
++			goto fail_map_info;
++		}
++	}
++
++	if (!megasas_get_map_info(instance))
++		megasas_sync_map_info(instance);
++
++	return 0;
++
++fail_alloc_cmds:
++fail_alloc_mfi_cmds:
++fail_map_info:
++	if (i == 1)
++		dma_free_coherent(&instance->pdev->dev, fusion->map_sz,
++				  fusion->ld_map[0], fusion->ld_map_phys[0]);
++fail_ioc_init:
++	return 1;
++}
++
++/**
++ * megasas_fire_cmd_fusion -	Sends command to the FW
++ * @frame_phys_addr :		Physical address of cmd
++ * @frame_count :		Number of frames for the command
++ * @regs :			MFI register set
++ */
++void
++megasas_fire_cmd_fusion(struct megasas_instance *instance,
++			dma_addr_t req_desc_lo,
++			u32 req_desc_hi,
++			struct megasas_register_set __iomem *regs)
++{
++	unsigned long flags;
++
++	spin_lock_irqsave(&instance->hba_lock, flags);
++
++	writel(req_desc_lo,
++	       &(regs)->inbound_low_queue_port);
++	writel(req_desc_hi, &(regs)->inbound_high_queue_port);
++	spin_unlock_irqrestore(&instance->hba_lock, flags);
++}
++
++/**
++ * map_cmd_status -	Maps FW cmd status to OS cmd status
++ * @cmd :		Pointer to cmd
++ * @status :		status of cmd returned by FW
++ * @ext_status :	ext status of cmd returned by FW
++ */
++
++void
++map_cmd_status(struct megasas_cmd_fusion *cmd, u8 status, u8 ext_status)
++{
++
++	switch (status) {
++
++	case MFI_STAT_OK:
++		cmd->scmd->result = DID_OK << 16;
++		break;
++
++	case MFI_STAT_SCSI_IO_FAILED:
++	case MFI_STAT_LD_INIT_IN_PROGRESS:
++		cmd->scmd->result = (DID_ERROR << 16) | ext_status;
++		break;
++
++	case MFI_STAT_SCSI_DONE_WITH_ERROR:
++
++		cmd->scmd->result = (DID_OK << 16) | ext_status;
++		if (ext_status == SAM_STAT_CHECK_CONDITION) {
++			memset(cmd->scmd->sense_buffer, 0,
++			       SCSI_SENSE_BUFFERSIZE);
++			memcpy(cmd->scmd->sense_buffer, cmd->sense,
++			       SCSI_SENSE_BUFFERSIZE);
++			cmd->scmd->result |= DRIVER_SENSE << 24;
++		}
++		break;
++
++	case MFI_STAT_LD_OFFLINE:
++	case MFI_STAT_DEVICE_NOT_FOUND:
++		cmd->scmd->result = DID_BAD_TARGET << 16;
++		break;
++
++	default:
++		printk(KERN_DEBUG "megasas: FW status %#x\n", status);
++		cmd->scmd->result = DID_ERROR << 16;
++		break;
++	}
++}
++
++/**
++ * megasas_make_sgl_fusion -	Prepares 32-bit SGL
++ * @instance:		Adapter soft state
++ * @scp:		SCSI command from the mid-layer
++ * @sgl_ptr:		SGL to be filled in
++ * @cmd:		cmd we are working on
++ *
++ * If successful, this function returns the number of SG elements.
++ */
++static int
++megasas_make_sgl_fusion(struct megasas_instance *instance,
++			struct scsi_cmnd *scp,
++			struct MPI25_IEEE_SGE_CHAIN64 *sgl_ptr,
++			struct megasas_cmd_fusion *cmd)
++{
++	int i, sg_processed;
++	int sge_count, sge_idx;
++	struct scatterlist *os_sgl;
++	struct fusion_context *fusion;
++
++	fusion = instance->ctrl_context;
++
++	cmd->io_request->ChainOffset = 0;
++
++	sge_count = scsi_dma_map(scp);
++
++	BUG_ON(sge_count < 0);
++
++	if (sge_count > instance->max_num_sge || !sge_count)
++		return sge_count;
++
++	if (sge_count > fusion->max_sge_in_main_msg) {
++		/* One element to store the chain info */
++		sge_idx = fusion->max_sge_in_main_msg - 1;
++	} else
++		sge_idx = sge_count;
++
++	scsi_for_each_sg(scp, os_sgl, sge_count, i) {
++		sgl_ptr->Length = sg_dma_len(os_sgl);
++		sgl_ptr->Address = sg_dma_address(os_sgl);
++		sgl_ptr->Flags = 0;
++		sgl_ptr++;
++
++		sg_processed = i + 1;
++
++		if ((sg_processed ==  (fusion->max_sge_in_main_msg - 1)) &&
++		    (sge_count > fusion->max_sge_in_main_msg)) {
++
++			struct MPI25_IEEE_SGE_CHAIN64 *sg_chain;
++			cmd->io_request->ChainOffset =
++				fusion->chain_offset_io_request;
++			sg_chain = sgl_ptr;
++			/* Prepare chain element */
++			sg_chain->NextChainOffset = 0;
++			sg_chain->Flags = (IEEE_SGE_FLAGS_CHAIN_ELEMENT |
++					   MPI2_IEEE_SGE_FLAGS_IOCPLBNTA_ADDR);
++			sg_chain->Length =  (sizeof(union MPI2_SGE_IO_UNION)
++					     *(sge_count - sg_processed));
++			sg_chain->Address = cmd->sg_frame_phys_addr;
++
++			sgl_ptr =
++			  (struct MPI25_IEEE_SGE_CHAIN64 *)cmd->sg_frame;
++		}
++	}
++
++	return sge_count;
++}
++
++/**
++ * megasas_set_pd_lba -	Sets PD LBA
++ * @cdb:		CDB
++ * @cdb_len:		cdb length
++ * @start_blk:		Start block of IO
++ *
++ * Used to set the PD LBA in CDB for FP IOs
++ */
++void
++megasas_set_pd_lba(struct MPI2_RAID_SCSI_IO_REQUEST *io_request, u8 cdb_len,
++		   struct IO_REQUEST_INFO *io_info, struct scsi_cmnd *scp,
++		   struct MR_FW_RAID_MAP_ALL *local_map_ptr, u32 ref_tag)
++{
++	struct MR_LD_RAID *raid;
++	u32 ld;
++	u64 start_blk = io_info->pdBlock;
++	u8 *cdb = io_request->CDB.CDB32;
++	u32 num_blocks = io_info->numBlocks;
++	u8 opcode, flagvals, groupnum, control;
++
++	/* Check if T10 PI (DIF) is enabled for this LD */
++	ld = MR_TargetIdToLdGet(io_info->ldTgtId, local_map_ptr);
++	raid = MR_LdRaidGet(ld, local_map_ptr);
++	if (raid->capability.ldPiMode == MR_PROT_INFO_TYPE_CONTROLLER) {
++		memset(cdb, 0, sizeof(io_request->CDB.CDB32));
++		cdb[0] =  MEGASAS_SCSI_VARIABLE_LENGTH_CMD;
++		cdb[7] =  MEGASAS_SCSI_ADDL_CDB_LEN;
++
++		if (scp->sc_data_direction == PCI_DMA_FROMDEVICE)
++			cdb[9] = MEGASAS_SCSI_SERVICE_ACTION_READ32;
++		else
++			cdb[9] = MEGASAS_SCSI_SERVICE_ACTION_WRITE32;
++		cdb[10] = MEGASAS_RD_WR_PROTECT_CHECK_ALL;
++
++		/* LBA */
++		cdb[12] = (u8)((start_blk >> 56) & 0xff);
++		cdb[13] = (u8)((start_blk >> 48) & 0xff);
++		cdb[14] = (u8)((start_blk >> 40) & 0xff);
++		cdb[15] = (u8)((start_blk >> 32) & 0xff);
++		cdb[16] = (u8)((start_blk >> 24) & 0xff);
++		cdb[17] = (u8)((start_blk >> 16) & 0xff);
++		cdb[18] = (u8)((start_blk >> 8) & 0xff);
++		cdb[19] = (u8)(start_blk & 0xff);
++
++		/* Logical block reference tag */
++		io_request->CDB.EEDP32.PrimaryReferenceTag =
++			cpu_to_be32(ref_tag);
++		io_request->CDB.EEDP32.PrimaryApplicationTagMask = 0xffff;
++
++		io_request->DataLength = num_blocks * 512;
++		io_request->IoFlags = 32; /* Specify 32-byte cdb */
++
++		/* Transfer length */
++		cdb[28] = (u8)((num_blocks >> 24) & 0xff);
++		cdb[29] = (u8)((num_blocks >> 16) & 0xff);
++		cdb[30] = (u8)((num_blocks >> 8) & 0xff);
++		cdb[31] = (u8)(num_blocks & 0xff);
++
++		/* set SCSI IO EEDPFlags */
++		if (scp->sc_data_direction == PCI_DMA_FROMDEVICE) {
++			io_request->EEDPFlags =
++				MPI2_SCSIIO_EEDPFLAGS_INC_PRI_REFTAG  |
++				MPI2_SCSIIO_EEDPFLAGS_CHECK_REFTAG |
++				MPI2_SCSIIO_EEDPFLAGS_CHECK_REMOVE_OP |
++				MPI2_SCSIIO_EEDPFLAGS_CHECK_APPTAG |
++				MPI2_SCSIIO_EEDPFLAGS_CHECK_GUARD;
++		} else {
++			io_request->EEDPFlags =
++				MPI2_SCSIIO_EEDPFLAGS_INC_PRI_REFTAG |
++				MPI2_SCSIIO_EEDPFLAGS_INSERT_OP;
++		}
++		io_request->Control |= (0x4 << 26);
++		io_request->EEDPBlockSize = MEGASAS_EEDPBLOCKSIZE;
++	} else {
++		/* Some drives don't support 16/12 byte CDB's, convert to 10 */
++		if (((cdb_len == 12) || (cdb_len == 16)) &&
++		    (start_blk <= 0xffffffff)) {
++			if (cdb_len == 16) {
++				opcode = cdb[0] == READ_16 ? READ_10 : WRITE_10;
++				flagvals = cdb[1];
++				groupnum = cdb[14];
++				control = cdb[15];
++			} else {
++				opcode = cdb[0] == READ_12 ? READ_10 : WRITE_10;
++				flagvals = cdb[1];
++				groupnum = cdb[10];
++				control = cdb[11];
++			}
++
++			memset(cdb, 0, sizeof(io_request->CDB.CDB32));
++
++			cdb[0] = opcode;
++			cdb[1] = flagvals;
++			cdb[6] = groupnum;
++			cdb[9] = control;
++
++			/* Transfer length */
++			cdb[8] = (u8)(num_blocks & 0xff);
++			cdb[7] = (u8)((num_blocks >> 8) & 0xff);
++
++			cdb_len = 10;
++		}
++
++		/* Normal case, just load LBA here */
++		switch (cdb_len) {
++		case 6:
++		{
++			u8 val = cdb[1] & 0xE0;
++			cdb[3] = (u8)(start_blk & 0xff);
++			cdb[2] = (u8)((start_blk >> 8) & 0xff);
++			cdb[1] = val | ((u8)(start_blk >> 16) & 0x1f);
++			break;
++		}
++		case 10:
++			cdb[5] = (u8)(start_blk & 0xff);
++			cdb[4] = (u8)((start_blk >> 8) & 0xff);
++			cdb[3] = (u8)((start_blk >> 16) & 0xff);
++			cdb[2] = (u8)((start_blk >> 24) & 0xff);
++			break;
++		case 12:
++			cdb[5]    = (u8)(start_blk & 0xff);
++			cdb[4]    = (u8)((start_blk >> 8) & 0xff);
++			cdb[3]    = (u8)((start_blk >> 16) & 0xff);
++			cdb[2]    = (u8)((start_blk >> 24) & 0xff);
++			break;
++		case 16:
++			cdb[9]    = (u8)(start_blk & 0xff);
++			cdb[8]    = (u8)((start_blk >> 8) & 0xff);
++			cdb[7]    = (u8)((start_blk >> 16) & 0xff);
++			cdb[6]    = (u8)((start_blk >> 24) & 0xff);
++			cdb[5]    = (u8)((start_blk >> 32) & 0xff);
++			cdb[4]    = (u8)((start_blk >> 40) & 0xff);
++			cdb[3]    = (u8)((start_blk >> 48) & 0xff);
++			cdb[2]    = (u8)((start_blk >> 56) & 0xff);
++			break;
++		}
++	}
++}
++
++/**
++ * megasas_build_ldio_fusion -	Prepares IOs to devices
++ * @instance:		Adapter soft state
++ * @scp:		SCSI command
++ * @cmd:		Command to be prepared
++ *
++ * Prepares the io_request and chain elements (sg_frame) for IO
++ * The IO can be for PD (Fast Path) or LD
++ */
++void
++megasas_build_ldio_fusion(struct megasas_instance *instance,
++			  struct scsi_cmnd *scp,
++			  struct megasas_cmd_fusion *cmd)
++{
++	u8 fp_possible;
++	u32 start_lba_lo, start_lba_hi, device_id;
++	struct MPI2_RAID_SCSI_IO_REQUEST *io_request;
++	union MEGASAS_REQUEST_DESCRIPTOR_UNION *req_desc;
++	struct IO_REQUEST_INFO io_info;
++	struct fusion_context *fusion;
++	struct MR_FW_RAID_MAP_ALL *local_map_ptr;
++
++	device_id = MEGASAS_DEV_INDEX(instance, scp);
++
++	fusion = instance->ctrl_context;
++
++	io_request = cmd->io_request;
++	io_request->RaidContext.VirtualDiskTgtId = device_id;
++	io_request->RaidContext.status = 0;
++	io_request->RaidContext.exStatus = 0;
++
++	req_desc = (union MEGASAS_REQUEST_DESCRIPTOR_UNION *)cmd->request_desc;
++
++	start_lba_lo = 0;
++	start_lba_hi = 0;
++	fp_possible = 0;
++
++	/*
++	 * 6-byte READ(0x08) or WRITE(0x0A) cdb
++	 */
++	if (scp->cmd_len == 6) {
++		io_request->DataLength = (u32) scp->cmnd[4];
++		start_lba_lo = ((u32) scp->cmnd[1] << 16) |
++			((u32) scp->cmnd[2] << 8) | (u32) scp->cmnd[3];
++
++		start_lba_lo &= 0x1FFFFF;
++	}
++
++	/*
++	 * 10-byte READ(0x28) or WRITE(0x2A) cdb
++	 */
++	else if (scp->cmd_len == 10) {
++		io_request->DataLength = (u32) scp->cmnd[8] |
++			((u32) scp->cmnd[7] << 8);
++		start_lba_lo = ((u32) scp->cmnd[2] << 24) |
++			((u32) scp->cmnd[3] << 16) |
++			((u32) scp->cmnd[4] << 8) | (u32) scp->cmnd[5];
++	}
++
++	/*
++	 * 12-byte READ(0xA8) or WRITE(0xAA) cdb
++	 */
++	else if (scp->cmd_len == 12) {
++		io_request->DataLength = ((u32) scp->cmnd[6] << 24) |
++			((u32) scp->cmnd[7] << 16) |
++			((u32) scp->cmnd[8] << 8) | (u32) scp->cmnd[9];
++		start_lba_lo = ((u32) scp->cmnd[2] << 24) |
++			((u32) scp->cmnd[3] << 16) |
++			((u32) scp->cmnd[4] << 8) | (u32) scp->cmnd[5];
++	}
++
++	/*
++	 * 16-byte READ(0x88) or WRITE(0x8A) cdb
++	 */
++	else if (scp->cmd_len == 16) {
++		io_request->DataLength = ((u32) scp->cmnd[10] << 24) |
++			((u32) scp->cmnd[11] << 16) |
++			((u32) scp->cmnd[12] << 8) | (u32) scp->cmnd[13];
++		start_lba_lo = ((u32) scp->cmnd[6] << 24) |
++			((u32) scp->cmnd[7] << 16) |
++			((u32) scp->cmnd[8] << 8) | (u32) scp->cmnd[9];
++
++		start_lba_hi = ((u32) scp->cmnd[2] << 24) |
++			((u32) scp->cmnd[3] << 16) |
++			((u32) scp->cmnd[4] << 8) | (u32) scp->cmnd[5];
++	}
++
++	memset(&io_info, 0, sizeof(struct IO_REQUEST_INFO));
++	io_info.ldStartBlock = ((u64)start_lba_hi << 32) | start_lba_lo;
++	io_info.numBlocks = io_request->DataLength;
++	io_info.ldTgtId = device_id;
++
++	if (scp->sc_data_direction == PCI_DMA_FROMDEVICE)
++		io_info.isRead = 1;
++
++	local_map_ptr = fusion->ld_map[(instance->map_id & 1)];
++
++	if ((MR_TargetIdToLdGet(device_id, local_map_ptr) >=
++	     MAX_LOGICAL_DRIVES) || (!fusion->fast_path_io)) {
++		io_request->RaidContext.regLockFlags  = 0;
++		fp_possible = 0;
++	} else {
++		if (MR_BuildRaidContext(&io_info, &io_request->RaidContext,
++					local_map_ptr))
++			fp_possible = io_info.fpOkForIo;
++	}
++
++	if (fp_possible) {
++		megasas_set_pd_lba(io_request, scp->cmd_len, &io_info, scp,
++				   local_map_ptr, start_lba_lo);
++		io_request->DataLength = scsi_bufflen(scp);
++		io_request->Function = MPI2_FUNCTION_SCSI_IO_REQUEST;
++		cmd->request_desc->SCSIIO.RequestFlags =
++			(MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY
++			 << MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
++		if ((fusion->load_balance_info[device_id].loadBalanceFlag) &&
++		    (io_info.isRead)) {
++			io_info.devHandle =
++				get_updated_dev_handle(
++					&fusion->load_balance_info[device_id],
++					&io_info);
++			scp->SCp.Status |= MEGASAS_LOAD_BALANCE_FLAG;
++		} else
++			scp->SCp.Status &= ~MEGASAS_LOAD_BALANCE_FLAG;
++		cmd->request_desc->SCSIIO.DevHandle = io_info.devHandle;
++		io_request->DevHandle = io_info.devHandle;
++	} else {
++		io_request->RaidContext.timeoutValue =
++			local_map_ptr->raidMap.fpPdIoTimeoutSec;
++		io_request->Function = MEGASAS_MPI2_FUNCTION_LD_IO_REQUEST;
++		io_request->DevHandle = device_id;
++		cmd->request_desc->SCSIIO.RequestFlags =
++			(MEGASAS_REQ_DESCRIPT_FLAGS_LD_IO
++			 << MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
++	} /* Not FP */
++}
++
++/**
++ * megasas_build_dcdb_fusion -	Prepares IOs to devices
++ * @instance:		Adapter soft state
++ * @scp:		SCSI command
++ * @cmd:		Command to be prepared
++ *
++ * Prepares the io_request frame for non-io cmds
++ */
++static void
++megasas_build_dcdb_fusion(struct megasas_instance *instance,
++			  struct scsi_cmnd *scmd,
++			  struct megasas_cmd_fusion *cmd)
++{
++	u32 device_id;
++	struct MPI2_RAID_SCSI_IO_REQUEST *io_request;
++	u16 pd_index = 0;
++	struct MR_FW_RAID_MAP_ALL *local_map_ptr;
++	struct fusion_context *fusion = instance->ctrl_context;
++
++	io_request = cmd->io_request;
++	device_id = MEGASAS_DEV_INDEX(instance, scmd);
++	pd_index = (scmd->device->channel * MEGASAS_MAX_DEV_PER_CHANNEL)
++		+scmd->device->id;
++	local_map_ptr = fusion->ld_map[(instance->map_id & 1)];
++
++	/* Check if this is a system PD I/O */
++	if ((instance->pd_list[pd_index].driveState == MR_PD_STATE_SYSTEM) &&
++	    (instance->pd_list[pd_index].driveType == TYPE_DISK)) {
++		io_request->Function = 0;
++		io_request->DevHandle =
++			local_map_ptr->raidMap.devHndlInfo[device_id].curDevHdl;
++		io_request->RaidContext.timeoutValue =
++			local_map_ptr->raidMap.fpPdIoTimeoutSec;
++		io_request->RaidContext.regLockFlags = 0;
++		io_request->RaidContext.regLockRowLBA = 0;
++		io_request->RaidContext.regLockLength = 0;
++		io_request->RaidContext.RAIDFlags =
++			MR_RAID_FLAGS_IO_SUB_TYPE_SYSTEM_PD <<
++			MR_RAID_CTX_RAID_FLAGS_IO_SUB_TYPE_SHIFT;
++		cmd->request_desc->SCSIIO.RequestFlags =
++			(MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY <<
++			 MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
++	} else {
++		io_request->Function  = MEGASAS_MPI2_FUNCTION_LD_IO_REQUEST;
++		io_request->DevHandle = device_id;
++		cmd->request_desc->SCSIIO.RequestFlags =
++			(MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO <<
++			 MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
++	}
++	io_request->RaidContext.VirtualDiskTgtId = device_id;
++	io_request->LUN[0] = scmd->device->lun;
++	io_request->DataLength = scsi_bufflen(scmd);
++}
++
++/**
++ * megasas_build_io_fusion -	Prepares IOs to devices
++ * @instance:		Adapter soft state
++ * @scp:		SCSI command
++ * @cmd:		Command to be prepared
++ *
++ * Invokes helper functions to prepare request frames
++ * and sets flags appropriate for IO/Non-IO cmd
++ */
++int
++megasas_build_io_fusion(struct megasas_instance *instance,
++			struct scsi_cmnd *scp,
++			struct megasas_cmd_fusion *cmd)
++{
++	u32 device_id, sge_count;
++	struct MPI2_RAID_SCSI_IO_REQUEST *io_request = cmd->io_request;
++
++	device_id = MEGASAS_DEV_INDEX(instance, scp);
++
++	/* Zero out some fields so they don't get reused */
++	io_request->LUN[0] = 0;
++	io_request->CDB.EEDP32.PrimaryReferenceTag = 0;
++	io_request->CDB.EEDP32.PrimaryApplicationTagMask = 0;
++	io_request->EEDPFlags = 0;
++	io_request->Control = 0;
++	io_request->EEDPBlockSize = 0;
++	io_request->IoFlags = 0;
++	io_request->RaidContext.RAIDFlags = 0;
++
++	memcpy(io_request->CDB.CDB32, scp->cmnd, scp->cmd_len);
++	/*
++	 * Just the CDB length,rest of the Flags are zero
++	 * This will be modified for FP in build_ldio_fusion
++	 */
++	io_request->IoFlags = scp->cmd_len;
++
++	if (megasas_is_ldio(scp))
++		megasas_build_ldio_fusion(instance, scp, cmd);
++	else
++		megasas_build_dcdb_fusion(instance, scp, cmd);
++
++	/*
++	 * Construct SGL
++	 */
++
++	sge_count =
++		megasas_make_sgl_fusion(instance, scp,
++					(struct MPI25_IEEE_SGE_CHAIN64 *)
++					&io_request->SGL, cmd);
++
++	if (sge_count > instance->max_num_sge) {
++		printk(KERN_ERR "megasas: Error. sge_count (0x%x) exceeds "
++		       "max (0x%x) allowed\n", sge_count,
++		       instance->max_num_sge);
++		return 1;
++	}
++
++	io_request->RaidContext.numSGE = sge_count;
++
++	io_request->SGLFlags = MPI2_SGE_FLAGS_64_BIT_ADDRESSING;
++
++	if (scp->sc_data_direction == PCI_DMA_TODEVICE)
++		io_request->Control |= MPI2_SCSIIO_CONTROL_WRITE;
++	else if (scp->sc_data_direction == PCI_DMA_FROMDEVICE)
++		io_request->Control |= MPI2_SCSIIO_CONTROL_READ;
++
++	io_request->SGLOffset0 =
++		offsetof(struct MPI2_RAID_SCSI_IO_REQUEST, SGL) / 4;
++
++	io_request->SenseBufferLowAddress = cmd->sense_phys_addr;
++	io_request->SenseBufferLength = SCSI_SENSE_BUFFERSIZE;
++
++	cmd->scmd = scp;
++	scp->SCp.ptr = (char *)cmd;
++
++	return 0;
++}
++
++union MEGASAS_REQUEST_DESCRIPTOR_UNION *
++megasas_get_request_descriptor(struct megasas_instance *instance, u16 index)
++{
++	u8 *p;
++	struct fusion_context *fusion;
++
++	if (index >= instance->max_fw_cmds) {
++		printk(KERN_ERR "megasas: Invalid SMID (0x%x)request for "
++		       "descriptor\n", index);
++		return NULL;
++	}
++	fusion = instance->ctrl_context;
++	p = fusion->req_frames_desc
++		+sizeof(union MEGASAS_REQUEST_DESCRIPTOR_UNION) *index;
++
++	return (union MEGASAS_REQUEST_DESCRIPTOR_UNION *)p;
++}
++
++/**
++ * megasas_build_and_issue_cmd_fusion -Main routine for building and
++ *                                     issuing non IOCTL cmd
++ * @instance:			Adapter soft state
++ * @scmd:			pointer to scsi cmd from OS
++ */
++static u32
++megasas_build_and_issue_cmd_fusion(struct megasas_instance *instance,
++				   struct scsi_cmnd *scmd)
++{
++	struct megasas_cmd_fusion *cmd;
++	union MEGASAS_REQUEST_DESCRIPTOR_UNION *req_desc;
++	u32 index;
++	struct fusion_context *fusion;
++
++	fusion = instance->ctrl_context;
++
++	cmd = megasas_get_cmd_fusion(instance);
++	if (!cmd)
++		return SCSI_MLQUEUE_HOST_BUSY;
++
++	index = cmd->index;
++
++	req_desc = megasas_get_request_descriptor(instance, index-1);
++	if (!req_desc)
++		return 1;
++
++	req_desc->Words = 0;
++	cmd->request_desc = req_desc;
++	cmd->request_desc->Words = 0;
++
++	if (megasas_build_io_fusion(instance, scmd, cmd)) {
++		megasas_return_cmd_fusion(instance, cmd);
++		printk(KERN_ERR "megasas: Error building command.\n");
++		cmd->request_desc = NULL;
++		return 1;
++	}
++
++	req_desc = cmd->request_desc;
++	req_desc->SCSIIO.SMID = index;
++
++	if (cmd->io_request->ChainOffset != 0 &&
++	    cmd->io_request->ChainOffset != 0xF)
++		printk(KERN_ERR "megasas: The chain offset value is not "
++		       "correct : %x\n", cmd->io_request->ChainOffset);
++
++	/*
++	 * Issue the command to the FW
++	 */
++	atomic_inc(&instance->fw_outstanding);
++
++	instance->instancet->fire_cmd(instance,
++				      req_desc->u.low, req_desc->u.high,
++				      instance->reg_set);
++
++	return 0;
++}
++
++/**
++ * complete_cmd_fusion -	Completes command
++ * @instance:			Adapter soft state
++ * Completes all commands that is in reply descriptor queue
++ */
++int
++complete_cmd_fusion(struct megasas_instance *instance)
++{
++	union MPI2_REPLY_DESCRIPTORS_UNION *desc;
++	struct MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR *reply_desc;
++	struct MPI2_RAID_SCSI_IO_REQUEST *scsi_io_req;
++	struct fusion_context *fusion;
++	struct megasas_cmd *cmd_mfi;
++	struct megasas_cmd_fusion *cmd_fusion;
++	u16 smid, num_completed;
++	u8 reply_descript_type, arm;
++	u32 status, extStatus, device_id;
++	union desc_value d_val;
++	struct LD_LOAD_BALANCE_INFO *lbinfo;
++
++	fusion = instance->ctrl_context;
++
++	if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR)
++		return IRQ_HANDLED;
++
++	desc = fusion->reply_frames_desc;
++	desc += fusion->last_reply_idx;
++
++	reply_desc = (struct MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR *)desc;
++
++	d_val.word = desc->Words;
++
++	reply_descript_type = reply_desc->ReplyFlags &
++		MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK;
++
++	if (reply_descript_type == MPI2_RPY_DESCRIPT_FLAGS_UNUSED)
++		return IRQ_NONE;
++
++	d_val.word = desc->Words;
++
++	num_completed = 0;
++
++	while ((d_val.u.low != UINT_MAX) && (d_val.u.high != UINT_MAX)) {
++		smid = reply_desc->SMID;
++
++		cmd_fusion = fusion->cmd_list[smid - 1];
++
++		scsi_io_req =
++			(struct MPI2_RAID_SCSI_IO_REQUEST *)
++		  cmd_fusion->io_request;
++
++		if (cmd_fusion->scmd)
++			cmd_fusion->scmd->SCp.ptr = NULL;
++
++		status = scsi_io_req->RaidContext.status;
++		extStatus = scsi_io_req->RaidContext.exStatus;
++
++		switch (scsi_io_req->Function) {
++		case MPI2_FUNCTION_SCSI_IO_REQUEST:  /*Fast Path IO.*/
++			/* Update load balancing info */
++			device_id = MEGASAS_DEV_INDEX(instance,
++						      cmd_fusion->scmd);
++			lbinfo = &fusion->load_balance_info[device_id];
++			if (cmd_fusion->scmd->SCp.Status &
++			    MEGASAS_LOAD_BALANCE_FLAG) {
++				arm = lbinfo->raid1DevHandle[0] ==
++					cmd_fusion->io_request->DevHandle ? 0 :
++					1;
++				atomic_dec(&lbinfo->scsi_pending_cmds[arm]);
++				cmd_fusion->scmd->SCp.Status &=
++					~MEGASAS_LOAD_BALANCE_FLAG;
++			}
++			if (reply_descript_type ==
++			    MPI2_RPY_DESCRIPT_FLAGS_SCSI_IO_SUCCESS) {
++				if (megasas_dbg_lvl == 5)
++					printk(KERN_ERR "\nmegasas: FAST Path "
++					       "IO Success\n");
++			}
++			/* Fall thru and complete IO */
++		case MEGASAS_MPI2_FUNCTION_LD_IO_REQUEST: /* LD-IO Path */
++			/* Map the FW Cmd Status */
++			map_cmd_status(cmd_fusion, status, extStatus);
++			scsi_dma_unmap(cmd_fusion->scmd);
++			cmd_fusion->scmd->scsi_done(cmd_fusion->scmd);
++			scsi_io_req->RaidContext.status = 0;
++			scsi_io_req->RaidContext.exStatus = 0;
++			megasas_return_cmd_fusion(instance, cmd_fusion);
++			atomic_dec(&instance->fw_outstanding);
++
++			break;
++		case MEGASAS_MPI2_FUNCTION_PASSTHRU_IO_REQUEST: /*MFI command */
++			cmd_mfi = instance->cmd_list[cmd_fusion->sync_cmd_idx];
++			megasas_complete_cmd(instance, cmd_mfi, DID_OK);
++			cmd_fusion->flags = 0;
++			megasas_return_cmd_fusion(instance, cmd_fusion);
++
++			break;
++		}
++
++		fusion->last_reply_idx++;
++		if (fusion->last_reply_idx >= fusion->reply_q_depth)
++			fusion->last_reply_idx = 0;
++
++		desc->Words = ULLONG_MAX;
++		num_completed++;
++
++		/* Get the next reply descriptor */
++		if (!fusion->last_reply_idx)
++			desc = fusion->reply_frames_desc;
++		else
++			desc++;
++
++		reply_desc =
++		  (struct MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR *)desc;
++
++		d_val.word = desc->Words;
++
++		reply_descript_type = reply_desc->ReplyFlags &
++			MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK;
++
++		if (reply_descript_type == MPI2_RPY_DESCRIPT_FLAGS_UNUSED)
++			break;
++	}
++
++	if (!num_completed)
++		return IRQ_NONE;
++
++	wmb();
++	writel(fusion->last_reply_idx,
++	       &instance->reg_set->reply_post_host_index);
++
++	return IRQ_HANDLED;
++}
++
++/**
++ * megasas_complete_cmd_dpc_fusion -	Completes command
++ * @instance:			Adapter soft state
++ *
++ * Tasklet to complete cmds
++ */
++void
++megasas_complete_cmd_dpc_fusion(unsigned long instance_addr)
++{
++	struct megasas_instance *instance =
++		(struct megasas_instance *)instance_addr;
++	unsigned long flags;
++
++	/* If we have already declared adapter dead, donot complete cmds */
++	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);
++	complete_cmd_fusion(instance);
++	spin_unlock_irqrestore(&instance->completion_lock, flags);
++}
++
++/**
++ * megasas_isr_fusion - isr entry point
++ */
++irqreturn_t megasas_isr_fusion(int irq, void *devp)
++{
++	struct megasas_instance *instance = (struct megasas_instance *)devp;
++	u32 mfiStatus, fw_state;
++
++	if (!instance->msi_flag) {
++		mfiStatus = instance->instancet->clear_intr(instance->reg_set);
++		if (!mfiStatus)
++			return IRQ_NONE;
++	}
++
++	/* If we are resetting, bail */
++	if (test_bit(MEGASAS_FUSION_IN_RESET, &instance->reset_flags))
++		return IRQ_HANDLED;
++
++	if (!complete_cmd_fusion(instance)) {
++		/* If we didn't complete any commands, check for FW fault */
++		fw_state = instance->instancet->read_fw_status_reg(
++			instance->reg_set) & MFI_STATE_MASK;
++		if (fw_state == MFI_STATE_FAULT)
++			schedule_work(&instance->work_init);
++	}
++
++	return IRQ_HANDLED;
++}
++
++/**
++ * build_mpt_mfi_pass_thru - builds a cmd fo MFI Pass thru
++ * @instance:			Adapter soft state
++ * mfi_cmd:			megasas_cmd pointer
++ *
++ */
++u8
++build_mpt_mfi_pass_thru(struct megasas_instance *instance,
++			struct megasas_cmd *mfi_cmd)
++{
++	struct MPI25_IEEE_SGE_CHAIN64 *mpi25_ieee_chain;
++	struct MPI2_RAID_SCSI_IO_REQUEST *io_req;
++	struct megasas_cmd_fusion *cmd;
++	struct fusion_context *fusion;
++	struct megasas_header *frame_hdr = &mfi_cmd->frame->hdr;
++
++	cmd = megasas_get_cmd_fusion(instance);
++	if (!cmd)
++		return 1;
++
++	/*  Save the smid. To be used for returning the cmd */
++	mfi_cmd->context.smid = cmd->index;
++
++	cmd->sync_cmd_idx = mfi_cmd->index;
++
++	/*
++	 * For cmds where the flag is set, store the flag and check
++	 * on completion. For cmds with this flag, don't call
++	 * megasas_complete_cmd
++	 */
++
++	if (frame_hdr->flags & MFI_FRAME_DONT_POST_IN_REPLY_QUEUE)
++		cmd->flags = MFI_FRAME_DONT_POST_IN_REPLY_QUEUE;
++
++	fusion = instance->ctrl_context;
++	io_req = cmd->io_request;
++	mpi25_ieee_chain =
++	  (struct MPI25_IEEE_SGE_CHAIN64 *)&io_req->SGL.IeeeChain;
++
++	io_req->Function    = MEGASAS_MPI2_FUNCTION_PASSTHRU_IO_REQUEST;
++	io_req->SGLOffset0  = offsetof(struct MPI2_RAID_SCSI_IO_REQUEST,
++				       SGL) / 4;
++	io_req->ChainOffset = fusion->chain_offset_mfi_pthru;
++
++	mpi25_ieee_chain->Address = mfi_cmd->frame_phys_addr;
++
++	mpi25_ieee_chain->Flags = IEEE_SGE_FLAGS_CHAIN_ELEMENT |
++		MPI2_IEEE_SGE_FLAGS_IOCPLBNTA_ADDR;
++
++	mpi25_ieee_chain->Length = MEGASAS_MAX_SZ_CHAIN_FRAME;
++
++	return 0;
++}
++
++/**
++ * build_mpt_cmd - Calls helper function to build a cmd MFI Pass thru cmd
++ * @instance:			Adapter soft state
++ * @cmd:			mfi cmd to build
++ *
++ */
++union MEGASAS_REQUEST_DESCRIPTOR_UNION *
++build_mpt_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd)
++{
++	union MEGASAS_REQUEST_DESCRIPTOR_UNION *req_desc;
++	u16 index;
++
++	if (build_mpt_mfi_pass_thru(instance, cmd)) {
++		printk(KERN_ERR "Couldn't build MFI pass thru cmd\n");
++		return NULL;
++	}
++
++	index = cmd->context.smid;
++
++	req_desc = megasas_get_request_descriptor(instance, index - 1);
++
++	if (!req_desc)
++		return NULL;
++
++	req_desc->Words = 0;
++	req_desc->SCSIIO.RequestFlags = (MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO <<
++					 MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
++
++	req_desc->SCSIIO.SMID = index;
++
++	return req_desc;
++}
++
++/**
++ * megasas_issue_dcmd_fusion - Issues a MFI Pass thru cmd
++ * @instance:			Adapter soft state
++ * @cmd:			mfi cmd pointer
++ *
++ */
++void
++megasas_issue_dcmd_fusion(struct megasas_instance *instance,
++			  struct megasas_cmd *cmd)
++{
++	union MEGASAS_REQUEST_DESCRIPTOR_UNION *req_desc;
++	union desc_value d_val;
++
++	req_desc = build_mpt_cmd(instance, cmd);
++	if (!req_desc) {
++		printk(KERN_ERR "Couldn't issue MFI pass thru cmd\n");
++		return;
++	}
++	d_val.word = req_desc->Words;
++
++	instance->instancet->fire_cmd(instance, req_desc->u.low,
++				      req_desc->u.high, instance->reg_set);
++}
++
++/**
++ * megasas_release_fusion -	Reverses the FW initialization
++ * @intance:			Adapter soft state
++ */
++void
++megasas_release_fusion(struct megasas_instance *instance)
++{
++	megasas_free_cmds(instance);
++	megasas_free_cmds_fusion(instance);
++
++	iounmap(instance->reg_set);
++
++	pci_release_selected_regions(instance->pdev, instance->bar);
++}
++
++/**
++ * megasas_read_fw_status_reg_fusion - returns the current FW status value
++ * @regs:			MFI register set
++ */
++static u32
++megasas_read_fw_status_reg_fusion(struct megasas_register_set __iomem *regs)
++{
++	return readl(&(regs)->outbound_scratch_pad);
++}
++
++/**
++ * megasas_adp_reset_fusion -	For controller reset
++ * @regs:				MFI register set
++ */
++static int
++megasas_adp_reset_fusion(struct megasas_instance *instance,
++			 struct megasas_register_set __iomem *regs)
++{
++	return 0;
++}
++
++/**
++ * megasas_check_reset_fusion -	For controller reset check
++ * @regs:				MFI register set
++ */
++static int
++megasas_check_reset_fusion(struct megasas_instance *instance,
++			   struct megasas_register_set __iomem *regs)
++{
++	return 0;
++}
++
++/* This function waits for outstanding commands on fusion to complete */
++int megasas_wait_for_outstanding_fusion(struct megasas_instance *instance)
++{
++	int i, outstanding, retval = 0;
++	u32 fw_state, wait_time = MEGASAS_RESET_WAIT_TIME;
++
++	for (i = 0; i < wait_time; i++) {
++		/* Check if firmware is in fault state */
++		fw_state = instance->instancet->read_fw_status_reg(
++			instance->reg_set) & MFI_STATE_MASK;
++		if (fw_state == MFI_STATE_FAULT) {
++			printk(KERN_WARNING "megasas: Found FW in FAULT state,"
++			       " will reset adapter.\n");
++			retval = 1;
++			goto out;
++		}
++
++		outstanding = atomic_read(&instance->fw_outstanding);
++		if (!outstanding)
++			goto out;
++
++		if (!(i % MEGASAS_RESET_NOTICE_INTERVAL)) {
++			printk(KERN_NOTICE "megasas: [%2d]waiting for %d "
++			       "commands to complete\n", i, outstanding);
++			megasas_complete_cmd_dpc_fusion(
++				(unsigned long)instance);
++		}
++		msleep(1000);
++	}
++
++	if (atomic_read(&instance->fw_outstanding)) {
++		printk("megaraid_sas: pending commands remain after waiting, "
++		       "will reset adapter.\n");
++		retval = 1;
++	}
++out:
++	return retval;
++}
++
++void  megasas_reset_reply_desc(struct megasas_instance *instance)
++{
++	int i;
++	struct fusion_context *fusion;
++	union MPI2_REPLY_DESCRIPTORS_UNION *reply_desc;
++
++	fusion = instance->ctrl_context;
++	fusion->last_reply_idx = 0;
++	reply_desc = fusion->reply_frames_desc;
++	for (i = 0 ; i < fusion->reply_q_depth; i++, reply_desc++)
++		reply_desc->Words = ULLONG_MAX;
++}
++
++/* Core fusion reset function */
++int megasas_reset_fusion(struct Scsi_Host *shost)
++{
++	int retval = SUCCESS, i, j, retry = 0;
++	struct megasas_instance *instance;
++	struct megasas_cmd_fusion *cmd_fusion;
++	struct fusion_context *fusion;
++	struct megasas_cmd *cmd_mfi;
++	union MEGASAS_REQUEST_DESCRIPTOR_UNION *req_desc;
++	u32 host_diag, abs_state;
++
++	instance = (struct megasas_instance *)shost->hostdata;
++	fusion = instance->ctrl_context;
++
++	mutex_lock(&instance->reset_mutex);
++	set_bit(MEGASAS_FUSION_IN_RESET, &instance->reset_flags);
++	instance->adprecovery = MEGASAS_ADPRESET_SM_INFAULT;
++	instance->instancet->disable_intr(instance->reg_set);
++	msleep(1000);
++
++	if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR) {
++		printk(KERN_WARNING "megaraid_sas: Hardware critical error, "
++		       "returning FAILED.\n");
++		retval = FAILED;
++		goto out;
++	}
++
++	/* First try waiting for commands to complete */
++	if (megasas_wait_for_outstanding_fusion(instance)) {
++		printk(KERN_WARNING "megaraid_sas: resetting fusion "
++		       "adapter.\n");
++		/* Now return commands back to the OS */
++		for (i = 0 ; i < instance->max_fw_cmds; i++) {
++			cmd_fusion = fusion->cmd_list[i];
++			if (cmd_fusion->scmd) {
++				scsi_dma_unmap(cmd_fusion->scmd);
++				cmd_fusion->scmd->result = (DID_RESET << 16);
++				cmd_fusion->scmd->scsi_done(cmd_fusion->scmd);
++				megasas_return_cmd_fusion(instance, cmd_fusion);
++				atomic_dec(&instance->fw_outstanding);
++			}
++		}
++
++		if (instance->disableOnlineCtrlReset == 1) {
++			/* Reset not supported, kill adapter */
++			printk(KERN_WARNING "megaraid_sas: Reset not supported"
++			       ", killing adapter.\n");
++			megaraid_sas_kill_hba(instance);
++			instance->adprecovery = MEGASAS_HW_CRITICAL_ERROR;
++			retval = FAILED;
++			goto out;
++		}
++
++		/* Now try to reset the chip */
++		for (i = 0; i < MEGASAS_FUSION_MAX_RESET_TRIES; i++) {
++			writel(MPI2_WRSEQ_FLUSH_KEY_VALUE,
++			       &instance->reg_set->fusion_seq_offset);
++			writel(MPI2_WRSEQ_1ST_KEY_VALUE,
++			       &instance->reg_set->fusion_seq_offset);
++			writel(MPI2_WRSEQ_2ND_KEY_VALUE,
++			       &instance->reg_set->fusion_seq_offset);
++			writel(MPI2_WRSEQ_3RD_KEY_VALUE,
++			       &instance->reg_set->fusion_seq_offset);
++			writel(MPI2_WRSEQ_4TH_KEY_VALUE,
++			       &instance->reg_set->fusion_seq_offset);
++			writel(MPI2_WRSEQ_5TH_KEY_VALUE,
++			       &instance->reg_set->fusion_seq_offset);
++			writel(MPI2_WRSEQ_6TH_KEY_VALUE,
++			       &instance->reg_set->fusion_seq_offset);
++
++			/* Check that the diag write enable (DRWE) bit is on */
++			host_diag = readl(&instance->reg_set->fusion_host_diag);
++			while (!(host_diag & HOST_DIAG_WRITE_ENABLE)) {
++				msleep(100);
++				host_diag =
++				readl(&instance->reg_set->fusion_host_diag);
++				if (retry++ == 100) {
++					printk(KERN_WARNING "megaraid_sas: "
++					       "Host diag unlock failed!\n");
++					break;
++				}
++			}
++			if (!(host_diag & HOST_DIAG_WRITE_ENABLE))
++				continue;
++
++			/* Send chip reset command */
++			writel(host_diag | HOST_DIAG_RESET_ADAPTER,
++			       &instance->reg_set->fusion_host_diag);
++			msleep(3000);
++
++			/* Make sure reset adapter bit is cleared */
++			host_diag = readl(&instance->reg_set->fusion_host_diag);
++			retry = 0;
++			while (host_diag & HOST_DIAG_RESET_ADAPTER) {
++				msleep(100);
++				host_diag =
++				readl(&instance->reg_set->fusion_host_diag);
++				if (retry++ == 1000) {
++					printk(KERN_WARNING "megaraid_sas: "
++					       "Diag reset adapter never "
++					       "cleared!\n");
++					break;
++				}
++			}
++			if (host_diag & HOST_DIAG_RESET_ADAPTER)
++				continue;
++
++			abs_state =
++				instance->instancet->read_fw_status_reg(
++					instance->reg_set);
++			retry = 0;
++
++			while ((abs_state <= MFI_STATE_FW_INIT) &&
++			       (retry++ < 1000)) {
++				msleep(100);
++				abs_state =
++				instance->instancet->read_fw_status_reg(
++					instance->reg_set);
++			}
++			if (abs_state <= MFI_STATE_FW_INIT) {
++				printk(KERN_WARNING "megaraid_sas: firmware "
++				       "state < MFI_STATE_FW_INIT, state = "
++				       "0x%x\n", abs_state);
++				continue;
++			}
++
++			/* Wait for FW to become ready */
++			if (megasas_transition_to_ready(instance)) {
++				printk(KERN_WARNING "megaraid_sas: Failed to "
++				       "transition controller to ready.\n");
++				continue;
++			}
++
++			megasas_reset_reply_desc(instance);
++			if (megasas_ioc_init_fusion(instance)) {
++				printk(KERN_WARNING "megaraid_sas: "
++				       "megasas_ioc_init_fusion() failed!\n");
++				continue;
++			}
++
++			instance->instancet->enable_intr(instance->reg_set);
++			instance->adprecovery = MEGASAS_HBA_OPERATIONAL;
++
++			/* Re-fire management commands */
++			for (j = 0 ; j < instance->max_fw_cmds; j++) {
++				cmd_fusion = fusion->cmd_list[j];
++				if (cmd_fusion->sync_cmd_idx !=
++				    (u32)ULONG_MAX) {
++					cmd_mfi =
++					instance->
++					cmd_list[cmd_fusion->sync_cmd_idx];
++					if (cmd_mfi->frame->dcmd.opcode ==
++					    MR_DCMD_LD_MAP_GET_INFO) {
++						megasas_return_cmd(instance,
++								   cmd_mfi);
++						megasas_return_cmd_fusion(
++							instance, cmd_fusion);
++					} else  {
++						req_desc =
++						megasas_get_request_descriptor(
++							instance,
++							cmd_mfi->context.smid
++							-1);
++						if (!req_desc)
++							printk(KERN_WARNING
++							       "req_desc NULL"
++							       "\n");
++						else {
++							instance->instancet->
++							fire_cmd(instance,
++								 req_desc->
++								 u.low,
++								 req_desc->
++								 u.high,
++								 instance->
++								 reg_set);
++						}
++					}
++				}
++			}
++
++			/* Reset load balance info */
++			memset(fusion->load_balance_info, 0,
++			       sizeof(struct LD_LOAD_BALANCE_INFO)
++			       *MAX_LOGICAL_DRIVES);
++
++			if (!megasas_get_map_info(instance))
++				megasas_sync_map_info(instance);
++
++			/* Adapter reset completed successfully */
++			printk(KERN_WARNING "megaraid_sas: Reset "
++			       "successful.\n");
++			retval = SUCCESS;
++			goto out;
++		}
++		/* Reset failed, kill the adapter */
++		printk(KERN_WARNING "megaraid_sas: Reset failed, killing "
++		       "adapter.\n");
++		megaraid_sas_kill_hba(instance);
++		retval = FAILED;
++	} else {
++		instance->instancet->enable_intr(instance->reg_set);
++		instance->adprecovery = MEGASAS_HBA_OPERATIONAL;
++	}
++out:
++	clear_bit(MEGASAS_FUSION_IN_RESET, &instance->reset_flags);
++	mutex_unlock(&instance->reset_mutex);
++	return retval;
++}
++
++/* Fusion OCR work queue */
++void megasas_fusion_ocr_wq(struct work_struct *work)
++{
++	struct megasas_instance *instance =
++		container_of(work, struct megasas_instance, work_init);
++
++	megasas_reset_fusion(instance->host);
++}
++
++struct megasas_instance_template megasas_instance_template_fusion = {
++	.fire_cmd = megasas_fire_cmd_fusion,
++	.enable_intr = megasas_enable_intr_fusion,
++	.disable_intr = megasas_disable_intr_fusion,
++	.clear_intr = megasas_clear_intr_fusion,
++	.read_fw_status_reg = megasas_read_fw_status_reg_fusion,
++	.adp_reset = megasas_adp_reset_fusion,
++	.check_reset = megasas_check_reset_fusion,
++	.service_isr = megasas_isr_fusion,
++	.tasklet = megasas_complete_cmd_dpc_fusion,
++	.init_adapter = megasas_init_adapter_fusion,
++	.build_and_issue_cmd = megasas_build_and_issue_cmd_fusion,
++	.issue_dcmd = megasas_issue_dcmd_fusion,
++};
+diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.h b/drivers/scsi/megaraid/megaraid_sas_fusion.h
+new file mode 100644
+index 000000000000..82b577a72c8b
+--- /dev/null
++++ b/drivers/scsi/megaraid/megaraid_sas_fusion.h
+@@ -0,0 +1,695 @@
++/*
++ *  Linux MegaRAID driver for SAS based RAID controllers
++ *
++ *  Copyright (c) 2009-2011  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 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.
++ *
++ *  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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ *
++ *  FILE: megaraid_sas_fusion.h
++ *
++ *  Authors: LSI Corporation
++ *           Manoj Jose
++ *           Sumant Patro
++ *
++ *  Send feedback to: <megaraidlinux at lsi.com>
++ *
++ *  Mail to: LSI Corporation, 1621 Barber Lane, Milpitas, CA 95035
++ *     ATTN: Linuxraid
++ */
++
++#ifndef _MEGARAID_SAS_FUSION_H_
++#define _MEGARAID_SAS_FUSION_H_
++
++/* Fusion defines */
++#define MEGASAS_MAX_SZ_CHAIN_FRAME 1024
++#define MFI_FUSION_ENABLE_INTERRUPT_MASK (0x00000009)
++#define MEGA_MPI2_RAID_DEFAULT_IO_FRAME_SIZE 256
++#define MEGASAS_MPI2_FUNCTION_PASSTHRU_IO_REQUEST   0xF0
++#define MEGASAS_MPI2_FUNCTION_LD_IO_REQUEST         0xF1
++#define MEGASAS_LOAD_BALANCE_FLAG		    0x1
++#define MEGASAS_DCMD_MBOX_PEND_FLAG		    0x1
++#define HOST_DIAG_WRITE_ENABLE			    0x80
++#define HOST_DIAG_RESET_ADAPTER			    0x4
++#define MEGASAS_FUSION_MAX_RESET_TRIES		    3
++
++/* T10 PI defines */
++#define MR_PROT_INFO_TYPE_CONTROLLER                0x8
++#define MEGASAS_SCSI_VARIABLE_LENGTH_CMD            0x7f
++#define MEGASAS_SCSI_SERVICE_ACTION_READ32          0x9
++#define MEGASAS_SCSI_SERVICE_ACTION_WRITE32         0xB
++#define MEGASAS_SCSI_ADDL_CDB_LEN                   0x18
++#define MEGASAS_RD_WR_PROTECT_CHECK_ALL		    0x20
++#define MEGASAS_RD_WR_PROTECT_CHECK_NONE	    0x60
++#define MEGASAS_EEDPBLOCKSIZE			    512
++
++/*
++ * Raid context flags
++ */
++
++#define MR_RAID_CTX_RAID_FLAGS_IO_SUB_TYPE_SHIFT   0x4
++#define MR_RAID_CTX_RAID_FLAGS_IO_SUB_TYPE_MASK    0x30
++enum MR_RAID_FLAGS_IO_SUB_TYPE {
++	MR_RAID_FLAGS_IO_SUB_TYPE_NONE = 0,
++	MR_RAID_FLAGS_IO_SUB_TYPE_SYSTEM_PD = 1,
++};
++
++/*
++ * Request descriptor types
++ */
++#define MEGASAS_REQ_DESCRIPT_FLAGS_LD_IO           0x7
++#define MEGASAS_REQ_DESCRIPT_FLAGS_MFA             0x1
++
++#define MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT      1
++
++#define MEGASAS_FP_CMD_LEN	16
++#define MEGASAS_FUSION_IN_RESET 0
++
++/*
++ * Raid Context structure which describes MegaRAID specific IO Paramenters
++ * This resides at offset 0x60 where the SGL normally starts in MPT IO Frames
++ */
++
++struct RAID_CONTEXT {
++	u16     resvd0;
++	u16     timeoutValue;
++	u8      regLockFlags;
++	u8      resvd1;
++	u16     VirtualDiskTgtId;
++	u64     regLockRowLBA;
++	u32     regLockLength;
++	u16     nextLMId;
++	u8      exStatus;
++	u8      status;
++	u8      RAIDFlags;
++	u8      numSGE;
++	u16	configSeqNum;
++	u8      spanArm;
++	u8      resvd2[3];
++};
++
++#define RAID_CTX_SPANARM_ARM_SHIFT	(0)
++#define RAID_CTX_SPANARM_ARM_MASK	(0x1f)
++
++#define RAID_CTX_SPANARM_SPAN_SHIFT	(5)
++#define RAID_CTX_SPANARM_SPAN_MASK	(0xE0)
++
++/*
++ * define region lock types
++ */
++enum REGION_TYPE {
++	REGION_TYPE_UNUSED       = 0,
++	REGION_TYPE_SHARED_READ  = 1,
++	REGION_TYPE_SHARED_WRITE = 2,
++	REGION_TYPE_EXCLUSIVE    = 3,
++};
++
++/* MPI2 defines */
++#define MPI2_FUNCTION_IOC_INIT              (0x02) /* IOC Init */
++#define MPI2_WHOINIT_HOST_DRIVER            (0x04)
++#define MPI2_VERSION_MAJOR                  (0x02)
++#define MPI2_VERSION_MINOR                  (0x00)
++#define MPI2_VERSION_MAJOR_MASK             (0xFF00)
++#define MPI2_VERSION_MAJOR_SHIFT            (8)
++#define MPI2_VERSION_MINOR_MASK             (0x00FF)
++#define MPI2_VERSION_MINOR_SHIFT            (0)
++#define MPI2_VERSION ((MPI2_VERSION_MAJOR << MPI2_VERSION_MAJOR_SHIFT) | \
++		      MPI2_VERSION_MINOR)
++#define MPI2_HEADER_VERSION_UNIT            (0x10)
++#define MPI2_HEADER_VERSION_DEV             (0x00)
++#define MPI2_HEADER_VERSION_UNIT_MASK       (0xFF00)
++#define MPI2_HEADER_VERSION_UNIT_SHIFT      (8)
++#define MPI2_HEADER_VERSION_DEV_MASK        (0x00FF)
++#define MPI2_HEADER_VERSION_DEV_SHIFT       (0)
++#define MPI2_HEADER_VERSION ((MPI2_HEADER_VERSION_UNIT << 8) | \
++			     MPI2_HEADER_VERSION_DEV)
++#define MPI2_IEEE_SGE_FLAGS_IOCPLBNTA_ADDR      (0x03)
++#define MPI2_SCSIIO_EEDPFLAGS_INC_PRI_REFTAG        (0x8000)
++#define MPI2_SCSIIO_EEDPFLAGS_CHECK_REFTAG          (0x0400)
++#define MPI2_SCSIIO_EEDPFLAGS_CHECK_REMOVE_OP       (0x0003)
++#define MPI2_SCSIIO_EEDPFLAGS_CHECK_APPTAG          (0x0200)
++#define MPI2_SCSIIO_EEDPFLAGS_CHECK_GUARD           (0x0100)
++#define MPI2_SCSIIO_EEDPFLAGS_INSERT_OP             (0x0004)
++#define MPI2_FUNCTION_SCSI_IO_REQUEST               (0x00) /* SCSI IO */
++#define MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY           (0x06)
++#define MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO                 (0x00)
++#define MPI2_SGE_FLAGS_64_BIT_ADDRESSING        (0x02)
++#define MPI2_SCSIIO_CONTROL_WRITE               (0x01000000)
++#define MPI2_SCSIIO_CONTROL_READ                (0x02000000)
++#define MPI2_REQ_DESCRIPT_FLAGS_TYPE_MASK       (0x0E)
++#define MPI2_RPY_DESCRIPT_FLAGS_UNUSED          (0x0F)
++#define MPI2_RPY_DESCRIPT_FLAGS_SCSI_IO_SUCCESS (0x00)
++#define MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK       (0x0F)
++#define MPI2_WRSEQ_FLUSH_KEY_VALUE              (0x0)
++#define MPI2_WRITE_SEQUENCE_OFFSET              (0x00000004)
++#define MPI2_WRSEQ_1ST_KEY_VALUE                (0xF)
++#define MPI2_WRSEQ_2ND_KEY_VALUE                (0x4)
++#define MPI2_WRSEQ_3RD_KEY_VALUE                (0xB)
++#define MPI2_WRSEQ_4TH_KEY_VALUE                (0x2)
++#define MPI2_WRSEQ_5TH_KEY_VALUE                (0x7)
++#define MPI2_WRSEQ_6TH_KEY_VALUE                (0xD)
++
++struct MPI25_IEEE_SGE_CHAIN64 {
++	u64                     Address;
++	u32                     Length;
++	u16                     Reserved1;
++	u8                      NextChainOffset;
++	u8                      Flags;
++};
++
++struct MPI2_SGE_SIMPLE_UNION {
++	u32                     FlagsLength;
++	union {
++		u32                 Address32;
++		u64                 Address64;
++	} u;
++};
++
++struct MPI2_SCSI_IO_CDB_EEDP32 {
++	u8                      CDB[20];                    /* 0x00 */
++	u32                     PrimaryReferenceTag;        /* 0x14 */
++	u16                     PrimaryApplicationTag;      /* 0x18 */
++	u16                     PrimaryApplicationTagMask;  /* 0x1A */
++	u32                     TransferLength;             /* 0x1C */
++};
++
++struct MPI2_SGE_CHAIN_UNION {
++	u16                     Length;
++	u8                      NextChainOffset;
++	u8                      Flags;
++	union {
++		u32                 Address32;
++		u64                 Address64;
++	} u;
++};
++
++struct MPI2_IEEE_SGE_SIMPLE32 {
++	u32                     Address;
++	u32                     FlagsLength;
++};
++
++struct MPI2_IEEE_SGE_CHAIN32 {
++	u32                     Address;
++	u32                     FlagsLength;
++};
++
++struct MPI2_IEEE_SGE_SIMPLE64 {
++	u64                     Address;
++	u32                     Length;
++	u16                     Reserved1;
++	u8                      Reserved2;
++	u8                      Flags;
++};
++
++struct MPI2_IEEE_SGE_CHAIN64 {
++	u64                     Address;
++	u32                     Length;
++	u16                     Reserved1;
++	u8                      Reserved2;
++	u8                      Flags;
++};
++
++union MPI2_IEEE_SGE_SIMPLE_UNION {
++	struct MPI2_IEEE_SGE_SIMPLE32  Simple32;
++	struct MPI2_IEEE_SGE_SIMPLE64  Simple64;
++};
++
++union MPI2_IEEE_SGE_CHAIN_UNION {
++	struct MPI2_IEEE_SGE_CHAIN32   Chain32;
++	struct MPI2_IEEE_SGE_CHAIN64   Chain64;
++};
++
++union MPI2_SGE_IO_UNION {
++	struct MPI2_SGE_SIMPLE_UNION       MpiSimple;
++	struct MPI2_SGE_CHAIN_UNION        MpiChain;
++	union MPI2_IEEE_SGE_SIMPLE_UNION  IeeeSimple;
++	union MPI2_IEEE_SGE_CHAIN_UNION   IeeeChain;
++};
++
++union MPI2_SCSI_IO_CDB_UNION {
++	u8                      CDB32[32];
++	struct MPI2_SCSI_IO_CDB_EEDP32 EEDP32;
++	struct MPI2_SGE_SIMPLE_UNION SGE;
++};
++
++/*
++ * RAID SCSI IO Request Message
++ * Total SGE count will be one less than  _MPI2_SCSI_IO_REQUEST
++ */
++struct MPI2_RAID_SCSI_IO_REQUEST {
++	u16                     DevHandle;                      /* 0x00 */
++	u8                      ChainOffset;                    /* 0x02 */
++	u8                      Function;                       /* 0x03 */
++	u16                     Reserved1;                      /* 0x04 */
++	u8                      Reserved2;                      /* 0x06 */
++	u8                      MsgFlags;                       /* 0x07 */
++	u8                      VP_ID;                          /* 0x08 */
++	u8                      VF_ID;                          /* 0x09 */
++	u16                     Reserved3;                      /* 0x0A */
++	u32                     SenseBufferLowAddress;          /* 0x0C */
++	u16                     SGLFlags;                       /* 0x10 */
++	u8                      SenseBufferLength;              /* 0x12 */
++	u8                      Reserved4;                      /* 0x13 */
++	u8                      SGLOffset0;                     /* 0x14 */
++	u8                      SGLOffset1;                     /* 0x15 */
++	u8                      SGLOffset2;                     /* 0x16 */
++	u8                      SGLOffset3;                     /* 0x17 */
++	u32                     SkipCount;                      /* 0x18 */
++	u32                     DataLength;                     /* 0x1C */
++	u32                     BidirectionalDataLength;        /* 0x20 */
++	u16                     IoFlags;                        /* 0x24 */
++	u16                     EEDPFlags;                      /* 0x26 */
++	u32                     EEDPBlockSize;                  /* 0x28 */
++	u32                     SecondaryReferenceTag;          /* 0x2C */
++	u16                     SecondaryApplicationTag;        /* 0x30 */
++	u16                     ApplicationTagTranslationMask;  /* 0x32 */
++	u8                      LUN[8];                         /* 0x34 */
++	u32                     Control;                        /* 0x3C */
++	union MPI2_SCSI_IO_CDB_UNION  CDB;			/* 0x40 */
++	struct RAID_CONTEXT	RaidContext;                    /* 0x60 */
++	union MPI2_SGE_IO_UNION       SGL;			/* 0x80 */
++};
++
++/*
++ * MPT RAID MFA IO Descriptor.
++ */
++struct MEGASAS_RAID_MFA_IO_REQUEST_DESCRIPTOR {
++	u32     RequestFlags:8;
++	u32     MessageAddress1:24; /* bits 31:8*/
++	u32     MessageAddress2;      /* bits 61:32 */
++};
++
++/* Default Request Descriptor */
++struct MPI2_DEFAULT_REQUEST_DESCRIPTOR {
++	u8              RequestFlags;               /* 0x00 */
++	u8              MSIxIndex;                  /* 0x01 */
++	u16             SMID;                       /* 0x02 */
++	u16             LMID;                       /* 0x04 */
++	u16             DescriptorTypeDependent;    /* 0x06 */
++};
++
++/* High Priority Request Descriptor */
++struct MPI2_HIGH_PRIORITY_REQUEST_DESCRIPTOR {
++	u8              RequestFlags;               /* 0x00 */
++	u8              MSIxIndex;                  /* 0x01 */
++	u16             SMID;                       /* 0x02 */
++	u16             LMID;                       /* 0x04 */
++	u16             Reserved1;                  /* 0x06 */
++};
++
++/* SCSI IO Request Descriptor */
++struct MPI2_SCSI_IO_REQUEST_DESCRIPTOR {
++	u8              RequestFlags;               /* 0x00 */
++	u8              MSIxIndex;                  /* 0x01 */
++	u16             SMID;                       /* 0x02 */
++	u16             LMID;                       /* 0x04 */
++	u16             DevHandle;                  /* 0x06 */
++};
++
++/* SCSI Target Request Descriptor */
++struct MPI2_SCSI_TARGET_REQUEST_DESCRIPTOR {
++	u8              RequestFlags;               /* 0x00 */
++	u8              MSIxIndex;                  /* 0x01 */
++	u16             SMID;                       /* 0x02 */
++	u16             LMID;                       /* 0x04 */
++	u16             IoIndex;                    /* 0x06 */
++};
++
++/* RAID Accelerator Request Descriptor */
++struct MPI2_RAID_ACCEL_REQUEST_DESCRIPTOR {
++	u8              RequestFlags;               /* 0x00 */
++	u8              MSIxIndex;                  /* 0x01 */
++	u16             SMID;                       /* 0x02 */
++	u16             LMID;                       /* 0x04 */
++	u16             Reserved;                   /* 0x06 */
++};
++
++/* union of Request Descriptors */
++union MEGASAS_REQUEST_DESCRIPTOR_UNION {
++	struct MPI2_DEFAULT_REQUEST_DESCRIPTOR             Default;
++	struct MPI2_HIGH_PRIORITY_REQUEST_DESCRIPTOR       HighPriority;
++	struct MPI2_SCSI_IO_REQUEST_DESCRIPTOR             SCSIIO;
++	struct MPI2_SCSI_TARGET_REQUEST_DESCRIPTOR         SCSITarget;
++	struct MPI2_RAID_ACCEL_REQUEST_DESCRIPTOR          RAIDAccelerator;
++	struct MEGASAS_RAID_MFA_IO_REQUEST_DESCRIPTOR      MFAIo;
++	union {
++		struct {
++			u32 low;
++			u32 high;
++		} u;
++		u64 Words;
++	};
++};
++
++/* Default Reply Descriptor */
++struct MPI2_DEFAULT_REPLY_DESCRIPTOR {
++	u8              ReplyFlags;                 /* 0x00 */
++	u8              MSIxIndex;                  /* 0x01 */
++	u16             DescriptorTypeDependent1;   /* 0x02 */
++	u32             DescriptorTypeDependent2;   /* 0x04 */
++};
++
++/* Address Reply Descriptor */
++struct MPI2_ADDRESS_REPLY_DESCRIPTOR {
++	u8              ReplyFlags;                 /* 0x00 */
++	u8              MSIxIndex;                  /* 0x01 */
++	u16             SMID;                       /* 0x02 */
++	u32             ReplyFrameAddress;          /* 0x04 */
++};
++
++/* SCSI IO Success Reply Descriptor */
++struct MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR {
++	u8              ReplyFlags;                 /* 0x00 */
++	u8              MSIxIndex;                  /* 0x01 */
++	u16             SMID;                       /* 0x02 */
++	u16             TaskTag;                    /* 0x04 */
++	u16             Reserved1;                  /* 0x06 */
++};
++
++/* TargetAssist Success Reply Descriptor */
++struct MPI2_TARGETASSIST_SUCCESS_REPLY_DESCRIPTOR {
++	u8              ReplyFlags;                 /* 0x00 */
++	u8              MSIxIndex;                  /* 0x01 */
++	u16             SMID;                       /* 0x02 */
++	u8              SequenceNumber;             /* 0x04 */
++	u8              Reserved1;                  /* 0x05 */
++	u16             IoIndex;                    /* 0x06 */
++};
++
++/* Target Command Buffer Reply Descriptor */
++struct MPI2_TARGET_COMMAND_BUFFER_REPLY_DESCRIPTOR {
++	u8              ReplyFlags;                 /* 0x00 */
++	u8              MSIxIndex;                  /* 0x01 */
++	u8              VP_ID;                      /* 0x02 */
++	u8              Flags;                      /* 0x03 */
++	u16             InitiatorDevHandle;         /* 0x04 */
++	u16             IoIndex;                    /* 0x06 */
++};
++
++/* RAID Accelerator Success Reply Descriptor */
++struct MPI2_RAID_ACCELERATOR_SUCCESS_REPLY_DESCRIPTOR {
++	u8              ReplyFlags;                 /* 0x00 */
++	u8              MSIxIndex;                  /* 0x01 */
++	u16             SMID;                       /* 0x02 */
++	u32             Reserved;                   /* 0x04 */
++};
++
++/* union of Reply Descriptors */
++union MPI2_REPLY_DESCRIPTORS_UNION {
++	struct MPI2_DEFAULT_REPLY_DESCRIPTOR                   Default;
++	struct MPI2_ADDRESS_REPLY_DESCRIPTOR                   AddressReply;
++	struct MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR           SCSIIOSuccess;
++	struct MPI2_TARGETASSIST_SUCCESS_REPLY_DESCRIPTOR TargetAssistSuccess;
++	struct MPI2_TARGET_COMMAND_BUFFER_REPLY_DESCRIPTOR TargetCommandBuffer;
++	struct MPI2_RAID_ACCELERATOR_SUCCESS_REPLY_DESCRIPTOR
++	RAIDAcceleratorSuccess;
++	u64                                             Words;
++};
++
++/* IOCInit Request message */
++struct MPI2_IOC_INIT_REQUEST {
++	u8                      WhoInit;                        /* 0x00 */
++	u8                      Reserved1;                      /* 0x01 */
++	u8                      ChainOffset;                    /* 0x02 */
++	u8                      Function;                       /* 0x03 */
++	u16                     Reserved2;                      /* 0x04 */
++	u8                      Reserved3;                      /* 0x06 */
++	u8                      MsgFlags;                       /* 0x07 */
++	u8                      VP_ID;                          /* 0x08 */
++	u8                      VF_ID;                          /* 0x09 */
++	u16                     Reserved4;                      /* 0x0A */
++	u16                     MsgVersion;                     /* 0x0C */
++	u16                     HeaderVersion;                  /* 0x0E */
++	u32                     Reserved5;                      /* 0x10 */
++	u16                     Reserved6;                      /* 0x14 */
++	u8                      Reserved7;                      /* 0x16 */
++	u8                      HostMSIxVectors;                /* 0x17 */
++	u16                     Reserved8;                      /* 0x18 */
++	u16                     SystemRequestFrameSize;         /* 0x1A */
++	u16                     ReplyDescriptorPostQueueDepth;  /* 0x1C */
++	u16                     ReplyFreeQueueDepth;            /* 0x1E */
++	u32                     SenseBufferAddressHigh;         /* 0x20 */
++	u32                     SystemReplyAddressHigh;         /* 0x24 */
++	u64                     SystemRequestFrameBaseAddress;  /* 0x28 */
++	u64                     ReplyDescriptorPostQueueAddress;/* 0x30 */
++	u64                     ReplyFreeQueueAddress;          /* 0x38 */
++	u64                     TimeStamp;                      /* 0x40 */
++};
++
++/* mrpriv defines */
++#define MR_PD_INVALID 0xFFFF
++#define MAX_SPAN_DEPTH 8
++#define MAX_RAIDMAP_SPAN_DEPTH (MAX_SPAN_DEPTH)
++#define MAX_ROW_SIZE 32
++#define MAX_RAIDMAP_ROW_SIZE (MAX_ROW_SIZE)
++#define MAX_LOGICAL_DRIVES 64
++#define MAX_RAIDMAP_LOGICAL_DRIVES (MAX_LOGICAL_DRIVES)
++#define MAX_RAIDMAP_VIEWS (MAX_LOGICAL_DRIVES)
++#define MAX_ARRAYS 128
++#define MAX_RAIDMAP_ARRAYS (MAX_ARRAYS)
++#define MAX_PHYSICAL_DEVICES 256
++#define MAX_RAIDMAP_PHYSICAL_DEVICES (MAX_PHYSICAL_DEVICES)
++#define MR_DCMD_LD_MAP_GET_INFO             0x0300e101
++
++struct MR_DEV_HANDLE_INFO {
++	u16     curDevHdl;
++	u8      validHandles;
++	u8      reserved;
++	u16     devHandle[2];
++};
++
++struct MR_ARRAY_INFO {
++	u16      pd[MAX_RAIDMAP_ROW_SIZE];
++};
++
++struct MR_QUAD_ELEMENT {
++	u64     logStart;
++	u64     logEnd;
++	u64     offsetInSpan;
++	u32     diff;
++	u32     reserved1;
++};
++
++struct MR_SPAN_INFO {
++	u32             noElements;
++	u32             reserved1;
++	struct MR_QUAD_ELEMENT quad[MAX_RAIDMAP_SPAN_DEPTH];
++};
++
++struct MR_LD_SPAN {
++	u64      startBlk;
++	u64      numBlks;
++	u16      arrayRef;
++	u8       reserved[6];
++};
++
++struct MR_SPAN_BLOCK_INFO {
++	u64          num_rows;
++	struct MR_LD_SPAN   span;
++	struct MR_SPAN_INFO block_span_info;
++};
++
++struct MR_LD_RAID {
++	struct {
++		u32     fpCapable:1;
++		u32     reserved5:3;
++		u32     ldPiMode:4;
++		u32     pdPiMode:4;
++		u32     encryptionType:8;
++		u32     fpWriteCapable:1;
++		u32     fpReadCapable:1;
++		u32     fpWriteAcrossStripe:1;
++		u32     fpReadAcrossStripe:1;
++		u32     reserved4:8;
++	} capability;
++	u32     reserved6;
++	u64     size;
++	u8      spanDepth;
++	u8      level;
++	u8      stripeShift;
++	u8      rowSize;
++	u8      rowDataSize;
++	u8      writeMode;
++	u8      PRL;
++	u8      SRL;
++	u16     targetId;
++	u8      ldState;
++	u8      regTypeReqOnWrite;
++	u8      modFactor;
++	u8      reserved2[1];
++	u16     seqNum;
++
++	struct {
++		u32 ldSyncRequired:1;
++		u32 reserved:31;
++	} flags;
++
++	u8      reserved3[0x5C];
++};
++
++struct MR_LD_SPAN_MAP {
++	struct MR_LD_RAID          ldRaid;
++	u8                  dataArmMap[MAX_RAIDMAP_ROW_SIZE];
++	struct MR_SPAN_BLOCK_INFO  spanBlock[MAX_RAIDMAP_SPAN_DEPTH];
++};
++
++struct MR_FW_RAID_MAP {
++	u32                 totalSize;
++	union {
++		struct {
++			u32         maxLd;
++			u32         maxSpanDepth;
++			u32         maxRowSize;
++			u32         maxPdCount;
++			u32         maxArrays;
++		} validationInfo;
++		u32             version[5];
++		u32             reserved1[5];
++	};
++
++	u32                 ldCount;
++	u32                 Reserved1;
++	u8                  ldTgtIdToLd[MAX_RAIDMAP_LOGICAL_DRIVES+
++					MAX_RAIDMAP_VIEWS];
++	u8                  fpPdIoTimeoutSec;
++	u8                  reserved2[7];
++	struct MR_ARRAY_INFO       arMapInfo[MAX_RAIDMAP_ARRAYS];
++	struct MR_DEV_HANDLE_INFO  devHndlInfo[MAX_RAIDMAP_PHYSICAL_DEVICES];
++	struct MR_LD_SPAN_MAP      ldSpanMap[1];
++};
++
++struct IO_REQUEST_INFO {
++	u64 ldStartBlock;
++	u32 numBlocks;
++	u16 ldTgtId;
++	u8 isRead;
++	u16 devHandle;
++	u64 pdBlock;
++	u8 fpOkForIo;
++};
++
++struct MR_LD_TARGET_SYNC {
++	u8  targetId;
++	u8  reserved;
++	u16 seqNum;
++};
++
++#define IEEE_SGE_FLAGS_ADDR_MASK            (0x03)
++#define IEEE_SGE_FLAGS_SYSTEM_ADDR          (0x00)
++#define IEEE_SGE_FLAGS_IOCDDR_ADDR          (0x01)
++#define IEEE_SGE_FLAGS_IOCPLB_ADDR          (0x02)
++#define IEEE_SGE_FLAGS_IOCPLBNTA_ADDR       (0x03)
++#define IEEE_SGE_FLAGS_CHAIN_ELEMENT        (0x80)
++#define IEEE_SGE_FLAGS_END_OF_LIST          (0x40)
++
++struct megasas_register_set;
++struct megasas_instance;
++
++union desc_word {
++	u64 word;
++	struct {
++		u32 low;
++		u32 high;
++	} u;
++};
++
++struct megasas_cmd_fusion {
++	struct MPI2_RAID_SCSI_IO_REQUEST	*io_request;
++	dma_addr_t			io_request_phys_addr;
++
++	union MPI2_SGE_IO_UNION	*sg_frame;
++	dma_addr_t		sg_frame_phys_addr;
++
++	u8 *sense;
++	dma_addr_t sense_phys_addr;
++
++	struct list_head list;
++	struct scsi_cmnd *scmd;
++	struct megasas_instance *instance;
++
++	u8 retry_for_fw_reset;
++	union MEGASAS_REQUEST_DESCRIPTOR_UNION  *request_desc;
++
++	/*
++	 * Context for a MFI frame.
++	 * Used to get the mfi cmd from list when a MFI cmd is completed
++	 */
++	u32 sync_cmd_idx;
++	u32 index;
++	u8 flags;
++};
++
++struct LD_LOAD_BALANCE_INFO {
++	u8	loadBalanceFlag;
++	u8	reserved1;
++	u16     raid1DevHandle[2];
++	atomic_t     scsi_pending_cmds[2];
++	u64     last_accessed_block[2];
++};
++
++struct MR_FW_RAID_MAP_ALL {
++	struct MR_FW_RAID_MAP raidMap;
++	struct MR_LD_SPAN_MAP ldSpanMap[MAX_LOGICAL_DRIVES - 1];
++} __attribute__ ((packed));
++
++struct fusion_context {
++	struct megasas_cmd_fusion **cmd_list;
++	struct list_head cmd_pool;
++
++	spinlock_t cmd_pool_lock;
++
++	dma_addr_t req_frames_desc_phys;
++	u8 *req_frames_desc;
++
++	struct dma_pool *io_request_frames_pool;
++	dma_addr_t io_request_frames_phys;
++	u8 *io_request_frames;
++
++	struct dma_pool *sg_dma_pool;
++	struct dma_pool *sense_dma_pool;
++
++	dma_addr_t reply_frames_desc_phys;
++	union MPI2_REPLY_DESCRIPTORS_UNION *reply_frames_desc;
++	struct dma_pool *reply_frames_desc_pool;
++
++	u16 last_reply_idx;
++
++	u32 reply_q_depth;
++	u32 request_alloc_sz;
++	u32 reply_alloc_sz;
++	u32 io_frames_alloc_sz;
++
++	u16	max_sge_in_main_msg;
++	u16	max_sge_in_chain;
++
++	u8	chain_offset_io_request;
++	u8	chain_offset_mfi_pthru;
++
++	struct MR_FW_RAID_MAP_ALL *ld_map[2];
++	dma_addr_t ld_map_phys[2];
++
++	u32 map_sz;
++	u8 fast_path_io;
++	struct LD_LOAD_BALANCE_INFO load_balance_info[MAX_LOGICAL_DRIVES];
++};
++
++union desc_value {
++	u64 word;
++	struct {
++		u32 low;
++		u32 high;
++	} u;
++};
++
++#endif /* _MEGARAID_SAS_FUSION_H_ */
+-- 
+1.8.0
+
+

Added: dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0018-megaraid_sas-fix-instance-access-in-megasas_reset_timer.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0018-megaraid_sas-fix-instance-access-in-megasas_reset_timer.patch	Sun Dec 16 23:23:22 2012	(r19615)
@@ -0,0 +1,48 @@
+From 205bad93c4d085c41b07107011e91172e89fa057 Mon Sep 17 00:00:00 2001
+From: adam radford <aradford at gmail.com>
+Date: Thu, 13 Oct 2011 16:01:12 -0700
+Subject: [PATCH 18/53] [SCSI] megaraid_sas: Fix instance access in  megasas_reset_timer
+
+commit f575c5d3ebdca3b0482847d8fcba971767754a9e upstream.
+
+The following patch for megaraid_sas will fix a potential bad pointer access
+in megasas_reset_timer(), when a MegaRAID 9265/9285 or 9360/9380 gets a
+timeout.  megasas_build_io_fusion() sets SCp.ptr to be a struct
+megasas_cmd_fusion *, but then megasas_reset_timer() was casting SCp.ptr to be
+a struct megasas_cmd *, then trying to access cmd->instance, which is invalid.
+
+Just loading instance from scmd->device->host->hostdata in
+megasas_reset_timer() fixes the issue.
+
+Signed-off-by: Adam Radford <aradford at gmail.com>
+Signed-off-by: James Bottomley <JBottomley at Parallels.com>
+Signed-off-by: Jonathan Nieder <jrnieder at gmail.com>
+---
+ drivers/scsi/megaraid/megaraid_sas_base.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c
+index d532b330e03f..31c612905ef6 100644
+--- a/drivers/scsi/megaraid/megaraid_sas_base.c
++++ b/drivers/scsi/megaraid/megaraid_sas_base.c
+@@ -1744,7 +1744,6 @@ static int megasas_generic_reset(struct scsi_cmnd *scmd)
+ static enum
+ blk_eh_timer_return megasas_reset_timer(struct scsi_cmnd *scmd)
+ {
+-	struct megasas_cmd *cmd = (struct megasas_cmd *)scmd->SCp.ptr;
+ 	struct megasas_instance *instance;
+ 	unsigned long flags;
+ 
+@@ -1753,7 +1752,7 @@ blk_eh_timer_return megasas_reset_timer(struct scsi_cmnd *scmd)
+ 		return BLK_EH_NOT_HANDLED;
+ 	}
+ 
+-	instance = cmd->instance;
++	instance = (struct megasas_instance *)scmd->device->host->hostdata;
+ 	if (!(instance->flag & MEGASAS_FW_BUSY)) {
+ 		/* FW is busy, throttle IO */
+ 		spin_lock_irqsave(instance->host->host_lock, flags);
+-- 
+1.8.0
+
+

Added: dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0019-megaraid_sas-tape-drive-support-fix.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0019-megaraid_sas-tape-drive-support-fix.patch	Sun Dec 16 23:23:22 2012	(r19615)
@@ -0,0 +1,44 @@
+From c5e3548418b026f10d6644305d10ee2ac5c4ab14 Mon Sep 17 00:00:00 2001
+From: "Yang, Bo" <Bo.Yang at lsi.com>
+Date: Tue, 6 Oct 2009 14:12:21 -0600
+Subject: [PATCH 19/53] [SCSI] megaraid_sas: tape drive support fix
+
+commit 8d56825321339f0ef7ad08eb58332e1836881e3b upstream.
+
+Add the Tape drive fix to the megaraid_sas driver: If the command is
+for the tape device, set the FW pthru timeout to the os layer timeout
+value.
+
+Signed-off-by: Bo Yang <bo.yang at lsi.com>
+Signed-off-by: James Bottomley <James.Bottomley at suse.de>
+Signed-off-by: Jonathan Nieder <jrnieder at gmail.com>
+---
+ drivers/scsi/megaraid/megaraid_sas_base.c | 11 +++++++++++
+ 1 file changed, 11 insertions(+)
+
+diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c
+index 31c612905ef6..e9574ebaedad 100644
+--- a/drivers/scsi/megaraid/megaraid_sas_base.c
++++ b/drivers/scsi/megaraid/megaraid_sas_base.c
+@@ -1095,6 +1095,17 @@ 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->request->timeout / HZ) > 0xFFFF)
++			pthru->timeout = 0xFFFF;
++		else
++			pthru->timeout = scp->request->timeout / HZ;
++	}
++
++	/*
+ 	 * Construct SGL
+ 	 */
+ 	if (instance->flag_ieee == 1) {
+-- 
+1.8.0
+
+

Added: dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0020-megaraid_sas-report-system-pds-to-os.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0020-megaraid_sas-report-system-pds-to-os.patch	Sun Dec 16 23:23:22 2012	(r19615)
@@ -0,0 +1,142 @@
+From 9dcd9cb49827ebaffb9c4242bec7ea71c81c2e1d Mon Sep 17 00:00:00 2001
+From: "Yang, Bo" <Bo.Yang at lsi.com>
+Date: Tue, 6 Oct 2009 14:33:06 -0600
+Subject: [PATCH 20/53] [SCSI] megaraid_sas: report system PDs to OS
+
+commit 044833b572b96afe91506a0edec42efd84ba4939 upstream.
+
+When OS issue inquiry, it will check driver's internal pd_list.
+
+Signed-off-by: Bo Yang <bo.yang at lsi.com>
+Signed-off-by: James Bottomley <James.Bottomley at suse.de>
+Signed-off-by: Jonathan Nieder <jrnieder at gmail.com>
+---
+ drivers/scsi/megaraid/megaraid_sas_base.c | 91 ++++++++++++++++++++++---------
+ 1 file changed, 65 insertions(+), 26 deletions(-)
+
+diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c
+index e9574ebaedad..a7e693259a40 100644
+--- a/drivers/scsi/megaraid/megaraid_sas_base.c
++++ b/drivers/scsi/megaraid/megaraid_sas_base.c
+@@ -1467,24 +1467,76 @@ megasas_queue_command(struct scsi_cmnd *scmd, void (*done) (struct scsi_cmnd *))
+ 	return 0;
+ }
+ 
++static struct megasas_instance *megasas_lookup_instance(u16 host_no)
++{
++	int i;
++
++	for (i = 0; i < megasas_mgmt_info.max_index; i++) {
++
++		if ((megasas_mgmt_info.instance[i]) &&
++		    (megasas_mgmt_info.instance[i]->host->host_no == host_no))
++			return megasas_mgmt_info.instance[i];
++	}
++
++	return NULL;
++}
++
+ static int megasas_slave_configure(struct scsi_device *sdev)
+ {
++	u16             pd_index = 0;
++	struct  megasas_instance *instance ;
++
++	instance = megasas_lookup_instance(sdev->host->host_no);
++
+ 	/*
+-	 * Don't export physical disk devices to the disk driver.
+-	 *
+-	 * FIXME: Currently we don't export them to the midlayer at all.
+-	 * 	  That will be fixed once LSI engineers have audited the
+-	 * 	  firmware for possible issues.
+-	 */
+-	if (sdev->channel < MEGASAS_MAX_PD_CHANNELS && sdev->type == TYPE_DISK)
++	* Don't export physical disk devices to the disk driver.
++	*
++	* FIXME: Currently we don't export them to the midlayer at all.
++	*        That will be fixed once LSI engineers have audited the
++	*        firmware for possible issues.
++	*/
++	if (sdev->channel < MEGASAS_MAX_PD_CHANNELS &&
++				sdev->type == TYPE_DISK) {
++		pd_index = (sdev->channel * MEGASAS_MAX_DEV_PER_CHANNEL) +
++								sdev->id;
++		if (instance->pd_list[pd_index].driveState ==
++						MR_PD_STATE_SYSTEM) {
++			blk_queue_rq_timeout(sdev->request_queue,
++				MEGASAS_DEFAULT_CMD_TIMEOUT * HZ);
++			return 0;
++		}
+ 		return -ENXIO;
++	}
+ 
+ 	/*
+-	 * The RAID firmware may require extended timeouts.
+-	 */
+-	if (sdev->channel >= MEGASAS_MAX_PD_CHANNELS)
+-		blk_queue_rq_timeout(sdev->request_queue,
+-				     MEGASAS_DEFAULT_CMD_TIMEOUT * HZ);
++	* The RAID firmware may require extended timeouts.
++	*/
++	blk_queue_rq_timeout(sdev->request_queue,
++		MEGASAS_DEFAULT_CMD_TIMEOUT * HZ);
++	return 0;
++}
++
++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)) {
++		/*
++		 * Open the OS scan to the SYSTEM PD
++		 */
++		pd_index =
++			(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 ==
++						TYPE_DISK)) {
++			return 0;
++		}
++		return -ENXIO;
++	}
+ 	return 0;
+ }
+ 
+@@ -1914,6 +1966,7 @@ static struct scsi_host_template megasas_template = {
+ 	.name = "LSI SAS based MegaRAID driver",
+ 	.proc_name = "megaraid_sas",
+ 	.slave_configure = megasas_slave_configure,
++	.slave_alloc = megasas_slave_alloc,
+ 	.queuecommand = megasas_queue_command,
+ 	.eh_device_reset_handler = megasas_reset_device,
+ 	.eh_bus_reset_handler = megasas_reset_bus_host,
+@@ -4545,20 +4598,6 @@ megasas_mgmt_fw_ioctl(struct megasas_instance *instance,
+ 	return error;
+ }
+ 
+-static struct megasas_instance *megasas_lookup_instance(u16 host_no)
+-{
+-	int i;
+-
+-	for (i = 0; i < megasas_mgmt_info.max_index; i++) {
+-
+-		if ((megasas_mgmt_info.instance[i]) &&
+-		    (megasas_mgmt_info.instance[i]->host->host_no == host_no))
+-			return megasas_mgmt_info.instance[i];
+-	}
+-
+-	return NULL;
+-}
+-
+ static int megasas_mgmt_ioctl_fw(struct file *file, unsigned long arg)
+ {
+ 	struct megasas_iocpacket __user *user_ioc =
+-- 
+1.8.0
+
+

Added: dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0021-megaraid_sas-use-the-firmware-boot-timeout-when-waiting-for-commands.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0021-megaraid_sas-use-the-firmware-boot-timeout-when-waiting-for-commands.patch	Sun Dec 16 23:23:22 2012	(r19615)
@@ -0,0 +1,130 @@
+From 7efd8525e290c2b6ae3eed07e3e4cf442d77bafb Mon Sep 17 00:00:00 2001
+From: "Yang, Bo" <Bo.Yang at lsi.com>
+Date: Tue, 6 Oct 2009 14:52:20 -0600
+Subject: [PATCH 21/53] [SCSI] megaraid_sas: use the firmware boot timeout  when waiting for commands
+
+commit 7218df69e3609d1fcf4d83cf8f3fc89dbfbf82a8 upstream.
+
+use the constant MEGASAS_RESET_WAIT_TIME when waiting for firmware
+commands to complete (currently 3 minutes).
+
+Signed-off-by: Bo Yang <bo.yang at lsi.com>
+Signed-off-by: James Bottomley <James.Bottomley at suse.de>
+Signed-off-by: Jonathan Nieder <jrnieder at gmail.com>
+---
+ drivers/scsi/megaraid/megaraid_sas_base.c | 28 +++++++++++++++++-----------
+ 1 file changed, 17 insertions(+), 11 deletions(-)
+
+diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c
+index a7e693259a40..4da5e8f5c42f 100644
+--- a/drivers/scsi/megaraid/megaraid_sas_base.c
++++ b/drivers/scsi/megaraid/megaraid_sas_base.c
+@@ -2505,6 +2505,7 @@ megasas_transition_to_ready(struct megasas_instance* instance)
+ 	u8 max_wait;
+ 	u32 fw_state;
+ 	u32 cur_state;
++	u32 abs_state, curr_abs_state;
+ 
+ 	fw_state = instance->instancet->read_fw_status_reg(instance->reg_set) & MFI_STATE_MASK;
+ 
+@@ -2514,6 +2515,9 @@ megasas_transition_to_ready(struct megasas_instance* instance)
+ 
+ 	while (fw_state != MFI_STATE_READY) {
+ 
++		abs_state =
++		instance->instancet->read_fw_status_reg(instance->reg_set);
++
+ 		switch (fw_state) {
+ 
+ 		case MFI_STATE_FAULT:
+@@ -2540,7 +2544,7 @@ megasas_transition_to_ready(struct megasas_instance* instance)
+ 					&instance->reg_set->inbound_doorbell);
+ 			}
+ 
+-			max_wait = 2;
++			max_wait = MEGASAS_RESET_WAIT_TIME;
+ 			cur_state = MFI_STATE_WAIT_HANDSHAKE;
+ 			break;
+ 
+@@ -2557,7 +2561,7 @@ megasas_transition_to_ready(struct megasas_instance* instance)
+ 				writel(MFI_INIT_HOTPLUG,
+ 					&instance->reg_set->inbound_doorbell);
+ 
+-			max_wait = 10;
++			max_wait = MEGASAS_RESET_WAIT_TIME;
+ 			cur_state = MFI_STATE_BOOT_MESSAGE_PENDING;
+ 			break;
+ 
+@@ -2590,7 +2594,7 @@ megasas_transition_to_ready(struct megasas_instance* instance)
+ 				writel(MFI_RESET_FLAGS,
+ 					&instance->reg_set->inbound_doorbell);
+ 
+-			max_wait = 60;
++			max_wait = MEGASAS_RESET_WAIT_TIME;
+ 			cur_state = MFI_STATE_OPERATIONAL;
+ 			break;
+ 
+@@ -2598,32 +2602,32 @@ megasas_transition_to_ready(struct megasas_instance* instance)
+ 			/*
+ 			 * This state should not last for more than 2 seconds
+ 			 */
+-			max_wait = 2;
++			max_wait = MEGASAS_RESET_WAIT_TIME;
+ 			cur_state = MFI_STATE_UNDEFINED;
+ 			break;
+ 
+ 		case MFI_STATE_BB_INIT:
+-			max_wait = 2;
++			max_wait = MEGASAS_RESET_WAIT_TIME;
+ 			cur_state = MFI_STATE_BB_INIT;
+ 			break;
+ 
+ 		case MFI_STATE_FW_INIT:
+-			max_wait = 20;
++			max_wait = MEGASAS_RESET_WAIT_TIME;
+ 			cur_state = MFI_STATE_FW_INIT;
+ 			break;
+ 
+ 		case MFI_STATE_FW_INIT_2:
+-			max_wait = 20;
++			max_wait = MEGASAS_RESET_WAIT_TIME;
+ 			cur_state = MFI_STATE_FW_INIT_2;
+ 			break;
+ 
+ 		case MFI_STATE_DEVICE_SCAN:
+-			max_wait = 20;
++			max_wait = MEGASAS_RESET_WAIT_TIME;
+ 			cur_state = MFI_STATE_DEVICE_SCAN;
+ 			break;
+ 
+ 		case MFI_STATE_FLUSH_CACHE:
+-			max_wait = 20;
++			max_wait = MEGASAS_RESET_WAIT_TIME;
+ 			cur_state = MFI_STATE_FLUSH_CACHE;
+ 			break;
+ 
+@@ -2639,8 +2643,10 @@ 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);
+ 
+-			if (fw_state == cur_state) {
++			if (abs_state == curr_abs_state) {
+ 				msleep(1);
+ 			} else
+ 				break;
+@@ -2649,7 +2655,7 @@ megasas_transition_to_ready(struct megasas_instance* instance)
+ 		/*
+ 		 * Return error if fw_state hasn't changed after max_wait
+ 		 */
+-		if (fw_state == cur_state) {
++		if (curr_abs_state == abs_state) {
+ 			printk(KERN_DEBUG "FW state [%d] hasn't changed "
+ 			       "in %d secs\n", fw_state, max_wait);
+ 			return -ENODEV;
+-- 
+1.8.0
+
+

Added: dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0022-megaraid_sas-update-version-number-and-documentation.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0022-megaraid_sas-update-version-number-and-documentation.patch	Sun Dec 16 23:23:22 2012	(r19615)
@@ -0,0 +1,120 @@
+From 32ce6408b5d67e3db1533ae61c80b089897e3e97 Mon Sep 17 00:00:00 2001
+From: "Yang, Bo" <Bo.Yang at lsi.com>
+Date: Tue, 6 Oct 2009 14:55:09 -0600
+Subject: [PATCH 22/53] [SCSI] megaraid_sas: Update version number and  documentation
+
+commit a0b7736828f7615823a7dec680632656d9a9edde upstream.
+
+Signed-off-by: Bo Yang <bo.yang at lsi.com>
+Signed-off-by: James Bottomley <James.Bottomley at suse.de>
+Signed-off-by: Jonathan Nieder <jrnieder at gmail.com>
+---
+ Documentation/scsi/ChangeLog.megaraid_sas | 62 +++++++++++++++++++++++++++++++
+ drivers/scsi/megaraid/megaraid_sas.h      |  6 +--
+ drivers/scsi/megaraid/megaraid_sas_base.c |  2 +-
+ 3 files changed, 66 insertions(+), 4 deletions(-)
+
+diff --git a/Documentation/scsi/ChangeLog.megaraid_sas b/Documentation/scsi/ChangeLog.megaraid_sas
+index c851ef497795..151a7b718b8c 100644
+--- a/Documentation/scsi/ChangeLog.megaraid_sas
++++ b/Documentation/scsi/ChangeLog.megaraid_sas
+@@ -1,3 +1,65 @@
++1 Release Date    : Tues.  July 28, 2009 10:12:45 PST 2009 -
++			(emaild-id:megaraidlinux at 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 at 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 at lsi.com)
++			Bo Yang
++
++2 Current Version : 00.00.04.08
++3 Older Version   : 00.00.04.06
++
++1.	Add the fix of pending in FW after deleted the logic drives.
++2.	Add the fix of deallocating memory after get pdlist.
++
++1 Release Date    : Tues. March 26, 2009 10:12:45 PST 2009 -
++			(emaild-id:megaraidlinux at lsi.com)
++			Bo Yang
++
++2 Current Version : 00.00.04.06
++3 Older Version   : 00.00.04.04
++
++1.	Add the fix of the driver cmd empty fix of the driver cmd empty.
++2.	Add the fix of the driver MSM AEN CMD cause the system slow.
++
++1 Release Date    : Tues. March 03, 2009 10:12:45 PST 2009 -
++			(emaild-id:megaraidlinux at lsi.com)
++			Bo Yang
++
++2 Current Version : 00.00.04.04
++3 Older Version   : 00.00.04.01
++
++1.	Add the Tape drive fix to the driver: If the command is for
++	the tape device, set the pthru timeout to the os layer timeout value.
++
++2.	Add Poll_wait mechanism to Gen-2 Linux driv.
++		In the aen handler, driver needs to wakeup poll handler similar to
++		the way it raises SIGIO.
++
++3.	Add new controller new SAS2 support to the driver.
++
++4.	Report the unconfigured PD (system PD) to OS.
++
++5.	Add the IEEE SGL support to the driver
++
++6.	Reasign the Application cmds to SAS2 controller
+ 
+ 1 Release Date    : Thur.July. 24 11:41:51 PST 2008 -
+                        (emaild-id:megaraidlinux at lsi.com)
+diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h
+index 887f33ebcf21..d98fca4ae70f 100644
+--- a/drivers/scsi/megaraid/megaraid_sas.h
++++ b/drivers/scsi/megaraid/megaraid_sas.h
+@@ -18,9 +18,9 @@
+ /*
+  * MegaRAID SAS Driver meta data
+  */
+-#define MEGASAS_VERSION				"00.00.04.01"
+-#define MEGASAS_RELDATE				"July 24, 2008"
+-#define MEGASAS_EXT_VERSION			"Thu July 24 11:41:51 PST 2008"
++#define MEGASAS_VERSION				"00.00.04.12-rc1"
++#define MEGASAS_RELDATE				"Sep. 17, 2009"
++#define MEGASAS_EXT_VERSION			"Thu Sep. 17 11:41:51 PST 2009"
+ 
+ /*
+  * Device IDs
+diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c
+index 4da5e8f5c42f..d3aa84309025 100644
+--- a/drivers/scsi/megaraid/megaraid_sas_base.c
++++ b/drivers/scsi/megaraid/megaraid_sas_base.c
+@@ -10,7 +10,7 @@
+  *	   2 of the License, or (at your option) any later version.
+  *
+  * FILE		: megaraid_sas.c
+- * Version     : v00.00.04.01-rc1
++ * Version     : v00.00.04.12-rc1
+  *
+  * Authors:
+  *	(email-id : megaraidlinux at lsi.com)
+-- 
+1.8.0
+
+

Added: dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0023-megaraid_sas-zero-pad_0-in-mfi-structure.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0023-megaraid_sas-zero-pad_0-in-mfi-structure.patch	Sun Dec 16 23:23:22 2012	(r19615)
@@ -0,0 +1,81 @@
+From 3f7e260e80ed745924528c60e31d0bce1f3c315f Mon Sep 17 00:00:00 2001
+From: "Yang, Bo" <Bo.Yang at lsi.com>
+Date: Sun, 6 Dec 2009 08:24:21 -0700
+Subject: [PATCH 23/53] [SCSI] megaraid_sas: Zero pad_0 in mfi structure
+
+commit 780a3762fb9208748baac5aa9c63a4d4c9287753 upstream.
+
+Add the pad_0 in mfi frame structure to 0 to fix the context value
+larger than 32bit value issue.
+
+Signed-off-by: Bo Yang <bo.yang at lsi.com>
+Signed-off-by: James Bottomley <James.Bottomley at suse.de>
+Signed-off-by: Jonathan Nieder <jrnieder at gmail.com>
+---
+ drivers/scsi/megaraid/megaraid_sas_base.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c
+index d3aa84309025..8bd792452866 100644
+--- a/drivers/scsi/megaraid/megaraid_sas_base.c
++++ b/drivers/scsi/megaraid/megaraid_sas_base.c
+@@ -1089,6 +1089,7 @@ megasas_build_dcdb(struct megasas_instance *instance, struct scsi_cmnd *scp,
+ 	pthru->lun = scp->device->lun;
+ 	pthru->cdb_len = scp->cmd_len;
+ 	pthru->timeout = 0;
++	pthru->pad_0 = 0;
+ 	pthru->flags = flags;
+ 	pthru->data_xfer_len = scsi_bufflen(scp);
+ 
+@@ -2956,6 +2957,7 @@ megasas_get_pd_list(struct megasas_instance *instance)
+ 	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;
+@@ -3125,6 +3127,7 @@ megasas_get_ctrl_info(struct megasas_instance *instance,
+ 	dcmd->sge_count = 1;
+ 	dcmd->flags = MFI_FRAME_DIR_READ;
+ 	dcmd->timeout = 0;
++	dcmd->pad_0 = 0;
+ 	dcmd->data_xfer_len = sizeof(struct megasas_ctrl_info);
+ 	dcmd->opcode = MR_DCMD_CTRL_GET_INFO;
+ 	dcmd->sgl.sge32[0].phys_addr = ci_h;
+@@ -3535,6 +3538,7 @@ megasas_get_seq_num(struct megasas_instance *instance,
+ 	dcmd->sge_count = 1;
+ 	dcmd->flags = MFI_FRAME_DIR_READ;
+ 	dcmd->timeout = 0;
++	dcmd->pad_0 = 0;
+ 	dcmd->data_xfer_len = sizeof(struct megasas_evt_log_info);
+ 	dcmd->opcode = MR_DCMD_CTRL_EVENT_GET_INFO;
+ 	dcmd->sgl.sge32[0].phys_addr = el_info_h;
+@@ -3649,6 +3653,7 @@ megasas_register_aen(struct megasas_instance *instance, u32 seq_num,
+ 	dcmd->sge_count = 1;
+ 	dcmd->flags = MFI_FRAME_DIR_READ;
+ 	dcmd->timeout = 0;
++	dcmd->pad_0 = 0;
+ 	instance->last_seq_num = seq_num;
+ 	dcmd->data_xfer_len = sizeof(struct megasas_evt_detail);
+ 	dcmd->opcode = MR_DCMD_CTRL_EVENT_WAIT;
+@@ -4047,6 +4052,7 @@ static void megasas_flush_cache(struct megasas_instance *instance)
+ 	dcmd->sge_count = 0;
+ 	dcmd->flags = MFI_FRAME_DIR_NONE;
+ 	dcmd->timeout = 0;
++	dcmd->pad_0 = 0;
+ 	dcmd->data_xfer_len = 0;
+ 	dcmd->opcode = MR_DCMD_CTRL_CACHE_FLUSH;
+ 	dcmd->mbox.b[0] = MR_FLUSH_CTRL_CACHE | MR_FLUSH_DISK_CACHE;
+@@ -4091,6 +4097,7 @@ static void megasas_shutdown_controller(struct megasas_instance *instance,
+ 	dcmd->sge_count = 0;
+ 	dcmd->flags = MFI_FRAME_DIR_NONE;
+ 	dcmd->timeout = 0;
++	dcmd->pad_0 = 0;
+ 	dcmd->data_xfer_len = 0;
+ 	dcmd->opcode = opcode;
+ 
+-- 
+1.8.0
+
+

Added: dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0024-megaraid_sas-version-and-documentation-update.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0024-megaraid_sas-version-and-documentation-update.patch	Sun Dec 16 23:23:22 2012	(r19615)
@@ -0,0 +1,74 @@
+From e6b88128d46c31cedf537ba76384a8ce5acef3ef Mon Sep 17 00:00:00 2001
+From: "Yang, Bo" <Bo.Yang at lsi.com>
+Date: Sun, 6 Dec 2009 08:42:28 -0700
+Subject: [PATCH 24/53] [SCSI] megaraid_sas: version and documentation update
+
+commit 63bad45db1d4e8aafe0633c5741c9720641f336a upstream.
+
+Signed-off-by: Bo Yang <bo.yang at lsi.com>
+Signed-off-by: James Bottomley <James.Bottomley at suse.de>
+Signed-off-by: Jonathan Nieder <jrnieder at gmail.com>
+---
+ Documentation/scsi/ChangeLog.megaraid_sas | 16 ++++++++++++++++
+ drivers/scsi/megaraid/megaraid_sas.h      |  6 +++---
+ drivers/scsi/megaraid/megaraid_sas_base.c |  2 +-
+ 3 files changed, 20 insertions(+), 4 deletions(-)
+
+diff --git a/Documentation/scsi/ChangeLog.megaraid_sas b/Documentation/scsi/ChangeLog.megaraid_sas
+index 151a7b718b8c..07e252c25b18 100644
+--- a/Documentation/scsi/ChangeLog.megaraid_sas
++++ b/Documentation/scsi/ChangeLog.megaraid_sas
+@@ -1,3 +1,19 @@
++1 Release Date    : Thur.  Oct 29, 2009 09:12:45 PST 2009 -
++			(emaild-id:megaraidlinux at lsi.com)
++			Bo Yang
++
++2 Current Version : 00.00.04.17.1-rc1
++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 at lsi.com)
+ 			Bo Yang
+diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h
+index d98fca4ae70f..8f03bcfd66ad 100644
+--- a/drivers/scsi/megaraid/megaraid_sas.h
++++ b/drivers/scsi/megaraid/megaraid_sas.h
+@@ -18,9 +18,9 @@
+ /*
+  * MegaRAID SAS Driver meta data
+  */
+-#define MEGASAS_VERSION				"00.00.04.12-rc1"
+-#define MEGASAS_RELDATE				"Sep. 17, 2009"
+-#define MEGASAS_EXT_VERSION			"Thu Sep. 17 11:41:51 PST 2009"
++#define MEGASAS_VERSION			"00.00.04.17.1-rc1"
++#define MEGASAS_RELDATE			"Oct. 29, 2009"
++#define MEGASAS_EXT_VERSION		"Thu. Oct. 29, 11:41:51 PST 2009"
+ 
+ /*
+  * Device IDs
+diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c
+index 8bd792452866..b797ed7a4882 100644
+--- a/drivers/scsi/megaraid/megaraid_sas_base.c
++++ b/drivers/scsi/megaraid/megaraid_sas_base.c
+@@ -10,7 +10,7 @@
+  *	   2 of the License, or (at your option) any later version.
+  *
+  * FILE		: megaraid_sas.c
+- * Version     : v00.00.04.12-rc1
++ * Version     : v00.00.04.17.1-rc1
+  *
+  * Authors:
+  *	(email-id : megaraidlinux at lsi.com)
+-- 
+1.8.0
+
+

Added: dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0025-megaraid_sas-support-devices-update-flag.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0025-megaraid_sas-support-devices-update-flag.patch	Sun Dec 16 23:23:22 2012	(r19615)
@@ -0,0 +1,92 @@
+From 43d08b393de5dea0ed2ec8138687b3acbe2257e7 Mon Sep 17 00:00:00 2001
+From: "Yang, Bo" <Bo.Yang at lsi.com>
+Date: Mon, 11 Oct 2010 06:59:20 -0600
+Subject: [PATCH 25/53] [SCSI] megaraid_sas: support devices update flag
+
+commit 837f5fe89c843422452ef5e1a7e3d20e9caa3268 upstream.
+
+Driver added the Device update flag to tell LSI application driver
+whether to do the device Update.  LSI MegaRAID SAS application will
+check this flag to decide if it needs to update the Device or not.
+
+Signed-off-by: Bo Yang <bo.yang at lsi.com>
+Signed-off-by: James Bottomley <James.Bottomley at suse.de>
+Signed-off-by: Jonathan Nieder <jrnieder at gmail.com>
+---
+ drivers/scsi/megaraid/megaraid_sas_base.c | 24 ++++++++++++++++++++++++
+ 1 file changed, 24 insertions(+)
+
+diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c
+index b797ed7a4882..2a5e542e718e 100644
+--- a/drivers/scsi/megaraid/megaraid_sas_base.c
++++ b/drivers/scsi/megaraid/megaraid_sas_base.c
+@@ -110,6 +110,7 @@ static int megasas_poll_wait_aen;
+ static DECLARE_WAIT_QUEUE_HEAD(megasas_poll_wait);
+ static u32 support_poll_for_event;
+ u32 megasas_dbg_lvl;
++static u32 support_device_change;
+ 
+ /* define lock for aen poll */
+ spinlock_t poll_aen_lock;
+@@ -4903,6 +4904,15 @@ megasas_sysfs_show_support_poll_for_event(struct device_driver *dd, char *buf)
+ 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)
+ {
+@@ -5224,6 +5234,7 @@ 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));
+ 
+@@ -5264,6 +5275,11 @@ static int __init megasas_init(void)
+ 		goto err_dcf_support_poll_for_event;
+ 
+ 	rval = driver_create_file(&megasas_pci_driver.driver,
++				&driver_attr_support_device_change);
++	if (rval)
++		goto err_dcf_support_device_change;
++
++	rval = driver_create_file(&megasas_pci_driver.driver,
+ 				  &driver_attr_dbg_lvl);
+ 	if (rval)
+ 		goto err_dcf_dbg_lvl;
+@@ -5279,6 +5295,10 @@ err_dcf_poll_mode_io:
+ 			   &driver_attr_dbg_lvl);
+ err_dcf_dbg_lvl:
+ 	driver_remove_file(&megasas_pci_driver.driver,
++			&driver_attr_support_device_change);
++
++err_dcf_support_device_change:
++	driver_remove_file(&megasas_pci_driver.driver,
+ 			&driver_attr_support_poll_for_event);
+ 
+ err_dcf_support_poll_for_event:
+@@ -5304,6 +5324,10 @@ static void __exit megasas_exit(void)
+ 	driver_remove_file(&megasas_pci_driver.driver,
+ 			   &driver_attr_dbg_lvl);
+ 	driver_remove_file(&megasas_pci_driver.driver,
++			&driver_attr_support_poll_for_event);
++	driver_remove_file(&megasas_pci_driver.driver,
++			&driver_attr_support_device_change);
++	driver_remove_file(&megasas_pci_driver.driver,
+ 			   &driver_attr_release_date);
+ 	driver_remove_file(&megasas_pci_driver.driver, &driver_attr_version);
+ 
+-- 
+1.8.0
+
+

Added: dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0026-megaraid_sas-add-input-parameter-for-max_sectors.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0026-megaraid_sas-add-input-parameter-for-max_sectors.patch	Sun Dec 16 23:23:22 2012	(r19615)
@@ -0,0 +1,83 @@
+From e2adcc06886a309a9b7072f74476a66d8c44ed30 Mon Sep 17 00:00:00 2001
+From: "Yang, Bo" <Bo.Yang at lsi.com>
+Date: Tue, 12 Oct 2010 07:18:50 -0600
+Subject: [PATCH 26/53] [SCSI] megaraid_sas: Add input parameter for  max_sectors
+
+commit 1fd106851698e9a858d20ab0e0f0afd5e9ec9332 upstream.
+
+Driver add the input parameters support for max_sectors for megaraid
+sas gen2 chip.  Customer can set the max_sectors support to 1MB for
+gen2 chip during the driver load.
+
+Signed-off-by: Bo Yang <bo.yang at lsi.com>
+Signed-off-by: James Bottomley <James.Bottomley at suse.de>
+Signed-off-by: Jonathan Nieder <jrnieder at gmail.com>
+---
+ drivers/scsi/megaraid/megaraid_sas.h      |  1 +
+ drivers/scsi/megaraid/megaraid_sas_base.c | 30 ++++++++++++++++++++++++++++++
+ 2 files changed, 31 insertions(+)
+
+diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h
+index 8f03bcfd66ad..a029a6cd1341 100644
+--- a/drivers/scsi/megaraid/megaraid_sas.h
++++ b/drivers/scsi/megaraid/megaraid_sas.h
+@@ -707,6 +707,7 @@ struct megasas_ctrl_info {
+ #define MEGASAS_MAX_LD_IDS			(MEGASAS_MAX_LD_CHANNELS * \
+ 						MEGASAS_MAX_DEV_PER_CHANNEL)
+ 
++#define MEGASAS_MAX_SECTORS                    (2*1024)
+ #define MEGASAS_DBG_LVL				1
+ 
+ #define MEGASAS_FW_BUSY				1
+diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c
+index 2a5e542e718e..ec17c0a1b127 100644
+--- a/drivers/scsi/megaraid/megaraid_sas_base.c
++++ b/drivers/scsi/megaraid/megaraid_sas_base.c
+@@ -61,6 +61,15 @@ static int msix_disable;
+ module_param(msix_disable, int, S_IRUGO);
+ MODULE_PARM_DESC(msix_disable, "Disable MSI-X interrupt handling. Default: 0");
+ 
++/*
++ * Number of sectors per IO command
++ * Will be set in megasas_init_mfi if user does not provide
++ */
++static unsigned int max_sectors;
++module_param_named(max_sectors, max_sectors, int, 0);
++MODULE_PARM_DESC(max_sectors,
++	"Maximum number of sectors per IO command");
++
+ MODULE_LICENSE("GPL");
+ MODULE_VERSION(MEGASAS_VERSION);
+ MODULE_AUTHOR("megaraidlinux at lsi.com");
+@@ -3733,6 +3742,27 @@ static int megasas_io_attach(struct megasas_instance *instance)
+ 			instance->max_fw_cmds - MEGASAS_INT_CMDS;
+ 	host->this_id = instance->init_id;
+ 	host->sg_tablesize = instance->max_num_sge;
++	/*
++	 * Check if the module parameter value for max_sectors can be used
++	 */
++	if (max_sectors && max_sectors < instance->max_sectors_per_req)
++		instance->max_sectors_per_req = max_sectors;
++	else {
++		if (max_sectors) {
++			if (((instance->pdev->device ==
++				PCI_DEVICE_ID_LSI_SAS1078GEN2) ||
++				(instance->pdev->device ==
++				PCI_DEVICE_ID_LSI_SAS0079GEN2)) &&
++				(max_sectors <= MEGASAS_MAX_SECTORS)) {
++				instance->max_sectors_per_req = max_sectors;
++			} else {
++			printk(KERN_INFO "megasas: max_sectors should be > 0"
++				"and <= %d (or < 1MB for GEN2 controller)\n",
++				instance->max_sectors_per_req);
++			}
++		}
++	}
++
+ 	host->max_sectors = instance->max_sectors_per_req;
+ 	host->cmd_per_lun = MEGASAS_DEFAULT_CMD_PER_LUN;
+ 	host->max_channel = MEGASAS_MAX_CHANNELS - 1;
+-- 
+1.8.0
+
+

Added: dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0027-megaraid_sas-add-three-times-online-controller-reset.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0027-megaraid_sas-add-three-times-online-controller-reset.patch	Sun Dec 16 23:23:22 2012	(r19615)
@@ -0,0 +1,140 @@
+From 30e6d6db4faa246df1bcf2b5a01ec84c0dffec54 Mon Sep 17 00:00:00 2001
+From: "Yang, Bo" <Bo.Yang at lsi.com>
+Date: Tue, 12 Oct 2010 07:20:27 -0600
+Subject: [PATCH 27/53] [SCSI] megaraid_sas: Add three times Online controller  reset
+
+commit 707e09bd867cee4cd0e5bff0a67513aa0232fcec upstream.
+
+If fw didn't raise the interrupt with the fw state change to driver
+and fw goes to failure state, driver Will check the FW state in
+driver's timeout routine and issue the reset if need.  Driver will do
+the OCR upto three times until kill adapter.  Also driver will issue
+OCR before driver kill adapter even if fw in operational state.
+
+Signed-off-by: Bo Yang <bo.yang at lsi.com>
+Signed-off-by: James Bottomley <James.Bottomley at suse.de>
+Signed-off-by: Jonathan Nieder <jrnieder at gmail.com>
+---
+ drivers/scsi/megaraid/megaraid_sas_base.c | 70 ++++++++++++++++++++++++++++++-
+ 1 file changed, 69 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c
+index ec17c0a1b127..733f7120817e 100644
+--- a/drivers/scsi/megaraid/megaraid_sas_base.c
++++ b/drivers/scsi/megaraid/megaraid_sas_base.c
+@@ -783,6 +783,10 @@ static int
+ megasas_check_reset_gen2(struct megasas_instance *instance,
+ 		struct megasas_register_set __iomem *regs)
+ {
++	if (instance->adprecovery != MEGASAS_HBA_OPERATIONAL) {
++		return 1;
++	}
++
+ 	return 0;
+ }
+ 
+@@ -992,6 +996,7 @@ megasas_make_sgl_skinny(struct megasas_instance *instance,
+ 			mfi_sgl->sge_skinny[i].length = sg_dma_len(os_sgl);
+ 			mfi_sgl->sge_skinny[i].phys_addr =
+ 						sg_dma_address(os_sgl);
++			mfi_sgl->sge_skinny[i].flag = 0;
+ 		}
+ 	}
+ 	return sge_count;
+@@ -1645,6 +1650,28 @@ static void megasas_complete_cmd_dpc(unsigned long instance_addr)
+ 	megasas_check_and_restore_queue_depth(instance);
+ }
+ 
++static void
++megasas_internal_reset_defer_cmds(struct megasas_instance *instance);
++
++static void
++process_fw_state_change_wq(struct work_struct *work);
++
++void megasas_do_ocr(struct megasas_instance *instance)
++{
++	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;
++	instance->issuepend_done = 0;
++
++	atomic_set(&instance->fw_outstanding, 0);
++	megasas_internal_reset_defer_cmds(instance);
++	process_fw_state_change_wq(&instance->work_init);
++}
++
+ /**
+  * megasas_wait_for_outstanding -	Wait for all outstanding cmds
+  * @instance:				Adapter soft state
+@@ -1662,6 +1689,8 @@ static int megasas_wait_for_outstanding(struct megasas_instance *instance)
+ 	unsigned long flags;
+ 	struct list_head clist_local;
+ 	struct megasas_cmd *reset_cmd;
++	u32 fw_state;
++	u8 kill_adapter_flag;
+ 
+ 	spin_lock_irqsave(&instance->hba_lock, flags);
+ 	adprecovery = instance->adprecovery;
+@@ -1747,7 +1776,45 @@ static int megasas_wait_for_outstanding(struct megasas_instance *instance)
+ 		msleep(1000);
+ 	}
+ 
+-	if (atomic_read(&instance->fw_outstanding)) {
++	i = 0;
++	kill_adapter_flag = 0;
++	do {
++		fw_state = instance->instancet->read_fw_status_reg(
++					instance->reg_set) & MFI_STATE_MASK;
++		if ((fw_state == MFI_STATE_FAULT) &&
++			(instance->disableOnlineCtrlReset == 0)) {
++			if (i == 3) {
++				kill_adapter_flag = 2;
++				break;
++			}
++			megasas_do_ocr(instance);
++			kill_adapter_flag = 1;
++
++			/* wait for 1 secs to let FW finish the pending cmds */
++			msleep(1000);
++		}
++		i++;
++	} while (i <= 3);
++
++	if (atomic_read(&instance->fw_outstanding) &&
++					!kill_adapter_flag) {
++		if (instance->disableOnlineCtrlReset == 0) {
++
++			megasas_do_ocr(instance);
++
++			/* wait for 5 secs to let FW finish the pending cmds */
++			for (i = 0; i < wait_time; i++) {
++				int outstanding =
++					atomic_read(&instance->fw_outstanding);
++				if (!outstanding)
++					return SUCCESS;
++				msleep(1000);
++			}
++		}
++	}
++
++	if (atomic_read(&instance->fw_outstanding) ||
++					(kill_adapter_flag == 2)) {
+ 		printk(KERN_NOTICE "megaraid_sas: pending cmds after reset\n");
+ 		/*
+ 		* Send signal to FW to stop processing any pending cmds.
+@@ -2810,6 +2877,7 @@ static int megasas_create_frame_pool(struct megasas_instance *instance)
+ 			return -ENOMEM;
+ 		}
+ 
++		memset(cmd->frame, 0, total_sz);
+ 		cmd->frame->io.context = cmd->index;
+ 		cmd->frame->io.pad_0 = 0;
+ 	}
+-- 
+1.8.0
+
+

Added: dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0028-megaraid_sas-version-and-documentation-update.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0028-megaraid_sas-version-and-documentation-update.patch	Sun Dec 16 23:23:22 2012	(r19615)
@@ -0,0 +1,105 @@
+From b402f0d112b558e0e37f7af3b02705ec2fb426de Mon Sep 17 00:00:00 2001
+From: "Yang, Bo" <Bo.Yang at lsi.com>
+Date: Tue, 12 Oct 2010 07:21:59 -0600
+Subject: [PATCH 28/53] [SCSI] megaraid_sas: Version and documentation update
+
+commit e340c3537239d5b6a2b21d4245c8577d457b0476 upstream.
+
+Signed-off-by: Bo Yang <bo.yang at lsi.com>
+Signed-off-by: James Bottomley <James.Bottomley at suse.de>
+Signed-off-by: Jonathan Nieder <jrnieder at gmail.com>
+---
+ Documentation/scsi/ChangeLog.megaraid_sas | 47 +++++++++++++++++++++++++++++++
+ drivers/scsi/megaraid/megaraid_sas.h      |  6 ++--
+ drivers/scsi/megaraid/megaraid_sas_base.c |  2 +-
+ 3 files changed, 51 insertions(+), 4 deletions(-)
+
+diff --git a/Documentation/scsi/ChangeLog.megaraid_sas b/Documentation/scsi/ChangeLog.megaraid_sas
+index 07e252c25b18..e9e619613b1f 100644
+--- a/Documentation/scsi/ChangeLog.megaraid_sas
++++ b/Documentation/scsi/ChangeLog.megaraid_sas
+@@ -1,3 +1,50 @@
++1 Release Date    : Thur.  May 03, 2010 09:12:45 PST 2009 -
++			(emaild-id:megaraidlinux at lsi.com)
++			Bo Yang
++
++2 Current Version : 00.00.04.31-rc1
++3 Older Version   : 00.00.04.17.1-rc1
++
++1.	Add the Online Controller Reset (OCR) to the Driver.
++	OCR is the new feature for megaraid_sas driver which
++	will allow the fw to do the chip reset which will not
++	affact the OS behavious.
++
++	To add the OCR support, driver need to do:
++		a). reset the controller chips -- Xscale and Gen2 which
++		will change the function calls and add the reset function
++		related to this two chips.
++
++		b). during the reset, driver will store the pending cmds
++		which not returned by FW to driver's pending queue.  Driver
++		will re-issue those pending cmds again to FW after the OCR
++		finished.
++
++		c). In driver's timeout routine, driver will report to
++		OS as reset. Also driver's queue routine will block the
++		cmds until the OCR finished.
++
++		d). in Driver's ISR routine, if driver get the FW state as
++		state change, FW in Failure status and FW support online controller
++		reset (OCR), driver will start to do the controller reset.
++
++		e). In driver's IOCTL routine, the application cmds will wait for the
++		OCR to finish, then issue the cmds to FW.
++
++		f). Before driver kill adapter, driver will do last chance of
++		OCR to see if driver can bring back the FW.
++
++2.	Add the support update flag to the driver to tell LSI megaraid_sas
++	application which driver will support the device update.  So application
++	will not need to do the device update after application add/del the device
++	from the system.
++3.	In driver's timeout routine, driver will do three time reset if fw is in
++	failed state.  Driver will kill adapter if can't bring back FW after the
++	this three times reset.
++4.	Add the input parameter max_sectors to 1MB support to our GEN2 controller.
++	customer can use the input paramenter max_sectors to add 1MB support to GEN2
++	controller.
++
+ 1 Release Date    : Thur.  Oct 29, 2009 09:12:45 PST 2009 -
+ 			(emaild-id:megaraidlinux at lsi.com)
+ 			Bo Yang
+diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h
+index a029a6cd1341..f029f2389405 100644
+--- a/drivers/scsi/megaraid/megaraid_sas.h
++++ b/drivers/scsi/megaraid/megaraid_sas.h
+@@ -18,9 +18,9 @@
+ /*
+  * MegaRAID SAS Driver meta data
+  */
+-#define MEGASAS_VERSION			"00.00.04.17.1-rc1"
+-#define MEGASAS_RELDATE			"Oct. 29, 2009"
+-#define MEGASAS_EXT_VERSION		"Thu. Oct. 29, 11:41:51 PST 2009"
++#define MEGASAS_VERSION			"00.00.04.31-rc1"
++#define MEGASAS_RELDATE			"May 3, 2010"
++#define MEGASAS_EXT_VERSION		"Mon. May 3, 11:41:51 PST 2010"
+ 
+ /*
+  * Device IDs
+diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c
+index 733f7120817e..d0107e110895 100644
+--- a/drivers/scsi/megaraid/megaraid_sas_base.c
++++ b/drivers/scsi/megaraid/megaraid_sas_base.c
+@@ -10,7 +10,7 @@
+  *	   2 of the License, or (at your option) any later version.
+  *
+  * FILE		: megaraid_sas.c
+- * Version     : v00.00.04.17.1-rc1
++ * Version     : v00.00.04.31-rc1
+  *
+  * Authors:
+  *	(email-id : megaraidlinux at lsi.com)
+-- 
+1.8.0
+
+

Added: dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0029-megaraid_sas-update-gpl-headers.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0029-megaraid_sas-update-gpl-headers.patch	Sun Dec 16 23:23:22 2012	(r19615)
@@ -0,0 +1,118 @@
+From 669f7026c69b4c6d300f24dc11b56665f84b15ee Mon Sep 17 00:00:00 2001
+From: adam radford <aradford at gmail.com>
+Date: Tue, 14 Dec 2010 18:51:48 -0800
+Subject: [PATCH 29/53] [SCSI] megaraid_sas: Update GPL headers.
+
+commit 3f1530c1e1f7fc570672f4a54565949070fad05f upstream.
+
+This patch updates the GPL headers in megaraid_sas_base.c and megaraid_sas.h.
+
+Signed-off-by: Adam Radford <aradford at gmail.com>
+Signed-off-by: James Bottomley <James.Bottomley at suse.de>
+Signed-off-by: Jonathan Nieder <jrnieder at gmail.com>
+---
+ drivers/scsi/megaraid/megaraid_sas.h      | 29 +++++++++++++++++------
+ drivers/scsi/megaraid/megaraid_sas_base.c | 39 ++++++++++++++++++-------------
+ 2 files changed, 45 insertions(+), 23 deletions(-)
+
+diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h
+index f029f2389405..6accf4c73a5d 100644
+--- a/drivers/scsi/megaraid/megaraid_sas.h
++++ b/drivers/scsi/megaraid/megaraid_sas.h
+@@ -1,15 +1,30 @@
+ /*
++ *  Linux MegaRAID driver for SAS based RAID controllers
+  *
+- *		Linux MegaRAID driver for SAS based RAID controllers
++ *  Copyright (c) 2009-2011  LSI Corporation.
+  *
+- * Copyright (c) 2003-2005  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.
++ *  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.
+  *
+- * FILE		: megaraid_sas.h
++ *  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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ *
++ *  FILE: megaraid_sas.h
++ *
++ *  Authors: LSI Corporation
++ *
++ *  Send feedback to: <megaraidlinux at lsi.com>
++ *
++ *  Mail to: LSI Corporation, 1621 Barber Lane, Milpitas, CA 95035
++ *     ATTN: Linuxraid
+  */
+ 
+ #ifndef LSI_MEGARAID_SAS_H
+diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c
+index d0107e110895..e73f011680e2 100644
+--- a/drivers/scsi/megaraid/megaraid_sas_base.c
++++ b/drivers/scsi/megaraid/megaraid_sas_base.c
+@@ -1,27 +1,34 @@
+ /*
++ *  Linux MegaRAID driver for SAS based RAID controllers
+  *
+- *		Linux MegaRAID driver for SAS based RAID controllers
++ *  Copyright (c) 2009-2011  LSI Corporation.
+  *
+- * Copyright (c) 2003-2005  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.
++ *  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.
+  *
+- * FILE		: megaraid_sas.c
+- * Version     : v00.00.04.31-rc1
++ *  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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+  *
+- * Authors:
+- *	(email-id : megaraidlinux at lsi.com)
+- * 	Sreenivas Bagalkote
+- * 	Sumant Patro
+- *	Bo Yang
++ *  FILE: megaraid_sas_base.c
++ *  Version : v00.00.05.29-rc1
+  *
+- * List of supported controllers
++ *  Authors: LSI Corporation
++ *           Sreenivas Bagalkote
++ *           Sumant Patro
++ *           Bo Yang
+  *
+- * OEM	Product Name			VID	DID	SSVID	SSID
+- * ---	------------			---	---	----	----
++ *  Send feedback to: <megaraidlinux at lsi.com>
++ *
++ *  Mail to: LSI Corporation, 1621 Barber Lane, Milpitas, CA 95035
++ *     ATTN: Linuxraid
+  */
+ 
+ #include <linux/kernel.h>
+-- 
+1.8.0
+
+

Added: dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0030-megaraid_sas-fix-failure-gotos.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0030-megaraid_sas-fix-failure-gotos.patch	Sun Dec 16 23:23:22 2012	(r19615)
@@ -0,0 +1,101 @@
+From 4240f3c8af7f47e565754394875116d13edd1ba1 Mon Sep 17 00:00:00 2001
+From: adam radford <aradford at gmail.com>
+Date: Thu, 24 Feb 2011 20:55:56 -0800
+Subject: [PATCH 30/53] [SCSI] megaraid_sas: Fix failure gotos
+
+commit eb1b12377376e43aae4be338ffbbc32931ca4d10 upstream.
+
+Signed-off-by: Adam Radford <aradford at gmail.com>
+Signed-off-by: James Bottomley <James.Bottomley at suse.de>
+Signed-off-by: Jonathan Nieder <jrnieder at gmail.com>
+---
+ drivers/scsi/megaraid/megaraid_sas_base.c   | 17 ++++++++---------
+ drivers/scsi/megaraid/megaraid_sas_fusion.c |  6 ++++--
+ 2 files changed, 12 insertions(+), 11 deletions(-)
+
+diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c
+index e73f011680e2..a630915f69f8 100644
+--- a/drivers/scsi/megaraid/megaraid_sas_base.c
++++ b/drivers/scsi/megaraid/megaraid_sas_base.c
+@@ -3421,7 +3421,6 @@ fail_reply_queue:
+ 	megasas_free_cmds(instance);
+ 
+ fail_alloc_cmds:
+-	iounmap(instance->reg_set);
+ 	return 1;
+ }
+ 
+@@ -3491,7 +3490,7 @@ static int megasas_init_fw(struct megasas_instance *instance)
+ 
+ 	/* Get operational params, sge flags, send init cmd to controller */
+ 	if (instance->instancet->init_adapter(instance))
+-		return -ENODEV;
++		goto fail_init_adapter;
+ 
+ 	printk(KERN_ERR "megasas: INIT adapter done\n");
+ 
+@@ -3550,6 +3549,7 @@ static int megasas_init_fw(struct megasas_instance *instance)
+ 				MEGASAS_COMPLETION_TIMER_INTERVAL);
+ 	return 0;
+ 
++fail_init_adapter:
+ fail_ready_state:
+ 	iounmap(instance->reg_set);
+ 
+@@ -4102,10 +4102,13 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ 	instance->instancet->disable_intr(instance->reg_set);
+ 	free_irq(instance->msi_flag ? instance->msixentry.vector :
+ 		 instance->pdev->irq, instance);
++fail_irq:
+ 	if (instance->msi_flag)
+ 		pci_disable_msix(instance->pdev);
+-
+-      fail_irq:
++	if (instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION)
++		megasas_release_fusion(instance);
++	else
++		megasas_release_mfi(instance);
+       fail_init_mfi:
+       fail_alloc_dma_buf:
+ 	if (instance->evt_detail)
+@@ -4113,13 +4116,9 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ 				    instance->evt_detail,
+ 				    instance->evt_detail_h);
+ 
+-	if (instance->producer) {
++	if (instance->producer)
+ 		pci_free_consistent(pdev, sizeof(u32), instance->producer,
+ 				    instance->producer_h);
+-		megasas_release_mfi(instance);
+-	} else {
+-		megasas_release_fusion(instance);
+-	}
+ 	if (instance->consumer)
+ 		pci_free_consistent(pdev, sizeof(u32), instance->consumer,
+ 				    instance->consumer_h);
+diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.c b/drivers/scsi/megaraid/megaraid_sas_fusion.c
+index c1e09d5a6196..26865290c22a 100644
+--- a/drivers/scsi/megaraid/megaraid_sas_fusion.c
++++ b/drivers/scsi/megaraid/megaraid_sas_fusion.c
+@@ -984,13 +984,15 @@ megasas_init_adapter_fusion(struct megasas_instance *instance)
+ 
+ 	return 0;
+ 
+-fail_alloc_cmds:
+-fail_alloc_mfi_cmds:
+ fail_map_info:
+ 	if (i == 1)
+ 		dma_free_coherent(&instance->pdev->dev, fusion->map_sz,
+ 				  fusion->ld_map[0], fusion->ld_map_phys[0]);
+ fail_ioc_init:
++	megasas_free_cmds_fusion(instance);
++fail_alloc_cmds:
++	megasas_free_cmds(instance);
++fail_alloc_mfi_cmds:
+ 	return 1;
+ }
+ 
+-- 
+1.8.0
+
+

Added: dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0031-megaraid_sas-add-missing-check_and_restore_queue_depth-call.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0031-megaraid_sas-add-missing-check_and_restore_queue_depth-call.patch	Sun Dec 16 23:23:22 2012	(r19615)
@@ -0,0 +1,42 @@
+From 83436b6fea981934bcfce3879bbafe050221bb9d Mon Sep 17 00:00:00 2001
+From: adam radford <aradford at gmail.com>
+Date: Thu, 24 Feb 2011 20:56:05 -0800
+Subject: [PATCH 31/53] [SCSI] megaraid_sas: Add missing  check_and_restore_queue_depth call
+
+commit 53ef2bbd2068097ac453dff4a3d82858446be5bb upstream.
+
+Signed-off-by: Adam Radford <aradford at gmail.com>
+Signed-off-by: James Bottomley <James.Bottomley at suse.de>
+Signed-off-by: Jonathan Nieder <jrnieder at gmail.com>
+---
+ drivers/scsi/megaraid/megaraid_sas_fusion.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.c b/drivers/scsi/megaraid/megaraid_sas_fusion.c
+index 26865290c22a..eb4f4de19338 100644
+--- a/drivers/scsi/megaraid/megaraid_sas_fusion.c
++++ b/drivers/scsi/megaraid/megaraid_sas_fusion.c
+@@ -82,6 +82,10 @@ u16 MR_TargetIdToLdGet(u32 ldTgtId, struct MR_FW_RAID_MAP_ALL *map);
+ struct MR_LD_RAID *MR_LdRaidGet(u32 ld, struct MR_FW_RAID_MAP_ALL *map);
+ 
+ u16 MR_GetLDTgtId(u32 ld, struct MR_FW_RAID_MAP_ALL *map);
++
++void
++megasas_check_and_restore_queue_depth(struct megasas_instance *instance);
++
+ u8 MR_ValidateMapInfo(struct MR_FW_RAID_MAP_ALL *map,
+ 		      struct LD_LOAD_BALANCE_INFO *lbInfo);
+ u16 get_updated_dev_handle(struct LD_LOAD_BALANCE_INFO *lbInfo,
+@@ -1746,7 +1750,7 @@ complete_cmd_fusion(struct megasas_instance *instance)
+ 	wmb();
+ 	writel(fusion->last_reply_idx,
+ 	       &instance->reg_set->reply_post_host_index);
+-
++	megasas_check_and_restore_queue_depth(instance);
+ 	return IRQ_HANDLED;
+ }
+ 
+-- 
+1.8.0
+
+

Added: dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0032-megaraid_sas-enable-msi-x-before-calling-megasas_init_fw.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0032-megaraid_sas-enable-msi-x-before-calling-megasas_init_fw.patch	Sun Dec 16 23:23:22 2012	(r19615)
@@ -0,0 +1,86 @@
+From 0a50715a36817e49dcd0d25364aeccad5010d441 Mon Sep 17 00:00:00 2001
+From: adam radford <aradford at gmail.com>
+Date: Thu, 24 Feb 2011 20:56:12 -0800
+Subject: [PATCH 32/53] [SCSI] megaraid_sas: Enable MSI-X before calling  megasas_init_fw
+
+commit 0a77066acc78b4048b0afc9d70b7e91c06e63356 upstream.
+
+Signed-off-by: Adam Radford <aradford at gmail.com>
+Signed-off-by: James Bottomley <James.Bottomley at suse.de>
+Signed-off-by: Jonathan Nieder <jrnieder at gmail.com>
+---
+ drivers/scsi/megaraid/megaraid_sas_base.c | 24 ++++++++++++------------
+ 1 file changed, 12 insertions(+), 12 deletions(-)
+
+diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c
+index a630915f69f8..c78bff2f29e7 100644
+--- a/drivers/scsi/megaraid/megaraid_sas_base.c
++++ b/drivers/scsi/megaraid/megaraid_sas_base.c
+@@ -4036,12 +4036,6 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ 	else
+ 		INIT_WORK(&instance->work_init, process_fw_state_change_wq);
+ 
+-	/*
+-	 * Initialize MFI Firmware
+-	 */
+-	if (megasas_init_fw(instance))
+-		goto fail_init_mfi;
+-
+ 	/* Try to enable MSI-X */
+ 	if ((instance->pdev->device != PCI_DEVICE_ID_LSI_SAS1078R) &&
+ 	    (instance->pdev->device != PCI_DEVICE_ID_LSI_SAS1078DE) &&
+@@ -4051,6 +4045,12 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ 		instance->msi_flag = 1;
+ 
+ 	/*
++	 * Initialize MFI Firmware
++	 */
++	if (megasas_init_fw(instance))
++		goto fail_init_mfi;
++
++	/*
+ 	 * Register IRQ
+ 	 */
+ 	if (request_irq(instance->msi_flag ? instance->msixentry.vector :
+@@ -4103,13 +4103,13 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ 	free_irq(instance->msi_flag ? instance->msixentry.vector :
+ 		 instance->pdev->irq, instance);
+ fail_irq:
+-	if (instance->msi_flag)
+-		pci_disable_msix(instance->pdev);
+ 	if (instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION)
+ 		megasas_release_fusion(instance);
+ 	else
+ 		megasas_release_mfi(instance);
+       fail_init_mfi:
++	if (instance->msi_flag)
++		pci_disable_msix(instance->pdev);
+       fail_alloc_dma_buf:
+ 	if (instance->evt_detail)
+ 		pci_free_consistent(pdev, sizeof(struct megasas_evt_detail),
+@@ -4293,6 +4293,10 @@ megasas_resume(struct pci_dev *pdev)
+ 	if (megasas_set_dma_mask(pdev))
+ 		goto fail_set_dma_mask;
+ 
++	/* Now re-enable MSI-X */
++	if (instance->msi_flag)
++		pci_enable_msix(instance->pdev, &instance->msixentry, 1);
++
+ 	/*
+ 	 * Initialize MFI Firmware
+ 	 */
+@@ -4329,10 +4333,6 @@ megasas_resume(struct pci_dev *pdev)
+ 	tasklet_init(&instance->isr_tasklet, instance->instancet->tasklet,
+ 		     (unsigned long)instance);
+ 
+-	/* Now re-enable MSI-X */
+-	if (instance->msi_flag)
+-		pci_enable_msix(instance->pdev, &instance->msixentry, 1);
+-
+ 	/*
+ 	 * Register IRQ
+ 	 */
+-- 
+1.8.0
+
+

Added: dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0033-megaraid_sas-call-tasklet_schedule-for-msi-x.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0033-megaraid_sas-call-tasklet_schedule-for-msi-x.patch	Sun Dec 16 23:23:22 2012	(r19615)
@@ -0,0 +1,36 @@
+From 3e8028252819b6aa3106a239749a84b7eadd6894 Mon Sep 17 00:00:00 2001
+From: adam radford <aradford at gmail.com>
+Date: Thu, 24 Feb 2011 20:56:21 -0800
+Subject: [PATCH 33/53] [SCSI] megaraid_sas: Call tasklet_schedule for MSI-X
+
+commit e1419191d8d38098fb6ef29e94aadd15dabff3da upstream.
+
+The following patch for megaraid_sas calls tasklet_schedule() even if
+outbound_intr_status == 0 for MFI based boards in MSI-X mode.
+
+Signed-off-by: Adam Radford <aradford at gmail.com>
+Signed-off-by: James Bottomley <James.Bottomley at suse.de>
+Signed-off-by: Jonathan Nieder <jrnieder at gmail.com>
+---
+ drivers/scsi/megaraid/megaraid_sas_base.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c
+index c78bff2f29e7..1ad032984a90 100644
+--- a/drivers/scsi/megaraid/megaraid_sas_base.c
++++ b/drivers/scsi/megaraid/megaraid_sas_base.c
+@@ -2500,7 +2500,9 @@ megasas_deplete_reply_queue(struct megasas_instance *instance,
+ 	if ((mfiStatus = instance->instancet->clear_intr(
+ 						instance->reg_set)
+ 						) == 0) {
+-		return IRQ_NONE;
++		/* Hardware may not set outbound_intr_status in MSI-X mode */
++		if (!instance->msi_flag)
++			return IRQ_NONE;
+ 	}
+ 
+ 	instance->mfiStatus = mfiStatus;
+-- 
+1.8.0
+
+

Added: dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0034-megaraid_sas-fix-probe_one-to-clear-msi-x-flags-in-kdump.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0034-megaraid_sas-fix-probe_one-to-clear-msi-x-flags-in-kdump.patch	Sun Dec 16 23:23:22 2012	(r19615)
@@ -0,0 +1,67 @@
+From 2afb7e045b531590b7f6f8c40268e08be013ccae Mon Sep 17 00:00:00 2001
+From: adam radford <aradford at gmail.com>
+Date: Thu, 24 Feb 2011 20:56:28 -0800
+Subject: [PATCH 34/53] [SCSI] megaraid_sas: Fix probe_one to clear MSI-X  flags in kdump
+
+commit 66192dfe1e74eae31a76cfc36092dabdba1324e6 upstream.
+
+The following patch for megaraid_sas fixes megasas_probe_one() to
+clear MSI-X flags in kdump when the 'reset_devices' kernel parameter
+is passed in.
+
+Signed-off-by: Adam Radford <aradford at gmail.com>
+Signed-off-by: James Bottomley <James.Bottomley at suse.de>
+Signed-off-by: Jonathan Nieder <jrnieder at gmail.com>
+---
+ drivers/scsi/megaraid/megaraid_sas.h      |  3 +++
+ drivers/scsi/megaraid/megaraid_sas_base.c | 19 ++++++++++++++++++-
+ 2 files changed, 21 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h
+index 6accf4c73a5d..9788121e2778 100644
+--- a/drivers/scsi/megaraid/megaraid_sas.h
++++ b/drivers/scsi/megaraid/megaraid_sas.h
+@@ -1477,4 +1477,7 @@ struct megasas_mgmt_info {
+ 	int max_index;
+ };
+ 
++#define msi_control_reg(base) (base + PCI_MSI_FLAGS)
++#define PCI_MSIX_FLAGS_ENABLE (1 << 15)
++
+ #endif				/*LSI_MEGARAID_SAS_H */
+diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c
+index 1ad032984a90..d8000f5ba571 100644
+--- a/drivers/scsi/megaraid/megaraid_sas_base.c
++++ b/drivers/scsi/megaraid/megaraid_sas_base.c
+@@ -3898,9 +3898,26 @@ fail_set_dma_mask:
+ static int __devinit
+ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ {
+-	int rval;
++	int rval, pos;
+ 	struct Scsi_Host *host;
+ 	struct megasas_instance *instance;
++	u16 control = 0;
++
++	/* Reset MSI-X in the kdump kernel */
++	if (reset_devices) {
++		pos = pci_find_capability(pdev, PCI_CAP_ID_MSIX);
++		if (pos) {
++			pci_read_config_word(pdev, msi_control_reg(pos),
++					     &control);
++			if (control & PCI_MSIX_FLAGS_ENABLE) {
++				dev_info(&pdev->dev, "resetting MSI-X\n");
++				pci_write_config_word(pdev,
++						      msi_control_reg(pos),
++						      control &
++						      ~PCI_MSIX_FLAGS_ENABLE);
++			}
++		}
++	}
+ 
+ 	/*
+ 	 * Announce PCI information
+-- 
+1.8.0
+
+

Added: dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0035-megaraid_sas-fix-megasas_build_dcdb_fusion-to-not-filter-by-type_disk.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0035-megaraid_sas-fix-megasas_build_dcdb_fusion-to-not-filter-by-type_disk.patch	Sun Dec 16 23:23:22 2012	(r19615)
@@ -0,0 +1,32 @@
+From bf7eb1761d7564f1d02369e2c72cd4c2dc6a6c34 Mon Sep 17 00:00:00 2001
+From: adam radford <aradford at gmail.com>
+Date: Thu, 24 Feb 2011 20:56:43 -0800
+Subject: [PATCH 35/53] [SCSI] megaraid_sas: Fix megasas_build_dcdb_fusion to  not filter by TYPE_DISK
+
+commit f512440589632c73e7c2f42d9d723994cd45958b upstream.
+
+Signed-off-by: Adam Radford <aradford at gmail.com>
+Signed-off-by: James Bottomley <James.Bottomley at suse.de>
+Signed-off-by: Jonathan Nieder <jrnieder at gmail.com>
+---
+ drivers/scsi/megaraid/megaraid_sas_fusion.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.c b/drivers/scsi/megaraid/megaraid_sas_fusion.c
+index eb4f4de19338..4ac1f6837532 100644
+--- a/drivers/scsi/megaraid/megaraid_sas_fusion.c
++++ b/drivers/scsi/megaraid/megaraid_sas_fusion.c
+@@ -1438,8 +1438,7 @@ megasas_build_dcdb_fusion(struct megasas_instance *instance,
+ 	local_map_ptr = fusion->ld_map[(instance->map_id & 1)];
+ 
+ 	/* Check if this is a system PD I/O */
+-	if ((instance->pd_list[pd_index].driveState == MR_PD_STATE_SYSTEM) &&
+-	    (instance->pd_list[pd_index].driveType == TYPE_DISK)) {
++	if (instance->pd_list[pd_index].driveState == MR_PD_STATE_SYSTEM) {
+ 		io_request->Function = 0;
+ 		io_request->DevHandle =
+ 			local_map_ptr->raidMap.devHndlInfo[device_id].curDevHdl;
+-- 
+1.8.0
+
+

Added: dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0036-megaraid_sas-fix-megasas_build_dcdb_fusion-to-use-correct-lun-field.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0036-megaraid_sas-fix-megasas_build_dcdb_fusion-to-use-correct-lun-field.patch	Sun Dec 16 23:23:22 2012	(r19615)
@@ -0,0 +1,40 @@
+From 420932ed3eb35c11530b66bf3aed041a1b30c81f Mon Sep 17 00:00:00 2001
+From: adam radford <aradford at gmail.com>
+Date: Thu, 24 Feb 2011 20:56:49 -0800
+Subject: [PATCH 36/53] [SCSI] megaraid_sas: Fix megasas_build_dcdb_fusion to  use correct LUN field
+
+commit eaa3c240de25c6e52ee1329e4acadfd99d7d104b upstream.
+
+Signed-off-by: Adam Radford <aradford at gmail.com>
+Signed-off-by: James Bottomley <James.Bottomley at suse.de>
+Signed-off-by: Jonathan Nieder <jrnieder at gmail.com>
+---
+ drivers/scsi/megaraid/megaraid_sas_fusion.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.c b/drivers/scsi/megaraid/megaraid_sas_fusion.c
+index 4ac1f6837532..905c1e9317b6 100644
+--- a/drivers/scsi/megaraid/megaraid_sas_fusion.c
++++ b/drivers/scsi/megaraid/megaraid_sas_fusion.c
+@@ -1461,7 +1461,7 @@ megasas_build_dcdb_fusion(struct megasas_instance *instance,
+ 			 MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
+ 	}
+ 	io_request->RaidContext.VirtualDiskTgtId = device_id;
+-	io_request->LUN[0] = scmd->device->lun;
++	io_request->LUN[1] = scmd->device->lun;
+ 	io_request->DataLength = scsi_bufflen(scmd);
+ }
+ 
+@@ -1485,7 +1485,7 @@ megasas_build_io_fusion(struct megasas_instance *instance,
+ 	device_id = MEGASAS_DEV_INDEX(instance, scp);
+ 
+ 	/* Zero out some fields so they don't get reused */
+-	io_request->LUN[0] = 0;
++	io_request->LUN[1] = 0;
+ 	io_request->CDB.EEDP32.PrimaryReferenceTag = 0;
+ 	io_request->CDB.EEDP32.PrimaryApplicationTagMask = 0;
+ 	io_request->EEDPFlags = 0;
+-- 
+1.8.0
+
+

Added: dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0037-megaraid_sas-add-cfg_cleared-aen.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0037-megaraid_sas-add-cfg_cleared-aen.patch	Sun Dec 16 23:23:22 2012	(r19615)
@@ -0,0 +1,33 @@
+From 9a59327ed9c5271f41422405e1fc3d8c4b9e76e3 Mon Sep 17 00:00:00 2001
+From: adam radford <aradford at gmail.com>
+Date: Thu, 24 Feb 2011 20:56:53 -0800
+Subject: [PATCH 37/53] [SCSI] megaraid_sas: Add CFG_CLEARED AEN
+
+commit 4c598b23807a3bf0e4f7e65f7934965acc47e1b9 upstream.
+
+The following patch for megaraid_sas adds a missing check for
+MR_EVT_CFG_CLEARED in megasas_aen_polling().
+
+Signed-off-by: Adam Radford <aradford at gmail.com>
+Signed-off-by: James Bottomley <James.Bottomley at suse.de>
+Signed-off-by: Jonathan Nieder <jrnieder at gmail.com>
+---
+ drivers/scsi/megaraid/megaraid_sas_base.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c
+index d8000f5ba571..6d7bed00aa14 100644
+--- a/drivers/scsi/megaraid/megaraid_sas_base.c
++++ b/drivers/scsi/megaraid/megaraid_sas_base.c
+@@ -5195,6 +5195,7 @@ megasas_aen_polling(struct work_struct *work)
+ 			break;
+ 
+ 		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++) {
+-- 
+1.8.0
+
+

Added: dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0038-megaraid_sas-fix-tasklet_init-call.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0038-megaraid_sas-fix-tasklet_init-call.patch	Sun Dec 16 23:23:22 2012	(r19615)
@@ -0,0 +1,34 @@
+From 2f06e458f26575334e71dc7f1e3f677aef1d0cac Mon Sep 17 00:00:00 2001
+From: adam radford <aradford at gmail.com>
+Date: Thu, 24 Feb 2011 20:57:00 -0800
+Subject: [PATCH 38/53] [SCSI] megaraid_sas: Fix tasklet_init call
+
+commit f86c5424b02717a9eb9b1049a67ff3e7e9e92edf upstream.
+
+The following patch fixes an incorrect tasklet_init() call in
+megasas_init_fw() to use instancet->tasklet.
+
+Signed-off-by: Adam Radford <aradford at gmail.com>
+Signed-off-by: James Bottomley <James.Bottomley at suse.de>
+Signed-off-by: Jonathan Nieder <jrnieder at gmail.com>
+---
+ drivers/scsi/megaraid/megaraid_sas_base.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c
+index 6d7bed00aa14..c9426cd93502 100644
+--- a/drivers/scsi/megaraid/megaraid_sas_base.c
++++ b/drivers/scsi/megaraid/megaraid_sas_base.c
+@@ -3541,7 +3541,7 @@ static int megasas_init_fw(struct megasas_instance *instance)
+ 	* Setup tasklet for cmd completion
+ 	*/
+ 
+-	tasklet_init(&instance->isr_tasklet, megasas_complete_cmd_dpc,
++	tasklet_init(&instance->isr_tasklet, instance->instancet->tasklet,
+ 		(unsigned long)instance);
+ 
+ 	/* Initialize the cmd completion timer */
+-- 
+1.8.0
+
+

Added: dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0039-megaraid_sas-fix-fault-state-handling.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0039-megaraid_sas-fix-fault-state-handling.patch	Sun Dec 16 23:23:22 2012	(r19615)
@@ -0,0 +1,36 @@
+From 224b576bd5ed3414b2910eb3600a216cde17f250 Mon Sep 17 00:00:00 2001
+From: adam radford <aradford at gmail.com>
+Date: Thu, 24 Feb 2011 20:57:04 -0800
+Subject: [PATCH 39/53] [SCSI] megaraid_sas: Fix fault state handling
+
+commit 1ac515ef3f2f7ab32498b0e4907933ff8b9b98c0 upstream.
+
+The following patch for megaraid_sas fixes fault state handling in
+megasas_transition_to_ready().
+
+Signed-off-by: Adam Radford <aradford at gmail.com>
+Signed-off-by: James Bottomley <James.Bottomley at suse.de>
+Signed-off-by: Jonathan Nieder <jrnieder at gmail.com>
+---
+ drivers/scsi/megaraid/megaraid_sas_base.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c
+index c9426cd93502..17e47ce05e90 100644
+--- a/drivers/scsi/megaraid/megaraid_sas_base.c
++++ b/drivers/scsi/megaraid/megaraid_sas_base.c
+@@ -2610,7 +2610,9 @@ megasas_transition_to_ready(struct megasas_instance* instance)
+ 		case MFI_STATE_FAULT:
+ 
+ 			printk(KERN_DEBUG "megasas: FW in FAULT state!!\n");
+-			return -ENODEV;
++			max_wait = MEGASAS_RESET_WAIT_TIME;
++			cur_state = MFI_STATE_FAULT;
++			break;
+ 
+ 		case MFI_STATE_WAIT_HANDSHAKE:
+ 			/*
+-- 
+1.8.0
+
+

Added: dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0040-megaraid_sas-fix-max_sectors-for-ieee-sgl.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0040-megaraid_sas-fix-max_sectors-for-ieee-sgl.patch	Sun Dec 16 23:23:22 2012	(r19615)
@@ -0,0 +1,46 @@
+From ee8d96232234db1e7d7a945d9717c21c36d26642 Mon Sep 17 00:00:00 2001
+From: adam radford <aradford at gmail.com>
+Date: Thu, 24 Feb 2011 20:57:09 -0800
+Subject: [PATCH 40/53] [SCSI] megaraid_sas: Fix max_sectors for IEEE SGL
+
+commit 42a8d2b34d107df34533ea4840daf8d62bdc90aa upstream.
+
+Signed-off-by: Adam Radford <aradford at gmail.com>
+Signed-off-by: James Bottomley <James.Bottomley at suse.de>
+Signed-off-by: Jonathan Nieder <jrnieder at gmail.com>
+---
+ drivers/scsi/megaraid/megaraid_sas.h      | 1 +
+ drivers/scsi/megaraid/megaraid_sas_base.c | 4 ++++
+ 2 files changed, 5 insertions(+)
+
+diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h
+index 9788121e2778..742626b972a7 100644
+--- a/drivers/scsi/megaraid/megaraid_sas.h
++++ b/drivers/scsi/megaraid/megaraid_sas.h
+@@ -723,6 +723,7 @@ struct megasas_ctrl_info {
+ 						MEGASAS_MAX_DEV_PER_CHANNEL)
+ 
+ #define MEGASAS_MAX_SECTORS                    (2*1024)
++#define MEGASAS_MAX_SECTORS_IEEE		(2*128)
+ #define MEGASAS_DBG_LVL				1
+ 
+ #define MEGASAS_FW_BUSY				1
+diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c
+index 17e47ce05e90..e5bd4d81c6e0 100644
+--- a/drivers/scsi/megaraid/megaraid_sas_base.c
++++ b/drivers/scsi/megaraid/megaraid_sas_base.c
+@@ -3821,6 +3821,10 @@ static int megasas_io_attach(struct megasas_instance *instance)
+ 			instance->max_fw_cmds - MEGASAS_INT_CMDS;
+ 	host->this_id = instance->init_id;
+ 	host->sg_tablesize = instance->max_num_sge;
++
++	if (instance->fw_support_ieee)
++		instance->max_sectors_per_req = MEGASAS_MAX_SECTORS_IEEE;
++
+ 	/*
+ 	 * Check if the module parameter value for max_sectors can be used
+ 	 */
+-- 
+1.8.0
+
+

Added: dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0041-megaraid_sas-fix-imr-ocr-support-to-work-correctly.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0041-megaraid_sas-fix-imr-ocr-support-to-work-correctly.patch	Sun Dec 16 23:23:22 2012	(r19615)
@@ -0,0 +1,151 @@
+From fe4427f117e25857e98d3b9259faa5b271b3d531 Mon Sep 17 00:00:00 2001
+From: adam radford <aradford at gmail.com>
+Date: Thu, 24 Feb 2011 20:57:15 -0800
+Subject: [PATCH 41/53] [SCSI] megaraid_sas: Fix iMR OCR support to work  correctly
+
+commit ebf054b00b0a6dfa81dc4472d8b19301318b7f47 upstream.
+
+Signed-off-by: Adam Radford <aradford at gmail.com>
+Signed-off-by: James Bottomley <James.Bottomley at suse.de>
+Signed-off-by: Jonathan Nieder <jrnieder at gmail.com>
+---
+ drivers/scsi/megaraid/megaraid_sas_base.c | 62 ++++++++++++++++++-------------
+ 1 file changed, 37 insertions(+), 25 deletions(-)
+
+diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c
+index e5bd4d81c6e0..3fa0be03e6ab 100644
+--- a/drivers/scsi/megaraid/megaraid_sas_base.c
++++ b/drivers/scsi/megaraid/megaraid_sas_base.c
+@@ -134,7 +134,11 @@ spinlock_t poll_aen_lock;
+ void
+ megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd,
+ 		     u8 alt_status);
+-
++static u32
++megasas_read_fw_status_reg_gen2(struct megasas_register_set __iomem *regs);
++static int
++megasas_adp_reset_gen2(struct megasas_instance *instance,
++		       struct megasas_register_set __iomem *reg_set);
+ static irqreturn_t megasas_isr(int irq, void *devp);
+ static u32
+ megasas_init_adapter_mfi(struct megasas_instance *instance);
+@@ -554,6 +558,8 @@ static int
+ megasas_clear_intr_skinny(struct megasas_register_set __iomem *regs)
+ {
+ 	u32 status;
++	u32 mfiStatus = 0;
++
+ 	/*
+ 	 * Check if it is our interrupt
+ 	 */
+@@ -564,6 +570,15 @@ megasas_clear_intr_skinny(struct megasas_register_set __iomem *regs)
+ 	}
+ 
+ 	/*
++	 * Check if it is our interrupt
++	 */
++	if ((megasas_read_fw_status_reg_gen2(regs) & MFI_STATE_MASK) ==
++	    MFI_STATE_FAULT) {
++		mfiStatus = MFI_INTR_FLAG_FIRMWARE_STATE_CHANGE;
++	} else
++		mfiStatus = MFI_INTR_FLAG_REPLY_MESSAGE;
++
++	/*
+ 	 * Clear the interrupt by writing back the same value
+ 	 */
+ 	writel(status, &regs->outbound_intr_status);
+@@ -573,7 +588,7 @@ megasas_clear_intr_skinny(struct megasas_register_set __iomem *regs)
+ 	*/
+ 	readl(&regs->outbound_intr_status);
+ 
+-	return 1;
++	return mfiStatus;
+ }
+ 
+ /**
+@@ -597,17 +612,6 @@ megasas_fire_cmd_skinny(struct megasas_instance *instance,
+ }
+ 
+ /**
+- * 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
+  */
+@@ -625,7 +629,7 @@ 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,
++	.adp_reset = megasas_adp_reset_gen2,
+ 	.check_reset = megasas_check_reset_skinny,
+ 	.service_isr = megasas_isr,
+ 	.tasklet = megasas_complete_cmd_dpc,
+@@ -740,20 +744,28 @@ megasas_adp_reset_gen2(struct megasas_instance *instance,
+ {
+ 	u32			retry = 0 ;
+ 	u32			HostDiag;
++	u32			*seq_offset = &reg_set->seq_offset;
++	u32			*hostdiag_offset = &reg_set->host_diag;
++
++	if (instance->instancet == &megasas_instance_template_skinny) {
++		seq_offset = &reg_set->fusion_seq_offset;
++		hostdiag_offset = &reg_set->fusion_host_diag;
++	}
++
++	writel(0, seq_offset);
++	writel(4, seq_offset);
++	writel(0xb, seq_offset);
++	writel(2, seq_offset);
++	writel(7, seq_offset);
++	writel(0xd, seq_offset);
+ 
+-	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);
++	HostDiag = (u32)readl(hostdiag_offset);
+ 
+ 	while ( !( HostDiag & DIAG_WRITE_ENABLE) ) {
+ 		msleep(100);
+-		HostDiag = (u32)readl(&reg_set->host_diag);
++		HostDiag = (u32)readl(hostdiag_offset);
+ 		printk(KERN_NOTICE "RESETGEN2: retry=%x, hostdiag=%x\n",
+ 					retry, HostDiag);
+ 
+@@ -764,14 +776,14 @@ megasas_adp_reset_gen2(struct megasas_instance *instance,
+ 
+ 	printk(KERN_NOTICE "ADP_RESET_GEN2: HostDiag=%x\n", HostDiag);
+ 
+-	writel((HostDiag | DIAG_RESET_ADAPTER), &reg_set->host_diag);
++	writel((HostDiag | DIAG_RESET_ADAPTER), hostdiag_offset);
+ 
+ 	ssleep(10);
+ 
+-	HostDiag = (u32)readl(&reg_set->host_diag);
++	HostDiag = (u32)readl(hostdiag_offset);
+ 	while ( ( HostDiag & DIAG_RESET_ADAPTER) ) {
+ 		msleep(100);
+-		HostDiag = (u32)readl(&reg_set->host_diag);
++		HostDiag = (u32)readl(hostdiag_offset);
+ 		printk(KERN_NOTICE "RESET_GEN2: retry=%x, hostdiag=%x\n",
+ 				retry, HostDiag);
+ 
+-- 
+1.8.0
+
+

Added: dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0042-megaraid_sas-documentation-update.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0042-megaraid_sas-documentation-update.patch	Sun Dec 16 23:23:22 2012	(r19615)
@@ -0,0 +1,51 @@
+From be23aa1f2602caebd4544563421e042c03a47ce8 Mon Sep 17 00:00:00 2001
+From: adam radford <aradford at gmail.com>
+Date: Tue, 14 Dec 2010 19:11:56 -0800
+Subject: [PATCH 42/53] [SCSI] megaraid_sas: Documentation update
+
+commit 5f7bb3a439ce51ae8b92ca1dc93b91712224b69a upstream.
+
+The following patch updates the
+Documentation/scsi/ChangeLog.megaraid_sas file.
+
+Signed-off-by: Adam Radford <aradford at gmail.com>
+Signed-off-by: James Bottomley <James.Bottomley at suse.de>
+Signed-off-by: Jonathan Nieder <jrnieder at gmail.com>
+---
+ Documentation/scsi/ChangeLog.megaraid_sas | 22 ++++++++++++++++++++++
+ 1 file changed, 22 insertions(+)
+
+diff --git a/Documentation/scsi/ChangeLog.megaraid_sas b/Documentation/scsi/ChangeLog.megaraid_sas
+index e9e619613b1f..399d39437654 100644
+--- a/Documentation/scsi/ChangeLog.megaraid_sas
++++ b/Documentation/scsi/ChangeLog.megaraid_sas
+@@ -1,3 +1,25 @@
++Release Date    : Tues.  Dec 14, 2010 17:00:00 PST 2010 -
++			(emaild-id:megaraidlinux at lsi.com)
++			Adam Radford
++Current Version : 00.00.05.29-rc1
++Old Version     : 00.00.04.31-rc1
++    1. Rename megaraid_sas.c to megaraid_sas_base.c.
++    2. Update GPL headers.
++    3. Add MSI-X support and 'msix_disable' module parameter.
++    4. Use lowest memory bar (for SR-IOV VF support).
++    5. Add struct megasas_instance_temlate changes, and change all code to use
++       new instance entries:
++
++       irqreturn_t (*service_isr )(int irq, void *devp);
++       void (*tasklet)(unsigned long);
++       u32 (*init_adapter)(struct megasas_instance *);
++       u32 (*build_and_issue_cmd) (struct megasas_instance *,
++       struct scsi_cmnd *);
++       void (*issue_dcmd) (struct megasas_instance *instance,
++                              struct megasas_cmd *cmd);
++
++   6. Add code to support MegaRAID 9265/9285 controllers device id (0x5b).
++-------------------------------------------------------------------------------
+ 1 Release Date    : Thur.  May 03, 2010 09:12:45 PST 2009 -
+ 			(emaild-id:megaraidlinux at lsi.com)
+ 			Bo Yang
+-- 
+1.8.0
+
+

Added: dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0043-megaraid_sas-add-9565-9285-specific-code-version-bump.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0043-megaraid_sas-add-9565-9285-specific-code-version-bump.patch	Sun Dec 16 23:23:22 2012	(r19615)
@@ -0,0 +1,36 @@
+From 3dbd42f787b807b4b0f29f5264d556a9774d1803 Mon Sep 17 00:00:00 2001
+From: Jonathan Nieder <jrnieder at gmail.com>
+Date: Mon, 29 Oct 2012 02:31:55 -0700
+Subject: [PATCH 43/53] [SCSI] megaraid_sas: Add 9565/9285 specific code  (Version bump)
+
+commit 9c915a8c99bce637226aa09cb05fc18486b229cb upstream.
+
+I dropped this hunk when first backporting because it did not apply
+cleanly and is not relevant to 9565/9285 support.
+
+Signed-off-by: Jonathan Nieder <jrnieder at gmail.com>
+---
+ drivers/scsi/megaraid/megaraid_sas.h | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h
+index 742626b972a7..c782bbc57cc8 100644
+--- a/drivers/scsi/megaraid/megaraid_sas.h
++++ b/drivers/scsi/megaraid/megaraid_sas.h
+@@ -33,9 +33,9 @@
+ /*
+  * MegaRAID SAS Driver meta data
+  */
+-#define MEGASAS_VERSION			"00.00.04.31-rc1"
+-#define MEGASAS_RELDATE			"May 3, 2010"
+-#define MEGASAS_EXT_VERSION		"Mon. May 3, 11:41:51 PST 2010"
++#define MEGASAS_VERSION				"00.00.05.29-rc1"
++#define MEGASAS_RELDATE				"Dec. 7, 2010"
++#define MEGASAS_EXT_VERSION			"Tue. Dec. 7 17:00:00 PDT 2010"
+ 
+ /*
+  * Device IDs
+-- 
+1.8.0
+
+

Added: dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0044-megaraid_sas-version-and-changelog-update.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0044-megaraid_sas-version-and-changelog-update.patch	Sun Dec 16 23:23:22 2012	(r19615)
@@ -0,0 +1,87 @@
+From 8062acd7fc775779e6807147b520a39d8a0e587b Mon Sep 17 00:00:00 2001
+From: adam radford <aradford at gmail.com>
+Date: Thu, 24 Feb 2011 20:57:21 -0800
+Subject: [PATCH 44/53] [SCSI] megaraid_sas: Version and Changelog update
+
+commit 00fa2b191b4bd74e9d22ac177e3d9e8ecd3582d3 upstream.
+
+Signed-off-by: Adam Radford <aradford at gmail.com>
+Signed-off-by: James Bottomley <James.Bottomley at suse.de>
+Signed-off-by: Jonathan Nieder <jrnieder at gmail.com>
+---
+ Documentation/scsi/ChangeLog.megaraid_sas | 23 +++++++++++++++++++++++
+ drivers/scsi/megaraid/megaraid_sas.h      |  6 +++---
+ drivers/scsi/megaraid/megaraid_sas_base.c |  3 ++-
+ 3 files changed, 28 insertions(+), 4 deletions(-)
+
+diff --git a/Documentation/scsi/ChangeLog.megaraid_sas b/Documentation/scsi/ChangeLog.megaraid_sas
+index 399d39437654..6339bc7ef541 100644
+--- a/Documentation/scsi/ChangeLog.megaraid_sas
++++ b/Documentation/scsi/ChangeLog.megaraid_sas
+@@ -1,3 +1,26 @@
++Release Date    : Thu. Feb 24, 2011 17:00:00 PST 2010 -
++			(emaild-id:megaraidlinux at lsi.com)
++			Adam Radford
++Current Version : 00.00.05.34-rc1
++Old Version     : 00.00.05.29-rc1
++    1. Fix some failure gotos from megasas_probe_one(), etc.
++    2. Add missing check_and_restore_queue_depth() call in
++       complete_cmd_fusion().
++    3. Enable MSI-X before calling megasas_init_fw().
++    4. Call tasklet_schedule() even if outbound_intr_status == 0 for MFI based
++       boards in MSI-X mode.
++    5. Fix megasas_probe_one() to clear PCI_MSIX_FLAGS_ENABLE in msi control
++       register in kdump kernel.
++    6. Fix megasas_get_cmd() to only print "Command pool empty" if
++       megasas_dbg_lvl is set.
++    7. Fix megasas_build_dcdb_fusion() to not filter by TYPE_DISK.
++    8. Fix megasas_build_dcdb_fusion() to use io_request->LUN[1] field.
++    9. Add MR_EVT_CFG_CLEARED to megasas_aen_polling().
++    10. Fix tasklet_init() in megasas_init_fw() to use instancet->tasklet.
++    11. Fix fault state handling in megasas_transition_to_ready().
++    12. Fix max_sectors setting for IEEE SGL's.
++    13. Fix iMR OCR support to work correctly.
++-------------------------------------------------------------------------------
+ Release Date    : Tues.  Dec 14, 2010 17:00:00 PST 2010 -
+ 			(emaild-id:megaraidlinux at lsi.com)
+ 			Adam Radford
+diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h
+index c782bbc57cc8..635b228c3ead 100644
+--- a/drivers/scsi/megaraid/megaraid_sas.h
++++ b/drivers/scsi/megaraid/megaraid_sas.h
+@@ -33,9 +33,9 @@
+ /*
+  * MegaRAID SAS Driver meta data
+  */
+-#define MEGASAS_VERSION				"00.00.05.29-rc1"
+-#define MEGASAS_RELDATE				"Dec. 7, 2010"
+-#define MEGASAS_EXT_VERSION			"Tue. Dec. 7 17:00:00 PDT 2010"
++#define MEGASAS_VERSION				"00.00.05.34-rc1"
++#define MEGASAS_RELDATE				"Feb. 24, 2011"
++#define MEGASAS_EXT_VERSION			"Thu. Feb. 24 17:00:00 PDT 2011"
+ 
+ /*
+  * Device IDs
+diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c
+index 3fa0be03e6ab..b51e6a487d38 100644
+--- a/drivers/scsi/megaraid/megaraid_sas_base.c
++++ b/drivers/scsi/megaraid/megaraid_sas_base.c
+@@ -18,12 +18,13 @@
+  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+  *
+  *  FILE: megaraid_sas_base.c
+- *  Version : v00.00.05.29-rc1
++ *  Version : v00.00.05.34-rc1
+  *
+  *  Authors: LSI Corporation
+  *           Sreenivas Bagalkote
+  *           Sumant Patro
+  *           Bo Yang
++ *           Adam Radford <linuxraid at lsi.com>
+  *
+  *  Send feedback to: <megaraidlinux at lsi.com>
+  *
+-- 
+1.8.0
+
+

Added: dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0045-megaraid_sas-remove-msi-x-black-list-use-mfi_reg_state-instead.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0045-megaraid_sas-remove-msi-x-black-list-use-mfi_reg_state-instead.patch	Sun Dec 16 23:23:22 2012	(r19615)
@@ -0,0 +1,98 @@
+From d7090b197b347ebf29713a3e0c6932189b09ed0c Mon Sep 17 00:00:00 2001
+From: adam radford <aradford at gmail.com>
+Date: Wed, 11 May 2011 18:33:47 -0700
+Subject: [PATCH 45/53] [SCSI] megaraid_sas: Remove MSI-X black list, use  MFI_REG_STATE instead
+
+commit 3f1abce4aba4ced0ba8be54b22f2882bdd01c746 upstream.
+
+This patch for megaraid_sas removes the MSI-X black list and uses
+MFI_REG_STATE.ready.msiEnable instead.
+
+Signed-off-by: Adam Radford <aradford at gmail.com>
+Signed-off-by: James Bottomley <jbottomley at parallels.com>
+Signed-off-by: Jonathan Nieder <jrnieder at gmail.com>
+---
+ drivers/scsi/megaraid/megaraid_sas_base.c | 41 +++++++++++++++----------------
+ 1 file changed, 20 insertions(+), 21 deletions(-)
+
+diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c
+index b51e6a487d38..e682f1ab09df 100644
+--- a/drivers/scsi/megaraid/megaraid_sas_base.c
++++ b/drivers/scsi/megaraid/megaraid_sas_base.c
+@@ -3452,7 +3452,7 @@ static int megasas_init_fw(struct megasas_instance *instance)
+ {
+ 	u32 max_sectors_1;
+ 	u32 max_sectors_2;
+-	u32 tmp_sectors;
++	u32 tmp_sectors, msix_enable;
+ 	struct megasas_register_set __iomem *reg_set;
+ 	struct megasas_ctrl_info *ctrl_info;
+ 	unsigned long bar_list;
+@@ -3505,6 +3505,13 @@ static int megasas_init_fw(struct megasas_instance *instance)
+ 	if (megasas_transition_to_ready(instance))
+ 		goto fail_ready_state;
+ 
++	/* Check if MSI-X is supported while in ready state */
++	msix_enable = (instance->instancet->read_fw_status_reg(reg_set) &
++		       0x4000000) >> 0x1a;
++	if (msix_enable && !msix_disable &&
++	    !pci_enable_msix(instance->pdev, &instance->msixentry, 1))
++		instance->msi_flag = 1;
++
+ 	/* Get operational params, sge flags, send init cmd to controller */
+ 	if (instance->instancet->init_adapter(instance))
+ 		goto fail_init_adapter;
+@@ -4074,14 +4081,6 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ 	else
+ 		INIT_WORK(&instance->work_init, process_fw_state_change_wq);
+ 
+-	/* Try to enable MSI-X */
+-	if ((instance->pdev->device != PCI_DEVICE_ID_LSI_SAS1078R) &&
+-	    (instance->pdev->device != PCI_DEVICE_ID_LSI_SAS1078DE) &&
+-	    (instance->pdev->device != PCI_DEVICE_ID_LSI_VERDE_ZCR) &&
+-	    !msix_disable && !pci_enable_msix(instance->pdev,
+-					      &instance->msixentry, 1))
+-		instance->msi_flag = 1;
+-
+ 	/*
+ 	 * Initialize MFI Firmware
+ 	 */
+@@ -4331,22 +4330,22 @@ megasas_resume(struct pci_dev *pdev)
+ 	if (megasas_set_dma_mask(pdev))
+ 		goto fail_set_dma_mask;
+ 
++	/*
++	 * Initialize MFI Firmware
++	 */
++
++	atomic_set(&instance->fw_outstanding, 0);
++
++	/*
++	 * We expect the FW state to be READY
++	 */
++	if (megasas_transition_to_ready(instance))
++		goto fail_ready_state;
++
+ 	/* Now re-enable MSI-X */
+ 	if (instance->msi_flag)
+ 		pci_enable_msix(instance->pdev, &instance->msixentry, 1);
+ 
+-	/*
+-	 * Initialize MFI Firmware
+-	 */
+-
+-	atomic_set(&instance->fw_outstanding, 0);
+-
+-	/*
+-	 * We expect the FW state to be READY
+-	 */
+-	if (megasas_transition_to_ready(instance))
+-		goto fail_ready_state;
+-
+ 	switch (instance->pdev->device) {
+ 	case PCI_DEVICE_ID_LSI_FUSION:
+ 	{
+-- 
+1.8.0
+
+

Added: dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0046-megaraid_sas-remove-un-used-function.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0046-megaraid_sas-remove-un-used-function.patch	Sun Dec 16 23:23:22 2012	(r19615)
@@ -0,0 +1,48 @@
+From 15eb3dd67c96030cdfd94dc3b63f32fd8b17dd60 Mon Sep 17 00:00:00 2001
+From: adam radford <aradford at gmail.com>
+Date: Wed, 11 May 2011 18:33:58 -0700
+Subject: [PATCH 46/53] [SCSI] megaraid_sas: Remove un-used function
+
+commit 70d031f36fa50a53128d0d2b5f95032cd534778b upstream.
+
+The following patch for megaraid_sas removes un-used function
+megasas_return_cmd_for_smid().
+
+Signed-off-by: Adam Radford <aradford at gmail.com>
+Signed-off-by: James Bottomley <jbottomley at parallels.com>
+Signed-off-by: Jonathan Nieder <jrnieder at gmail.com>
+---
+ drivers/scsi/megaraid/megaraid_sas_fusion.c | 16 ----------------
+ 1 file changed, 16 deletions(-)
+
+diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.c b/drivers/scsi/megaraid/megaraid_sas_fusion.c
+index 905c1e9317b6..c25ef20ee907 100644
+--- a/drivers/scsi/megaraid/megaraid_sas_fusion.c
++++ b/drivers/scsi/megaraid/megaraid_sas_fusion.c
+@@ -697,22 +697,6 @@ fail_get_cmd:
+ }
+ 
+ /*
+- * megasas_return_cmd_for_smid -	Returns a cmd_fusion for a SMID
+- * @instance:				Adapter soft state
+- *
+- */
+-void
+-megasas_return_cmd_for_smid(struct megasas_instance *instance, u16 smid)
+-{
+-	struct fusion_context *fusion;
+-	struct megasas_cmd_fusion *cmd;
+-
+-	fusion = instance->ctrl_context;
+-	cmd = fusion->cmd_list[smid - 1];
+-	megasas_return_cmd_fusion(instance, cmd);
+-}
+-
+-/*
+  * megasas_get_ld_map_info -	Returns FW's ld_map structure
+  * @instance:				Adapter soft state
+  * @pend:				Pend the command or not
+-- 
+1.8.0
+
+

Added: dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0047-megaraid_sas-check-mfi_reg_state.fault.resetadapter.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0047-megaraid_sas-check-mfi_reg_state.fault.resetadapter.patch	Sun Dec 16 23:23:22 2012	(r19615)
@@ -0,0 +1,115 @@
+From 96ecbc1c5330e76b4b8f6334d66bdeb0177987fd Mon Sep 17 00:00:00 2001
+From: adam radford <aradford at gmail.com>
+Date: Wed, 11 May 2011 18:34:08 -0700
+Subject: [PATCH 47/53] [SCSI] megaraid_sas: Check  MFI_REG_STATE.fault.resetAdapter
+
+commit 7e70e7336515cd367b9cfcf5379e04808bdcbe96 upstream.
+
+The following patch for megaraid_sas fixes the function
+megasas_reset_fusion() and makes the reset code check
+MFI_REG_STATE.fault.resetAdapter.
+
+Signed-off-by: Adam Radford <aradford at gmail.com>
+Signed-off-by: James Bottomley <jbottomley at parallels.com>
+Signed-off-by: Jonathan Nieder <jrnieder at gmail.com>
+---
+ drivers/scsi/megaraid/megaraid_sas.h        |  4 ++--
+ drivers/scsi/megaraid/megaraid_sas_fusion.c | 28 +++++++++++++++++-----------
+ 2 files changed, 19 insertions(+), 13 deletions(-)
+
+diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h
+index 635b228c3ead..32eb61787488 100644
+--- a/drivers/scsi/megaraid/megaraid_sas.h
++++ b/drivers/scsi/megaraid/megaraid_sas.h
+@@ -76,8 +76,8 @@
+ #define MFI_STATE_READY				0xB0000000
+ #define MFI_STATE_OPERATIONAL			0xC0000000
+ #define MFI_STATE_FAULT				0xF0000000
+-#define  MFI_RESET_REQUIRED			0x00000001
+-
++#define MFI_RESET_REQUIRED			0x00000001
++#define MFI_RESET_ADAPTER			0x00000002
+ #define MEGAMFI_FRAME_SIZE			64
+ 
+ /*
+diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.c b/drivers/scsi/megaraid/megaraid_sas_fusion.c
+index c25ef20ee907..c65bf5ad9440 100644
+--- a/drivers/scsi/megaraid/megaraid_sas_fusion.c
++++ b/drivers/scsi/megaraid/megaraid_sas_fusion.c
+@@ -2011,24 +2011,24 @@ int megasas_reset_fusion(struct Scsi_Host *shost)
+ 	struct fusion_context *fusion;
+ 	struct megasas_cmd *cmd_mfi;
+ 	union MEGASAS_REQUEST_DESCRIPTOR_UNION *req_desc;
+-	u32 host_diag, abs_state;
++	u32 host_diag, abs_state, status_reg, reset_adapter;
+ 
+ 	instance = (struct megasas_instance *)shost->hostdata;
+ 	fusion = instance->ctrl_context;
+ 
++	if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR) {
++		printk(KERN_WARNING "megaraid_sas: Hardware critical error, "
++		       "returning FAILED.\n");
++		retval = FAILED;
++		goto out;
++	}
++
+ 	mutex_lock(&instance->reset_mutex);
+ 	set_bit(MEGASAS_FUSION_IN_RESET, &instance->reset_flags);
+ 	instance->adprecovery = MEGASAS_ADPRESET_SM_INFAULT;
+ 	instance->instancet->disable_intr(instance->reg_set);
+ 	msleep(1000);
+ 
+-	if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR) {
+-		printk(KERN_WARNING "megaraid_sas: Hardware critical error, "
+-		       "returning FAILED.\n");
+-		retval = FAILED;
+-		goto out;
+-	}
+-
+ 	/* First try waiting for commands to complete */
+ 	if (megasas_wait_for_outstanding_fusion(instance)) {
+ 		printk(KERN_WARNING "megaraid_sas: resetting fusion "
+@@ -2045,7 +2045,12 @@ int megasas_reset_fusion(struct Scsi_Host *shost)
+ 			}
+ 		}
+ 
+-		if (instance->disableOnlineCtrlReset == 1) {
++		status_reg = instance->instancet->read_fw_status_reg(
++			instance->reg_set);
++		abs_state = status_reg & MFI_STATE_MASK;
++		reset_adapter = status_reg & MFI_RESET_ADAPTER;
++		if (instance->disableOnlineCtrlReset ||
++		    (abs_state == MFI_STATE_FAULT && !reset_adapter)) {
+ 			/* Reset not supported, kill adapter */
+ 			printk(KERN_WARNING "megaraid_sas: Reset not supported"
+ 			       ", killing adapter.\n");
+@@ -2074,6 +2079,7 @@ int megasas_reset_fusion(struct Scsi_Host *shost)
+ 
+ 			/* Check that the diag write enable (DRWE) bit is on */
+ 			host_diag = readl(&instance->reg_set->fusion_host_diag);
++			retry = 0;
+ 			while (!(host_diag & HOST_DIAG_WRITE_ENABLE)) {
+ 				msleep(100);
+ 				host_diag =
+@@ -2111,7 +2117,7 @@ int megasas_reset_fusion(struct Scsi_Host *shost)
+ 
+ 			abs_state =
+ 				instance->instancet->read_fw_status_reg(
+-					instance->reg_set);
++					instance->reg_set) & MFI_STATE_MASK;
+ 			retry = 0;
+ 
+ 			while ((abs_state <= MFI_STATE_FW_INIT) &&
+@@ -2119,7 +2125,7 @@ int megasas_reset_fusion(struct Scsi_Host *shost)
+ 				msleep(100);
+ 				abs_state =
+ 				instance->instancet->read_fw_status_reg(
+-					instance->reg_set);
++					instance->reg_set) & MFI_STATE_MASK;
+ 			}
+ 			if (abs_state <= MFI_STATE_FW_INIT) {
+ 				printk(KERN_WARNING "megaraid_sas: firmware "
+-- 
+1.8.0
+
+

Added: dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0048-megaraid_sas-disable-interrupts-free_irq-in-megasas_shutdown.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0048-megaraid_sas-disable-interrupts-free_irq-in-megasas_shutdown.patch	Sun Dec 16 23:23:22 2012	(r19615)
@@ -0,0 +1,37 @@
+From 827abc36e1c21775c23f6b180d86c08586ca1661 Mon Sep 17 00:00:00 2001
+From: adam radford <aradford at gmail.com>
+Date: Wed, 11 May 2011 18:34:17 -0700
+Subject: [PATCH 48/53] [SCSI] megaraid_sas: Disable interrupts/free_irq() in  megasas_shutdown()
+
+commit 46fd256e05581e4a04d5a8ec107d35afe938c65b upstream.
+
+The following patch for megaraid_sas disables interrupts and
+free_irq() in megasas_shutdown().
+
+Signed-off-by: Adam Radford <aradford at gmail.com>
+Signed-off-by: James Bottomley <jbottomley at parallels.com>
+Signed-off-by: Jonathan Nieder <jrnieder at gmail.com>
+---
+ drivers/scsi/megaraid/megaraid_sas_base.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c
+index e682f1ab09df..245378009ad7 100644
+--- a/drivers/scsi/megaraid/megaraid_sas_base.c
++++ b/drivers/scsi/megaraid/megaraid_sas_base.c
+@@ -4526,6 +4526,11 @@ static void megasas_shutdown(struct pci_dev *pdev)
+ 	instance->unload = 1;
+ 	megasas_flush_cache(instance);
+ 	megasas_shutdown_controller(instance, MR_DCMD_CTRL_SHUTDOWN);
++	instance->instancet->disable_intr(instance->reg_set);
++	free_irq(instance->msi_flag ? instance->msixentry.vector :
++		 instance->pdev->irq, instance);
++	if (instance->msi_flag)
++		pci_disable_msix(instance->pdev);
+ }
+ 
+ /**
+-- 
+1.8.0
+
+

Added: dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0049-megaraid_sas-fix-bug-where-aens-could-be-lost-in-probe-and-resume.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0049-megaraid_sas-fix-bug-where-aens-could-be-lost-in-probe-and-resume.patch	Sun Dec 16 23:23:22 2012	(r19615)
@@ -0,0 +1,79 @@
+From 360b5f45d49e4a6a22509ae79c750fcc4f684070 Mon Sep 17 00:00:00 2001
+From: adam radford <aradford at gmail.com>
+Date: Wed, 11 May 2011 18:34:29 -0700
+Subject: [PATCH 49/53] [SCSI] megaraid_sas: Fix bug where AENs could be lost  in probe() and resume()
+
+commit 541f90b7c6dffe4cf4a3e8142ac8bd047da94733 upstream.
+
+Signed-off-by: Adam Radford <aradford at gmail.com>
+Signed-off-by: James Bottomley <jbottomley at parallels.com>
+Signed-off-by: Jonathan Nieder <jrnieder at gmail.com>
+---
+ drivers/scsi/megaraid/megaraid_sas_base.c | 31 ++++++++++++++++---------------
+ 1 file changed, 16 insertions(+), 15 deletions(-)
+
+diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c
+index 245378009ad7..4d655c98cf93 100644
+--- a/drivers/scsi/megaraid/megaraid_sas_base.c
++++ b/drivers/scsi/megaraid/megaraid_sas_base.c
+@@ -4113,20 +4113,21 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ 	megasas_mgmt_info.max_index++;
+ 
+ 	/*
+-	 * Initiate AEN (Asynchronous Event Notification)
+-	 */
+-	if (megasas_start_aen(instance)) {
+-		printk(KERN_DEBUG "megasas: start aen failed\n");
+-		goto fail_start_aen;
+-	}
+-
+-	/*
+ 	 * Register with SCSI mid-layer
+ 	 */
+ 	if (megasas_io_attach(instance))
+ 		goto fail_io_attach;
+ 
+ 	instance->unload = 0;
++
++	/*
++	 * Initiate AEN (Asynchronous Event Notification)
++	 */
++	if (megasas_start_aen(instance)) {
++		printk(KERN_DEBUG "megasas: start aen failed\n");
++		goto fail_start_aen;
++	}
++
+ 	return 0;
+ 
+       fail_start_aen:
+@@ -4382,19 +4383,19 @@ megasas_resume(struct pci_dev *pdev)
+ 
+ 	instance->instancet->enable_intr(instance->reg_set);
+ 
++	/* Initialize the cmd completion timer */
++	if (poll_mode_io)
++		megasas_start_timer(instance, &instance->io_completion_timer,
++				megasas_io_completion_timer,
++				MEGASAS_COMPLETION_TIMER_INTERVAL);
++	instance->unload = 0;
++
+ 	/*
+ 	 * Initiate AEN (Asynchronous Event Notification)
+ 	 */
+ 	if (megasas_start_aen(instance))
+ 		printk(KERN_ERR "megasas: Start AEN failed\n");
+ 
+-	/* Initialize the cmd completion timer */
+-	if (poll_mode_io)
+-		megasas_start_timer(instance, &instance->io_completion_timer,
+-				megasas_io_completion_timer,
+-				MEGASAS_COMPLETION_TIMER_INTERVAL);
+-	instance->unload = 0;
+-
+ 	return 0;
+ 
+ fail_irq:
+-- 
+1.8.0
+
+

Added: dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0050-megaraid_sas-convert-6-10-12-byte-cdb-s-for-fastpath-io.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0050-megaraid_sas-convert-6-10-12-byte-cdb-s-for-fastpath-io.patch	Sun Dec 16 23:23:22 2012	(r19615)
@@ -0,0 +1,81 @@
+From 3e7c5d14efc4bf3281b961c26be49f022df60a40 Mon Sep 17 00:00:00 2001
+From: adam radford <aradford at gmail.com>
+Date: Wed, 11 May 2011 18:34:40 -0700
+Subject: [PATCH 50/53] [SCSI] megaraid_sas: Convert 6,10,12 byte CDB's for  FastPath IO
+
+commit 495c5609700e21059fa0a4651b0f4f5847332319 upstream.
+
+The following patch for megaraid_sas converts 6,10,12 byte CDB's to 16
+byte CDB for large LBA's for FastPath IO.
+
+Signed-off-by: Adam Radford <aradford at gmail.com>
+Signed-off-by: James Bottomley <jbottomley at parallels.com>
+Signed-off-by: Jonathan Nieder <jrnieder at gmail.com>
+---
+ drivers/scsi/megaraid/megaraid_sas_fusion.c | 41 ++++++++++++++++++++++++++++-
+ 1 file changed, 40 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.c b/drivers/scsi/megaraid/megaraid_sas_fusion.c
+index c65bf5ad9440..35000aed1c44 100644
+--- a/drivers/scsi/megaraid/megaraid_sas_fusion.c
++++ b/drivers/scsi/megaraid/megaraid_sas_fusion.c
+@@ -1138,7 +1138,7 @@ megasas_set_pd_lba(struct MPI2_RAID_SCSI_IO_REQUEST *io_request, u8 cdb_len,
+ 	u64 start_blk = io_info->pdBlock;
+ 	u8 *cdb = io_request->CDB.CDB32;
+ 	u32 num_blocks = io_info->numBlocks;
+-	u8 opcode, flagvals, groupnum, control;
++	u8 opcode = 0, flagvals = 0, groupnum = 0, control = 0;
+ 
+ 	/* Check if T10 PI (DIF) is enabled for this LD */
+ 	ld = MR_TargetIdToLdGet(io_info->ldTgtId, local_map_ptr);
+@@ -1220,7 +1220,46 @@ megasas_set_pd_lba(struct MPI2_RAID_SCSI_IO_REQUEST *io_request, u8 cdb_len,
+ 			cdb[8] = (u8)(num_blocks & 0xff);
+ 			cdb[7] = (u8)((num_blocks >> 8) & 0xff);
+ 
++			io_request->IoFlags = 10; /* Specify 10-byte cdb */
+ 			cdb_len = 10;
++		} else if ((cdb_len < 16) && (start_blk > 0xffffffff)) {
++			/* Convert to 16 byte CDB for large LBA's */
++			switch (cdb_len) {
++			case 6:
++				opcode = cdb[0] == READ_6 ? READ_16 : WRITE_16;
++				control = cdb[5];
++				break;
++			case 10:
++				opcode =
++					cdb[0] == READ_10 ? READ_16 : WRITE_16;
++				flagvals = cdb[1];
++				groupnum = cdb[6];
++				control = cdb[9];
++				break;
++			case 12:
++				opcode =
++					cdb[0] == READ_12 ? READ_16 : WRITE_16;
++				flagvals = cdb[1];
++				groupnum = cdb[10];
++				control = cdb[11];
++				break;
++			}
++
++			memset(cdb, 0, sizeof(io_request->CDB.CDB32));
++
++			cdb[0] = opcode;
++			cdb[1] = flagvals;
++			cdb[14] = groupnum;
++			cdb[15] = control;
++
++			/* Transfer length */
++			cdb[13] = (u8)(num_blocks & 0xff);
++			cdb[12] = (u8)((num_blocks >> 8) & 0xff);
++			cdb[11] = (u8)((num_blocks >> 16) & 0xff);
++			cdb[10] = (u8)((num_blocks >> 24) & 0xff);
++
++			io_request->IoFlags = 16; /* Specify 16-byte cdb */
++			cdb_len = 16;
+ 		}
+ 
+ 		/* Normal case, just load LBA here */
+-- 
+1.8.0
+
+

Added: dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0051-megaraid_sas-add-1078-ocr-support.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0051-megaraid_sas-add-1078-ocr-support.patch	Sun Dec 16 23:23:22 2012	(r19615)
@@ -0,0 +1,106 @@
+From 38acd949b45e3e84fff8d2c5672ff7eddbacb35d Mon Sep 17 00:00:00 2001
+From: adam radford <aradford at gmail.com>
+Date: Wed, 11 May 2011 18:34:52 -0700
+Subject: [PATCH 51/53] [SCSI] megaraid_sas: Add 1078 OCR support
+
+commit 3cc6851f9a3509e2ced0eb218599857b07c0ab46 upstream.
+
+Signed-off-by: Adam Radford <aradford at gmail.com>
+Signed-off-by: James Bottomley <jbottomley at parallels.com>
+Signed-off-by: Jonathan Nieder <jrnieder at gmail.com>
+---
+ drivers/scsi/megaraid/megaraid_sas_base.c | 34 +++++++++++++++----------------
+ 1 file changed, 17 insertions(+), 17 deletions(-)
+
+diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c
+index 4d655c98cf93..94d49fac658f 100644
+--- a/drivers/scsi/megaraid/megaraid_sas_base.c
++++ b/drivers/scsi/megaraid/megaraid_sas_base.c
+@@ -437,15 +437,18 @@ megasas_read_fw_status_reg_ppc(struct megasas_register_set __iomem * regs)
+ static int
+ megasas_clear_intr_ppc(struct megasas_register_set __iomem * regs)
+ {
+-	u32 status;
++	u32 status, mfiStatus = 0;
++
+ 	/*
+ 	 * Check if it is our interrupt
+ 	 */
+ 	status = readl(&regs->outbound_intr_status);
+ 
+-	if (!(status & MFI_REPLY_1078_MESSAGE_INTERRUPT)) {
+-		return 0;
+-	}
++	if (status & MFI_REPLY_1078_MESSAGE_INTERRUPT)
++		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
+@@ -455,8 +458,9 @@ megasas_clear_intr_ppc(struct megasas_register_set __iomem * regs)
+ 	/* Dummy readl to force pci flush */
+ 	readl(&regs->outbound_doorbell_clear);
+ 
+-	return 1;
++	return mfiStatus;
+ }
++
+ /**
+  * megasas_fire_cmd_ppc -	Sends command to the FW
+  * @frame_phys_addr :		Physical address of cmd
+@@ -477,17 +481,6 @@ megasas_fire_cmd_ppc(struct megasas_instance *instance,
+ }
+ 
+ /**
+- * 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
+  */
+@@ -495,8 +488,12 @@ static int
+ megasas_check_reset_ppc(struct megasas_instance *instance,
+ 			struct megasas_register_set __iomem *regs)
+ {
++	if (instance->adprecovery != MEGASAS_HBA_OPERATIONAL)
++		return 1;
++
+ 	return 0;
+ }
++
+ static struct megasas_instance_template megasas_instance_template_ppc = {
+ 
+ 	.fire_cmd = megasas_fire_cmd_ppc,
+@@ -504,7 +501,7 @@ 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,
++	.adp_reset = megasas_adp_reset_xscale,
+ 	.check_reset = megasas_check_reset_ppc,
+ 	.service_isr = megasas_isr,
+ 	.tasklet = megasas_complete_cmd_dpc,
+@@ -620,6 +617,9 @@ static int
+ megasas_check_reset_skinny(struct megasas_instance *instance,
+ 				struct megasas_register_set __iomem *regs)
+ {
++	if (instance->adprecovery != MEGASAS_HBA_OPERATIONAL)
++		return 1;
++
+ 	return 0;
+ }
+ 
+-- 
+1.8.0
+
+

Added: dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0052-megaraid_sas-version-and-changelog-update.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0052-megaraid_sas-version-and-changelog-update.patch	Sun Dec 16 23:23:22 2012	(r19615)
@@ -0,0 +1,72 @@
+From eb2eee548e156baf3d3e6aef9a358488db022c9f Mon Sep 17 00:00:00 2001
+From: adam radford <aradford at gmail.com>
+Date: Wed, 11 May 2011 18:35:05 -0700
+Subject: [PATCH 52/53] [SCSI] megaraid_sas: Version and Changelog update
+
+commit 4f788dce0baf44295a8d9708d3f124587158c061 upstream.
+
+Signed-off-by: Adam Radford <aradford at gmail.com>
+Signed-off-by: James Bottomley <jbottomley at parallels.com>
+Signed-off-by: Jonathan Nieder <jrnieder at gmail.com>
+---
+ Documentation/scsi/ChangeLog.megaraid_sas | 14 ++++++++++++++
+ drivers/scsi/megaraid/megaraid_sas.h      |  6 +++---
+ drivers/scsi/megaraid/megaraid_sas_base.c |  2 +-
+ 3 files changed, 18 insertions(+), 4 deletions(-)
+
+diff --git a/Documentation/scsi/ChangeLog.megaraid_sas b/Documentation/scsi/ChangeLog.megaraid_sas
+index 6339bc7ef541..a2e140095ef7 100644
+--- a/Documentation/scsi/ChangeLog.megaraid_sas
++++ b/Documentation/scsi/ChangeLog.megaraid_sas
+@@ -1,3 +1,17 @@
++Release Date    : Wed. May 11, 2011 17:00:00 PST 2010 -
++			(emaild-id:megaraidlinux at lsi.com)
++			Adam Radford
++Current Version : 00.00.05.38-rc1
++Old Version     : 00.00.05.34-rc1
++    1. Remove MSI-X black list, use MFI_REG_STATE.ready.msiEnable.
++    2. Remove un-used function megasas_return_cmd_for_smid().
++    3. Check MFI_REG_STATE.fault.resetAdapter in megasas_reset_fusion().
++    4. Disable interrupts/free_irq() in megasas_shutdown().
++    5. Fix bug where AENs could be lost in probe() and resume().
++    6. Convert 6,10,12 byte CDB's to 16 byte CDB for large LBA's for FastPath
++       IO.
++    7. Add 1078 OCR support.
++-------------------------------------------------------------------------------
+ Release Date    : Thu. Feb 24, 2011 17:00:00 PST 2010 -
+ 			(emaild-id:megaraidlinux at lsi.com)
+ 			Adam Radford
+diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h
+index 32eb61787488..fcc09ca374b7 100644
+--- a/drivers/scsi/megaraid/megaraid_sas.h
++++ b/drivers/scsi/megaraid/megaraid_sas.h
+@@ -33,9 +33,9 @@
+ /*
+  * MegaRAID SAS Driver meta data
+  */
+-#define MEGASAS_VERSION				"00.00.05.34-rc1"
+-#define MEGASAS_RELDATE				"Feb. 24, 2011"
+-#define MEGASAS_EXT_VERSION			"Thu. Feb. 24 17:00:00 PDT 2011"
++#define MEGASAS_VERSION				"00.00.05.38-rc1"
++#define MEGASAS_RELDATE				"May. 11, 2011"
++#define MEGASAS_EXT_VERSION			"Wed. May. 11 17:00:00 PDT 2011"
+ 
+ /*
+  * Device IDs
+diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c
+index 94d49fac658f..d89fa1d85d77 100644
+--- a/drivers/scsi/megaraid/megaraid_sas_base.c
++++ b/drivers/scsi/megaraid/megaraid_sas_base.c
+@@ -18,7 +18,7 @@
+  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+  *
+  *  FILE: megaraid_sas_base.c
+- *  Version : v00.00.05.34-rc1
++ *  Version : v00.00.05.38-rc1
+  *
+  *  Authors: LSI Corporation
+  *           Sreenivas Bagalkote
+-- 
+1.8.0
+
+

Added: dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0053-megaraid_sas-move-poll_aen_lock-initializer.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0053-megaraid_sas-move-poll_aen_lock-initializer.patch	Sun Dec 16 23:23:22 2012	(r19615)
@@ -0,0 +1,44 @@
+From 2b082e5d334030d5325a4f43a4b33514c1d211bf Mon Sep 17 00:00:00 2001
+From: Kashyap Desai <Kashyap.Desai at lsi.com>
+Date: Tue, 17 Jul 2012 18:20:44 -0700
+Subject: [PATCH 53/53] [SCSI] megaraid_sas: Move poll_aen_lock initializer
+
+commit bd8d6dd43a77bfd2b8fef5b094b9d6095e169dee upstream.
+
+The following patch moves the poll_aen_lock initializer from
+megasas_probe_one() to megasas_init().  This prevents a crash when a user
+loads the driver and tries to issue a poll() system call on the ioctl
+interface with no adapters present.
+
+Signed-off-by: Kashyap Desai <Kashyap.Desai at lsi.com>
+Signed-off-by: Adam Radford <aradford at gmail.com>
+Signed-off-by: James Bottomley <JBottomley at Parallels.com>
+Signed-off-by: Jonathan Nieder <jrnieder at gmail.com>
+---
+ drivers/scsi/megaraid/megaraid_sas_base.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c
+index d89fa1d85d77..26d1ad44e4c7 100644
+--- a/drivers/scsi/megaraid/megaraid_sas_base.c
++++ b/drivers/scsi/megaraid/megaraid_sas_base.c
+@@ -4051,7 +4051,6 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ 	spin_lock_init(&instance->cmd_pool_lock);
+ 	spin_lock_init(&instance->hba_lock);
+ 	spin_lock_init(&instance->completion_lock);
+-	spin_lock_init(&poll_aen_lock);
+ 
+ 	mutex_init(&instance->aen_mutex);
+ 	mutex_init(&instance->reset_mutex);
+@@ -5381,6 +5380,8 @@ static int __init megasas_init(void)
+ 	printk(KERN_INFO "megasas: %s %s\n", MEGASAS_VERSION,
+ 	       MEGASAS_EXT_VERSION);
+ 
++	spin_lock_init(&poll_aen_lock);
++
+ 	support_poll_for_event = 2;
+ 	support_device_change = 1;
+ 
+-- 
+1.8.0
+

Added: dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0054-megaraid_sas-cosmetic-changes.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/squeeze/linux-2.6/debian/patches/features/all/megaraid_sas/0054-megaraid_sas-cosmetic-changes.patch	Sun Dec 16 23:23:22 2012	(r19615)
@@ -0,0 +1,137 @@
+From: Ben Hutchings <ben at decadent.org.uk>
+Subject: megaraid_sas: Cosmetic changes to resync with upstream
+Date: Sun, 16 Dec 2012 23:17:41 +0000
+
+Apply cosmetic changes:
+- Spelling fixes from commits 25985edcedea, 80682fa9f7093 and others
+- commit 5cd049a59913 ('[SCSI] remove cmd->serial_number litter')
+- Code motion from merge commits
+
+--- a/drivers/scsi/megaraid/megaraid_sas_base.c
++++ b/drivers/scsi/megaraid/megaraid_sas_base.c
+@@ -65,10 +65,6 @@
+ MODULE_PARM_DESC(poll_mode_io,
+ 	"Complete cmds from IO path, (default=0)");
+ 
+-static int msix_disable;
+-module_param(msix_disable, int, S_IRUGO);
+-MODULE_PARM_DESC(msix_disable, "Disable MSI-X interrupt handling. Default: 0");
+-
+ /*
+  * Number of sectors per IO command
+  * Will be set in megasas_init_mfi if user does not provide
+@@ -78,6 +74,10 @@
+ MODULE_PARM_DESC(max_sectors,
+ 	"Maximum number of sectors per IO command");
+ 
++static int msix_disable;
++module_param(msix_disable, int, S_IRUGO);
++MODULE_PARM_DESC(msix_disable, "Disable MSI-X interrupt handling. Default: 0");
++
+ MODULE_LICENSE("GPL");
+ MODULE_VERSION(MEGASAS_VERSION);
+ MODULE_AUTHOR("megaraidlinux at lsi.com");
+@@ -890,7 +890,7 @@
+  * @instance:				Adapter soft state
+  * @cmd_to_abort:			Previously issued cmd to be aborted
+  *
+- * MFI firmware can abort previously issued AEN comamnd (automatic event
++ * MFI firmware can abort previously issued AEN command (automatic event
+  * notification). The megasas_issue_blocked_abort_cmd() issues such abort
+  * cmd and waits for return status.
+  * Max wait time is MEGASAS_INTERNAL_CMD_WAIT_TIME secs
+@@ -1696,7 +1698,7 @@
+  * megasas_wait_for_outstanding -	Wait for all outstanding cmds
+  * @instance:				Adapter soft state
+  *
+- * This function waits for upto MEGASAS_RESET_WAIT_TIME seconds for FW to
++ * This function waits for up to MEGASAS_RESET_WAIT_TIME seconds for FW to
+  * complete all its outstanding commands. Returns error if one or more IOs
+  * are pending after this time period. It also marks the controller dead.
+  */
+@@ -1749,10 +1751,9 @@
+ 			list_del_init(&reset_cmd->list);
+ 			if (reset_cmd->scmd) {
+ 				reset_cmd->scmd->result = DID_RESET << 16;
+-				printk(KERN_NOTICE "%d:%p reset [%02x], %#lx\n",
++				printk(KERN_NOTICE "%d:%p reset [%02x]\n",
+ 					reset_index, reset_cmd,
+-					reset_cmd->scmd->cmnd[0],
+-					reset_cmd->scmd->serial_number);
++					reset_cmd->scmd->cmnd[0]);
+ 
+ 				reset_cmd->scmd->scsi_done(reset_cmd->scmd);
+ 				megasas_return_cmd(instance, reset_cmd);
+@@ -1877,8 +1878,8 @@
+ 
+ 	instance = (struct megasas_instance *)scmd->device->host->hostdata;
+ 
+-	scmd_printk(KERN_NOTICE, scmd, "megasas: RESET -%ld cmd=%x retries=%x\n",
+-		 scmd->serial_number, scmd->cmnd[0], scmd->retries);
++	scmd_printk(KERN_NOTICE, scmd, "megasas: RESET cmd=%x retries=%x\n",
++		 scmd->cmnd[0], scmd->retries);
+ 
+ 	if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR) {
+ 		printk(KERN_ERR "megasas: cannot recover from previous reset "
+@@ -2346,9 +2347,9 @@
+ 							cmd->frame_phys_addr ,
+ 							0, instance->reg_set);
+ 		} else if (cmd->scmd) {
+-			printk(KERN_NOTICE "megasas: %p scsi cmd [%02x],%#lx"
++			printk(KERN_NOTICE "megasas: %p scsi cmd [%02x]"
+ 			"detected on the internal queue, issue again.\n",
+-			cmd, cmd->scmd->cmnd[0], cmd->scmd->serial_number);
++			cmd, cmd->scmd->cmnd[0]);
+ 
+ 			atomic_inc(&instance->fw_outstanding);
+ 			instance->instancet->fire_cmd(instance,
+@@ -5424,11 +5423,6 @@
+ 		goto err_dcf_support_poll_for_event;
+ 
+ 	rval = driver_create_file(&megasas_pci_driver.driver,
+-				&driver_attr_support_device_change);
+-	if (rval)
+-		goto err_dcf_support_device_change;
+-
+-	rval = driver_create_file(&megasas_pci_driver.driver,
+ 				  &driver_attr_dbg_lvl);
+ 	if (rval)
+ 		goto err_dcf_dbg_lvl;
+@@ -5437,17 +5431,22 @@
+ 	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_device_change);
+-
+-err_dcf_support_device_change:
+-	driver_remove_file(&megasas_pci_driver.driver,
+ 			&driver_attr_support_poll_for_event);
+ 
+ err_dcf_support_poll_for_event:
+--- a/drivers/scsi/megaraid/megaraid_sas.h
++++ b/drivers/scsi/megaraid/megaraid_sas.h
+@@ -1347,7 +1347,7 @@
+ 	struct timer_list io_completion_timer;
+ 	struct list_head internal_reset_pending_q;
+ 
+-	/* Ptr to hba specfic information */
++	/* Ptr to hba specific information */
+ 	void *ctrl_context;
+ 	u8	msi_flag;
+ 	struct msix_entry msixentry;

Modified: dists/squeeze/linux-2.6/debian/patches/series/47
==============================================================================
--- dists/squeeze/linux-2.6/debian/patches/series/47	Sun Dec 16 22:31:39 2012	(r19614)
+++ dists/squeeze/linux-2.6/debian/patches/series/47	Sun Dec 16 23:23:22 2012	(r19615)
@@ -66,3 +66,55 @@
 + features/all/hpsa/0136-hpsa-fix-handling-of-protocol-error.patch
 + features/all/hpsa/0137-hpsa-Use-LUN-reset-instead-of-target-reset.patch
 + features/all/hpsa/0138-hpsa-dial-down-lockup-detection-during-firmware-flas.patch
+
+# Update megaraid_sas to 3.0.56
+# First 5 commits already applied in -29
++ features/all/megaraid_sas/0006-megaraid_sas-infrastructure-to-get-pds-from-fw.patch
++ features/all/megaraid_sas/0007-megaraid_sas-add-the-support-for-updating-the-os-after-adding-removing-the-devices-from-fw.patch
++ features/all/megaraid_sas/0008-megaraid_sas-add-the-logical-drive-list-to-driver.patch
++ features/all/megaraid_sas/0009-megaraid_sas-driver-fixed-the-device-update-issue.patch
++ features/all/megaraid_sas/0010-megaraid_sas-add-the-ieee-sge-support-to-sas2-controller.patch
++ features/all/megaraid_sas/0011-megaraid_sas-add-online-controller-reset-to-megaraid-sas-drive.patch
++ features/all/megaraid_sas/0012-megaraid_sas-rename-megaraid_sas.c-to-megaraid_sas_base.c.patch
++ features/all/megaraid_sas/0013-megaraid_sas-add-msi-x-support-and-msix_disable-module-parameter.patch
++ features/all/megaraid_sas/0014-megaraid_sas-make-driver-pci-legacy-i-o-port-free-driver.patch
++ features/all/megaraid_sas/0015-megaraid_sas-use-lowest-memory-bar-for-sr-iov-vf-support.patch
++ features/all/megaraid_sas/0016-megaraid_sas-add-struct-megasas_instance_template-changes.patch
++ features/all/megaraid_sas/0017-megaraid_sas-add-9565-9285-specific-code.patch
++ features/all/megaraid_sas/0018-megaraid_sas-fix-instance-access-in-megasas_reset_timer.patch
++ features/all/megaraid_sas/0019-megaraid_sas-tape-drive-support-fix.patch
++ features/all/megaraid_sas/0020-megaraid_sas-report-system-pds-to-os.patch
++ features/all/megaraid_sas/0021-megaraid_sas-use-the-firmware-boot-timeout-when-waiting-for-commands.patch
++ features/all/megaraid_sas/0022-megaraid_sas-update-version-number-and-documentation.patch
++ features/all/megaraid_sas/0023-megaraid_sas-zero-pad_0-in-mfi-structure.patch
++ features/all/megaraid_sas/0024-megaraid_sas-version-and-documentation-update.patch
++ features/all/megaraid_sas/0025-megaraid_sas-support-devices-update-flag.patch
++ features/all/megaraid_sas/0026-megaraid_sas-add-input-parameter-for-max_sectors.patch
++ features/all/megaraid_sas/0027-megaraid_sas-add-three-times-online-controller-reset.patch
++ features/all/megaraid_sas/0028-megaraid_sas-version-and-documentation-update.patch
++ features/all/megaraid_sas/0029-megaraid_sas-update-gpl-headers.patch
++ features/all/megaraid_sas/0030-megaraid_sas-fix-failure-gotos.patch
++ features/all/megaraid_sas/0031-megaraid_sas-add-missing-check_and_restore_queue_depth-call.patch
++ features/all/megaraid_sas/0032-megaraid_sas-enable-msi-x-before-calling-megasas_init_fw.patch
++ features/all/megaraid_sas/0033-megaraid_sas-call-tasklet_schedule-for-msi-x.patch
++ features/all/megaraid_sas/0034-megaraid_sas-fix-probe_one-to-clear-msi-x-flags-in-kdump.patch
++ features/all/megaraid_sas/0035-megaraid_sas-fix-megasas_build_dcdb_fusion-to-not-filter-by-type_disk.patch
++ features/all/megaraid_sas/0036-megaraid_sas-fix-megasas_build_dcdb_fusion-to-use-correct-lun-field.patch
++ features/all/megaraid_sas/0037-megaraid_sas-add-cfg_cleared-aen.patch
++ features/all/megaraid_sas/0038-megaraid_sas-fix-tasklet_init-call.patch
++ features/all/megaraid_sas/0039-megaraid_sas-fix-fault-state-handling.patch
++ features/all/megaraid_sas/0040-megaraid_sas-fix-max_sectors-for-ieee-sgl.patch
++ features/all/megaraid_sas/0041-megaraid_sas-fix-imr-ocr-support-to-work-correctly.patch
++ features/all/megaraid_sas/0042-megaraid_sas-documentation-update.patch
++ features/all/megaraid_sas/0043-megaraid_sas-add-9565-9285-specific-code-version-bump.patch
++ features/all/megaraid_sas/0044-megaraid_sas-version-and-changelog-update.patch
++ features/all/megaraid_sas/0045-megaraid_sas-remove-msi-x-black-list-use-mfi_reg_state-instead.patch
++ features/all/megaraid_sas/0046-megaraid_sas-remove-un-used-function.patch
++ features/all/megaraid_sas/0047-megaraid_sas-check-mfi_reg_state.fault.resetadapter.patch
++ features/all/megaraid_sas/0048-megaraid_sas-disable-interrupts-free_irq-in-megasas_shutdown.patch
++ features/all/megaraid_sas/0049-megaraid_sas-fix-bug-where-aens-could-be-lost-in-probe-and-resume.patch
++ features/all/megaraid_sas/0050-megaraid_sas-convert-6-10-12-byte-cdb-s-for-fastpath-io.patch
++ features/all/megaraid_sas/0051-megaraid_sas-add-1078-ocr-support.patch
++ features/all/megaraid_sas/0052-megaraid_sas-version-and-changelog-update.patch
++ features/all/megaraid_sas/0053-megaraid_sas-move-poll_aen_lock-initializer.patch
++ features/all/megaraid_sas/0054-megaraid_sas-cosmetic-changes.patch



More information about the Kernel-svn-changes mailing list