]>
Commit | Line | Data |
---|---|---|
82094b55 AF |
1 | From: Penchala Narsimha Reddy Chilakala <ServeRAIDDriver@hcl.in> |
2 | Subject: Problems with aacraid | |
3 | References: bnc#524242 | |
4 | ||
5 | The attached patch aac24701 was generated for the following issues only: | |
6 | ||
7 | Issue:1 | |
8 | -------- | |
9 | Behavior of the ternary operation in function aac_send_raw_srb () was | |
10 | observed incorrect in 64-bit version. This issue was because of missing | |
11 | parenthesis in the condition to check the sg count. | |
12 | ||
13 | Fix details: | |
14 | ------------- | |
15 | Fixed by adding parentheses. | |
16 | ||
17 | Issue:2 | |
18 | -------- | |
19 | Driver IOCTLs is signaled with EINTR while waiting on response from the | |
20 | lower layers. Returning “EINTR” will never initiate internal retry. | |
21 | ||
22 | Fix details: | |
23 | ------------- | |
24 | Fixed by replacing “EINTR” with “ERESTARTSYS” for mid-layer retries. | |
25 | ||
26 | Issue:3 | |
27 | -------- | |
28 | The driver tends to not free the memory (FIB) when the management | |
29 | request exits prematurely. The accumulation of such un-freed memory causes the | |
30 | driver to fail to allocate anymore memory (FIB) and hence return 0x70000 value | |
31 | to the upper layer, which puts the file system into read only mode. | |
32 | ||
33 | Fix details: | |
34 | ------------- | |
35 | The fix makes sure to free the memory(FIB) even if the request exits | |
36 | prematurely hence ensuring the driver wouldn’t run out of memory(FIBs) | |
37 | ||
38 | Issue:4 | |
39 | -------- | |
40 | The driver exhibits performance problems as the execution of | |
41 | SYNCHRONIZE CACHE is quite time-consuming. | |
42 | ||
43 | Fix details: | |
44 | ------------- | |
45 | The issue is fixed by setting WCE=0 in the INQUIRY data, thus | |
46 | causing the SCSI midlayer not to issue any SYNCHRONIZE CACHE commands. | |
47 | ||
48 | Signed-off-by: Hannes Reinecke <hare@suse.de> | |
49 | ||
50 | diff -ru a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c | |
51 | --- a/drivers/scsi/aacraid/aachba.c 2009-09-16 16:40:05.000000000 +0530 | |
52 | +++ b/drivers/scsi/aacraid/aachba.c 2009-09-16 17:41:00.000000000 +0530 | |
53 | @@ -143,7 +143,7 @@ | |
54 | */ | |
55 | ||
56 | static int nondasd = -1; | |
57 | -static int aac_cache; | |
58 | +static int aac_cache = 2; /* WCE=0 to avoid performance problems */ | |
59 | static int dacmode = -1; | |
60 | int aac_msi; | |
61 | int aac_commit = -1; | |
62 | @@ -157,7 +157,7 @@ | |
63 | MODULE_PARM_DESC(cache, "Disable Queue Flush commands:\n" | |
64 | "\tbit 0 - Disable FUA in WRITE SCSI commands\n" | |
65 | "\tbit 1 - Disable SYNCHRONIZE_CACHE SCSI command\n" | |
66 | - "\tbit 2 - Disable only if Battery not protecting Cache"); | |
67 | + "\tbit 2 - Disable only if Battery is protecting Cache"); | |
68 | module_param(dacmode, int, S_IRUGO|S_IWUSR); | |
69 | MODULE_PARM_DESC(dacmode, "Control whether dma addressing is using 64 bit DAC." | |
70 | " 0=off, 1=on"); | |
71 | @@ -217,6 +217,14 @@ | |
72 | module_param_named(reset_devices, aac_reset_devices, int, S_IRUGO|S_IWUSR); | |
73 | MODULE_PARM_DESC(reset_devices, "Force an adapter reset at initialization."); | |
74 | ||
75 | +int aac_wwn = 1; | |
76 | +module_param_named(wwn, aac_wwn, int, S_IRUGO|S_IWUSR); | |
77 | +MODULE_PARM_DESC(wwn, "Select a WWN type for the arrays:\n" | |
78 | + "\t0 - Disable\n" | |
79 | + "\t1 - Array Meta Data Signature (default)\n" | |
80 | + "\t2 - Adapter Serial Number"); | |
81 | + | |
82 | + | |
83 | static inline int aac_valid_context(struct scsi_cmnd *scsicmd, | |
84 | struct fib *fibptr) { | |
85 | struct scsi_device *device; | |
86 | @@ -285,7 +293,10 @@ | |
87 | status = -EINVAL; | |
88 | } | |
89 | } | |
90 | - aac_fib_complete(fibptr); | |
91 | + /* Do not set XferState to zero unless receives a response from F/W */ | |
92 | + if (status >= 0) | |
93 | + aac_fib_complete(fibptr); | |
94 | + | |
95 | /* Send a CT_COMMIT_CONFIG to enable discovery of devices */ | |
96 | if (status >= 0) { | |
97 | if ((aac_commit == 1) || commit_flag) { | |
98 | @@ -302,13 +313,18 @@ | |
99 | FsaNormal, | |
100 | 1, 1, | |
101 | NULL, NULL); | |
102 | - aac_fib_complete(fibptr); | |
103 | + /* Do not set XferState to zero unless | |
104 | + * receives a response from F/W */ | |
105 | + if (status >= 0) | |
106 | + aac_fib_complete(fibptr); | |
107 | } else if (aac_commit == 0) { | |
108 | printk(KERN_WARNING | |
109 | "aac_get_config_status: Foreign device configurations are being ignored\n"); | |
110 | } | |
111 | } | |
112 | - aac_fib_free(fibptr); | |
113 | + /* FIB should be freed only after getting the response from the F/W */ | |
114 | + if (status != -ERESTARTSYS) | |
115 | + aac_fib_free(fibptr); | |
116 | return status; | |
117 | } | |
118 | ||
119 | @@ -347,7 +363,9 @@ | |
120 | maximum_num_containers = le32_to_cpu(dresp->ContainerSwitchEntries); | |
121 | aac_fib_complete(fibptr); | |
122 | } | |
123 | - aac_fib_free(fibptr); | |
124 | + /* FIB should be freed only after getting the response from the F/W */ | |
125 | + if (status != -ERESTARTSYS) | |
126 | + aac_fib_free(fibptr); | |
127 | ||
128 | if (maximum_num_containers < MAXIMUM_NUM_CONTAINERS) | |
129 | maximum_num_containers = MAXIMUM_NUM_CONTAINERS; | |
130 | @@ -1206,9 +1224,8 @@ | |
131 | ||
132 | static int aac_scsi_32_64(struct fib * fib, struct scsi_cmnd * cmd) | |
133 | { | |
134 | - if ((sizeof(dma_addr_t) > 4) && | |
135 | - (num_physpages > (0xFFFFFFFFULL >> PAGE_SHIFT)) && | |
136 | - (fib->dev->adapter_info.options & AAC_OPT_SGMAP_HOST64)) | |
137 | + if ((sizeof(dma_addr_t) > 4) && fib->dev->needs_dac && | |
138 | + (fib->dev->adapter_info.options & AAC_OPT_SGMAP_HOST64)) | |
139 | return FAILED; | |
140 | return aac_scsi_32(fib, cmd); | |
141 | } | |
142 | @@ -1238,8 +1255,12 @@ | |
143 | NULL); | |
144 | ||
145 | if (rcode < 0) { | |
146 | - aac_fib_complete(fibptr); | |
147 | - aac_fib_free(fibptr); | |
148 | + /* FIB should be freed only after | |
149 | + * getting the response from the F/W */ | |
150 | + if (rcode != -ERESTARTSYS) { | |
151 | + aac_fib_complete(fibptr); | |
152 | + aac_fib_free(fibptr); | |
153 | + } | |
154 | return rcode; | |
155 | } | |
156 | memcpy(&dev->adapter_info, info, sizeof(*info)); | |
157 | @@ -1263,6 +1284,12 @@ | |
158 | ||
159 | if (rcode >= 0) | |
160 | memcpy(&dev->supplement_adapter_info, sinfo, sizeof(*sinfo)); | |
161 | + if (rcode == -ERESTARTSYS) { | |
162 | + fibptr = aac_fib_alloc(dev); | |
163 | + if (!fibptr) | |
164 | + return -ENOMEM; | |
165 | + } | |
166 | + | |
167 | } | |
168 | ||
169 | ||
170 | @@ -1371,8 +1398,11 @@ | |
171 | if (dev->nondasd_support && !dev->in_reset) | |
172 | printk(KERN_INFO "%s%d: Non-DASD support enabled.\n",dev->name, dev->id); | |
173 | ||
174 | + if (dma_get_required_mask(&dev->pdev->dev) > DMA_32BIT_MASK) | |
175 | + dev->needs_dac = 1; | |
176 | dev->dac_support = 0; | |
177 | - if( (sizeof(dma_addr_t) > 4) && (dev->adapter_info.options & AAC_OPT_SGMAP_HOST64)){ | |
178 | + if ((sizeof(dma_addr_t) > 4) && dev->needs_dac && | |
179 | + (dev->adapter_info.options & AAC_OPT_SGMAP_HOST64)) { | |
180 | if (!dev->in_reset) | |
181 | printk(KERN_INFO "%s%d: 64bit support enabled.\n", | |
182 | dev->name, dev->id); | |
183 | @@ -1382,6 +1412,15 @@ | |
184 | if(dacmode != -1) { | |
185 | dev->dac_support = (dacmode!=0); | |
186 | } | |
187 | + | |
188 | + /* avoid problems with AAC_QUIRK_SCSI_32 controllers */ | |
189 | + if (dev->dac_support && (aac_get_driver_ident(dev->cardtype)->quirks | |
190 | + & AAC_QUIRK_SCSI_32)) { | |
191 | + dev->nondasd_support = 0; | |
192 | + dev->jbod = 0; | |
193 | + expose_physicals = 0; | |
194 | + } | |
195 | + | |
196 | if(dev->dac_support != 0) { | |
197 | if (!pci_set_dma_mask(dev->pdev, DMA_64BIT_MASK) && | |
198 | !pci_set_consistent_dma_mask(dev->pdev, DMA_64BIT_MASK)) { | |
199 | @@ -1451,9 +1490,11 @@ | |
200 | (dev->scsi_host_ptr->sg_tablesize * 8) + 112; | |
201 | } | |
202 | } | |
203 | - | |
204 | - aac_fib_complete(fibptr); | |
205 | - aac_fib_free(fibptr); | |
206 | + /* FIB should be freed only after getting the response from the F/W */ | |
207 | + if (rcode != -ERESTARTSYS) { | |
208 | + aac_fib_complete(fibptr); | |
209 | + aac_fib_free(fibptr); | |
210 | + } | |
211 | ||
212 | return rcode; | |
213 | } | |
214 | @@ -1614,6 +1655,7 @@ | |
215 | * Alocate and initialize a Fib | |
216 | */ | |
217 | if (!(cmd_fibcontext = aac_fib_alloc(dev))) { | |
218 | + printk(KERN_WARNING "aac_read: fib allocation failed\n"); | |
219 | return -1; | |
220 | } | |
221 | ||
222 | @@ -1693,9 +1735,14 @@ | |
223 | * Allocate and initialize a Fib then setup a BlockWrite command | |
224 | */ | |
225 | if (!(cmd_fibcontext = aac_fib_alloc(dev))) { | |
226 | - scsicmd->result = DID_ERROR << 16; | |
227 | - scsicmd->scsi_done(scsicmd); | |
228 | - return 0; | |
229 | + /* FIB temporarily unavailable,not catastrophic failure */ | |
230 | + | |
231 | + /* scsicmd->result = DID_ERROR << 16; | |
232 | + * scsicmd->scsi_done(scsicmd); | |
233 | + * return 0; | |
234 | + */ | |
235 | + printk(KERN_WARNING "aac_write: fib allocation failed\n"); | |
236 | + return -1; | |
237 | } | |
238 | ||
239 | status = aac_adapter_write(cmd_fibcontext, scsicmd, lba, count, fua); | |
240 | @@ -2058,7 +2105,7 @@ | |
241 | dprintk((KERN_DEBUG "INQUIRY command, ID: %d.\n", cid)); | |
242 | memset(&inq_data, 0, sizeof (struct inquiry_data)); | |
243 | ||
244 | - if (scsicmd->cmnd[1] & 0x1) { | |
245 | + if ((scsicmd->cmnd[1] & 0x1) && aac_wwn) { | |
246 | char *arr = (char *)&inq_data; | |
247 | ||
248 | /* EVPD bit set */ | |
249 | @@ -2081,7 +2128,12 @@ | |
250 | arr[1] = scsicmd->cmnd[2]; | |
251 | scsi_sg_copy_from_buffer(scsicmd, &inq_data, | |
252 | sizeof(inq_data)); | |
253 | - return aac_get_container_serial(scsicmd); | |
254 | + if (aac_wwn != 2) | |
255 | + return aac_get_container_serial( | |
256 | + scsicmd); | |
257 | + /* SLES 10 SP1 special */ | |
258 | + scsicmd->result = DID_OK << 16 | | |
259 | + COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; | |
260 | } else { | |
261 | /* vpd page not implemented */ | |
262 | scsicmd->result = DID_OK << 16 | | |
263 | diff -ru a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h | |
264 | --- a/drivers/scsi/aacraid/aacraid.h 2009-09-16 16:40:05.000000000 +0530 | |
265 | +++ b/drivers/scsi/aacraid/aacraid.h 2009-09-16 17:46:20.000000000 +0530 | |
266 | @@ -12,7 +12,7 @@ | |
267 | *----------------------------------------------------------------------------*/ | |
268 | ||
269 | #ifndef AAC_DRIVER_BUILD | |
270 | -# define AAC_DRIVER_BUILD 2456 | |
271 | +# define AAC_DRIVER_BUILD 24701 | |
272 | # define AAC_DRIVER_BRANCH "-ms" | |
273 | #endif | |
274 | #define MAXIMUM_NUM_CONTAINERS 32 | |
275 | @@ -865,7 +865,11 @@ | |
276 | u8 MfgPcbaSerialNo[12]; | |
277 | u8 MfgWWNName[8]; | |
278 | __le32 SupportedOptions2; | |
279 | - __le32 ReservedGrowth[1]; | |
280 | + __le32 StructExpansion; | |
281 | + /* StructExpansion == 1 */ | |
282 | + __le32 FeatureBits3; | |
283 | + __le32 SupportedPerformanceModes; | |
284 | + __le32 ReservedForFutureGrowth[80]; | |
285 | }; | |
286 | #define AAC_FEATURE_FALCON cpu_to_le32(0x00000010) | |
287 | #define AAC_FEATURE_JBOD cpu_to_le32(0x08000000) | |
288 | @@ -1020,6 +1024,7 @@ | |
289 | u8 jbod; | |
290 | u8 cache_protected; | |
291 | u8 dac_support; | |
292 | + u8 needs_dac; | |
293 | u8 raid_scsi_mode; | |
294 | u8 comm_interface; | |
295 | # define AAC_COMM_PRODUCER 0 | |
296 | @@ -1031,6 +1036,9 @@ | |
297 | u8 printf_enabled; | |
298 | u8 in_reset; | |
299 | u8 msi; | |
300 | + int management_fib_count; | |
301 | + spinlock_t manage_lock; | |
302 | + | |
303 | }; | |
304 | ||
305 | #define aac_adapter_interrupt(dev) \ | |
306 | diff -ru a/drivers/scsi/aacraid/commctrl.c b/drivers/scsi/aacraid/commctrl.c | |
307 | --- a/drivers/scsi/aacraid/commctrl.c 2009-09-16 16:40:05.000000000 +0530 | |
308 | +++ b/drivers/scsi/aacraid/commctrl.c 2009-09-16 17:41:00.000000000 +0530 | |
309 | @@ -143,7 +143,7 @@ | |
310 | fibptr->hw_fib_pa = hw_fib_pa; | |
311 | fibptr->hw_fib_va = hw_fib; | |
312 | } | |
313 | - if (retval != -EINTR) | |
314 | + if (retval != -ERESTARTSYS) | |
315 | aac_fib_free(fibptr); | |
316 | return retval; | |
317 | } | |
318 | @@ -312,7 +312,7 @@ | |
319 | } | |
320 | if (f.wait) { | |
321 | if(down_interruptible(&fibctx->wait_sem) < 0) { | |
322 | - status = -EINTR; | |
323 | + status = -ERESTARTSYS; | |
324 | } else { | |
325 | /* Lock again and retry */ | |
326 | spin_lock_irqsave(&dev->fib_lock, flags); | |
327 | @@ -583,10 +583,10 @@ | |
328 | u64 addr; | |
329 | void* p; | |
330 | if (upsg->sg[i].count > | |
331 | - (dev->adapter_info.options & | |
332 | + ((dev->adapter_info.options & | |
333 | AAC_OPT_NEW_COMM) ? | |
334 | (dev->scsi_host_ptr->max_sectors << 9) : | |
335 | - 65536) { | |
336 | + 65536)) { | |
337 | rcode = -EINVAL; | |
338 | goto cleanup; | |
339 | } | |
340 | @@ -635,10 +635,10 @@ | |
341 | u64 addr; | |
342 | void* p; | |
343 | if (usg->sg[i].count > | |
344 | - (dev->adapter_info.options & | |
345 | + ((dev->adapter_info.options & | |
346 | AAC_OPT_NEW_COMM) ? | |
347 | (dev->scsi_host_ptr->max_sectors << 9) : | |
348 | - 65536) { | |
349 | + 65536)) { | |
350 | rcode = -EINVAL; | |
351 | goto cleanup; | |
352 | } | |
353 | @@ -685,10 +685,10 @@ | |
354 | uintptr_t addr; | |
355 | void* p; | |
356 | if (usg->sg[i].count > | |
357 | - (dev->adapter_info.options & | |
358 | + ((dev->adapter_info.options & | |
359 | AAC_OPT_NEW_COMM) ? | |
360 | (dev->scsi_host_ptr->max_sectors << 9) : | |
361 | - 65536) { | |
362 | + 65536)) { | |
363 | rcode = -EINVAL; | |
364 | goto cleanup; | |
365 | } | |
366 | @@ -724,10 +724,10 @@ | |
367 | dma_addr_t addr; | |
368 | void* p; | |
369 | if (upsg->sg[i].count > | |
370 | - (dev->adapter_info.options & | |
371 | + ((dev->adapter_info.options & | |
372 | AAC_OPT_NEW_COMM) ? | |
373 | (dev->scsi_host_ptr->max_sectors << 9) : | |
374 | - 65536) { | |
375 | + 65536)) { | |
376 | rcode = -EINVAL; | |
377 | goto cleanup; | |
378 | } | |
379 | @@ -762,8 +762,8 @@ | |
380 | psg->count = cpu_to_le32(sg_indx+1); | |
381 | status = aac_fib_send(ScsiPortCommand, srbfib, actual_fibsize, FsaNormal, 1, 1, NULL, NULL); | |
382 | } | |
383 | - if (status == -EINTR) { | |
384 | - rcode = -EINTR; | |
385 | + if (status == -ERESTARTSYS) { | |
386 | + rcode = -ERESTARTSYS; | |
387 | goto cleanup; | |
388 | } | |
389 | ||
390 | @@ -800,7 +800,7 @@ | |
391 | for(i=0; i <= sg_indx; i++){ | |
392 | kfree(sg_list[i]); | |
393 | } | |
394 | - if (rcode != -EINTR) { | |
395 | + if (rcode != -ERESTARTSYS) { | |
396 | aac_fib_complete(srbfib); | |
397 | aac_fib_free(srbfib); | |
398 | } | |
399 | @@ -832,13 +832,22 @@ | |
400 | int aac_do_ioctl(struct aac_dev * dev, int cmd, void __user *arg) | |
401 | { | |
402 | int status; | |
403 | - | |
404 | + unsigned long mflags; | |
405 | + | |
406 | /* | |
407 | * HBA gets first crack | |
408 | */ | |
409 | ||
410 | + spin_lock_irqsave(&dev->manage_lock, mflags); | |
411 | + if (dev->management_fib_count > AAC_NUM_MGT_FIB) { | |
412 | + printk(KERN_INFO "No management Fibs Available:%d\n", | |
413 | + dev->management_fib_count); | |
414 | + spin_unlock_irqrestore(&dev->manage_lock, mflags); | |
415 | + return -EBUSY; | |
416 | + } | |
417 | + spin_unlock_irqrestore(&dev->manage_lock, mflags); | |
418 | status = aac_dev_ioctl(dev, cmd, arg); | |
419 | - if(status != -ENOTTY) | |
420 | + if (status != -ENOTTY) | |
421 | return status; | |
422 | ||
423 | switch (cmd) { | |
424 | diff -ru a/drivers/scsi/aacraid/comminit.c b/drivers/scsi/aacraid/comminit.c | |
425 | --- a/drivers/scsi/aacraid/comminit.c 2009-09-16 16:40:05.000000000 +0530 | |
426 | +++ b/drivers/scsi/aacraid/comminit.c 2009-09-16 17:41:00.000000000 +0530 | |
427 | @@ -54,6 +54,7 @@ | |
428 | const unsigned long printfbufsiz = 256; | |
429 | struct aac_init *init; | |
430 | dma_addr_t phys; | |
431 | + unsigned long aac_max_hostphysmempages; | |
432 | ||
433 | size = fibsize + sizeof(struct aac_init) + commsize + commalign + printfbufsiz; | |
434 | ||
435 | @@ -90,7 +91,18 @@ | |
436 | init->AdapterFibsPhysicalAddress = cpu_to_le32((u32)phys); | |
437 | init->AdapterFibsSize = cpu_to_le32(fibsize); | |
438 | init->AdapterFibAlign = cpu_to_le32(sizeof(struct hw_fib)); | |
439 | - init->HostPhysMemPages = cpu_to_le32(AAC_MAX_HOSTPHYSMEMPAGES); | |
440 | + /* | |
441 | + * number of 4k pages of host physical memory. The aacraid fw needs | |
442 | + * this number to be less than 4gb worth of pages. New firmware doesn't | |
443 | + * have any issues with the mapping system, but older Firmware did, and | |
444 | + * had *troubles* dealing with the math overloading past 32 bits, thus | |
445 | + * we must limit this field. | |
446 | + */ | |
447 | + aac_max_hostphysmempages = dma_get_required_mask(&dev->pdev->dev) >> 12; | |
448 | + if (aac_max_hostphysmempages < AAC_MAX_HOSTPHYSMEMPAGES) | |
449 | + init->HostPhysMemPages = cpu_to_le32(aac_max_hostphysmempages); | |
450 | + else | |
451 | + init->HostPhysMemPages = cpu_to_le32(AAC_MAX_HOSTPHYSMEMPAGES); | |
452 | ||
453 | init->InitFlags = 0; | |
454 | if (dev->comm_interface == AAC_COMM_MESSAGE) { | |
455 | @@ -182,7 +194,9 @@ | |
456 | ||
457 | if (status >= 0) | |
458 | aac_fib_complete(fibctx); | |
459 | - aac_fib_free(fibctx); | |
460 | + /* FIB should be freed only after getting the response from the F/W */ | |
461 | + if (status != -ERESTARTSYS) | |
462 | + aac_fib_free(fibctx); | |
463 | return status; | |
464 | } | |
465 | ||
466 | @@ -292,6 +306,8 @@ | |
467 | /* | |
468 | * Check the preferred comm settings, defaults from template. | |
469 | */ | |
470 | + dev->management_fib_count = 0; | |
471 | + spin_lock_init(&dev->manage_lock); | |
472 | dev->max_fib_size = sizeof(struct hw_fib); | |
473 | dev->sg_tablesize = host->sg_tablesize = (dev->max_fib_size | |
474 | - sizeof(struct aac_fibhdr) | |
475 | diff -ru a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c | |
476 | --- a/drivers/scsi/aacraid/commsup.c 2009-09-16 16:40:05.000000000 +0530 | |
477 | +++ b/drivers/scsi/aacraid/commsup.c 2009-09-16 17:41:00.000000000 +0530 | |
478 | @@ -189,7 +189,14 @@ | |
479 | ||
480 | void aac_fib_free(struct fib *fibptr) | |
481 | { | |
482 | - unsigned long flags; | |
483 | + unsigned long flags, flagsv; | |
484 | + | |
485 | + spin_lock_irqsave(&fibptr->event_lock, flagsv); | |
486 | + if (fibptr->done == 2) { | |
487 | + spin_unlock_irqrestore(&fibptr->event_lock, flagsv); | |
488 | + return; | |
489 | + } | |
490 | + spin_unlock_irqrestore(&fibptr->event_lock, flagsv); | |
491 | ||
492 | spin_lock_irqsave(&fibptr->dev->fib_lock, flags); | |
493 | if (unlikely(fibptr->flags & FIB_CONTEXT_FLAG_TIMED_OUT)) | |
494 | @@ -473,14 +480,27 @@ | |
495 | ||
496 | if(wait) | |
497 | spin_lock_irqsave(&fibptr->event_lock, flags); | |
498 | - aac_adapter_deliver(fibptr); | |
499 | + | |
500 | + if (aac_adapter_deliver(fibptr) != 0) { | |
501 | + printk(KERN_ERR "aac_fib_send: returned -EBUSY\n"); | |
502 | + if (wait) | |
503 | + spin_unlock_irqrestore(&fibptr->event_lock, flags); | |
504 | + return -EBUSY; | |
505 | + } | |
506 | + | |
507 | ||
508 | /* | |
509 | * If the caller wanted us to wait for response wait now. | |
510 | */ | |
511 | ||
512 | if (wait) { | |
513 | + unsigned long mflags; | |
514 | spin_unlock_irqrestore(&fibptr->event_lock, flags); | |
515 | + | |
516 | + spin_lock_irqsave(&dev->manage_lock, mflags); | |
517 | + dev->management_fib_count++; | |
518 | + spin_unlock_irqrestore(&dev->manage_lock, mflags); | |
519 | + | |
520 | /* Only set for first known interruptable command */ | |
521 | if (wait < 0) { | |
522 | /* | |
523 | @@ -515,15 +535,14 @@ | |
524 | } | |
525 | udelay(5); | |
526 | } | |
527 | - } else if (down_interruptible(&fibptr->event_wait)) { | |
528 | - fibptr->done = 2; | |
529 | - up(&fibptr->event_wait); | |
530 | - } | |
531 | + } else | |
532 | + down_interruptible(&fibptr->event_wait); | |
533 | + | |
534 | spin_lock_irqsave(&fibptr->event_lock, flags); | |
535 | - if ((fibptr->done == 0) || (fibptr->done == 2)) { | |
536 | + if (fibptr->done == 0) { | |
537 | fibptr->done = 2; /* Tell interrupt we aborted */ | |
538 | spin_unlock_irqrestore(&fibptr->event_lock, flags); | |
539 | - return -EINTR; | |
540 | + return -ERESTARTSYS; | |
541 | } | |
542 | spin_unlock_irqrestore(&fibptr->event_lock, flags); | |
543 | BUG_ON(fibptr->done == 0); | |
544 | @@ -689,6 +708,7 @@ | |
545 | ||
546 | int aac_fib_complete(struct fib *fibptr) | |
547 | { | |
548 | + unsigned long flags; | |
549 | struct hw_fib * hw_fib = fibptr->hw_fib_va; | |
550 | ||
551 | /* | |
552 | @@ -709,6 +729,13 @@ | |
553 | * command is complete that we had sent to the adapter and this | |
554 | * cdb could be reused. | |
555 | */ | |
556 | + spin_lock_irqsave(&fibptr->event_lock, flags); | |
557 | + if (fibptr->done == 2) { | |
558 | + spin_unlock_irqrestore(&fibptr->event_lock, flags); | |
559 | + return 0; | |
560 | + } | |
561 | + spin_unlock_irqrestore(&fibptr->event_lock, flags); | |
562 | + | |
563 | if((hw_fib->header.XferState & cpu_to_le32(SentFromHost)) && | |
564 | (hw_fib->header.XferState & cpu_to_le32(AdapterProcessed))) | |
565 | { | |
566 | @@ -1355,7 +1382,10 @@ | |
567 | ||
568 | if (status >= 0) | |
569 | aac_fib_complete(fibctx); | |
570 | - aac_fib_free(fibctx); | |
571 | + /* FIB should be freed only after getting | |
572 | + * the response from the F/W */ | |
573 | + if (status != -ERESTARTSYS) | |
574 | + aac_fib_free(fibctx); | |
575 | } | |
576 | } | |
577 | ||
578 | @@ -1759,6 +1789,7 @@ | |
579 | struct fib *fibptr; | |
580 | ||
581 | if ((fibptr = aac_fib_alloc(dev))) { | |
582 | + int status; | |
583 | __le32 *info; | |
584 | ||
585 | aac_fib_init(fibptr); | |
586 | @@ -1769,15 +1800,21 @@ | |
587 | ||
588 | *info = cpu_to_le32(now.tv_sec); | |
589 | ||
590 | - (void)aac_fib_send(SendHostTime, | |
591 | + status = aac_fib_send(SendHostTime, | |
592 | fibptr, | |
593 | sizeof(*info), | |
594 | FsaNormal, | |
595 | 1, 1, | |
596 | NULL, | |
597 | NULL); | |
598 | - aac_fib_complete(fibptr); | |
599 | - aac_fib_free(fibptr); | |
600 | + /* Do not set XferState to zero unless | |
601 | + * receives a response from F/W */ | |
602 | + if (status >= 0) | |
603 | + aac_fib_complete(fibptr); | |
604 | + /* FIB should be freed only after | |
605 | + * getting the response from the F/W */ | |
606 | + if (status != -ERESTARTSYS) | |
607 | + aac_fib_free(fibptr); | |
608 | } | |
609 | difference = (long)(unsigned)update_interval*HZ; | |
610 | } else { | |
611 | diff -ru a/drivers/scsi/aacraid/dpcsup.c b/drivers/scsi/aacraid/dpcsup.c | |
612 | --- a/drivers/scsi/aacraid/dpcsup.c 2009-09-16 16:40:05.000000000 +0530 | |
613 | +++ b/drivers/scsi/aacraid/dpcsup.c 2009-09-16 17:41:00.000000000 +0530 | |
614 | @@ -57,7 +57,7 @@ | |
615 | struct hw_fib * hwfib; | |
616 | struct fib * fib; | |
617 | int consumed = 0; | |
618 | - unsigned long flags; | |
619 | + unsigned long flags, mflags; | |
620 | ||
621 | spin_lock_irqsave(q->lock, flags); | |
622 | /* | |
623 | @@ -125,12 +125,21 @@ | |
624 | } else { | |
625 | unsigned long flagv; | |
626 | spin_lock_irqsave(&fib->event_lock, flagv); | |
627 | - if (!fib->done) | |
628 | + if (!fib->done) { | |
629 | fib->done = 1; | |
630 | - up(&fib->event_wait); | |
631 | + up(&fib->event_wait); | |
632 | + } | |
633 | spin_unlock_irqrestore(&fib->event_lock, flagv); | |
634 | + | |
635 | + spin_lock_irqsave(&dev->manage_lock, mflags); | |
636 | + dev->management_fib_count--; | |
637 | + spin_unlock_irqrestore(&dev->manage_lock, mflags); | |
638 | + | |
639 | FIB_COUNTER_INCREMENT(aac_config.NormalRecved); | |
640 | if (fib->done == 2) { | |
641 | + spin_lock_irqsave(&fib->event_lock, flagv); | |
642 | + fib->done = 0; | |
643 | + spin_unlock_irqrestore(&fib->event_lock, flagv); | |
644 | aac_fib_complete(fib); | |
645 | aac_fib_free(fib); | |
646 | } | |
647 | @@ -232,6 +241,7 @@ | |
648 | ||
649 | unsigned int aac_intr_normal(struct aac_dev * dev, u32 index) | |
650 | { | |
651 | + unsigned long mflags; | |
652 | dprintk((KERN_INFO "aac_intr_normal(%p,%x)\n", dev, index)); | |
653 | if ((index & 0x00000002L)) { | |
654 | struct hw_fib * hw_fib; | |
655 | @@ -320,11 +330,25 @@ | |
656 | unsigned long flagv; | |
657 | dprintk((KERN_INFO "event_wait up\n")); | |
658 | spin_lock_irqsave(&fib->event_lock, flagv); | |
659 | - if (!fib->done) | |
660 | + if (!fib->done) { | |
661 | fib->done = 1; | |
662 | - up(&fib->event_wait); | |
663 | + up(&fib->event_wait); | |
664 | + } | |
665 | spin_unlock_irqrestore(&fib->event_lock, flagv); | |
666 | + | |
667 | + spin_lock_irqsave(&dev->manage_lock, mflags); | |
668 | + dev->management_fib_count--; | |
669 | + spin_unlock_irqrestore(&dev->manage_lock, mflags); | |
670 | + | |
671 | FIB_COUNTER_INCREMENT(aac_config.NormalRecved); | |
672 | + if (fib->done == 2) { | |
673 | + spin_lock_irqsave(&fib->event_lock, flagv); | |
674 | + fib->done = 0; | |
675 | + spin_unlock_irqrestore(&fib->event_lock, flagv); | |
676 | + aac_fib_complete(fib); | |
677 | + aac_fib_free(fib); | |
678 | + } | |
679 | + | |
680 | } | |
681 | return 0; | |
682 | } | |
683 | diff -ru a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c | |
684 | --- a/drivers/scsi/aacraid/linit.c 2009-09-16 16:40:05.000000000 +0530 | |
685 | +++ b/drivers/scsi/aacraid/linit.c 2009-09-16 17:41:00.000000000 +0530 | |
686 | @@ -86,7 +86,13 @@ | |
687 | * | |
688 | * Note: The last field is used to index into aac_drivers below. | |
689 | */ | |
690 | -static struct pci_device_id aac_pci_tbl[] = { | |
691 | +#ifdef DECLARE_PCI_DEVICE_TABLE | |
692 | +static DECLARE_PCI_DEVICE_TABLE(aac_pci_tbl) = { | |
693 | +#elif defined(__devinitconst) | |
694 | +static const struct pci_device_id aac_pci_tbl[] __devinitconst = { | |
695 | +#else | |
696 | +static const struct pci_device_id aac_pci_tbl[] __devinitdata = { | |
697 | +#endif | |
698 | { 0x1028, 0x0001, 0x1028, 0x0001, 0, 0, 0 }, /* PERC 2/Si (Iguana/PERC2Si) */ | |
699 | { 0x1028, 0x0002, 0x1028, 0x0002, 0, 0, 1 }, /* PERC 3/Di (Opal/PERC3Di) */ | |
700 | { 0x1028, 0x0003, 0x1028, 0x0003, 0, 0, 2 }, /* PERC 3/Si (SlimFast/PERC3Si */ |