[SCSI] allow sleeping in ->eh_abort_handler()
authorJeff Garzik <jgarzik@pobox.com>
Sat, 28 May 2005 11:54:40 +0000 (07:54 -0400)
committerJeff Garzik <jgarzik@pobox.com>
Fri, 17 Jun 2005 17:04:55 +0000 (12:04 -0500)
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
19 files changed:
Documentation/scsi/scsi_mid_low_api.txt
drivers/message/fusion/mptscsih.c
drivers/s390/scsi/zfcp_scsi.c
drivers/scsi/aic7xxx/aic79xx_osm.c
drivers/scsi/aic7xxx/aic7xxx_osm.c
drivers/scsi/aic7xxx_old.c
drivers/scsi/ibmmca.c
drivers/scsi/ibmvscsi/ibmvscsi.c
drivers/scsi/in2000.c
drivers/scsi/ipr.c
drivers/scsi/ips.c
drivers/scsi/lpfc/lpfc_scsi.c
drivers/scsi/megaraid/megaraid_mbox.c
drivers/scsi/qla1280.c
drivers/scsi/qla2xxx/qla_os.c
drivers/scsi/scsi_error.c
drivers/scsi/sym53c8xx_2/sym_glue.c
drivers/scsi/ultrastor.c
drivers/usb/storage/scsiglue.c

index e41703d7d24d3f0579acccdc0b28a56da2621ff1..f4a37ee670f2978f0112e5f7af5f33909f6b39b4 100644 (file)
@@ -936,8 +936,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
  *
index c8492034cfe75acbc60bbdc1534fccb81d190d35..6a5851c51a21e1eba78a5cbb0d01c44ed6c5138c 100644 (file)
@@ -1707,7 +1707,6 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
        MPT_FRAME_HDR   *mf;
        u32              ctx2abort;
        int              scpnt_idx;
-       spinlock_t      *host_lock = SCpnt->device->host->host_lock;
 
        /* If we can't locate our host adapter structure, return FAILED status.
         */
@@ -1755,7 +1754,6 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
 
        hd->abortSCpnt = SCpnt;
 
-       spin_unlock_irq(host_lock);
        if (mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK,
                SCpnt->device->channel, SCpnt->device->id, SCpnt->device->lun,
                ctx2abort, 2 /* 2 second timeout */)
@@ -1772,8 +1770,6 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
                hd->tmPending = 0;
                hd->tmState = TM_STATE_NONE;
 
-               spin_lock_irq(host_lock);
-
                /* Unmap the DMA buffers, if any. */
                if (SCpnt->use_sg) {
                        pci_unmap_sg(ioc->pcidev, (struct scatterlist *) SCpnt->request_buffer,
@@ -1789,7 +1785,6 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
                mpt_free_msg_frame(ioc, mf);
                return FAILED;
        }
-       spin_lock_irq(host_lock);
        return SUCCESS;
 }
 
index c6f69fc475a2ab71a5801e4cd57164017abbc2ad..6e4447598495c3a24d976e7da8fd07ae802bcf85 100644 (file)
@@ -433,7 +433,7 @@ zfcp_port_lookup(struct zfcp_adapter *adapter, int channel, scsi_id_t id)
  *             FAILED  - otherwise
  */
 int
-zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
+__zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
 {
        int retval = SUCCESS;
        struct zfcp_fsf_req *new_fsf_req, *old_fsf_req;
@@ -611,6 +611,17 @@ zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
        return retval;
 }
 
+int
+zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
+{
+       int rc;
+       struct Scsi_Host *scsi_host = scpnt->device->host;
+       spin_lock_irq(scsi_host->host_lock);
+       rc = __zfcp_scsi_eh_abort_handler(scpnt);
+       spin_unlock_irq(scsi_host->host_lock);
+       return rc;
+}
+
 /*
  * function:   zfcp_scsi_eh_device_reset_handler
  *
index 550c9921691ad8df96602bf833d2c28ba7eba411..7fc6c76e519b2a69b53b9ee45e6df3764e1ea00c 100644 (file)
@@ -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);
 }
 
index e3892585d7e68380a09d4f0a6322e9ecc4cd1f83..89f073a3b76626fe667dbfac6ced905c3d0259db 100644 (file)
@@ -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);
 }
 
index 9e9d0c40187e50ed1af8e5199514611e0903f26f..ee127e8aea55694dcde683927426decadbb12cf8 100644 (file)
@@ -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
index a3fdead9bce99a64284647d4ea7c5024b07d9b52..0018fb5c09a94ce9df57c0a4640a1d1f14f4d225 100644 (file)
@@ -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;
index e89f76e5dd531fc2c0a892b9ab63f79baf95ca30..d857842bc45b5ab7abf5e50f480113fe41d7b545 100644 (file)
@@ -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)) {
index e1fe6f13b8291cb15b8acba6832c036d5892b836..fbb29f7971d7a48c7cae12691b2fa5743fd45f4b 100644 (file)
@@ -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
index a3d9cf675681f4745ff78a03223d66f15d00ab99..f9c01a13abef57fa059626b07bcd8fbaa6f88a86 100644 (file)
@@ -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;
 }
 
 /**
index fbc2cb6667a1a349e81aa559311e472ad7a94f91..6572e100f7b2a030bfb979dc7ef3cf83953e1c46 100644 (file)
@@ -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;
 }
 
index 42fab03ad2baa5b0ef275aeefe01f857adda168d..e9b84f9d8e81b3ca930586314c46015360830f79 100644 (file)
@@ -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];
@@ -917,6 +917,16 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd)
        return ret == IOCB_SUCCESS ? SUCCESS : FAILED;
 }
 
+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)
 {
index 78768736077feeb979659382fff26d19aafac100..bec4406011aa133ad0a3c88ee768a6cc54ecb643 100644 (file)
@@ -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
index 653e589b7d7f8f32e9988c2fe8be48e7f99138b2..638be81c45090f2e35495007ae58b3ef13485688 100644 (file)
@@ -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;
 }
 
 /**************************************************************************
index 7f8d747bd5e546e3b753ce06e3568f32d0a0ec07..1693998aa727fb77e7169d3a62661e2d7d440554 100644 (file)
@@ -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,
index 113c02dbb2dfbf0590b541b08a778d2e10fe74c9..3877a78f5e50040c179728d40c2f2ccc639dac1d 100644 (file)
@@ -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);
 }
 
 /**
index be58ffd5a432c901e0d29b4b85e6aec53d368a02..e2d055ed5b6f866447e37ab20600600de38a4ee0 100644 (file)
@@ -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)
index 2c17470a229d907d7a9233583368b5595538ea93..486551bd54baf16b1f7603492d2bedd31e3e497a 100644 (file)
@@ -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
index 22e48a2b0bd186879f0e0ae6f5001560f382f5f1..7dce9c01c357b878a4266f90e0dd0f3460809b16 100644 (file)
@@ -233,13 +233,11 @@ static int command_abort(struct scsi_cmnd *srb)
                set_bit(US_FLIDX_ABORTING, &us->flags);
                usb_stor_stop_transport(us);
        }
-       scsi_unlock(us_to_host(us));
 
        /* Wait for the aborted command to finish */
        wait_for_completion(&us->notify);
 
        /* Reacquire the lock and allow USB transfers to resume */
-       scsi_lock(us_to_host(us));
        clear_bit(US_FLIDX_ABORTING, &us->flags);
        clear_bit(US_FLIDX_TIMED_OUT, &us->flags);
        return SUCCESS;