19162SPeter.Dunlap@Sun.COM /*
29162SPeter.Dunlap@Sun.COM * CDDL HEADER START
39162SPeter.Dunlap@Sun.COM *
49162SPeter.Dunlap@Sun.COM * The contents of this file are subject to the terms of the
59162SPeter.Dunlap@Sun.COM * Common Development and Distribution License (the "License").
69162SPeter.Dunlap@Sun.COM * You may not use this file except in compliance with the License.
79162SPeter.Dunlap@Sun.COM *
89162SPeter.Dunlap@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
99162SPeter.Dunlap@Sun.COM * or http://www.opensolaris.org/os/licensing.
109162SPeter.Dunlap@Sun.COM * See the License for the specific language governing permissions
119162SPeter.Dunlap@Sun.COM * and limitations under the License.
129162SPeter.Dunlap@Sun.COM *
139162SPeter.Dunlap@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each
149162SPeter.Dunlap@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
159162SPeter.Dunlap@Sun.COM * If applicable, add the following below this CDDL HEADER, with the
169162SPeter.Dunlap@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying
179162SPeter.Dunlap@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner]
189162SPeter.Dunlap@Sun.COM *
199162SPeter.Dunlap@Sun.COM * CDDL HEADER END
209162SPeter.Dunlap@Sun.COM */
219162SPeter.Dunlap@Sun.COM /*
229162SPeter.Dunlap@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
239162SPeter.Dunlap@Sun.COM * Use is subject to license terms.
249162SPeter.Dunlap@Sun.COM */
259162SPeter.Dunlap@Sun.COM
269162SPeter.Dunlap@Sun.COM #include <sys/types.h>
279162SPeter.Dunlap@Sun.COM #include <sys/ddi.h>
289162SPeter.Dunlap@Sun.COM #include <sys/types.h>
299162SPeter.Dunlap@Sun.COM #include <sys/socket.h>
309162SPeter.Dunlap@Sun.COM #include <netinet/in.h>
319162SPeter.Dunlap@Sun.COM #include <sys/sunddi.h>
329162SPeter.Dunlap@Sun.COM #include <sys/ib/ibtl/ibti.h>
339162SPeter.Dunlap@Sun.COM #include <sys/ib/ibtl/ibtl_types.h>
349162SPeter.Dunlap@Sun.COM
359162SPeter.Dunlap@Sun.COM #include <sys/ib/clients/iser/iser.h>
369162SPeter.Dunlap@Sun.COM
379162SPeter.Dunlap@Sun.COM extern idm_transport_ops_t iser_transport_ops;
389162SPeter.Dunlap@Sun.COM
399162SPeter.Dunlap@Sun.COM /*
409162SPeter.Dunlap@Sun.COM * iser_cm.c
419162SPeter.Dunlap@Sun.COM * InfiniBand Communication Manager routines for iSER
429162SPeter.Dunlap@Sun.COM */
439162SPeter.Dunlap@Sun.COM static ibt_cm_status_t iser_ib_handle_cm_req(idm_svc_t *svc_hdl,
449162SPeter.Dunlap@Sun.COM ibt_cm_event_t *evp, ibt_cm_return_args_t *rargsp, void *rcmp,
459162SPeter.Dunlap@Sun.COM ibt_priv_data_len_t rcmp_len);
469162SPeter.Dunlap@Sun.COM
479162SPeter.Dunlap@Sun.COM static ibt_cm_status_t iser_ib_handle_cm_rep(iser_state_t *statep,
489162SPeter.Dunlap@Sun.COM ibt_cm_event_t *evp, ibt_cm_return_args_t *rargsp, void *rcmp,
499162SPeter.Dunlap@Sun.COM ibt_priv_data_len_t rcmp_len);
509162SPeter.Dunlap@Sun.COM
519162SPeter.Dunlap@Sun.COM static ibt_cm_status_t iser_handle_cm_conn_est(ibt_cm_event_t *evp);
529162SPeter.Dunlap@Sun.COM static ibt_cm_status_t iser_handle_cm_conn_closed(ibt_cm_event_t *evp);
539162SPeter.Dunlap@Sun.COM static ibt_cm_status_t iser_handle_cm_event_failure(ibt_cm_event_t *evp);
549162SPeter.Dunlap@Sun.COM
559162SPeter.Dunlap@Sun.COM /*
569162SPeter.Dunlap@Sun.COM * iser_ib_cm_handler()
579162SPeter.Dunlap@Sun.COM */
589162SPeter.Dunlap@Sun.COM ibt_cm_status_t
iser_ib_cm_handler(void * cm_private,ibt_cm_event_t * eventp,ibt_cm_return_args_t * ret_args,void * ret_priv_data,ibt_priv_data_len_t ret_len_max)599162SPeter.Dunlap@Sun.COM iser_ib_cm_handler(void *cm_private, ibt_cm_event_t *eventp,
609162SPeter.Dunlap@Sun.COM ibt_cm_return_args_t *ret_args, void *ret_priv_data,
619162SPeter.Dunlap@Sun.COM ibt_priv_data_len_t ret_len_max)
629162SPeter.Dunlap@Sun.COM {
639162SPeter.Dunlap@Sun.COM ibt_cm_status_t ret = IBT_CM_REJECT;
649162SPeter.Dunlap@Sun.COM
659162SPeter.Dunlap@Sun.COM switch (eventp->cm_type) {
669162SPeter.Dunlap@Sun.COM
679162SPeter.Dunlap@Sun.COM case IBT_CM_EVENT_REQ_RCV:
689162SPeter.Dunlap@Sun.COM ISER_LOG(CE_NOTE, "iser_ib_cm_handler: IBT_CM_EVENT_REQ_RCV");
699162SPeter.Dunlap@Sun.COM ret = iser_ib_handle_cm_req((idm_svc_t *)cm_private, eventp,
709162SPeter.Dunlap@Sun.COM ret_args, ret_priv_data, ret_len_max);
719162SPeter.Dunlap@Sun.COM break;
729162SPeter.Dunlap@Sun.COM
739162SPeter.Dunlap@Sun.COM case IBT_CM_EVENT_REP_RCV:
749162SPeter.Dunlap@Sun.COM ISER_LOG(CE_NOTE, "iser_ib_cm_handler: IBT_CM_EVENT_REP_RCV");
759162SPeter.Dunlap@Sun.COM ret = iser_ib_handle_cm_rep((iser_state_t *)cm_private,
769162SPeter.Dunlap@Sun.COM eventp, ret_args, ret_priv_data, ret_len_max);
779162SPeter.Dunlap@Sun.COM break;
789162SPeter.Dunlap@Sun.COM
799162SPeter.Dunlap@Sun.COM case IBT_CM_EVENT_CONN_EST:
809162SPeter.Dunlap@Sun.COM ISER_LOG(CE_NOTE, "iser_ib_cm_handler: IBT_CM_EVENT_CONN_EST");
819162SPeter.Dunlap@Sun.COM ret = iser_handle_cm_conn_est(eventp);
829162SPeter.Dunlap@Sun.COM break;
839162SPeter.Dunlap@Sun.COM
849162SPeter.Dunlap@Sun.COM case IBT_CM_EVENT_CONN_CLOSED:
859162SPeter.Dunlap@Sun.COM ISER_LOG(CE_NOTE, "iser_ib_cm_handler: "
869162SPeter.Dunlap@Sun.COM "IBT_CM_EVENT_CONN_CLOSED");
879162SPeter.Dunlap@Sun.COM ret = iser_handle_cm_conn_closed(eventp);
889162SPeter.Dunlap@Sun.COM break;
899162SPeter.Dunlap@Sun.COM
909162SPeter.Dunlap@Sun.COM case IBT_CM_EVENT_FAILURE:
919162SPeter.Dunlap@Sun.COM ISER_LOG(CE_NOTE, "iser_ib_cm_handler: Event failure");
929162SPeter.Dunlap@Sun.COM ret = iser_handle_cm_event_failure(eventp);
939162SPeter.Dunlap@Sun.COM break;
949162SPeter.Dunlap@Sun.COM
959162SPeter.Dunlap@Sun.COM case IBT_CM_EVENT_MRA_RCV:
969162SPeter.Dunlap@Sun.COM /* Not supported */
979162SPeter.Dunlap@Sun.COM ISER_LOG(CE_NOTE, "iser_ib_cm_handler: MRA message received");
989162SPeter.Dunlap@Sun.COM break;
999162SPeter.Dunlap@Sun.COM
1009162SPeter.Dunlap@Sun.COM case IBT_CM_EVENT_LAP_RCV:
1019162SPeter.Dunlap@Sun.COM /* Not supported */
1029162SPeter.Dunlap@Sun.COM ISER_LOG(CE_NOTE, "iser_ib_cm_handler: LAP message received");
1039162SPeter.Dunlap@Sun.COM break;
1049162SPeter.Dunlap@Sun.COM
1059162SPeter.Dunlap@Sun.COM case IBT_CM_EVENT_APR_RCV:
1069162SPeter.Dunlap@Sun.COM /* Not supported */
1079162SPeter.Dunlap@Sun.COM ISER_LOG(CE_NOTE, "iser_ib_cm_handler: APR message received");
1089162SPeter.Dunlap@Sun.COM break;
1099162SPeter.Dunlap@Sun.COM
1109162SPeter.Dunlap@Sun.COM default:
1119162SPeter.Dunlap@Sun.COM ISER_LOG(CE_NOTE, "iser_ib_cm_handler: unknown event (0x%x)",
1129162SPeter.Dunlap@Sun.COM eventp->cm_type);
1139162SPeter.Dunlap@Sun.COM break;
1149162SPeter.Dunlap@Sun.COM }
1159162SPeter.Dunlap@Sun.COM
1169162SPeter.Dunlap@Sun.COM return (ret);
1179162SPeter.Dunlap@Sun.COM }
1189162SPeter.Dunlap@Sun.COM
1199162SPeter.Dunlap@Sun.COM /* ARGSUSED */
1209162SPeter.Dunlap@Sun.COM static ibt_cm_status_t
iser_ib_handle_cm_req(idm_svc_t * svc_hdl,ibt_cm_event_t * evp,ibt_cm_return_args_t * rargsp,void * rcmp,ibt_priv_data_len_t rcmp_len)1219162SPeter.Dunlap@Sun.COM iser_ib_handle_cm_req(idm_svc_t *svc_hdl, ibt_cm_event_t *evp,
1229162SPeter.Dunlap@Sun.COM ibt_cm_return_args_t *rargsp, void *rcmp, ibt_priv_data_len_t rcmp_len)
1239162SPeter.Dunlap@Sun.COM {
1249162SPeter.Dunlap@Sun.COM
1259162SPeter.Dunlap@Sun.COM iser_private_data_t iser_priv_data;
1269162SPeter.Dunlap@Sun.COM ibt_ip_cm_info_t ipcm_info;
1279162SPeter.Dunlap@Sun.COM iser_chan_t *chan;
1289162SPeter.Dunlap@Sun.COM iser_conn_t *iser_conn;
1299162SPeter.Dunlap@Sun.COM int status;
1309162SPeter.Dunlap@Sun.COM
1319162SPeter.Dunlap@Sun.COM /*
1329162SPeter.Dunlap@Sun.COM * CM private data brings IP information
1339162SPeter.Dunlap@Sun.COM * Private data received is a stream of bytes and may not be properly
1349162SPeter.Dunlap@Sun.COM * aligned. So, bcopy the data onto the stack before accessing it.
1359162SPeter.Dunlap@Sun.COM */
1369162SPeter.Dunlap@Sun.COM bcopy((uint8_t *)evp->cm_priv_data, &iser_priv_data,
1379162SPeter.Dunlap@Sun.COM sizeof (iser_private_data_t));
1389162SPeter.Dunlap@Sun.COM
1399162SPeter.Dunlap@Sun.COM /* extract the CM IP info */
1409162SPeter.Dunlap@Sun.COM status = ibt_get_ip_data(evp->cm_priv_data_len, evp->cm_priv_data,
1419162SPeter.Dunlap@Sun.COM &ipcm_info);
1429162SPeter.Dunlap@Sun.COM if (status != IBT_SUCCESS) {
1439162SPeter.Dunlap@Sun.COM return (IBT_CM_REJECT);
1449162SPeter.Dunlap@Sun.COM }
1459162SPeter.Dunlap@Sun.COM
1469162SPeter.Dunlap@Sun.COM ISER_LOG(CE_NOTE, "iser_ib_handle_cm_req: ipcm_info (0x%p): src IP "
1479162SPeter.Dunlap@Sun.COM "(0x%08x) src port (0x%04x) dst IP: (0x%08x)", (void *)&ipcm_info,
1489162SPeter.Dunlap@Sun.COM ipcm_info.src_addr.un.ip4addr, ipcm_info.src_port,
1499162SPeter.Dunlap@Sun.COM ipcm_info.dst_addr.un.ip4addr);
1509162SPeter.Dunlap@Sun.COM
1519162SPeter.Dunlap@Sun.COM /* Allocate a channel to establish the new connection */
152*10322SPriya.Krishnan@Sun.COM chan = iser_ib_alloc_channel_nopathlookup(
153*10322SPriya.Krishnan@Sun.COM evp->cm_event.req.req_hca_guid,
154*10322SPriya.Krishnan@Sun.COM evp->cm_event.req.req_prim_hca_port);
1559162SPeter.Dunlap@Sun.COM if (chan == NULL) {
156*10322SPriya.Krishnan@Sun.COM ISER_LOG(CE_NOTE, "iser_ib_handle_cm_req: failed to allocate "
157*10322SPriya.Krishnan@Sun.COM "a channel from src IP (0x%08x) src port (0x%04x) "
158*10322SPriya.Krishnan@Sun.COM "to dst IP: (0x%08x) on hca(%llx %d)",
159*10322SPriya.Krishnan@Sun.COM ipcm_info.src_addr.un.ip4addr, ipcm_info.src_port,
160*10322SPriya.Krishnan@Sun.COM ipcm_info.dst_addr.un.ip4addr,
161*10322SPriya.Krishnan@Sun.COM (longlong_t)evp->cm_event.req.req_hca_guid,
162*10322SPriya.Krishnan@Sun.COM evp->cm_event.req.req_prim_hca_port);
1639162SPeter.Dunlap@Sun.COM return (IBT_CM_REJECT);
1649162SPeter.Dunlap@Sun.COM }
1659162SPeter.Dunlap@Sun.COM
166*10322SPriya.Krishnan@Sun.COM /* Set the local and remote ip */
167*10322SPriya.Krishnan@Sun.COM chan->ic_localip = ipcm_info.dst_addr;
168*10322SPriya.Krishnan@Sun.COM chan->ic_remoteip = ipcm_info.src_addr;
169*10322SPriya.Krishnan@Sun.COM
1709162SPeter.Dunlap@Sun.COM /* Set the local and remote port numbers on the channel handle */
1719162SPeter.Dunlap@Sun.COM chan->ic_lport = svc_hdl->is_svc_req.sr_port;
1729162SPeter.Dunlap@Sun.COM chan->ic_rport = ipcm_info.src_port;
1739162SPeter.Dunlap@Sun.COM
1749162SPeter.Dunlap@Sun.COM /* Allocate the iser_conn_t for the IDM svc binding */
1759162SPeter.Dunlap@Sun.COM iser_conn = kmem_zalloc(sizeof (iser_conn_t), KM_SLEEP);
1769162SPeter.Dunlap@Sun.COM
1779162SPeter.Dunlap@Sun.COM /* Set up the iser_conn attributes */
1789162SPeter.Dunlap@Sun.COM mutex_init(&iser_conn->ic_lock, NULL, MUTEX_DRIVER, NULL);
1799162SPeter.Dunlap@Sun.COM cv_init(&iser_conn->ic_stage_cv, NULL, CV_DEFAULT, NULL);
1809162SPeter.Dunlap@Sun.COM iser_conn->ic_type = ISER_CONN_TYPE_TGT;
1819162SPeter.Dunlap@Sun.COM iser_conn->ic_chan = chan;
1829162SPeter.Dunlap@Sun.COM iser_conn->ic_stage = ISER_CONN_STAGE_ALLOCATED;
1839162SPeter.Dunlap@Sun.COM
1849162SPeter.Dunlap@Sun.COM /* Hold a reference to the iSER service handle */
1859162SPeter.Dunlap@Sun.COM iser_tgt_svc_hold((iser_svc_t *)svc_hdl->is_iser_svc);
1869162SPeter.Dunlap@Sun.COM
1879162SPeter.Dunlap@Sun.COM iser_conn->ic_idms = svc_hdl;
1889162SPeter.Dunlap@Sun.COM
1899162SPeter.Dunlap@Sun.COM /*
1909162SPeter.Dunlap@Sun.COM * Now set a pointer to the iser_conn in the iser_chan for
1919162SPeter.Dunlap@Sun.COM * access during CM event handling
1929162SPeter.Dunlap@Sun.COM */
1939162SPeter.Dunlap@Sun.COM chan->ic_conn = iser_conn;
1949162SPeter.Dunlap@Sun.COM
1959162SPeter.Dunlap@Sun.COM rargsp->cm_ret.rep.cm_channel = chan->ic_chanhdl;
1969162SPeter.Dunlap@Sun.COM
1979162SPeter.Dunlap@Sun.COM return (IBT_CM_ACCEPT);
1989162SPeter.Dunlap@Sun.COM }
1999162SPeter.Dunlap@Sun.COM
2009162SPeter.Dunlap@Sun.COM /* ARGSUSED */
2019162SPeter.Dunlap@Sun.COM static ibt_cm_status_t
iser_ib_handle_cm_rep(iser_state_t * statep,ibt_cm_event_t * evp,ibt_cm_return_args_t * rargsp,void * rcmp,ibt_priv_data_len_t rcmp_len)2029162SPeter.Dunlap@Sun.COM iser_ib_handle_cm_rep(iser_state_t *statep, ibt_cm_event_t *evp,
2039162SPeter.Dunlap@Sun.COM ibt_cm_return_args_t *rargsp, void *rcmp, ibt_priv_data_len_t rcmp_len)
2049162SPeter.Dunlap@Sun.COM {
2059162SPeter.Dunlap@Sun.COM /* pre-post work requests into the receive queue */
2069162SPeter.Dunlap@Sun.COM iser_ib_post_recv(evp->cm_channel);
2079162SPeter.Dunlap@Sun.COM
2089162SPeter.Dunlap@Sun.COM /* It looks like the RTU need not be send specifically */
2099162SPeter.Dunlap@Sun.COM return (IBT_CM_ACCEPT);
2109162SPeter.Dunlap@Sun.COM }
2119162SPeter.Dunlap@Sun.COM
2129162SPeter.Dunlap@Sun.COM static ibt_cm_status_t
iser_handle_cm_conn_est(ibt_cm_event_t * evp)2139162SPeter.Dunlap@Sun.COM iser_handle_cm_conn_est(ibt_cm_event_t *evp)
2149162SPeter.Dunlap@Sun.COM {
2159162SPeter.Dunlap@Sun.COM iser_chan_t *iser_chan;
2169162SPeter.Dunlap@Sun.COM iser_conn_t *iser_conn;
2179162SPeter.Dunlap@Sun.COM iser_svc_t *iser_svc;
2189162SPeter.Dunlap@Sun.COM idm_status_t status;
2199162SPeter.Dunlap@Sun.COM idm_conn_t *ic;
2209162SPeter.Dunlap@Sun.COM
2219162SPeter.Dunlap@Sun.COM iser_chan = (iser_chan_t *)ibt_get_chan_private(evp->cm_channel);
2229162SPeter.Dunlap@Sun.COM
2239162SPeter.Dunlap@Sun.COM /*
2249162SPeter.Dunlap@Sun.COM * An ibt_open_rc_channel() comes in as a IBT_CM_EVENT_REQ_RCV on the
2259162SPeter.Dunlap@Sun.COM * iSER-IB target, upon which the target sends a Response, accepting
2269162SPeter.Dunlap@Sun.COM * the request. This comes in as a IBT_CM_EVENT_REP_RCV on the iSER-IB
2279162SPeter.Dunlap@Sun.COM * initiator, which then sends an RTU. Upon getting this RTU from the
2289162SPeter.Dunlap@Sun.COM * iSER-IB initiator, the IBT_CM_EVENT_CONN_EST event is generated on
2299162SPeter.Dunlap@Sun.COM * the target. Then subsequently an IBT_CM_EVENT_CONN_EST event is
2309162SPeter.Dunlap@Sun.COM * generated on the initiator.
2319162SPeter.Dunlap@Sun.COM *
2329162SPeter.Dunlap@Sun.COM * Our new connection has been established on the target. If we are
2339162SPeter.Dunlap@Sun.COM * receiving this event on the target side, the iser_channel can be
2349162SPeter.Dunlap@Sun.COM * used as it is already populated. On the target side, an IDM
2359162SPeter.Dunlap@Sun.COM * connection is then allocated and the IDM layer is notified.
2369162SPeter.Dunlap@Sun.COM * If we are on the initiator we needn't do anything, since we
2379162SPeter.Dunlap@Sun.COM * already have the IDM linkage in place for this connection.
2389162SPeter.Dunlap@Sun.COM */
2399162SPeter.Dunlap@Sun.COM if (iser_chan->ic_conn->ic_type == ISER_CONN_TYPE_TGT) {
2409162SPeter.Dunlap@Sun.COM
2419162SPeter.Dunlap@Sun.COM iser_conn = iser_chan->ic_conn;
2429162SPeter.Dunlap@Sun.COM iser_svc = (iser_svc_t *)iser_conn->ic_idms->is_iser_svc;
2439162SPeter.Dunlap@Sun.COM
2449162SPeter.Dunlap@Sun.COM mutex_enter(&iser_conn->ic_lock);
2459162SPeter.Dunlap@Sun.COM
2469162SPeter.Dunlap@Sun.COM status = idm_svc_conn_create(iser_conn->ic_idms,
2479162SPeter.Dunlap@Sun.COM IDM_TRANSPORT_TYPE_ISER, &ic);
2489162SPeter.Dunlap@Sun.COM if (status != IDM_STATUS_SUCCESS) {
2499162SPeter.Dunlap@Sun.COM /*
2509162SPeter.Dunlap@Sun.COM * No IDM rsrcs or something equally Bad.
2519162SPeter.Dunlap@Sun.COM * Return non-SUCCESS to IBCM. He'll give
2529162SPeter.Dunlap@Sun.COM * us a CONN_CLOSED, which we'll handle
2539162SPeter.Dunlap@Sun.COM * below.
2549162SPeter.Dunlap@Sun.COM */
2559162SPeter.Dunlap@Sun.COM ISER_LOG(CE_NOTE, "iser_handle_cm_conn_est: "
2569162SPeter.Dunlap@Sun.COM "idm_svc_conn_create_failed");
2579162SPeter.Dunlap@Sun.COM mutex_exit(&iser_conn->ic_lock);
2589162SPeter.Dunlap@Sun.COM return (IBT_CM_NO_RESOURCE);
2599162SPeter.Dunlap@Sun.COM }
2609162SPeter.Dunlap@Sun.COM
2619162SPeter.Dunlap@Sun.COM /* We no longer need the hold on the iSER service handle */
2629162SPeter.Dunlap@Sun.COM iser_tgt_svc_rele(iser_svc);
2639162SPeter.Dunlap@Sun.COM
2649162SPeter.Dunlap@Sun.COM /* Hold a reference on the IDM connection handle */
2659162SPeter.Dunlap@Sun.COM idm_conn_hold(ic);
2669162SPeter.Dunlap@Sun.COM
2679162SPeter.Dunlap@Sun.COM /* Set the transport ops and conn on the idm_conn handle */
2689162SPeter.Dunlap@Sun.COM ic->ic_transport_ops = &iser_transport_ops;
2699162SPeter.Dunlap@Sun.COM ic->ic_transport_private = (void *)iser_conn;
2709162SPeter.Dunlap@Sun.COM ic->ic_transport_hdrlen = ISER_HEADER_LENGTH;
2719162SPeter.Dunlap@Sun.COM iser_conn->ic_idmc = ic;
2729162SPeter.Dunlap@Sun.COM
2739162SPeter.Dunlap@Sun.COM /*
2749162SPeter.Dunlap@Sun.COM * Set the local and remote addresses in the idm conn handle.
2759162SPeter.Dunlap@Sun.COM */
2769162SPeter.Dunlap@Sun.COM iser_ib_conv_ibtaddr2sockaddr(&ic->ic_laddr,
2779162SPeter.Dunlap@Sun.COM &iser_conn->ic_chan->ic_localip, iser_chan->ic_lport);
2789162SPeter.Dunlap@Sun.COM iser_ib_conv_ibtaddr2sockaddr(&ic->ic_raddr,
2799162SPeter.Dunlap@Sun.COM &iser_conn->ic_chan->ic_remoteip, iser_chan->ic_rport);
2809162SPeter.Dunlap@Sun.COM
2819162SPeter.Dunlap@Sun.COM /*
2829162SPeter.Dunlap@Sun.COM * Kick the state machine. At CS_S3_XPT_UP the state machine
2839162SPeter.Dunlap@Sun.COM * will notify the client (target) about the new connection.
2849162SPeter.Dunlap@Sun.COM */
2859162SPeter.Dunlap@Sun.COM idm_conn_event(ic, CE_CONNECT_ACCEPT, NULL);
2869162SPeter.Dunlap@Sun.COM iser_conn->ic_stage = ISER_CONN_STAGE_IC_CONNECTED;
2879162SPeter.Dunlap@Sun.COM mutex_exit(&iser_conn->ic_lock);
2889162SPeter.Dunlap@Sun.COM
2899162SPeter.Dunlap@Sun.COM /*
2909162SPeter.Dunlap@Sun.COM * Post work requests on the receive queue
2919162SPeter.Dunlap@Sun.COM */
2929162SPeter.Dunlap@Sun.COM iser_ib_post_recv(iser_chan->ic_chanhdl);
2939162SPeter.Dunlap@Sun.COM
2949162SPeter.Dunlap@Sun.COM }
2959162SPeter.Dunlap@Sun.COM
2969162SPeter.Dunlap@Sun.COM return (IBT_CM_ACCEPT);
2979162SPeter.Dunlap@Sun.COM }
2989162SPeter.Dunlap@Sun.COM
2999162SPeter.Dunlap@Sun.COM static ibt_cm_status_t
iser_handle_cm_conn_closed(ibt_cm_event_t * evp)3009162SPeter.Dunlap@Sun.COM iser_handle_cm_conn_closed(ibt_cm_event_t *evp)
3019162SPeter.Dunlap@Sun.COM {
3029162SPeter.Dunlap@Sun.COM
3039162SPeter.Dunlap@Sun.COM iser_chan_t *chan;
3049162SPeter.Dunlap@Sun.COM
3059162SPeter.Dunlap@Sun.COM chan = (iser_chan_t *)ibt_get_chan_private(evp->cm_channel);
3069162SPeter.Dunlap@Sun.COM
3079162SPeter.Dunlap@Sun.COM ISER_LOG(CE_NOTE, "iser_handle_cm_conn_closed: chan (0x%p) "
3089162SPeter.Dunlap@Sun.COM "reason (0x%x)", (void *)chan, evp->cm_event.closed);
3099162SPeter.Dunlap@Sun.COM
3109162SPeter.Dunlap@Sun.COM switch (evp->cm_event.closed) {
3119162SPeter.Dunlap@Sun.COM case IBT_CM_CLOSED_DREP_RCVD: /* we requested a disconnect */
3129162SPeter.Dunlap@Sun.COM case IBT_CM_CLOSED_ALREADY: /* duplicate close */
3139162SPeter.Dunlap@Sun.COM /* ignore these */
3149162SPeter.Dunlap@Sun.COM return (IBT_CM_ACCEPT);
3159162SPeter.Dunlap@Sun.COM
3169162SPeter.Dunlap@Sun.COM case IBT_CM_CLOSED_DREQ_RCVD: /* request to close the channel */
3179162SPeter.Dunlap@Sun.COM case IBT_CM_CLOSED_REJ_RCVD: /* reject after conn establishment */
3189162SPeter.Dunlap@Sun.COM case IBT_CM_CLOSED_DREQ_TIMEOUT: /* our close request timed out */
3199162SPeter.Dunlap@Sun.COM case IBT_CM_CLOSED_DUP: /* duplicate close request */
3209162SPeter.Dunlap@Sun.COM case IBT_CM_CLOSED_ABORT: /* aborted connection establishment */
3219162SPeter.Dunlap@Sun.COM case IBT_CM_CLOSED_STALE: /* stale / unref connection */
3229162SPeter.Dunlap@Sun.COM /* handle these depending upon our connection state */
3239162SPeter.Dunlap@Sun.COM mutex_enter(&chan->ic_conn->ic_lock);
3249162SPeter.Dunlap@Sun.COM switch (chan->ic_conn->ic_stage) {
3259162SPeter.Dunlap@Sun.COM case ISER_CONN_STAGE_UNDEFINED:
3269162SPeter.Dunlap@Sun.COM case ISER_CONN_STAGE_CLOSED:
3279162SPeter.Dunlap@Sun.COM /* do nothing, just drop the lock */
3289162SPeter.Dunlap@Sun.COM mutex_exit(&chan->ic_conn->ic_lock);
3299162SPeter.Dunlap@Sun.COM break;
3309162SPeter.Dunlap@Sun.COM
3319162SPeter.Dunlap@Sun.COM case ISER_CONN_STAGE_ALLOCATED:
3329162SPeter.Dunlap@Sun.COM /*
3339162SPeter.Dunlap@Sun.COM * We blew up or were offlined during connection
3349162SPeter.Dunlap@Sun.COM * establishment. Teardown the iSER conn and chan
3359162SPeter.Dunlap@Sun.COM * handles.
3369162SPeter.Dunlap@Sun.COM */
3379162SPeter.Dunlap@Sun.COM mutex_exit(&chan->ic_conn->ic_lock);
3389162SPeter.Dunlap@Sun.COM iser_internal_conn_destroy(chan->ic_conn);
3399162SPeter.Dunlap@Sun.COM break;
3409162SPeter.Dunlap@Sun.COM
3419162SPeter.Dunlap@Sun.COM case ISER_CONN_STAGE_IC_DISCONNECTED:
3429162SPeter.Dunlap@Sun.COM case ISER_CONN_STAGE_IC_FREED:
3439162SPeter.Dunlap@Sun.COM case ISER_CONN_STAGE_CLOSING:
3449162SPeter.Dunlap@Sun.COM /* we're down, set CLOSED */
3459162SPeter.Dunlap@Sun.COM chan->ic_conn->ic_stage = ISER_CONN_STAGE_CLOSED;
3469162SPeter.Dunlap@Sun.COM mutex_exit(&chan->ic_conn->ic_lock);
3479162SPeter.Dunlap@Sun.COM break;
3489162SPeter.Dunlap@Sun.COM
3499162SPeter.Dunlap@Sun.COM case ISER_CONN_STAGE_IC_CONNECTED:
3509162SPeter.Dunlap@Sun.COM case ISER_CONN_STAGE_HELLO_SENT:
3519162SPeter.Dunlap@Sun.COM case ISER_CONN_STAGE_HELLO_SENT_FAIL:
3529162SPeter.Dunlap@Sun.COM case ISER_CONN_STAGE_HELLO_WAIT:
3539162SPeter.Dunlap@Sun.COM case ISER_CONN_STAGE_HELLO_RCV:
3549162SPeter.Dunlap@Sun.COM case ISER_CONN_STAGE_HELLO_RCV_FAIL:
3559162SPeter.Dunlap@Sun.COM case ISER_CONN_STAGE_HELLOREPLY_SENT:
3569162SPeter.Dunlap@Sun.COM case ISER_CONN_STAGE_HELLOREPLY_SENT_FAIL:
3579162SPeter.Dunlap@Sun.COM case ISER_CONN_STAGE_HELLOREPLY_RCV:
3589162SPeter.Dunlap@Sun.COM case ISER_CONN_STAGE_HELLOREPLY_RCV_FAIL:
3599162SPeter.Dunlap@Sun.COM case ISER_CONN_STAGE_LOGGED_IN:
3609162SPeter.Dunlap@Sun.COM /* for all other stages, fail the transport */
3619162SPeter.Dunlap@Sun.COM idm_conn_event(chan->ic_conn->ic_idmc,
3629162SPeter.Dunlap@Sun.COM CE_TRANSPORT_FAIL, IDM_STATUS_FAIL);
3639162SPeter.Dunlap@Sun.COM chan->ic_conn->ic_stage = ISER_CONN_STAGE_CLOSING;
3649162SPeter.Dunlap@Sun.COM mutex_exit(&chan->ic_conn->ic_lock);
3659162SPeter.Dunlap@Sun.COM break;
3669162SPeter.Dunlap@Sun.COM
3679162SPeter.Dunlap@Sun.COM default:
3689162SPeter.Dunlap@Sun.COM mutex_exit(&chan->ic_conn->ic_lock);
3699162SPeter.Dunlap@Sun.COM ASSERT(0);
3709162SPeter.Dunlap@Sun.COM
3719162SPeter.Dunlap@Sun.COM }
3729162SPeter.Dunlap@Sun.COM
3739162SPeter.Dunlap@Sun.COM /* accept the event */
3749162SPeter.Dunlap@Sun.COM return (IBT_CM_ACCEPT);
3759162SPeter.Dunlap@Sun.COM
3769162SPeter.Dunlap@Sun.COM default:
3779162SPeter.Dunlap@Sun.COM /* unknown event */
3789162SPeter.Dunlap@Sun.COM ISER_LOG(CE_NOTE, "iser_handle_cm_conn_closed: unknown closed "
3799162SPeter.Dunlap@Sun.COM "event: (0x%x)", evp->cm_event.closed);
3809162SPeter.Dunlap@Sun.COM return (IBT_CM_REJECT);
3819162SPeter.Dunlap@Sun.COM }
3829162SPeter.Dunlap@Sun.COM }
3839162SPeter.Dunlap@Sun.COM
3849162SPeter.Dunlap@Sun.COM /*
3859162SPeter.Dunlap@Sun.COM * Handle EVENT FAILURE
3869162SPeter.Dunlap@Sun.COM */
3879162SPeter.Dunlap@Sun.COM static ibt_cm_status_t
iser_handle_cm_event_failure(ibt_cm_event_t * evp)3889162SPeter.Dunlap@Sun.COM iser_handle_cm_event_failure(ibt_cm_event_t *evp)
3899162SPeter.Dunlap@Sun.COM {
3909162SPeter.Dunlap@Sun.COM iser_chan_t *chan;
3919162SPeter.Dunlap@Sun.COM
3929162SPeter.Dunlap@Sun.COM chan = (iser_chan_t *)ibt_get_chan_private(evp->cm_channel);
3939162SPeter.Dunlap@Sun.COM
3949162SPeter.Dunlap@Sun.COM ISER_LOG(CE_NOTE, "iser_handle_cm_event_failure: chan (0x%p): "
3959162SPeter.Dunlap@Sun.COM "code: %d msg: %d reason: %d", (void *)chan,
3969162SPeter.Dunlap@Sun.COM evp->cm_event.failed.cf_code, evp->cm_event.failed.cf_msg,
3979162SPeter.Dunlap@Sun.COM evp->cm_event.failed.cf_reason);
3989162SPeter.Dunlap@Sun.COM
3999162SPeter.Dunlap@Sun.COM if ((evp->cm_channel == NULL) || (chan == NULL)) {
4009162SPeter.Dunlap@Sun.COM /* channel not established yet */
4019162SPeter.Dunlap@Sun.COM return (IBT_CM_ACCEPT);
4029162SPeter.Dunlap@Sun.COM }
4039162SPeter.Dunlap@Sun.COM
4049162SPeter.Dunlap@Sun.COM if ((evp->cm_event.failed.cf_code != IBT_CM_FAILURE_STALE) &&
4059162SPeter.Dunlap@Sun.COM (evp->cm_event.failed.cf_msg == IBT_CM_FAILURE_REQ)) {
4069162SPeter.Dunlap@Sun.COM /*
4079162SPeter.Dunlap@Sun.COM * This end is active, just ignore, ibt_open_rc_channel()
4089162SPeter.Dunlap@Sun.COM * caller will take care of cleanup.
4099162SPeter.Dunlap@Sun.COM */
4109162SPeter.Dunlap@Sun.COM return (IBT_CM_ACCEPT);
4119162SPeter.Dunlap@Sun.COM }
4129162SPeter.Dunlap@Sun.COM
4139162SPeter.Dunlap@Sun.COM /* handle depending upon our connection state */
4149162SPeter.Dunlap@Sun.COM mutex_enter(&chan->ic_conn->ic_lock);
4159162SPeter.Dunlap@Sun.COM switch (chan->ic_conn->ic_stage) {
4169162SPeter.Dunlap@Sun.COM case ISER_CONN_STAGE_UNDEFINED:
4179162SPeter.Dunlap@Sun.COM case ISER_CONN_STAGE_CLOSED:
4189162SPeter.Dunlap@Sun.COM /* do nothing, just drop the lock */
4199162SPeter.Dunlap@Sun.COM mutex_exit(&chan->ic_conn->ic_lock);
4209162SPeter.Dunlap@Sun.COM break;
4219162SPeter.Dunlap@Sun.COM
4229162SPeter.Dunlap@Sun.COM case ISER_CONN_STAGE_ALLOCATED:
4239162SPeter.Dunlap@Sun.COM /*
4249162SPeter.Dunlap@Sun.COM * We blew up or were offlined during connection
4259162SPeter.Dunlap@Sun.COM * establishment. Teardown the iSER conn and chan
4269162SPeter.Dunlap@Sun.COM * handles.
4279162SPeter.Dunlap@Sun.COM */
4289162SPeter.Dunlap@Sun.COM mutex_exit(&chan->ic_conn->ic_lock);
4299162SPeter.Dunlap@Sun.COM iser_internal_conn_destroy(chan->ic_conn);
4309162SPeter.Dunlap@Sun.COM break;
4319162SPeter.Dunlap@Sun.COM
4329162SPeter.Dunlap@Sun.COM case ISER_CONN_STAGE_IC_DISCONNECTED:
4339162SPeter.Dunlap@Sun.COM case ISER_CONN_STAGE_IC_FREED:
4349162SPeter.Dunlap@Sun.COM case ISER_CONN_STAGE_CLOSING:
4359162SPeter.Dunlap@Sun.COM /* update to CLOSED, then drop the lock */
4369162SPeter.Dunlap@Sun.COM chan->ic_conn->ic_stage = ISER_CONN_STAGE_CLOSED;
4379162SPeter.Dunlap@Sun.COM mutex_exit(&chan->ic_conn->ic_lock);
4389162SPeter.Dunlap@Sun.COM break;
4399162SPeter.Dunlap@Sun.COM
4409162SPeter.Dunlap@Sun.COM case ISER_CONN_STAGE_IC_CONNECTED:
4419162SPeter.Dunlap@Sun.COM case ISER_CONN_STAGE_HELLO_SENT:
4429162SPeter.Dunlap@Sun.COM case ISER_CONN_STAGE_HELLO_SENT_FAIL:
4439162SPeter.Dunlap@Sun.COM case ISER_CONN_STAGE_HELLO_WAIT:
4449162SPeter.Dunlap@Sun.COM case ISER_CONN_STAGE_HELLO_RCV:
4459162SPeter.Dunlap@Sun.COM case ISER_CONN_STAGE_HELLO_RCV_FAIL:
4469162SPeter.Dunlap@Sun.COM case ISER_CONN_STAGE_HELLOREPLY_SENT:
4479162SPeter.Dunlap@Sun.COM case ISER_CONN_STAGE_HELLOREPLY_SENT_FAIL:
4489162SPeter.Dunlap@Sun.COM case ISER_CONN_STAGE_HELLOREPLY_RCV:
4499162SPeter.Dunlap@Sun.COM case ISER_CONN_STAGE_HELLOREPLY_RCV_FAIL:
4509162SPeter.Dunlap@Sun.COM case ISER_CONN_STAGE_LOGGED_IN:
4519162SPeter.Dunlap@Sun.COM /* fail the transport and move the conn to CLOSING */
4529162SPeter.Dunlap@Sun.COM idm_conn_event(chan->ic_conn->ic_idmc, CE_TRANSPORT_FAIL,
4539162SPeter.Dunlap@Sun.COM IDM_STATUS_FAIL);
4549162SPeter.Dunlap@Sun.COM chan->ic_conn->ic_stage = ISER_CONN_STAGE_CLOSING;
4559162SPeter.Dunlap@Sun.COM mutex_exit(&chan->ic_conn->ic_lock);
4569162SPeter.Dunlap@Sun.COM break;
4579162SPeter.Dunlap@Sun.COM
4589162SPeter.Dunlap@Sun.COM default:
4599162SPeter.Dunlap@Sun.COM mutex_exit(&chan->ic_conn->ic_lock);
4609162SPeter.Dunlap@Sun.COM ASSERT(0);
4619162SPeter.Dunlap@Sun.COM }
4629162SPeter.Dunlap@Sun.COM
4639162SPeter.Dunlap@Sun.COM /* accept the event */
4649162SPeter.Dunlap@Sun.COM return (IBT_CM_ACCEPT);
4659162SPeter.Dunlap@Sun.COM }
466