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 /drivers/scsi/3w-9xxx.c | |
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>
Diffstat (limited to 'drivers/scsi/3w-9xxx.c')
-rw-r--r-- | drivers/scsi/3w-9xxx.c | 55 |
1 files changed, 47 insertions, 8 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); |