Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9c915a8c authored by Adam Radford's avatar Adam Radford Committed by James Bottomley
Browse files

[SCSI] megaraid_sas: Add 9565/9285 specific code



This patch adds MegaRAID 9265/9285 (Device id 0x5b) specific code

Signed-off-by: default avatarAdam Radford <aradford@gmail.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@suse.de>
parent cd50ba8e
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
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
+30 −8
Original line number Diff line number Diff line
@@ -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
@@ -47,6 +47,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

/*
 * =====================================
@@ -436,7 +437,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;
@@ -716,6 +716,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 * \
@@ -784,7 +785,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*/
@@ -804,15 +808,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*/

@@ -1287,6 +1294,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;

@@ -1336,9 +1346,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 {
@@ -1397,8 +1413,14 @@ struct megasas_cmd {
	struct list_head list;
	struct scsi_cmnd *scmd;
	struct megasas_instance *instance;
	union {
		struct {
			u16 smid;
			u16 resvd;
		} context;
		u32 frame_count;
	};
};

#define MAX_MGMT_ADAPTERS		1024
#define MAX_IOCTL_SGE			16
+260 −102
Original line number Diff line number Diff line
@@ -53,6 +53,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"

/*
@@ -81,7 +82,7 @@ MODULE_VERSION(MEGASAS_VERSION);
MODULE_AUTHOR("megaraidlinux@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,
@@ -109,6 +110,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 */
	{}
};

@@ -122,15 +125,16 @@ 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;
static u32 support_device_change;

/* 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);
@@ -138,6 +142,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)
@@ -152,7 +173,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;
@@ -177,7 +198,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;
@@ -185,6 +206,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);
@@ -796,6 +818,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
@@ -803,11 +830,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;

@@ -817,21 +842,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);
}

/**
@@ -849,8 +865,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);

@@ -894,8 +909,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
@@ -1291,7 +1305,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;
@@ -1551,15 +1565,44 @@ static int megasas_slave_alloc(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);
	}
}

@@ -1613,24 +1656,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);
}

static void
@@ -1808,7 +1834,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);
@@ -1912,10 +1938,15 @@ 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
	 */
	if (instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION)
		ret = megasas_reset_fusion(scmd->device->host);
	else
		ret = megasas_generic_reset(scmd);

	return ret;
@@ -2086,13 +2117,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;
@@ -2185,6 +2217,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);
@@ -2523,7 +2586,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;
@@ -2557,11 +2620,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,
@@ -2576,9 +2640,11 @@ 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_HOTPLUG,
				&instance->reg_set->reserved_0[0]);
				       &instance->reg_set->doorbell);
			} else
				writel(MFI_INIT_HOTPLUG,
					&instance->reg_set->inbound_doorbell);
@@ -2595,9 +2661,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);
@@ -2681,7 +2761,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)
@@ -2732,7 +2812,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
@@ -2819,14 +2899,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 */
@@ -2854,14 +2935,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.
@@ -2875,6 +2956,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),
@@ -3288,6 +3370,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;
	/*
@@ -3381,6 +3464,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;
@@ -3482,8 +3568,9 @@ 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);

	if (instance->reply_queue)
		pci_free_consistent(instance->pdev, reply_q_sz,
			    instance->reply_queue, instance->reply_queue_h);

@@ -3678,8 +3765,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;
}
@@ -3756,12 +3842,18 @@ static int megasas_io_attach(struct megasas_instance *instance)
	}

	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
	 */
@@ -3846,20 +3938,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),
	switch (instance->pdev->device) {
	case PCI_DEVICE_ID_LSI_FUSION:
	{
		struct fusion_context *fusion;

		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 =
			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");
			printk(KERN_DEBUG "megasas: Failed to allocate"
			       "memory for producer, consumer\n");
			goto fail_alloc_dma_buf;
		}

		*instance->producer = 0;
		*instance->consumer = 0;
		break;
	}

	megasas_poll_wait_aen = 0;
	instance->flag_ieee = 0;
	instance->ev = NULL;
@@ -3895,11 +4012,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;
@@ -3917,6 +4034,9 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
	instance->last_time = 0;
	instance->disableOnlineCtrlReset = 1;

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

	/*
@@ -4000,6 +4120,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,
@@ -4072,7 +4194,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);
@@ -4177,9 +4301,6 @@ megasas_resume(struct pci_dev *pdev)
	 * Initialize MFI Firmware
	 */

	*instance->producer = 0;
	*instance->consumer = 0;

	atomic_set(&instance->fw_outstanding, 0);

	/*
@@ -4188,10 +4309,28 @@ megasas_resume(struct pci_dev *pdev)
	if (megasas_transition_to_ready(instance))
		goto fail_ready_state;

	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,
	tasklet_init(&instance->isr_tasklet, instance->instancet->tasklet,
		     (unsigned long)instance);

	/* Now re-enable MSI-X */
@@ -4261,10 +4400,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);
@@ -4306,16 +4447,32 @@ static void __devexit megasas_detach_one(struct pci_dev *pdev)
	if (instance->msi_flag)
		pci_disable_msix(instance->pdev);

	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,
		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,
		pci_free_consistent(pdev, sizeof(u32),
				    instance->consumer,
				    instance->consumer_h);
		break;
	}

	scsi_host_put(host);

@@ -5079,6 +5236,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:
Loading