aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authoradam radford <aradford@gmail.com>2006-10-26 21:01:06 -0400
committerJames Bottomley <jejb@mulgrave.il.steeleye.com>2006-11-09 00:27:57 -0500
commit4039c30ef5d9189ff8dc72aaf610d1c933877e20 (patch)
tree8f706764ef62b47d0c2b552372b28fdcc7dac9c0 /drivers
parent42961ee8fc4b05f5ca4d96ab34abd5149afe3541 (diff)
[SCSI] 3ware 9000 add support for 9650SE
Updates the 3ware 9000 driver: - Free irq handler in __twa_shutdown(). - Serialize reset code. - Add support for 9650SE controllers. Signed-off-by: Adam Radford <linuxraid@amcc.com> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/scsi/3w-9xxx.c141
-rw-r--r--drivers/scsi/3w-9xxx.h14
2 files changed, 94 insertions, 61 deletions
diff --git a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c
index 5f8c26cd66ca..b091a0fc4eb0 100644
--- a/drivers/scsi/3w-9xxx.c
+++ b/drivers/scsi/3w-9xxx.c
@@ -66,6 +66,9 @@
66 2.26.02.006 - Fix 9550SX pchip reset timeout. 66 2.26.02.006 - Fix 9550SX pchip reset timeout.
67 Add big endian support. 67 Add big endian support.
68 2.26.02.007 - Disable local interrupts during kmap/unmap_atomic(). 68 2.26.02.007 - Disable local interrupts during kmap/unmap_atomic().
69 2.26.02.008 - Free irq handler in __twa_shutdown().
70 Serialize reset code.
71 Add support for 9650SE controllers.
69*/ 72*/
70 73
71#include <linux/module.h> 74#include <linux/module.h>
@@ -89,7 +92,7 @@
89#include "3w-9xxx.h" 92#include "3w-9xxx.h"
90 93
91/* Globals */ 94/* Globals */
92#define TW_DRIVER_VERSION "2.26.02.007" 95#define TW_DRIVER_VERSION "2.26.02.008"
93static TW_Device_Extension *twa_device_extension_list[TW_MAX_SLOT]; 96static TW_Device_Extension *twa_device_extension_list[TW_MAX_SLOT];
94static unsigned int twa_device_extension_count; 97static unsigned int twa_device_extension_count;
95static int twa_major = -1; 98static int twa_major = -1;
@@ -566,9 +569,9 @@ static int twa_check_srl(TW_Device_Extension *tw_dev, int *flashed)
566 goto out; 569 goto out;
567 } 570 }
568 571
569 tw_dev->working_srl = fw_on_ctlr_srl; 572 tw_dev->tw_compat_info.working_srl = fw_on_ctlr_srl;
570 tw_dev->working_branch = fw_on_ctlr_branch; 573 tw_dev->tw_compat_info.working_branch = fw_on_ctlr_branch;
571 tw_dev->working_build = fw_on_ctlr_build; 574 tw_dev->tw_compat_info.working_build = fw_on_ctlr_build;
572 575
573 /* Try base mode compatibility */ 576 /* Try base mode compatibility */
574 if (!(init_connect_result & TW_CTLR_FW_COMPATIBLE)) { 577 if (!(init_connect_result & TW_CTLR_FW_COMPATIBLE)) {
@@ -590,10 +593,23 @@ static int twa_check_srl(TW_Device_Extension *tw_dev, int *flashed)
590 } 593 }
591 goto out; 594 goto out;
592 } 595 }
593 tw_dev->working_srl = TW_BASE_FW_SRL; 596 tw_dev->tw_compat_info.working_srl = TW_BASE_FW_SRL;
594 tw_dev->working_branch = TW_BASE_FW_BRANCH; 597 tw_dev->tw_compat_info.working_branch = TW_BASE_FW_BRANCH;
595 tw_dev->working_build = TW_BASE_FW_BUILD; 598 tw_dev->tw_compat_info.working_build = TW_BASE_FW_BUILD;
596 } 599 }
600
601 /* Load rest of compatibility struct */
602 strncpy(tw_dev->tw_compat_info.driver_version, TW_DRIVER_VERSION, strlen(TW_DRIVER_VERSION));
603 tw_dev->tw_compat_info.driver_srl_high = TW_CURRENT_DRIVER_SRL;
604 tw_dev->tw_compat_info.driver_branch_high = TW_CURRENT_DRIVER_BRANCH;
605 tw_dev->tw_compat_info.driver_build_high = TW_CURRENT_DRIVER_BUILD;
606 tw_dev->tw_compat_info.driver_srl_low = TW_BASE_FW_SRL;
607 tw_dev->tw_compat_info.driver_branch_low = TW_BASE_FW_BRANCH;
608 tw_dev->tw_compat_info.driver_build_low = TW_BASE_FW_BUILD;
609 tw_dev->tw_compat_info.fw_on_ctlr_srl = fw_on_ctlr_srl;
610 tw_dev->tw_compat_info.fw_on_ctlr_branch = fw_on_ctlr_branch;
611 tw_dev->tw_compat_info.fw_on_ctlr_build = fw_on_ctlr_build;
612
597 retval = 0; 613 retval = 0;
598out: 614out:
599 return retval; 615 return retval;
@@ -631,7 +647,7 @@ static int twa_chrdev_ioctl(struct inode *inode, struct file *file, unsigned int
631 goto out2; 647 goto out2;
632 648
633 /* Check data buffer size */ 649 /* Check data buffer size */
634 if (driver_command.buffer_length > TW_MAX_SECTORS * 512) { 650 if (driver_command.buffer_length > TW_MAX_SECTORS * 2048) {
635 retval = TW_IOCTL_ERROR_OS_EINVAL; 651 retval = TW_IOCTL_ERROR_OS_EINVAL;
636 goto out2; 652 goto out2;
637 } 653 }
@@ -680,13 +696,6 @@ static int twa_chrdev_ioctl(struct inode *inode, struct file *file, unsigned int
680 /* Now wait for command to complete */ 696 /* Now wait for command to complete */
681 timeout = wait_event_timeout(tw_dev->ioctl_wqueue, tw_dev->chrdev_request_id == TW_IOCTL_CHRDEV_FREE, timeout); 697 timeout = wait_event_timeout(tw_dev->ioctl_wqueue, tw_dev->chrdev_request_id == TW_IOCTL_CHRDEV_FREE, timeout);
682 698
683 /* See if we reset while waiting for the ioctl to complete */
684 if (test_bit(TW_IN_RESET, &tw_dev->flags)) {
685 clear_bit(TW_IN_RESET, &tw_dev->flags);
686 retval = TW_IOCTL_ERROR_OS_ERESTARTSYS;
687 goto out3;
688 }
689
690 /* We timed out, and didn't get an interrupt */ 699 /* We timed out, and didn't get an interrupt */
691 if (tw_dev->chrdev_request_id != TW_IOCTL_CHRDEV_FREE) { 700 if (tw_dev->chrdev_request_id != TW_IOCTL_CHRDEV_FREE) {
692 /* Now we need to reset the board */ 701 /* Now we need to reset the board */
@@ -694,11 +703,6 @@ static int twa_chrdev_ioctl(struct inode *inode, struct file *file, unsigned int
694 tw_dev->host->host_no, TW_DRIVER, 0xc, 703 tw_dev->host->host_no, TW_DRIVER, 0xc,
695 cmd); 704 cmd);
696 retval = TW_IOCTL_ERROR_OS_EIO; 705 retval = TW_IOCTL_ERROR_OS_EIO;
697 spin_lock_irqsave(tw_dev->host->host_lock, flags);
698 tw_dev->state[request_id] = TW_S_COMPLETED;
699 twa_free_request_id(tw_dev, request_id);
700 tw_dev->posted_request_count--;
701 spin_unlock_irqrestore(tw_dev->host->host_lock, flags);
702 twa_reset_device_extension(tw_dev, 1); 706 twa_reset_device_extension(tw_dev, 1);
703 goto out3; 707 goto out3;
704 } 708 }
@@ -717,16 +721,7 @@ static int twa_chrdev_ioctl(struct inode *inode, struct file *file, unsigned int
717 tw_ioctl->driver_command.status = 0; 721 tw_ioctl->driver_command.status = 0;
718 /* Copy compatiblity struct into ioctl data buffer */ 722 /* Copy compatiblity struct into ioctl data buffer */
719 tw_compat_info = (TW_Compatibility_Info *)tw_ioctl->data_buffer; 723 tw_compat_info = (TW_Compatibility_Info *)tw_ioctl->data_buffer;
720 strncpy(tw_compat_info->driver_version, TW_DRIVER_VERSION, strlen(TW_DRIVER_VERSION)); 724 memcpy(tw_compat_info, &tw_dev->tw_compat_info, sizeof(TW_Compatibility_Info));
721 tw_compat_info->working_srl = tw_dev->working_srl;
722 tw_compat_info->working_branch = tw_dev->working_branch;
723 tw_compat_info->working_build = tw_dev->working_build;
724 tw_compat_info->driver_srl_high = TW_CURRENT_DRIVER_SRL;
725 tw_compat_info->driver_branch_high = TW_CURRENT_DRIVER_BRANCH;
726 tw_compat_info->driver_build_high = TW_CURRENT_DRIVER_BUILD;
727 tw_compat_info->driver_srl_low = TW_BASE_FW_SRL;
728 tw_compat_info->driver_branch_low = TW_BASE_FW_BRANCH;
729 tw_compat_info->driver_build_low = TW_BASE_FW_BUILD;
730 break; 725 break;
731 case TW_IOCTL_GET_LAST_EVENT: 726 case TW_IOCTL_GET_LAST_EVENT:
732 if (tw_dev->event_queue_wrapped) { 727 if (tw_dev->event_queue_wrapped) {
@@ -895,7 +890,8 @@ static int twa_decode_bits(TW_Device_Extension *tw_dev, u32 status_reg_value)
895 } 890 }
896 891
897 if (status_reg_value & TW_STATUS_QUEUE_ERROR) { 892 if (status_reg_value & TW_STATUS_QUEUE_ERROR) {
898 TW_PRINTK(tw_dev->host, TW_DRIVER, 0xe, "Controller Queue Error: clearing"); 893 if ((tw_dev->tw_pci_dev->device != PCI_DEVICE_ID_3WARE_9650SE) || (!test_bit(TW_IN_RESET, &tw_dev->flags)))
894 TW_PRINTK(tw_dev->host, TW_DRIVER, 0xe, "Controller Queue Error: clearing");
899 writel(TW_CONTROL_CLEAR_QUEUE_ERROR, TW_CONTROL_REG_ADDR(tw_dev)); 895 writel(TW_CONTROL_CLEAR_QUEUE_ERROR, TW_CONTROL_REG_ADDR(tw_dev));
900 } 896 }
901 897
@@ -939,10 +935,12 @@ static int twa_empty_response_queue_large(TW_Device_Extension *tw_dev)
939 unsigned long before; 935 unsigned long before;
940 int retval = 1; 936 int retval = 1;
941 937
942 if (tw_dev->tw_pci_dev->device == PCI_DEVICE_ID_3WARE_9550SX) { 938 if ((tw_dev->tw_pci_dev->device == PCI_DEVICE_ID_3WARE_9550SX) ||
939 (tw_dev->tw_pci_dev->device == PCI_DEVICE_ID_3WARE_9650SE)) {
943 before = jiffies; 940 before = jiffies;
944 while ((response_que_value & TW_9550SX_DRAIN_COMPLETED) != TW_9550SX_DRAIN_COMPLETED) { 941 while ((response_que_value & TW_9550SX_DRAIN_COMPLETED) != TW_9550SX_DRAIN_COMPLETED) {
945 response_que_value = readl(TW_RESPONSE_QUEUE_REG_ADDR_LARGE(tw_dev)); 942 response_que_value = readl(TW_RESPONSE_QUEUE_REG_ADDR_LARGE(tw_dev));
943 msleep(1);
946 if (time_after(jiffies, before + HZ * 30)) 944 if (time_after(jiffies, before + HZ * 30))
947 goto out; 945 goto out;
948 } 946 }
@@ -1214,6 +1212,10 @@ static irqreturn_t twa_interrupt(int irq, void *dev_instance)
1214 1212
1215 handled = 1; 1213 handled = 1;
1216 1214
1215 /* If we are resetting, bail */
1216 if (test_bit(TW_IN_RESET, &tw_dev->flags))
1217 goto twa_interrupt_bail;
1218
1217 /* Check controller for errors */ 1219 /* Check controller for errors */
1218 if (twa_check_bits(status_reg_value)) { 1220 if (twa_check_bits(status_reg_value)) {
1219 if (twa_decode_bits(tw_dev, status_reg_value)) { 1221 if (twa_decode_bits(tw_dev, status_reg_value)) {
@@ -1355,8 +1357,8 @@ static void twa_load_sgl(TW_Command_Full *full_command_packet, int request_id, d
1355 1357
1356 if (TW_OP_OUT(full_command_packet->command.newcommand.opcode__reserved) == TW_OP_EXECUTE_SCSI) { 1358 if (TW_OP_OUT(full_command_packet->command.newcommand.opcode__reserved) == TW_OP_EXECUTE_SCSI) {
1357 newcommand = &full_command_packet->command.newcommand; 1359 newcommand = &full_command_packet->command.newcommand;
1358 newcommand->request_id__lunl = 1360 newcommand->request_id__lunl =
1359 TW_REQ_LUN_IN(TW_LUN_OUT(newcommand->request_id__lunl), request_id); 1361 cpu_to_le16(TW_REQ_LUN_IN(TW_LUN_OUT(newcommand->request_id__lunl), request_id));
1360 newcommand->sg_list[0].address = TW_CPU_TO_SGL(dma_handle + sizeof(TW_Ioctl_Buf_Apache) - 1); 1362 newcommand->sg_list[0].address = TW_CPU_TO_SGL(dma_handle + sizeof(TW_Ioctl_Buf_Apache) - 1);
1361 newcommand->sg_list[0].length = cpu_to_le32(length); 1363 newcommand->sg_list[0].length = cpu_to_le32(length);
1362 newcommand->sgl_entries__lunh = 1364 newcommand->sgl_entries__lunh =
@@ -1531,6 +1533,13 @@ static int twa_post_command_packet(TW_Device_Extension *tw_dev, int request_id,
1531 int retval = 1; 1533 int retval = 1;
1532 1534
1533 command_que_value = tw_dev->command_packet_phys[request_id]; 1535 command_que_value = tw_dev->command_packet_phys[request_id];
1536
1537 /* For 9650SE write low 4 bytes first */
1538 if (tw_dev->tw_pci_dev->device == PCI_DEVICE_ID_3WARE_9650SE) {
1539 command_que_value += TW_COMMAND_OFFSET;
1540 writel((u32)command_que_value, TW_COMMAND_QUEUE_REG_ADDR_LARGE(tw_dev));
1541 }
1542
1534 status_reg_value = readl(TW_STATUS_REG_ADDR(tw_dev)); 1543 status_reg_value = readl(TW_STATUS_REG_ADDR(tw_dev));
1535 1544
1536 if (twa_check_bits(status_reg_value)) 1545 if (twa_check_bits(status_reg_value))
@@ -1557,13 +1566,17 @@ static int twa_post_command_packet(TW_Device_Extension *tw_dev, int request_id,
1557 TW_UNMASK_COMMAND_INTERRUPT(tw_dev); 1566 TW_UNMASK_COMMAND_INTERRUPT(tw_dev);
1558 goto out; 1567 goto out;
1559 } else { 1568 } else {
1560 /* We successfully posted the command packet */ 1569 if (tw_dev->tw_pci_dev->device == PCI_DEVICE_ID_3WARE_9650SE) {
1561 if (sizeof(dma_addr_t) > 4) { 1570 /* Now write upper 4 bytes */
1562 command_que_value += TW_COMMAND_OFFSET; 1571 writel((u32)((u64)command_que_value >> 32), TW_COMMAND_QUEUE_REG_ADDR_LARGE(tw_dev) + 0x4);
1563 writel((u32)command_que_value, TW_COMMAND_QUEUE_REG_ADDR(tw_dev));
1564 writel((u32)((u64)command_que_value >> 32), TW_COMMAND_QUEUE_REG_ADDR(tw_dev) + 0x4);
1565 } else { 1572 } else {
1566 writel(TW_COMMAND_OFFSET + command_que_value, TW_COMMAND_QUEUE_REG_ADDR(tw_dev)); 1573 if (sizeof(dma_addr_t) > 4) {
1574 command_que_value += TW_COMMAND_OFFSET;
1575 writel((u32)command_que_value, TW_COMMAND_QUEUE_REG_ADDR(tw_dev));
1576 writel((u32)((u64)command_que_value >> 32), TW_COMMAND_QUEUE_REG_ADDR(tw_dev) + 0x4);
1577 } else {
1578 writel(TW_COMMAND_OFFSET + command_que_value, TW_COMMAND_QUEUE_REG_ADDR(tw_dev));
1579 }
1567 } 1580 }
1568 tw_dev->state[request_id] = TW_S_POSTED; 1581 tw_dev->state[request_id] = TW_S_POSTED;
1569 tw_dev->posted_request_count++; 1582 tw_dev->posted_request_count++;
@@ -1620,14 +1633,9 @@ static int twa_reset_device_extension(TW_Device_Extension *tw_dev, int ioctl_res
1620 goto out; 1633 goto out;
1621 1634
1622 TW_ENABLE_AND_CLEAR_INTERRUPTS(tw_dev); 1635 TW_ENABLE_AND_CLEAR_INTERRUPTS(tw_dev);
1636 clear_bit(TW_IN_RESET, &tw_dev->flags);
1637 tw_dev->chrdev_request_id = TW_IOCTL_CHRDEV_FREE;
1623 1638
1624 /* Wake up any ioctl that was pending before the reset */
1625 if ((tw_dev->chrdev_request_id == TW_IOCTL_CHRDEV_FREE) || (ioctl_reset)) {
1626 clear_bit(TW_IN_RESET, &tw_dev->flags);
1627 } else {
1628 tw_dev->chrdev_request_id = TW_IOCTL_CHRDEV_FREE;
1629 wake_up(&tw_dev->ioctl_wqueue);
1630 }
1631 retval = 0; 1639 retval = 0;
1632out: 1640out:
1633 return retval; 1641 return retval;
@@ -1736,6 +1744,9 @@ static int twa_scsi_eh_reset(struct scsi_cmnd *SCpnt)
1736 "WARNING: (0x%02X:0x%04X): Command (0x%x) timed out, resetting card.\n", 1744 "WARNING: (0x%02X:0x%04X): Command (0x%x) timed out, resetting card.\n",
1737 TW_DRIVER, 0x2c, SCpnt->cmnd[0]); 1745 TW_DRIVER, 0x2c, SCpnt->cmnd[0]);
1738 1746
1747 /* Make sure we are not issuing an ioctl or resetting from ioctl */
1748 mutex_lock(&tw_dev->ioctl_lock);
1749
1739 /* Now reset the card and some of the device extension data */ 1750 /* Now reset the card and some of the device extension data */
1740 if (twa_reset_device_extension(tw_dev, 0)) { 1751 if (twa_reset_device_extension(tw_dev, 0)) {
1741 TW_PRINTK(tw_dev->host, TW_DRIVER, 0x2b, "Controller reset failed during scsi host reset"); 1752 TW_PRINTK(tw_dev->host, TW_DRIVER, 0x2b, "Controller reset failed during scsi host reset");
@@ -1744,6 +1755,7 @@ static int twa_scsi_eh_reset(struct scsi_cmnd *SCpnt)
1744 1755
1745 retval = SUCCESS; 1756 retval = SUCCESS;
1746out: 1757out:
1758 mutex_unlock(&tw_dev->ioctl_lock);
1747 return retval; 1759 return retval;
1748} /* End twa_scsi_eh_reset() */ 1760} /* End twa_scsi_eh_reset() */
1749 1761
@@ -1753,8 +1765,14 @@ static int twa_scsi_queue(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd
1753 int request_id, retval; 1765 int request_id, retval;
1754 TW_Device_Extension *tw_dev = (TW_Device_Extension *)SCpnt->device->host->hostdata; 1766 TW_Device_Extension *tw_dev = (TW_Device_Extension *)SCpnt->device->host->hostdata;
1755 1767
1768 /* If we are resetting due to timed out ioctl, report as busy */
1769 if (test_bit(TW_IN_RESET, &tw_dev->flags)) {
1770 retval = SCSI_MLQUEUE_HOST_BUSY;
1771 goto out;
1772 }
1773
1756 /* Check if this FW supports luns */ 1774 /* Check if this FW supports luns */
1757 if ((SCpnt->device->lun != 0) && (tw_dev->working_srl < TW_FW_SRL_LUNS_SUPPORTED)) { 1775 if ((SCpnt->device->lun != 0) && (tw_dev->tw_compat_info.working_srl < TW_FW_SRL_LUNS_SUPPORTED)) {
1758 SCpnt->result = (DID_BAD_TARGET << 16); 1776 SCpnt->result = (DID_BAD_TARGET << 16);
1759 done(SCpnt); 1777 done(SCpnt);
1760 retval = 0; 1778 retval = 0;
@@ -1960,6 +1978,9 @@ static void __twa_shutdown(TW_Device_Extension *tw_dev)
1960 /* Disable interrupts */ 1978 /* Disable interrupts */
1961 TW_DISABLE_INTERRUPTS(tw_dev); 1979 TW_DISABLE_INTERRUPTS(tw_dev);
1962 1980
1981 /* Free up the IRQ */
1982 free_irq(tw_dev->tw_pci_dev->irq, tw_dev);
1983
1963 printk(KERN_WARNING "3w-9xxx: Shutting down host %d.\n", tw_dev->host->host_no); 1984 printk(KERN_WARNING "3w-9xxx: Shutting down host %d.\n", tw_dev->host->host_no);
1964 1985
1965 /* Tell the card we are shutting down */ 1986 /* Tell the card we are shutting down */
@@ -2091,21 +2112,25 @@ static int __devinit twa_probe(struct pci_dev *pdev, const struct pci_device_id
2091 2112
2092 /* Initialize the card */ 2113 /* Initialize the card */
2093 if (twa_reset_sequence(tw_dev, 0)) 2114 if (twa_reset_sequence(tw_dev, 0))
2094 goto out_release_mem_region; 2115 goto out_iounmap;
2095 2116
2096 /* Set host specific parameters */ 2117 /* Set host specific parameters */
2097 host->max_id = TW_MAX_UNITS; 2118 if (pdev->device == PCI_DEVICE_ID_3WARE_9650SE)
2119 host->max_id = TW_MAX_UNITS_9650SE;
2120 else
2121 host->max_id = TW_MAX_UNITS;
2122
2098 host->max_cmd_len = TW_MAX_CDB_LEN; 2123 host->max_cmd_len = TW_MAX_CDB_LEN;
2099 2124
2100 /* Channels aren't supported by adapter */ 2125 /* Channels aren't supported by adapter */
2101 host->max_lun = TW_MAX_LUNS(tw_dev->working_srl); 2126 host->max_lun = TW_MAX_LUNS(tw_dev->tw_compat_info.working_srl);
2102 host->max_channel = 0; 2127 host->max_channel = 0;
2103 2128
2104 /* Register the card with the kernel SCSI layer */ 2129 /* Register the card with the kernel SCSI layer */
2105 retval = scsi_add_host(host, &pdev->dev); 2130 retval = scsi_add_host(host, &pdev->dev);
2106 if (retval) { 2131 if (retval) {
2107 TW_PRINTK(tw_dev->host, TW_DRIVER, 0x27, "scsi add host failed"); 2132 TW_PRINTK(tw_dev->host, TW_DRIVER, 0x27, "scsi add host failed");
2108 goto out_release_mem_region; 2133 goto out_iounmap;
2109 } 2134 }
2110 2135
2111 pci_set_drvdata(pdev, host); 2136 pci_set_drvdata(pdev, host);
@@ -2145,6 +2170,8 @@ static int __devinit twa_probe(struct pci_dev *pdev, const struct pci_device_id
2145 2170
2146out_remove_host: 2171out_remove_host:
2147 scsi_remove_host(host); 2172 scsi_remove_host(host);
2173out_iounmap:
2174 iounmap(tw_dev->base_addr);
2148out_release_mem_region: 2175out_release_mem_region:
2149 pci_release_regions(pdev); 2176 pci_release_regions(pdev);
2150out_free_device_extension: 2177out_free_device_extension:
@@ -2170,12 +2197,12 @@ static void twa_remove(struct pci_dev *pdev)
2170 twa_major = -1; 2197 twa_major = -1;
2171 } 2198 }
2172 2199
2173 /* Free up the IRQ */
2174 free_irq(tw_dev->tw_pci_dev->irq, tw_dev);
2175
2176 /* Shutdown the card */ 2200 /* Shutdown the card */
2177 __twa_shutdown(tw_dev); 2201 __twa_shutdown(tw_dev);
2178 2202
2203 /* Free IO remapping */
2204 iounmap(tw_dev->base_addr);
2205
2179 /* Free up the mem region */ 2206 /* Free up the mem region */
2180 pci_release_regions(pdev); 2207 pci_release_regions(pdev);
2181 2208
@@ -2193,6 +2220,8 @@ static struct pci_device_id twa_pci_tbl[] __devinitdata = {
2193 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, 2220 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
2194 { PCI_VENDOR_ID_3WARE, PCI_DEVICE_ID_3WARE_9550SX, 2221 { PCI_VENDOR_ID_3WARE, PCI_DEVICE_ID_3WARE_9550SX,
2195 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, 2222 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
2223 { PCI_VENDOR_ID_3WARE, PCI_DEVICE_ID_3WARE_9650SE,
2224 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
2196 { } 2225 { }
2197}; 2226};
2198MODULE_DEVICE_TABLE(pci, twa_pci_tbl); 2227MODULE_DEVICE_TABLE(pci, twa_pci_tbl);
diff --git a/drivers/scsi/3w-9xxx.h b/drivers/scsi/3w-9xxx.h
index e5685be96f45..7901517d4513 100644
--- a/drivers/scsi/3w-9xxx.h
+++ b/drivers/scsi/3w-9xxx.h
@@ -289,7 +289,6 @@ static twa_message_type twa_error_table[] = {
289#define TW_STATUS_VALID_INTERRUPT 0x00DF0000 289#define TW_STATUS_VALID_INTERRUPT 0x00DF0000
290 290
291/* PCI related defines */ 291/* PCI related defines */
292#define TW_NUMDEVICES 1
293#define TW_PCI_CLEAR_PARITY_ERRORS 0xc100 292#define TW_PCI_CLEAR_PARITY_ERRORS 0xc100
294#define TW_PCI_CLEAR_PCI_ABORT 0x2000 293#define TW_PCI_CLEAR_PCI_ABORT 0x2000
295 294
@@ -335,6 +334,7 @@ static twa_message_type twa_error_table[] = {
335#define TW_ALIGNMENT_9000 4 /* 4 bytes */ 334#define TW_ALIGNMENT_9000 4 /* 4 bytes */
336#define TW_ALIGNMENT_9000_SGL 0x3 335#define TW_ALIGNMENT_9000_SGL 0x3
337#define TW_MAX_UNITS 16 336#define TW_MAX_UNITS 16
337#define TW_MAX_UNITS_9650SE 32
338#define TW_INIT_MESSAGE_CREDITS 0x100 338#define TW_INIT_MESSAGE_CREDITS 0x100
339#define TW_INIT_COMMAND_PACKET_SIZE 0x3 339#define TW_INIT_COMMAND_PACKET_SIZE 0x3
340#define TW_INIT_COMMAND_PACKET_SIZE_EXTENDED 0x6 340#define TW_INIT_COMMAND_PACKET_SIZE_EXTENDED 0x6
@@ -354,7 +354,6 @@ static twa_message_type twa_error_table[] = {
354#define TW_MAX_RESPONSE_DRAIN 256 354#define TW_MAX_RESPONSE_DRAIN 256
355#define TW_MAX_AEN_DRAIN 40 355#define TW_MAX_AEN_DRAIN 40
356#define TW_IN_RESET 2 356#define TW_IN_RESET 2
357#define TW_IN_CHRDEV_IOCTL 3
358#define TW_IN_ATTENTION_LOOP 4 357#define TW_IN_ATTENTION_LOOP 4
359#define TW_MAX_SECTORS 256 358#define TW_MAX_SECTORS 256
360#define TW_AEN_WAIT_TIME 1000 359#define TW_AEN_WAIT_TIME 1000
@@ -417,6 +416,9 @@ static twa_message_type twa_error_table[] = {
417#ifndef PCI_DEVICE_ID_3WARE_9550SX 416#ifndef PCI_DEVICE_ID_3WARE_9550SX
418#define PCI_DEVICE_ID_3WARE_9550SX 0x1003 417#define PCI_DEVICE_ID_3WARE_9550SX 0x1003
419#endif 418#endif
419#ifndef PCI_DEVICE_ID_3WARE_9650SE
420#define PCI_DEVICE_ID_3WARE_9650SE 0x1004
421#endif
420 422
421/* Bitmask macros to eliminate bitfields */ 423/* Bitmask macros to eliminate bitfields */
422 424
@@ -442,6 +444,7 @@ static twa_message_type twa_error_table[] = {
442#define TW_CONTROL_REG_ADDR(x) (x->base_addr) 444#define TW_CONTROL_REG_ADDR(x) (x->base_addr)
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))
447#define TW_COMMAND_QUEUE_REG_ADDR_LARGE(x) ((unsigned char __iomem *)x->base_addr + 0x20)
445#define TW_RESPONSE_QUEUE_REG_ADDR(x) ((unsigned char __iomem *)x->base_addr + 0xC) 448#define TW_RESPONSE_QUEUE_REG_ADDR(x) ((unsigned char __iomem *)x->base_addr + 0xC)
446#define TW_RESPONSE_QUEUE_REG_ADDR_LARGE(x) ((unsigned char __iomem *)x->base_addr + 0x30) 449#define TW_RESPONSE_QUEUE_REG_ADDR_LARGE(x) ((unsigned char __iomem *)x->base_addr + 0x30)
447#define TW_CLEAR_ALL_INTERRUPTS(x) (writel(TW_STATUS_VALID_INTERRUPT, TW_CONTROL_REG_ADDR(x))) 450#define TW_CLEAR_ALL_INTERRUPTS(x) (writel(TW_STATUS_VALID_INTERRUPT, TW_CONTROL_REG_ADDR(x)))
@@ -626,6 +629,9 @@ typedef struct TAG_TW_Compatibility_Info
626 unsigned short driver_srl_low; 629 unsigned short driver_srl_low;
627 unsigned short driver_branch_low; 630 unsigned short driver_branch_low;
628 unsigned short driver_build_low; 631 unsigned short driver_build_low;
632 unsigned short fw_on_ctlr_srl;
633 unsigned short fw_on_ctlr_branch;
634 unsigned short fw_on_ctlr_build;
629} TW_Compatibility_Info; 635} TW_Compatibility_Info;
630 636
631#pragma pack() 637#pragma pack()
@@ -668,9 +674,7 @@ typedef struct TAG_TW_Device_Extension {
668 wait_queue_head_t ioctl_wqueue; 674 wait_queue_head_t ioctl_wqueue;
669 struct mutex ioctl_lock; 675 struct mutex ioctl_lock;
670 char aen_clobber; 676 char aen_clobber;
671 unsigned short working_srl; 677 TW_Compatibility_Info tw_compat_info;
672 unsigned short working_branch;
673 unsigned short working_build;
674} TW_Device_Extension; 678} TW_Device_Extension;
675 679
676#endif /* _3W_9XXX_H */ 680#endif /* _3W_9XXX_H */