Commit 49bfd8db authored by adam radford's avatar adam radford Committed by James Bottomley

[SCSI] 3ware 9000: Add support for 9550SX controllers

Signed-off-by: default avatarAdam Radford <linuxraid@amcc.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@SteelEye.com>
parent 68ce1eb5
...@@ -60,6 +60,7 @@ ...@@ -60,6 +60,7 @@
Remove un-needed eh_abort handler. Remove un-needed eh_abort handler.
Add support for embedded firmware error strings. Add support for embedded firmware error strings.
2.26.02.003 - Correctly handle single sgl's with use_sg=1. 2.26.02.003 - Correctly handle single sgl's with use_sg=1.
2.26.02.004 - Add support for 9550SX controllers.
*/ */
#include <linux/module.h> #include <linux/module.h>
...@@ -82,7 +83,7 @@ ...@@ -82,7 +83,7 @@
#include "3w-9xxx.h" #include "3w-9xxx.h"
/* Globals */ /* Globals */
#define TW_DRIVER_VERSION "2.26.02.003" #define TW_DRIVER_VERSION "2.26.02.004"
static TW_Device_Extension *twa_device_extension_list[TW_MAX_SLOT]; static TW_Device_Extension *twa_device_extension_list[TW_MAX_SLOT];
static unsigned int twa_device_extension_count; static unsigned int twa_device_extension_count;
static int twa_major = -1; static int twa_major = -1;
...@@ -892,11 +893,6 @@ static int twa_decode_bits(TW_Device_Extension *tw_dev, u32 status_reg_value) ...@@ -892,11 +893,6 @@ static int twa_decode_bits(TW_Device_Extension *tw_dev, u32 status_reg_value)
writel(TW_CONTROL_CLEAR_QUEUE_ERROR, TW_CONTROL_REG_ADDR(tw_dev)); writel(TW_CONTROL_CLEAR_QUEUE_ERROR, TW_CONTROL_REG_ADDR(tw_dev));
} }
if (status_reg_value & TW_STATUS_SBUF_WRITE_ERROR) {
TW_PRINTK(tw_dev->host, TW_DRIVER, 0xf, "SBUF Write Error: clearing");
writel(TW_CONTROL_CLEAR_SBUF_WRITE_ERROR, TW_CONTROL_REG_ADDR(tw_dev));
}
if (status_reg_value & TW_STATUS_MICROCONTROLLER_ERROR) { if (status_reg_value & TW_STATUS_MICROCONTROLLER_ERROR) {
if (tw_dev->reset_print == 0) { if (tw_dev->reset_print == 0) {
TW_PRINTK(tw_dev->host, TW_DRIVER, 0x10, "Microcontroller Error: clearing"); TW_PRINTK(tw_dev->host, TW_DRIVER, 0x10, "Microcontroller Error: clearing");
...@@ -930,6 +926,36 @@ out: ...@@ -930,6 +926,36 @@ out:
return retval; return retval;
} /* End twa_empty_response_queue() */ } /* End twa_empty_response_queue() */
/* This function will clear the pchip/response queue on 9550SX */
static int twa_empty_response_queue_large(TW_Device_Extension *tw_dev)
{
u32 status_reg_value, response_que_value;
int count = 0, retval = 1;
if (tw_dev->tw_pci_dev->device == PCI_DEVICE_ID_3WARE_9550SX) {
status_reg_value = readl(TW_STATUS_REG_ADDR(tw_dev));
while (((status_reg_value & TW_STATUS_RESPONSE_QUEUE_EMPTY) == 0) && (count < TW_MAX_RESPONSE_DRAIN)) {
response_que_value = readl(TW_RESPONSE_QUEUE_REG_ADDR_LARGE(tw_dev));
if ((response_que_value & TW_9550SX_DRAIN_COMPLETED) == TW_9550SX_DRAIN_COMPLETED) {
/* P-chip settle time */
msleep(500);
retval = 0;
goto out;
}
status_reg_value = readl(TW_STATUS_REG_ADDR(tw_dev));
count++;
}
if (count == TW_MAX_RESPONSE_DRAIN)
goto out;
retval = 0;
} else
retval = 0;
out:
return retval;
} /* End twa_empty_response_queue_large() */
/* This function passes sense keys from firmware to scsi layer */ /* This function passes sense keys from firmware to scsi layer */
static int twa_fill_sense(TW_Device_Extension *tw_dev, int request_id, int copy_sense, int print_host) static int twa_fill_sense(TW_Device_Extension *tw_dev, int request_id, int copy_sense, int print_host)
{ {
...@@ -1613,8 +1639,16 @@ static int twa_reset_sequence(TW_Device_Extension *tw_dev, int soft_reset) ...@@ -1613,8 +1639,16 @@ static int twa_reset_sequence(TW_Device_Extension *tw_dev, int soft_reset)
int tries = 0, retval = 1, flashed = 0, do_soft_reset = soft_reset; int tries = 0, retval = 1, flashed = 0, do_soft_reset = soft_reset;
while (tries < TW_MAX_RESET_TRIES) { while (tries < TW_MAX_RESET_TRIES) {
if (do_soft_reset) if (do_soft_reset) {
TW_SOFT_RESET(tw_dev); TW_SOFT_RESET(tw_dev);
/* Clear pchip/response queue on 9550SX */
if (twa_empty_response_queue_large(tw_dev)) {
TW_PRINTK(tw_dev->host, TW_DRIVER, 0x36, "Response queue (large) empty failed during reset sequence");
do_soft_reset = 1;
tries++;
continue;
}
}
/* Make sure controller is in a good state */ /* Make sure controller is in a good state */
if (twa_poll_status(tw_dev, TW_STATUS_MICROCONTROLLER_READY | (do_soft_reset == 1 ? TW_STATUS_ATTENTION_INTERRUPT : 0), 60)) { if (twa_poll_status(tw_dev, TW_STATUS_MICROCONTROLLER_READY | (do_soft_reset == 1 ? TW_STATUS_ATTENTION_INTERRUPT : 0), 60)) {
...@@ -2034,7 +2068,10 @@ static int __devinit twa_probe(struct pci_dev *pdev, const struct pci_device_id ...@@ -2034,7 +2068,10 @@ static int __devinit twa_probe(struct pci_dev *pdev, const struct pci_device_id
goto out_free_device_extension; goto out_free_device_extension;
} }
if (pdev->device == PCI_DEVICE_ID_3WARE_9000)
mem_addr = pci_resource_start(pdev, 1); mem_addr = pci_resource_start(pdev, 1);
else
mem_addr = pci_resource_start(pdev, 2);
/* Save base address */ /* Save base address */
tw_dev->base_addr = ioremap(mem_addr, PAGE_SIZE); tw_dev->base_addr = ioremap(mem_addr, PAGE_SIZE);
...@@ -2148,6 +2185,8 @@ static void twa_remove(struct pci_dev *pdev) ...@@ -2148,6 +2185,8 @@ static void twa_remove(struct pci_dev *pdev)
static struct pci_device_id twa_pci_tbl[] __devinitdata = { static struct pci_device_id twa_pci_tbl[] __devinitdata = {
{ PCI_VENDOR_ID_3WARE, PCI_DEVICE_ID_3WARE_9000, { PCI_VENDOR_ID_3WARE, PCI_DEVICE_ID_3WARE_9000,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{ PCI_VENDOR_ID_3WARE, PCI_DEVICE_ID_3WARE_9550SX,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{ } { }
}; };
MODULE_DEVICE_TABLE(pci, twa_pci_tbl); MODULE_DEVICE_TABLE(pci, twa_pci_tbl);
......
...@@ -267,7 +267,6 @@ static twa_message_type twa_error_table[] = { ...@@ -267,7 +267,6 @@ static twa_message_type twa_error_table[] = {
#define TW_CONTROL_CLEAR_PARITY_ERROR 0x00800000 #define TW_CONTROL_CLEAR_PARITY_ERROR 0x00800000
#define TW_CONTROL_CLEAR_QUEUE_ERROR 0x00400000 #define TW_CONTROL_CLEAR_QUEUE_ERROR 0x00400000
#define TW_CONTROL_CLEAR_PCI_ABORT 0x00100000 #define TW_CONTROL_CLEAR_PCI_ABORT 0x00100000
#define TW_CONTROL_CLEAR_SBUF_WRITE_ERROR 0x00000008
/* Status register bit definitions */ /* Status register bit definitions */
#define TW_STATUS_MAJOR_VERSION_MASK 0xF0000000 #define TW_STATUS_MAJOR_VERSION_MASK 0xF0000000
...@@ -285,9 +284,8 @@ static twa_message_type twa_error_table[] = { ...@@ -285,9 +284,8 @@ static twa_message_type twa_error_table[] = {
#define TW_STATUS_MICROCONTROLLER_READY 0x00002000 #define TW_STATUS_MICROCONTROLLER_READY 0x00002000
#define TW_STATUS_COMMAND_QUEUE_EMPTY 0x00001000 #define TW_STATUS_COMMAND_QUEUE_EMPTY 0x00001000
#define TW_STATUS_EXPECTED_BITS 0x00002000 #define TW_STATUS_EXPECTED_BITS 0x00002000
#define TW_STATUS_UNEXPECTED_BITS 0x00F00008 #define TW_STATUS_UNEXPECTED_BITS 0x00F00000
#define TW_STATUS_SBUF_WRITE_ERROR 0x00000008 #define TW_STATUS_VALID_INTERRUPT 0x00DF0000
#define TW_STATUS_VALID_INTERRUPT 0x00DF0008
/* RESPONSE QUEUE BIT DEFINITIONS */ /* RESPONSE QUEUE BIT DEFINITIONS */
#define TW_RESPONSE_ID_MASK 0x00000FF0 #define TW_RESPONSE_ID_MASK 0x00000FF0
...@@ -324,9 +322,9 @@ static twa_message_type twa_error_table[] = { ...@@ -324,9 +322,9 @@ static twa_message_type twa_error_table[] = {
/* Compatibility defines */ /* Compatibility defines */
#define TW_9000_ARCH_ID 0x5 #define TW_9000_ARCH_ID 0x5
#define TW_CURRENT_DRIVER_SRL 28 #define TW_CURRENT_DRIVER_SRL 30
#define TW_CURRENT_DRIVER_BUILD 9 #define TW_CURRENT_DRIVER_BUILD 80
#define TW_CURRENT_DRIVER_BRANCH 4 #define TW_CURRENT_DRIVER_BRANCH 0
/* Phase defines */ /* Phase defines */
#define TW_PHASE_INITIAL 0 #define TW_PHASE_INITIAL 0
...@@ -334,6 +332,7 @@ static twa_message_type twa_error_table[] = { ...@@ -334,6 +332,7 @@ static twa_message_type twa_error_table[] = {
#define TW_PHASE_SGLIST 2 #define TW_PHASE_SGLIST 2
/* Misc defines */ /* Misc defines */
#define TW_9550SX_DRAIN_COMPLETED 0xFFFF
#define TW_SECTOR_SIZE 512 #define TW_SECTOR_SIZE 512
#define TW_ALIGNMENT_9000 4 /* 4 bytes */ #define TW_ALIGNMENT_9000 4 /* 4 bytes */
#define TW_ALIGNMENT_9000_SGL 0x3 #define TW_ALIGNMENT_9000_SGL 0x3
...@@ -417,6 +416,9 @@ static twa_message_type twa_error_table[] = { ...@@ -417,6 +416,9 @@ static twa_message_type twa_error_table[] = {
#ifndef PCI_DEVICE_ID_3WARE_9000 #ifndef PCI_DEVICE_ID_3WARE_9000
#define PCI_DEVICE_ID_3WARE_9000 0x1002 #define PCI_DEVICE_ID_3WARE_9000 0x1002
#endif #endif
#ifndef PCI_DEVICE_ID_3WARE_9550SX
#define PCI_DEVICE_ID_3WARE_9550SX 0x1003
#endif
/* Bitmask macros to eliminate bitfields */ /* Bitmask macros to eliminate bitfields */
...@@ -443,6 +445,7 @@ static twa_message_type twa_error_table[] = { ...@@ -443,6 +445,7 @@ static twa_message_type twa_error_table[] = {
#define TW_STATUS_REG_ADDR(x) ((unsigned char __iomem *)x->base_addr + 0x4) #define TW_STATUS_REG_ADDR(x) ((unsigned char __iomem *)x->base_addr + 0x4)
#define TW_COMMAND_QUEUE_REG_ADDR(x) (sizeof(dma_addr_t) > 4 ? ((unsigned char __iomem *)x->base_addr + 0x20) : ((unsigned char __iomem *)x->base_addr + 0x8)) #define TW_COMMAND_QUEUE_REG_ADDR(x) (sizeof(dma_addr_t) > 4 ? ((unsigned char __iomem *)x->base_addr + 0x20) : ((unsigned char __iomem *)x->base_addr + 0x8))
#define TW_RESPONSE_QUEUE_REG_ADDR(x) ((unsigned char __iomem *)x->base_addr + 0xC) #define TW_RESPONSE_QUEUE_REG_ADDR(x) ((unsigned char __iomem *)x->base_addr + 0xC)
#define TW_RESPONSE_QUEUE_REG_ADDR_LARGE(x) ((unsigned char __iomem *)x->base_addr + 0x30)
#define TW_CLEAR_ALL_INTERRUPTS(x) (writel(TW_STATUS_VALID_INTERRUPT, TW_CONTROL_REG_ADDR(x))) #define TW_CLEAR_ALL_INTERRUPTS(x) (writel(TW_STATUS_VALID_INTERRUPT, TW_CONTROL_REG_ADDR(x)))
#define TW_CLEAR_ATTENTION_INTERRUPT(x) (writel(TW_CONTROL_CLEAR_ATTENTION_INTERRUPT, TW_CONTROL_REG_ADDR(x))) #define TW_CLEAR_ATTENTION_INTERRUPT(x) (writel(TW_CONTROL_CLEAR_ATTENTION_INTERRUPT, TW_CONTROL_REG_ADDR(x)))
#define TW_CLEAR_HOST_INTERRUPT(x) (writel(TW_CONTROL_CLEAR_HOST_INTERRUPT, TW_CONTROL_REG_ADDR(x))) #define TW_CLEAR_HOST_INTERRUPT(x) (writel(TW_CONTROL_CLEAR_HOST_INTERRUPT, TW_CONTROL_REG_ADDR(x)))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment