Extend ICL to add receive offload methods. For software ICL backend
they are no-ops. MFC after: 1 month Sponsored by: The FreeBSD Foundation
This commit is contained in:
parent
a840d2f5b8
commit
7a03d007cf
@ -164,6 +164,12 @@ static void cfiscsi_pdu_handle_task_request(struct icl_pdu *request);
|
||||
static void cfiscsi_pdu_handle_data_out(struct icl_pdu *request);
|
||||
static void cfiscsi_pdu_handle_logout_request(struct icl_pdu *request);
|
||||
static void cfiscsi_session_terminate(struct cfiscsi_session *cs);
|
||||
static struct cfiscsi_data_wait *cfiscsi_data_wait_new(
|
||||
struct cfiscsi_session *cs, union ctl_io *io,
|
||||
uint32_t initiator_task_tag,
|
||||
uint32_t *target_transfer_tagp);
|
||||
static void cfiscsi_data_wait_free(struct cfiscsi_session *cs,
|
||||
struct cfiscsi_data_wait *cdw);
|
||||
static struct cfiscsi_target *cfiscsi_target_find(struct cfiscsi_softc
|
||||
*softc, const char *name, uint16_t tag);
|
||||
static struct cfiscsi_target *cfiscsi_target_find_or_create(
|
||||
@ -929,7 +935,7 @@ cfiscsi_pdu_handle_data_out(struct icl_pdu *request)
|
||||
CFISCSI_SESSION_UNLOCK(cs);
|
||||
done = (io->scsiio.ext_data_filled != cdw->cdw_r2t_end ||
|
||||
io->scsiio.ext_data_filled == io->scsiio.kern_data_len);
|
||||
uma_zfree(cfiscsi_data_wait_zone, cdw);
|
||||
cfiscsi_data_wait_free(cs, cdw);
|
||||
if (done)
|
||||
io->scsiio.be_move_done(io);
|
||||
else
|
||||
@ -1067,6 +1073,45 @@ cfiscsi_callout(void *context)
|
||||
cfiscsi_pdu_queue(cp);
|
||||
}
|
||||
|
||||
static struct cfiscsi_data_wait *
|
||||
cfiscsi_data_wait_new(struct cfiscsi_session *cs, union ctl_io *io,
|
||||
uint32_t initiator_task_tag, uint32_t *target_transfer_tagp)
|
||||
{
|
||||
struct cfiscsi_data_wait *cdw;
|
||||
int error;
|
||||
|
||||
cdw = uma_zalloc(cfiscsi_data_wait_zone, M_NOWAIT | M_ZERO);
|
||||
if (cdw == NULL) {
|
||||
CFISCSI_SESSION_WARN(cs,
|
||||
"failed to allocate %zd bytes", sizeof(*cdw));
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
error = icl_conn_transfer_setup(cs->cs_conn, io, target_transfer_tagp,
|
||||
&cdw->cdw_icl_prv);
|
||||
if (error != 0) {
|
||||
CFISCSI_SESSION_WARN(cs,
|
||||
"icl_conn_transfer_setup() failed with error %d", error);
|
||||
uma_zfree(cfiscsi_data_wait_zone, cdw);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
cdw->cdw_ctl_io = io;
|
||||
cdw->cdw_target_transfer_tag = *target_transfer_tagp;
|
||||
cdw->cdw_initiator_task_tag = initiator_task_tag;
|
||||
|
||||
return (cdw);
|
||||
}
|
||||
|
||||
static void
|
||||
cfiscsi_data_wait_free(struct cfiscsi_session *cs,
|
||||
struct cfiscsi_data_wait *cdw)
|
||||
{
|
||||
|
||||
icl_conn_transfer_done(cs->cs_conn, cdw->cdw_icl_prv);
|
||||
uma_zfree(cfiscsi_data_wait_zone, cdw);
|
||||
}
|
||||
|
||||
static void
|
||||
cfiscsi_session_terminate_tasks(struct cfiscsi_session *cs)
|
||||
{
|
||||
@ -1106,7 +1151,7 @@ cfiscsi_session_terminate_tasks(struct cfiscsi_session *cs)
|
||||
*/
|
||||
cdw->cdw_ctl_io->scsiio.io_hdr.port_status = 42;
|
||||
cdw->cdw_ctl_io->scsiio.be_move_done(cdw->cdw_ctl_io);
|
||||
uma_zfree(cfiscsi_data_wait_zone, cdw);
|
||||
cfiscsi_data_wait_free(cs, cdw);
|
||||
CFISCSI_SESSION_LOCK(cs);
|
||||
}
|
||||
CFISCSI_SESSION_UNLOCK(cs);
|
||||
@ -2600,13 +2645,8 @@ cfiscsi_datamove_out(union ctl_io *io)
|
||||
|
||||
target_transfer_tag =
|
||||
atomic_fetchadd_32(&cs->cs_target_transfer_tag, 1);
|
||||
|
||||
#if 0
|
||||
CFISCSI_SESSION_DEBUG(cs, "expecting Data-Out with initiator "
|
||||
"task tag 0x%x, target transfer tag 0x%x",
|
||||
bhssc->bhssc_initiator_task_tag, target_transfer_tag);
|
||||
#endif
|
||||
cdw = uma_zalloc(cfiscsi_data_wait_zone, M_NOWAIT | M_ZERO);
|
||||
cdw = cfiscsi_data_wait_new(cs, io, bhssc->bhssc_initiator_task_tag,
|
||||
&target_transfer_tag);
|
||||
if (cdw == NULL) {
|
||||
CFISCSI_SESSION_WARN(cs, "failed to "
|
||||
"allocate memory; dropping connection");
|
||||
@ -2615,6 +2655,12 @@ cfiscsi_datamove_out(union ctl_io *io)
|
||||
cfiscsi_session_terminate(cs);
|
||||
return;
|
||||
}
|
||||
#if 0
|
||||
CFISCSI_SESSION_DEBUG(cs, "expecting Data-Out with initiator "
|
||||
"task tag 0x%x, target transfer tag 0x%x",
|
||||
bhssc->bhssc_initiator_task_tag, target_transfer_tag);
|
||||
#endif
|
||||
|
||||
cdw->cdw_ctl_io = io;
|
||||
cdw->cdw_target_transfer_tag = target_transfer_tag;
|
||||
cdw->cdw_initiator_task_tag = bhssc->bhssc_initiator_task_tag;
|
||||
@ -2651,7 +2697,7 @@ cfiscsi_datamove_out(union ctl_io *io)
|
||||
icl_pdu_data_segment_length(request)) {
|
||||
done = cfiscsi_handle_data_segment(request, cdw);
|
||||
if (done) {
|
||||
uma_zfree(cfiscsi_data_wait_zone, cdw);
|
||||
cfiscsi_data_wait_free(cs, cdw);
|
||||
io->scsiio.be_move_done(io);
|
||||
return;
|
||||
}
|
||||
@ -2854,7 +2900,7 @@ cfiscsi_task_management_done(union ctl_io *io)
|
||||
TAILQ_REMOVE(&cs->cs_waiting_for_data_out,
|
||||
cdw, cdw_next);
|
||||
cdw->cdw_ctl_io->scsiio.be_move_done(cdw->cdw_ctl_io);
|
||||
uma_zfree(cfiscsi_data_wait_zone, cdw);
|
||||
cfiscsi_data_wait_free(cs, cdw);
|
||||
}
|
||||
CFISCSI_SESSION_UNLOCK(cs);
|
||||
}
|
||||
|
@ -59,6 +59,7 @@ struct cfiscsi_data_wait {
|
||||
size_t cdw_sg_len;
|
||||
uint32_t cdw_r2t_end;
|
||||
uint32_t cdw_datasn;
|
||||
void *cdw_icl_prv;
|
||||
};
|
||||
|
||||
#define CFISCSI_SESSION_STATE_INVALID 0
|
||||
|
@ -85,3 +85,27 @@ METHOD void close {
|
||||
METHOD bool connected {
|
||||
struct icl_conn *_ic;
|
||||
};
|
||||
|
||||
METHOD int task_setup {
|
||||
struct icl_conn *_ic;
|
||||
struct ccb_scsiio *_csio;
|
||||
uint32_t *_task_tag;
|
||||
void **_prvp;
|
||||
};
|
||||
|
||||
METHOD void task_done {
|
||||
struct icl_conn *_ic;
|
||||
void *_prv;
|
||||
};
|
||||
|
||||
METHOD int transfer_setup {
|
||||
struct icl_conn *_ic;
|
||||
union ctl_io *_io;
|
||||
uint32_t *_transfer_tag;
|
||||
void **_prvp;
|
||||
};
|
||||
|
||||
METHOD void transfer_done {
|
||||
struct icl_conn *_ic;
|
||||
void *_prv;
|
||||
};
|
||||
|
@ -98,6 +98,10 @@ static icl_conn_handoff_t icl_soft_conn_handoff;
|
||||
static icl_conn_free_t icl_soft_conn_free;
|
||||
static icl_conn_close_t icl_soft_conn_close;
|
||||
static icl_conn_connected_t icl_soft_conn_connected;
|
||||
static icl_conn_task_setup_t icl_soft_conn_task_setup;
|
||||
static icl_conn_task_done_t icl_soft_conn_task_done;
|
||||
static icl_conn_transfer_setup_t icl_soft_conn_transfer_setup;
|
||||
static icl_conn_transfer_done_t icl_soft_conn_transfer_done;
|
||||
|
||||
static kobj_method_t icl_soft_methods[] = {
|
||||
KOBJMETHOD(icl_conn_new_pdu, icl_soft_conn_new_pdu),
|
||||
@ -111,6 +115,10 @@ static kobj_method_t icl_soft_methods[] = {
|
||||
KOBJMETHOD(icl_conn_free, icl_soft_conn_free),
|
||||
KOBJMETHOD(icl_conn_close, icl_soft_conn_close),
|
||||
KOBJMETHOD(icl_conn_connected, icl_soft_conn_connected),
|
||||
KOBJMETHOD(icl_conn_task_setup, icl_soft_conn_task_setup),
|
||||
KOBJMETHOD(icl_conn_task_done, icl_soft_conn_task_done),
|
||||
KOBJMETHOD(icl_conn_transfer_setup, icl_soft_conn_transfer_setup),
|
||||
KOBJMETHOD(icl_conn_transfer_done, icl_soft_conn_transfer_done),
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
@ -1435,6 +1443,32 @@ icl_soft_conn_connected(struct icl_conn *ic)
|
||||
return (true);
|
||||
}
|
||||
|
||||
int
|
||||
icl_soft_conn_task_setup(struct icl_conn *ic, struct ccb_scsiio *csio,
|
||||
uint32_t *task_tagp, void **prvp)
|
||||
{
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
icl_soft_conn_task_done(struct icl_conn *ic, void *prv)
|
||||
{
|
||||
}
|
||||
|
||||
int
|
||||
icl_soft_conn_transfer_setup(struct icl_conn *ic, union ctl_io *io,
|
||||
uint32_t *transfer_tag, void **prvp)
|
||||
{
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
icl_soft_conn_transfer_done(struct icl_conn *ic, void *prv)
|
||||
{
|
||||
}
|
||||
|
||||
static int
|
||||
icl_soft_limits(size_t *limitp)
|
||||
{
|
||||
|
@ -112,4 +112,34 @@ icl_conn_connected(struct icl_conn *ic)
|
||||
return (ICL_CONN_CONNECTED(ic));
|
||||
}
|
||||
|
||||
static inline int
|
||||
icl_conn_task_setup(struct icl_conn *ic, struct ccb_scsiio *csio,
|
||||
uint32_t *task_tagp, void **prvp)
|
||||
{
|
||||
|
||||
return (ICL_CONN_TASK_SETUP(ic, csio, task_tagp, prvp));
|
||||
}
|
||||
|
||||
static inline void
|
||||
icl_conn_task_done(struct icl_conn *ic, void *prv)
|
||||
{
|
||||
|
||||
ICL_CONN_TASK_DONE(ic, prv);
|
||||
}
|
||||
|
||||
static inline int
|
||||
icl_conn_transfer_setup(struct icl_conn *ic, union ctl_io *io,
|
||||
uint32_t *transfer_tagp, void **prvp)
|
||||
{
|
||||
|
||||
return (ICL_CONN_TRANSFER_SETUP(ic, io, transfer_tagp, prvp));
|
||||
}
|
||||
|
||||
static inline void
|
||||
icl_conn_transfer_done(struct icl_conn *ic, void *prv)
|
||||
{
|
||||
|
||||
ICL_CONN_TRANSFER_DONE(ic, prv);
|
||||
}
|
||||
|
||||
#endif /* !ICL_WRAPPERS_H */
|
||||
|
@ -169,7 +169,7 @@ static void iscsi_poll(struct cam_sim *sim);
|
||||
static struct iscsi_outstanding *iscsi_outstanding_find(struct iscsi_session *is,
|
||||
uint32_t initiator_task_tag);
|
||||
static struct iscsi_outstanding *iscsi_outstanding_add(struct iscsi_session *is,
|
||||
uint32_t initiator_task_tag, union ccb *ccb);
|
||||
union ccb *ccb, uint32_t *initiator_task_tagp);
|
||||
static void iscsi_outstanding_remove(struct iscsi_session *is,
|
||||
struct iscsi_outstanding *io);
|
||||
|
||||
@ -1993,21 +1993,33 @@ iscsi_outstanding_find_ccb(struct iscsi_session *is, union ccb *ccb)
|
||||
|
||||
static struct iscsi_outstanding *
|
||||
iscsi_outstanding_add(struct iscsi_session *is,
|
||||
uint32_t initiator_task_tag, union ccb *ccb)
|
||||
union ccb *ccb, uint32_t *initiator_task_tagp)
|
||||
{
|
||||
struct iscsi_outstanding *io;
|
||||
int error;
|
||||
|
||||
ISCSI_SESSION_LOCK_ASSERT(is);
|
||||
|
||||
KASSERT(iscsi_outstanding_find(is, initiator_task_tag) == NULL,
|
||||
("initiator_task_tag 0x%x already added", initiator_task_tag));
|
||||
|
||||
io = uma_zalloc(iscsi_outstanding_zone, M_NOWAIT | M_ZERO);
|
||||
if (io == NULL) {
|
||||
ISCSI_SESSION_WARN(is, "failed to allocate %zd bytes", sizeof(*io));
|
||||
ISCSI_SESSION_WARN(is, "failed to allocate %zd bytes",
|
||||
sizeof(*io));
|
||||
return (NULL);
|
||||
}
|
||||
io->io_initiator_task_tag = initiator_task_tag;
|
||||
|
||||
error = icl_conn_task_setup(is->is_conn, &ccb->csio,
|
||||
initiator_task_tagp, &io->io_icl_prv);
|
||||
if (error != 0) {
|
||||
ISCSI_SESSION_WARN(is,
|
||||
"icl_conn_task_setup() failed with error %d", error);
|
||||
uma_zfree(iscsi_outstanding_zone, io);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
KASSERT(iscsi_outstanding_find(is, *initiator_task_tagp) == NULL,
|
||||
("initiator_task_tag 0x%x already added", *initiator_task_tagp));
|
||||
|
||||
io->io_initiator_task_tag = *initiator_task_tagp;
|
||||
io->io_ccb = ccb;
|
||||
TAILQ_INSERT_TAIL(&is->is_outstanding, io, io_next);
|
||||
return (io);
|
||||
@ -2019,6 +2031,7 @@ iscsi_outstanding_remove(struct iscsi_session *is, struct iscsi_outstanding *io)
|
||||
|
||||
ISCSI_SESSION_LOCK_ASSERT(is);
|
||||
|
||||
icl_conn_task_done(is->is_conn, io->io_icl_prv);
|
||||
TAILQ_REMOVE(&is->is_outstanding, io, io_next);
|
||||
uma_zfree(iscsi_outstanding_zone, io);
|
||||
}
|
||||
@ -2030,6 +2043,7 @@ iscsi_action_abort(struct iscsi_session *is, union ccb *ccb)
|
||||
struct iscsi_bhs_task_management_request *bhstmr;
|
||||
struct ccb_abort *cab = &ccb->cab;
|
||||
struct iscsi_outstanding *io, *aio;
|
||||
uint32_t initiator_task_tag;
|
||||
|
||||
ISCSI_SESSION_LOCK_ASSERT(is);
|
||||
|
||||
@ -2057,16 +2071,9 @@ iscsi_action_abort(struct iscsi_session *is, union ccb *ccb)
|
||||
return;
|
||||
}
|
||||
|
||||
bhstmr = (struct iscsi_bhs_task_management_request *)request->ip_bhs;
|
||||
bhstmr->bhstmr_opcode = ISCSI_BHS_OPCODE_TASK_REQUEST;
|
||||
bhstmr->bhstmr_function = 0x80 | BHSTMR_FUNCTION_ABORT_TASK;
|
||||
initiator_task_tag = is->is_initiator_task_tag++;
|
||||
|
||||
bhstmr->bhstmr_lun = htobe64(CAM_EXTLUN_BYTE_SWIZZLE(ccb->ccb_h.target_lun));
|
||||
bhstmr->bhstmr_initiator_task_tag = is->is_initiator_task_tag;
|
||||
is->is_initiator_task_tag++;
|
||||
bhstmr->bhstmr_referenced_task_tag = aio->io_initiator_task_tag;
|
||||
|
||||
io = iscsi_outstanding_add(is, bhstmr->bhstmr_initiator_task_tag, NULL);
|
||||
io = iscsi_outstanding_add(is, NULL, &initiator_task_tag);
|
||||
if (io == NULL) {
|
||||
icl_pdu_free(request);
|
||||
ccb->ccb_h.status = CAM_RESRC_UNAVAIL;
|
||||
@ -2074,6 +2081,14 @@ iscsi_action_abort(struct iscsi_session *is, union ccb *ccb)
|
||||
return;
|
||||
}
|
||||
io->io_datasn = aio->io_initiator_task_tag;
|
||||
|
||||
bhstmr = (struct iscsi_bhs_task_management_request *)request->ip_bhs;
|
||||
bhstmr->bhstmr_opcode = ISCSI_BHS_OPCODE_TASK_REQUEST;
|
||||
bhstmr->bhstmr_function = 0x80 | BHSTMR_FUNCTION_ABORT_TASK;
|
||||
bhstmr->bhstmr_lun = htobe64(CAM_EXTLUN_BYTE_SWIZZLE(ccb->ccb_h.target_lun));
|
||||
bhstmr->bhstmr_initiator_task_tag = initiator_task_tag;
|
||||
bhstmr->bhstmr_referenced_task_tag = aio->io_initiator_task_tag;
|
||||
|
||||
iscsi_pdu_queue_locked(request);
|
||||
}
|
||||
|
||||
@ -2085,6 +2100,7 @@ iscsi_action_scsiio(struct iscsi_session *is, union ccb *ccb)
|
||||
struct ccb_scsiio *csio;
|
||||
struct iscsi_outstanding *io;
|
||||
size_t len;
|
||||
uint32_t initiator_task_tag;
|
||||
int error;
|
||||
|
||||
ISCSI_SESSION_LOCK_ASSERT(is);
|
||||
@ -2115,6 +2131,19 @@ iscsi_action_scsiio(struct iscsi_session *is, union ccb *ccb)
|
||||
return;
|
||||
}
|
||||
|
||||
initiator_task_tag = is->is_initiator_task_tag++;
|
||||
io = iscsi_outstanding_add(is, ccb, &initiator_task_tag);
|
||||
if (io == NULL) {
|
||||
icl_pdu_free(request);
|
||||
if ((ccb->ccb_h.status & CAM_DEV_QFRZN) == 0) {
|
||||
xpt_freeze_devq(ccb->ccb_h.path, 1);
|
||||
ISCSI_SESSION_DEBUG(is, "freezing devq");
|
||||
}
|
||||
ccb->ccb_h.status = CAM_RESRC_UNAVAIL | CAM_DEV_QFRZN;
|
||||
xpt_done(ccb);
|
||||
return;
|
||||
}
|
||||
|
||||
csio = &ccb->csio;
|
||||
bhssc = (struct iscsi_bhs_scsi_command *)request->ip_bhs;
|
||||
bhssc->bhssc_opcode = ISCSI_BHS_OPCODE_SCSI_COMMAND;
|
||||
@ -2148,8 +2177,7 @@ iscsi_action_scsiio(struct iscsi_session *is, union ccb *ccb)
|
||||
bhssc->bhssc_flags |= BHSSC_FLAGS_ATTR_UNTAGGED;
|
||||
|
||||
bhssc->bhssc_lun = htobe64(CAM_EXTLUN_BYTE_SWIZZLE(ccb->ccb_h.target_lun));
|
||||
bhssc->bhssc_initiator_task_tag = is->is_initiator_task_tag;
|
||||
is->is_initiator_task_tag++;
|
||||
bhssc->bhssc_initiator_task_tag = initiator_task_tag;
|
||||
bhssc->bhssc_expected_data_transfer_length = htonl(csio->dxfer_len);
|
||||
KASSERT(csio->cdb_len <= sizeof(bhssc->bhssc_cdb),
|
||||
("unsupported CDB size %zd", (size_t)csio->cdb_len));
|
||||
@ -2159,18 +2187,6 @@ iscsi_action_scsiio(struct iscsi_session *is, union ccb *ccb)
|
||||
else
|
||||
memcpy(&bhssc->bhssc_cdb, csio->cdb_io.cdb_bytes, csio->cdb_len);
|
||||
|
||||
io = iscsi_outstanding_add(is, bhssc->bhssc_initiator_task_tag, ccb);
|
||||
if (io == NULL) {
|
||||
icl_pdu_free(request);
|
||||
if ((ccb->ccb_h.status & CAM_DEV_QFRZN) == 0) {
|
||||
xpt_freeze_devq(ccb->ccb_h.path, 1);
|
||||
ISCSI_SESSION_DEBUG(is, "freezing devq");
|
||||
}
|
||||
ccb->ccb_h.status = CAM_RESRC_UNAVAIL | CAM_DEV_QFRZN;
|
||||
xpt_done(ccb);
|
||||
return;
|
||||
}
|
||||
|
||||
if (is->is_immediate_data &&
|
||||
(csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT) {
|
||||
len = csio->dxfer_len;
|
||||
|
@ -45,6 +45,7 @@ struct iscsi_outstanding {
|
||||
size_t io_received;
|
||||
uint32_t io_initiator_task_tag;
|
||||
uint32_t io_datasn;
|
||||
void *io_icl_prv;
|
||||
};
|
||||
|
||||
struct iscsi_session {
|
||||
|
Loading…
x
Reference in New Issue
Block a user