Sophie

Sophie

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

kernel-2.6.18-128.1.10.el5.src.rpm

From: Tomas Henzl <thenzl@redhat.com>
Date: Thu, 21 Aug 2008 18:18:56 +0200
Subject: [scsi] megaraid_sas: update to version 4.01-rh1
Message-id: 48AD9570.5060504@redhat.com
O-Subject: [RHEL5.3 PATCH] bz442913 Update megaraid_sas to version 4.01-rh1
Bugzilla: 442913
RH-Acked-by: Pete Zaitcev <zaitcev@redhat.com>
RH-Acked-by: David Milburn <dmilburn@redhat.com>

Greetings,

This patch resolves the  bz#442913.
It adds support for new hardware "GEN2" and some bug fixes.

Comment from LSI:
* MFI_POLL_TIMEOUT_SECS is now 60 seconds (increased from 10 seconds). This
was done to accommodate the firmware, which could take a maximum of 60 seconds
to respond to the INIT command.
* A bug that caused continuous chip resets and command timeouts due to frame
count calculation is now fixed. With this update, the driver now sends the
correct frame count to the firmware upon request.
* Add the new controller (0078, 0079) support to the driver. Those controllers
are LSI's next generatation(gen2) SAS controllers.
* Add shutdown DCMD cmd to the shutdown routine to make FW shutdown proper.
* Unexpected interrupt occurs in HWR Linux driver, add the dumy readl pci
flush will fix this issue.

The patch can be found on James Bottomley git
(git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-rc-fixes-2.6).
I tested it on a x86_64 box, but a significant part of the code is support for the new gen2 hardware
to which I do not have access.

Tomas

diff --git a/Documentation/scsi/ChangeLog.megaraid_sas b/Documentation/scsi/ChangeLog.megaraid_sas
index 2a66690..52a27a7 100644
--- a/Documentation/scsi/ChangeLog.megaraid_sas
+++ b/Documentation/scsi/ChangeLog.megaraid_sas
@@ -1,3 +1,53 @@
+1 Release Date    : Thur.July. 24 11:41:51 PST 2008 -
+			(emaild-id:megaraidlinux@lsi.com)
+			Sumant Patro
+			Bo Yang 
+
+2 Current Version : 00.00.04.01-RH1
+3 Older Version   : 00.00.03.22
+
+1. Add the new controller (0078, 0079) support to the driver
+	Those controllers are LSI's next generatation(gen2) SAS controllers. 
+
+1 Release Date    : Mon.June. 23 10:12:45 PST 2008 -
+			(emaild-id:megaraidlinux@lsi.com)
+			Sumant Patro
+			Bo Yang 
+
+2 Current Version : 00.00.03.22
+3 Older Version   : 00.00.03.20
+
+1. Add shutdown DCMD cmd to the shutdown routine to make FW shutdown proper.
+2. Unexpected interrupt occurs in HWR Linux driver, add the dumy readl pci flush will fix this issue.
+
+1 Release Date    : Mon. May 15 11:02:31 PDT 2008 -
+			(emaild-id:megaraidlinux@lsi.com)
+			Sumant Patro
+			Bo Yang
+
+2 Current Version : 00.00.03.20-RH1
+3 Older Version   : 00.00.03.16
+
+1. Fixed the driver frame count.
+	When Driver sent wrong frame count to firmware.  As this
+	particular command is sent to drive, FW is seeing continuous
+	chip resets and so the command will timeout.
+
+2. Add the new controller(1078DE) support to the driver
+	and Increase the max_wait to 60 from 10 in the controller
+	operational status.  With this max_wait increase, driver will
+	make sure the FW will 	finish the pending cmd for KDUMP case.
+
+1 Release Date    : Thur. Nov. 07 16:30:43 PST 2007 -
+			(emaild-id:megaraidlinux@lsi.com)
+			Sumant Patro
+			Bo Yang
+
+2 Current Version : 00.00.03.16
+3 Older Version   : 00.00.03.15
+
+1. Increased MFI_POLL_TIMEOUT_SECS to 60 seconds from 10. FW may take
+	a max of 60 seconds to respond to the INIT cmd.
 
 1 Release Date    : Wed. Nov. 21 10:29:45 PST 2007 -
 			(emaild-id:megaraidlinux@lsi.com)
diff --git a/drivers/scsi/megaraid/megaraid_sas.c b/drivers/scsi/megaraid/megaraid_sas.c
index 8738357..8d1fd9e 100644
--- a/drivers/scsi/megaraid/megaraid_sas.c
+++ b/drivers/scsi/megaraid/megaraid_sas.c
@@ -10,7 +10,7 @@
  *	   2 of the License, or (at your option) any later version.
  *
  * FILE		: megaraid_sas.c
- * Version	: v00.00.03.15-RH1
+ * Version	: v00.00.04.01-RH1
  *
  * Authors:
  *	(email-id : megaraidlinux@lsi.com)
@@ -47,11 +47,11 @@
 #include "megaraid_sas.h"
 
 /*
- * Module parameters
+ * Modules parameters
  */
 
 /*
- * poll_mode_io:1- schedule command completion from q cmd
+ * 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);
@@ -72,6 +72,12 @@ static struct pci_device_id megasas_pci_table[] = {
 	/* xscale IOP */
 	{PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1078R)},
 	/* ppc IOP */
+	{PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_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_SAS1078DE)},
+	/* ppc IOP */
 	{PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_VERDE_ZCR)},
 	/* xscale IOP, vega */
 	{PCI_DEVICE(PCI_VENDOR_ID_DELL, PCI_DEVICE_ID_DELL_PERC5)},
@@ -198,6 +204,9 @@ megasas_clear_intr_xscale(struct megasas_register_set __iomem * regs)
 	 */
 	writel(status, &regs->outbound_intr_status);
 
+	/* Dummy readl to force pci flush */
+	readl(&regs->outbound_intr_status);
+
 	return 0;
 }
 
@@ -249,7 +258,7 @@ megasas_enable_intr_ppc(struct megasas_register_set __iomem * regs)
 }
 
 /**
- * megasas_disable_intr_ppc -	Disable interrupt
+ * megasas_disable_intr_ppc -	Disables interrupt
  * @regs:			MFI register set
  */
 static inline void
@@ -293,6 +302,9 @@ megasas_clear_intr_ppc(struct megasas_register_set __iomem * regs)
 	 */
 	writel(status, &regs->outbound_doorbell_clear);
 
+	/* Dummy readl to force pci flush */
+	readl(&regs->outbound_doorbell_clear);
+
 	return 0;
 }
 /**
@@ -323,6 +335,106 @@ static struct megasas_instance_template megasas_instance_template_ppc = {
 */
 
 /**
+*	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;
+	/*
+	 * Check if it is our interrupt
+	 */
+	status = readl(&regs->outbound_intr_status);
+
+	if (!(status & MFI_GEN2_ENABLE_INTERRUPT_MASK)) {
+		return 1;
+	}
+
+	/*
+	 * Clear the interrupt by writing back the same value
+	 */
+	writel(status, &regs->outbound_doorbell_clear);
+
+	/* Dummy readl to force pci flush */
+	readl(&regs->outbound_intr_status);
+
+	return 0;
+}
+/**
+ * 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(dma_addr_t frame_phys_addr, u32 frame_count,
+			struct megasas_register_set __iomem *regs)
+{
+	writel((frame_phys_addr | (frame_count<<1))|1,
+			&(regs)->inbound_queue_port);
+}
+
+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,
+};
+
+/**
+ *      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 
@@ -531,11 +643,11 @@ megasas_make_sgl64(struct megasas_instance *instance, struct scsi_cmnd *scp,
  /**
  * megasas_get_frame_count - Computes the number of frames
  * @sge_count		: number of sg elements
+ * @frame_type		: type of frame- io or pthru frame
  *
  * Returns the number of frames required for numnber of sge's (sge_count)
  */
-
-static u32 megasas_get_frame_count(u8 sge_count)
+static u32 megasas_get_frame_count(u8 sge_count, u8 frame_type)
 {
 	int num_cnt;
 	int sge_bytes;
@@ -546,13 +658,22 @@ static u32 megasas_get_frame_count(u8 sge_count)
 	    sizeof(struct megasas_sge32);
 
 	/*
-	* Main frame can contain 2 SGEs for 64-bit SGLs and
-	* 3 SGEs for 32-bit SGLs
-	*/
-	if (IS_DMA64)
-		num_cnt = sge_count - 2;
-	else
-		num_cnt = sge_count - 3;
+	 * 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 (IS_DMA64)
+			num_cnt = sge_count - 1;
+		else
+			num_cnt = sge_count - 2;
+	} 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;
@@ -634,7 +755,8 @@ 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(pthru->sge_count,
+							PTHRU_FRAME);
 
 	return cmd->frame_count;
 }
@@ -751,7 +873,7 @@ 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);
+	cmd->frame_count = megasas_get_frame_count(ldio->sge_count, IO_FRAME);
 
 	return cmd->frame_count;
 }
@@ -958,7 +1080,7 @@ static void megasas_complete_cmd_dpc(unsigned long instance_addr)
 	u32 context;
 	struct megasas_cmd *cmd;
 	struct megasas_instance *instance =
-			(struct megasas_instance *)instance_addr;
+				(struct megasas_instance *)instance_addr;
 	unsigned long flags;
 
 	/* If we have already declared adapter dead, donot complete cmds */
@@ -1543,7 +1665,7 @@ megasas_transition_to_ready(struct megasas_instance* instance)
 			instance->instancet->disable_intr(instance->reg_set);
 			writel(MFI_RESET_FLAGS, &instance->reg_set->inbound_doorbell);
 
-			max_wait = 10;
+			max_wait = 60;
 			cur_state = MFI_STATE_OPERATIONAL;
 			break;
 
@@ -2050,7 +2172,12 @@ static int megasas_init_mfi(struct megasas_instance *instance)
 	/*
 	 * Map the message registers
 	 */
-	instance->base_addr = pci_resource_start(instance->pdev, 0);
+	if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS1078GEN2) ||
+		(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");
@@ -2068,9 +2195,14 @@ static int megasas_init_mfi(struct megasas_instance *instance)
 
 	switch(instance->pdev->device)
 	{
-		case PCI_DEVICE_ID_LSI_SAS1078R:	
+		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_SAS1064R:
 		case PCI_DEVICE_ID_DELL_PERC5:
 		default:
@@ -2925,6 +3057,8 @@ static void megasas_shutdown(struct pci_dev *pdev)
 {
 	struct megasas_instance *instance = pci_get_drvdata(pdev);
 	megasas_flush_cache(instance);
+	megasas_shutdown_controller(instance, MR_DCMD_CTRL_SHUTDOWN);
+
 }
 
 /**
diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h
index b26f430..4f4ddf1 100644
--- a/drivers/scsi/megaraid/megaraid_sas.h
+++ b/drivers/scsi/megaraid/megaraid_sas.h
@@ -18,14 +18,17 @@
 /*
  * MegaRAID SAS Driver meta data
  */
-#define MEGASAS_VERSION				"00.00.03.15-RH1"
-#define MEGASAS_RELDATE				"Nov 21, 2007"
-#define MEGASAS_EXT_VERSION			"Wed Nov. 21 10:29:45 PST 2007"
+#define MEGASAS_VERSION				"00.00.04.01-RH1"
+#define MEGASAS_RELDATE				"July 10, 2008"
+#define MEGASAS_EXT_VERSION			"Thu July 10 09:41:51 PST 2008"
 
 /*
  * Device IDs
  */
 #define	PCI_DEVICE_ID_LSI_SAS1078R		0x0060
+#define	PCI_DEVICE_ID_LSI_SAS1078DE		0x007C
+#define	PCI_DEVICE_ID_LSI_SAS1078GEN2		0x0078
+#define	PCI_DEVICE_ID_LSI_SAS0079GEN2		0x0079
 #define	PCI_DEVICE_ID_LSI_VERDE_ZCR		0x0413
 
 /*
@@ -542,6 +545,9 @@ struct megasas_ctrl_info {
 
 #define MEGASAS_DBG_LVL				1
 #define MEGASAS_FW_BUSY				1
+/* Frame Type */
+#define IO_FRAME					0
+#define PTHRU_FRAME					1
 
 /*
  * When SCSI mid-layer calls driver's reset routine, driver waits for
@@ -576,6 +582,8 @@ struct megasas_ctrl_info {
 #define MEGASAS_COMPLETION_TIMER_INTERVAL	(HZ/10)
 
 #define MFI_REPLY_1078_MESSAGE_INTERRUPT	0x80000000
+#define MFI_REPLY_GEN2_MESSAGE_INTERRUPT       0x00000001
+#define MFI_GEN2_ENABLE_INTERRUPT_MASK         (0x00000001 | 0x00000004)
 
 /*
 * register set for both 1068 and 1078 controllers