diff options
Diffstat (limited to 'drivers/scsi/libfc/fc_fcp.c')
-rw-r--r-- | drivers/scsi/libfc/fc_fcp.c | 41 |
1 files changed, 30 insertions, 11 deletions
diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c index 9cd2149..735b324 100644 --- a/drivers/scsi/libfc/fc_fcp.c +++ b/drivers/scsi/libfc/fc_fcp.c @@ -498,7 +498,7 @@ crc_err: stats = per_cpu_ptr(lport->dev_stats, get_cpu()); stats->ErrorFrames++; /* per cpu count, not total count, but OK for limit */ - if (stats->InvalidCRCCount++ < 5) + if (stats->InvalidCRCCount++ < FC_MAX_ERROR_CNT) printk(KERN_WARNING "libfc: CRC error on data " "frame for port (%6.6x)\n", lport->port_id); @@ -690,7 +690,7 @@ static int fc_fcp_send_data(struct fc_fcp_pkt *fsp, struct fc_seq *seq, } /** - * fc_fcp_abts_resp() - Send an ABTS response + * fc_fcp_abts_resp() - Receive an ABTS response * @fsp: The FCP packet that is being aborted * @fp: The response frame */ @@ -730,7 +730,7 @@ static void fc_fcp_abts_resp(struct fc_fcp_pkt *fsp, struct fc_frame *fp) } /** - * fc_fcp_recv() - Reveive an FCP frame + * fc_fcp_recv() - Receive an FCP frame * @seq: The sequence the frame is on * @fp: The received frame * @arg: The related FCP packet @@ -759,7 +759,6 @@ static void fc_fcp_recv(struct fc_seq *seq, struct fc_frame *fp, void *arg) goto out; if (fc_fcp_lock_pkt(fsp)) goto out; - fsp->last_pkt_time = jiffies; if (fh->fh_type == FC_TYPE_BLS) { fc_fcp_abts_resp(fsp, fp); @@ -1030,11 +1029,26 @@ restart: fc_fcp_pkt_hold(fsp); spin_unlock_irqrestore(&si->scsi_queue_lock, flags); - if (!fc_fcp_lock_pkt(fsp)) { + spin_lock_bh(&fsp->scsi_pkt_lock); + if (!(fsp->state & FC_SRB_COMPL)) { + fsp->state |= FC_SRB_COMPL; + /* + * TODO: dropping scsi_pkt_lock and then reacquiring + * again around fc_fcp_cleanup_cmd() is required, + * since fc_fcp_cleanup_cmd() calls into + * fc_seq_set_resp() and that func preempts cpu using + * schedule. May be schedule and related code should be + * removed instead of unlocking here to avoid scheduling + * while atomic bug. + */ + spin_unlock_bh(&fsp->scsi_pkt_lock); + fc_fcp_cleanup_cmd(fsp, error); + + spin_lock_bh(&fsp->scsi_pkt_lock); fc_io_compl(fsp); - fc_fcp_unlock_pkt(fsp); } + spin_unlock_bh(&fsp->scsi_pkt_lock); fc_fcp_pkt_release(fsp); spin_lock_irqsave(&si->scsi_queue_lock, flags); @@ -1084,6 +1098,7 @@ static int fc_fcp_pkt_send(struct fc_lport *lport, struct fc_fcp_pkt *fsp) rc = lport->tt.fcp_cmd_send(lport, fsp, fc_fcp_recv); if (unlikely(rc)) { spin_lock_irqsave(&si->scsi_queue_lock, flags); + fsp->cmd->SCp.ptr = NULL; list_del(&fsp->list); spin_unlock_irqrestore(&si->scsi_queue_lock, flags); } @@ -1147,7 +1162,6 @@ static int fc_fcp_cmd_send(struct fc_lport *lport, struct fc_fcp_pkt *fsp, rc = -1; goto unlock; } - fsp->last_pkt_time = jiffies; fsp->seq_ptr = seq; fc_fcp_pkt_hold(fsp); /* hold for fc_fcp_pkt_destroy */ @@ -1645,12 +1659,10 @@ static void fc_fcp_srr(struct fc_fcp_pkt *fsp, enum fc_rctl r_ctl, u32 offset) struct fc_seq *seq; struct fcp_srr *srr; struct fc_frame *fp; - u8 cdb_op; unsigned int rec_tov; rport = fsp->rport; rpriv = rport->dd_data; - cdb_op = fsp->cdb_cmd.fc_cdb[0]; if (!(rpriv->flags & FC_RP_FLAGS_RETRY) || rpriv->rp_state != RPORT_ST_READY) @@ -2020,6 +2032,11 @@ int fc_eh_abort(struct scsi_cmnd *sc_cmd) struct fc_fcp_internal *si; int rc = FAILED; unsigned long flags; + int rval; + + rval = fc_block_scsi_eh(sc_cmd); + if (rval) + return rval; lport = shost_priv(sc_cmd->device->host); if (lport->state != LPORT_ST_READY) @@ -2069,9 +2086,9 @@ int fc_eh_device_reset(struct scsi_cmnd *sc_cmd) int rc = FAILED; int rval; - rval = fc_remote_port_chkready(rport); + rval = fc_block_scsi_eh(sc_cmd); if (rval) - goto out; + return rval; lport = shost_priv(sc_cmd->device->host); @@ -2117,6 +2134,8 @@ int fc_eh_host_reset(struct scsi_cmnd *sc_cmd) FC_SCSI_DBG(lport, "Resetting host\n"); + fc_block_scsi_eh(sc_cmd); + lport->tt.lport_reset(lport); wait_tmo = jiffies + FC_HOST_RESET_TIMEOUT; while (!fc_fcp_lport_queue_ready(lport) && time_before(jiffies, |