diff options
| author | adam radford <aradford@gmail.com> | 2005-09-21 20:20:14 -0400 |
|---|---|---|
| committer | James Bottomley <jejb@mulgrave.(none)> | 2005-09-25 10:36:26 -0400 |
| commit | 49bfd8db4a39ea14fb3780b162012b4b3611fce8 (patch) | |
| tree | 32eb481522ad819bc82490306f860a3bed4045e2 | |
| parent | 68ce1eb54056e4fad6e73968e958b926d28cb0dd (diff) | |
[SCSI] 3ware 9000: Add support for 9550SX controllers
Signed-off-by: Adam Radford <linuxraid@amcc.com>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
| -rw-r--r-- | drivers/scsi/3w-9xxx.c | 55 | ||||
| -rw-r--r-- | drivers/scsi/3w-9xxx.h | 17 |
2 files changed, 57 insertions, 15 deletions
diff --git a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c index a6ac61611f35..a748fbfb6692 100644 --- a/drivers/scsi/3w-9xxx.c +++ b/drivers/scsi/3w-9xxx.c | |||
| @@ -60,6 +60,7 @@ | |||
| 60 | Remove un-needed eh_abort handler. | 60 | Remove un-needed eh_abort handler. |
| 61 | Add support for embedded firmware error strings. | 61 | Add support for embedded firmware error strings. |
| 62 | 2.26.02.003 - Correctly handle single sgl's with use_sg=1. | 62 | 2.26.02.003 - Correctly handle single sgl's with use_sg=1. |
| 63 | 2.26.02.004 - Add support for 9550SX controllers. | ||
| 63 | */ | 64 | */ |
| 64 | 65 | ||
| 65 | #include <linux/module.h> | 66 | #include <linux/module.h> |
| @@ -82,7 +83,7 @@ | |||
| 82 | #include "3w-9xxx.h" | 83 | #include "3w-9xxx.h" |
| 83 | 84 | ||
| 84 | /* Globals */ | 85 | /* Globals */ |
| 85 | #define TW_DRIVER_VERSION "2.26.02.003" | 86 | #define TW_DRIVER_VERSION "2.26.02.004" |
| 86 | static TW_Device_Extension *twa_device_extension_list[TW_MAX_SLOT]; | 87 | static TW_Device_Extension *twa_device_extension_list[TW_MAX_SLOT]; |
| 87 | static unsigned int twa_device_extension_count; | 88 | static unsigned int twa_device_extension_count; |
| 88 | static int twa_major = -1; | 89 | static int twa_major = -1; |
| @@ -892,11 +893,6 @@ static int twa_decode_bits(TW_Device_Extension *tw_dev, u32 status_reg_value) | |||
| 892 | writel(TW_CONTROL_CLEAR_QUEUE_ERROR, TW_CONTROL_REG_ADDR(tw_dev)); | 893 | writel(TW_CONTROL_CLEAR_QUEUE_ERROR, TW_CONTROL_REG_ADDR(tw_dev)); |
| 893 | } | 894 | } |
| 894 | 895 | ||
| 895 | if (status_reg_value & TW_STATUS_SBUF_WRITE_ERROR) { | ||
| 896 | TW_PRINTK(tw_dev->host, TW_DRIVER, 0xf, "SBUF Write Error: clearing"); | ||
| 897 | writel(TW_CONTROL_CLEAR_SBUF_WRITE_ERROR, TW_CONTROL_REG_ADDR(tw_dev)); | ||
| 898 | } | ||
| 899 | |||
| 900 | if (status_reg_value & TW_STATUS_MICROCONTROLLER_ERROR) { | 896 | if (status_reg_value & TW_STATUS_MICROCONTROLLER_ERROR) { |
| 901 | if (tw_dev->reset_print == 0) { | 897 | if (tw_dev->reset_print == 0) { |
| 902 | TW_PRINTK(tw_dev->host, TW_DRIVER, 0x10, "Microcontroller Error: clearing"); | 898 | TW_PRINTK(tw_dev->host, TW_DRIVER, 0x10, "Microcontroller Error: clearing"); |
| @@ -930,6 +926,36 @@ out: | |||
| 930 | return retval; | 926 | return retval; |
| 931 | } /* End twa_empty_response_queue() */ | 927 | } /* End twa_empty_response_queue() */ |
| 932 | 928 | ||
| 929 | /* This function will clear the pchip/response queue on 9550SX */ | ||
| 930 | static int twa_empty_response_queue_large(TW_Device_Extension *tw_dev) | ||
| 931 | { | ||
| 932 | u32 status_reg_value, response_que_value; | ||
| 933 | int count = 0, retval = 1; | ||
| 934 | |||
| 935 | if (tw_dev->tw_pci_dev->device == PCI_DEVICE_ID_3WARE_9550SX) { | ||
| 936 | status_reg_value = readl(TW_STATUS_REG_ADDR(tw_dev)); | ||
| 937 | |||
| 938 | while (((status_reg_value & TW_STATUS_RESPONSE_QUEUE_EMPTY) == 0) && (count < TW_MAX_RESPONSE_DRAIN)) { | ||
| 939 | response_que_value = readl(TW_RESPONSE_QUEUE_REG_ADDR_LARGE(tw_dev)); | ||
| 940 | if ((response_que_value & TW_9550SX_DRAIN_COMPLETED) == TW_9550SX_DRAIN_COMPLETED) { | ||
| 941 | /* P-chip settle time */ | ||
| 942 | msleep(500); | ||
| 943 | retval = 0; | ||
| 944 | goto out; | ||
| 945 | } | ||
| 946 | status_reg_value = readl(TW_STATUS_REG_ADDR(tw_dev)); | ||
| 947 | count++; | ||
| 948 | } | ||
| 949 | if (count == TW_MAX_RESPONSE_DRAIN) | ||
| 950 | goto out; | ||
| 951 | |||
| 952 | retval = 0; | ||
| 953 | } else | ||
| 954 | retval = 0; | ||
| 955 | out: | ||
| 956 | return retval; | ||
| 957 | } /* End twa_empty_response_queue_large() */ | ||
| 958 | |||
| 933 | /* This function passes sense keys from firmware to scsi layer */ | 959 | /* This function passes sense keys from firmware to scsi layer */ |
| 934 | static int twa_fill_sense(TW_Device_Extension *tw_dev, int request_id, int copy_sense, int print_host) | 960 | static int twa_fill_sense(TW_Device_Extension *tw_dev, int request_id, int copy_sense, int print_host) |
| 935 | { | 961 | { |
| @@ -1613,8 +1639,16 @@ static int twa_reset_sequence(TW_Device_Extension *tw_dev, int soft_reset) | |||
| 1613 | int tries = 0, retval = 1, flashed = 0, do_soft_reset = soft_reset; | 1639 | int tries = 0, retval = 1, flashed = 0, do_soft_reset = soft_reset; |
| 1614 | 1640 | ||
| 1615 | while (tries < TW_MAX_RESET_TRIES) { | 1641 | while (tries < TW_MAX_RESET_TRIES) { |
| 1616 | if (do_soft_reset) | 1642 | if (do_soft_reset) { |
| 1617 | TW_SOFT_RESET(tw_dev); | 1643 | TW_SOFT_RESET(tw_dev); |
| 1644 | /* Clear pchip/response queue on 9550SX */ | ||
| 1645 | if (twa_empty_response_queue_large(tw_dev)) { | ||
| 1646 | TW_PRINTK(tw_dev->host, TW_DRIVER, 0x36, "Response queue (large) empty failed during reset sequence"); | ||
| 1647 | do_soft_reset = 1; | ||
| 1648 | tries++; | ||
| 1649 | continue; | ||
| 1650 | } | ||
| 1651 | } | ||
| 1618 | 1652 | ||
| 1619 | /* Make sure controller is in a good state */ | 1653 | /* Make sure controller is in a good state */ |
| 1620 | if (twa_poll_status(tw_dev, TW_STATUS_MICROCONTROLLER_READY | (do_soft_reset == 1 ? TW_STATUS_ATTENTION_INTERRUPT : 0), 60)) { | 1654 | 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 | goto out_free_device_extension; | 2068 | goto out_free_device_extension; |
| 2035 | } | 2069 | } |
| 2036 | 2070 | ||
| 2037 | mem_addr = pci_resource_start(pdev, 1); | 2071 | if (pdev->device == PCI_DEVICE_ID_3WARE_9000) |
| 2072 | mem_addr = pci_resource_start(pdev, 1); | ||
| 2073 | else | ||
| 2074 | mem_addr = pci_resource_start(pdev, 2); | ||
| 2038 | 2075 | ||
| 2039 | /* Save base address */ | 2076 | /* Save base address */ |
| 2040 | tw_dev->base_addr = ioremap(mem_addr, PAGE_SIZE); | 2077 | tw_dev->base_addr = ioremap(mem_addr, PAGE_SIZE); |
| @@ -2148,6 +2185,8 @@ static void twa_remove(struct pci_dev *pdev) | |||
| 2148 | static struct pci_device_id twa_pci_tbl[] __devinitdata = { | 2185 | static struct pci_device_id twa_pci_tbl[] __devinitdata = { |
| 2149 | { PCI_VENDOR_ID_3WARE, PCI_DEVICE_ID_3WARE_9000, | 2186 | { PCI_VENDOR_ID_3WARE, PCI_DEVICE_ID_3WARE_9000, |
| 2150 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, | 2187 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, |
| 2188 | { PCI_VENDOR_ID_3WARE, PCI_DEVICE_ID_3WARE_9550SX, | ||
| 2189 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, | ||
| 2151 | { } | 2190 | { } |
| 2152 | }; | 2191 | }; |
| 2153 | MODULE_DEVICE_TABLE(pci, twa_pci_tbl); | 2192 | MODULE_DEVICE_TABLE(pci, twa_pci_tbl); |
diff --git a/drivers/scsi/3w-9xxx.h b/drivers/scsi/3w-9xxx.h index 8c8ecbed3b58..46f22cdc8298 100644 --- a/drivers/scsi/3w-9xxx.h +++ b/drivers/scsi/3w-9xxx.h | |||
| @@ -267,7 +267,6 @@ static twa_message_type twa_error_table[] = { | |||
| 267 | #define TW_CONTROL_CLEAR_PARITY_ERROR 0x00800000 | 267 | #define TW_CONTROL_CLEAR_PARITY_ERROR 0x00800000 |
| 268 | #define TW_CONTROL_CLEAR_QUEUE_ERROR 0x00400000 | 268 | #define TW_CONTROL_CLEAR_QUEUE_ERROR 0x00400000 |
| 269 | #define TW_CONTROL_CLEAR_PCI_ABORT 0x00100000 | 269 | #define TW_CONTROL_CLEAR_PCI_ABORT 0x00100000 |
| 270 | #define TW_CONTROL_CLEAR_SBUF_WRITE_ERROR 0x00000008 | ||
| 271 | 270 | ||
| 272 | /* Status register bit definitions */ | 271 | /* Status register bit definitions */ |
| 273 | #define TW_STATUS_MAJOR_VERSION_MASK 0xF0000000 | 272 | #define TW_STATUS_MAJOR_VERSION_MASK 0xF0000000 |
| @@ -285,9 +284,8 @@ static twa_message_type twa_error_table[] = { | |||
| 285 | #define TW_STATUS_MICROCONTROLLER_READY 0x00002000 | 284 | #define TW_STATUS_MICROCONTROLLER_READY 0x00002000 |
| 286 | #define TW_STATUS_COMMAND_QUEUE_EMPTY 0x00001000 | 285 | #define TW_STATUS_COMMAND_QUEUE_EMPTY 0x00001000 |
| 287 | #define TW_STATUS_EXPECTED_BITS 0x00002000 | 286 | #define TW_STATUS_EXPECTED_BITS 0x00002000 |
| 288 | #define TW_STATUS_UNEXPECTED_BITS 0x00F00008 | 287 | #define TW_STATUS_UNEXPECTED_BITS 0x00F00000 |
| 289 | #define TW_STATUS_SBUF_WRITE_ERROR 0x00000008 | 288 | #define TW_STATUS_VALID_INTERRUPT 0x00DF0000 |
| 290 | #define TW_STATUS_VALID_INTERRUPT 0x00DF0008 | ||
| 291 | 289 | ||
| 292 | /* RESPONSE QUEUE BIT DEFINITIONS */ | 290 | /* RESPONSE QUEUE BIT DEFINITIONS */ |
| 293 | #define TW_RESPONSE_ID_MASK 0x00000FF0 | 291 | #define TW_RESPONSE_ID_MASK 0x00000FF0 |
| @@ -324,9 +322,9 @@ static twa_message_type twa_error_table[] = { | |||
| 324 | 322 | ||
| 325 | /* Compatibility defines */ | 323 | /* Compatibility defines */ |
| 326 | #define TW_9000_ARCH_ID 0x5 | 324 | #define TW_9000_ARCH_ID 0x5 |
| 327 | #define TW_CURRENT_DRIVER_SRL 28 | 325 | #define TW_CURRENT_DRIVER_SRL 30 |
| 328 | #define TW_CURRENT_DRIVER_BUILD 9 | 326 | #define TW_CURRENT_DRIVER_BUILD 80 |
| 329 | #define TW_CURRENT_DRIVER_BRANCH 4 | 327 | #define TW_CURRENT_DRIVER_BRANCH 0 |
| 330 | 328 | ||
| 331 | /* Phase defines */ | 329 | /* Phase defines */ |
| 332 | #define TW_PHASE_INITIAL 0 | 330 | #define TW_PHASE_INITIAL 0 |
| @@ -334,6 +332,7 @@ static twa_message_type twa_error_table[] = { | |||
| 334 | #define TW_PHASE_SGLIST 2 | 332 | #define TW_PHASE_SGLIST 2 |
| 335 | 333 | ||
| 336 | /* Misc defines */ | 334 | /* Misc defines */ |
| 335 | #define TW_9550SX_DRAIN_COMPLETED 0xFFFF | ||
| 337 | #define TW_SECTOR_SIZE 512 | 336 | #define TW_SECTOR_SIZE 512 |
| 338 | #define TW_ALIGNMENT_9000 4 /* 4 bytes */ | 337 | #define TW_ALIGNMENT_9000 4 /* 4 bytes */ |
| 339 | #define TW_ALIGNMENT_9000_SGL 0x3 | 338 | #define TW_ALIGNMENT_9000_SGL 0x3 |
| @@ -417,6 +416,9 @@ static twa_message_type twa_error_table[] = { | |||
| 417 | #ifndef PCI_DEVICE_ID_3WARE_9000 | 416 | #ifndef PCI_DEVICE_ID_3WARE_9000 |
| 418 | #define PCI_DEVICE_ID_3WARE_9000 0x1002 | 417 | #define PCI_DEVICE_ID_3WARE_9000 0x1002 |
| 419 | #endif | 418 | #endif |
| 419 | #ifndef PCI_DEVICE_ID_3WARE_9550SX | ||
| 420 | #define PCI_DEVICE_ID_3WARE_9550SX 0x1003 | ||
| 421 | #endif | ||
| 420 | 422 | ||
| 421 | /* Bitmask macros to eliminate bitfields */ | 423 | /* Bitmask macros to eliminate bitfields */ |
| 422 | 424 | ||
| @@ -443,6 +445,7 @@ static twa_message_type twa_error_table[] = { | |||
| 443 | #define TW_STATUS_REG_ADDR(x) ((unsigned char __iomem *)x->base_addr + 0x4) | 445 | #define TW_STATUS_REG_ADDR(x) ((unsigned char __iomem *)x->base_addr + 0x4) |
| 444 | #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)) | 446 | #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)) |
| 445 | #define TW_RESPONSE_QUEUE_REG_ADDR(x) ((unsigned char __iomem *)x->base_addr + 0xC) | 447 | #define TW_RESPONSE_QUEUE_REG_ADDR(x) ((unsigned char __iomem *)x->base_addr + 0xC) |
| 448 | #define TW_RESPONSE_QUEUE_REG_ADDR_LARGE(x) ((unsigned char __iomem *)x->base_addr + 0x30) | ||
| 446 | #define TW_CLEAR_ALL_INTERRUPTS(x) (writel(TW_STATUS_VALID_INTERRUPT, TW_CONTROL_REG_ADDR(x))) | 449 | #define TW_CLEAR_ALL_INTERRUPTS(x) (writel(TW_STATUS_VALID_INTERRUPT, TW_CONTROL_REG_ADDR(x))) |
| 447 | #define TW_CLEAR_ATTENTION_INTERRUPT(x) (writel(TW_CONTROL_CLEAR_ATTENTION_INTERRUPT, TW_CONTROL_REG_ADDR(x))) | 450 | #define TW_CLEAR_ATTENTION_INTERRUPT(x) (writel(TW_CONTROL_CLEAR_ATTENTION_INTERRUPT, TW_CONTROL_REG_ADDR(x))) |
| 448 | #define TW_CLEAR_HOST_INTERRUPT(x) (writel(TW_CONTROL_CLEAR_HOST_INTERRUPT, TW_CONTROL_REG_ADDR(x))) | 451 | #define TW_CLEAR_HOST_INTERRUPT(x) (writel(TW_CONTROL_CLEAR_HOST_INTERRUPT, TW_CONTROL_REG_ADDR(x))) |
