[Patch 1/6] megaraid_sas: FW transition and q size changes

From: Sumant Patro
Date: Tue Oct 03 2006 - 20:30:06 EST


Resubmitting with one addition (item f mentioned below)

This patch has the following enhancements :
a. handles new transition states of FW to support controller hotplug.
b. It reduces by 1 the maximum cmds that the driver may send to FW.
c. Sends "Stop Processing" cmd to FW before returning failure from reset routine
d. Adds print in megasas_transition routine
e. Sends "RESET" flag to FW to do a soft reset of controller
to move from Operational to Ready state.
f. Sending correct pointer (cmd->sense) to pci_pool_free

This patch has been generated on latest scsi-misc git.

Signed-off-by: Sumant Patro <Sumant.Patro@xxxxxxxx>

diff -uprN linux2.6-orig/drivers/scsi/megaraid/megaraid_sas.c linux2.6/drivers/scsi/megaraid/megaraid_sas.c
--- linux2.6-orig/drivers/scsi/megaraid/megaraid_sas.c 2006-10-02 10:15:31.000000000 -0700
+++ linux2.6/drivers/scsi/megaraid/megaraid_sas.c 2006-10-02 10:16:40.000000000 -0700
@@ -832,6 +832,12 @@ static int megasas_wait_for_outstanding(
}

if (atomic_read(&instance->fw_outstanding)) {
+ /*
+ * Send signal to FW to stop processing any pending cmds.
+ * The controller will be taken offline by the OS now.
+ */
+ writel(MFI_STOP_ADP,
+ &instance->reg_set->inbound_doorbell);
instance->hw_crit_error = 1;
return FAILED;
}
@@ -1229,10 +1235,12 @@ megasas_transition_to_ready(struct megas

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

- printk(KERN_INFO "megasas: Waiting for FW to come to ready"
- " state\n");
switch (fw_state) {

case MFI_STATE_FAULT:
@@ -1244,19 +1252,27 @@ megasas_transition_to_ready(struct megas
/*
* Set the CLR bit in inbound doorbell
*/
- writel(MFI_INIT_CLEAR_HANDSHAKE,
+ 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:
+ 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 2 secs
+ * Bring it to READY state; assuming max wait 10 secs
*/
megasas_disable_intr(instance);
- writel(MFI_INIT_READY, &instance->reg_set->inbound_doorbell);
+ writel(MFI_RESET_FLAGS, &instance->reg_set->inbound_doorbell);

max_wait = 10;
cur_state = MFI_STATE_OPERATIONAL;
@@ -1323,6 +1339,7 @@ megasas_transition_to_ready(struct megas
return -ENODEV;
}
};
+ printk(KERN_INFO "megasas: FW now in Ready state\n");

return 0;
}
@@ -1352,7 +1369,7 @@ static void megasas_teardown_frame_pool(
cmd->frame_phys_addr);

if (cmd->sense)
- pci_pool_free(instance->sense_dma_pool, cmd->frame,
+ pci_pool_free(instance->sense_dma_pool, cmd->sense,
cmd->sense_phys_addr);
}

@@ -1690,6 +1707,12 @@ static int megasas_init_mfi(struct megas
* 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;
/*
diff -uprN linux2.6-orig/drivers/scsi/megaraid/megaraid_sas.h linux2.6/drivers/scsi/megaraid/megaraid_sas.h
--- linux2.6-orig/drivers/scsi/megaraid/megaraid_sas.h 2006-10-02 10:15:31.000000000 -0700
+++ linux2.6/drivers/scsi/megaraid/megaraid_sas.h 2006-10-02 10:16:13.000000000 -0700
@@ -50,6 +50,7 @@
#define MFI_STATE_WAIT_HANDSHAKE 0x60000000
#define MFI_STATE_FW_INIT_2 0x70000000
#define MFI_STATE_DEVICE_SCAN 0x80000000
+#define MFI_STATE_BOOT_MESSAGE_PENDING 0x90000000
#define MFI_STATE_FLUSH_CACHE 0xA0000000
#define MFI_STATE_READY 0xB0000000
#define MFI_STATE_OPERATIONAL 0xC0000000
@@ -64,12 +65,18 @@
* READY : Move from OPERATIONAL to READY state; discard queue info
* MFIMODE : Discard (possible) low MFA posted in 64-bit mode (??)
* CLR_HANDSHAKE: FW is waiting for HANDSHAKE from BIOS or Driver
+ * HOTPLUG : Resume from Hotplug
+ * MFI_STOP_ADP : Send signal to FW to stop processing
*/
-#define MFI_INIT_ABORT 0x00000000
+#define MFI_INIT_ABORT 0x00000001
#define MFI_INIT_READY 0x00000002
#define MFI_INIT_MFIMODE 0x00000004
#define MFI_INIT_CLEAR_HANDSHAKE 0x00000008
-#define MFI_RESET_FLAGS MFI_INIT_READY|MFI_INIT_MFIMODE
+#define MFI_INIT_HOTPLUG 0x00000010
+#define MFI_STOP_ADP 0x00000020
+#define MFI_RESET_FLAGS MFI_INIT_READY| \
+ MFI_INIT_MFIMODE| \
+ MFI_INIT_ABORT

/**
* MFI frame flags



diff -uprN linux2.6-orig/drivers/scsi/megaraid/megaraid_sas.c linux2.6/drivers/scsi/megaraid/megaraid_sas.c
--- linux2.6-orig/drivers/scsi/megaraid/megaraid_sas.c 2006-10-02 10:15:31.000000000 -0700
+++ linux2.6/drivers/scsi/megaraid/megaraid_sas.c 2006-10-02 10:16:40.000000000 -0700
@@ -832,6 +832,12 @@ static int megasas_wait_for_outstanding(
}

if (atomic_read(&instance->fw_outstanding)) {
+ /*
+ * Send signal to FW to stop processing any pending cmds.
+ * The controller will be taken offline by the OS now.
+ */
+ writel(MFI_STOP_ADP,
+ &instance->reg_set->inbound_doorbell);
instance->hw_crit_error = 1;
return FAILED;
}
@@ -1229,10 +1235,12 @@ megasas_transition_to_ready(struct megas

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

- printk(KERN_INFO "megasas: Waiting for FW to come to ready"
- " state\n");
switch (fw_state) {

case MFI_STATE_FAULT:
@@ -1244,19 +1252,27 @@ megasas_transition_to_ready(struct megas
/*
* Set the CLR bit in inbound doorbell
*/
- writel(MFI_INIT_CLEAR_HANDSHAKE,
+ 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:
+ 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 2 secs
+ * Bring it to READY state; assuming max wait 10 secs
*/
megasas_disable_intr(instance);
- writel(MFI_INIT_READY, &instance->reg_set->inbound_doorbell);
+ writel(MFI_RESET_FLAGS, &instance->reg_set->inbound_doorbell);

max_wait = 10;
cur_state = MFI_STATE_OPERATIONAL;
@@ -1323,6 +1339,7 @@ megasas_transition_to_ready(struct megas
return -ENODEV;
}
};
+ printk(KERN_INFO "megasas: FW now in Ready state\n");

return 0;
}
@@ -1352,7 +1369,7 @@ static void megasas_teardown_frame_pool(
cmd->frame_phys_addr);

if (cmd->sense)
- pci_pool_free(instance->sense_dma_pool, cmd->frame,
+ pci_pool_free(instance->sense_dma_pool, cmd->sense,
cmd->sense_phys_addr);
}

@@ -1690,6 +1707,12 @@ static int megasas_init_mfi(struct megas
* 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;
/*
diff -uprN linux2.6-orig/drivers/scsi/megaraid/megaraid_sas.h linux2.6/drivers/scsi/megaraid/megaraid_sas.h
--- linux2.6-orig/drivers/scsi/megaraid/megaraid_sas.h 2006-10-02 10:15:31.000000000 -0700
+++ linux2.6/drivers/scsi/megaraid/megaraid_sas.h 2006-10-02 10:16:13.000000000 -0700
@@ -50,6 +50,7 @@
#define MFI_STATE_WAIT_HANDSHAKE 0x60000000
#define MFI_STATE_FW_INIT_2 0x70000000
#define MFI_STATE_DEVICE_SCAN 0x80000000
+#define MFI_STATE_BOOT_MESSAGE_PENDING 0x90000000
#define MFI_STATE_FLUSH_CACHE 0xA0000000
#define MFI_STATE_READY 0xB0000000
#define MFI_STATE_OPERATIONAL 0xC0000000
@@ -64,12 +65,18 @@
* READY : Move from OPERATIONAL to READY state; discard queue info
* MFIMODE : Discard (possible) low MFA posted in 64-bit mode (??)
* CLR_HANDSHAKE: FW is waiting for HANDSHAKE from BIOS or Driver
+ * HOTPLUG : Resume from Hotplug
+ * MFI_STOP_ADP : Send signal to FW to stop processing
*/
-#define MFI_INIT_ABORT 0x00000000
+#define MFI_INIT_ABORT 0x00000001
#define MFI_INIT_READY 0x00000002
#define MFI_INIT_MFIMODE 0x00000004
#define MFI_INIT_CLEAR_HANDSHAKE 0x00000008
-#define MFI_RESET_FLAGS MFI_INIT_READY|MFI_INIT_MFIMODE
+#define MFI_INIT_HOTPLUG 0x00000010
+#define MFI_STOP_ADP 0x00000020
+#define MFI_RESET_FLAGS MFI_INIT_READY| \
+ MFI_INIT_MFIMODE| \
+ MFI_INIT_ABORT

/**
* MFI frame flags