diff options
Diffstat (limited to 'drivers/scsi/libfc/fc_fcp.c')
-rw-r--r-- | drivers/scsi/libfc/fc_fcp.c | 75 |
1 files changed, 70 insertions, 5 deletions
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) | |||
259 | } | 259 | } |
260 | 260 | ||
261 | fsp->state &= ~FC_SRB_ABORT_PENDING; | 261 | fsp->state &= ~FC_SRB_ABORT_PENDING; |
262 | fsp->io_status = SUGGEST_RETRY << 24; | 262 | fsp->io_status = 0; |
263 | fsp->status_code = FC_ERROR; | 263 | fsp->status_code = FC_ERROR; |
264 | fc_fcp_complete_locked(fsp); | 264 | fc_fcp_complete_locked(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 | */ | ||
277 | void 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 | } | ||
292 | EXPORT_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 | */ | ||
302 | static 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) && |
@@ -435,7 +488,13 @@ static int fc_fcp_send_data(struct fc_fcp_pkt *fsp, struct fc_seq *seq, | |||
435 | * burst length (t_blen) to seq_blen, otherwise set t_blen | 488 | * burst length (t_blen) to seq_blen, otherwise set t_blen |
436 | * to max FC frame payload previously set in fsp->max_payload. | 489 | * to max FC frame payload previously set in fsp->max_payload. |
437 | */ | 490 | */ |
438 | t_blen = lp->seq_offload ? seq_blen : fsp->max_payload; | 491 | t_blen = fsp->max_payload; |
492 | if (lp->seq_offload) { | ||
493 | t_blen = min(seq_blen, (size_t)lp->lso_max); | ||
494 | FC_DEBUG_FCP("fsp=%p:lso:blen=%zx lso_max=0x%x t_blen=%zx\n", | ||
495 | fsp, seq_blen, lp->lso_max, t_blen); | ||
496 | } | ||
497 | |||
439 | WARN_ON(t_blen < FC_MIN_MAX_PAYLOAD); | 498 | WARN_ON(t_blen < FC_MIN_MAX_PAYLOAD); |
440 | if (t_blen > 512) | 499 | if (t_blen > 512) |
441 | t_blen &= ~(512 - 1); /* round down to block size */ | 500 | 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) | |||
744 | fsp->scsi_comp_flags = flags; | 803 | fsp->scsi_comp_flags = flags; |
745 | expected_len = fsp->data_len; | 804 | expected_len = fsp->data_len; |
746 | 805 | ||
806 | /* if ddp, update xfer len */ | ||
807 | fc_fcp_ddp_done(fsp); | ||
808 | |||
747 | if (unlikely((flags & ~FCP_CONF_REQ) || fc_rp->fr_status)) { | 809 | if (unlikely((flags & ~FCP_CONF_REQ) || fc_rp->fr_status)) { |
748 | rp_ex = (void *)(fc_rp + 1); | 810 | rp_ex = (void *)(fc_rp + 1); |
749 | if (flags & (FCP_RSP_LEN_VAL | FCP_SNS_LEN_VAL)) { | 811 | 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) | |||
859 | (!(fsp->scsi_comp_flags & FCP_RESID_UNDER) || | 921 | (!(fsp->scsi_comp_flags & FCP_RESID_UNDER) || |
860 | fsp->xfer_len < fsp->data_len - fsp->scsi_resid)) { | 922 | fsp->xfer_len < fsp->data_len - fsp->scsi_resid)) { |
861 | fsp->status_code = FC_DATA_UNDRUN; | 923 | fsp->status_code = FC_DATA_UNDRUN; |
862 | fsp->io_status = SUGGEST_RETRY << 24; | 924 | fsp->io_status = 0; |
863 | } | 925 | } |
864 | } | 926 | } |
865 | 927 | ||
@@ -1006,7 +1068,7 @@ static int fc_fcp_cmd_send(struct fc_lport *lp, struct fc_fcp_pkt *fsp, | |||
1006 | } | 1068 | } |
1007 | 1069 | ||
1008 | memcpy(fc_frame_payload_get(fp, len), &fsp->cdb_cmd, len); | 1070 | memcpy(fc_frame_payload_get(fp, len), &fsp->cdb_cmd, len); |
1009 | fr_cmd(fp) = fsp->cmd; | 1071 | fr_fsp(fp) = fsp; |
1010 | rport = fsp->rport; | 1072 | rport = fsp->rport; |
1011 | fsp->max_payload = rport->maxframe_size; | 1073 | fsp->max_payload = rport->maxframe_size; |
1012 | rp = rport->dd_data; | 1074 | rp = rport->dd_data; |
@@ -1267,7 +1329,7 @@ static void fc_fcp_rec(struct fc_fcp_pkt *fsp) | |||
1267 | rp = rport->dd_data; | 1329 | rp = rport->dd_data; |
1268 | if (!fsp->seq_ptr || rp->rp_state != RPORT_ST_READY) { | 1330 | if (!fsp->seq_ptr || rp->rp_state != RPORT_ST_READY) { |
1269 | fsp->status_code = FC_HRD_ERROR; | 1331 | fsp->status_code = FC_HRD_ERROR; |
1270 | fsp->io_status = SUGGEST_RETRY << 24; | 1332 | fsp->io_status = 0; |
1271 | fc_fcp_complete_locked(fsp); | 1333 | fc_fcp_complete_locked(fsp); |
1272 | return; | 1334 | return; |
1273 | } | 1335 | } |
@@ -1740,6 +1802,9 @@ static void fc_io_compl(struct fc_fcp_pkt *fsp) | |||
1740 | struct fc_lport *lp; | 1802 | struct fc_lport *lp; |
1741 | unsigned long flags; | 1803 | unsigned long flags; |
1742 | 1804 | ||
1805 | /* release outstanding ddp context */ | ||
1806 | fc_fcp_ddp_done(fsp); | ||
1807 | |||
1743 | fsp->state |= FC_SRB_COMPL; | 1808 | fsp->state |= FC_SRB_COMPL; |
1744 | if (!(fsp->state & FC_SRB_FCP_PROCESSING_TMO)) { | 1809 | if (!(fsp->state & FC_SRB_FCP_PROCESSING_TMO)) { |
1745 | spin_unlock_bh(&fsp->scsi_pkt_lock); | 1810 | spin_unlock_bh(&fsp->scsi_pkt_lock); |