Author: marcus                       Date: Thu May 31 22:23:38 2007 GMT
Module: SOURCES                       Tag: HEAD
---- Log message:
- addedd 9650 support,
patch based on file
3w-9xxx-linux-src-2.6-upstream_kernels-9.4.1.1.tgz
from 3ware drivers

---- Files affected:
SOURCES:
   linux-3w-9xxx.patch (NONE -> 1.1)  (NEW)

---- Diffs:

================================================================
Index: SOURCES/linux-3w-9xxx.patch
diff -u /dev/null SOURCES/linux-3w-9xxx.patch:1.1
--- /dev/null   Fri Jun  1 00:23:38 2007
+++ SOURCES/linux-3w-9xxx.patch Fri Jun  1 00:23:33 2007
@@ -0,0 +1,770 @@
+diff -uNr linux-2.6.16.orig/drivers/scsi/3w-9xxx.c 
linux-2.6.16/drivers/scsi/3w-9xxx.c
+--- linux-2.6.16.orig/drivers/scsi/3w-9xxx.c   2007-05-31 23:13:02.123552000 
+0200
++++ linux-2.6.16/drivers/scsi/3w-9xxx.c        2006-10-20 22:22:02.000000000 
+0200
+@@ -2,8 +2,9 @@
+    3w-9xxx.c -- 3ware 9000 Storage Controller device driver for Linux.
+ 
+    Written By: Adam Radford <[EMAIL PROTECTED]>
++   Modifications By: Tom Couch <[EMAIL PROTECTED]>
+ 
+-   Copyright (C) 2004-2005 Applied Micro Circuits Corporation.
++   Copyright (C) 2004-2006 Applied Micro Circuits Corporation.
+ 
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+@@ -62,6 +63,12 @@
+    2.26.02.003 - Correctly handle single sgl's with use_sg=1.
+    2.26.02.004 - Add support for 9550SX controllers.
+    2.26.02.005 - Fix use_sg == 0 mapping on systems with 4GB or higher.
++   2.26.02.006 - Fix 9550SX pchip reset timeout.
++                 Add big endian support.
++   2.26.02.007 - Disable local interrupts during kmap/unmap_atomic().
++   2.26.02.008 - Free irq handler in __twa_shutdown().
++                 Serialize reset code.
++                 Add support for 9650SE controllers.
+ */
+ 
+ #include <linux/module.h>
+@@ -85,7 +92,7 @@
+ #include "3w-9xxx.h"
+ 
+ /* Globals */
+-#define TW_DRIVER_VERSION "2.26.02.007"
++#define TW_DRIVER_VERSION "2.26.02.008"
+ static TW_Device_Extension *twa_device_extension_list[TW_MAX_SLOT];
+ static unsigned int twa_device_extension_count;
+ static int twa_major = -1;
+@@ -208,7 +215,7 @@
+ 
+       header = (TW_Command_Apache_Header 
*)tw_dev->generic_buffer_virt[request_id];
+       tw_dev->posted_request_count--;
+-      aen = header->status_block.error;
++      aen = le16_to_cpu(header->status_block.error);
+       full_command_packet = tw_dev->command_packet_virt[request_id];
+       command_packet = &full_command_packet->command.oldcommand;
+ 
+@@ -305,7 +312,7 @@
+ 
+               tw_dev->posted_request_count--;
+               header = (TW_Command_Apache_Header 
*)tw_dev->generic_buffer_virt[request_id];
+-              aen = header->status_block.error;
++              aen = le16_to_cpu(header->status_block.error);
+               queue = 0;
+               count++;
+ 
+@@ -365,7 +372,7 @@
+                       tw_dev->aen_clobber = 1;
+       }
+ 
+-      aen = header->status_block.error;
++      aen = le16_to_cpu(header->status_block.error);
+       memset(event, 0, sizeof(TW_Event));
+ 
+       event->severity = TW_SEV_OUT(header->status_block.severity__reserved);
+@@ -382,7 +389,7 @@
+ 
+       header->err_specific_desc[sizeof(header->err_specific_desc) - 1] = '\0';
+       event->parameter_len = strlen(header->err_specific_desc);
+-      memcpy(event->parameter_data, header->err_specific_desc, 
event->parameter_len);
++      memcpy(event->parameter_data, header->err_specific_desc, 
event->parameter_len + (error_str[0] == '\0' ? 0 : (1 + strlen(error_str))));
+       if (event->severity != TW_AEN_SEVERITY_DEBUG)
+               printk(KERN_WARNING "3w-9xxx:%s AEN: %s (0x%02X:0x%04X): 
%s:%s.\n",
+                      host,
+@@ -462,24 +469,24 @@
+       command_packet = &full_command_packet->command.oldcommand;
+       command_packet->opcode__sgloffset = TW_OPSGL_IN(2, TW_OP_SET_PARAM);
+       command_packet->request_id = request_id;
+-      command_packet->byte8_offset.param.sgl[0].address = 
tw_dev->generic_buffer_phys[request_id];
+-      command_packet->byte8_offset.param.sgl[0].length = TW_SECTOR_SIZE;
++      command_packet->byte8_offset.param.sgl[0].address = 
TW_CPU_TO_SGL(tw_dev->generic_buffer_phys[request_id]);
++      command_packet->byte8_offset.param.sgl[0].length = 
cpu_to_le32(TW_SECTOR_SIZE);
+       command_packet->size = TW_COMMAND_SIZE;
+-      command_packet->byte6_offset.parameter_count = 1;
++      command_packet->byte6_offset.parameter_count = cpu_to_le16(1);
+ 
+       /* Setup the param */
+       param = (TW_Param_Apache *)tw_dev->generic_buffer_virt[request_id];
+       memset(param, 0, TW_SECTOR_SIZE);
+-      param->table_id = TW_TIMEKEEP_TABLE | 0x8000; /* Controller time keep 
table */
+-      param->parameter_id = 0x3; /* SchedulerTime */
+-      param->parameter_size_bytes = 4;
++      param->table_id = cpu_to_le16(TW_TIMEKEEP_TABLE | 0x8000); /* 
Controller time keep table */
++      param->parameter_id = cpu_to_le16(0x3); /* SchedulerTime */
++      param->parameter_size_bytes = cpu_to_le16(4);
+ 
+       /* Convert system time in UTC to local time seconds since last 
+            Sunday 12:00AM */
+       do_gettimeofday(&utc);
+       local_time = (u32)(utc.tv_sec - (sys_tz.tz_minuteswest * 60));
+       schedulertime = local_time - (3 * 86400);
+-      schedulertime = schedulertime % 604800;
++      schedulertime = cpu_to_le32(schedulertime % 604800);
+ 
+       memcpy(param->data, &schedulertime, sizeof(u32));
+ 
+@@ -562,9 +569,9 @@
+               goto out;
+       }
+ 
+-      tw_dev->working_srl = fw_on_ctlr_srl;
+-      tw_dev->working_branch = fw_on_ctlr_branch;
+-      tw_dev->working_build = fw_on_ctlr_build;
++      tw_dev->tw_compat_info.working_srl = fw_on_ctlr_srl;
++      tw_dev->tw_compat_info.working_branch = fw_on_ctlr_branch;
++      tw_dev->tw_compat_info.working_build = fw_on_ctlr_build;
+ 
+       /* Try base mode compatibility */
+       if (!(init_connect_result & TW_CTLR_FW_COMPATIBLE)) {
+@@ -586,10 +593,23 @@
+                       }
+                       goto out;
+               }
+-              tw_dev->working_srl = TW_BASE_FW_SRL;
+-              tw_dev->working_branch = TW_BASE_FW_BRANCH;
+-              tw_dev->working_build = TW_BASE_FW_BUILD;
+-      }
++              tw_dev->tw_compat_info.working_srl = TW_BASE_FW_SRL;
++              tw_dev->tw_compat_info.working_branch = TW_BASE_FW_BRANCH;
++              tw_dev->tw_compat_info.working_build = TW_BASE_FW_BUILD;
++      }
++
++      /* Load rest of compatibility struct */
++      strncpy(tw_dev->tw_compat_info.driver_version, TW_DRIVER_VERSION, 
strlen(TW_DRIVER_VERSION));
++      tw_dev->tw_compat_info.driver_srl_high = TW_CURRENT_DRIVER_SRL;
++      tw_dev->tw_compat_info.driver_branch_high = TW_CURRENT_DRIVER_BRANCH;
++      tw_dev->tw_compat_info.driver_build_high = TW_CURRENT_DRIVER_BUILD;
++      tw_dev->tw_compat_info.driver_srl_low = TW_BASE_FW_SRL;
++      tw_dev->tw_compat_info.driver_branch_low = TW_BASE_FW_BRANCH;
++      tw_dev->tw_compat_info.driver_build_low = TW_BASE_FW_BUILD;
++      tw_dev->tw_compat_info.fw_on_ctlr_srl = fw_on_ctlr_srl;
++      tw_dev->tw_compat_info.fw_on_ctlr_branch = fw_on_ctlr_branch;
++      tw_dev->tw_compat_info.fw_on_ctlr_build = fw_on_ctlr_build;
++
+       retval = 0;
+ out:
+       return retval;
+@@ -627,7 +647,7 @@
+               goto out2;
+ 
+       /* Check data buffer size */
+-      if (driver_command.buffer_length > TW_MAX_SECTORS * 512) {
++      if (driver_command.buffer_length > TW_MAX_SECTORS * 2048) {
+               retval = TW_IOCTL_ERROR_OS_EINVAL;
+               goto out2;
+       }
+@@ -676,13 +696,6 @@
+               /* Now wait for command to complete */
+               timeout = wait_event_timeout(tw_dev->ioctl_wqueue, 
tw_dev->chrdev_request_id == TW_IOCTL_CHRDEV_FREE, timeout);
+ 
+-              /* See if we reset while waiting for the ioctl to complete */
+-              if (test_bit(TW_IN_RESET, &tw_dev->flags)) {
+-                      clear_bit(TW_IN_RESET, &tw_dev->flags);
+-                      retval = TW_IOCTL_ERROR_OS_ERESTARTSYS;
+-                      goto out3;
+-              }
+-
+               /* We timed out, and didn't get an interrupt */
+               if (tw_dev->chrdev_request_id != TW_IOCTL_CHRDEV_FREE) {
+                       /* Now we need to reset the board */
+@@ -690,11 +703,6 @@
+                              tw_dev->host->host_no, TW_DRIVER, 0xc,
+                              cmd);
+                       retval = TW_IOCTL_ERROR_OS_EIO;
+-                      spin_lock_irqsave(tw_dev->host->host_lock, flags);
+-                      tw_dev->state[request_id] = TW_S_COMPLETED;
+-                      twa_free_request_id(tw_dev, request_id);
+-                      tw_dev->posted_request_count--;
+-                      spin_unlock_irqrestore(tw_dev->host->host_lock, flags);
+                       twa_reset_device_extension(tw_dev, 1);
+                       goto out3;
+               }
+@@ -713,16 +721,7 @@
+               tw_ioctl->driver_command.status = 0;
+               /* Copy compatiblity struct into ioctl data buffer */
+               tw_compat_info = (TW_Compatibility_Info *)tw_ioctl->data_buffer;
+-              strncpy(tw_compat_info->driver_version, TW_DRIVER_VERSION, 
strlen(TW_DRIVER_VERSION));
+-              tw_compat_info->working_srl = tw_dev->working_srl;
+-              tw_compat_info->working_branch = tw_dev->working_branch;
+-              tw_compat_info->working_build = tw_dev->working_build;
+-              tw_compat_info->driver_srl_high = TW_CURRENT_DRIVER_SRL;
+-              tw_compat_info->driver_branch_high = TW_CURRENT_DRIVER_BRANCH;
+-              tw_compat_info->driver_build_high = TW_CURRENT_DRIVER_BUILD;
+-              tw_compat_info->driver_srl_low = TW_BASE_FW_SRL;
+-              tw_compat_info->driver_branch_low = TW_BASE_FW_BRANCH;
+-              tw_compat_info->driver_build_low = TW_BASE_FW_BUILD;
++              memcpy(tw_compat_info, &tw_dev->tw_compat_info, 
sizeof(TW_Compatibility_Info));
+               break;
+       case TW_IOCTL_GET_LAST_EVENT:
+               if (tw_dev->event_queue_wrapped) {
+@@ -891,7 +890,8 @@
+       }
+ 
+       if (status_reg_value & TW_STATUS_QUEUE_ERROR) {
+-              TW_PRINTK(tw_dev->host, TW_DRIVER, 0xe, "Controller Queue 
Error: clearing");
++              if ((tw_dev->tw_pci_dev->device != PCI_DEVICE_ID_3WARE_9650SE) 
|| (!test_bit(TW_IN_RESET, &tw_dev->flags)))
++                      TW_PRINTK(tw_dev->host, TW_DRIVER, 0xe, "Controller 
Queue Error: clearing");
+               writel(TW_CONTROL_CLEAR_QUEUE_ERROR, 
TW_CONTROL_REG_ADDR(tw_dev));
+       }
+ 
+@@ -931,26 +931,21 @@
+ /* This function will clear the pchip/response queue on 9550SX */
+ static int twa_empty_response_queue_large(TW_Device_Extension *tw_dev)
+ {
+-      u32 status_reg_value, response_que_value;
+-      int count = 0, retval = 1;
+-
+-      if (tw_dev->tw_pci_dev->device == PCI_DEVICE_ID_3WARE_9550SX) {
+-              status_reg_value = readl(TW_STATUS_REG_ADDR(tw_dev));
++      u32 response_que_value = 0;
++      unsigned long before;
++      int retval = 1;
+ 
+-              while (((status_reg_value & TW_STATUS_RESPONSE_QUEUE_EMPTY) == 
0) && (count < TW_MAX_RESPONSE_DRAIN)) {
++      if ((tw_dev->tw_pci_dev->device == PCI_DEVICE_ID_3WARE_9550SX) ||
++          (tw_dev->tw_pci_dev->device == PCI_DEVICE_ID_3WARE_9650SE)) {
++              before = jiffies;
++              while ((response_que_value & TW_9550SX_DRAIN_COMPLETED) != 
TW_9550SX_DRAIN_COMPLETED) {
+                       response_que_value = 
readl(TW_RESPONSE_QUEUE_REG_ADDR_LARGE(tw_dev));
+-                      if ((response_que_value & TW_9550SX_DRAIN_COMPLETED) == 
TW_9550SX_DRAIN_COMPLETED) {
+-                              /* P-chip settle time */
+-                              msleep(500);
+-                              retval = 0;
++                      msleep(1);
++                      if (time_after(jiffies, before + HZ * 30))
+                               goto out;
+-                      }
+-                      status_reg_value = readl(TW_STATUS_REG_ADDR(tw_dev));
+-                      count++;
+               }
+-              if (count == TW_MAX_RESPONSE_DRAIN)
+-                      goto out;
+-              
++              /* P-chip settle time */
++              msleep(500);
+               retval = 0;
+       } else
+               retval = 0;
+@@ -972,7 +967,7 @@
+       error_str = 
&(full_command_packet->header.err_specific_desc[strlen(full_command_packet->header.err_specific_desc)
 + 1]);
+ 
+       /* Don't print error for Logical unit not supported during rollcall */
+-      error = full_command_packet->header.status_block.error;
++      error = le16_to_cpu(full_command_packet->header.status_block.error);
+       if ((error != TW_ERROR_LOGICAL_UNIT_NOT_SUPPORTED) && (error != 
TW_ERROR_UNIT_OFFLINE)) {
+               if (print_host)
+                       printk(KERN_WARNING "3w-9xxx: scsi%d: ERROR: 
(0x%02X:0x%04X): %s:%s.\n",
+@@ -1030,7 +1025,7 @@
+       tw_dev->free_tail = (tw_dev->free_tail + 1) % TW_Q_LENGTH;
+ } /* End twa_free_request_id() */
+ 
+-/* This function will get parameter table entires from the firmware */
++/* This function will get parameter table entries from the firmware */
+ static void *twa_get_param(TW_Device_Extension *tw_dev, int request_id, int 
table_id, int parameter_id, int parameter_size_bytes)
+ {
+       TW_Command_Full *full_command_packet;
+@@ -1047,18 +1042,18 @@
+       command_packet->opcode__sgloffset = TW_OPSGL_IN(2, TW_OP_GET_PARAM);
+       command_packet->size              = TW_COMMAND_SIZE;
+       command_packet->request_id        = request_id;
+-      command_packet->byte6_offset.block_count = 1;
++      command_packet->byte6_offset.block_count = cpu_to_le16(1);
+ 
+       /* Now setup the param */
+       param = (TW_Param_Apache *)tw_dev->generic_buffer_virt[request_id];
+       memset(param, 0, TW_SECTOR_SIZE);
+-      param->table_id = table_id | 0x8000;
+-      param->parameter_id = parameter_id;
+-      param->parameter_size_bytes = parameter_size_bytes;
++      param->table_id = cpu_to_le16(table_id | 0x8000);
++      param->parameter_id = cpu_to_le16(parameter_id);
++      param->parameter_size_bytes = cpu_to_le16(parameter_size_bytes);
+       param_value = tw_dev->generic_buffer_phys[request_id];
+ 
+-      command_packet->byte8_offset.param.sgl[0].address = param_value;
+-      command_packet->byte8_offset.param.sgl[0].length = TW_SECTOR_SIZE;
++      command_packet->byte8_offset.param.sgl[0].address = 
TW_CPU_TO_SGL(param_value);
++      command_packet->byte8_offset.param.sgl[0].length = 
cpu_to_le32(TW_SECTOR_SIZE);
+ 
+       /* Post the command packet to the board */
+       twa_post_command_packet(tw_dev, request_id, 1);
+@@ -1107,18 +1102,20 @@
+       tw_initconnect = (TW_Initconnect 
*)&full_command_packet->command.oldcommand;
+       tw_initconnect->opcode__reserved = TW_OPRES_IN(0, 
TW_OP_INIT_CONNECTION);
+       tw_initconnect->request_id = request_id;
+-      tw_initconnect->message_credits = message_credits;
++      tw_initconnect->message_credits = cpu_to_le16(message_credits);
+       tw_initconnect->features = set_features;
+ 
+       /* Turn on 64-bit sgl support if we need to */
+       tw_initconnect->features |= sizeof(dma_addr_t) > 4 ? 1 : 0;
+ 
++      tw_initconnect->features = cpu_to_le32(tw_initconnect->features);
++
+       if (set_features & TW_EXTENDED_INIT_CONNECT) {
+               tw_initconnect->size = TW_INIT_COMMAND_PACKET_SIZE_EXTENDED;
+-              tw_initconnect->fw_srl = current_fw_srl;
+-              tw_initconnect->fw_arch_id = current_fw_arch_id;
+-              tw_initconnect->fw_branch = current_fw_branch;
+-              tw_initconnect->fw_build = current_fw_build;
++              tw_initconnect->fw_srl = cpu_to_le16(current_fw_srl);
++              tw_initconnect->fw_arch_id = cpu_to_le16(current_fw_arch_id);
++              tw_initconnect->fw_branch = cpu_to_le16(current_fw_branch);
++              tw_initconnect->fw_build = cpu_to_le16(current_fw_build);
+       } else 
+               tw_initconnect->size = TW_INIT_COMMAND_PACKET_SIZE;
+ 
+@@ -1130,11 +1127,11 @@
+               TW_PRINTK(tw_dev->host, TW_DRIVER, 0x15, "No valid response 
during init connection");
+       } else {
+               if (set_features & TW_EXTENDED_INIT_CONNECT) {
+-                      *fw_on_ctlr_srl = tw_initconnect->fw_srl;
+-                      *fw_on_ctlr_arch_id = tw_initconnect->fw_arch_id;
+-                      *fw_on_ctlr_branch = tw_initconnect->fw_branch;
+-                      *fw_on_ctlr_build = tw_initconnect->fw_build;
+-                      *init_connect_result = tw_initconnect->result;
++                      *fw_on_ctlr_srl = le16_to_cpu(tw_initconnect->fw_srl);
++                      *fw_on_ctlr_arch_id = 
le16_to_cpu(tw_initconnect->fw_arch_id);
++                      *fw_on_ctlr_branch = 
le16_to_cpu(tw_initconnect->fw_branch);
++                      *fw_on_ctlr_build = 
le16_to_cpu(tw_initconnect->fw_build);
++                      *init_connect_result = 
le32_to_cpu(tw_initconnect->result);
+               }
+               retval = 0;
+       }
+@@ -1193,7 +1190,7 @@
+ } /* End twa_initialize_device_extension() */
+ 
+ /* This function is the interrupt service routine */
+-static irqreturn_t twa_interrupt(int irq, void *dev_instance, struct pt_regs 
*regs)
++static irqreturn_t twa_interrupt(int irq, void *dev_instance)
+ {
+       int request_id, error = 0;
+       u32 status_reg_value;
+@@ -1215,6 +1212,10 @@
+ 
+       handled = 1;
+ 
++      /* If we are resetting, bail */
++      if (test_bit(TW_IN_RESET, &tw_dev->flags))
++              goto twa_interrupt_bail;
++
+       /* Check controller for errors */
+       if (twa_check_bits(status_reg_value)) {
+               if (twa_decode_bits(tw_dev, status_reg_value)) {
+@@ -1356,12 +1357,12 @@
+ 
+       if (TW_OP_OUT(full_command_packet->command.newcommand.opcode__reserved) 
== TW_OP_EXECUTE_SCSI) {
+               newcommand = &full_command_packet->command.newcommand;
+-              newcommand->request_id__lunl = 
+-                      TW_REQ_LUN_IN(TW_LUN_OUT(newcommand->request_id__lunl), 
request_id);
+-              newcommand->sg_list[0].address = dma_handle + 
sizeof(TW_Ioctl_Buf_Apache) - 1;
+-              newcommand->sg_list[0].length = length;
++              newcommand->request_id__lunl =
++                      
cpu_to_le16(TW_REQ_LUN_IN(TW_LUN_OUT(newcommand->request_id__lunl), 
request_id));
++              newcommand->sg_list[0].address = TW_CPU_TO_SGL(dma_handle + 
sizeof(TW_Ioctl_Buf_Apache) - 1);
++              newcommand->sg_list[0].length = cpu_to_le32(length);
+               newcommand->sgl_entries__lunh =
+-                      
TW_REQ_LUN_IN(TW_LUN_OUT(newcommand->sgl_entries__lunh), 1);
++                      
cpu_to_le16(TW_REQ_LUN_IN(TW_LUN_OUT(newcommand->sgl_entries__lunh), 1));
+       } else {
+               oldcommand = &full_command_packet->command.oldcommand;
+               oldcommand->request_id = request_id;
+@@ -1369,8 +1370,8 @@
+               if (TW_SGL_OUT(oldcommand->opcode__sgloffset)) {
+                       /* Load the sg list */
+                       sgl = (TW_SG_Entry *)((u32 
*)oldcommand+TW_SGL_OUT(oldcommand->opcode__sgloffset));
+-                      sgl->address = dma_handle + sizeof(TW_Ioctl_Buf_Apache) 
- 1;
+-                      sgl->length = length;
++                      sgl->address = TW_CPU_TO_SGL(dma_handle + 
sizeof(TW_Ioctl_Buf_Apache) - 1);
++                      sgl->length = cpu_to_le32(length);
+ 
+                       if ((sizeof(long) < 8) && (sizeof(dma_addr_t) > 4))
+                               oldcommand->size += 1;
+@@ -1389,7 +1390,7 @@
+       if (cmd->use_sg == 0)
+               goto out;
+ 
+-      use_sg = pci_map_sg(pdev, cmd->buffer, cmd->use_sg, DMA_BIDIRECTIONAL);
++      use_sg = pci_map_sg(pdev, cmd->request_buffer, cmd->use_sg, 
DMA_BIDIRECTIONAL);
+ 
+       if (use_sg == 0) {
+               TW_PRINTK(tw_dev->host, TW_DRIVER, 0x1c, "Failed to map scatter 
gather list");
+@@ -1532,6 +1533,13 @@
+       int retval = 1;
+ 
+       command_que_value = tw_dev->command_packet_phys[request_id];
++
++      /* For 9650SE write low 4 bytes first */
++      if (tw_dev->tw_pci_dev->device == PCI_DEVICE_ID_3WARE_9650SE) {
++              command_que_value += TW_COMMAND_OFFSET;
++              writel((u32)command_que_value, 
TW_COMMAND_QUEUE_REG_ADDR_LARGE(tw_dev));
++      }
++
+       status_reg_value = readl(TW_STATUS_REG_ADDR(tw_dev));
+ 
+       if (twa_check_bits(status_reg_value))
+@@ -1558,13 +1566,17 @@
+               TW_UNMASK_COMMAND_INTERRUPT(tw_dev);
+               goto out;
+       } else {
+-              /* We successfully posted the command packet */
+-              if (sizeof(dma_addr_t) > 4) {
+-                      command_que_value += TW_COMMAND_OFFSET;
+-                      writel((u32)command_que_value, 
TW_COMMAND_QUEUE_REG_ADDR(tw_dev));
+-                      writel((u32)((u64)command_que_value >> 32), 
TW_COMMAND_QUEUE_REG_ADDR(tw_dev) + 0x4);
++              if (tw_dev->tw_pci_dev->device == PCI_DEVICE_ID_3WARE_9650SE) {
++                      /* Now write upper 4 bytes */
++                      writel((u32)((u64)command_que_value >> 32), 
TW_COMMAND_QUEUE_REG_ADDR_LARGE(tw_dev) + 0x4);
+               } else {
+-                      writel(TW_COMMAND_OFFSET + command_que_value, 
TW_COMMAND_QUEUE_REG_ADDR(tw_dev));
++                      if (sizeof(dma_addr_t) > 4) {
++                              command_que_value += TW_COMMAND_OFFSET;
++                              writel((u32)command_que_value, 
TW_COMMAND_QUEUE_REG_ADDR(tw_dev));
++                              writel((u32)((u64)command_que_value >> 32), 
TW_COMMAND_QUEUE_REG_ADDR(tw_dev) + 0x4);
++                      } else {
++                              writel(TW_COMMAND_OFFSET + command_que_value, 
TW_COMMAND_QUEUE_REG_ADDR(tw_dev));
++                      }
+               }
+               tw_dev->state[request_id] = TW_S_POSTED;
+               tw_dev->posted_request_count++;
+@@ -1621,14 +1633,9 @@
+               goto out;
+ 
+       TW_ENABLE_AND_CLEAR_INTERRUPTS(tw_dev);
++      clear_bit(TW_IN_RESET, &tw_dev->flags);
++      tw_dev->chrdev_request_id = TW_IOCTL_CHRDEV_FREE;
+ 
+-      /* Wake up any ioctl that was pending before the reset */
+-      if ((tw_dev->chrdev_request_id == TW_IOCTL_CHRDEV_FREE) || 
(ioctl_reset)) {
+-              clear_bit(TW_IN_RESET, &tw_dev->flags);
+-      } else {
+-              tw_dev->chrdev_request_id = TW_IOCTL_CHRDEV_FREE;
+-              wake_up(&tw_dev->ioctl_wqueue);
+-      }
+       retval = 0;
+ out:
+       return retval;
+@@ -1737,6 +1744,9 @@
+               "WARNING: (0x%02X:0x%04X): Command (0x%x) timed out, resetting 
card.\n",
+               TW_DRIVER, 0x2c, SCpnt->cmnd[0]);
+ 
++      /* Make sure we are not issuing an ioctl or resetting from ioctl */
++      mutex_lock(&tw_dev->ioctl_lock);
++
+       /* Now reset the card and some of the device extension data */
+       if (twa_reset_device_extension(tw_dev, 0)) {
+               TW_PRINTK(tw_dev->host, TW_DRIVER, 0x2b, "Controller reset 
failed during scsi host reset");
+@@ -1745,6 +1755,7 @@
+ 
+       retval = SUCCESS;
+ out:
++      mutex_unlock(&tw_dev->ioctl_lock);
+       return retval;
+ } /* End twa_scsi_eh_reset() */
+ 
+@@ -1754,8 +1765,14 @@
+       int request_id, retval;
+       TW_Device_Extension *tw_dev = (TW_Device_Extension 
*)SCpnt->device->host->hostdata;
+ 
++      /* If we are resetting due to timed out ioctl, report as busy */
++      if (test_bit(TW_IN_RESET, &tw_dev->flags)) {
++              retval = SCSI_MLQUEUE_HOST_BUSY;
++              goto out;
++      }
++
+       /* Check if this FW supports luns */
+-      if ((SCpnt->device->lun != 0) && (tw_dev->working_srl < 
TW_FW_SRL_LUNS_SUPPORTED)) {
++      if ((SCpnt->device->lun != 0) && (tw_dev->tw_compat_info.working_srl < 
TW_FW_SRL_LUNS_SUPPORTED)) {
+               SCpnt->result = (DID_BAD_TARGET << 16);
+               done(SCpnt);
+               retval = 0;
+@@ -1828,10 +1845,10 @@
+       if (srb) {
+               command_packet->unit = srb->device->id;
+               command_packet->request_id__lunl =
+-                      TW_REQ_LUN_IN(srb->device->lun, request_id);
++                      cpu_to_le16(TW_REQ_LUN_IN(srb->device->lun, 
request_id));
+       } else {
+               command_packet->request_id__lunl =
+-                      TW_REQ_LUN_IN(0, request_id);
++                      cpu_to_le16(TW_REQ_LUN_IN(0, request_id));
+               command_packet->unit = 0;
+       }
+ 
+@@ -1841,8 +1858,8 @@
+               /* Map sglist from scsi layer to cmd packet */
+               if (tw_dev->srb[request_id]->use_sg == 0) {
+                       if (tw_dev->srb[request_id]->request_bufflen < 
TW_MIN_SGL_LENGTH) {
+-                              command_packet->sg_list[0].address = 
tw_dev->generic_buffer_phys[request_id];
+-                              command_packet->sg_list[0].length = 
TW_MIN_SGL_LENGTH;
++                              command_packet->sg_list[0].address = 
TW_CPU_TO_SGL(tw_dev->generic_buffer_phys[request_id]);
++                              command_packet->sg_list[0].length = 
cpu_to_le32(TW_MIN_SGL_LENGTH);
+                               if (tw_dev->srb[request_id]->sc_data_direction 
== DMA_TO_DEVICE || tw_dev->srb[request_id]->sc_data_direction == 
DMA_BIDIRECTIONAL)
+                                       
memcpy(tw_dev->generic_buffer_virt[request_id], 
tw_dev->srb[request_id]->request_buffer, 
tw_dev->srb[request_id]->request_bufflen);
+                       } else {
+@@ -1850,12 +1867,12 @@
+                               if (buffaddr == 0)
+                                       goto out;
+ 
+-                              command_packet->sg_list[0].address = buffaddr;
+-                              command_packet->sg_list[0].length = 
tw_dev->srb[request_id]->request_bufflen;
++                              command_packet->sg_list[0].address = 
TW_CPU_TO_SGL(buffaddr);
++                              command_packet->sg_list[0].length = 
cpu_to_le32(tw_dev->srb[request_id]->request_bufflen);
+                       }
+-                      command_packet->sgl_entries__lunh = 
TW_REQ_LUN_IN((srb->device->lun >> 4), 1);
++                      command_packet->sgl_entries__lunh = 
cpu_to_le16(TW_REQ_LUN_IN((srb->device->lun >> 4), 1));
+ 
+-                      if (command_packet->sg_list[0].address & 
TW_ALIGNMENT_9000_SGL) {
++                      if (command_packet->sg_list[0].address & 
TW_CPU_TO_SGL(TW_ALIGNMENT_9000_SGL)) {
+                               TW_PRINTK(tw_dev->host, TW_DRIVER, 0x2d, "Found 
unaligned address during execute scsi");
+                               goto out;
+                       }
+@@ -1869,35 +1886,35 @@
+                                       
memcpy(tw_dev->generic_buffer_virt[request_id], buf, sg->length);
+                                       kunmap_atomic(buf - sg->offset, 
KM_IRQ0);
+                               }
+-                              command_packet->sg_list[0].address = 
tw_dev->generic_buffer_phys[request_id];
+-                              command_packet->sg_list[0].length = 
TW_MIN_SGL_LENGTH;
++                              command_packet->sg_list[0].address = 
TW_CPU_TO_SGL(tw_dev->generic_buffer_phys[request_id]);
++                              command_packet->sg_list[0].length = 
cpu_to_le32(TW_MIN_SGL_LENGTH);
+                       } else {
+                               sg_count = twa_map_scsi_sg_data(tw_dev, 
request_id);
+                               if (sg_count == 0)
+                                       goto out;
+ 
+                               for (i = 0; i < sg_count; i++) {
+-                                      command_packet->sg_list[i].address = 
sg_dma_address(&sglist[i]);
+-                                      command_packet->sg_list[i].length = 
sg_dma_len(&sglist[i]);
+-                                      if (command_packet->sg_list[i].address 
& TW_ALIGNMENT_9000_SGL) {
++                                      command_packet->sg_list[i].address = 
TW_CPU_TO_SGL(sg_dma_address(&sglist[i]));
++                                      command_packet->sg_list[i].length = 
cpu_to_le32(sg_dma_len(&sglist[i]));
++                                      if (command_packet->sg_list[i].address 
& TW_CPU_TO_SGL(TW_ALIGNMENT_9000_SGL)) {
+                                               TW_PRINTK(tw_dev->host, 
TW_DRIVER, 0x2e, "Found unaligned sgl address during execute scsi");
+                                               goto out;
+                                       }
+                               }
+                       }
+-                      command_packet->sgl_entries__lunh = 
TW_REQ_LUN_IN((srb->device->lun >> 4), tw_dev->srb[request_id]->use_sg);
++                      command_packet->sgl_entries__lunh = 
cpu_to_le16(TW_REQ_LUN_IN((srb->device->lun >> 4), 
tw_dev->srb[request_id]->use_sg));
+               }
+       } else {
+               /* Internal cdb post */
+               for (i = 0; i < use_sg; i++) {
+-                      command_packet->sg_list[i].address = 
sglistarg[i].address;
+-                      command_packet->sg_list[i].length = sglistarg[i].length;
+-                      if (command_packet->sg_list[i].address & 
TW_ALIGNMENT_9000_SGL) {
++                      command_packet->sg_list[i].address = 
TW_CPU_TO_SGL(sglistarg[i].address);
++                      command_packet->sg_list[i].length = 
cpu_to_le32(sglistarg[i].length);
++                      if (command_packet->sg_list[i].address & 
TW_CPU_TO_SGL(TW_ALIGNMENT_9000_SGL)) {
+                               TW_PRINTK(tw_dev->host, TW_DRIVER, 0x2f, "Found 
unaligned sgl address during internal post");
+                               goto out;
+                       }
+               }
+-              command_packet->sgl_entries__lunh = TW_REQ_LUN_IN(0, use_sg);
++              command_packet->sgl_entries__lunh = 
cpu_to_le16(TW_REQ_LUN_IN(0, use_sg));
+       }
+ 
+       if (srb) {
+@@ -1961,6 +1978,9 @@
+       /* Disable interrupts */
+       TW_DISABLE_INTERRUPTS(tw_dev);
+ 
++      /* Free up the IRQ */
++      free_irq(tw_dev->tw_pci_dev->irq, tw_dev);
++
+       printk(KERN_WARNING "3w-9xxx: Shutting down host %d.\n", 
tw_dev->host->host_no);
+ 
+       /* Tell the card we are shutting down */
+@@ -2092,21 +2112,25 @@
+ 
+       /* Initialize the card */
+       if (twa_reset_sequence(tw_dev, 0))
+-              goto out_release_mem_region;
++              goto out_iounmap;
+ 
+       /* Set host specific parameters */
+-      host->max_id = TW_MAX_UNITS;
++      if (pdev->device == PCI_DEVICE_ID_3WARE_9650SE)
++              host->max_id = TW_MAX_UNITS_9650SE;
++      else
++              host->max_id = TW_MAX_UNITS;
++
+       host->max_cmd_len = TW_MAX_CDB_LEN;
<<Diff was trimmed, longer than 597 lines>>
_______________________________________________
pld-cvs-commit mailing list
[email protected]
http://lists.pld-linux.org/mailman/listinfo/pld-cvs-commit

Reply via email to