aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authoradam radford <aradford@gmail.com>2007-07-20 18:28:28 -0400
committerJames Bottomley <jejb@mulgrave.localdomain>2007-07-21 09:57:40 -0400
commit0e78d158b67fba3977f577f293c323359d80dd0e (patch)
tree539065fd92feb757e548891dbe29c481df091075 /drivers/scsi
parent6826ee4fdbe24c7aab56ce833ef94be81d190587 (diff)
[SCSI] 3w-9xxx: add support for 9690SA
The attached patch updates the 3ware 9000 driver: - Fix dma mask setting to fallback to 32-bit if 64-bit fails. - Add support for 9690SA controllers. Signed-off-by: Adam Radford <linuxraid@amcc.com> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/3w-9xxx.c67
-rw-r--r--drivers/scsi/3w-9xxx.h5
2 files changed, 45 insertions, 27 deletions
diff --git a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c
index 76c09097175f..fcad9fd73971 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"
96static TW_Device_Extension *twa_device_extension_list[TW_MAX_SLOT]; 98static TW_Device_Extension *twa_device_extension_list[TW_MAX_SLOT];
97static unsigned int twa_device_extension_count; 99static unsigned int twa_device_extension_count;
98static int twa_major = -1; 100static 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);
127static void twa_load_sgl(TW_Command_Full *full_command_packet, int request_id, dma_addr_t dma_handle, int length); 129static 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);
128static int twa_poll_response(TW_Device_Extension *tw_dev, int request_id, int seconds); 130static int twa_poll_response(TW_Device_Extension *tw_dev, int request_id, int seconds);
129static int twa_poll_status_gone(TW_Device_Extension *tw_dev, u32 flag, int seconds); 131static int twa_poll_status_gone(TW_Device_Extension *tw_dev, u32 flag, int seconds);
130static int twa_post_command_packet(TW_Device_Extension *tw_dev, int request_id, char internal); 132static int twa_post_command_packet(TW_Device_Extension *tw_dev, int request_id, char internal);
131static int twa_reset_device_extension(TW_Device_Extension *tw_dev, int ioctl_reset); 133static int twa_reset_device_extension(TW_Device_Extension *tw_dev);
132static int twa_reset_sequence(TW_Device_Extension *tw_dev, int soft_reset); 134static int twa_reset_sequence(TW_Device_Extension *tw_dev, int soft_reset);
133static int twa_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id, char *cdb, int use_sg, TW_SG_Entry *sglistarg); 135static int twa_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id, char *cdb, int use_sg, TW_SG_Entry *sglistarg);
134static void twa_scsiop_execute_scsi_complete(TW_Device_Extension *tw_dev, int request_id); 136static 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));
@@ -1196,7 +1199,6 @@ static irqreturn_t twa_interrupt(int irq, void *dev_instance)
1196 u32 status_reg_value; 1199 u32 status_reg_value;
1197 TW_Response_Queue response_que; 1200 TW_Response_Queue response_que;
1198 TW_Command_Full *full_command_packet; 1201 TW_Command_Full *full_command_packet;
1199 TW_Command *command_packet;
1200 TW_Device_Extension *tw_dev = (TW_Device_Extension *)dev_instance; 1202 TW_Device_Extension *tw_dev = (TW_Device_Extension *)dev_instance;
1201 int handled = 0; 1203 int handled = 0;
1202 1204
@@ -1274,7 +1276,6 @@ static irqreturn_t twa_interrupt(int irq, void *dev_instance)
1274 request_id = TW_RESID_OUT(response_que.response_id); 1276 request_id = TW_RESID_OUT(response_que.response_id);
1275 full_command_packet = tw_dev->command_packet_virt[request_id]; 1277 full_command_packet = tw_dev->command_packet_virt[request_id];
1276 error = 0; 1278 error = 0;
1277 command_packet = &full_command_packet->command.oldcommand;
1278 /* Check for command packet errors */ 1279 /* Check for command packet errors */
1279 if (full_command_packet->command.newcommand.status != 0) { 1280 if (full_command_packet->command.newcommand.status != 0) {
1280 if (tw_dev->srb[request_id] != 0) { 1281 if (tw_dev->srb[request_id] != 0) {
@@ -1353,11 +1354,15 @@ twa_interrupt_bail:
1353} /* End twa_interrupt() */ 1354} /* End twa_interrupt() */
1354 1355
1355/* This function will load the request id and various sgls for ioctls */ 1356/* This function will load the request id and various sgls for ioctls */
1356static void twa_load_sgl(TW_Command_Full *full_command_packet, int request_id, dma_addr_t dma_handle, int length) 1357static 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)
1357{ 1358{
1358 TW_Command *oldcommand; 1359 TW_Command *oldcommand;
1359 TW_Command_Apache *newcommand; 1360 TW_Command_Apache *newcommand;
1360 TW_SG_Entry *sgl; 1361 TW_SG_Entry *sgl;
1362 unsigned int pae = 0;
1363
1364 if ((sizeof(long) < 8) && (sizeof(dma_addr_t) > 4))
1365 pae = 1;
1361 1366
1362 if (TW_OP_OUT(full_command_packet->command.newcommand.opcode__reserved) == TW_OP_EXECUTE_SCSI) { 1367 if (TW_OP_OUT(full_command_packet->command.newcommand.opcode__reserved) == TW_OP_EXECUTE_SCSI) {
1363 newcommand = &full_command_packet->command.newcommand; 1368 newcommand = &full_command_packet->command.newcommand;
@@ -1373,12 +1378,14 @@ static void twa_load_sgl(TW_Command_Full *full_command_packet, int request_id, d
1373 1378
1374 if (TW_SGL_OUT(oldcommand->opcode__sgloffset)) { 1379 if (TW_SGL_OUT(oldcommand->opcode__sgloffset)) {
1375 /* Load the sg list */ 1380 /* Load the sg list */
1376 sgl = (TW_SG_Entry *)((u32 *)oldcommand+TW_SGL_OUT(oldcommand->opcode__sgloffset)); 1381 if (tw_dev->tw_pci_dev->device == PCI_DEVICE_ID_3WARE_9690SA)
1382 sgl = (TW_SG_Entry *)((u32 *)oldcommand+oldcommand->size - (sizeof(TW_SG_Entry)/4) + pae);
1383 else
1384 sgl = (TW_SG_Entry *)((u32 *)oldcommand+TW_SGL_OUT(oldcommand->opcode__sgloffset));
1377 sgl->address = TW_CPU_TO_SGL(dma_handle + sizeof(TW_Ioctl_Buf_Apache) - 1); 1385 sgl->address = TW_CPU_TO_SGL(dma_handle + sizeof(TW_Ioctl_Buf_Apache) - 1);
1378 sgl->length = cpu_to_le32(length); 1386 sgl->length = cpu_to_le32(length);
1379 1387
1380 if ((sizeof(long) < 8) && (sizeof(dma_addr_t) > 4)) 1388 oldcommand->size += pae;
1381 oldcommand->size += 1;
1382 } 1389 }
1383 } 1390 }
1384} /* End twa_load_sgl() */ 1391} /* End twa_load_sgl() */
@@ -1507,7 +1514,8 @@ static int twa_post_command_packet(TW_Device_Extension *tw_dev, int request_id,
1507 command_que_value = tw_dev->command_packet_phys[request_id]; 1514 command_que_value = tw_dev->command_packet_phys[request_id];
1508 1515
1509 /* For 9650SE write low 4 bytes first */ 1516 /* For 9650SE write low 4 bytes first */
1510 if (tw_dev->tw_pci_dev->device == PCI_DEVICE_ID_3WARE_9650SE) { 1517 if ((tw_dev->tw_pci_dev->device == PCI_DEVICE_ID_3WARE_9650SE) ||
1518 (tw_dev->tw_pci_dev->device == PCI_DEVICE_ID_3WARE_9690SA)) {
1511 command_que_value += TW_COMMAND_OFFSET; 1519 command_que_value += TW_COMMAND_OFFSET;
1512 writel((u32)command_que_value, TW_COMMAND_QUEUE_REG_ADDR_LARGE(tw_dev)); 1520 writel((u32)command_que_value, TW_COMMAND_QUEUE_REG_ADDR_LARGE(tw_dev));
1513 } 1521 }
@@ -1538,7 +1546,8 @@ static int twa_post_command_packet(TW_Device_Extension *tw_dev, int request_id,
1538 TW_UNMASK_COMMAND_INTERRUPT(tw_dev); 1546 TW_UNMASK_COMMAND_INTERRUPT(tw_dev);
1539 goto out; 1547 goto out;
1540 } else { 1548 } else {
1541 if (tw_dev->tw_pci_dev->device == PCI_DEVICE_ID_3WARE_9650SE) { 1549 if ((tw_dev->tw_pci_dev->device == PCI_DEVICE_ID_3WARE_9650SE) ||
1550 (tw_dev->tw_pci_dev->device == PCI_DEVICE_ID_3WARE_9690SA)) {
1542 /* Now write upper 4 bytes */ 1551 /* Now write upper 4 bytes */
1543 writel((u32)((u64)command_que_value >> 32), TW_COMMAND_QUEUE_REG_ADDR_LARGE(tw_dev) + 0x4); 1552 writel((u32)((u64)command_que_value >> 32), TW_COMMAND_QUEUE_REG_ADDR_LARGE(tw_dev) + 0x4);
1544 } else { 1553 } else {
@@ -1562,7 +1571,7 @@ out:
1562} /* End twa_post_command_packet() */ 1571} /* End twa_post_command_packet() */
1563 1572
1564/* This function will reset a device extension */ 1573/* This function will reset a device extension */
1565static int twa_reset_device_extension(TW_Device_Extension *tw_dev, int ioctl_reset) 1574static int twa_reset_device_extension(TW_Device_Extension *tw_dev)
1566{ 1575{
1567 int i = 0; 1576 int i = 0;
1568 int retval = 1; 1577 int retval = 1;
@@ -1720,7 +1729,7 @@ static int twa_scsi_eh_reset(struct scsi_cmnd *SCpnt)
1720 mutex_lock(&tw_dev->ioctl_lock); 1729 mutex_lock(&tw_dev->ioctl_lock);
1721 1730
1722 /* Now reset the card and some of the device extension data */ 1731 /* Now reset the card and some of the device extension data */
1723 if (twa_reset_device_extension(tw_dev, 0)) { 1732 if (twa_reset_device_extension(tw_dev)) {
1724 TW_PRINTK(tw_dev->host, TW_DRIVER, 0x2b, "Controller reset failed during scsi host reset"); 1733 TW_PRINTK(tw_dev->host, TW_DRIVER, 0x2b, "Controller reset failed during scsi host reset");
1725 goto out; 1734 goto out;
1726 } 1735 }
@@ -2002,11 +2011,14 @@ static int __devinit twa_probe(struct pci_dev *pdev, const struct pci_device_id
2002 2011
2003 pci_set_master(pdev); 2012 pci_set_master(pdev);
2004 2013
2005 retval = pci_set_dma_mask(pdev, sizeof(dma_addr_t) > 4 ? DMA_64BIT_MASK : DMA_32BIT_MASK); 2014 if (pci_set_dma_mask(pdev, DMA_64BIT_MASK)
2006 if (retval) { 2015 || pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK))
2007 TW_PRINTK(host, TW_DRIVER, 0x23, "Failed to set dma mask"); 2016 if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)
2008 goto out_disable_device; 2017 || pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK)) {
2009 } 2018 TW_PRINTK(host, TW_DRIVER, 0x23, "Failed to set dma mask");
2019 retval = -ENODEV;
2020 goto out_disable_device;
2021 }
2010 2022
2011 host = scsi_host_alloc(&driver_template, sizeof(TW_Device_Extension)); 2023 host = scsi_host_alloc(&driver_template, sizeof(TW_Device_Extension));
2012 if (!host) { 2024 if (!host) {
@@ -2054,7 +2066,8 @@ static int __devinit twa_probe(struct pci_dev *pdev, const struct pci_device_id
2054 goto out_iounmap; 2066 goto out_iounmap;
2055 2067
2056 /* Set host specific parameters */ 2068 /* Set host specific parameters */
2057 if (pdev->device == PCI_DEVICE_ID_3WARE_9650SE) 2069 if ((pdev->device == PCI_DEVICE_ID_3WARE_9650SE) ||
2070 (pdev->device == PCI_DEVICE_ID_3WARE_9690SA))
2058 host->max_id = TW_MAX_UNITS_9650SE; 2071 host->max_id = TW_MAX_UNITS_9650SE;
2059 else 2072 else
2060 host->max_id = TW_MAX_UNITS; 2073 host->max_id = TW_MAX_UNITS;
@@ -2161,6 +2174,8 @@ static struct pci_device_id twa_pci_tbl[] __devinitdata = {
2161 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, 2174 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
2162 { PCI_VENDOR_ID_3WARE, PCI_DEVICE_ID_3WARE_9650SE, 2175 { PCI_VENDOR_ID_3WARE, PCI_DEVICE_ID_3WARE_9650SE,
2163 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, 2176 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
2177 { PCI_VENDOR_ID_3WARE, PCI_DEVICE_ID_3WARE_9690SA,
2178 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
2164 { } 2179 { }
2165}; 2180};
2166MODULE_DEVICE_TABLE(pci, twa_pci_tbl); 2181MODULE_DEVICE_TABLE(pci, twa_pci_tbl);
diff --git a/drivers/scsi/3w-9xxx.h b/drivers/scsi/3w-9xxx.h
index 7901517d4513..d14a9479e389 100644
--- a/drivers/scsi/3w-9xxx.h
+++ b/drivers/scsi/3w-9xxx.h
@@ -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
@@ -419,6 +419,9 @@ static twa_message_type twa_error_table[] = {
419#ifndef PCI_DEVICE_ID_3WARE_9650SE 419#ifndef PCI_DEVICE_ID_3WARE_9650SE
420#define PCI_DEVICE_ID_3WARE_9650SE 0x1004 420#define PCI_DEVICE_ID_3WARE_9650SE 0x1004
421#endif 421#endif
422#ifndef PCI_DEVICE_ID_3WARE_9690SA
423#define PCI_DEVICE_ID_3WARE_9690SA 0x1005
424#endif
422 425
423/* Bitmask macros to eliminate bitfields */ 426/* Bitmask macros to eliminate bitfields */
424 427