diff options
Diffstat (limited to 'drivers/scsi/3w-9xxx.c')
-rw-r--r-- | drivers/scsi/3w-9xxx.c | 67 |
1 files changed, 41 insertions, 26 deletions
diff --git a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c index 6b49f6a2524d..efd9d8d3a890 100644 --- a/drivers/scsi/3w-9xxx.c +++ b/drivers/scsi/3w-9xxx.c | |||
@@ -4,7 +4,7 @@ | |||
4 | Written By: Adam Radford <linuxraid@amcc.com> | 4 | Written By: Adam Radford <linuxraid@amcc.com> |
5 | Modifications By: Tom Couch <linuxraid@amcc.com> | 5 | Modifications By: Tom Couch <linuxraid@amcc.com> |
6 | 6 | ||
7 | Copyright (C) 2004-2006 Applied Micro Circuits Corporation. | 7 | Copyright (C) 2004-2007 Applied Micro Circuits Corporation. |
8 | 8 | ||
9 | This program is free software; you can redistribute it and/or modify | 9 | This program is free software; you can redistribute it and/or modify |
10 | it under the terms of the GNU General Public License as published by | 10 | it under the terms of the GNU General Public License as published by |
@@ -69,6 +69,8 @@ | |||
69 | 2.26.02.008 - Free irq handler in __twa_shutdown(). | 69 | 2.26.02.008 - Free irq handler in __twa_shutdown(). |
70 | Serialize reset code. | 70 | Serialize reset code. |
71 | Add support for 9650SE controllers. | 71 | Add support for 9650SE controllers. |
72 | 2.26.02.009 - Fix dma mask setting to fallback to 32-bit if 64-bit fails. | ||
73 | 2.26.02.010 - Add support for 9690SA controllers. | ||
72 | */ | 74 | */ |
73 | 75 | ||
74 | #include <linux/module.h> | 76 | #include <linux/module.h> |
@@ -92,7 +94,7 @@ | |||
92 | #include "3w-9xxx.h" | 94 | #include "3w-9xxx.h" |
93 | 95 | ||
94 | /* Globals */ | 96 | /* Globals */ |
95 | #define TW_DRIVER_VERSION "2.26.02.008" | 97 | #define TW_DRIVER_VERSION "2.26.02.010" |
96 | static TW_Device_Extension *twa_device_extension_list[TW_MAX_SLOT]; | 98 | static TW_Device_Extension *twa_device_extension_list[TW_MAX_SLOT]; |
97 | static unsigned int twa_device_extension_count; | 99 | static unsigned int twa_device_extension_count; |
98 | static int twa_major = -1; | 100 | static int twa_major = -1; |
@@ -124,11 +126,11 @@ static int twa_initconnection(TW_Device_Extension *tw_dev, int message_credits, | |||
124 | unsigned short *fw_on_ctlr_branch, | 126 | unsigned short *fw_on_ctlr_branch, |
125 | unsigned short *fw_on_ctlr_build, | 127 | unsigned short *fw_on_ctlr_build, |
126 | u32 *init_connect_result); | 128 | u32 *init_connect_result); |
127 | static void twa_load_sgl(TW_Command_Full *full_command_packet, int request_id, dma_addr_t dma_handle, int length); | 129 | static void twa_load_sgl(TW_Device_Extension *tw_dev, TW_Command_Full *full_command_packet, int request_id, dma_addr_t dma_handle, int length); |
128 | static int twa_poll_response(TW_Device_Extension *tw_dev, int request_id, int seconds); | 130 | static int twa_poll_response(TW_Device_Extension *tw_dev, int request_id, int seconds); |
129 | static int twa_poll_status_gone(TW_Device_Extension *tw_dev, u32 flag, int seconds); | 131 | static int twa_poll_status_gone(TW_Device_Extension *tw_dev, u32 flag, int seconds); |
130 | static int twa_post_command_packet(TW_Device_Extension *tw_dev, int request_id, char internal); | 132 | static int twa_post_command_packet(TW_Device_Extension *tw_dev, int request_id, char internal); |
131 | static int twa_reset_device_extension(TW_Device_Extension *tw_dev, int ioctl_reset); | 133 | static int twa_reset_device_extension(TW_Device_Extension *tw_dev); |
132 | static int twa_reset_sequence(TW_Device_Extension *tw_dev, int soft_reset); | 134 | static int twa_reset_sequence(TW_Device_Extension *tw_dev, int soft_reset); |
133 | static int twa_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id, char *cdb, int use_sg, TW_SG_Entry *sglistarg); | 135 | static int twa_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id, char *cdb, int use_sg, TW_SG_Entry *sglistarg); |
134 | static void twa_scsiop_execute_scsi_complete(TW_Device_Extension *tw_dev, int request_id); | 136 | static void twa_scsiop_execute_scsi_complete(TW_Device_Extension *tw_dev, int request_id); |
@@ -683,7 +685,7 @@ static int twa_chrdev_ioctl(struct inode *inode, struct file *file, unsigned int | |||
683 | full_command_packet = &tw_ioctl->firmware_command; | 685 | full_command_packet = &tw_ioctl->firmware_command; |
684 | 686 | ||
685 | /* Load request id and sglist for both command types */ | 687 | /* Load request id and sglist for both command types */ |
686 | twa_load_sgl(full_command_packet, request_id, dma_handle, data_buffer_length_adjusted); | 688 | twa_load_sgl(tw_dev, full_command_packet, request_id, dma_handle, data_buffer_length_adjusted); |
687 | 689 | ||
688 | memcpy(tw_dev->command_packet_virt[request_id], &(tw_ioctl->firmware_command), sizeof(TW_Command_Full)); | 690 | memcpy(tw_dev->command_packet_virt[request_id], &(tw_ioctl->firmware_command), sizeof(TW_Command_Full)); |
689 | 691 | ||
@@ -700,10 +702,10 @@ static int twa_chrdev_ioctl(struct inode *inode, struct file *file, unsigned int | |||
700 | if (tw_dev->chrdev_request_id != TW_IOCTL_CHRDEV_FREE) { | 702 | if (tw_dev->chrdev_request_id != TW_IOCTL_CHRDEV_FREE) { |
701 | /* Now we need to reset the board */ | 703 | /* Now we need to reset the board */ |
702 | printk(KERN_WARNING "3w-9xxx: scsi%d: WARNING: (0x%02X:0x%04X): Character ioctl (0x%x) timed out, resetting card.\n", | 704 | printk(KERN_WARNING "3w-9xxx: scsi%d: WARNING: (0x%02X:0x%04X): Character ioctl (0x%x) timed out, resetting card.\n", |
703 | tw_dev->host->host_no, TW_DRIVER, 0xc, | 705 | tw_dev->host->host_no, TW_DRIVER, 0x37, |
704 | cmd); | 706 | cmd); |
705 | retval = TW_IOCTL_ERROR_OS_EIO; | 707 | retval = TW_IOCTL_ERROR_OS_EIO; |
706 | twa_reset_device_extension(tw_dev, 1); | 708 | twa_reset_device_extension(tw_dev); |
707 | goto out3; | 709 | goto out3; |
708 | } | 710 | } |
709 | 711 | ||
@@ -890,7 +892,9 @@ static int twa_decode_bits(TW_Device_Extension *tw_dev, u32 status_reg_value) | |||
890 | } | 892 | } |
891 | 893 | ||
892 | if (status_reg_value & TW_STATUS_QUEUE_ERROR) { | 894 | if (status_reg_value & TW_STATUS_QUEUE_ERROR) { |
893 | if ((tw_dev->tw_pci_dev->device != PCI_DEVICE_ID_3WARE_9650SE) || (!test_bit(TW_IN_RESET, &tw_dev->flags))) | 895 | if (((tw_dev->tw_pci_dev->device != PCI_DEVICE_ID_3WARE_9650SE) && |
896 | (tw_dev->tw_pci_dev->device != PCI_DEVICE_ID_3WARE_9690SA)) || | ||
897 | (!test_bit(TW_IN_RESET, &tw_dev->flags))) | ||
894 | TW_PRINTK(tw_dev->host, TW_DRIVER, 0xe, "Controller Queue Error: clearing"); | 898 | TW_PRINTK(tw_dev->host, TW_DRIVER, 0xe, "Controller Queue Error: clearing"); |
895 | writel(TW_CONTROL_CLEAR_QUEUE_ERROR, TW_CONTROL_REG_ADDR(tw_dev)); | 899 | writel(TW_CONTROL_CLEAR_QUEUE_ERROR, TW_CONTROL_REG_ADDR(tw_dev)); |
896 | } | 900 | } |
@@ -935,8 +939,7 @@ static int twa_empty_response_queue_large(TW_Device_Extension *tw_dev) | |||
935 | unsigned long before; | 939 | unsigned long before; |
936 | int retval = 1; | 940 | int retval = 1; |
937 | 941 | ||
938 | if ((tw_dev->tw_pci_dev->device == PCI_DEVICE_ID_3WARE_9550SX) || | 942 | if (tw_dev->tw_pci_dev->device != PCI_DEVICE_ID_3WARE_9000) { |
939 | (tw_dev->tw_pci_dev->device == PCI_DEVICE_ID_3WARE_9650SE)) { | ||
940 | before = jiffies; | 943 | before = jiffies; |
941 | while ((response_que_value & TW_9550SX_DRAIN_COMPLETED) != TW_9550SX_DRAIN_COMPLETED) { | 944 | while ((response_que_value & TW_9550SX_DRAIN_COMPLETED) != TW_9550SX_DRAIN_COMPLETED) { |
942 | response_que_value = readl(TW_RESPONSE_QUEUE_REG_ADDR_LARGE(tw_dev)); | 945 | response_que_value = readl(TW_RESPONSE_QUEUE_REG_ADDR_LARGE(tw_dev)); |
@@ -1195,7 +1198,6 @@ static irqreturn_t twa_interrupt(int irq, void *dev_instance) | |||
1195 | u32 status_reg_value; | 1198 | u32 status_reg_value; |
1196 | TW_Response_Queue response_que; | 1199 | TW_Response_Queue response_que; |
1197 | TW_Command_Full *full_command_packet; | 1200 | TW_Command_Full *full_command_packet; |
1198 | TW_Command *command_packet; | ||
1199 | TW_Device_Extension *tw_dev = (TW_Device_Extension *)dev_instance; | 1201 | TW_Device_Extension *tw_dev = (TW_Device_Extension *)dev_instance; |
1200 | int handled = 0; | 1202 | int handled = 0; |
1201 | 1203 | ||
@@ -1273,7 +1275,6 @@ static irqreturn_t twa_interrupt(int irq, void *dev_instance) | |||
1273 | request_id = TW_RESID_OUT(response_que.response_id); | 1275 | request_id = TW_RESID_OUT(response_que.response_id); |
1274 | full_command_packet = tw_dev->command_packet_virt[request_id]; | 1276 | full_command_packet = tw_dev->command_packet_virt[request_id]; |
1275 | error = 0; | 1277 | error = 0; |
1276 | command_packet = &full_command_packet->command.oldcommand; | ||
1277 | /* Check for command packet errors */ | 1278 | /* Check for command packet errors */ |
1278 | if (full_command_packet->command.newcommand.status != 0) { | 1279 | if (full_command_packet->command.newcommand.status != 0) { |
1279 | if (tw_dev->srb[request_id] != 0) { | 1280 | if (tw_dev->srb[request_id] != 0) { |
@@ -1352,11 +1353,15 @@ twa_interrupt_bail: | |||
1352 | } /* End twa_interrupt() */ | 1353 | } /* End twa_interrupt() */ |
1353 | 1354 | ||
1354 | /* This function will load the request id and various sgls for ioctls */ | 1355 | /* This function will load the request id and various sgls for ioctls */ |
1355 | static void twa_load_sgl(TW_Command_Full *full_command_packet, int request_id, dma_addr_t dma_handle, int length) | 1356 | static void twa_load_sgl(TW_Device_Extension *tw_dev, TW_Command_Full *full_command_packet, int request_id, dma_addr_t dma_handle, int length) |
1356 | { | 1357 | { |
1357 | TW_Command *oldcommand; | 1358 | TW_Command *oldcommand; |
1358 | TW_Command_Apache *newcommand; | 1359 | TW_Command_Apache *newcommand; |
1359 | TW_SG_Entry *sgl; | 1360 | TW_SG_Entry *sgl; |
1361 | unsigned int pae = 0; | ||
1362 | |||
1363 | if ((sizeof(long) < 8) && (sizeof(dma_addr_t) > 4)) | ||
1364 | pae = 1; | ||
1360 | 1365 | ||
1361 | if (TW_OP_OUT(full_command_packet->command.newcommand.opcode__reserved) == TW_OP_EXECUTE_SCSI) { | 1366 | if (TW_OP_OUT(full_command_packet->command.newcommand.opcode__reserved) == TW_OP_EXECUTE_SCSI) { |
1362 | newcommand = &full_command_packet->command.newcommand; | 1367 | newcommand = &full_command_packet->command.newcommand; |
@@ -1372,12 +1377,14 @@ static void twa_load_sgl(TW_Command_Full *full_command_packet, int request_id, d | |||
1372 | 1377 | ||
1373 | if (TW_SGL_OUT(oldcommand->opcode__sgloffset)) { | 1378 | if (TW_SGL_OUT(oldcommand->opcode__sgloffset)) { |
1374 | /* Load the sg list */ | 1379 | /* Load the sg list */ |
1375 | sgl = (TW_SG_Entry *)((u32 *)oldcommand+TW_SGL_OUT(oldcommand->opcode__sgloffset)); | 1380 | if (tw_dev->tw_pci_dev->device == PCI_DEVICE_ID_3WARE_9690SA) |
1381 | sgl = (TW_SG_Entry *)((u32 *)oldcommand+oldcommand->size - (sizeof(TW_SG_Entry)/4) + pae); | ||
1382 | else | ||
1383 | sgl = (TW_SG_Entry *)((u32 *)oldcommand+TW_SGL_OUT(oldcommand->opcode__sgloffset)); | ||
1376 | sgl->address = TW_CPU_TO_SGL(dma_handle + sizeof(TW_Ioctl_Buf_Apache) - 1); | 1384 | sgl->address = TW_CPU_TO_SGL(dma_handle + sizeof(TW_Ioctl_Buf_Apache) - 1); |
1377 | sgl->length = cpu_to_le32(length); | 1385 | sgl->length = cpu_to_le32(length); |
1378 | 1386 | ||
1379 | if ((sizeof(long) < 8) && (sizeof(dma_addr_t) > 4)) | 1387 | oldcommand->size += pae; |
1380 | oldcommand->size += 1; | ||
1381 | } | 1388 | } |
1382 | } | 1389 | } |
1383 | } /* End twa_load_sgl() */ | 1390 | } /* End twa_load_sgl() */ |
@@ -1506,7 +1513,8 @@ static int twa_post_command_packet(TW_Device_Extension *tw_dev, int request_id, | |||
1506 | command_que_value = tw_dev->command_packet_phys[request_id]; | 1513 | command_que_value = tw_dev->command_packet_phys[request_id]; |
1507 | 1514 | ||
1508 | /* For 9650SE write low 4 bytes first */ | 1515 | /* For 9650SE write low 4 bytes first */ |
1509 | if (tw_dev->tw_pci_dev->device == PCI_DEVICE_ID_3WARE_9650SE) { | 1516 | if ((tw_dev->tw_pci_dev->device == PCI_DEVICE_ID_3WARE_9650SE) || |
1517 | (tw_dev->tw_pci_dev->device == PCI_DEVICE_ID_3WARE_9690SA)) { | ||
1510 | command_que_value += TW_COMMAND_OFFSET; | 1518 | command_que_value += TW_COMMAND_OFFSET; |
1511 | writel((u32)command_que_value, TW_COMMAND_QUEUE_REG_ADDR_LARGE(tw_dev)); | 1519 | writel((u32)command_que_value, TW_COMMAND_QUEUE_REG_ADDR_LARGE(tw_dev)); |
1512 | } | 1520 | } |
@@ -1537,7 +1545,8 @@ static int twa_post_command_packet(TW_Device_Extension *tw_dev, int request_id, | |||
1537 | TW_UNMASK_COMMAND_INTERRUPT(tw_dev); | 1545 | TW_UNMASK_COMMAND_INTERRUPT(tw_dev); |
1538 | goto out; | 1546 | goto out; |
1539 | } else { | 1547 | } else { |
1540 | if (tw_dev->tw_pci_dev->device == PCI_DEVICE_ID_3WARE_9650SE) { | 1548 | if ((tw_dev->tw_pci_dev->device == PCI_DEVICE_ID_3WARE_9650SE) || |
1549 | (tw_dev->tw_pci_dev->device == PCI_DEVICE_ID_3WARE_9690SA)) { | ||
1541 | /* Now write upper 4 bytes */ | 1550 | /* Now write upper 4 bytes */ |
1542 | writel((u32)((u64)command_que_value >> 32), TW_COMMAND_QUEUE_REG_ADDR_LARGE(tw_dev) + 0x4); | 1551 | writel((u32)((u64)command_que_value >> 32), TW_COMMAND_QUEUE_REG_ADDR_LARGE(tw_dev) + 0x4); |
1543 | } else { | 1552 | } else { |
@@ -1561,7 +1570,7 @@ out: | |||
1561 | } /* End twa_post_command_packet() */ | 1570 | } /* End twa_post_command_packet() */ |
1562 | 1571 | ||
1563 | /* This function will reset a device extension */ | 1572 | /* This function will reset a device extension */ |
1564 | static int twa_reset_device_extension(TW_Device_Extension *tw_dev, int ioctl_reset) | 1573 | static int twa_reset_device_extension(TW_Device_Extension *tw_dev) |
1565 | { | 1574 | { |
1566 | int i = 0; | 1575 | int i = 0; |
1567 | int retval = 1; | 1576 | int retval = 1; |
@@ -1719,7 +1728,7 @@ static int twa_scsi_eh_reset(struct scsi_cmnd *SCpnt) | |||
1719 | mutex_lock(&tw_dev->ioctl_lock); | 1728 | mutex_lock(&tw_dev->ioctl_lock); |
1720 | 1729 | ||
1721 | /* Now reset the card and some of the device extension data */ | 1730 | /* Now reset the card and some of the device extension data */ |
1722 | if (twa_reset_device_extension(tw_dev, 0)) { | 1731 | if (twa_reset_device_extension(tw_dev)) { |
1723 | TW_PRINTK(tw_dev->host, TW_DRIVER, 0x2b, "Controller reset failed during scsi host reset"); | 1732 | TW_PRINTK(tw_dev->host, TW_DRIVER, 0x2b, "Controller reset failed during scsi host reset"); |
1724 | goto out; | 1733 | goto out; |
1725 | } | 1734 | } |
@@ -2001,11 +2010,14 @@ static int __devinit twa_probe(struct pci_dev *pdev, const struct pci_device_id | |||
2001 | 2010 | ||
2002 | pci_set_master(pdev); | 2011 | pci_set_master(pdev); |
2003 | 2012 | ||
2004 | retval = pci_set_dma_mask(pdev, sizeof(dma_addr_t) > 4 ? DMA_64BIT_MASK : DMA_32BIT_MASK); | 2013 | if (pci_set_dma_mask(pdev, DMA_64BIT_MASK) |
2005 | if (retval) { | 2014 | || pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK)) |
2006 | TW_PRINTK(host, TW_DRIVER, 0x23, "Failed to set dma mask"); | 2015 | if (pci_set_dma_mask(pdev, DMA_32BIT_MASK) |
2007 | goto out_disable_device; | 2016 | || pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK)) { |
2008 | } | 2017 | TW_PRINTK(host, TW_DRIVER, 0x23, "Failed to set dma mask"); |
2018 | retval = -ENODEV; | ||
2019 | goto out_disable_device; | ||
2020 | } | ||
2009 | 2021 | ||
2010 | host = scsi_host_alloc(&driver_template, sizeof(TW_Device_Extension)); | 2022 | host = scsi_host_alloc(&driver_template, sizeof(TW_Device_Extension)); |
2011 | if (!host) { | 2023 | if (!host) { |
@@ -2053,7 +2065,8 @@ static int __devinit twa_probe(struct pci_dev *pdev, const struct pci_device_id | |||
2053 | goto out_iounmap; | 2065 | goto out_iounmap; |
2054 | 2066 | ||
2055 | /* Set host specific parameters */ | 2067 | /* Set host specific parameters */ |
2056 | if (pdev->device == PCI_DEVICE_ID_3WARE_9650SE) | 2068 | if ((pdev->device == PCI_DEVICE_ID_3WARE_9650SE) || |
2069 | (pdev->device == PCI_DEVICE_ID_3WARE_9690SA)) | ||
2057 | host->max_id = TW_MAX_UNITS_9650SE; | 2070 | host->max_id = TW_MAX_UNITS_9650SE; |
2058 | else | 2071 | else |
2059 | host->max_id = TW_MAX_UNITS; | 2072 | host->max_id = TW_MAX_UNITS; |
@@ -2160,6 +2173,8 @@ static struct pci_device_id twa_pci_tbl[] __devinitdata = { | |||
2160 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, | 2173 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, |
2161 | { PCI_VENDOR_ID_3WARE, PCI_DEVICE_ID_3WARE_9650SE, | 2174 | { PCI_VENDOR_ID_3WARE, PCI_DEVICE_ID_3WARE_9650SE, |
2162 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, | 2175 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, |
2176 | { PCI_VENDOR_ID_3WARE, PCI_DEVICE_ID_3WARE_9690SA, | ||
2177 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, | ||
2163 | { } | 2178 | { } |
2164 | }; | 2179 | }; |
2165 | MODULE_DEVICE_TABLE(pci, twa_pci_tbl); | 2180 | MODULE_DEVICE_TABLE(pci, twa_pci_tbl); |