aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/aacraid
diff options
context:
space:
mode:
authorSalyzyn, Mark <Mark_Salyzyn@adaptec.com>2008-01-08 16:26:43 -0500
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2008-01-23 12:29:21 -0500
commitb6ef70f33ca2a3084b4fea12414550724a9114dc (patch)
tree4b8b857371adb3439c80c3612598411f46a54330 /drivers/scsi/aacraid
parent6dcd4a7fe5dfaace2763187d6941e700a8bc6f27 (diff)
[SCSI] aacraid: OS panic after Adapter panic (hardening).
In experiments in the lab we managed to trigger an Adapter firmware panic (BlinkLED) coincidentally while several pass-through ioctl command from the management software were outstanding on a bug only present on a class of RAID Adapters that require a hardware reset rather than a commanded reset. The net result was an attempt to time out the management software command as if it came from the SCSI layer resulting in an OS panic. Adapters that use commanded reset, management commands are returned failed by the Adapter correctly. The adapter firmware panic that resulted in this condition was also resolved, and there were no adapters in the field with this specific firmware bug so we do not expect any field reports. This is a rare or unlikely corner condition, and no reports have ever been forwarded from the field. Signed-off-by: Mark Salyzyn <aacraid@adaptec.com> Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers/scsi/aacraid')
-rw-r--r--drivers/scsi/aacraid/aacraid.h1
-rw-r--r--drivers/scsi/aacraid/commsup.c4
-rw-r--r--drivers/scsi/aacraid/dpcsup.c4
-rw-r--r--drivers/scsi/aacraid/linit.c19
4 files changed, 25 insertions, 3 deletions
diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h
index 07def7261004..85b85ae198f4 100644
--- a/drivers/scsi/aacraid/aacraid.h
+++ b/drivers/scsi/aacraid/aacraid.h
@@ -1073,6 +1073,7 @@ struct aac_dev
1073 (dev)->a_ops.adapter_comm(dev, comm) 1073 (dev)->a_ops.adapter_comm(dev, comm)
1074 1074
1075#define FIB_CONTEXT_FLAG_TIMED_OUT (0x00000001) 1075#define FIB_CONTEXT_FLAG_TIMED_OUT (0x00000001)
1076#define FIB_CONTEXT_FLAG (0x00000002)
1076 1077
1077/* 1078/*
1078 * Define the command values 1079 * Define the command values
diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c
index e82d89ccaf15..3a3017d8dc65 100644
--- a/drivers/scsi/aacraid/commsup.c
+++ b/drivers/scsi/aacraid/commsup.c
@@ -171,6 +171,7 @@ struct fib *aac_fib_alloc(struct aac_dev *dev)
171 * each I/O 171 * each I/O
172 */ 172 */
173 fibptr->hw_fib_va->header.XferState = 0; 173 fibptr->hw_fib_va->header.XferState = 0;
174 fibptr->flags = 0;
174 fibptr->callback = NULL; 175 fibptr->callback = NULL;
175 fibptr->callback_data = NULL; 176 fibptr->callback_data = NULL;
176 177
@@ -402,6 +403,7 @@ int aac_fib_send(u16 command, struct fib *fibptr, unsigned long size,
402 * will have a debug mode where the adapter can notify the host 403 * will have a debug mode where the adapter can notify the host
403 * it had a problem and the host can log that fact. 404 * it had a problem and the host can log that fact.
404 */ 405 */
406 fibptr->flags = 0;
405 if (wait && !reply) { 407 if (wait && !reply) {
406 return -EINVAL; 408 return -EINVAL;
407 } else if (!wait && reply) { 409 } else if (!wait && reply) {
@@ -450,10 +452,10 @@ int aac_fib_send(u16 command, struct fib *fibptr, unsigned long size,
450 if (!wait) { 452 if (!wait) {
451 fibptr->callback = callback; 453 fibptr->callback = callback;
452 fibptr->callback_data = callback_data; 454 fibptr->callback_data = callback_data;
455 fibptr->flags = FIB_CONTEXT_FLAG;
453 } 456 }
454 457
455 fibptr->done = 0; 458 fibptr->done = 0;
456 fibptr->flags = 0;
457 459
458 FIB_COUNTER_INCREMENT(aac_config.FibsSent); 460 FIB_COUNTER_INCREMENT(aac_config.FibsSent);
459 461
diff --git a/drivers/scsi/aacraid/dpcsup.c b/drivers/scsi/aacraid/dpcsup.c
index 4726ab666c52..d1163ded132b 100644
--- a/drivers/scsi/aacraid/dpcsup.c
+++ b/drivers/scsi/aacraid/dpcsup.c
@@ -120,6 +120,7 @@ unsigned int aac_response_normal(struct aac_queue * q)
120 * NOTE: we cannot touch the fib after this 120 * NOTE: we cannot touch the fib after this
121 * call, because it may have been deallocated. 121 * call, because it may have been deallocated.
122 */ 122 */
123 fib->flags = 0;
123 fib->callback(fib->callback_data, fib); 124 fib->callback(fib->callback_data, fib);
124 } else { 125 } else {
125 unsigned long flagv; 126 unsigned long flagv;
@@ -229,7 +230,7 @@ unsigned int aac_command_normal(struct aac_queue *q)
229 * all QE there are and wake up all the waiters before exiting. 230 * all QE there are and wake up all the waiters before exiting.
230 */ 231 */
231 232
232unsigned int aac_intr_normal(struct aac_dev *dev, u32 index) 233unsigned int aac_intr_normal(struct aac_dev * dev, u32 index)
233{ 234{
234 dprintk((KERN_INFO "aac_intr_normal(%p,%x)\n", dev, index)); 235 dprintk((KERN_INFO "aac_intr_normal(%p,%x)\n", dev, index));
235 if ((index & 0x00000002L)) { 236 if ((index & 0x00000002L)) {
@@ -313,6 +314,7 @@ unsigned int aac_intr_normal(struct aac_dev *dev, u32 index)
313 * NOTE: we cannot touch the fib after this 314 * NOTE: we cannot touch the fib after this
314 * call, because it may have been deallocated. 315 * call, because it may have been deallocated.
315 */ 316 */
317 fib->flags = 0;
316 fib->callback(fib->callback_data, fib); 318 fib->callback(fib->callback_data, fib);
317 } else { 319 } else {
318 unsigned long flagv; 320 unsigned long flagv;
diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c
index 742e1a8edc60..6a553ea730db 100644
--- a/drivers/scsi/aacraid/linit.c
+++ b/drivers/scsi/aacraid/linit.c
@@ -536,17 +536,33 @@ static int aac_eh_abort(struct scsi_cmnd* cmd)
536 break; 536 break;
537 case INQUIRY: 537 case INQUIRY:
538 case READ_CAPACITY: 538 case READ_CAPACITY:
539 case TEST_UNIT_READY:
540 /* Mark associated FIB to not complete, eh handler does this */ 539 /* Mark associated FIB to not complete, eh handler does this */
541 for (count = 0; count < (host->can_queue + AAC_NUM_MGT_FIB); ++count) { 540 for (count = 0; count < (host->can_queue + AAC_NUM_MGT_FIB); ++count) {
542 struct fib * fib = &aac->fibs[count]; 541 struct fib * fib = &aac->fibs[count];
543 if (fib->hw_fib_va->header.XferState && 542 if (fib->hw_fib_va->header.XferState &&
543 (fib->flags & FIB_CONTEXT_FLAG) &&
544 (fib->callback_data == cmd)) { 544 (fib->callback_data == cmd)) {
545 fib->flags |= FIB_CONTEXT_FLAG_TIMED_OUT; 545 fib->flags |= FIB_CONTEXT_FLAG_TIMED_OUT;
546 cmd->SCp.phase = AAC_OWNER_ERROR_HANDLER; 546 cmd->SCp.phase = AAC_OWNER_ERROR_HANDLER;
547 ret = SUCCESS; 547 ret = SUCCESS;
548 } 548 }
549 } 549 }
550 break;
551 case TEST_UNIT_READY:
552 /* Mark associated FIB to not complete, eh handler does this */
553 for (count = 0; count < (host->can_queue + AAC_NUM_MGT_FIB); ++count) {
554 struct scsi_cmnd * command;
555 struct fib * fib = &aac->fibs[count];
556 if ((fib->hw_fib_va->header.XferState & cpu_to_le32(Async | NoResponseExpected)) &&
557 (fib->flags & FIB_CONTEXT_FLAG) &&
558 ((command = fib->callback_data)) &&
559 (command->device == cmd->device)) {
560 fib->flags |= FIB_CONTEXT_FLAG_TIMED_OUT;
561 command->SCp.phase = AAC_OWNER_ERROR_HANDLER;
562 if (command == cmd)
563 ret = SUCCESS;
564 }
565 }
550 } 566 }
551 return ret; 567 return ret;
552} 568}
@@ -569,6 +585,7 @@ static int aac_eh_reset(struct scsi_cmnd* cmd)
569 for (count = 0; count < (host->can_queue + AAC_NUM_MGT_FIB); ++count) { 585 for (count = 0; count < (host->can_queue + AAC_NUM_MGT_FIB); ++count) {
570 struct fib * fib = &aac->fibs[count]; 586 struct fib * fib = &aac->fibs[count];
571 if (fib->hw_fib_va->header.XferState && 587 if (fib->hw_fib_va->header.XferState &&
588 (fib->flags & FIB_CONTEXT_FLAG) &&
572 (fib->callback_data == cmd)) { 589 (fib->callback_data == cmd)) {
573 fib->flags |= FIB_CONTEXT_FLAG_TIMED_OUT; 590 fib->flags |= FIB_CONTEXT_FLAG_TIMED_OUT;
574 cmd->SCp.phase = AAC_OWNER_ERROR_HANDLER; 591 cmd->SCp.phase = AAC_OWNER_ERROR_HANDLER;