/* * iser_internal_conn_destroy() * Tear down iSER-specific connection resources. This is used below * in iser_conn_destroy(), but also from the CM code when we may have * some of the connection established, but not fully connected. */ void iser_internal_conn_destroy(iser_conn_t *ic) { mutex_enter(&ic->ic_lock); iser_channel_free(ic->ic_chan); if ((ic->ic_type == ISER_CONN_TYPE_TGT) && (ic->ic_stage == ISER_CONN_STAGE_ALLOCATED)) { /* * This is a target connection that has yet to be * established. Free our reference on the target * service handle. */ iser_tgt_svc_rele(ic->ic_idms->is_iser_svc); } cv_destroy(&ic->ic_stage_cv); mutex_exit(&ic->ic_lock); mutex_destroy(&ic->ic_lock); kmem_free(ic, sizeof (iser_conn_t)); }
static ibt_cm_status_t iser_handle_cm_conn_est(ibt_cm_event_t *evp) { iser_chan_t *iser_chan; iser_conn_t *iser_conn; iser_svc_t *iser_svc; idm_status_t status; idm_conn_t *ic; iser_chan = (iser_chan_t *)ibt_get_chan_private(evp->cm_channel); /* * An ibt_open_rc_channel() comes in as a IBT_CM_EVENT_REQ_RCV on the * iSER-IB target, upon which the target sends a Response, accepting * the request. This comes in as a IBT_CM_EVENT_REP_RCV on the iSER-IB * initiator, which then sends an RTU. Upon getting this RTU from the * iSER-IB initiator, the IBT_CM_EVENT_CONN_EST event is generated on * the target. Then subsequently an IBT_CM_EVENT_CONN_EST event is * generated on the initiator. * * Our new connection has been established on the target. If we are * receiving this event on the target side, the iser_channel can be * used as it is already populated. On the target side, an IDM * connection is then allocated and the IDM layer is notified. * If we are on the initiator we needn't do anything, since we * already have the IDM linkage in place for this connection. */ if (iser_chan->ic_conn->ic_type == ISER_CONN_TYPE_TGT) { iser_conn = iser_chan->ic_conn; iser_svc = (iser_svc_t *)iser_conn->ic_idms->is_iser_svc; mutex_enter(&iser_conn->ic_lock); status = idm_svc_conn_create(iser_conn->ic_idms, IDM_TRANSPORT_TYPE_ISER, &ic); if (status != IDM_STATUS_SUCCESS) { /* * No IDM rsrcs or something equally Bad. * Return non-SUCCESS to IBCM. He'll give * us a CONN_CLOSED, which we'll handle * below. */ ISER_LOG(CE_NOTE, "iser_handle_cm_conn_est: " "idm_svc_conn_create_failed"); mutex_exit(&iser_conn->ic_lock); return (IBT_CM_NO_RESOURCE); } /* We no longer need the hold on the iSER service handle */ iser_tgt_svc_rele(iser_svc); /* Hold a reference on the IDM connection handle */ idm_conn_hold(ic); /* Set the transport ops and conn on the idm_conn handle */ ic->ic_transport_ops = &iser_transport_ops; ic->ic_transport_private = (void *)iser_conn; ic->ic_transport_hdrlen = ISER_HEADER_LENGTH; iser_conn->ic_idmc = ic; /* * Set the local and remote addresses in the idm conn handle. */ iser_ib_conv_ibtaddr2sockaddr(&ic->ic_laddr, &iser_conn->ic_chan->ic_localip, iser_chan->ic_lport); iser_ib_conv_ibtaddr2sockaddr(&ic->ic_raddr, &iser_conn->ic_chan->ic_remoteip, iser_chan->ic_rport); /* * Kick the state machine. At CS_S3_XPT_UP the state machine * will notify the client (target) about the new connection. */ idm_conn_event(ic, CE_CONNECT_ACCEPT, NULL); iser_conn->ic_stage = ISER_CONN_STAGE_IC_CONNECTED; mutex_exit(&iser_conn->ic_lock); /* * Post work requests on the receive queue */ iser_ib_post_recv(iser_chan->ic_chanhdl); } return (IBT_CM_ACCEPT); }