summaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorJeff Garzik <jgarzik@pobox.com>2005-05-28 07:54:40 -0400
committerJeff Garzik <jgarzik@pobox.com>2005-06-17 12:04:55 -0500
commit8fa728a26886f56a9ee10a44fea0ddda301d21c3 (patch)
tree105ead5c90057400abae0c8aa9e2b5ba1818c327 /drivers/scsi
parent3471c288036bf0835a82d0b1bbce2002f6e68390 (diff)
downloadlinux-8fa728a26886f56a9ee10a44fea0ddda301d21c3.tar.gz
linux-8fa728a26886f56a9ee10a44fea0ddda301d21c3.tar.bz2
linux-8fa728a26886f56a9ee10a44fea0ddda301d21c3.zip
[SCSI] allow sleeping in ->eh_abort_handler()
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_osm.c8
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_osm.c4
-rw-r--r--drivers/scsi/aic7xxx_old.c15
-rw-r--r--drivers/scsi/ibmmca.c14
-rw-r--r--drivers/scsi/ibmvscsi/ibmvscsi.c2
-rw-r--r--drivers/scsi/in2000.c12
-rw-r--r--drivers/scsi/ipr.c24
-rw-r--r--drivers/scsi/ips.c7
-rw-r--r--drivers/scsi/lpfc/lpfc_scsi.c12
-rw-r--r--drivers/scsi/megaraid/megaraid_mbox.c17
-rw-r--r--drivers/scsi/qla1280.c8
-rw-r--r--drivers/scsi/qla2xxx/qla_os.c2
-rw-r--r--drivers/scsi/scsi_error.c13
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_glue.c8
-rw-r--r--drivers/scsi/ultrastor.c2
15 files changed, 109 insertions, 39 deletions
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c
index 550c9921691a..7fc6c76e519b 100644
--- a/drivers/scsi/aic7xxx/aic79xx_osm.c
+++ b/drivers/scsi/aic7xxx/aic79xx_osm.c
@@ -941,7 +941,7 @@ ahd_linux_queue(Scsi_Cmnd * cmd, void (*scsi_done) (Scsi_Cmnd *))
*/
cmd->scsi_done = scsi_done;
- ahd_midlayer_entrypoint_lock(ahd, &flags);
+ ahd_lock(ahd, &flags);
/*
* Close the race of a command that was in the process of
@@ -955,7 +955,7 @@ ahd_linux_queue(Scsi_Cmnd * cmd, void (*scsi_done) (Scsi_Cmnd *))
ahd_cmd_set_transaction_status(cmd, CAM_REQUEUE_REQ);
ahd_linux_queue_cmd_complete(ahd, cmd);
ahd_schedule_completeq(ahd);
- ahd_midlayer_entrypoint_unlock(ahd, &flags);
+ ahd_unlock(ahd, &flags);
return (0);
}
dev = ahd_linux_get_device(ahd, cmd->device->channel,
@@ -965,7 +965,7 @@ ahd_linux_queue(Scsi_Cmnd * cmd, void (*scsi_done) (Scsi_Cmnd *))
ahd_cmd_set_transaction_status(cmd, CAM_RESRC_UNAVAIL);
ahd_linux_queue_cmd_complete(ahd, cmd);
ahd_schedule_completeq(ahd);
- ahd_midlayer_entrypoint_unlock(ahd, &flags);
+ ahd_unlock(ahd, &flags);
printf("%s: aic79xx_linux_queue - Unable to allocate device!\n",
ahd_name(ahd));
return (0);
@@ -979,7 +979,7 @@ ahd_linux_queue(Scsi_Cmnd * cmd, void (*scsi_done) (Scsi_Cmnd *))
dev->flags |= AHD_DEV_ON_RUN_LIST;
ahd_linux_run_device_queues(ahd);
}
- ahd_midlayer_entrypoint_unlock(ahd, &flags);
+ ahd_unlock(ahd, &flags);
return (0);
}
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c
index e3892585d7e6..89f073a3b766 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_osm.c
+++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c
@@ -2249,6 +2249,8 @@ ahc_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag)
printf(" 0x%x", cmd->cmnd[cdb_byte]);
printf("\n");
+ spin_lock_irq(&ahc->platform_data->spin_lock);
+
/*
* First determine if we currently own this command.
* Start by searching the device queue. If not found
@@ -2503,6 +2505,8 @@ done:
}
spin_lock_irq(&ahc->platform_data->spin_lock);
}
+
+ spin_unlock_irq(&ahc->platform_data->spin_lock);
return (retval);
}
diff --git a/drivers/scsi/aic7xxx_old.c b/drivers/scsi/aic7xxx_old.c
index 9e9d0c40187e..ee127e8aea55 100644
--- a/drivers/scsi/aic7xxx_old.c
+++ b/drivers/scsi/aic7xxx_old.c
@@ -10585,7 +10585,7 @@ aic7xxx_panic_abort(struct aic7xxx_host *p, Scsi_Cmnd *cmd)
* Abort the current SCSI command(s).
*-F*************************************************************************/
static int
-aic7xxx_abort(Scsi_Cmnd *cmd)
+__aic7xxx_abort(Scsi_Cmnd *cmd)
{
struct aic7xxx_scb *scb = NULL;
struct aic7xxx_host *p;
@@ -10802,6 +10802,19 @@ success:
return SUCCESS;
}
+static int
+aic7xxx_abort(Scsi_Cmnd *cmd)
+{
+ int rc;
+
+ spin_lock_irq(cmd->device->host->host_lock);
+ rc = __aic7xxx_abort(cmd);
+ spin_unlock_irq(cmd->device->host->host_lock);
+
+ return rc;
+}
+
+
/*+F*************************************************************************
* Function:
* aic7xxx_reset
diff --git a/drivers/scsi/ibmmca.c b/drivers/scsi/ibmmca.c
index a3fdead9bce9..0018fb5c09a9 100644
--- a/drivers/scsi/ibmmca.c
+++ b/drivers/scsi/ibmmca.c
@@ -2118,7 +2118,7 @@ static int ibmmca_queuecommand(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *))
return 0;
}
-static int ibmmca_abort(Scsi_Cmnd * cmd)
+static int __ibmmca_abort(Scsi_Cmnd * cmd)
{
/* Abort does not work, as the adapter never generates an interrupt on
* whatever situation is simulated, even when really pending commands
@@ -2225,6 +2225,18 @@ static int ibmmca_abort(Scsi_Cmnd * cmd)
}
}
+static int ibmmca_abort(Scsi_Cmnd * cmd)
+{
+ struct Scsi_Host *shpnt = cmd->device->host;
+ int rc;
+
+ spin_lock_irq(shpnt->host_lock);
+ rc = __ibmmca_abort(cmd);
+ spin_unlock_irq(shpnt->host_lock);
+
+ return rc;
+}
+
static int ibmmca_host_reset(Scsi_Cmnd * cmd)
{
struct Scsi_Host *shpnt;
diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c
index e89f76e5dd53..d857842bc45b 100644
--- a/drivers/scsi/ibmvscsi/ibmvscsi.c
+++ b/drivers/scsi/ibmvscsi/ibmvscsi.c
@@ -874,9 +874,7 @@ static int ibmvscsi_eh_abort_handler(struct scsi_cmnd *cmd)
return FAILED;
}
- spin_unlock_irq(hostdata->host->host_lock);
wait_for_completion(&evt->comp);
- spin_lock_irq(hostdata->host->host_lock);
/* make sure we got a good response */
if (unlikely(srp_rsp.srp.generic.type != SRP_RSP_TYPE)) {
diff --git a/drivers/scsi/in2000.c b/drivers/scsi/in2000.c
index e1fe6f13b829..fbb29f7971d7 100644
--- a/drivers/scsi/in2000.c
+++ b/drivers/scsi/in2000.c
@@ -1671,7 +1671,7 @@ static int in2000_bus_reset(Scsi_Cmnd * cmd)
return SUCCESS;
}
-static int in2000_abort(Scsi_Cmnd * cmd)
+static int __in2000_abort(Scsi_Cmnd * cmd)
{
struct Scsi_Host *instance;
struct IN2000_hostdata *hostdata;
@@ -1792,6 +1792,16 @@ static int in2000_abort(Scsi_Cmnd * cmd)
return SUCCESS;
}
+static int in2000_abort(Scsi_Cmnd * cmd)
+{
+ int rc;
+
+ spin_lock_irq(cmd->device->host->host_lock);
+ rc = __in2000_abort(cmd);
+ spin_unlock_irq(cmd->device->host->host_lock);
+
+ return rc;
+}
#define MAX_IN2000_HOSTS 3
diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c
index a3d9cf675681..f9c01a13abef 100644
--- a/drivers/scsi/ipr.c
+++ b/drivers/scsi/ipr.c
@@ -3068,6 +3068,12 @@ static int ipr_cancel_op(struct scsi_cmnd * scsi_cmd)
ioa_cfg = (struct ipr_ioa_cfg *)scsi_cmd->device->host->hostdata;
res = scsi_cmd->device->hostdata;
+ /* If we are currently going through reset/reload, return failed.
+ * This will force the mid-layer to call ipr_eh_host_reset,
+ * which will then go to sleep and wait for the reset to complete
+ */
+ if (ioa_cfg->in_reset_reload || ioa_cfg->ioa_is_dead)
+ return FAILED;
if (!res || (!ipr_is_gscsi(res) && !ipr_is_vset_device(res)))
return FAILED;
@@ -3118,23 +3124,17 @@ static int ipr_cancel_op(struct scsi_cmnd * scsi_cmd)
**/
static int ipr_eh_abort(struct scsi_cmnd * scsi_cmd)
{
- struct ipr_ioa_cfg *ioa_cfg;
+ unsigned long flags;
+ int rc;
ENTER;
- ioa_cfg = (struct ipr_ioa_cfg *) scsi_cmd->device->host->hostdata;
- /* If we are currently going through reset/reload, return failed. This will force the
- mid-layer to call ipr_eh_host_reset, which will then go to sleep and wait for the
- reset to complete */
- if (ioa_cfg->in_reset_reload)
- return FAILED;
- if (ioa_cfg->ioa_is_dead)
- return FAILED;
- if (!scsi_cmd->device->hostdata)
- return FAILED;
+ spin_lock_irqsave(scsi_cmd->device->host->host_lock, flags);
+ rc = ipr_cancel_op(scsi_cmd);
+ spin_unlock_irqrestore(scsi_cmd->device->host->host_lock, flags);
LEAVE;
- return ipr_cancel_op(scsi_cmd);
+ return rc;
}
/**
diff --git a/drivers/scsi/ips.c b/drivers/scsi/ips.c
index fbc2cb6667a1..6572e100f7b2 100644
--- a/drivers/scsi/ips.c
+++ b/drivers/scsi/ips.c
@@ -819,12 +819,15 @@ ips_eh_abort(Scsi_Cmnd * SC)
ips_ha_t *ha;
ips_copp_wait_item_t *item;
int ret;
+ unsigned long cpu_flags;
+ struct Scsi_Host *host;
METHOD_TRACE("ips_eh_abort", 1);
if (!SC)
return (FAILED);
+ host = SC->device->host;
ha = (ips_ha_t *) SC->device->host->hostdata;
if (!ha)
@@ -833,6 +836,8 @@ ips_eh_abort(Scsi_Cmnd * SC)
if (!ha->active)
return (FAILED);
+ IPS_LOCK_SAVE(host->host_lock, cpu_flags);
+
/* See if the command is on the copp queue */
item = ha->copp_waitlist.head;
while ((item) && (item->scsi_cmd != SC))
@@ -851,6 +856,8 @@ ips_eh_abort(Scsi_Cmnd * SC)
/* command must have already been sent */
ret = (FAILED);
}
+
+ IPS_UNLOCK_RESTORE(host->host_lock, cpu_flags);
return ret;
}
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c
index 42fab03ad2ba..e9b84f9d8e81 100644
--- a/drivers/scsi/lpfc/lpfc_scsi.c
+++ b/drivers/scsi/lpfc/lpfc_scsi.c
@@ -798,7 +798,7 @@ lpfc_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *))
}
static int
-lpfc_abort_handler(struct scsi_cmnd *cmnd)
+__lpfc_abort_handler(struct scsi_cmnd *cmnd)
{
struct lpfc_hba *phba =
(struct lpfc_hba *)cmnd->device->host->hostdata[0];
@@ -918,6 +918,16 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd)
}
static int
+lpfc_abort_handler(struct scsi_cmnd *cmnd)
+{
+ int rc;
+ spin_lock_irq(cmnd->device->host->host_lock);
+ rc = __lpfc_abort_handler(cmnd);
+ spin_unlock_irq(cmnd->device->host->host_lock);
+ return rc;
+}
+
+static int
lpfc_reset_lun_handler(struct scsi_cmnd *cmnd)
{
struct Scsi_Host *shost = cmnd->device->host;
diff --git a/drivers/scsi/megaraid/megaraid_mbox.c b/drivers/scsi/megaraid/megaraid_mbox.c
index 78768736077f..bec4406011aa 100644
--- a/drivers/scsi/megaraid/megaraid_mbox.c
+++ b/drivers/scsi/megaraid/megaraid_mbox.c
@@ -2566,7 +2566,7 @@ megaraid_mbox_dpc(unsigned long devp)
* aborted. All the commands issued to the F/W must complete.
**/
static int
-megaraid_abort_handler(struct scsi_cmnd *scp)
+__megaraid_abort_handler(struct scsi_cmnd *scp)
{
adapter_t *adapter;
mraid_device_t *raid_dev;
@@ -2699,6 +2699,21 @@ megaraid_abort_handler(struct scsi_cmnd *scp)
return FAILED;
}
+static int
+megaraid_abort_handler(struct scsi_cmnd *scp)
+{
+ adapter_t *adapter;
+ int rc;
+
+ adapter = SCP2ADAPTER(scp);
+
+ spin_lock_irq(adapter->host_lock);
+ rc = __megaraid_abort_handler(scp);
+ spin_unlock_irq(adapter->host_lock);
+
+ return rc;
+}
+
/**
* megaraid_reset_handler - device reset hadler for mailbox based driver
diff --git a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c
index 653e589b7d7f..638be81c4509 100644
--- a/drivers/scsi/qla1280.c
+++ b/drivers/scsi/qla1280.c
@@ -1098,7 +1098,13 @@ qla1280_error_action(struct scsi_cmnd *cmd, enum action action)
static int
qla1280_eh_abort(struct scsi_cmnd * cmd)
{
- return qla1280_error_action(cmd, ABORT_COMMAND);
+ int rc;
+
+ spin_lock_irq(cmd->device->host->host_lock);
+ rc = qla1280_error_action(cmd, ABORT_COMMAND);
+ spin_unlock_irq(cmd->device->host->host_lock);
+
+ return rc;
}
/**************************************************************************
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 7f8d747bd5e5..1693998aa727 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -476,7 +476,6 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd)
serial = cmd->serial_number;
/* Check active list for command command. */
- spin_unlock_irq(ha->host->host_lock);
spin_lock(&ha->hardware_lock);
for (i = 1; i < MAX_OUTSTANDING_COMMANDS; i++) {
sp = ha->outstanding_cmds[i];
@@ -516,7 +515,6 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd)
}
spin_lock(&ha->hardware_lock);
}
- spin_lock_irq(ha->host->host_lock);
qla_printk(KERN_INFO, ha,
"scsi(%ld:%d:%d): Abort command issued -- %lx %x.\n", ha->host_no,
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
index 113c02dbb2df..3877a78f5e50 100644
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -526,10 +526,8 @@ static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, int timeout)
* abort a timed out command or not. not sure how
* we should treat them differently anyways.
*/
- spin_lock_irqsave(shost->host_lock, flags);
if (shost->hostt->eh_abort_handler)
shost->hostt->eh_abort_handler(scmd);
- spin_unlock_irqrestore(shost->host_lock, flags);
scmd->request->rq_status = RQ_SCSI_DONE;
scmd->owner = SCSI_OWNER_ERROR_HANDLER;
@@ -735,11 +733,8 @@ static int scsi_eh_get_sense(struct list_head *work_q,
**/
static int scsi_try_to_abort_cmd(struct scsi_cmnd *scmd)
{
- unsigned long flags;
- int rtn = FAILED;
-
if (!scmd->device->host->hostt->eh_abort_handler)
- return rtn;
+ return FAILED;
/*
* scsi_done was called just after the command timed out and before
@@ -750,11 +745,7 @@ static int scsi_try_to_abort_cmd(struct scsi_cmnd *scmd)
scmd->owner = SCSI_OWNER_LOWLEVEL;
- spin_lock_irqsave(scmd->device->host->host_lock, flags);
- rtn = scmd->device->host->hostt->eh_abort_handler(scmd);
- spin_unlock_irqrestore(scmd->device->host->host_lock, flags);
-
- return rtn;
+ return scmd->device->host->hostt->eh_abort_handler(scmd);
}
/**
diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c
index be58ffd5a432..e2d055ed5b6f 100644
--- a/drivers/scsi/sym53c8xx_2/sym_glue.c
+++ b/drivers/scsi/sym53c8xx_2/sym_glue.c
@@ -856,7 +856,13 @@ prepare:
*/
static int sym53c8xx_eh_abort_handler(struct scsi_cmnd *cmd)
{
- return sym_eh_handler(SYM_EH_ABORT, "ABORT", cmd);
+ int rc;
+
+ spin_lock_irq(cmd->device->host->host_lock);
+ rc = sym_eh_handler(SYM_EH_ABORT, "ABORT", cmd);
+ spin_unlock_irq(cmd->device->host->host_lock);
+
+ return rc;
}
static int sym53c8xx_eh_device_reset_handler(struct scsi_cmnd *cmd)
diff --git a/drivers/scsi/ultrastor.c b/drivers/scsi/ultrastor.c
index 2c17470a229d..486551bd54ba 100644
--- a/drivers/scsi/ultrastor.c
+++ b/drivers/scsi/ultrastor.c
@@ -879,7 +879,7 @@ static int ultrastor_abort(Scsi_Cmnd *SCpnt)
ogm_addr = (unsigned int)isa_bus_to_virt(inl(port0 + 23));
icm_status = inb(port0 + 27);
icm_addr = (unsigned int)isa_bus_to_virt(inl(port0 + 28));
- spin_lock_irqsave(host->host_lock, flags);
+ spin_unlock_irqrestore(host->host_lock, flags);
}
/* First check to see if an interrupt is pending. I suspect the SiS