Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 27922b4260f65d317aabda37e42bbbff > files > 1816

kernel-2.6.18-238.el5.src.rpm

From: Jun'ichi \Nick\ Nomura <jnomura@redhat.com>
Subject: [RHEL5 PATCH] megaraid initialization fix for kdump
Date: Thu, 30 Nov 2006 11:11:01 -0500
Bugzilla: 208451
Message-Id: <456F0295.7070800@redhat.com>
Changelog: megaraid initialization fix for kdump


Hi,

BZ#208451 kdump kernel panics on MegaRAID driver
https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=208451

This patch came from LSI Logic, the maintainer of the upstream
driver. They are going to post the same fix to upstream.

The patch fixes a problem of megaraid driver during kdump.
Without this patch, megaraid driver either panics or fails to
initialize the adapter during the kdump's 2nd kernel boot
if there are pending commands or interrupts from other devices
sharing the same IRQ.

The patch changes the initialization code as the followings:
  - Send SYNC command first to the firmware on loading.
    The command clears the pending commands in the adapter
    and re-initialize its internal RAID structure.
  - Initialize mailbox_lock before request_irq() to prevent
    the interrupt handler from using uninitialized lock.

I have tested this patch with kernel-2.6.18-1.2747.el5
on both normal boot and kdump boot and both on i686 and x86_64.
Without the patch, under I/O stress, the kdump boot had failed
almost always. (10 failures out of 10 trials)
With this patch, I haven't seen kdump failure after 10 trials
each on 2 different systems with the same test case.
Also, I haven't seen any issues in repeated power cycle test.

Thanks,
-- 
Jun'ichi "Nick" Nomura / On-site engineer from NEC






 drivers/scsi/megaraid/megaraid_mbox.c |  128 ++++++++++++++++++++++++++++------
 drivers/scsi/megaraid/megaraid_mbox.h |    4 -
 2 files changed, 110 insertions(+), 22 deletions(-)

diff -uprN linux-2.6.orig/drivers/scsi/megaraid/megaraid_mbox.c linux-2.6.new/drivers/scsi/megaraid/megaraid_mbox.c
--- linux-2.6.orig/drivers/scsi/megaraid/megaraid_mbox.c	2006-11-28 10:34:39.000000000 -0800
+++ linux-2.6.new/drivers/scsi/megaraid/megaraid_mbox.c	2006-11-28 11:43:25.000000000 -0800
@@ -10,13 +10,13 @@
  *	   2 of the License, or (at your option) any later version.
  *
  * FILE		: megaraid_mbox.c
- * Version	: v2.20.4.9 (Jul 16 2006)
+ * Version	: v2.20.5.1 (Nov 16 2006)
  *
  * Authors:
- * 	Atul Mukker		<Atul.Mukker@lsil.com>
- * 	Sreenivas Bagalkote	<Sreenivas.Bagalkote@lsil.com>
- * 	Manoj Jose		<Manoj.Jose@lsil.com>
- * 	Seokmann Ju		<Seokmann.Ju@lsil.com>
+ * 	Atul Mukker		<Atul.Mukker@lsi.com>
+ * 	Sreenivas Bagalkote	<Sreenivas.Bagalkote@lsi.com>
+ * 	Manoj Jose		<Manoj.Jose@lsi.com>
+ * 	Seokmann Ju		<Seokmann.Ju@lsi.com>
  *
  * List of supported controllers
  *
@@ -107,6 +107,7 @@ static int megaraid_mbox_support_random_
 static int megaraid_mbox_get_max_sg(adapter_t *);
 static void megaraid_mbox_enum_raid_scsi(adapter_t *);
 static void megaraid_mbox_flush_cache(adapter_t *);
+static int megaraid_mbox_fire_sync_cmd(adapter_t *);
 
 static void megaraid_mbox_display_scb(adapter_t *, scb_t *);
 static void megaraid_mbox_setup_device_map(adapter_t *);
@@ -137,7 +138,7 @@ static int wait_till_fw_empty(adapter_t 
 
 
 
-MODULE_AUTHOR("sju@lsil.com");
+MODULE_AUTHOR("sumant.patro@lsi.com");
 MODULE_DESCRIPTION("LSI Logic MegaRAID Mailbox Driver");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(MEGARAID_VERSION);
@@ -763,6 +764,22 @@ megaraid_init_mbox(adapter_t *adapter)
 		goto out_release_regions;
 	}
 
+	// initialize the mutual exclusion lock for the mailbox
+	spin_lock_init(&raid_dev->mailbox_lock);
+
+	// allocate memory required for commands
+	if (megaraid_alloc_cmd_packets(adapter) != 0) {
+		goto out_iounmap;
+	}
+
+	/*
+	 * Issue SYNC cmd to flush the pending cmds in the adapter
+	 * and initialize its internal state  
+	 */
+	
+	if (megaraid_mbox_fire_sync_cmd(adapter))
+		con_log(CL_ANN, ("megaraid: sync cmd failed\n"));
+
 	//
 	// Setup the rest of the soft state using the library of FW routines
 	//
@@ -773,22 +790,13 @@ megaraid_init_mbox(adapter_t *adapter)
 
 		con_log(CL_ANN, (KERN_WARNING
 			"megaraid: Couldn't register IRQ %d!\n", adapter->irq));
+		goto out_alloc_cmds;
 
-		goto out_iounmap;
-	}
-
-
-	// initialize the mutual exclusion lock for the mailbox
-	spin_lock_init(&raid_dev->mailbox_lock);
-
-	// allocate memory required for commands
-	if (megaraid_alloc_cmd_packets(adapter) != 0) {
-		goto out_free_irq;
 	}
 
 	// Product info
 	if (megaraid_mbox_product_info(adapter) != 0) {
-		goto out_alloc_cmds;
+		goto out_free_irq;
 	}
 
 	// Do we support extended CDBs
@@ -859,7 +867,7 @@ megaraid_init_mbox(adapter_t *adapter)
 	 * accessed
 	 */
 	if (megaraid_sysfs_alloc_resources(adapter) != 0) {
-		goto out_alloc_cmds;
+		goto out_free_irq;
 	}
 
 	// Set the DMA mask to 64-bit. All supported controllers as capable of
@@ -904,10 +912,10 @@ megaraid_init_mbox(adapter_t *adapter)
 
 out_free_sysfs_res:
 	megaraid_sysfs_free_resources(adapter);
-out_alloc_cmds:
-	megaraid_free_cmd_packets(adapter);
 out_free_irq:
 	free_irq(adapter->irq, adapter);
+out_alloc_cmds:
+	megaraid_free_cmd_packets(adapter);
 out_iounmap:
 	iounmap(raid_dev->baseaddr);
 out_release_regions:
@@ -3364,6 +3372,86 @@ megaraid_mbox_flush_cache(adapter_t *ada
 
 
 /**
+ * megaraid_mbox_fire_sync_cmd - fire the sync cmd 
+ * @param adapter	: soft state for the controller
+ */
+static int 
+megaraid_mbox_fire_sync_cmd(adapter_t *adapter)
+{
+	mbox_t	*mbox;
+	uint8_t	raw_mbox[sizeof(mbox_t)];
+	mraid_device_t	*raid_dev = ADAP2RAIDDEV(adapter);
+	mbox64_t *mbox64;
+	uint8_t	status = 0;
+	int i;
+	uint32_t dword;
+
+	mbox = (mbox_t *)raw_mbox;
+
+	memset((caddr_t)raw_mbox, 0, sizeof(mbox_t));
+
+	raw_mbox[0] = 0xFF;
+
+	mbox64	= raid_dev->mbox64;
+	mbox	= raid_dev->mbox;
+
+	/*
+	 * Wait until mailbox is free
+	 */
+	if (megaraid_busywait_mbox(raid_dev) != 0) {
+		status = 1;
+		goto blocked_mailbox;
+	}
+
+	/*
+	 * Copy mailbox data into host structure
+	 */
+	memcpy((caddr_t)mbox, (caddr_t)raw_mbox, 16);
+	mbox->cmdid		= 0xFE;
+	mbox->busy		= 1;
+	mbox->poll		= 0;
+	mbox->ack		= 0;
+	mbox->numstatus		= 0;
+	mbox->status		= 0;
+
+	wmb();
+	WRINDOOR(raid_dev, raid_dev->mbox_dma | 0x1);
+
+	// wait for maximum 1 min for status to post.
+	// If the Firmware SUPPORTS the ABOVE COMMAND,
+	// mbox->cmd will be set to 0
+	// else
+	// the firmware will reject the command with
+	// mbox->numstatus set to 1
+
+	i = 0;
+	status = 0;
+	while (!mbox->numstatus && mbox->cmd == 0xFF) {
+		rmb();
+		msleep(1);
+		i++;
+		if (i > 1000 * 60) {
+			status = 1;
+			break;
+		}	
+	}
+	if (mbox->numstatus == 1)
+		status = 1; /*cmd not supported*/
+	/*
+	 * Check for interrupt line 
+	 */
+	dword = RDOUTDOOR(raid_dev);
+	WROUTDOOR(raid_dev, dword);
+	WRINDOOR(raid_dev,2); 
+
+	return status;
+
+blocked_mailbox:	
+	con_log(CL_ANN, (KERN_WARNING "megaraid: blocked mailbox\n"));
+	return status;
+}
+
+/**
  * megaraid_mbox_display_scb - display SCB information, mostly debug purposes
  * @param adapter	: controllers' soft state
  * @param scb		: SCB to be displayed
diff -uprN linux-2.6.orig/drivers/scsi/megaraid/megaraid_mbox.h linux-2.6.new/drivers/scsi/megaraid/megaraid_mbox.h
--- linux-2.6.orig/drivers/scsi/megaraid/megaraid_mbox.h	2006-11-28 10:34:39.000000000 -0800
+++ linux-2.6.new/drivers/scsi/megaraid/megaraid_mbox.h	2006-11-28 11:15:30.000000000 -0800
@@ -21,8 +21,8 @@
 #include "megaraid_ioctl.h"
 
 
-#define MEGARAID_VERSION	"2.20.4.9"
-#define MEGARAID_EXT_VERSION	"(Release Date: Sun Jul 16 12:27:22 EST 2006)"
+#define MEGARAID_VERSION	"2.20.5.1"
+#define MEGARAID_EXT_VERSION	"(Release Date: Thu Nov 16 15:32:35 EST 2006)"
 
 
 /*