Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > media > main-src > by-pkgid > d0a35cd31c1125e2132804d68547073d > files > 3559

kernel-2.6.18-194.26.1.el5.src.rpm

From: Tomas Henzl <thenzl@redhat.com>
Date: Tue, 1 Dec 2009 14:38:01 -0500
Subject: [scsi] megaraid: upgrade to version 4.17-RH1
Message-id: <20091201143701.7257.9715.sendpatchset@localhost.localdomain>
Patchwork-id: 21566
O-Subject: [RHEL5.5 2/2] bz518243 megaraid: upgrade to version 4.17-RH1
Bugzilla: 518243

This is for bz#518243
(it looks like it will also help with 541838
 - debug kernel can not bootup on Boxboro-EX machines)

This patch comes from Bo Yang (LSI):
"Fixed the multiapplication can't get AEN (reset the aen flag in ioctl
routine).
Zero the pad_0 for DCMD cmd to fix the fw missup the context value.
Add the three mins wait during the fw initialize and bootup.
Fixed the hibernation hang issue.
Driver will auto update the device add/delete."

Part of this patch is posted to upstrem (version 4.12)
another  part is still not. LSI promised yesterday they will post everything
by the end of week.

Signed-off-by: Don Zickus <dzickus@redhat.com>

diff --git a/drivers/scsi/megaraid/megaraid_sas.c b/drivers/scsi/megaraid/megaraid_sas.c
index 3b42c08..9d283d9 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.04.08-RH2
+ * Version	: v00.00.04.17-RH1
  *
  * Authors:
  *	(email-id : megaraidlinux@lsi.com)
@@ -40,6 +40,7 @@
 #include <linux/blkdev.h>
 #include <linux/mutex.h>
 #include <linux/poll.h>
+#include <linux/smp_lock.h>
 
 #include <scsi/scsi.h>
 #include <scsi/scsi_cmnd.h>
@@ -96,6 +97,8 @@ 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 DEFINE_MUTEX(megasas_poll_wait_mutex);
+
 
 static int megasas_poll_wait_aen;
 static DECLARE_WAIT_QUEUE_HEAD (megasas_poll_wait);
@@ -103,6 +106,8 @@ extern void
 poll_wait(struct file *filp, wait_queue_head_t *q, poll_table *token);
 
 static u32 support_poll_for_event;
+spinlock_t poll_aen_lock;
+
 static u32 megasas_dbg_lvl;
 
 static void
@@ -903,6 +908,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 = scp->request_bufflen;
 
@@ -933,6 +939,10 @@ megasas_build_dcdb(struct megasas_instance *instance, struct scsi_cmnd *scp,
 	} else
 		pthru->sge_count = megasas_make_sgl32(instance, scp,
 						      &pthru->sgl);
+       if (pthru->sge_count > instance->max_num_sge) {
+        	printk("megasas: build_dcdb error, two many SGE\n");
+	        return 0;
+	}
 
 	/*
 	 * Sense info specific
@@ -1061,6 +1071,11 @@ 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("megasas: build_ld_io  error, sge_count = %x\n", ldio->sge_count);
+	        return 0;
+	}
+
 	/*
 	 * Sense info specific
 	 */
@@ -1593,11 +1608,15 @@ static void megasas_aen_polling(void *arg);
 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);
 	}
@@ -1606,7 +1625,7 @@ megasas_service_aen(struct megasas_instance *instance, struct megasas_cmd *cmd)
 
 	instance->aen_cmd = NULL;
 	megasas_return_cmd(instance, cmd);
-	if ((!cmd->abort_aen) && (instance->unload == 0 )) {
+	if (instance->unload == 0) {
 		struct megasas_aen_event *ev;
 		ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
 		if (!ev) {
@@ -1743,6 +1762,7 @@ static void
 megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd,
 		     u8 alt_status)
 {
+	unsigned long flags;
 	int exception = 0;
 	struct megasas_header *hdr = &cmd->frame->hdr;
 
@@ -1834,6 +1854,12 @@ megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd,
 	case MFI_CMD_SMP:
 	case MFI_CMD_STP:
 	case MFI_CMD_DCMD:
+		if (cmd->frame->dcmd.opcode == MR_DCMD_CTRL_EVENT_GET_INFO || 
+			cmd->frame->dcmd.opcode == MR_DCMD_CTRL_EVENT_GET) {
+			spin_lock_irqsave(&poll_aen_lock, flags);
+			megasas_poll_wait_aen = 0;
+			spin_unlock_irqrestore(&poll_aen_lock, flags);
+		}
 
 		/*
 		 * See if got an event notification
@@ -1911,6 +1937,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;
 
@@ -1919,6 +1946,8 @@ megasas_transition_to_ready(struct megasas_instance* instance)
  		       " state\n");
 
 	while (fw_state != MFI_STATE_READY) {
+	
+		abs_state = instance->instancet->read_fw_status_reg(instance->reg_set);
 
 		switch (fw_state) {
 
@@ -1941,7 +1970,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;
 
@@ -1955,7 +1984,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;
 
@@ -1971,7 +2000,7 @@ megasas_transition_to_ready(struct megasas_instance* instance)
 			} else 
 				writel(MFI_RESET_FLAGS, &instance->reg_set->inbound_doorbell);
 
-			max_wait = 60;
+			max_wait = MEGASAS_RESET_WAIT_TIME;
 			cur_state = MFI_STATE_OPERATIONAL;
 			break;
 
@@ -1979,32 +2008,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;
 
@@ -2020,8 +2049,9 @@ 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;
@@ -2030,7 +2060,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;
@@ -2372,6 +2402,87 @@ 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 (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 for megasas_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
@@ -2418,6 +2529,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;
@@ -2674,6 +2786,9 @@ static int megasas_init_mfi(struct megasas_instance *instance)
 	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);
 
 	/*
@@ -2797,6 +2912,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;
@@ -2911,6 +3027,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;
 	dcmd->data_xfer_len = sizeof(struct megasas_evt_detail);
 	dcmd->opcode = MR_DCMD_CTRL_EVENT_WAIT;
 	dcmd->mbox.w[0] = seq_num;
@@ -2985,11 +3102,7 @@ static int megasas_io_attach(struct megasas_instance *instance)
 	} else 
 		host->can_queue = instance->max_fw_cmds - MEGASAS_INT_CMDS;
 	host->this_id = instance->init_id;
-	if(instance->flag_ieee) {
-		host->sg_tablesize = 28;
-	} else {
-		host->sg_tablesize = instance->max_num_sge;
-	}
+	host->sg_tablesize = instance->max_num_sge;
 	host->max_sectors = instance->max_sectors_per_req;
 	host->cmd_per_lun = MEGASAS_DEFAULT_CMD_PER_LUN;
 	host->max_channel = MEGASAS_MAX_CHANNELS - 1;
@@ -3123,6 +3236,7 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
 	spin_lock_init(&instance->completion_lock);
 
 	sema_init(&instance->aen_mutex, 1);
+	spin_lock_init(&poll_aen_lock);
 
 	/*
 	 * Initialize PCI related and misc parameters
@@ -3250,6 +3364,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;
@@ -3289,6 +3404,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;
 
@@ -3299,6 +3415,7 @@ static void megasas_shutdown_controller(struct megasas_instance *instance,
 	return;
 }
 
+#ifdef CONFIG_PM
 /**
  * megasas_suspend -	driver suspend entry point
  * @pdev:		PCI device structure
@@ -3433,11 +3550,16 @@ fail_ready_state:
 	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 megasas_detach_one(struct pci_dev *pdev)
+static void __devexit megasas_detach_one(struct pci_dev *pdev)
 {
 	int i;
 	struct Scsi_Host *host;
@@ -3502,6 +3624,7 @@ static void megasas_detach_one(struct pci_dev *pdev)
 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);
 
@@ -3553,13 +3676,17 @@ static int megasas_mgmt_fasync(int fd, struct file *filep, int mode)
  * */
 static unsigned int megasas_mgmt_poll(struct file *file, poll_table *wait)
 {
-	unsigned int mask = 0;
-	poll_wait(file, &megasas_poll_wait, 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);
 
-	if (megasas_poll_wait_aen) {
-		mask |=   (POLLIN | POLLRDNORM);
-	}
-	return mask;
+   	return mask;
 }
 
 /**
@@ -3579,7 +3706,7 @@ megasas_mgmt_fw_ioctl(struct megasas_instance *instance,
 	int error = 0, i;
 	void *sense = NULL;
 	dma_addr_t sense_handle;
-	u32 *sense_ptr;
+	unsigned long *sense_ptr;
 
 	memset(kbuff_arr, 0, sizeof(kbuff_arr));
 
@@ -3657,7 +3784,7 @@ megasas_mgmt_fw_ioctl(struct megasas_instance *instance,
 		}
 
 		sense_ptr =
-		    (u32 *) ((unsigned long)cmd->frame + ioc->sense_off);
+		    (unsigned long *) ((unsigned long)cmd->frame + ioc->sense_off);
 		*sense_ptr = sense_handle;
 	}
 
@@ -3688,11 +3815,13 @@ megasas_mgmt_fw_ioctl(struct megasas_instance *instance,
 		 * sense_ptr points to the location that has the user
 		 * sense buffer address
 		 */
-		sense_ptr = (u32 *) ((unsigned long)ioc->frame.raw +
-				     ioc->sense_off);
+		sense_ptr = (unsigned long *) ((unsigned long)ioc->frame.raw +
+				ioc->sense_off);
 
 		if (copy_to_user((void __user *)((unsigned long)(*sense_ptr)),
 				 sense, ioc->sense_len)) {
+			printk(KERN_ERR "megasas: Failed to copy out to user "
+					"sense data\n");
 			error = -EFAULT;
 			goto out;
 		}
@@ -4016,13 +4145,18 @@ static DRIVER_ATTR(poll_mode_io, S_IRUGO|S_IWUSR,
 			megasas_sysfs_show_poll_mode_io,
 			megasas_sysfs_set_poll_mode_io);
 
-static void
+static void 
 megasas_aen_polling(void *arg)
 {
+	struct 	Scsi_Host *host;
+	struct 	scsi_device *sdev1;
+	u16	pd_index = 0;
+	u16	ld_index = 0;
+
 	struct megasas_aen_event *ev = arg;
 	struct megasas_instance *instance = ev->instance;
 	union megasas_evt_class_locale class_locale;
-	int doscan = 0;
+	int 	i, j, doscan = 0;
 	u32 seq_num;
 	int error;
 
@@ -4031,16 +4165,104 @@ megasas_aen_polling(void *arg)
 		kfree(ev);
 		return;
 	}
+	host = instance->host;
 
 	if (instance->evt_detail) {
 
 		switch (instance->evt_detail->code) {
+		printk("EVENT received: event_code=%x!\n", instance->evt_detail->code);
 
 		case MR_EVT_PD_INSERTED:
+			if(megasas_get_pd_list(instance) == 0) {
+			
+			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_CFG_CLEARED:
+		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;
@@ -4052,40 +4274,76 @@ megasas_aen_polling(void *arg)
 		return;
 	}
 
-	if (doscan) {
+	if (doscan) { /*keep this incase we need to use*/
 		printk(KERN_INFO "%s[%d]: scanning ...\n",
 			__FUNCTION__, instance->host->host_no);
 		megasas_get_pd_list(instance);
-		scsi_scan_host(instance->host);
-		msleep(1000);
-	}
+		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);
+					}
+				}
+			}
+		}
 
-	kfree(ev);
+		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);
+					}
+				} else {
+					if (sdev1) {
+						scsi_remove_device(sdev1);
+						scsi_device_put(sdev1);
+					}
+				}
+			}
+		}		
 
-	seq_num = instance->evt_detail->seq_num + 1;
+	}
 
-	/**
-	* Register AEN with FW for latest sequence number plus 1
-	**/
+	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;
 
-       if ( instance->aen_cmd != NULL ) {
-               return ; 
-       }
-
+	if ( instance->aen_cmd != NULL ) {
+		kfree(ev);
+		return ; 
+	}
 	down(&instance->aen_mutex);
-
 	error = megasas_register_aen(instance, seq_num,
-				class_locale.word);
-
+				    class_locale.word);
 	up(&instance->aen_mutex);
 
-	if (error)
+	if(error)
 		printk(KERN_ERR "%s[%d]: register aen failed error %x\n",
-			 __FUNCTION__, instance->host->host_no, error);
+			__FUNCTION__, instance->host->host_no, error);
+	kfree(ev);
+
 }
 
 /**
@@ -4101,7 +4359,7 @@ static int __init megasas_init(void)
 	printk(KERN_INFO "megasas: %s %s\n", MEGASAS_VERSION,
 	       MEGASAS_EXT_VERSION);
 
-	support_poll_for_event = 1;
+	support_poll_for_event = 2;
 
 
 	memset(&megasas_mgmt_info, 0, sizeof(megasas_mgmt_info));
diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h
index 69b7471..966a1cd 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.08-RH2"
-#define MEGASAS_RELDATE				"May 05, 2009"
-#define MEGASAS_EXT_VERSION			"Tues. May 5, 11:41:51 PST 2009"
+#define MEGASAS_VERSION				"00.00.04.17-RH1"
+#define MEGASAS_RELDATE				"Nov. 25, 2009"
+#define MEGASAS_EXT_VERSION			"Wed. Nov. 25, 11:41:51 PST 2009"
 
 /*
  * Device IDs
@@ -117,6 +117,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
@@ -146,6 +147,8 @@
 #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
+
 
 /*
  * MFI command completion codes
@@ -345,6 +348,33 @@ struct MR_PD_ADDRESS {
     u64     sasAddr[2];
 } __attribute__ ((packed));
 
+ /*
+ * defines the logical drive reference structure
+ */
+typedef union  _MR_LD_REF {        // LD reference structure
+    struct {
+        u8      targetId;           // LD target id (0 to MAX_TARGET_ID)
+        u8      reserved;           // reserved to make in line with MR_PD_REF
+        u16     seqNum;             // Sequence Number
+    };
+    u32     ref;                    // shorthand reference to full 32-bits
+} MR_LD_REF;                        // 4 bytes
+
+
+/*
+ * defines the logical drive list structure
+ */
+struct MR_LD_LIST {
+    u32     ldCount;                // number of LDs
+    u32     reserved;               // pad to 8-byte boundary
+    struct {
+        MR_LD_REF   ref;            // LD reference
+        u8          state;          // current LD state (MR_LD_STATE)
+        u8          reserved[3];    // pad to 8-byte boundary
+        u64         size;           // LD size
+    } ldList[MAX_LOGICAL_DRIVES];
+} __attribute__ ((packed));
+
 /*
  * defines the physical drive list structure
  */
@@ -651,6 +681,8 @@ struct megasas_ctrl_info {
 #define MEGASAS_MAX_PD				(MEGASAS_MAX_PD_CHANNELS * \
 							MEGASAS_MAX_DEV_PER_CHANNEL)
 
+#define MEGASAS_MAX_LD_IDS			(MEGASAS_MAX_LD_CHANNELS * \
+							MEGASAS_MAX_DEV_PER_CHANNEL)
 #define MEGASAS_DBG_LVL				1
 #define MEGASAS_FW_BUSY				1
 /* Frame Type */
@@ -1236,6 +1268,7 @@ struct megasas_instance {
 
 	struct megasas_instance_template *instancet;
 	struct tasklet_struct isr_tasklet;
+	u8     ld_ids[MEGASAS_MAX_LD_IDS];
 
 	u8 flag;
 	u8 unload;