diff options
Diffstat (limited to 'drivers/scsi/libfc')
-rw-r--r-- | drivers/scsi/libfc/fc_exch.c | 6 | ||||
-rw-r--r-- | drivers/scsi/libfc/fc_fcp.c | 75 | ||||
-rw-r--r-- | drivers/scsi/libfc/fc_lport.c | 5 | ||||
-rw-r--r-- | drivers/scsi/libfc/fc_rport.c | 2 |
4 files changed, 78 insertions, 10 deletions
diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c index 505825b6124d..992af05aacf1 100644 --- a/drivers/scsi/libfc/fc_exch.c +++ b/drivers/scsi/libfc/fc_exch.c @@ -281,7 +281,7 @@ static void fc_exch_release(struct fc_exch *ep) ep->destructor(&ep->seq, ep->arg); if (ep->lp->tt.exch_put) ep->lp->tt.exch_put(ep->lp, mp, ep->xid); - WARN_ON(!ep->esb_stat & ESB_ST_COMPLETE); + WARN_ON(!(ep->esb_stat & ESB_ST_COMPLETE)); mempool_free(ep, mp->ep_pool); } } @@ -489,7 +489,7 @@ static u16 fc_em_alloc_xid(struct fc_exch_mgr *mp, const struct fc_frame *fp) struct fc_exch *ep = NULL; if (mp->max_read) { - if (fc_frame_is_read(fp)) { + if (fc_fcp_is_read(fr_fsp(fp))) { min = mp->min_xid; max = mp->max_read; plast = &mp->last_read; @@ -1841,6 +1841,8 @@ struct fc_seq *fc_exch_seq_send(struct fc_lport *lp, fc_exch_setup_hdr(ep, fp, ep->f_ctl); sp->cnt++; + fc_fcp_ddp_setup(fr_fsp(fp), ep->xid); + if (unlikely(lp->tt.frame_send(lp, fp))) goto err; diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c index 2a631d7dbcec..a5725f3b7ce1 100644 --- a/drivers/scsi/libfc/fc_fcp.c +++ b/drivers/scsi/libfc/fc_fcp.c @@ -259,12 +259,62 @@ static void fc_fcp_retry_cmd(struct fc_fcp_pkt *fsp) } fsp->state &= ~FC_SRB_ABORT_PENDING; - fsp->io_status = SUGGEST_RETRY << 24; + fsp->io_status = 0; fsp->status_code = FC_ERROR; fc_fcp_complete_locked(fsp); } /* + * fc_fcp_ddp_setup - calls to LLD's ddp_setup to set up DDP + * transfer for a read I/O indicated by the fc_fcp_pkt. + * @fsp: ptr to the fc_fcp_pkt + * + * This is called in exch_seq_send() when we have a newly allocated + * exchange with a valid exchange id to setup ddp. + * + * returns: none + */ +void fc_fcp_ddp_setup(struct fc_fcp_pkt *fsp, u16 xid) +{ + struct fc_lport *lp; + + if (!fsp) + return; + + lp = fsp->lp; + if ((fsp->req_flags & FC_SRB_READ) && + (lp->lro_enabled) && (lp->tt.ddp_setup)) { + if (lp->tt.ddp_setup(lp, xid, scsi_sglist(fsp->cmd), + scsi_sg_count(fsp->cmd))) + fsp->xfer_ddp = xid; + } +} +EXPORT_SYMBOL(fc_fcp_ddp_setup); + +/* + * fc_fcp_ddp_done - calls to LLD's ddp_done to release any + * DDP related resources for this I/O if it is initialized + * as a ddp transfer + * @fsp: ptr to the fc_fcp_pkt + * + * returns: none + */ +static void fc_fcp_ddp_done(struct fc_fcp_pkt *fsp) +{ + struct fc_lport *lp; + + if (!fsp) + return; + + lp = fsp->lp; + if (fsp->xfer_ddp && lp->tt.ddp_done) { + fsp->xfer_len = lp->tt.ddp_done(lp, fsp->xfer_ddp); + fsp->xfer_ddp = 0; + } +} + + +/* * Receive SCSI data from target. * Called after receiving solicited data. */ @@ -289,6 +339,9 @@ static void fc_fcp_recv_data(struct fc_fcp_pkt *fsp, struct fc_frame *fp) len = fr_len(fp) - sizeof(*fh); buf = fc_frame_payload_get(fp, 0); + /* if this I/O is ddped, update xfer len */ + fc_fcp_ddp_done(fsp); + if (offset + len > fsp->data_len) { /* this should never happen */ if ((fr_flags(fp) & FCPHF_CRC_UNCHECKED) && @@ -435,7 +488,13 @@ static int fc_fcp_send_data(struct fc_fcp_pkt *fsp, struct fc_seq *seq, * burst length (t_blen) to seq_blen, otherwise set t_blen * to max FC frame payload previously set in fsp->max_payload. */ - t_blen = lp->seq_offload ? seq_blen : fsp->max_payload; + t_blen = fsp->max_payload; + if (lp->seq_offload) { + t_blen = min(seq_blen, (size_t)lp->lso_max); + FC_DEBUG_FCP("fsp=%p:lso:blen=%zx lso_max=0x%x t_blen=%zx\n", + fsp, seq_blen, lp->lso_max, t_blen); + } + WARN_ON(t_blen < FC_MIN_MAX_PAYLOAD); if (t_blen > 512) t_blen &= ~(512 - 1); /* round down to block size */ @@ -744,6 +803,9 @@ static void fc_fcp_resp(struct fc_fcp_pkt *fsp, struct fc_frame *fp) fsp->scsi_comp_flags = flags; expected_len = fsp->data_len; + /* if ddp, update xfer len */ + fc_fcp_ddp_done(fsp); + if (unlikely((flags & ~FCP_CONF_REQ) || fc_rp->fr_status)) { rp_ex = (void *)(fc_rp + 1); if (flags & (FCP_RSP_LEN_VAL | FCP_SNS_LEN_VAL)) { @@ -859,7 +921,7 @@ static void fc_fcp_complete_locked(struct fc_fcp_pkt *fsp) (!(fsp->scsi_comp_flags & FCP_RESID_UNDER) || fsp->xfer_len < fsp->data_len - fsp->scsi_resid)) { fsp->status_code = FC_DATA_UNDRUN; - fsp->io_status = SUGGEST_RETRY << 24; + fsp->io_status = 0; } } @@ -1006,7 +1068,7 @@ static int fc_fcp_cmd_send(struct fc_lport *lp, struct fc_fcp_pkt *fsp, } memcpy(fc_frame_payload_get(fp, len), &fsp->cdb_cmd, len); - fr_cmd(fp) = fsp->cmd; + fr_fsp(fp) = fsp; rport = fsp->rport; fsp->max_payload = rport->maxframe_size; rp = rport->dd_data; @@ -1267,7 +1329,7 @@ static void fc_fcp_rec(struct fc_fcp_pkt *fsp) rp = rport->dd_data; if (!fsp->seq_ptr || rp->rp_state != RPORT_ST_READY) { fsp->status_code = FC_HRD_ERROR; - fsp->io_status = SUGGEST_RETRY << 24; + fsp->io_status = 0; fc_fcp_complete_locked(fsp); return; } @@ -1740,6 +1802,9 @@ static void fc_io_compl(struct fc_fcp_pkt *fsp) struct fc_lport *lp; unsigned long flags; + /* release outstanding ddp context */ + fc_fcp_ddp_done(fsp); + fsp->state |= FC_SRB_COMPL; if (!(fsp->state & FC_SRB_FCP_PROCESSING_TMO)) { spin_unlock_bh(&fsp->scsi_pkt_lock); diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c index 2ae50a1188e6..7ef44501ecc6 100644 --- a/drivers/scsi/libfc/fc_lport.c +++ b/drivers/scsi/libfc/fc_lport.c @@ -762,10 +762,11 @@ static void fc_lport_recv_flogi_req(struct fc_seq *sp_in, remote_wwpn = get_unaligned_be64(&flp->fl_wwpn); if (remote_wwpn == lport->wwpn) { FC_DBG("FLOGI from port with same WWPN %llx " - "possible configuration error\n", remote_wwpn); + "possible configuration error\n", + (unsigned long long)remote_wwpn); goto out; } - FC_DBG("FLOGI from port WWPN %llx\n", remote_wwpn); + FC_DBG("FLOGI from port WWPN %llx\n", (unsigned long long)remote_wwpn); /* * XXX what is the right thing to do for FIDs? diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index dae65133a833..0472bb73221e 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c @@ -988,7 +988,7 @@ static void fc_rport_recv_plogi_req(struct fc_rport *rport, switch (rdata->rp_state) { case RPORT_ST_INIT: FC_DEBUG_RPORT("incoming PLOGI from %6x wwpn %llx state INIT " - "- reject\n", sid, wwpn); + "- reject\n", sid, (unsigned long long)wwpn); reject = ELS_RJT_UNSUP; break; case RPORT_ST_PLOGI: |