aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/aacraid/aachba.c
diff options
context:
space:
mode:
authorMark Haverkamp <markh@linux-foundation.org>2007-03-15 13:27:45 -0400
committerJames Bottomley <jejb@mulgrave.il.steeleye.com>2007-03-20 11:56:03 -0400
commit03d4433721880bf1972c924b168e4e1dd3c59d53 (patch)
tree820ad2f8aea551d03e7ff8751aba7dfe1f674bcd /drivers/scsi/aacraid/aachba.c
parentf2b1a06ad46209c6e631e3099138d1fa3f14d3a8 (diff)
[SCSI] aacraid: Improved error handling
Received from Mark Salyzyn, This set of fixes improve error handling stability of the driver. A popular manifestation of the problems is an NULL pointer reference in the interrupt handler when referencing portions of the scsi command context, or in the scsi_done handling when an offlined device is referenced. The aacraid driver currently does not get notification of orphaned command completions due to devices going offline. The driver also fails to handle the commands that are finished by the error handler, and thus can complete again later at the hands of the adapter causing situations of completion of an invalid scsi command context. Test Unit Ready calls abort assuming that the abort was successful, but are not, and thus when the interrupt from the adapter occurs, they reference invalid command contexts. We add in a TIMED_OUT flag to inform the aacraid FIB context that the interrupt service should merely release the driver resources and not complete the command up. We take advantage of this with the abort handler as well for select abortable commands. And we detect and react if a command that can not be aborted is currently still outstanding to the controller when reissued by the retry mechanism. Signed-off-by: Mark Haverkamp <markh@linux-foundation.org> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi/aacraid/aachba.c')
-rw-r--r--drivers/scsi/aacraid/aachba.c51
1 files changed, 48 insertions, 3 deletions
diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c
index 3d21d7dd2e5f..0c4e27eb6520 100644
--- a/drivers/scsi/aacraid/aachba.c
+++ b/drivers/scsi/aacraid/aachba.c
@@ -5,7 +5,7 @@
5 * based on the old aacraid driver that is.. 5 * based on the old aacraid driver that is..
6 * Adaptec aacraid device driver for Linux. 6 * Adaptec aacraid device driver for Linux.
7 * 7 *
8 * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com) 8 * Copyright (c) 2000-2007 Adaptec, Inc. (aacraid@adaptec.com)
9 * 9 *
10 * This program is free software; you can redistribute it and/or modify 10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by 11 * it under the terms of the GNU General Public License as published by
@@ -172,6 +172,30 @@ MODULE_PARM_DESC(acbsize, "Request a specific adapter control block (FIB) size.
172int expose_physicals = -1; 172int expose_physicals = -1;
173module_param(expose_physicals, int, S_IRUGO|S_IWUSR); 173module_param(expose_physicals, int, S_IRUGO|S_IWUSR);
174MODULE_PARM_DESC(expose_physicals, "Expose physical components of the arrays. -1=protect 0=off, 1=on"); 174MODULE_PARM_DESC(expose_physicals, "Expose physical components of the arrays. -1=protect 0=off, 1=on");
175
176
177static inline int aac_valid_context(struct scsi_cmnd *scsicmd,
178 struct fib *fibptr) {
179 struct scsi_device *device;
180
181 if (unlikely(!scsicmd || !scsicmd->scsi_done )) {
182 dprintk((KERN_WARNING "aac_valid_context: scsi command corrupt\n"))
183;
184 aac_fib_complete(fibptr);
185 aac_fib_free(fibptr);
186 return 0;
187 }
188 scsicmd->SCp.phase = AAC_OWNER_MIDLEVEL;
189 device = scsicmd->device;
190 if (unlikely(!device || !scsi_device_online(device))) {
191 dprintk((KERN_WARNING "aac_valid_context: scsi device corrupt\n"));
192 aac_fib_complete(fibptr);
193 aac_fib_free(fibptr);
194 return 0;
195 }
196 return 1;
197}
198
175/** 199/**
176 * aac_get_config_status - check the adapter configuration 200 * aac_get_config_status - check the adapter configuration
177 * @common: adapter to query 201 * @common: adapter to query
@@ -342,6 +366,9 @@ static void get_container_name_callback(void *context, struct fib * fibptr)
342 scsicmd = (struct scsi_cmnd *) context; 366 scsicmd = (struct scsi_cmnd *) context;
343 scsicmd->SCp.phase = AAC_OWNER_MIDLEVEL; 367 scsicmd->SCp.phase = AAC_OWNER_MIDLEVEL;
344 368
369 if (!aac_valid_context(scsicmd, fibptr))
370 return;
371
345 dprintk((KERN_DEBUG "get_container_name_callback[cpu %d]: t = %ld.\n", smp_processor_id(), jiffies)); 372 dprintk((KERN_DEBUG "get_container_name_callback[cpu %d]: t = %ld.\n", smp_processor_id(), jiffies));
346 BUG_ON(fibptr == NULL); 373 BUG_ON(fibptr == NULL);
347 374
@@ -431,9 +458,14 @@ static int aac_probe_container_callback2(struct scsi_cmnd * scsicmd)
431 458
432static int _aac_probe_container2(void * context, struct fib * fibptr) 459static int _aac_probe_container2(void * context, struct fib * fibptr)
433{ 460{
434 struct scsi_cmnd * scsicmd = (struct scsi_cmnd *)context; 461 struct fsa_dev_info *fsa_dev_ptr;
435 struct fsa_dev_info *fsa_dev_ptr = ((struct aac_dev *)(scsicmd->device->host->hostdata))->fsa_dev;
436 int (*callback)(struct scsi_cmnd *); 462 int (*callback)(struct scsi_cmnd *);
463 struct scsi_cmnd * scsicmd = (struct scsi_cmnd *)context;
464
465 if (!aac_valid_context(scsicmd, fibptr))
466 return 0;
467
468 fsa_dev_ptr = ((struct aac_dev *)(scsicmd->device->host->hostdata))->fsa_dev;
437 469
438 scsicmd->SCp.Status = 0; 470 scsicmd->SCp.Status = 0;
439 if (fsa_dev_ptr) { 471 if (fsa_dev_ptr) {
@@ -477,6 +509,9 @@ static int _aac_probe_container1(void * context, struct fib * fibptr)
477 scsicmd = (struct scsi_cmnd *) context; 509 scsicmd = (struct scsi_cmnd *) context;
478 scsicmd->SCp.phase = AAC_OWNER_MIDLEVEL; 510 scsicmd->SCp.phase = AAC_OWNER_MIDLEVEL;
479 511
512 if (!aac_valid_context(scsicmd, fibptr))
513 return 0;
514
480 aac_fib_init(fibptr); 515 aac_fib_init(fibptr);
481 516
482 dinfo = (struct aac_query_mount *)fib_data(fibptr); 517 dinfo = (struct aac_query_mount *)fib_data(fibptr);
@@ -1287,6 +1322,9 @@ static void io_callback(void *context, struct fib * fibptr)
1287 scsicmd = (struct scsi_cmnd *) context; 1322 scsicmd = (struct scsi_cmnd *) context;
1288 scsicmd->SCp.phase = AAC_OWNER_MIDLEVEL; 1323 scsicmd->SCp.phase = AAC_OWNER_MIDLEVEL;
1289 1324
1325 if (!aac_valid_context(scsicmd, fibptr))
1326 return;
1327
1290 dev = (struct aac_dev *)scsicmd->device->host->hostdata; 1328 dev = (struct aac_dev *)scsicmd->device->host->hostdata;
1291 cid = scmd_id(scsicmd); 1329 cid = scmd_id(scsicmd);
1292 1330
@@ -1534,6 +1572,9 @@ static void synchronize_callback(void *context, struct fib *fibptr)
1534 cmd = context; 1572 cmd = context;
1535 cmd->SCp.phase = AAC_OWNER_MIDLEVEL; 1573 cmd->SCp.phase = AAC_OWNER_MIDLEVEL;
1536 1574
1575 if (!aac_valid_context(cmd, fibptr))
1576 return;
1577
1537 dprintk((KERN_DEBUG "synchronize_callback[cpu %d]: t = %ld.\n", 1578 dprintk((KERN_DEBUG "synchronize_callback[cpu %d]: t = %ld.\n",
1538 smp_processor_id(), jiffies)); 1579 smp_processor_id(), jiffies));
1539 BUG_ON(fibptr == NULL); 1580 BUG_ON(fibptr == NULL);
@@ -2086,6 +2127,10 @@ static void aac_srb_callback(void *context, struct fib * fibptr)
2086 2127
2087 scsicmd = (struct scsi_cmnd *) context; 2128 scsicmd = (struct scsi_cmnd *) context;
2088 scsicmd->SCp.phase = AAC_OWNER_MIDLEVEL; 2129 scsicmd->SCp.phase = AAC_OWNER_MIDLEVEL;
2130
2131 if (!aac_valid_context(scsicmd, fibptr))
2132 return;
2133
2089 dev = (struct aac_dev *)scsicmd->device->host->hostdata; 2134 dev = (struct aac_dev *)scsicmd->device->host->hostdata;
2090 2135
2091 BUG_ON(fibptr == NULL); 2136 BUG_ON(fibptr == NULL);