aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/libfc/fc_fcp.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/libfc/fc_fcp.c')
-rw-r--r--drivers/scsi/libfc/fc_fcp.c61
1 files changed, 60 insertions, 1 deletions
diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c
index 48adb89d911a..a5725f3b7ce1 100644
--- a/drivers/scsi/libfc/fc_fcp.c
+++ b/drivers/scsi/libfc/fc_fcp.c
@@ -265,6 +265,56 @@ static void fc_fcp_retry_cmd(struct fc_fcp_pkt *fsp)
265} 265}
266 266
267/* 267/*
268 * fc_fcp_ddp_setup - calls to LLD's ddp_setup to set up DDP
269 * transfer for a read I/O indicated by the fc_fcp_pkt.
270 * @fsp: ptr to the fc_fcp_pkt
271 *
272 * This is called in exch_seq_send() when we have a newly allocated
273 * exchange with a valid exchange id to setup ddp.
274 *
275 * returns: none
276 */
277void fc_fcp_ddp_setup(struct fc_fcp_pkt *fsp, u16 xid)
278{
279 struct fc_lport *lp;
280
281 if (!fsp)
282 return;
283
284 lp = fsp->lp;
285 if ((fsp->req_flags & FC_SRB_READ) &&
286 (lp->lro_enabled) && (lp->tt.ddp_setup)) {
287 if (lp->tt.ddp_setup(lp, xid, scsi_sglist(fsp->cmd),
288 scsi_sg_count(fsp->cmd)))
289 fsp->xfer_ddp = xid;
290 }
291}
292EXPORT_SYMBOL(fc_fcp_ddp_setup);
293
294/*
295 * fc_fcp_ddp_done - calls to LLD's ddp_done to release any
296 * DDP related resources for this I/O if it is initialized
297 * as a ddp transfer
298 * @fsp: ptr to the fc_fcp_pkt
299 *
300 * returns: none
301 */
302static void fc_fcp_ddp_done(struct fc_fcp_pkt *fsp)
303{
304 struct fc_lport *lp;
305
306 if (!fsp)
307 return;
308
309 lp = fsp->lp;
310 if (fsp->xfer_ddp && lp->tt.ddp_done) {
311 fsp->xfer_len = lp->tt.ddp_done(lp, fsp->xfer_ddp);
312 fsp->xfer_ddp = 0;
313 }
314}
315
316
317/*
268 * Receive SCSI data from target. 318 * Receive SCSI data from target.
269 * Called after receiving solicited data. 319 * Called after receiving solicited data.
270 */ 320 */
@@ -289,6 +339,9 @@ static void fc_fcp_recv_data(struct fc_fcp_pkt *fsp, struct fc_frame *fp)
289 len = fr_len(fp) - sizeof(*fh); 339 len = fr_len(fp) - sizeof(*fh);
290 buf = fc_frame_payload_get(fp, 0); 340 buf = fc_frame_payload_get(fp, 0);
291 341
342 /* if this I/O is ddped, update xfer len */
343 fc_fcp_ddp_done(fsp);
344
292 if (offset + len > fsp->data_len) { 345 if (offset + len > fsp->data_len) {
293 /* this should never happen */ 346 /* this should never happen */
294 if ((fr_flags(fp) & FCPHF_CRC_UNCHECKED) && 347 if ((fr_flags(fp) & FCPHF_CRC_UNCHECKED) &&
@@ -750,6 +803,9 @@ static void fc_fcp_resp(struct fc_fcp_pkt *fsp, struct fc_frame *fp)
750 fsp->scsi_comp_flags = flags; 803 fsp->scsi_comp_flags = flags;
751 expected_len = fsp->data_len; 804 expected_len = fsp->data_len;
752 805
806 /* if ddp, update xfer len */
807 fc_fcp_ddp_done(fsp);
808
753 if (unlikely((flags & ~FCP_CONF_REQ) || fc_rp->fr_status)) { 809 if (unlikely((flags & ~FCP_CONF_REQ) || fc_rp->fr_status)) {
754 rp_ex = (void *)(fc_rp + 1); 810 rp_ex = (void *)(fc_rp + 1);
755 if (flags & (FCP_RSP_LEN_VAL | FCP_SNS_LEN_VAL)) { 811 if (flags & (FCP_RSP_LEN_VAL | FCP_SNS_LEN_VAL)) {
@@ -1012,7 +1068,7 @@ static int fc_fcp_cmd_send(struct fc_lport *lp, struct fc_fcp_pkt *fsp,
1012 } 1068 }
1013 1069
1014 memcpy(fc_frame_payload_get(fp, len), &fsp->cdb_cmd, len); 1070 memcpy(fc_frame_payload_get(fp, len), &fsp->cdb_cmd, len);
1015 fr_cmd(fp) = fsp->cmd; 1071 fr_fsp(fp) = fsp;
1016 rport = fsp->rport; 1072 rport = fsp->rport;
1017 fsp->max_payload = rport->maxframe_size; 1073 fsp->max_payload = rport->maxframe_size;
1018 rp = rport->dd_data; 1074 rp = rport->dd_data;
@@ -1746,6 +1802,9 @@ static void fc_io_compl(struct fc_fcp_pkt *fsp)
1746 struct fc_lport *lp; 1802 struct fc_lport *lp;
1747 unsigned long flags; 1803 unsigned long flags;
1748 1804
1805 /* release outstanding ddp context */
1806 fc_fcp_ddp_done(fsp);
1807
1749 fsp->state |= FC_SRB_COMPL; 1808 fsp->state |= FC_SRB_COMPL;
1750 if (!(fsp->state & FC_SRB_FCP_PROCESSING_TMO)) { 1809 if (!(fsp->state & FC_SRB_FCP_PROCESSING_TMO)) {
1751 spin_unlock_bh(&fsp->scsi_pkt_lock); 1810 spin_unlock_bh(&fsp->scsi_pkt_lock);