Lines Matching +full:single +full:- +full:tt

1 // SPDX-License-Identifier: GPL-2.0-only
7 * Maintained at www.Open-FCoE.org
41 #define FC_SRB_DISCONTIG (1 << 4) /* non-sequential data recvd */
54 * struct fc_fcp_internal - FCP layer internal data
71 #define fc_get_scsi_internal(x) ((struct fc_fcp_internal *)(x)->scsi_priv)
124 * fc_fcp_pkt_alloc() - Allocate a fcp_pkt
136 fsp = mempool_alloc(si->scsi_pkt_pool, gfp); in fc_fcp_pkt_alloc()
139 fsp->lp = lport; in fc_fcp_pkt_alloc()
140 fsp->xfer_ddp = FC_XID_UNKNOWN; in fc_fcp_pkt_alloc()
141 refcount_set(&fsp->ref_cnt, 1); in fc_fcp_pkt_alloc()
142 timer_setup(&fsp->timer, NULL, 0); in fc_fcp_pkt_alloc()
143 INIT_LIST_HEAD(&fsp->list); in fc_fcp_pkt_alloc()
144 spin_lock_init(&fsp->scsi_pkt_lock); in fc_fcp_pkt_alloc()
146 this_cpu_inc(lport->stats->FcpPktAllocFails); in fc_fcp_pkt_alloc()
152 * fc_fcp_pkt_release() - Release hold on a fcp_pkt
160 if (refcount_dec_and_test(&fsp->ref_cnt)) { in fc_fcp_pkt_release()
161 struct fc_fcp_internal *si = fc_get_scsi_internal(fsp->lp); in fc_fcp_pkt_release()
163 mempool_free(fsp, si->scsi_pkt_pool); in fc_fcp_pkt_release()
168 * fc_fcp_pkt_hold() - Hold a fcp_pkt
173 refcount_inc(&fsp->ref_cnt); in fc_fcp_pkt_hold()
177 * fc_fcp_pkt_destroy() - Release hold on a fcp_pkt
193 * fc_fcp_lock_pkt() - Lock a fcp_pkt and increase its reference count
196 * We should only return error if we return a command to SCSI-ml before
199 * each other on the wire/network-layer.
211 spin_lock_bh(&fsp->scsi_pkt_lock); in fc_fcp_lock_pkt()
212 if (fsp->state & FC_SRB_COMPL) { in fc_fcp_lock_pkt()
213 spin_unlock_bh(&fsp->scsi_pkt_lock); in fc_fcp_lock_pkt()
214 return -EPERM; in fc_fcp_lock_pkt()
222 * fc_fcp_unlock_pkt() - Release a fcp_pkt's lock and decrement its
228 spin_unlock_bh(&fsp->scsi_pkt_lock); in fc_fcp_unlock_pkt()
233 * fc_fcp_timer_set() - Start a timer for a fcp_pkt
239 if (!(fsp->state & FC_SRB_COMPL)) { in fc_fcp_timer_set()
240 mod_timer(&fsp->timer, jiffies + delay); in fc_fcp_timer_set()
241 fsp->timer_delay = delay; in fc_fcp_timer_set()
247 fsp->state |= FC_SRB_ABORTED; in fc_fcp_abort_done()
248 fsp->state &= ~FC_SRB_ABORT_PENDING; in fc_fcp_abort_done()
250 if (fsp->wait_for_comp) in fc_fcp_abort_done()
251 complete(&fsp->tm_done); in fc_fcp_abort_done()
257 * fc_fcp_send_abort() - Send an abort for exchanges associated with a
265 if (!fsp->seq_ptr) in fc_fcp_send_abort()
266 return -EINVAL; in fc_fcp_send_abort()
268 if (fsp->state & FC_SRB_ABORT_PENDING) { in fc_fcp_send_abort()
270 return -EBUSY; in fc_fcp_send_abort()
273 this_cpu_inc(fsp->lp->stats->FcpPktAborts); in fc_fcp_send_abort()
275 fsp->state |= FC_SRB_ABORT_PENDING; in fc_fcp_send_abort()
276 rc = fc_seq_exch_abort(fsp->seq_ptr, 0); in fc_fcp_send_abort()
278 * fc_seq_exch_abort() might return -ENXIO if in fc_fcp_send_abort()
281 if (rc == -ENXIO) { in fc_fcp_send_abort()
289 * fc_fcp_retry_cmd() - Retry a fcp_pkt
295 * fc_io_compl() will notify the SCSI-ml that the I/O is done.
296 * The SCSI-ml will retry the command.
300 if (fsp->seq_ptr) { in fc_fcp_retry_cmd()
301 fc_exch_done(fsp->seq_ptr); in fc_fcp_retry_cmd()
302 fsp->seq_ptr = NULL; in fc_fcp_retry_cmd()
305 fsp->state &= ~FC_SRB_ABORT_PENDING; in fc_fcp_retry_cmd()
306 fsp->io_status = 0; in fc_fcp_retry_cmd()
307 fsp->status_code = status_code; in fc_fcp_retry_cmd()
312 * fc_fcp_ddp_setup() - Calls a LLD's ddp_setup routine to set up DDP context
320 lport = fsp->lp; in fc_fcp_ddp_setup()
321 if ((fsp->req_flags & FC_SRB_READ) && in fc_fcp_ddp_setup()
322 (lport->lro_enabled) && (lport->tt.ddp_setup)) { in fc_fcp_ddp_setup()
323 if (lport->tt.ddp_setup(lport, xid, scsi_sglist(fsp->cmd), in fc_fcp_ddp_setup()
324 scsi_sg_count(fsp->cmd))) in fc_fcp_ddp_setup()
325 fsp->xfer_ddp = xid; in fc_fcp_ddp_setup()
330 * fc_fcp_ddp_done() - Calls a LLD's ddp_done routine to release any
341 if (fsp->xfer_ddp == FC_XID_UNKNOWN) in fc_fcp_ddp_done()
344 lport = fsp->lp; in fc_fcp_ddp_done()
345 if (lport->tt.ddp_done) { in fc_fcp_ddp_done()
346 fsp->xfer_len = lport->tt.ddp_done(lport, fsp->xfer_ddp); in fc_fcp_ddp_done()
347 fsp->xfer_ddp = FC_XID_UNKNOWN; in fc_fcp_ddp_done()
352 * fc_fcp_can_queue_ramp_up() - increases can_queue
361 spin_lock_irqsave(lport->host->host_lock, flags); in fc_fcp_can_queue_ramp_up()
363 if (si->last_can_queue_ramp_up_time && in fc_fcp_can_queue_ramp_up()
364 (time_before(jiffies, si->last_can_queue_ramp_up_time + in fc_fcp_can_queue_ramp_up()
368 if (time_before(jiffies, si->last_can_queue_ramp_down_time + in fc_fcp_can_queue_ramp_up()
372 si->last_can_queue_ramp_up_time = jiffies; in fc_fcp_can_queue_ramp_up()
374 can_queue = lport->host->can_queue << 1; in fc_fcp_can_queue_ramp_up()
375 if (can_queue >= si->max_can_queue) { in fc_fcp_can_queue_ramp_up()
376 can_queue = si->max_can_queue; in fc_fcp_can_queue_ramp_up()
377 si->last_can_queue_ramp_down_time = 0; in fc_fcp_can_queue_ramp_up()
379 lport->host->can_queue = can_queue; in fc_fcp_can_queue_ramp_up()
380 shost_printk(KERN_ERR, lport->host, "libfc: increased " in fc_fcp_can_queue_ramp_up()
384 spin_unlock_irqrestore(lport->host->host_lock, flags); in fc_fcp_can_queue_ramp_up()
388 * fc_fcp_can_queue_ramp_down() - reduces can_queue
404 spin_lock_irqsave(lport->host->host_lock, flags); in fc_fcp_can_queue_ramp_down()
406 if (si->last_can_queue_ramp_down_time && in fc_fcp_can_queue_ramp_down()
407 (time_before(jiffies, si->last_can_queue_ramp_down_time + in fc_fcp_can_queue_ramp_down()
411 si->last_can_queue_ramp_down_time = jiffies; in fc_fcp_can_queue_ramp_down()
413 can_queue = lport->host->can_queue; in fc_fcp_can_queue_ramp_down()
417 lport->host->can_queue = can_queue; in fc_fcp_can_queue_ramp_down()
421 spin_unlock_irqrestore(lport->host->host_lock, flags); in fc_fcp_can_queue_ramp_down()
426 * fc_fcp_frame_alloc() - Allocates fc_frame structure and buffer.
442 this_cpu_inc(lport->stats->FcpFrameAllocFails); in fc_fcp_frame_alloc()
445 shost_printk(KERN_ERR, lport->host, in fc_fcp_frame_alloc()
447 "reducing can_queue to %d.\n", lport->host->can_queue); in fc_fcp_frame_alloc()
452 * get_fsp_rec_tov() - Helper function to get REC_TOV
455 * Returns rec tov in jiffies as rpriv->e_d_tov + 1 second
459 struct fc_rport_libfc_priv *rpriv = fsp->rport->dd_data; in get_fsp_rec_tov()
462 if (rpriv && rpriv->e_d_tov > e_d_tov) in get_fsp_rec_tov()
463 e_d_tov = rpriv->e_d_tov; in get_fsp_rec_tov()
468 * fc_fcp_recv_data() - Handler for receiving SCSI-FCP data from a target
474 struct scsi_cmnd *sc = fsp->cmd; in fc_fcp_recv_data()
475 struct fc_lport *lport = fsp->lp; in fc_fcp_recv_data()
488 offset = ntohl(fh->fh_parm_offset); in fc_fcp_recv_data()
490 len = fr_len(fp) - sizeof(*fh); in fc_fcp_recv_data()
497 * Indicate error to scsi-ml because something went wrong with the in fc_fcp_recv_data()
500 if (fsp->xfer_ddp != FC_XID_UNKNOWN) { in fc_fcp_recv_data()
506 if (offset + len > fsp->data_len) { in fc_fcp_recv_data()
512 "data_len %x\n", len, offset, fsp->data_len); in fc_fcp_recv_data()
514 /* Data is corrupted indicate scsi-ml should retry */ in fc_fcp_recv_data()
518 if (offset != fsp->xfer_len) in fc_fcp_recv_data()
519 fsp->state |= FC_SRB_DISCONTIG; in fc_fcp_recv_data()
533 crc = crc32(crc, buf + len, 4 - (len % 4)); in fc_fcp_recv_data()
537 this_cpu_inc(lport->stats->ErrorFrames); in fc_fcp_recv_data()
539 if (this_cpu_inc_return(lport->stats->InvalidCRCCount) < FC_MAX_ERROR_CNT) in fc_fcp_recv_data()
542 lport->port_id); in fc_fcp_recv_data()
550 if (fsp->state & FC_SRB_DISCONTIG) { in fc_fcp_recv_data()
558 if (fsp->xfer_contig_end == start_offset) in fc_fcp_recv_data()
559 fsp->xfer_contig_end += copy_len; in fc_fcp_recv_data()
560 fsp->xfer_len += copy_len; in fc_fcp_recv_data()
566 if (unlikely(fsp->state & FC_SRB_RCV_STATUS) && in fc_fcp_recv_data()
567 fsp->xfer_len == fsp->data_len - fsp->scsi_resid) { in fc_fcp_recv_data()
568 FC_FCP_DBG( fsp, "complete out-of-order sequence\n" ); in fc_fcp_recv_data()
577 * fc_fcp_send_data() - Send SCSI data to a target
585 * seq_blen amount of data in single frame, otherwise send
596 struct fc_lport *lport = fsp->lp; in fc_fcp_send_data()
607 int using_sg = lport->sg_supp; in fc_fcp_send_data()
611 if (unlikely(offset + seq_blen > fsp->data_len)) { in fc_fcp_send_data()
613 FC_FCP_DBG(fsp, "xfer-ready past end. seq_blen %zx " in fc_fcp_send_data()
617 } else if (offset != fsp->xfer_len) { in fc_fcp_send_data()
618 /* Out of Order Data Request - no problem, but unexpected. */ in fc_fcp_send_data()
619 FC_FCP_DBG(fsp, "xfer-ready non-contiguous. " in fc_fcp_send_data()
626 * to max FC frame payload previously set in fsp->max_payload. in fc_fcp_send_data()
628 t_blen = fsp->max_payload; in fc_fcp_send_data()
629 if (lport->seq_offload) { in fc_fcp_send_data()
630 t_blen = min(seq_blen, (size_t)lport->lso_max); in fc_fcp_send_data()
632 fsp, seq_blen, lport->lso_max, t_blen); in fc_fcp_send_data()
636 t_blen &= ~(512 - 1); /* round down to block size */ in fc_fcp_send_data()
637 sc = fsp->cmd; in fc_fcp_send_data()
649 if (offset >= sg->length) { in fc_fcp_send_data()
650 offset -= sg->length; in fc_fcp_send_data()
659 * handle odd lengths in non-linear skbs. in fc_fcp_send_data()
666 return -ENOMEM; in fc_fcp_send_data()
670 fr_max_payload(fp) = fsp->max_payload; in fc_fcp_send_data()
673 off = offset + sg->offset; in fc_fcp_send_data()
674 sg_bytes = min(tlen, sg->length - offset); in fc_fcp_send_data()
676 (size_t) (PAGE_SIZE - (off & ~PAGE_MASK))); in fc_fcp_send_data()
681 skb_shinfo(fp_skb(fp))->nr_frags, in fc_fcp_send_data()
683 fp_skb(fp)->data_len += sg_bytes; in fc_fcp_send_data()
685 fp_skb(fp)->truesize += PAGE_SIZE; in fc_fcp_send_data()
699 tlen -= sg_bytes; in fc_fcp_send_data()
700 remaining -= sg_bytes; in fc_fcp_send_data()
702 if ((skb_shinfo(fp_skb(fp))->nr_frags < FC_FRAME_SG_LEN) && in fc_fcp_send_data()
714 fc_fill_fc_hdr(fp, FC_RCTL_DD_SOL_DATA, ep->did, ep->sid, in fc_fcp_send_data()
727 fsp->xfer_len += seq_blen; /* premature count? */ in fc_fcp_send_data()
732 * fc_fcp_abts_resp() - Receive an ABTS response
743 switch (fh->fh_r_ctl) { in fc_fcp_abts_resp()
748 if (brp && brp->br_reason == FC_BA_RJT_LOG_ERR) in fc_fcp_abts_resp()
754 * and scsi-ml recover in this case, in fc_fcp_abts_resp()
765 * fc_fcp_recv() - Receive an FCP frame
776 struct fc_lport *lport = fsp->lp; in fc_fcp_recv()
788 r_ctl = fh->fh_r_ctl; in fc_fcp_recv()
790 if (lport->state != LPORT_ST_READY) { in fc_fcp_recv()
792 lport->state, r_ctl); in fc_fcp_recv()
798 if (fh->fh_type == FC_TYPE_BLS) { in fc_fcp_recv()
803 if (fsp->state & (FC_SRB_ABORTED | FC_SRB_ABORT_PENDING)) { in fc_fcp_recv()
818 (size_t) ntohl(dd->ft_data_ro), in fc_fcp_recv()
819 (size_t) ntohl(dd->ft_burst_len)); in fc_fcp_recv()
821 seq->rec_data = fsp->xfer_len; in fc_fcp_recv()
829 seq->rec_data = fsp->xfer_contig_end; in fc_fcp_recv()
844 * fc_fcp_resp() - Handler for FCP responses
864 plen -= sizeof(*fh); in fc_fcp_resp()
866 fsp->cdb_status = fc_rp->fr_status; in fc_fcp_resp()
867 flags = fc_rp->fr_flags; in fc_fcp_resp()
868 fsp->scsi_comp_flags = flags; in fc_fcp_resp()
869 expected_len = fsp->data_len; in fc_fcp_resp()
874 if (unlikely((flags & ~FCP_CONF_REQ) || fc_rp->fr_status)) { in fc_fcp_resp()
881 respl = ntohl(rp_ex->fr_rsp_len); in fc_fcp_resp()
885 if (fsp->wait_for_comp) { in fc_fcp_resp()
887 fsp->cdb_status = fc_rp_info->rsp_code; in fc_fcp_resp()
888 complete(&fsp->tm_done); in fc_fcp_resp()
897 snsl = ntohl(rp_ex->fr_sns_len); in fc_fcp_resp()
900 memcpy(fsp->cmd->sense_buffer, in fc_fcp_resp()
905 if (plen < sizeof(*fc_rp) + sizeof(rp_ex->fr_resid)) in fc_fcp_resp()
908 fsp->scsi_resid = ntohl(rp_ex->fr_resid); in fc_fcp_resp()
910 * The cmnd->underflow is the minimum number of in fc_fcp_resp()
918 (fc_rp->fr_status == 0) && in fc_fcp_resp()
919 (scsi_bufflen(fsp->cmd) - in fc_fcp_resp()
920 fsp->scsi_resid) < fsp->cmd->underflow) in fc_fcp_resp()
922 expected_len -= fsp->scsi_resid; in fc_fcp_resp()
924 fsp->status_code = FC_ERROR; in fc_fcp_resp()
928 fsp->state |= FC_SRB_RCV_STATUS; in fc_fcp_resp()
933 if (unlikely(fsp->cdb_status == SAM_STAT_GOOD && in fc_fcp_resp()
934 fsp->xfer_len != expected_len)) { in fc_fcp_resp()
935 if (fsp->xfer_len < expected_len) { in fc_fcp_resp()
941 if (fsp->lp->qfull) { in fc_fcp_resp()
943 fsp->rport->port_id); in fc_fcp_resp()
948 fsp->rport->port_id, in fc_fcp_resp()
949 fsp->xfer_len, expected_len, fsp->data_len); in fc_fcp_resp()
953 fsp->status_code = FC_DATA_OVRRUN; in fc_fcp_resp()
956 fsp->rport->port_id, in fc_fcp_resp()
957 fsp->xfer_len, expected_len, fsp->data_len); in fc_fcp_resp()
966 fsp->status_code = FC_ERROR; in fc_fcp_resp()
971 * fc_fcp_complete_locked() - Complete processing of a fcp_pkt with the
980 struct fc_lport *lport = fsp->lp; in fc_fcp_complete_locked()
985 if (fsp->state & FC_SRB_ABORT_PENDING) in fc_fcp_complete_locked()
988 if (fsp->state & FC_SRB_ABORTED) { in fc_fcp_complete_locked()
989 if (!fsp->status_code) in fc_fcp_complete_locked()
990 fsp->status_code = FC_CMD_ABORTED; in fc_fcp_complete_locked()
996 if (fsp->cdb_status == SAM_STAT_GOOD && in fc_fcp_complete_locked()
997 fsp->xfer_len < fsp->data_len && !fsp->io_status && in fc_fcp_complete_locked()
998 (!(fsp->scsi_comp_flags & FCP_RESID_UNDER) || in fc_fcp_complete_locked()
999 fsp->xfer_len < fsp->data_len - fsp->scsi_resid)) { in fc_fcp_complete_locked()
1001 fsp->xfer_len, fsp->data_len); in fc_fcp_complete_locked()
1002 fsp->status_code = FC_DATA_UNDRUN; in fc_fcp_complete_locked()
1006 seq = fsp->seq_ptr; in fc_fcp_complete_locked()
1008 fsp->seq_ptr = NULL; in fc_fcp_complete_locked()
1009 if (unlikely(fsp->scsi_comp_flags & FCP_CONF_REQ)) { in fc_fcp_complete_locked()
1014 conf_frame = fc_fcp_frame_alloc(fsp->lp, 0); in fc_fcp_complete_locked()
1020 ep->did, ep->sid, in fc_fcp_complete_locked()
1032 if (fsp->cmd) in fc_fcp_complete_locked()
1037 * fc_fcp_cleanup_cmd() - Cancel the active exchange on a fcp_pkt
1043 if (fsp->seq_ptr) { in fc_fcp_cleanup_cmd()
1044 fc_exch_done(fsp->seq_ptr); in fc_fcp_cleanup_cmd()
1045 fsp->seq_ptr = NULL; in fc_fcp_cleanup_cmd()
1047 fsp->status_code = error; in fc_fcp_cleanup_cmd()
1051 * fc_fcp_cleanup_each_cmd() - Cancel all exchanges on a local port
1057 * If lun or id is -1, they are ignored.
1067 spin_lock_irqsave(&si->scsi_queue_lock, flags); in fc_fcp_cleanup_each_cmd()
1069 list_for_each_entry(fsp, &si->scsi_pkt_queue, list) { in fc_fcp_cleanup_each_cmd()
1070 sc_cmd = fsp->cmd; in fc_fcp_cleanup_each_cmd()
1071 if (id != -1 && scmd_id(sc_cmd) != id) in fc_fcp_cleanup_each_cmd()
1074 if (lun != -1 && sc_cmd->device->lun != lun) in fc_fcp_cleanup_each_cmd()
1078 spin_unlock_irqrestore(&si->scsi_queue_lock, flags); in fc_fcp_cleanup_each_cmd()
1080 spin_lock_bh(&fsp->scsi_pkt_lock); in fc_fcp_cleanup_each_cmd()
1081 if (!(fsp->state & FC_SRB_COMPL)) { in fc_fcp_cleanup_each_cmd()
1082 fsp->state |= FC_SRB_COMPL; in fc_fcp_cleanup_each_cmd()
1092 spin_unlock_bh(&fsp->scsi_pkt_lock); in fc_fcp_cleanup_each_cmd()
1096 spin_lock_bh(&fsp->scsi_pkt_lock); in fc_fcp_cleanup_each_cmd()
1099 spin_unlock_bh(&fsp->scsi_pkt_lock); in fc_fcp_cleanup_each_cmd()
1102 spin_lock_irqsave(&si->scsi_queue_lock, flags); in fc_fcp_cleanup_each_cmd()
1109 spin_unlock_irqrestore(&si->scsi_queue_lock, flags); in fc_fcp_cleanup_each_cmd()
1113 * fc_fcp_abort_io() - Abort all FCP-SCSI exchanges on a local port
1118 fc_fcp_cleanup_each_cmd(lport, -1, -1, FC_HRD_ERROR); in fc_fcp_abort_io()
1122 * fc_fcp_pkt_send() - Send a fcp_pkt
1126 * Return: Zero for success and -1 for failure
1135 libfc_priv(fsp->cmd)->fsp = fsp; in fc_fcp_pkt_send()
1136 fsp->cdb_cmd.fc_dl = htonl(fsp->data_len); in fc_fcp_pkt_send()
1137 fsp->cdb_cmd.fc_flags = fsp->req_flags & ~FCP_CFL_LEN_MASK; in fc_fcp_pkt_send()
1139 int_to_scsilun(fsp->cmd->device->lun, &fsp->cdb_cmd.fc_lun); in fc_fcp_pkt_send()
1140 memcpy(fsp->cdb_cmd.fc_cdb, fsp->cmd->cmnd, fsp->cmd->cmd_len); in fc_fcp_pkt_send()
1142 spin_lock_irqsave(&si->scsi_queue_lock, flags); in fc_fcp_pkt_send()
1143 list_add_tail(&fsp->list, &si->scsi_pkt_queue); in fc_fcp_pkt_send()
1144 spin_unlock_irqrestore(&si->scsi_queue_lock, flags); in fc_fcp_pkt_send()
1145 rc = lport->tt.fcp_cmd_send(lport, fsp, fc_fcp_recv); in fc_fcp_pkt_send()
1147 spin_lock_irqsave(&si->scsi_queue_lock, flags); in fc_fcp_pkt_send()
1148 libfc_priv(fsp->cmd)->fsp = NULL; in fc_fcp_pkt_send()
1149 list_del(&fsp->list); in fc_fcp_pkt_send()
1150 spin_unlock_irqrestore(&si->scsi_queue_lock, flags); in fc_fcp_pkt_send()
1157 * fc_fcp_cmd_send() - Send a FCP command
1171 const size_t len = sizeof(fsp->cdb_cmd); in fc_fcp_cmd_send()
1177 fp = fc_fcp_frame_alloc(lport, sizeof(fsp->cdb_cmd)); in fc_fcp_cmd_send()
1179 rc = -1; in fc_fcp_cmd_send()
1183 memcpy(fc_frame_payload_get(fp, len), &fsp->cdb_cmd, len); in fc_fcp_cmd_send()
1185 rport = fsp->rport; in fc_fcp_cmd_send()
1186 fsp->max_payload = rport->maxframe_size; in fc_fcp_cmd_send()
1187 rpriv = rport->dd_data; in fc_fcp_cmd_send()
1189 fc_fill_fc_hdr(fp, FC_RCTL_DD_UNSOL_CMD, rport->port_id, in fc_fcp_cmd_send()
1190 rpriv->local_port->port_id, FC_TYPE_FCP, in fc_fcp_cmd_send()
1195 rc = -1; in fc_fcp_cmd_send()
1198 fsp->seq_ptr = seq; in fc_fcp_cmd_send()
1201 fsp->timer.function = fc_fcp_timeout; in fc_fcp_cmd_send()
1202 if (rpriv->flags & FC_RP_FLAGS_REC_SUPPORTED) in fc_fcp_cmd_send()
1211 * fc_fcp_error() - Handler for FCP layer errors
1222 if (error == -FC_EX_CLOSED) { in fc_fcp_error()
1231 fsp->state &= ~FC_SRB_ABORT_PENDING; in fc_fcp_error()
1232 fsp->status_code = FC_CMD_PLOGO; in fc_fcp_error()
1239 * fc_fcp_pkt_abort() - Abort a fcp_pkt
1249 FC_FCP_DBG(fsp, "pkt abort state %x\n", fsp->state); in fc_fcp_pkt_abort()
1255 if (fsp->state & FC_SRB_ABORTED) { in fc_fcp_pkt_abort()
1260 init_completion(&fsp->tm_done); in fc_fcp_pkt_abort()
1261 fsp->wait_for_comp = 1; in fc_fcp_pkt_abort()
1263 spin_unlock_bh(&fsp->scsi_pkt_lock); in fc_fcp_pkt_abort()
1264 ticks_left = wait_for_completion_timeout(&fsp->tm_done, in fc_fcp_pkt_abort()
1266 spin_lock_bh(&fsp->scsi_pkt_lock); in fc_fcp_pkt_abort()
1267 fsp->wait_for_comp = 0; in fc_fcp_pkt_abort()
1271 } else if (fsp->state & FC_SRB_ABORTED) { in fc_fcp_pkt_abort()
1281 * fc_lun_reset_send() - Send LUN reset command
1287 struct fc_lport *lport = fsp->lp; in fc_lun_reset_send()
1289 if (lport->tt.fcp_cmd_send(lport, fsp, fc_tm_done)) { in fc_lun_reset_send()
1290 if (fsp->recov_retry++ >= FC_MAX_RECOV_RETRY) in fc_lun_reset_send()
1294 fsp->timer.function = fc_lun_reset_send; in fc_lun_reset_send()
1301 * fc_lun_reset() - Send a LUN RESET command to a device
1313 fsp->cdb_cmd.fc_dl = htonl(fsp->data_len); in fc_lun_reset()
1314 fsp->cdb_cmd.fc_tm_flags = FCP_TMF_LUN_RESET; in fc_lun_reset()
1315 int_to_scsilun(lun, &fsp->cdb_cmd.fc_lun); in fc_lun_reset()
1317 fsp->wait_for_comp = 1; in fc_lun_reset()
1318 init_completion(&fsp->tm_done); in fc_lun_reset()
1320 fc_lun_reset_send(&fsp->timer); in fc_lun_reset()
1326 rc = wait_for_completion_timeout(&fsp->tm_done, FC_SCSI_TM_TOV); in fc_lun_reset()
1328 spin_lock_bh(&fsp->scsi_pkt_lock); in fc_lun_reset()
1329 fsp->state |= FC_SRB_COMPL; in fc_lun_reset()
1330 spin_unlock_bh(&fsp->scsi_pkt_lock); in fc_lun_reset()
1332 del_timer_sync(&fsp->timer); in fc_lun_reset()
1334 spin_lock_bh(&fsp->scsi_pkt_lock); in fc_lun_reset()
1335 if (fsp->seq_ptr) { in fc_lun_reset()
1336 fc_exch_done(fsp->seq_ptr); in fc_lun_reset()
1337 fsp->seq_ptr = NULL; in fc_lun_reset()
1339 fsp->wait_for_comp = 0; in fc_lun_reset()
1340 spin_unlock_bh(&fsp->scsi_pkt_lock); in fc_lun_reset()
1348 if (fsp->cdb_status != FCP_TMF_CMPL) in fc_lun_reset()
1357 * fc_tm_done() - Task Management response handler
1372 * scsi-eh will escalate for when either happens. in fc_tm_done()
1383 if (!fsp->seq_ptr || !fsp->wait_for_comp) in fc_tm_done()
1387 if (fh->fh_type != FC_TYPE_BLS) in fc_tm_done()
1389 fsp->seq_ptr = NULL; in fc_tm_done()
1398 * fc_fcp_cleanup() - Cleanup all FCP exchanges on a local port
1403 fc_fcp_cleanup_each_cmd(lport, -1, -1, FC_ERROR); in fc_fcp_cleanup()
1407 * fc_fcp_timeout() - Handler for fcp_pkt timeouts
1420 struct fc_rport *rport = fsp->rport; in fc_fcp_timeout()
1421 struct fc_rport_libfc_priv *rpriv = rport->dd_data; in fc_fcp_timeout()
1426 if (fsp->cdb_cmd.fc_tm_flags) in fc_fcp_timeout()
1429 if (fsp->lp->qfull) { in fc_fcp_timeout()
1431 fsp->timer_delay); in fc_fcp_timeout()
1432 fsp->timer.function = fc_fcp_timeout; in fc_fcp_timeout()
1433 fc_fcp_timer_set(fsp, fsp->timer_delay); in fc_fcp_timeout()
1437 fsp->timer_delay, rpriv->flags, fsp->state); in fc_fcp_timeout()
1438 fsp->state |= FC_SRB_FCP_PROCESSING_TMO; in fc_fcp_timeout()
1440 if (rpriv->flags & FC_RP_FLAGS_REC_SUPPORTED) in fc_fcp_timeout()
1442 else if (fsp->state & FC_SRB_RCV_STATUS) in fc_fcp_timeout()
1446 fsp->state &= ~FC_SRB_FCP_PROCESSING_TMO; in fc_fcp_timeout()
1452 * fc_fcp_rec() - Send a REC ELS request
1462 lport = fsp->lp; in fc_fcp_rec()
1463 rport = fsp->rport; in fc_fcp_rec()
1464 rpriv = rport->dd_data; in fc_fcp_rec()
1465 if (!fsp->seq_ptr || rpriv->rp_state != RPORT_ST_READY) { in fc_fcp_rec()
1466 fsp->status_code = FC_HRD_ERROR; in fc_fcp_rec()
1467 fsp->io_status = 0; in fc_fcp_rec()
1476 fr_seq(fp) = fsp->seq_ptr; in fc_fcp_rec()
1477 fc_fill_fc_hdr(fp, FC_RCTL_ELS_REQ, rport->port_id, in fc_fcp_rec()
1478 rpriv->local_port->port_id, FC_TYPE_ELS, in fc_fcp_rec()
1480 if (lport->tt.elsct_send(lport, rport->port_id, fp, ELS_REC, in fc_fcp_rec()
1482 2 * lport->r_a_tov)) { in fc_fcp_rec()
1487 if (fsp->recov_retry++ < FC_MAX_RECOV_RETRY) in fc_fcp_rec()
1494 * fc_fcp_rec_resp() - Handler for REC ELS responses
1524 fsp->recov_retry = 0; in fc_fcp_rec_resp()
1528 switch (rjt->er_reason) { in fc_fcp_rec_resp()
1532 fsp->rport->port_id, rjt->er_reason, in fc_fcp_rec_resp()
1533 rjt->er_explan); in fc_fcp_rec_resp()
1537 rpriv = fsp->rport->dd_data; in fc_fcp_rec_resp()
1543 rpriv->flags &= ~FC_RP_FLAGS_REC_SUPPORTED; in fc_fcp_rec_resp()
1548 fsp->rport->port_id, rjt->er_reason, in fc_fcp_rec_resp()
1549 rjt->er_explan); in fc_fcp_rec_resp()
1556 if (rjt->er_explan == ELS_EXPL_OXID_RXID) { in fc_fcp_rec_resp()
1557 struct fc_exch *ep = fc_seq_exch(fsp->seq_ptr); in fc_fcp_rec_resp()
1558 ep->state |= FC_EX_QUARANTINE; in fc_fcp_rec_resp()
1559 fsp->state |= FC_SRB_ABORTED; in fc_fcp_rec_resp()
1567 if (fsp->state & FC_SRB_ABORTED) in fc_fcp_rec_resp()
1570 data_dir = fsp->cmd->sc_data_direction; in fc_fcp_rec_resp()
1572 offset = ntohl(recp->reca_fc4value); in fc_fcp_rec_resp()
1573 e_stat = ntohl(recp->reca_e_stat); in fc_fcp_rec_resp()
1589 * Recovery via SRR relies on in-order-delivery. in fc_fcp_rec_resp()
1593 } else if (fsp->xfer_contig_end == offset) { in fc_fcp_rec_resp()
1596 offset = fsp->xfer_contig_end; in fc_fcp_rec_resp()
1626 if (offset < fsp->data_len) in fc_fcp_rec_resp()
1628 } else if (offset == fsp->xfer_contig_end) { in fc_fcp_rec_resp()
1630 } else if (fsp->xfer_contig_end < offset) { in fc_fcp_rec_resp()
1631 offset = fsp->xfer_contig_end; in fc_fcp_rec_resp()
1644 * fc_fcp_rec_error() - Handler for REC errors
1656 case -FC_EX_CLOSED: in fc_fcp_rec_error()
1658 fsp, fsp->rport->port_id); in fc_fcp_rec_error()
1664 fsp, fsp->rport->port_id, error); in fc_fcp_rec_error()
1665 fsp->status_code = FC_CMD_PLOGO; in fc_fcp_rec_error()
1668 case -FC_EX_TIMEOUT: in fc_fcp_rec_error()
1674 fsp, fsp->rport->port_id, fsp->recov_retry, in fc_fcp_rec_error()
1676 if (fsp->recov_retry++ < FC_MAX_RECOV_RETRY) in fc_fcp_rec_error()
1688 * fc_fcp_recovery() - Handler for fcp_pkt recovery
1695 fsp->status_code = code; in fc_fcp_recovery()
1696 fsp->cdb_status = 0; in fc_fcp_recovery()
1697 fsp->io_status = 0; in fc_fcp_recovery()
1698 if (!fsp->cmd) in fc_fcp_recovery()
1700 * Only abort non-scsi commands; otherwise let the in fc_fcp_recovery()
1701 * scsi command timer fire and scsi-ml escalate. in fc_fcp_recovery()
1707 * fc_fcp_srr() - Send a SRR request (Sequence Retransmission Request)
1716 struct fc_lport *lport = fsp->lp; in fc_fcp_srr()
1719 struct fc_exch *ep = fc_seq_exch(fsp->seq_ptr); in fc_fcp_srr()
1724 rport = fsp->rport; in fc_fcp_srr()
1725 rpriv = rport->dd_data; in fc_fcp_srr()
1727 if (!(rpriv->flags & FC_RP_FLAGS_RETRY) || in fc_fcp_srr()
1728 rpriv->rp_state != RPORT_ST_READY) in fc_fcp_srr()
1736 srr->srr_op = ELS_SRR; in fc_fcp_srr()
1737 srr->srr_ox_id = htons(ep->oxid); in fc_fcp_srr()
1738 srr->srr_rx_id = htons(ep->rxid); in fc_fcp_srr()
1739 srr->srr_r_ctl = r_ctl; in fc_fcp_srr()
1740 srr->srr_rel_off = htonl(offset); in fc_fcp_srr()
1742 fc_fill_fc_hdr(fp, FC_RCTL_ELS4_REQ, rport->port_id, in fc_fcp_srr()
1743 rpriv->local_port->port_id, FC_TYPE_FCP, in fc_fcp_srr()
1752 fsp->recov_seq = seq; in fc_fcp_srr()
1753 fsp->xfer_len = offset; in fc_fcp_srr()
1754 fsp->xfer_contig_end = offset; in fc_fcp_srr()
1755 fsp->state &= ~FC_SRB_RCV_STATUS; in fc_fcp_srr()
1763 * fc_fcp_srr_resp() - Handler for SRR response
1784 * the ep. But if fc_fcp_srr_error had got -FC_EX_TIMEOUT, in fc_fcp_srr_resp()
1789 if (fh->fh_type == FC_TYPE_BLS) { in fc_fcp_srr_resp()
1796 fsp->recov_retry = 0; in fc_fcp_srr_resp()
1811 * fc_fcp_srr_error() - Handler for SRR errors
1820 case -FC_EX_TIMEOUT: in fc_fcp_srr_error()
1821 FC_FCP_DBG(fsp, "SRR timeout, retries %d\n", fsp->recov_retry); in fc_fcp_srr_error()
1822 if (fsp->recov_retry++ < FC_MAX_RECOV_RETRY) in fc_fcp_srr_error()
1827 case -FC_EX_CLOSED: /* e.g., link failure */ in fc_fcp_srr_error()
1836 fc_exch_done(fsp->recov_seq); in fc_fcp_srr_error()
1840 * fc_fcp_lport_queue_ready() - Determine if the lport and it's queue is ready
1846 return (lport->state == LPORT_ST_READY) && in fc_fcp_lport_queue_ready()
1847 lport->link_up && !lport->qfull; in fc_fcp_lport_queue_ready()
1851 * fc_queuecommand() - The queuecommand function of the SCSI template
1860 struct fc_rport *rport = starget_to_rport(scsi_target(sc_cmd->device)); in fc_queuecommand()
1867 sc_cmd->result = rval; in fc_queuecommand()
1872 if (!*(struct fc_remote_port **)rport->dd_data) { in fc_queuecommand()
1877 sc_cmd->result = DID_IMM_RETRY << 16; in fc_queuecommand()
1883 if (lport->qfull) { in fc_queuecommand()
1885 shost_printk(KERN_ERR, lport->host, in fc_queuecommand()
1888 lport->host->can_queue); in fc_queuecommand()
1903 fsp->cmd = sc_cmd; /* save the cmd */ in fc_queuecommand()
1904 fsp->rport = rport; /* set the remote port ptr */ in fc_queuecommand()
1909 fsp->data_len = scsi_bufflen(sc_cmd); in fc_queuecommand()
1910 fsp->xfer_len = 0; in fc_queuecommand()
1915 if (sc_cmd->sc_data_direction == DMA_FROM_DEVICE) { in fc_queuecommand()
1916 fsp->req_flags = FC_SRB_READ; in fc_queuecommand()
1917 this_cpu_inc(lport->stats->InputRequests); in fc_queuecommand()
1918 this_cpu_add(lport->stats->InputBytes, fsp->data_len); in fc_queuecommand()
1919 } else if (sc_cmd->sc_data_direction == DMA_TO_DEVICE) { in fc_queuecommand()
1920 fsp->req_flags = FC_SRB_WRITE; in fc_queuecommand()
1921 this_cpu_inc(lport->stats->OutputRequests); in fc_queuecommand()
1922 this_cpu_add(lport->stats->OutputBytes, fsp->data_len); in fc_queuecommand()
1924 fsp->req_flags = 0; in fc_queuecommand()
1925 this_cpu_inc(lport->stats->ControlRequests); in fc_queuecommand()
1930 * if we get -1 return then put the request in the pending in fc_queuecommand()
1935 fsp->state = FC_SRB_FREE; in fc_queuecommand()
1945 * fc_io_compl() - Handle responses for completed commands
1961 fsp->state |= FC_SRB_COMPL; in fc_io_compl()
1962 if (!(fsp->state & FC_SRB_FCP_PROCESSING_TMO)) { in fc_io_compl()
1963 spin_unlock_bh(&fsp->scsi_pkt_lock); in fc_io_compl()
1964 del_timer_sync(&fsp->timer); in fc_io_compl()
1965 spin_lock_bh(&fsp->scsi_pkt_lock); in fc_io_compl()
1968 lport = fsp->lp; in fc_io_compl()
1975 if (si->last_can_queue_ramp_down_time) in fc_io_compl()
1978 sc_cmd = fsp->cmd; in fc_io_compl()
1979 libfc_priv(sc_cmd)->status = fsp->cdb_status; in fc_io_compl()
1980 switch (fsp->status_code) { in fc_io_compl()
1982 if (fsp->cdb_status == 0) { in fc_io_compl()
1986 sc_cmd->result = DID_OK << 16; in fc_io_compl()
1987 if (fsp->scsi_resid) in fc_io_compl()
1988 libfc_priv(sc_cmd)->resid_len = fsp->scsi_resid; in fc_io_compl()
1994 sc_cmd->result = (DID_OK << 16) | fsp->cdb_status; in fc_io_compl()
1998 FC_FCP_DBG(fsp, "Returning DID_ERROR to scsi-ml " in fc_io_compl()
2000 sc_cmd->result = DID_ERROR << 16; in fc_io_compl()
2003 if ((fsp->cdb_status == 0) && !(fsp->req_flags & FC_SRB_READ)) { in fc_io_compl()
2008 if (fsp->state & FC_SRB_RCV_STATUS) { in fc_io_compl()
2009 sc_cmd->result = DID_OK << 16; in fc_io_compl()
2011 FC_FCP_DBG(fsp, "Returning DID_ERROR to scsi-ml" in fc_io_compl()
2013 sc_cmd->result = DID_ERROR << 16; in fc_io_compl()
2019 FC_FCP_DBG(fsp, "Returning DID_ERROR to scsi-ml " in fc_io_compl()
2021 libfc_priv(sc_cmd)->resid_len = fsp->scsi_resid; in fc_io_compl()
2022 sc_cmd->result = (DID_ERROR << 16) | fsp->cdb_status; in fc_io_compl()
2029 FC_FCP_DBG(fsp, "Returning DID_ERROR to scsi-ml " in fc_io_compl()
2031 sc_cmd->result = (DID_ERROR << 16) | fsp->cdb_status; in fc_io_compl()
2034 if (host_byte(sc_cmd->result) == DID_TIME_OUT) in fc_io_compl()
2035 FC_FCP_DBG(fsp, "Returning DID_TIME_OUT to scsi-ml " in fc_io_compl()
2038 FC_FCP_DBG(fsp, "Returning DID_ERROR to scsi-ml " in fc_io_compl()
2042 sc_cmd->result |= fsp->io_status; in fc_io_compl()
2045 FC_FCP_DBG(fsp, "Returning DID_RESET to scsi-ml " in fc_io_compl()
2047 sc_cmd->result = (DID_RESET << 16); in fc_io_compl()
2050 FC_FCP_DBG(fsp, "Returning DID_SOFT_ERROR to scsi-ml " in fc_io_compl()
2052 sc_cmd->result = (DID_SOFT_ERROR << 16); in fc_io_compl()
2055 FC_FCP_DBG(fsp, "Returning DID_NO_CONNECT to scsi-ml " in fc_io_compl()
2057 sc_cmd->result = (DID_NO_CONNECT << 16); in fc_io_compl()
2060 FC_FCP_DBG(fsp, "Returning DID_PARITY to scsi-ml " in fc_io_compl()
2062 sc_cmd->result = (DID_PARITY << 16); in fc_io_compl()
2065 FC_FCP_DBG(fsp, "Returning DID_TIME_OUT to scsi-ml " in fc_io_compl()
2067 sc_cmd->result = (DID_TIME_OUT << 16); in fc_io_compl()
2070 FC_FCP_DBG(fsp, "Returning DID_ERROR to scsi-ml " in fc_io_compl()
2072 sc_cmd->result = (DID_ERROR << 16); in fc_io_compl()
2076 if (lport->state != LPORT_ST_READY && fsp->status_code != FC_COMPLETE) in fc_io_compl()
2077 sc_cmd->result = (DID_TRANSPORT_DISRUPTED << 16); in fc_io_compl()
2079 spin_lock_irqsave(&si->scsi_queue_lock, flags); in fc_io_compl()
2080 list_del(&fsp->list); in fc_io_compl()
2081 libfc_priv(sc_cmd)->fsp = NULL; in fc_io_compl()
2082 spin_unlock_irqrestore(&si->scsi_queue_lock, flags); in fc_io_compl()
2090 * fc_eh_abort() - Abort a command
2109 lport = shost_priv(sc_cmd->device->host); in fc_eh_abort()
2110 if (lport->state != LPORT_ST_READY) in fc_eh_abort()
2112 else if (!lport->link_up) in fc_eh_abort()
2116 spin_lock_irqsave(&si->scsi_queue_lock, flags); in fc_eh_abort()
2117 fsp = libfc_priv(sc_cmd)->fsp; in fc_eh_abort()
2120 spin_unlock_irqrestore(&si->scsi_queue_lock, flags); in fc_eh_abort()
2125 spin_unlock_irqrestore(&si->scsi_queue_lock, flags); in fc_eh_abort()
2143 * fc_eh_device_reset() - Reset a single LUN
2153 struct fc_rport *rport = starget_to_rport(scsi_target(sc_cmd->device)); in fc_eh_device_reset()
2161 lport = shost_priv(sc_cmd->device->host); in fc_eh_device_reset()
2163 if (lport->state != LPORT_ST_READY) in fc_eh_device_reset()
2166 FC_SCSI_DBG(lport, "Resetting rport (%6.6x)\n", rport->port_id); in fc_eh_device_reset()
2179 fsp->rport = rport; /* set the remote port ptr */ in fc_eh_device_reset()
2184 rc = fc_lun_reset(lport, fsp, scmd_id(sc_cmd), sc_cmd->device->lun); in fc_eh_device_reset()
2185 fsp->state = FC_SRB_FREE; in fc_eh_device_reset()
2194 * fc_eh_host_reset() - Reset a Scsi_Host.
2199 struct Scsi_Host *shost = sc_cmd->device->host; in fc_eh_host_reset()
2213 "on port (%6.6x)\n", lport->port_id); in fc_eh_host_reset()
2218 lport->port_id); in fc_eh_host_reset()
2225 * fc_sdev_init() - Configure the queue depth of a Scsi_Host
2236 return -ENXIO; in fc_sdev_init()
2244 * fc_fcp_destroy() - Tear down the FCP layer for a given local port
2251 if (!list_empty(&si->scsi_pkt_queue)) in fc_fcp_destroy()
2253 "port (%6.6x)\n", lport->port_id); in fc_fcp_destroy()
2255 mempool_destroy(si->scsi_pkt_pool); in fc_fcp_destroy()
2257 lport->scsi_priv = NULL; in fc_fcp_destroy()
2271 rc = -ENOMEM; in fc_setup_fcp()
2283 * fc_fcp_init() - Initialize the FCP layer for a local port
2291 if (!lport->tt.fcp_cmd_send) in fc_fcp_init()
2292 lport->tt.fcp_cmd_send = fc_fcp_cmd_send; in fc_fcp_init()
2294 if (!lport->tt.fcp_cleanup) in fc_fcp_init()
2295 lport->tt.fcp_cleanup = fc_fcp_cleanup; in fc_fcp_init()
2297 if (!lport->tt.fcp_abort_io) in fc_fcp_init()
2298 lport->tt.fcp_abort_io = fc_fcp_abort_io; in fc_fcp_init()
2302 return -ENOMEM; in fc_fcp_init()
2303 lport->scsi_priv = si; in fc_fcp_init()
2304 si->max_can_queue = lport->host->can_queue; in fc_fcp_init()
2305 INIT_LIST_HEAD(&si->scsi_pkt_queue); in fc_fcp_init()
2306 spin_lock_init(&si->scsi_queue_lock); in fc_fcp_init()
2308 si->scsi_pkt_pool = mempool_create_slab_pool(2, scsi_pkt_cachep); in fc_fcp_init()
2309 if (!si->scsi_pkt_pool) { in fc_fcp_init()
2310 rc = -ENOMEM; in fc_fcp_init()