Beispiel #1
0
/*
 * 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);
}