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:
Edward Tomasz Napierala 2015-02-08 19:15:14 +00:00
parent a840d2f5b8
commit 7a03d007cf
7 changed files with 193 additions and 41 deletions

View File

@ -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);
}

View File

@ -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

View File

@ -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;
};

View File

@ -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)
{

View File

@ -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 */

View File

@ -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;

View File

@ -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 {