]> git.pld-linux.org Git - packages/kernel.git/blame - linux-3w-9xxx.patch
- release 4
[packages/kernel.git] / linux-3w-9xxx.patch
CommitLineData
7383e370 1diff -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 */
661diff -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.129721 seconds and 4 git commands to generate.