[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>

authored by adam radford and committed by James Bottomley 0e78d158 6826ee4f

+45 -27
+41 -26
drivers/scsi/3w-9xxx.c
··· 4 Written By: Adam Radford <linuxraid@amcc.com> 5 Modifications By: Tom Couch <linuxraid@amcc.com> 6 7 - Copyright (C) 2004-2006 Applied Micro Circuits Corporation. 8 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 ··· 69 2.26.02.008 - Free irq handler in __twa_shutdown(). 70 Serialize reset code. 71 Add support for 9650SE controllers. 72 */ 73 74 #include <linux/module.h> ··· 94 #include "3w-9xxx.h" 95 96 /* Globals */ 97 - #define TW_DRIVER_VERSION "2.26.02.008" 98 static TW_Device_Extension *twa_device_extension_list[TW_MAX_SLOT]; 99 static unsigned int twa_device_extension_count; 100 static int twa_major = -1; ··· 126 unsigned short *fw_on_ctlr_branch, 127 unsigned short *fw_on_ctlr_build, 128 u32 *init_connect_result); 129 - static void twa_load_sgl(TW_Command_Full *full_command_packet, int request_id, dma_addr_t dma_handle, int length); 130 static int twa_poll_response(TW_Device_Extension *tw_dev, int request_id, int seconds); 131 static int twa_poll_status_gone(TW_Device_Extension *tw_dev, u32 flag, int seconds); 132 static int twa_post_command_packet(TW_Device_Extension *tw_dev, int request_id, char internal); 133 - static int twa_reset_device_extension(TW_Device_Extension *tw_dev, int ioctl_reset); 134 static int twa_reset_sequence(TW_Device_Extension *tw_dev, int soft_reset); 135 static int twa_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id, char *cdb, int use_sg, TW_SG_Entry *sglistarg); 136 static void twa_scsiop_execute_scsi_complete(TW_Device_Extension *tw_dev, int request_id); ··· 685 full_command_packet = &tw_ioctl->firmware_command; 686 687 /* Load request id and sglist for both command types */ 688 - twa_load_sgl(full_command_packet, request_id, dma_handle, data_buffer_length_adjusted); 689 690 memcpy(tw_dev->command_packet_virt[request_id], &(tw_ioctl->firmware_command), sizeof(TW_Command_Full)); 691 ··· 702 if (tw_dev->chrdev_request_id != TW_IOCTL_CHRDEV_FREE) { 703 /* Now we need to reset the board */ 704 printk(KERN_WARNING "3w-9xxx: scsi%d: WARNING: (0x%02X:0x%04X): Character ioctl (0x%x) timed out, resetting card.\n", 705 - tw_dev->host->host_no, TW_DRIVER, 0xc, 706 cmd); 707 retval = TW_IOCTL_ERROR_OS_EIO; 708 - twa_reset_device_extension(tw_dev, 1); 709 goto out3; 710 } 711 ··· 892 } 893 894 if (status_reg_value & TW_STATUS_QUEUE_ERROR) { 895 - if ((tw_dev->tw_pci_dev->device != PCI_DEVICE_ID_3WARE_9650SE) || (!test_bit(TW_IN_RESET, &tw_dev->flags))) 896 TW_PRINTK(tw_dev->host, TW_DRIVER, 0xe, "Controller Queue Error: clearing"); 897 writel(TW_CONTROL_CLEAR_QUEUE_ERROR, TW_CONTROL_REG_ADDR(tw_dev)); 898 } ··· 939 unsigned long before; 940 int retval = 1; 941 942 - if ((tw_dev->tw_pci_dev->device == PCI_DEVICE_ID_3WARE_9550SX) || 943 - (tw_dev->tw_pci_dev->device == PCI_DEVICE_ID_3WARE_9650SE)) { 944 before = jiffies; 945 while ((response_que_value & TW_9550SX_DRAIN_COMPLETED) != TW_9550SX_DRAIN_COMPLETED) { 946 response_que_value = readl(TW_RESPONSE_QUEUE_REG_ADDR_LARGE(tw_dev)); ··· 1199 u32 status_reg_value; 1200 TW_Response_Queue response_que; 1201 TW_Command_Full *full_command_packet; 1202 - TW_Command *command_packet; 1203 TW_Device_Extension *tw_dev = (TW_Device_Extension *)dev_instance; 1204 int handled = 0; 1205 ··· 1276 request_id = TW_RESID_OUT(response_que.response_id); 1277 full_command_packet = tw_dev->command_packet_virt[request_id]; 1278 error = 0; 1279 - command_packet = &full_command_packet->command.oldcommand; 1280 /* Check for command packet errors */ 1281 if (full_command_packet->command.newcommand.status != 0) { 1282 if (tw_dev->srb[request_id] != 0) { ··· 1354 } /* End twa_interrupt() */ 1355 1356 /* This function will load the request id and various sgls for ioctls */ 1357 - static void twa_load_sgl(TW_Command_Full *full_command_packet, int request_id, dma_addr_t dma_handle, int length) 1358 { 1359 TW_Command *oldcommand; 1360 TW_Command_Apache *newcommand; 1361 TW_SG_Entry *sgl; 1362 1363 if (TW_OP_OUT(full_command_packet->command.newcommand.opcode__reserved) == TW_OP_EXECUTE_SCSI) { 1364 newcommand = &full_command_packet->command.newcommand; ··· 1378 1379 if (TW_SGL_OUT(oldcommand->opcode__sgloffset)) { 1380 /* Load the sg list */ 1381 - sgl = (TW_SG_Entry *)((u32 *)oldcommand+TW_SGL_OUT(oldcommand->opcode__sgloffset)); 1382 sgl->address = TW_CPU_TO_SGL(dma_handle + sizeof(TW_Ioctl_Buf_Apache) - 1); 1383 sgl->length = cpu_to_le32(length); 1384 1385 - if ((sizeof(long) < 8) && (sizeof(dma_addr_t) > 4)) 1386 - oldcommand->size += 1; 1387 } 1388 } 1389 } /* End twa_load_sgl() */ ··· 1514 command_que_value = tw_dev->command_packet_phys[request_id]; 1515 1516 /* For 9650SE write low 4 bytes first */ 1517 - if (tw_dev->tw_pci_dev->device == PCI_DEVICE_ID_3WARE_9650SE) { 1518 command_que_value += TW_COMMAND_OFFSET; 1519 writel((u32)command_que_value, TW_COMMAND_QUEUE_REG_ADDR_LARGE(tw_dev)); 1520 } ··· 1546 TW_UNMASK_COMMAND_INTERRUPT(tw_dev); 1547 goto out; 1548 } else { 1549 - if (tw_dev->tw_pci_dev->device == PCI_DEVICE_ID_3WARE_9650SE) { 1550 /* Now write upper 4 bytes */ 1551 writel((u32)((u64)command_que_value >> 32), TW_COMMAND_QUEUE_REG_ADDR_LARGE(tw_dev) + 0x4); 1552 } else { ··· 1571 } /* End twa_post_command_packet() */ 1572 1573 /* This function will reset a device extension */ 1574 - static int twa_reset_device_extension(TW_Device_Extension *tw_dev, int ioctl_reset) 1575 { 1576 int i = 0; 1577 int retval = 1; ··· 1729 mutex_lock(&tw_dev->ioctl_lock); 1730 1731 /* Now reset the card and some of the device extension data */ 1732 - if (twa_reset_device_extension(tw_dev, 0)) { 1733 TW_PRINTK(tw_dev->host, TW_DRIVER, 0x2b, "Controller reset failed during scsi host reset"); 1734 goto out; 1735 } ··· 2011 2012 pci_set_master(pdev); 2013 2014 - retval = pci_set_dma_mask(pdev, sizeof(dma_addr_t) > 4 ? DMA_64BIT_MASK : DMA_32BIT_MASK); 2015 - if (retval) { 2016 - TW_PRINTK(host, TW_DRIVER, 0x23, "Failed to set dma mask"); 2017 - goto out_disable_device; 2018 - } 2019 2020 host = scsi_host_alloc(&driver_template, sizeof(TW_Device_Extension)); 2021 if (!host) { ··· 2066 goto out_iounmap; 2067 2068 /* Set host specific parameters */ 2069 - if (pdev->device == PCI_DEVICE_ID_3WARE_9650SE) 2070 host->max_id = TW_MAX_UNITS_9650SE; 2071 else 2072 host->max_id = TW_MAX_UNITS; ··· 2173 { PCI_VENDOR_ID_3WARE, PCI_DEVICE_ID_3WARE_9550SX, 2174 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, 2175 { PCI_VENDOR_ID_3WARE, PCI_DEVICE_ID_3WARE_9650SE, 2176 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, 2177 { } 2178 };
··· 4 Written By: Adam Radford <linuxraid@amcc.com> 5 Modifications By: Tom Couch <linuxraid@amcc.com> 6 7 + Copyright (C) 2004-2007 Applied Micro Circuits Corporation. 8 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 ··· 69 2.26.02.008 - Free irq handler in __twa_shutdown(). 70 Serialize reset code. 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. 74 */ 75 76 #include <linux/module.h> ··· 92 #include "3w-9xxx.h" 93 94 /* Globals */ 95 + #define TW_DRIVER_VERSION "2.26.02.010" 96 static TW_Device_Extension *twa_device_extension_list[TW_MAX_SLOT]; 97 static unsigned int twa_device_extension_count; 98 static int twa_major = -1; ··· 124 unsigned short *fw_on_ctlr_branch, 125 unsigned short *fw_on_ctlr_build, 126 u32 *init_connect_result); 127 + 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); 129 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); 131 + 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); 133 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); ··· 683 full_command_packet = &tw_ioctl->firmware_command; 684 685 /* Load request id and sglist for both command types */ 686 + twa_load_sgl(tw_dev, full_command_packet, request_id, dma_handle, data_buffer_length_adjusted); 687 688 memcpy(tw_dev->command_packet_virt[request_id], &(tw_ioctl->firmware_command), sizeof(TW_Command_Full)); 689 ··· 700 if (tw_dev->chrdev_request_id != TW_IOCTL_CHRDEV_FREE) { 701 /* 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", 703 + tw_dev->host->host_no, TW_DRIVER, 0x37, 704 cmd); 705 retval = TW_IOCTL_ERROR_OS_EIO; 706 + twa_reset_device_extension(tw_dev); 707 goto out3; 708 } 709 ··· 890 } 891 892 if (status_reg_value & TW_STATUS_QUEUE_ERROR) { 893 + if (((tw_dev->tw_pci_dev->device != PCI_DEVICE_ID_3WARE_9650SE) && 894 + (tw_dev->tw_pci_dev->device != PCI_DEVICE_ID_3WARE_9690SA)) || 895 + (!test_bit(TW_IN_RESET, &tw_dev->flags))) 896 TW_PRINTK(tw_dev->host, TW_DRIVER, 0xe, "Controller Queue Error: clearing"); 897 writel(TW_CONTROL_CLEAR_QUEUE_ERROR, TW_CONTROL_REG_ADDR(tw_dev)); 898 } ··· 935 unsigned long before; 936 int retval = 1; 937 938 + if (tw_dev->tw_pci_dev->device != PCI_DEVICE_ID_3WARE_9000) { 939 before = jiffies; 940 while ((response_que_value & TW_9550SX_DRAIN_COMPLETED) != TW_9550SX_DRAIN_COMPLETED) { 941 response_que_value = readl(TW_RESPONSE_QUEUE_REG_ADDR_LARGE(tw_dev)); ··· 1196 u32 status_reg_value; 1197 TW_Response_Queue response_que; 1198 TW_Command_Full *full_command_packet; 1199 TW_Device_Extension *tw_dev = (TW_Device_Extension *)dev_instance; 1200 int handled = 0; 1201 ··· 1274 request_id = TW_RESID_OUT(response_que.response_id); 1275 full_command_packet = tw_dev->command_packet_virt[request_id]; 1276 error = 0; 1277 /* Check for command packet errors */ 1278 if (full_command_packet->command.newcommand.status != 0) { 1279 if (tw_dev->srb[request_id] != 0) { ··· 1353 } /* End twa_interrupt() */ 1354 1355 /* This function will load the request id and various sgls for ioctls */ 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) 1357 { 1358 TW_Command *oldcommand; 1359 TW_Command_Apache *newcommand; 1360 TW_SG_Entry *sgl; 1361 + unsigned int pae = 0; 1362 + 1363 + if ((sizeof(long) < 8) && (sizeof(dma_addr_t) > 4)) 1364 + pae = 1; 1365 1366 if (TW_OP_OUT(full_command_packet->command.newcommand.opcode__reserved) == TW_OP_EXECUTE_SCSI) { 1367 newcommand = &full_command_packet->command.newcommand; ··· 1373 1374 if (TW_SGL_OUT(oldcommand->opcode__sgloffset)) { 1375 /* Load the sg list */ 1376 + if (tw_dev->tw_pci_dev->device == PCI_DEVICE_ID_3WARE_9690SA) 1377 + sgl = (TW_SG_Entry *)((u32 *)oldcommand+oldcommand->size - (sizeof(TW_SG_Entry)/4) + pae); 1378 + else 1379 + sgl = (TW_SG_Entry *)((u32 *)oldcommand+TW_SGL_OUT(oldcommand->opcode__sgloffset)); 1380 sgl->address = TW_CPU_TO_SGL(dma_handle + sizeof(TW_Ioctl_Buf_Apache) - 1); 1381 sgl->length = cpu_to_le32(length); 1382 1383 + oldcommand->size += pae; 1384 } 1385 } 1386 } /* End twa_load_sgl() */ ··· 1507 command_que_value = tw_dev->command_packet_phys[request_id]; 1508 1509 /* For 9650SE write low 4 bytes first */ 1510 + if ((tw_dev->tw_pci_dev->device == PCI_DEVICE_ID_3WARE_9650SE) || 1511 + (tw_dev->tw_pci_dev->device == PCI_DEVICE_ID_3WARE_9690SA)) { 1512 command_que_value += TW_COMMAND_OFFSET; 1513 writel((u32)command_que_value, TW_COMMAND_QUEUE_REG_ADDR_LARGE(tw_dev)); 1514 } ··· 1538 TW_UNMASK_COMMAND_INTERRUPT(tw_dev); 1539 goto out; 1540 } else { 1541 + if ((tw_dev->tw_pci_dev->device == PCI_DEVICE_ID_3WARE_9650SE) || 1542 + (tw_dev->tw_pci_dev->device == PCI_DEVICE_ID_3WARE_9690SA)) { 1543 /* Now write upper 4 bytes */ 1544 writel((u32)((u64)command_que_value >> 32), TW_COMMAND_QUEUE_REG_ADDR_LARGE(tw_dev) + 0x4); 1545 } else { ··· 1562 } /* End twa_post_command_packet() */ 1563 1564 /* This function will reset a device extension */ 1565 + static int twa_reset_device_extension(TW_Device_Extension *tw_dev) 1566 { 1567 int i = 0; 1568 int retval = 1; ··· 1720 mutex_lock(&tw_dev->ioctl_lock); 1721 1722 /* Now reset the card and some of the device extension data */ 1723 + if (twa_reset_device_extension(tw_dev)) { 1724 TW_PRINTK(tw_dev->host, TW_DRIVER, 0x2b, "Controller reset failed during scsi host reset"); 1725 goto out; 1726 } ··· 2002 2003 pci_set_master(pdev); 2004 2005 + if (pci_set_dma_mask(pdev, DMA_64BIT_MASK) 2006 + || pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK)) 2007 + if (pci_set_dma_mask(pdev, DMA_32BIT_MASK) 2008 + || pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK)) { 2009 + TW_PRINTK(host, TW_DRIVER, 0x23, "Failed to set dma mask"); 2010 + retval = -ENODEV; 2011 + goto out_disable_device; 2012 + } 2013 2014 host = scsi_host_alloc(&driver_template, sizeof(TW_Device_Extension)); 2015 if (!host) { ··· 2054 goto out_iounmap; 2055 2056 /* Set host specific parameters */ 2057 + if ((pdev->device == PCI_DEVICE_ID_3WARE_9650SE) || 2058 + (pdev->device == PCI_DEVICE_ID_3WARE_9690SA)) 2059 host->max_id = TW_MAX_UNITS_9650SE; 2060 else 2061 host->max_id = TW_MAX_UNITS; ··· 2160 { PCI_VENDOR_ID_3WARE, PCI_DEVICE_ID_3WARE_9550SX, 2161 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, 2162 { PCI_VENDOR_ID_3WARE, PCI_DEVICE_ID_3WARE_9650SE, 2163 + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, 2164 + { PCI_VENDOR_ID_3WARE, PCI_DEVICE_ID_3WARE_9690SA, 2165 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, 2166 { } 2167 };
+4 -1
drivers/scsi/3w-9xxx.h
··· 4 Written By: Adam Radford <linuxraid@amcc.com> 5 Modifications By: Tom Couch <linuxraid@amcc.com> 6 7 - Copyright (C) 2004-2006 Applied Micro Circuits Corporation. 8 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 ··· 418 #endif 419 #ifndef PCI_DEVICE_ID_3WARE_9650SE 420 #define PCI_DEVICE_ID_3WARE_9650SE 0x1004 421 #endif 422 423 /* Bitmask macros to eliminate bitfields */
··· 4 Written By: Adam Radford <linuxraid@amcc.com> 5 Modifications By: Tom Couch <linuxraid@amcc.com> 6 7 + Copyright (C) 2004-2007 Applied Micro Circuits Corporation. 8 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 ··· 418 #endif 419 #ifndef PCI_DEVICE_ID_3WARE_9650SE 420 #define PCI_DEVICE_ID_3WARE_9650SE 0x1004 421 + #endif 422 + #ifndef PCI_DEVICE_ID_3WARE_9690SA 423 + #define PCI_DEVICE_ID_3WARE_9690SA 0x1005 424 #endif 425 426 /* Bitmask macros to eliminate bitfields */