Skip to content

Commit

Permalink
[SCSI] allow sleeping in ->eh_bus_reset_handler()
Browse files Browse the repository at this point in the history
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
  • Loading branch information
Jeff Garzik committed Jun 17, 2005
1 parent 94d0e7b commit 68b3aa7
Show file tree
Hide file tree
Showing 32 changed files with 133 additions and 40 deletions.
3 changes: 1 addition & 2 deletions Documentation/scsi/scsi_mid_low_api.txt
Original file line number Diff line number Diff line change
Expand Up @@ -954,8 +954,7 @@ Details:
*
* Returns SUCCESS if command aborted else FAILED
*
* Locks: struct Scsi_Host::host_lock held (with irqsave) on entry
* and assumed to be held on return.
* Locks: None held
*
* Calling context: kernel thread
*
Expand Down
3 changes: 3 additions & 0 deletions drivers/fc4/fc.c
Original file line number Diff line number Diff line change
Expand Up @@ -983,7 +983,10 @@ int fcp_scsi_dev_reset(Scsi_Cmnd *SCpnt)
fc->rst_pkt->request->rq_status = RQ_SCSI_BUSY;

fc->rst_pkt->done = fcp_scsi_reset_done;

spin_lock_irqsave(SCpnt->device->host->host_lock, flags);
fcp_scsi_queue_it(fc, fc->rst_pkt, fcmd, 0);
spin_unlock_irqrestore(SCpnt->device->host->host_lock, flags);

down(&sem);

Expand Down
3 changes: 1 addition & 2 deletions drivers/message/fusion/mptscsih.c
Original file line number Diff line number Diff line change
Expand Up @@ -1865,7 +1865,6 @@ mptscsih_bus_reset(struct scsi_cmnd * SCpnt)
hd->timeouts++;

/* We are now ready to execute the task management request. */
spin_unlock_irq(host_lock);
if (mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS,
SCpnt->device->channel, 0, 0, 0, 5 /* 5 second timeout */)
< 0){
Expand All @@ -1881,7 +1880,7 @@ mptscsih_bus_reset(struct scsi_cmnd * SCpnt)
spin_lock_irq(host_lock);
return FAILED;
}
spin_lock_irq(host_lock);

return SUCCESS;
}

Expand Down
3 changes: 0 additions & 3 deletions drivers/s390/scsi/zfcp_scsi.c
Original file line number Diff line number Diff line change
Expand Up @@ -731,16 +731,13 @@ zfcp_scsi_eh_bus_reset_handler(struct scsi_cmnd *scpnt)
struct zfcp_unit *unit;
struct Scsi_Host *scsi_host = scpnt->device->host;

spin_unlock_irq(scsi_host->host_lock);

unit = (struct zfcp_unit *) scpnt->device->hostdata;
ZFCP_LOG_NORMAL("bus reset because of problems with "
"unit 0x%016Lx\n", unit->fcp_lun);
zfcp_erp_adapter_reopen(unit->port->adapter, 0);
zfcp_erp_wait(unit->port->adapter);
retval = SUCCESS;

spin_lock_irq(scsi_host->host_lock);
return retval;
}

Expand Down
9 changes: 8 additions & 1 deletion drivers/scsi/53c700.c
Original file line number Diff line number Diff line change
Expand Up @@ -1957,23 +1957,30 @@ NCR_700_bus_reset(struct scsi_cmnd * SCp)
printk(KERN_INFO "scsi%d (%d:%d) New error handler wants BUS reset, cmd %p\n\t",
SCp->device->host->host_no, SCp->device->id, SCp->device->lun, SCp);
scsi_print_command(SCp);

/* In theory, eh_complete should always be null because the
* eh is single threaded, but just in case we're handling a
* reset via sg or something */
while(hostdata->eh_complete != NULL) {
spin_lock_irq(SCp->device->host->host_lock);
while (hostdata->eh_complete != NULL) {
spin_unlock_irq(SCp->device->host->host_lock);
msleep_interruptible(100);
spin_lock_irq(SCp->device->host->host_lock);
}

hostdata->eh_complete = &complete;
NCR_700_internal_bus_reset(SCp->device->host);

spin_unlock_irq(SCp->device->host->host_lock);
wait_for_completion(&complete);
spin_lock_irq(SCp->device->host->host_lock);

hostdata->eh_complete = NULL;
/* Revalidate the transport parameters of the failing device */
if(hostdata->fast)
spi_schedule_dv_device(SCp->device);

spin_unlock_irq(SCp->device->host->host_lock);
return SUCCESS;
}

Expand Down
14 changes: 10 additions & 4 deletions drivers/scsi/NCR5380.c
Original file line number Diff line number Diff line change
Expand Up @@ -2825,11 +2825,17 @@ static int NCR5380_abort(Scsi_Cmnd * cmd) {
* Locks: host lock taken by caller
*/

static int NCR5380_bus_reset(Scsi_Cmnd * cmd) {
static int NCR5380_bus_reset(Scsi_Cmnd * cmd)
{
struct Scsi_Host *instance = cmd->device->host;

NCR5380_local_declare();
NCR5380_setup(cmd->device->host);
NCR5380_setup(instance);
NCR5380_print_status(instance);

spin_lock_irq(instance->host_lock);
do_reset(instance);
spin_unlock_irq(instance->host_lock);

NCR5380_print_status(cmd->device->host);
do_reset(cmd->device->host);
return SUCCESS;
}
4 changes: 1 addition & 3 deletions drivers/scsi/NCR53C9x.c
Original file line number Diff line number Diff line change
Expand Up @@ -1467,14 +1467,12 @@ int esp_reset(Scsi_Cmnd *SCptr)
{
struct NCR_ESP *esp = (struct NCR_ESP *) SCptr->device->host->hostdata;

spin_lock_irq(esp->ehost->host_lock);
(void) esp_do_resetbus(esp, esp->eregs);

spin_unlock_irq(esp->ehost->host_lock);

wait_event(esp->reset_queue, (esp->resetting_bus == 0));

spin_lock_irq(esp->ehost->host_lock);

return SUCCESS;
}

Expand Down
4 changes: 4 additions & 0 deletions drivers/scsi/a2091.c
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,11 @@ int __init a2091_detect(Scsi_Host_Template *tpnt)
static int a2091_bus_reset(Scsi_Cmnd *cmd)
{
/* FIXME perform bus-specific reset */

spin_lock_irq(cmd->device->host->host_lock);
wd33c93_host_reset(cmd);
spin_unlock_irq(cmd->device->host->host_lock);

return SUCCESS;
}

Expand Down
4 changes: 4 additions & 0 deletions drivers/scsi/a3000.c
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,11 @@ int __init a3000_detect(Scsi_Host_Template *tpnt)
static int a3000_bus_reset(Scsi_Cmnd *cmd)
{
/* FIXME perform bus-specific reset */

spin_lock_irq(cmd->device->host->host_lock);
wd33c93_host_reset(cmd);
spin_unlock_irq(cmd->device->host->host_lock);

return SUCCESS;
}

Expand Down
4 changes: 3 additions & 1 deletion drivers/scsi/aha1542.c
Original file line number Diff line number Diff line change
Expand Up @@ -1464,8 +1464,8 @@ static int aha1542_bus_reset(Scsi_Cmnd * SCpnt)
* check for timeout, and if we are doing something like this
* we are pretty desperate anyways.
*/
spin_unlock_irq(SCpnt->device->host->host_lock);
ssleep(4);

spin_lock_irq(SCpnt->device->host->host_lock);

WAIT(STATUS(SCpnt->device->host->io_port),
Expand Down Expand Up @@ -1503,9 +1503,11 @@ static int aha1542_bus_reset(Scsi_Cmnd * SCpnt)
}
}

spin_unlock_irq(SCpnt->device->host->host_lock);
return SUCCESS;

fail:
spin_unlock_irq(SCpnt->device->host->host_lock);
return FAILED;
}

Expand Down
4 changes: 2 additions & 2 deletions drivers/scsi/aic7xxx/aic79xx_osm.c
Original file line number Diff line number Diff line change
Expand Up @@ -1591,11 +1591,11 @@ ahd_linux_bus_reset(Scsi_Cmnd *cmd)
printf("%s: Bus reset called for cmd %p\n",
ahd_name(ahd), cmd);
#endif
ahd_midlayer_entrypoint_lock(ahd, &s);
ahd_lock(ahd, &s);
found = ahd_reset_channel(ahd, cmd->device->channel + 'A',
/*initiate reset*/TRUE);
ahd_linux_run_complete_queue(ahd);
ahd_midlayer_entrypoint_unlock(ahd, &s);
ahd_unlock(ahd, &s);

if (bootverbose)
printf("%s: SCSI bus reset delivered. "
Expand Down
4 changes: 4 additions & 0 deletions drivers/scsi/aic7xxx/aic7xxx_osm.c
Original file line number Diff line number Diff line change
Expand Up @@ -829,10 +829,14 @@ ahc_linux_bus_reset(struct scsi_cmnd *cmd)
{
struct ahc_softc *ahc;
int found;
unsigned long flags;

ahc = *(struct ahc_softc **)cmd->device->host->hostdata;

ahc_lock(ahc, &flags);
found = ahc_reset_channel(ahc, cmd->device->channel + 'A',
/*initiate reset*/TRUE);
ahc_unlock(ahc, &flags);

if (bootverbose)
printf("%s: SCSI bus reset delivered. "
Expand Down
12 changes: 11 additions & 1 deletion drivers/scsi/dc395x.c
Original file line number Diff line number Diff line change
Expand Up @@ -1310,7 +1310,7 @@ static void reset_dev_param(struct AdapterCtlBlk *acb)
* @cmd - some command for this host (for fetching hooks)
* Returns: SUCCESS (0x2002) on success, else FAILED (0x2003).
*/
static int dc395x_eh_bus_reset(struct scsi_cmnd *cmd)
static int __dc395x_eh_bus_reset(struct scsi_cmnd *cmd)
{
struct AdapterCtlBlk *acb =
(struct AdapterCtlBlk *)cmd->device->host->hostdata;
Expand Down Expand Up @@ -1356,6 +1356,16 @@ static int dc395x_eh_bus_reset(struct scsi_cmnd *cmd)
return SUCCESS;
}

static int dc395x_eh_bus_reset(struct scsi_cmnd *cmd)
{
int rc;

spin_lock_irq(cmd->device->host->host_lock);
rc = __dc395x_eh_bus_reset(cmd);
spin_unlock_irq(cmd->device->host->host_lock);

return rc;
}

/*
* abort an errant SCSI command
Expand Down
5 changes: 5 additions & 0 deletions drivers/scsi/fd_mcs.c
Original file line number Diff line number Diff line change
Expand Up @@ -1243,6 +1243,7 @@ static int fd_mcs_abort(Scsi_Cmnd * SCpnt)

static int fd_mcs_bus_reset(Scsi_Cmnd * SCpnt) {
struct Scsi_Host *shpnt = SCpnt->device->host;
unsigned long flags;

#if DEBUG_RESET
static int called_once = 0;
Expand All @@ -1259,13 +1260,17 @@ static int fd_mcs_bus_reset(Scsi_Cmnd * SCpnt) {
called_once = 1;
#endif

spin_lock_irqsave(shpnt->host_lock, flags);

outb(1, SCSI_Cntl_port);
do_pause(2);
outb(0, SCSI_Cntl_port);
do_pause(115);
outb(0, SCSI_Mode_Cntl_port);
outb(PARITY_MASK, TMC_Cntl_port);

spin_unlock_irqrestore(shpnt->host_lock, flags);

/* Unless this is the very first call (i.e., SCPnt == NULL), everything
is probably hosed at this point. We will, however, try to keep
things going by informing the high-level code that we need help. */
Expand Down
6 changes: 6 additions & 0 deletions drivers/scsi/fdomain.c
Original file line number Diff line number Diff line change
Expand Up @@ -1543,12 +1543,18 @@ static int fdomain_16x0_abort(struct scsi_cmnd *SCpnt)

int fdomain_16x0_bus_reset(struct scsi_cmnd *SCpnt)
{
unsigned long flags;

local_irq_save(flags);

outb(1, port_base + SCSI_Cntl);
do_pause( 2 );
outb(0, port_base + SCSI_Cntl);
do_pause( 115 );
outb(0, port_base + SCSI_Mode_Cntl);
outb(PARITY_MASK, port_base + TMC_Cntl);

local_irq_restore(flags);
return SUCCESS;
}

Expand Down
4 changes: 4 additions & 0 deletions drivers/scsi/gvp11.c
Original file line number Diff line number Diff line change
Expand Up @@ -345,7 +345,11 @@ int __init gvp11_detect(Scsi_Host_Template *tpnt)
static int gvp11_bus_reset(Scsi_Cmnd *cmd)
{
/* FIXME perform bus-specific reset */

spin_lock_irq(cmd->device->host->host_lock);
wd33c93_host_reset(cmd);
spin_unlock_irq(cmd->device->host->host_lock);

return SUCCESS;
}

Expand Down
9 changes: 5 additions & 4 deletions drivers/scsi/imm.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include <linux/blkdev.h>
#include <linux/parport.h>
#include <linux/workqueue.h>
#include <linux/delay.h>
#include <asm/io.h>

#include <scsi/scsi.h>
Expand Down Expand Up @@ -610,9 +611,9 @@ static int imm_init(imm_struct *dev)
if (imm_connect(dev, 0) != 1)
return -EIO;
imm_reset_pulse(dev->base);
udelay(1000); /* Delay to allow devices to settle */
mdelay(1); /* Delay to allow devices to settle */
imm_disconnect(dev);
udelay(1000); /* Another delay to allow devices to settle */
mdelay(1); /* Another delay to allow devices to settle */
return device_check(dev);
}

Expand Down Expand Up @@ -1026,9 +1027,9 @@ static int imm_reset(struct scsi_cmnd *cmd)

imm_connect(dev, CONNECT_NORMAL);
imm_reset_pulse(dev->base);
udelay(1000); /* device settle delay */
mdelay(1); /* device settle delay */
imm_disconnect(dev);
udelay(1000); /* device settle delay */
mdelay(1); /* device settle delay */
return SUCCESS;
}

Expand Down
6 changes: 5 additions & 1 deletion drivers/scsi/in2000.c
Original file line number Diff line number Diff line change
Expand Up @@ -1644,14 +1644,16 @@ static int in2000_bus_reset(Scsi_Cmnd * cmd)
struct Scsi_Host *instance;
struct IN2000_hostdata *hostdata;
int x;
unsigned long flags;

instance = cmd->device->host;
hostdata = (struct IN2000_hostdata *) instance->hostdata;

printk(KERN_WARNING "scsi%d: Reset. ", instance->host_no);

/* do scsi-reset here */
spin_lock_irqsave(instance->host_lock, flags);

/* do scsi-reset here */
reset_hardware(instance, RESET_CARD_AND_BUS);
for (x = 0; x < 8; x++) {
hostdata->busy[x] = 0;
Expand All @@ -1668,6 +1670,8 @@ static int in2000_bus_reset(Scsi_Cmnd * cmd)
hostdata->outgoing_len = 0;

cmd->result = DID_RESET << 16;

spin_unlock_irqrestore(instance->host_lock, flags);
return SUCCESS;
}

Expand Down
4 changes: 4 additions & 0 deletions drivers/scsi/initio.c
Original file line number Diff line number Diff line change
Expand Up @@ -3014,7 +3014,11 @@ static int i91u_bus_reset(struct scsi_cmnd * SCpnt)
HCS *pHCB;

pHCB = (HCS *) SCpnt->device->host->base;

spin_lock_irq(SCpnt->device->host->host_lock);
tul_reset_scsi(pHCB, 0);
spin_unlock_irq(SCpnt->device->host->host_lock);

return SUCCESS;
}

Expand Down
12 changes: 11 additions & 1 deletion drivers/scsi/lpfc/lpfc_scsi.c
Original file line number Diff line number Diff line change
Expand Up @@ -1054,7 +1054,7 @@ lpfc_reset_lun_handler(struct scsi_cmnd *cmnd)
* Note: midlayer calls this function with the host_lock held
*/
static int
lpfc_reset_bus_handler(struct scsi_cmnd *cmnd)
__lpfc_reset_bus_handler(struct scsi_cmnd *cmnd)
{
struct Scsi_Host *shost = cmnd->device->host;
struct lpfc_hba *phba = (struct lpfc_hba *)shost->hostdata[0];
Expand Down Expand Up @@ -1143,6 +1143,16 @@ lpfc_reset_bus_handler(struct scsi_cmnd *cmnd)
return ret;
}

static int
lpfc_reset_bus_handler(struct scsi_cmnd *cmnd)
{
int rc;
spin_lock_irq(cmnd->device->host->host_lock);
rc = __lpfc_reset_bus_handler(cmnd);
spin_unlock_irq(cmnd->device->host->host_lock);
return rc;
}

static int
lpfc_slave_alloc(struct scsi_device *sdev)
{
Expand Down
4 changes: 4 additions & 0 deletions drivers/scsi/mvme147.c
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,11 @@ int mvme147_detect(Scsi_Host_Template *tpnt)
static int mvme147_bus_reset(Scsi_Cmnd *cmd)
{
/* FIXME perform bus-specific reset */

spin_lock_irq(cmd->device->host->host_lock);
wd33c93_host_reset(cmd);
spin_unlock_irq(cmd->device->host->host_lock);

return SUCCESS;
}

Expand Down
Loading

0 comments on commit 68b3aa7

Please sign in to comment.