]> git.pld-linux.org Git - packages/kernel.git/blob - linux-3w-9xxx.patch
- release 4
[packages/kernel.git] / linux-3w-9xxx.patch
1 diff -uNr linux-2.6.16.orig/drivers/scsi/3w-9xxx.c linux-2.6.16/drivers/scsi/3w-9xxx.c
2 --- linux-2.6.16.orig/drivers/scsi/3w-9xxx.c    2007-05-31 23:13:02.123552000 +0200
3 +++ linux-2.6.16/drivers/scsi/3w-9xxx.c 2006-10-20 22:22:02.000000000 +0200
4 @@ -2,8 +2,9 @@
5     3w-9xxx.c -- 3ware 9000 Storage Controller device driver for Linux.
6  
7     Written By: Adam Radford <linuxraid@amcc.com>
8 +   Modifications By: Tom Couch <linuxraid@amcc.com>
9  
10 -   Copyright (C) 2004-2005 Applied Micro Circuits Corporation.
11 +   Copyright (C) 2004-2006 Applied Micro Circuits Corporation.
12  
13     This program is free software; you can redistribute it and/or modify
14     it under the terms of the GNU General Public License as published by
15 @@ -62,6 +63,12 @@
16     2.26.02.003 - Correctly handle single sgl's with use_sg=1.
17     2.26.02.004 - Add support for 9550SX controllers.
18     2.26.02.005 - Fix use_sg == 0 mapping on systems with 4GB or higher.
19 +   2.26.02.006 - Fix 9550SX pchip reset timeout.
20 +                 Add big endian support.
21 +   2.26.02.007 - Disable local interrupts during kmap/unmap_atomic().
22 +   2.26.02.008 - Free irq handler in __twa_shutdown().
23 +                 Serialize reset code.
24 +                 Add support for 9650SE controllers.
25  */
26  
27  #include <linux/module.h>
28 @@ -85,7 +92,7 @@
29  #include "3w-9xxx.h"
30  
31  /* Globals */
32 -#define TW_DRIVER_VERSION "2.26.02.007"
33 +#define TW_DRIVER_VERSION "2.26.02.008"
34  static TW_Device_Extension *twa_device_extension_list[TW_MAX_SLOT];
35  static unsigned int twa_device_extension_count;
36  static int twa_major = -1;
37 @@ -208,7 +215,7 @@
38  
39         header = (TW_Command_Apache_Header *)tw_dev->generic_buffer_virt[request_id];
40         tw_dev->posted_request_count--;
41 -       aen = header->status_block.error;
42 +       aen = le16_to_cpu(header->status_block.error);
43         full_command_packet = tw_dev->command_packet_virt[request_id];
44         command_packet = &full_command_packet->command.oldcommand;
45  
46 @@ -305,7 +312,7 @@
47  
48                 tw_dev->posted_request_count--;
49                 header = (TW_Command_Apache_Header *)tw_dev->generic_buffer_virt[request_id];
50 -               aen = header->status_block.error;
51 +               aen = le16_to_cpu(header->status_block.error);
52                 queue = 0;
53                 count++;
54  
55 @@ -365,7 +372,7 @@
56                         tw_dev->aen_clobber = 1;
57         }
58  
59 -       aen = header->status_block.error;
60 +       aen = le16_to_cpu(header->status_block.error);
61         memset(event, 0, sizeof(TW_Event));
62  
63         event->severity = TW_SEV_OUT(header->status_block.severity__reserved);
64 @@ -382,7 +389,7 @@
65  
66         header->err_specific_desc[sizeof(header->err_specific_desc) - 1] = '\0';
67         event->parameter_len = strlen(header->err_specific_desc);
68 -       memcpy(event->parameter_data, header->err_specific_desc, event->parameter_len);
69 +       memcpy(event->parameter_data, header->err_specific_desc, event->parameter_len + (error_str[0] == '\0' ? 0 : (1 + strlen(error_str))));
70         if (event->severity != TW_AEN_SEVERITY_DEBUG)
71                 printk(KERN_WARNING "3w-9xxx:%s AEN: %s (0x%02X:0x%04X): %s:%s.\n",
72                        host,
73 @@ -462,24 +469,24 @@
74         command_packet = &full_command_packet->command.oldcommand;
75         command_packet->opcode__sgloffset = TW_OPSGL_IN(2, TW_OP_SET_PARAM);
76         command_packet->request_id = request_id;
77 -       command_packet->byte8_offset.param.sgl[0].address = tw_dev->generic_buffer_phys[request_id];
78 -       command_packet->byte8_offset.param.sgl[0].length = TW_SECTOR_SIZE;
79 +       command_packet->byte8_offset.param.sgl[0].address = TW_CPU_TO_SGL(tw_dev->generic_buffer_phys[request_id]);
80 +       command_packet->byte8_offset.param.sgl[0].length = cpu_to_le32(TW_SECTOR_SIZE);
81         command_packet->size = TW_COMMAND_SIZE;
82 -       command_packet->byte6_offset.parameter_count = 1;
83 +       command_packet->byte6_offset.parameter_count = cpu_to_le16(1);
84  
85         /* Setup the param */
86         param = (TW_Param_Apache *)tw_dev->generic_buffer_virt[request_id];
87         memset(param, 0, TW_SECTOR_SIZE);
88 -       param->table_id = TW_TIMEKEEP_TABLE | 0x8000; /* Controller time keep table */
89 -       param->parameter_id = 0x3; /* SchedulerTime */
90 -       param->parameter_size_bytes = 4;
91 +       param->table_id = cpu_to_le16(TW_TIMEKEEP_TABLE | 0x8000); /* Controller time keep table */
92 +       param->parameter_id = cpu_to_le16(0x3); /* SchedulerTime */
93 +       param->parameter_size_bytes = cpu_to_le16(4);
94  
95         /* Convert system time in UTC to local time seconds since last 
96             Sunday 12:00AM */
97         do_gettimeofday(&utc);
98         local_time = (u32)(utc.tv_sec - (sys_tz.tz_minuteswest * 60));
99         schedulertime = local_time - (3 * 86400);
100 -       schedulertime = schedulertime % 604800;
101 +       schedulertime = cpu_to_le32(schedulertime % 604800);
102  
103         memcpy(param->data, &schedulertime, sizeof(u32));
104  
105 @@ -562,9 +569,9 @@
106                 goto out;
107         }
108  
109 -       tw_dev->working_srl = fw_on_ctlr_srl;
110 -       tw_dev->working_branch = fw_on_ctlr_branch;
111 -       tw_dev->working_build = fw_on_ctlr_build;
112 +       tw_dev->tw_compat_info.working_srl = fw_on_ctlr_srl;
113 +       tw_dev->tw_compat_info.working_branch = fw_on_ctlr_branch;
114 +       tw_dev->tw_compat_info.working_build = fw_on_ctlr_build;
115  
116         /* Try base mode compatibility */
117         if (!(init_connect_result & TW_CTLR_FW_COMPATIBLE)) {
118 @@ -586,10 +593,23 @@
119                         }
120                         goto out;
121                 }
122 -               tw_dev->working_srl = TW_BASE_FW_SRL;
123 -               tw_dev->working_branch = TW_BASE_FW_BRANCH;
124 -               tw_dev->working_build = TW_BASE_FW_BUILD;
125 -       }
126 +               tw_dev->tw_compat_info.working_srl = TW_BASE_FW_SRL;
127 +               tw_dev->tw_compat_info.working_branch = TW_BASE_FW_BRANCH;
128 +               tw_dev->tw_compat_info.working_build = TW_BASE_FW_BUILD;
129 +       }
130 +
131 +       /* Load rest of compatibility struct */
132 +       strncpy(tw_dev->tw_compat_info.driver_version, TW_DRIVER_VERSION, strlen(TW_DRIVER_VERSION));
133 +       tw_dev->tw_compat_info.driver_srl_high = TW_CURRENT_DRIVER_SRL;
134 +       tw_dev->tw_compat_info.driver_branch_high = TW_CURRENT_DRIVER_BRANCH;
135 +       tw_dev->tw_compat_info.driver_build_high = TW_CURRENT_DRIVER_BUILD;
136 +       tw_dev->tw_compat_info.driver_srl_low = TW_BASE_FW_SRL;
137 +       tw_dev->tw_compat_info.driver_branch_low = TW_BASE_FW_BRANCH;
138 +       tw_dev->tw_compat_info.driver_build_low = TW_BASE_FW_BUILD;
139 +       tw_dev->tw_compat_info.fw_on_ctlr_srl = fw_on_ctlr_srl;
140 +       tw_dev->tw_compat_info.fw_on_ctlr_branch = fw_on_ctlr_branch;
141 +       tw_dev->tw_compat_info.fw_on_ctlr_build = fw_on_ctlr_build;
142 +
143         retval = 0;
144  out:
145         return retval;
146 @@ -627,7 +647,7 @@
147                 goto out2;
148  
149         /* Check data buffer size */
150 -       if (driver_command.buffer_length > TW_MAX_SECTORS * 512) {
151 +       if (driver_command.buffer_length > TW_MAX_SECTORS * 2048) {
152                 retval = TW_IOCTL_ERROR_OS_EINVAL;
153                 goto out2;
154         }
155 @@ -676,13 +696,6 @@
156                 /* Now wait for command to complete */
157                 timeout = wait_event_timeout(tw_dev->ioctl_wqueue, tw_dev->chrdev_request_id == TW_IOCTL_CHRDEV_FREE, timeout);
158  
159 -               /* See if we reset while waiting for the ioctl to complete */
160 -               if (test_bit(TW_IN_RESET, &tw_dev->flags)) {
161 -                       clear_bit(TW_IN_RESET, &tw_dev->flags);
162 -                       retval = TW_IOCTL_ERROR_OS_ERESTARTSYS;
163 -                       goto out3;
164 -               }
165 -
166                 /* We timed out, and didn't get an interrupt */
167                 if (tw_dev->chrdev_request_id != TW_IOCTL_CHRDEV_FREE) {
168                         /* Now we need to reset the board */
169 @@ -690,11 +703,6 @@
170                                tw_dev->host->host_no, TW_DRIVER, 0xc,
171                                cmd);
172                         retval = TW_IOCTL_ERROR_OS_EIO;
173 -                       spin_lock_irqsave(tw_dev->host->host_lock, flags);
174 -                       tw_dev->state[request_id] = TW_S_COMPLETED;
175 -                       twa_free_request_id(tw_dev, request_id);
176 -                       tw_dev->posted_request_count--;
177 -                       spin_unlock_irqrestore(tw_dev->host->host_lock, flags);
178                         twa_reset_device_extension(tw_dev, 1);
179                         goto out3;
180                 }
181 @@ -713,16 +721,7 @@
182                 tw_ioctl->driver_command.status = 0;
183                 /* Copy compatiblity struct into ioctl data buffer */
184                 tw_compat_info = (TW_Compatibility_Info *)tw_ioctl->data_buffer;
185 -               strncpy(tw_compat_info->driver_version, TW_DRIVER_VERSION, strlen(TW_DRIVER_VERSION));
186 -               tw_compat_info->working_srl = tw_dev->working_srl;
187 -               tw_compat_info->working_branch = tw_dev->working_branch;
188 -               tw_compat_info->working_build = tw_dev->working_build;
189 -               tw_compat_info->driver_srl_high = TW_CURRENT_DRIVER_SRL;
190 -               tw_compat_info->driver_branch_high = TW_CURRENT_DRIVER_BRANCH;
191 -               tw_compat_info->driver_build_high = TW_CURRENT_DRIVER_BUILD;
192 -               tw_compat_info->driver_srl_low = TW_BASE_FW_SRL;
193 -               tw_compat_info->driver_branch_low = TW_BASE_FW_BRANCH;
194 -               tw_compat_info->driver_build_low = TW_BASE_FW_BUILD;
195 +               memcpy(tw_compat_info, &tw_dev->tw_compat_info, sizeof(TW_Compatibility_Info));
196                 break;
197         case TW_IOCTL_GET_LAST_EVENT:
198                 if (tw_dev->event_queue_wrapped) {
199 @@ -891,7 +890,8 @@
200         }
201  
202         if (status_reg_value & TW_STATUS_QUEUE_ERROR) {
203 -               TW_PRINTK(tw_dev->host, TW_DRIVER, 0xe, "Controller Queue Error: clearing");
204 +               if ((tw_dev->tw_pci_dev->device != PCI_DEVICE_ID_3WARE_9650SE) || (!test_bit(TW_IN_RESET, &tw_dev->flags)))
205 +                       TW_PRINTK(tw_dev->host, TW_DRIVER, 0xe, "Controller Queue Error: clearing");
206                 writel(TW_CONTROL_CLEAR_QUEUE_ERROR, TW_CONTROL_REG_ADDR(tw_dev));
207         }
208  
209 @@ -931,26 +931,21 @@
210  /* This function will clear the pchip/response queue on 9550SX */
211  static int twa_empty_response_queue_large(TW_Device_Extension *tw_dev)
212  {
213 -       u32 status_reg_value, response_que_value;
214 -       int count = 0, retval = 1;
215 -
216 -       if (tw_dev->tw_pci_dev->device == PCI_DEVICE_ID_3WARE_9550SX) {
217 -               status_reg_value = readl(TW_STATUS_REG_ADDR(tw_dev));
218 +       u32 response_que_value = 0;
219 +       unsigned long before;
220 +       int retval = 1;
221  
222 -               while (((status_reg_value & TW_STATUS_RESPONSE_QUEUE_EMPTY) == 0) && (count < TW_MAX_RESPONSE_DRAIN)) {
223 +       if ((tw_dev->tw_pci_dev->device == PCI_DEVICE_ID_3WARE_9550SX) ||
224 +           (tw_dev->tw_pci_dev->device == PCI_DEVICE_ID_3WARE_9650SE)) {
225 +               before = jiffies;
226 +               while ((response_que_value & TW_9550SX_DRAIN_COMPLETED) != TW_9550SX_DRAIN_COMPLETED) {
227                         response_que_value = readl(TW_RESPONSE_QUEUE_REG_ADDR_LARGE(tw_dev));
228 -                       if ((response_que_value & TW_9550SX_DRAIN_COMPLETED) == TW_9550SX_DRAIN_COMPLETED) {
229 -                               /* P-chip settle time */
230 -                               msleep(500);
231 -                               retval = 0;
232 +                       msleep(1);
233 +                       if (time_after(jiffies, before + HZ * 30))
234                                 goto out;
235 -                       }
236 -                       status_reg_value = readl(TW_STATUS_REG_ADDR(tw_dev));
237 -                       count++;
238                 }
239 -               if (count == TW_MAX_RESPONSE_DRAIN)
240 -                       goto out;
241 -               
242 +               /* P-chip settle time */
243 +               msleep(500);
244                 retval = 0;
245         } else
246                 retval = 0;
247 @@ -972,7 +967,7 @@
248         error_str = &(full_command_packet->header.err_specific_desc[strlen(full_command_packet->header.err_specific_desc) + 1]);
249  
250         /* Don't print error for Logical unit not supported during rollcall */
251 -       error = full_command_packet->header.status_block.error;
252 +       error = le16_to_cpu(full_command_packet->header.status_block.error);
253         if ((error != TW_ERROR_LOGICAL_UNIT_NOT_SUPPORTED) && (error != TW_ERROR_UNIT_OFFLINE)) {
254                 if (print_host)
255                         printk(KERN_WARNING "3w-9xxx: scsi%d: ERROR: (0x%02X:0x%04X): %s:%s.\n",
256 @@ -1030,7 +1025,7 @@
257         tw_dev->free_tail = (tw_dev->free_tail + 1) % TW_Q_LENGTH;
258  } /* End twa_free_request_id() */
259  
260 -/* This function will get parameter table entires from the firmware */
261 +/* This function will get parameter table entries from the firmware */
262  static void *twa_get_param(TW_Device_Extension *tw_dev, int request_id, int table_id, int parameter_id, int parameter_size_bytes)
263  {
264         TW_Command_Full *full_command_packet;
265 @@ -1047,18 +1042,18 @@
266         command_packet->opcode__sgloffset = TW_OPSGL_IN(2, TW_OP_GET_PARAM);
267         command_packet->size              = TW_COMMAND_SIZE;
268         command_packet->request_id        = request_id;
269 -       command_packet->byte6_offset.block_count = 1;
270 +       command_packet->byte6_offset.block_count = cpu_to_le16(1);
271  
272         /* Now setup the param */
273         param = (TW_Param_Apache *)tw_dev->generic_buffer_virt[request_id];
274         memset(param, 0, TW_SECTOR_SIZE);
275 -       param->table_id = table_id | 0x8000;
276 -       param->parameter_id = parameter_id;
277 -       param->parameter_size_bytes = parameter_size_bytes;
278 +       param->table_id = cpu_to_le16(table_id | 0x8000);
279 +       param->parameter_id = cpu_to_le16(parameter_id);
280 +       param->parameter_size_bytes = cpu_to_le16(parameter_size_bytes);
281         param_value = tw_dev->generic_buffer_phys[request_id];
282  
283 -       command_packet->byte8_offset.param.sgl[0].address = param_value;
284 -       command_packet->byte8_offset.param.sgl[0].length = TW_SECTOR_SIZE;
285 +       command_packet->byte8_offset.param.sgl[0].address = TW_CPU_TO_SGL(param_value);
286 +       command_packet->byte8_offset.param.sgl[0].length = cpu_to_le32(TW_SECTOR_SIZE);
287  
288         /* Post the command packet to the board */
289         twa_post_command_packet(tw_dev, request_id, 1);
290 @@ -1107,18 +1102,20 @@
291         tw_initconnect = (TW_Initconnect *)&full_command_packet->command.oldcommand;
292         tw_initconnect->opcode__reserved = TW_OPRES_IN(0, TW_OP_INIT_CONNECTION);
293         tw_initconnect->request_id = request_id;
294 -       tw_initconnect->message_credits = message_credits;
295 +       tw_initconnect->message_credits = cpu_to_le16(message_credits);
296         tw_initconnect->features = set_features;
297  
298         /* Turn on 64-bit sgl support if we need to */
299         tw_initconnect->features |= sizeof(dma_addr_t) > 4 ? 1 : 0;
300  
301 +       tw_initconnect->features = cpu_to_le32(tw_initconnect->features);
302 +
303         if (set_features & TW_EXTENDED_INIT_CONNECT) {
304                 tw_initconnect->size = TW_INIT_COMMAND_PACKET_SIZE_EXTENDED;
305 -               tw_initconnect->fw_srl = current_fw_srl;
306 -               tw_initconnect->fw_arch_id = current_fw_arch_id;
307 -               tw_initconnect->fw_branch = current_fw_branch;
308 -               tw_initconnect->fw_build = current_fw_build;
309 +               tw_initconnect->fw_srl = cpu_to_le16(current_fw_srl);
310 +               tw_initconnect->fw_arch_id = cpu_to_le16(current_fw_arch_id);
311 +               tw_initconnect->fw_branch = cpu_to_le16(current_fw_branch);
312 +               tw_initconnect->fw_build = cpu_to_le16(current_fw_build);
313         } else 
314                 tw_initconnect->size = TW_INIT_COMMAND_PACKET_SIZE;
315  
316 @@ -1130,11 +1127,11 @@
317                 TW_PRINTK(tw_dev->host, TW_DRIVER, 0x15, "No valid response during init connection");
318         } else {
319                 if (set_features & TW_EXTENDED_INIT_CONNECT) {
320 -                       *fw_on_ctlr_srl = tw_initconnect->fw_srl;
321 -                       *fw_on_ctlr_arch_id = tw_initconnect->fw_arch_id;
322 -                       *fw_on_ctlr_branch = tw_initconnect->fw_branch;
323 -                       *fw_on_ctlr_build = tw_initconnect->fw_build;
324 -                       *init_connect_result = tw_initconnect->result;
325 +                       *fw_on_ctlr_srl = le16_to_cpu(tw_initconnect->fw_srl);
326 +                       *fw_on_ctlr_arch_id = le16_to_cpu(tw_initconnect->fw_arch_id);
327 +                       *fw_on_ctlr_branch = le16_to_cpu(tw_initconnect->fw_branch);
328 +                       *fw_on_ctlr_build = le16_to_cpu(tw_initconnect->fw_build);
329 +                       *init_connect_result = le32_to_cpu(tw_initconnect->result);
330                 }
331                 retval = 0;
332         }
333 @@ -1193,7 +1190,7 @@
334  } /* End twa_initialize_device_extension() */
335  
336  /* This function is the interrupt service routine */
337 -static irqreturn_t twa_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
338 +static irqreturn_t twa_interrupt(int irq, void *dev_instance)
339  {
340         int request_id, error = 0;
341         u32 status_reg_value;
342 @@ -1215,6 +1212,10 @@
343  
344         handled = 1;
345  
346 +       /* If we are resetting, bail */
347 +       if (test_bit(TW_IN_RESET, &tw_dev->flags))
348 +               goto twa_interrupt_bail;
349 +
350         /* Check controller for errors */
351         if (twa_check_bits(status_reg_value)) {
352                 if (twa_decode_bits(tw_dev, status_reg_value)) {
353 @@ -1356,12 +1357,12 @@
354  
355         if (TW_OP_OUT(full_command_packet->command.newcommand.opcode__reserved) == TW_OP_EXECUTE_SCSI) {
356                 newcommand = &full_command_packet->command.newcommand;
357 -               newcommand->request_id__lunl = 
358 -                       TW_REQ_LUN_IN(TW_LUN_OUT(newcommand->request_id__lunl), request_id);
359 -               newcommand->sg_list[0].address = dma_handle + sizeof(TW_Ioctl_Buf_Apache) - 1;
360 -               newcommand->sg_list[0].length = length;
361 +               newcommand->request_id__lunl =
362 +                       cpu_to_le16(TW_REQ_LUN_IN(TW_LUN_OUT(newcommand->request_id__lunl), request_id));
363 +               newcommand->sg_list[0].address = TW_CPU_TO_SGL(dma_handle + sizeof(TW_Ioctl_Buf_Apache) - 1);
364 +               newcommand->sg_list[0].length = cpu_to_le32(length);
365                 newcommand->sgl_entries__lunh =
366 -                       TW_REQ_LUN_IN(TW_LUN_OUT(newcommand->sgl_entries__lunh), 1);
367 +                       cpu_to_le16(TW_REQ_LUN_IN(TW_LUN_OUT(newcommand->sgl_entries__lunh), 1));
368         } else {
369                 oldcommand = &full_command_packet->command.oldcommand;
370                 oldcommand->request_id = request_id;
371 @@ -1369,8 +1370,8 @@
372                 if (TW_SGL_OUT(oldcommand->opcode__sgloffset)) {
373                         /* Load the sg list */
374                         sgl = (TW_SG_Entry *)((u32 *)oldcommand+TW_SGL_OUT(oldcommand->opcode__sgloffset));
375 -                       sgl->address = dma_handle + sizeof(TW_Ioctl_Buf_Apache) - 1;
376 -                       sgl->length = length;
377 +                       sgl->address = TW_CPU_TO_SGL(dma_handle + sizeof(TW_Ioctl_Buf_Apache) - 1);
378 +                       sgl->length = cpu_to_le32(length);
379  
380                         if ((sizeof(long) < 8) && (sizeof(dma_addr_t) > 4))
381                                 oldcommand->size += 1;
382 @@ -1389,7 +1390,7 @@
383         if (cmd->use_sg == 0)
384                 goto out;
385  
386 -       use_sg = pci_map_sg(pdev, cmd->buffer, cmd->use_sg, DMA_BIDIRECTIONAL);
387 +       use_sg = pci_map_sg(pdev, cmd->request_buffer, cmd->use_sg, DMA_BIDIRECTIONAL);
388  
389         if (use_sg == 0) {
390                 TW_PRINTK(tw_dev->host, TW_DRIVER, 0x1c, "Failed to map scatter gather list");
391 @@ -1532,6 +1533,13 @@
392         int retval = 1;
393  
394         command_que_value = tw_dev->command_packet_phys[request_id];
395 +
396 +       /* For 9650SE write low 4 bytes first */
397 +       if (tw_dev->tw_pci_dev->device == PCI_DEVICE_ID_3WARE_9650SE) {
398 +               command_que_value += TW_COMMAND_OFFSET;
399 +               writel((u32)command_que_value, TW_COMMAND_QUEUE_REG_ADDR_LARGE(tw_dev));
400 +       }
401 +
402         status_reg_value = readl(TW_STATUS_REG_ADDR(tw_dev));
403  
404         if (twa_check_bits(status_reg_value))
405 @@ -1558,13 +1566,17 @@
406                 TW_UNMASK_COMMAND_INTERRUPT(tw_dev);
407                 goto out;
408         } else {
409 -               /* We successfully posted the command packet */
410 -               if (sizeof(dma_addr_t) > 4) {
411 -                       command_que_value += TW_COMMAND_OFFSET;
412 -                       writel((u32)command_que_value, TW_COMMAND_QUEUE_REG_ADDR(tw_dev));
413 -                       writel((u32)((u64)command_que_value >> 32), TW_COMMAND_QUEUE_REG_ADDR(tw_dev) + 0x4);
414 +               if (tw_dev->tw_pci_dev->device == PCI_DEVICE_ID_3WARE_9650SE) {
415 +                       /* Now write upper 4 bytes */
416 +                       writel((u32)((u64)command_que_value >> 32), TW_COMMAND_QUEUE_REG_ADDR_LARGE(tw_dev) + 0x4);
417                 } else {
418 -                       writel(TW_COMMAND_OFFSET + command_que_value, TW_COMMAND_QUEUE_REG_ADDR(tw_dev));
419 +                       if (sizeof(dma_addr_t) > 4) {
420 +                               command_que_value += TW_COMMAND_OFFSET;
421 +                               writel((u32)command_que_value, TW_COMMAND_QUEUE_REG_ADDR(tw_dev));
422 +                               writel((u32)((u64)command_que_value >> 32), TW_COMMAND_QUEUE_REG_ADDR(tw_dev) + 0x4);
423 +                       } else {
424 +                               writel(TW_COMMAND_OFFSET + command_que_value, TW_COMMAND_QUEUE_REG_ADDR(tw_dev));
425 +                       }
426                 }
427                 tw_dev->state[request_id] = TW_S_POSTED;
428                 tw_dev->posted_request_count++;
429 @@ -1621,14 +1633,9 @@
430                 goto out;
431  
432         TW_ENABLE_AND_CLEAR_INTERRUPTS(tw_dev);
433 +       clear_bit(TW_IN_RESET, &tw_dev->flags);
434 +       tw_dev->chrdev_request_id = TW_IOCTL_CHRDEV_FREE;
435  
436 -       /* Wake up any ioctl that was pending before the reset */
437 -       if ((tw_dev->chrdev_request_id == TW_IOCTL_CHRDEV_FREE) || (ioctl_reset)) {
438 -               clear_bit(TW_IN_RESET, &tw_dev->flags);
439 -       } else {
440 -               tw_dev->chrdev_request_id = TW_IOCTL_CHRDEV_FREE;
441 -               wake_up(&tw_dev->ioctl_wqueue);
442 -       }
443         retval = 0;
444  out:
445         return retval;
446 @@ -1737,6 +1744,9 @@
447                 "WARNING: (0x%02X:0x%04X): Command (0x%x) timed out, resetting card.\n",
448                 TW_DRIVER, 0x2c, SCpnt->cmnd[0]);
449  
450 +       /* Make sure we are not issuing an ioctl or resetting from ioctl */
451 +       mutex_lock(&tw_dev->ioctl_lock);
452 +
453         /* Now reset the card and some of the device extension data */
454         if (twa_reset_device_extension(tw_dev, 0)) {
455                 TW_PRINTK(tw_dev->host, TW_DRIVER, 0x2b, "Controller reset failed during scsi host reset");
456 @@ -1745,6 +1755,7 @@
457  
458         retval = SUCCESS;
459  out:
460 +       mutex_unlock(&tw_dev->ioctl_lock);
461         return retval;
462  } /* End twa_scsi_eh_reset() */
463  
464 @@ -1754,8 +1765,14 @@
465         int request_id, retval;
466         TW_Device_Extension *tw_dev = (TW_Device_Extension *)SCpnt->device->host->hostdata;
467  
468 +       /* If we are resetting due to timed out ioctl, report as busy */
469 +       if (test_bit(TW_IN_RESET, &tw_dev->flags)) {
470 +               retval = SCSI_MLQUEUE_HOST_BUSY;
471 +               goto out;
472 +       }
473 +
474         /* Check if this FW supports luns */
475 -       if ((SCpnt->device->lun != 0) && (tw_dev->working_srl < TW_FW_SRL_LUNS_SUPPORTED)) {
476 +       if ((SCpnt->device->lun != 0) && (tw_dev->tw_compat_info.working_srl < TW_FW_SRL_LUNS_SUPPORTED)) {
477                 SCpnt->result = (DID_BAD_TARGET << 16);
478                 done(SCpnt);
479                 retval = 0;
480 @@ -1828,10 +1845,10 @@
481         if (srb) {
482                 command_packet->unit = srb->device->id;
483                 command_packet->request_id__lunl =
484 -                       TW_REQ_LUN_IN(srb->device->lun, request_id);
485 +                       cpu_to_le16(TW_REQ_LUN_IN(srb->device->lun, request_id));
486         } else {
487                 command_packet->request_id__lunl =
488 -                       TW_REQ_LUN_IN(0, request_id);
489 +                       cpu_to_le16(TW_REQ_LUN_IN(0, request_id));
490                 command_packet->unit = 0;
491         }
492  
493 @@ -1841,8 +1858,8 @@
494                 /* Map sglist from scsi layer to cmd packet */
495                 if (tw_dev->srb[request_id]->use_sg == 0) {
496                         if (tw_dev->srb[request_id]->request_bufflen < TW_MIN_SGL_LENGTH) {
497 -                               command_packet->sg_list[0].address = tw_dev->generic_buffer_phys[request_id];
498 -                               command_packet->sg_list[0].length = TW_MIN_SGL_LENGTH;
499 +                               command_packet->sg_list[0].address = TW_CPU_TO_SGL(tw_dev->generic_buffer_phys[request_id]);
500 +                               command_packet->sg_list[0].length = cpu_to_le32(TW_MIN_SGL_LENGTH);
501                                 if (tw_dev->srb[request_id]->sc_data_direction == DMA_TO_DEVICE || tw_dev->srb[request_id]->sc_data_direction == DMA_BIDIRECTIONAL)
502                                         memcpy(tw_dev->generic_buffer_virt[request_id], tw_dev->srb[request_id]->request_buffer, tw_dev->srb[request_id]->request_bufflen);
503                         } else {
504 @@ -1850,12 +1867,12 @@
505                                 if (buffaddr == 0)
506                                         goto out;
507  
508 -                               command_packet->sg_list[0].address = buffaddr;
509 -                               command_packet->sg_list[0].length = tw_dev->srb[request_id]->request_bufflen;
510 +                               command_packet->sg_list[0].address = TW_CPU_TO_SGL(buffaddr);
511 +                               command_packet->sg_list[0].length = cpu_to_le32(tw_dev->srb[request_id]->request_bufflen);
512                         }
513 -                       command_packet->sgl_entries__lunh = TW_REQ_LUN_IN((srb->device->lun >> 4), 1);
514 +                       command_packet->sgl_entries__lunh = cpu_to_le16(TW_REQ_LUN_IN((srb->device->lun >> 4), 1));
515  
516 -                       if (command_packet->sg_list[0].address & TW_ALIGNMENT_9000_SGL) {
517 +                       if (command_packet->sg_list[0].address & TW_CPU_TO_SGL(TW_ALIGNMENT_9000_SGL)) {
518                                 TW_PRINTK(tw_dev->host, TW_DRIVER, 0x2d, "Found unaligned address during execute scsi");
519                                 goto out;
520                         }
521 @@ -1869,35 +1886,35 @@
522                                         memcpy(tw_dev->generic_buffer_virt[request_id], buf, sg->length);
523                                         kunmap_atomic(buf - sg->offset, KM_IRQ0);
524                                 }
525 -                               command_packet->sg_list[0].address = tw_dev->generic_buffer_phys[request_id];
526 -                               command_packet->sg_list[0].length = TW_MIN_SGL_LENGTH;
527 +                               command_packet->sg_list[0].address = TW_CPU_TO_SGL(tw_dev->generic_buffer_phys[request_id]);
528 +                               command_packet->sg_list[0].length = cpu_to_le32(TW_MIN_SGL_LENGTH);
529                         } else {
530                                 sg_count = twa_map_scsi_sg_data(tw_dev, request_id);
531                                 if (sg_count == 0)
532                                         goto out;
533  
534                                 for (i = 0; i < sg_count; i++) {
535 -                                       command_packet->sg_list[i].address = sg_dma_address(&sglist[i]);
536 -                                       command_packet->sg_list[i].length = sg_dma_len(&sglist[i]);
537 -                                       if (command_packet->sg_list[i].address & TW_ALIGNMENT_9000_SGL) {
538 +                                       command_packet->sg_list[i].address = TW_CPU_TO_SGL(sg_dma_address(&sglist[i]));
539 +                                       command_packet->sg_list[i].length = cpu_to_le32(sg_dma_len(&sglist[i]));
540 +                                       if (command_packet->sg_list[i].address & TW_CPU_TO_SGL(TW_ALIGNMENT_9000_SGL)) {
541                                                 TW_PRINTK(tw_dev->host, TW_DRIVER, 0x2e, "Found unaligned sgl address during execute scsi");
542                                                 goto out;
543                                         }
544                                 }
545                         }
546 -                       command_packet->sgl_entries__lunh = TW_REQ_LUN_IN((srb->device->lun >> 4), tw_dev->srb[request_id]->use_sg);
547 +                       command_packet->sgl_entries__lunh = cpu_to_le16(TW_REQ_LUN_IN((srb->device->lun >> 4), tw_dev->srb[request_id]->use_sg));
548                 }
549         } else {
550                 /* Internal cdb post */
551                 for (i = 0; i < use_sg; i++) {
552 -                       command_packet->sg_list[i].address = sglistarg[i].address;
553 -                       command_packet->sg_list[i].length = sglistarg[i].length;
554 -                       if (command_packet->sg_list[i].address & TW_ALIGNMENT_9000_SGL) {
555 +                       command_packet->sg_list[i].address = TW_CPU_TO_SGL(sglistarg[i].address);
556 +                       command_packet->sg_list[i].length = cpu_to_le32(sglistarg[i].length);
557 +                       if (command_packet->sg_list[i].address & TW_CPU_TO_SGL(TW_ALIGNMENT_9000_SGL)) {
558                                 TW_PRINTK(tw_dev->host, TW_DRIVER, 0x2f, "Found unaligned sgl address during internal post");
559                                 goto out;
560                         }
561                 }
562 -               command_packet->sgl_entries__lunh = TW_REQ_LUN_IN(0, use_sg);
563 +               command_packet->sgl_entries__lunh = cpu_to_le16(TW_REQ_LUN_IN(0, use_sg));
564         }
565  
566         if (srb) {
567 @@ -1961,6 +1978,9 @@
568         /* Disable interrupts */
569         TW_DISABLE_INTERRUPTS(tw_dev);
570  
571 +       /* Free up the IRQ */
572 +       free_irq(tw_dev->tw_pci_dev->irq, tw_dev);
573 +
574         printk(KERN_WARNING "3w-9xxx: Shutting down host %d.\n", tw_dev->host->host_no);
575  
576         /* Tell the card we are shutting down */
577 @@ -2092,21 +2112,25 @@
578  
579         /* Initialize the card */
580         if (twa_reset_sequence(tw_dev, 0))
581 -               goto out_release_mem_region;
582 +               goto out_iounmap;
583  
584         /* Set host specific parameters */
585 -       host->max_id = TW_MAX_UNITS;
586 +       if (pdev->device == PCI_DEVICE_ID_3WARE_9650SE)
587 +               host->max_id = TW_MAX_UNITS_9650SE;
588 +       else
589 +               host->max_id = TW_MAX_UNITS;
590 +
591         host->max_cmd_len = TW_MAX_CDB_LEN;
592  
593         /* Channels aren't supported by adapter */
594 -       host->max_lun = TW_MAX_LUNS(tw_dev->working_srl);
595 +       host->max_lun = TW_MAX_LUNS(tw_dev->tw_compat_info.working_srl);
596         host->max_channel = 0;
597  
598         /* Register the card with the kernel SCSI layer */
599         retval = scsi_add_host(host, &pdev->dev);
600         if (retval) {
601                 TW_PRINTK(tw_dev->host, TW_DRIVER, 0x27, "scsi add host failed");
602 -               goto out_release_mem_region;
603 +               goto out_iounmap;
604         }
605  
606         pci_set_drvdata(pdev, host);
607 @@ -2119,8 +2143,8 @@
608                                      TW_PARAM_FWVER, TW_PARAM_FWVER_LENGTH),
609                (char *)twa_get_param(tw_dev, 1, TW_VERSION_TABLE,
610                                      TW_PARAM_BIOSVER, TW_PARAM_BIOSVER_LENGTH),
611 -              *(int *)twa_get_param(tw_dev, 2, TW_INFORMATION_TABLE,
612 -                                    TW_PARAM_PORTCOUNT, TW_PARAM_PORTCOUNT_LENGTH));
613 +              le32_to_cpu(*(int *)twa_get_param(tw_dev, 2, TW_INFORMATION_TABLE,
614 +                                    TW_PARAM_PORTCOUNT, TW_PARAM_PORTCOUNT_LENGTH)));
615  
616         /* Now setup the interrupt handler */
617         retval = request_irq(pdev->irq, twa_interrupt, SA_SHIRQ, "3w-9xxx", tw_dev);
618 @@ -2146,6 +2170,8 @@
619  
620  out_remove_host:
621         scsi_remove_host(host);
622 +out_iounmap:
623 +       iounmap(tw_dev->base_addr);
624  out_release_mem_region:
625         pci_release_regions(pdev);
626  out_free_device_extension:
627 @@ -2171,12 +2197,12 @@
628                 twa_major = -1;
629         }
630  
631 -       /* Free up the IRQ */
632 -       free_irq(tw_dev->tw_pci_dev->irq, tw_dev);
633 -
634         /* Shutdown the card */
635         __twa_shutdown(tw_dev);
636  
637 +       /* Free IO remapping */
638 +       iounmap(tw_dev->base_addr);
639 +
640         /* Free up the mem region */
641         pci_release_regions(pdev);
642  
643 @@ -2194,6 +2220,8 @@
644           PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
645         { PCI_VENDOR_ID_3WARE, PCI_DEVICE_ID_3WARE_9550SX,
646           PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
647 +       { PCI_VENDOR_ID_3WARE, PCI_DEVICE_ID_3WARE_9650SE,
648 +         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
649         { }
650  };
651  MODULE_DEVICE_TABLE(pci, twa_pci_tbl);
652 @@ -2212,7 +2240,7 @@
653  {
654         printk(KERN_WARNING "3ware 9000 Storage Controller device driver for Linux v%s.\n", TW_DRIVER_VERSION);
655  
656 -       return pci_module_init(&twa_driver);
657 +       return pci_register_driver(&twa_driver);
658  } /* End twa_init() */
659  
660  /* This function is called on driver exit */
661 diff -uNr linux-2.6.16.orig/drivers/scsi/3w-9xxx.h linux-2.6.16/drivers/scsi/3w-9xxx.h
662 --- linux-2.6.16.orig/drivers/scsi/3w-9xxx.h    2006-03-20 06:53:29.000000000 +0100
663 +++ linux-2.6.16/drivers/scsi/3w-9xxx.h 2006-10-20 22:22:02.000000000 +0200
664 @@ -2,8 +2,9 @@
665     3w-9xxx.h -- 3ware 9000 Storage Controller device driver for Linux.
666  
667     Written By: Adam Radford <linuxraid@amcc.com>
668 +   Modifications By: Tom Couch <linuxraid@amcc.com>
669  
670 -   Copyright (C) 2004-2005 Applied Micro Circuits Corporation.
671 +   Copyright (C) 2004-2006 Applied Micro Circuits Corporation.
672  
673     This program is free software; you can redistribute it and/or modify
674     it under the terms of the GNU General Public License as published by
675 @@ -287,11 +288,7 @@
676  #define TW_STATUS_UNEXPECTED_BITS             0x00F00000
677  #define TW_STATUS_VALID_INTERRUPT              0x00DF0000
678  
679 -/* RESPONSE QUEUE BIT DEFINITIONS */
680 -#define TW_RESPONSE_ID_MASK                   0x00000FF0
681 -
682  /* PCI related defines */
683 -#define TW_NUMDEVICES 1
684  #define TW_PCI_CLEAR_PARITY_ERRORS 0xc100
685  #define TW_PCI_CLEAR_PCI_ABORT     0x2000
686  
687 @@ -337,6 +334,7 @@
688  #define TW_ALIGNMENT_9000                     4  /* 4 bytes */
689  #define TW_ALIGNMENT_9000_SGL                 0x3
690  #define TW_MAX_UNITS                         16
691 +#define TW_MAX_UNITS_9650SE                  32
692  #define TW_INIT_MESSAGE_CREDITS                      0x100
693  #define TW_INIT_COMMAND_PACKET_SIZE          0x3
694  #define TW_INIT_COMMAND_PACKET_SIZE_EXTENDED  0x6
695 @@ -356,7 +354,6 @@
696  #define TW_MAX_RESPONSE_DRAIN                256
697  #define TW_MAX_AEN_DRAIN                     40
698  #define TW_IN_RESET                           2
699 -#define TW_IN_CHRDEV_IOCTL                    3
700  #define TW_IN_ATTENTION_LOOP                 4
701  #define TW_MAX_SECTORS                        256
702  #define TW_AEN_WAIT_TIME                      1000
703 @@ -419,6 +416,9 @@
704  #ifndef PCI_DEVICE_ID_3WARE_9550SX
705  #define PCI_DEVICE_ID_3WARE_9550SX 0x1003
706  #endif
707 +#ifndef PCI_DEVICE_ID_3WARE_9650SE
708 +#define PCI_DEVICE_ID_3WARE_9650SE 0x1004
709 +#endif
710  
711  /* Bitmask macros to eliminate bitfields */
712  
713 @@ -444,6 +444,7 @@
714  #define TW_CONTROL_REG_ADDR(x) (x->base_addr)
715  #define TW_STATUS_REG_ADDR(x) ((unsigned char __iomem *)x->base_addr + 0x4)
716  #define TW_COMMAND_QUEUE_REG_ADDR(x) (sizeof(dma_addr_t) > 4 ? ((unsigned char __iomem *)x->base_addr + 0x20) : ((unsigned char __iomem *)x->base_addr + 0x8))
717 +#define TW_COMMAND_QUEUE_REG_ADDR_LARGE(x) ((unsigned char __iomem *)x->base_addr + 0x20)
718  #define TW_RESPONSE_QUEUE_REG_ADDR(x) ((unsigned char __iomem *)x->base_addr + 0xC)
719  #define TW_RESPONSE_QUEUE_REG_ADDR_LARGE(x) ((unsigned char __iomem *)x->base_addr + 0x30)
720  #define TW_CLEAR_ALL_INTERRUPTS(x) (writel(TW_STATUS_VALID_INTERRUPT, TW_CONTROL_REG_ADDR(x)))
721 @@ -471,6 +472,7 @@
722  #define TW_APACHE_MAX_SGL_LENGTH (sizeof(dma_addr_t) > 4 ? 72 : 109)
723  #define TW_ESCALADE_MAX_SGL_LENGTH (sizeof(dma_addr_t) > 4 ? 41 : 62)
724  #define TW_PADDING_LENGTH (sizeof(dma_addr_t) > 4 ? 8 : 0)
725 +#define TW_CPU_TO_SGL(x) (sizeof(dma_addr_t) > 4 ? cpu_to_le64(x) : cpu_to_le32(x))
726  
727  #pragma pack(1)
728  
729 @@ -614,13 +616,6 @@
730         u32 value;
731  } TW_Response_Queue;
732  
733 -typedef struct TAG_TW_Info {
734 -       char *buffer;
735 -       int length;
736 -       int offset;
737 -       int position;
738 -} TW_Info;
739 -
740  /* Compatibility information structure */
741  typedef struct TAG_TW_Compatibility_Info
742  {
743 @@ -634,8 +629,13 @@
744         unsigned short driver_srl_low;
745         unsigned short driver_branch_low;
746         unsigned short driver_build_low;
747 +       unsigned short fw_on_ctlr_srl;
748 +       unsigned short fw_on_ctlr_branch;
749 +       unsigned short fw_on_ctlr_build;
750  } TW_Compatibility_Info;
751  
752 +#pragma pack()
753 +
754  typedef struct TAG_TW_Device_Extension {
755         u32                     __iomem *base_addr;
756         unsigned long           *generic_buffer_virt[TW_Q_LENGTH];
757 @@ -674,12 +674,8 @@
758         wait_queue_head_t       ioctl_wqueue;
759         struct mutex            ioctl_lock;
760         char                    aen_clobber;
761 -       unsigned short          working_srl;
762 -       unsigned short          working_branch;
763 -       unsigned short          working_build;
764 +       TW_Compatibility_Info   tw_compat_info;
765  } TW_Device_Extension;
766  
767 -#pragma pack()
768 -
769  #endif /* _3W_9XXX_H */
770  
This page took 0.202967 seconds and 3 git commands to generate.