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