aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/aacraid/linit.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/aacraid/linit.c')
-rw-r--r--drivers/scsi/aacraid/linit.c65
1 files changed, 59 insertions, 6 deletions
diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c
index 0f948c2fb609..350ea7feb61d 100644
--- a/drivers/scsi/aacraid/linit.c
+++ b/drivers/scsi/aacraid/linit.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
@@ -82,8 +82,6 @@ static LIST_HEAD(aac_devices);
82static int aac_cfg_major = -1; 82static int aac_cfg_major = -1;
83char aac_driver_version[] = AAC_DRIVER_FULL_VERSION; 83char aac_driver_version[] = AAC_DRIVER_FULL_VERSION;
84 84
85extern int expose_physicals;
86
87/* 85/*
88 * Because of the way Linux names scsi devices, the order in this table has 86 * Because of the way Linux names scsi devices, the order in this table has
89 * become important. Check for on-board Raid first, add-in cards second. 87 * become important. Check for on-board Raid first, add-in cards second.
@@ -247,7 +245,19 @@ static struct aac_driver_ident aac_drivers[] = {
247 245
248static int aac_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)) 246static int aac_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
249{ 247{
248 struct Scsi_Host *host = cmd->device->host;
249 struct aac_dev *dev = (struct aac_dev *)host->hostdata;
250 u32 count = 0;
250 cmd->scsi_done = done; 251 cmd->scsi_done = done;
252 for (; count < (host->can_queue + AAC_NUM_MGT_FIB); ++count) {
253 struct fib * fib = &dev->fibs[count];
254 struct scsi_cmnd * command;
255 if (fib->hw_fib_va->header.XferState &&
256 ((command = fib->callback_data)) &&
257 (command == cmd) &&
258 (cmd->SCp.phase == AAC_OWNER_FIRMWARE))
259 return 0; /* Already owned by Adapter */
260 }
251 cmd->SCp.phase = AAC_OWNER_LOWLEVEL; 261 cmd->SCp.phase = AAC_OWNER_LOWLEVEL;
252 return (aac_scsi_cmd(cmd) ? FAILED : 0); 262 return (aac_scsi_cmd(cmd) ? FAILED : 0);
253} 263}
@@ -446,6 +456,40 @@ static int aac_ioctl(struct scsi_device *sdev, int cmd, void __user * arg)
446 return aac_do_ioctl(dev, cmd, arg); 456 return aac_do_ioctl(dev, cmd, arg);
447} 457}
448 458
459static int aac_eh_abort(struct scsi_cmnd* cmd)
460{
461 struct scsi_device * dev = cmd->device;
462 struct Scsi_Host * host = dev->host;
463 struct aac_dev * aac = (struct aac_dev *)host->hostdata;
464 int count;
465 int ret = FAILED;
466
467 printk(KERN_ERR "%s: Host adapter abort request (%d,%d,%d,%d)\n",
468 AAC_DRIVERNAME,
469 host->host_no, sdev_channel(dev), sdev_id(dev), dev->lun);
470 switch (cmd->cmnd[0]) {
471 case SERVICE_ACTION_IN:
472 if (!(aac->raw_io_interface) ||
473 !(aac->raw_io_64) ||
474 ((cmd->cmnd[1] & 0x1f) != SAI_READ_CAPACITY_16))
475 break;
476 case INQUIRY:
477 case READ_CAPACITY:
478 case TEST_UNIT_READY:
479 /* Mark associated FIB to not complete, eh handler does this */
480 for (count = 0; count < (host->can_queue + AAC_NUM_MGT_FIB); ++count) {
481 struct fib * fib = &aac->fibs[count];
482 if (fib->hw_fib_va->header.XferState &&
483 (fib->callback_data == cmd)) {
484 fib->flags |= FIB_CONTEXT_FLAG_TIMED_OUT;
485 cmd->SCp.phase = AAC_OWNER_ERROR_HANDLER;
486 ret = SUCCESS;
487 }
488 }
489 }
490 return ret;
491}
492
449/* 493/*
450 * aac_eh_reset - Reset command handling 494 * aac_eh_reset - Reset command handling
451 * @scsi_cmd: SCSI command block causing the reset 495 * @scsi_cmd: SCSI command block causing the reset
@@ -457,12 +501,20 @@ static int aac_eh_reset(struct scsi_cmnd* cmd)
457 struct Scsi_Host * host = dev->host; 501 struct Scsi_Host * host = dev->host;
458 struct scsi_cmnd * command; 502 struct scsi_cmnd * command;
459 int count; 503 int count;
460 struct aac_dev * aac; 504 struct aac_dev * aac = (struct aac_dev *)host->hostdata;
461 unsigned long flags; 505 unsigned long flags;
462 506
507 /* Mark the associated FIB to not complete, eh handler does this */
508 for (count = 0; count < (host->can_queue + AAC_NUM_MGT_FIB); ++count) {
509 struct fib * fib = &aac->fibs[count];
510 if (fib->hw_fib_va->header.XferState &&
511 (fib->callback_data == cmd)) {
512 fib->flags |= FIB_CONTEXT_FLAG_TIMED_OUT;
513 cmd->SCp.phase = AAC_OWNER_ERROR_HANDLER;
514 }
515 }
463 printk(KERN_ERR "%s: Host adapter reset request. SCSI hang ?\n", 516 printk(KERN_ERR "%s: Host adapter reset request. SCSI hang ?\n",
464 AAC_DRIVERNAME); 517 AAC_DRIVERNAME);
465 aac = (struct aac_dev *)host->hostdata;
466 518
467 if ((count = aac_check_health(aac))) 519 if ((count = aac_check_health(aac)))
468 return count; 520 return count;
@@ -496,7 +548,7 @@ static int aac_eh_reset(struct scsi_cmnd* cmd)
496 ssleep(1); 548 ssleep(1);
497 } 549 }
498 printk(KERN_ERR "%s: SCSI bus appears hung\n", AAC_DRIVERNAME); 550 printk(KERN_ERR "%s: SCSI bus appears hung\n", AAC_DRIVERNAME);
499 return -ETIMEDOUT; 551 return SUCCESS; /* Cause an immediate retry of the command with a ten second delay after successful tur */
500} 552}
501 553
502/** 554/**
@@ -796,6 +848,7 @@ static struct scsi_host_template aac_driver_template = {
796 .bios_param = aac_biosparm, 848 .bios_param = aac_biosparm,
797 .shost_attrs = aac_attrs, 849 .shost_attrs = aac_attrs,
798 .slave_configure = aac_slave_configure, 850 .slave_configure = aac_slave_configure,
851 .eh_abort_handler = aac_eh_abort,
799 .eh_host_reset_handler = aac_eh_reset, 852 .eh_host_reset_handler = aac_eh_reset,
800 .can_queue = AAC_NUM_IO_FIB, 853 .can_queue = AAC_NUM_IO_FIB,
801 .this_id = MAXIMUM_NUM_CONTAINERS, 854 .this_id = MAXIMUM_NUM_CONTAINERS,