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 /*
2212485SPeter.Gill@Sun.COM * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
239162SPeter.Dunlap@Sun.COM */
249162SPeter.Dunlap@Sun.COM
259162SPeter.Dunlap@Sun.COM #include <sys/ddi.h>
269162SPeter.Dunlap@Sun.COM #include <sys/sunddi.h>
279162SPeter.Dunlap@Sun.COM
289162SPeter.Dunlap@Sun.COM #include <sys/socket.h> /* networking stuff */
299162SPeter.Dunlap@Sun.COM #include <sys/sysmacros.h> /* offsetof */
309162SPeter.Dunlap@Sun.COM
319162SPeter.Dunlap@Sun.COM #include <sys/ib/clients/iser/iser.h>
329162SPeter.Dunlap@Sun.COM #include <sys/ib/clients/iser/iser_idm.h>
339162SPeter.Dunlap@Sun.COM
349162SPeter.Dunlap@Sun.COM /*
359162SPeter.Dunlap@Sun.COM * iSER transport routines
369162SPeter.Dunlap@Sun.COM *
379162SPeter.Dunlap@Sun.COM * All transport functions except iser_tgt_svc_create() are called through
389162SPeter.Dunlap@Sun.COM * the ops vector, iser_tgt_svc_create() is called from the async handler
399162SPeter.Dunlap@Sun.COM * inaddition to being called by the ULP
409162SPeter.Dunlap@Sun.COM */
419162SPeter.Dunlap@Sun.COM
429162SPeter.Dunlap@Sun.COM static void iser_pdu_tx(idm_conn_t *ic, idm_pdu_t *pdu);
439162SPeter.Dunlap@Sun.COM
449162SPeter.Dunlap@Sun.COM static idm_status_t iser_buf_tx_to_ini(idm_task_t *idt, idm_buf_t *idb);
459162SPeter.Dunlap@Sun.COM static idm_status_t iser_buf_rx_from_ini(idm_task_t *idt, idm_buf_t *idb);
469162SPeter.Dunlap@Sun.COM static idm_status_t iser_tgt_enable_datamover(idm_conn_t *ic);
479162SPeter.Dunlap@Sun.COM static idm_status_t iser_ini_enable_datamover(idm_conn_t *ic);
489162SPeter.Dunlap@Sun.COM static void iser_notice_key_values(struct idm_conn_s *ic,
499162SPeter.Dunlap@Sun.COM nvlist_t *negotiated_nvl);
5010261SCharles.Ting@Sun.COM static kv_status_t iser_declare_key_values(struct idm_conn_s *ic,
5110261SCharles.Ting@Sun.COM nvlist_t *config_nvl, nvlist_t *outgoing_nvl);
529162SPeter.Dunlap@Sun.COM static idm_status_t iser_free_task_rsrcs(idm_task_t *idt);
539162SPeter.Dunlap@Sun.COM static kv_status_t iser_negotiate_key_values(idm_conn_t *ic,
549162SPeter.Dunlap@Sun.COM nvlist_t *request_nvl, nvlist_t *response_nvl, nvlist_t *negotiated_nvl);
559162SPeter.Dunlap@Sun.COM static kv_status_t iser_handle_numerical(nvpair_t *nvp, uint64_t value,
569162SPeter.Dunlap@Sun.COM const idm_kv_xlate_t *ikvx, uint64_t min_value, uint64_t max_value,
579162SPeter.Dunlap@Sun.COM uint64_t iser_max_value, nvlist_t *request_nvl, nvlist_t *response_nvl,
589162SPeter.Dunlap@Sun.COM nvlist_t *negotiated_nvl);
599162SPeter.Dunlap@Sun.COM static kv_status_t iser_handle_boolean(nvpair_t *nvp, boolean_t value,
609162SPeter.Dunlap@Sun.COM const idm_kv_xlate_t *ikvx, boolean_t iser_value, nvlist_t *request_nvl,
619162SPeter.Dunlap@Sun.COM nvlist_t *response_nvl, nvlist_t *negotiated_nvl);
629162SPeter.Dunlap@Sun.COM static kv_status_t iser_handle_key(nvpair_t *nvp, const idm_kv_xlate_t *ikvx,
639162SPeter.Dunlap@Sun.COM nvlist_t *request_nvl, nvlist_t *response_nvl, nvlist_t *negotiated_nvl);
649162SPeter.Dunlap@Sun.COM static kv_status_t iser_process_request_nvlist(nvlist_t *request_nvl,
659162SPeter.Dunlap@Sun.COM nvlist_t *response_nvl, nvlist_t *negotiated_nvl);
669162SPeter.Dunlap@Sun.COM static boolean_t iser_conn_is_capable(idm_conn_req_t *ic,
679162SPeter.Dunlap@Sun.COM idm_transport_caps_t *caps);
689162SPeter.Dunlap@Sun.COM static idm_status_t iser_buf_alloc(idm_buf_t *idb, uint64_t buflen);
699162SPeter.Dunlap@Sun.COM static idm_status_t iser_buf_setup(idm_buf_t *idb);
709162SPeter.Dunlap@Sun.COM static void iser_buf_teardown(idm_buf_t *idb);
719162SPeter.Dunlap@Sun.COM static void iser_buf_free(idm_buf_t *idb);
729162SPeter.Dunlap@Sun.COM static void iser_tgt_svc_destroy(struct idm_svc_s *is);
739162SPeter.Dunlap@Sun.COM static idm_status_t iser_tgt_svc_online(struct idm_svc_s *is);
749162SPeter.Dunlap@Sun.COM static void iser_tgt_svc_offline(struct idm_svc_s *is);
759162SPeter.Dunlap@Sun.COM static idm_status_t iser_tgt_conn_connect(struct idm_conn_s *ic);
769162SPeter.Dunlap@Sun.COM static idm_status_t iser_ini_conn_create(idm_conn_req_t *cr,
779162SPeter.Dunlap@Sun.COM struct idm_conn_s *ic);
789162SPeter.Dunlap@Sun.COM static void iser_conn_destroy(struct idm_conn_s *ic);
799162SPeter.Dunlap@Sun.COM static idm_status_t iser_ini_conn_connect(struct idm_conn_s *ic);
809162SPeter.Dunlap@Sun.COM static void iser_conn_disconnect(struct idm_conn_s *ic);
819162SPeter.Dunlap@Sun.COM
829162SPeter.Dunlap@Sun.COM /*
839162SPeter.Dunlap@Sun.COM * iSER IDM transport operations
849162SPeter.Dunlap@Sun.COM */
859162SPeter.Dunlap@Sun.COM idm_transport_ops_t iser_transport_ops = {
869162SPeter.Dunlap@Sun.COM &iser_pdu_tx, /* it_tx_pdu */
879162SPeter.Dunlap@Sun.COM &iser_buf_tx_to_ini, /* it_buf_tx_to_ini */
889162SPeter.Dunlap@Sun.COM &iser_buf_rx_from_ini, /* it_buf_rx_from_ini */
899162SPeter.Dunlap@Sun.COM NULL, /* it_rx_datain */
909162SPeter.Dunlap@Sun.COM NULL, /* it_rx_rtt */
919162SPeter.Dunlap@Sun.COM NULL, /* it_rx_dataout */
929162SPeter.Dunlap@Sun.COM NULL, /* it_alloc_conn_rsrc */
939162SPeter.Dunlap@Sun.COM NULL, /* it_free_conn_rsrc */
949162SPeter.Dunlap@Sun.COM &iser_tgt_enable_datamover, /* it_tgt_enable_datamover */
959162SPeter.Dunlap@Sun.COM &iser_ini_enable_datamover, /* it_ini_enable_datamover */
969162SPeter.Dunlap@Sun.COM NULL, /* it_conn_terminate */
979162SPeter.Dunlap@Sun.COM &iser_free_task_rsrcs, /* it_free_task_rsrc */
989162SPeter.Dunlap@Sun.COM &iser_negotiate_key_values, /* it_negotiate_key_values */
999162SPeter.Dunlap@Sun.COM &iser_notice_key_values, /* it_notice_key_values */
1009162SPeter.Dunlap@Sun.COM &iser_conn_is_capable, /* it_conn_is_capable */
1019162SPeter.Dunlap@Sun.COM &iser_buf_alloc, /* it_buf_alloc */
1029162SPeter.Dunlap@Sun.COM &iser_buf_free, /* it_buf_free */
1039162SPeter.Dunlap@Sun.COM &iser_buf_setup, /* it_buf_setup */
1049162SPeter.Dunlap@Sun.COM &iser_buf_teardown, /* it_buf_teardown */
1059162SPeter.Dunlap@Sun.COM &iser_tgt_svc_create, /* it_tgt_svc_create */
1069162SPeter.Dunlap@Sun.COM &iser_tgt_svc_destroy, /* it_tgt_svc_destroy */
1079162SPeter.Dunlap@Sun.COM &iser_tgt_svc_online, /* it_tgt_svc_online */
1089162SPeter.Dunlap@Sun.COM &iser_tgt_svc_offline, /* it_tgt_svc_offline */
1099162SPeter.Dunlap@Sun.COM &iser_conn_destroy, /* it_tgt_conn_destroy */
1109162SPeter.Dunlap@Sun.COM &iser_tgt_conn_connect, /* it_tgt_conn_connect */
1119162SPeter.Dunlap@Sun.COM &iser_conn_disconnect, /* it_tgt_conn_disconnect */
1129162SPeter.Dunlap@Sun.COM &iser_ini_conn_create, /* it_ini_conn_create */
1139162SPeter.Dunlap@Sun.COM &iser_conn_destroy, /* it_ini_conn_destroy */
1149162SPeter.Dunlap@Sun.COM &iser_ini_conn_connect, /* it_ini_conn_connect */
11510261SCharles.Ting@Sun.COM &iser_conn_disconnect, /* it_ini_conn_disconnect */
11610261SCharles.Ting@Sun.COM &iser_declare_key_values /* it_declare_key_values */
1179162SPeter.Dunlap@Sun.COM };
1189162SPeter.Dunlap@Sun.COM
1199162SPeter.Dunlap@Sun.COM /*
1209162SPeter.Dunlap@Sun.COM * iSER IDM transport capabilities
1219162SPeter.Dunlap@Sun.COM */
1229162SPeter.Dunlap@Sun.COM idm_transport_caps_t iser_transport_caps = {
1239162SPeter.Dunlap@Sun.COM 0 /* flags */
1249162SPeter.Dunlap@Sun.COM };
1259162SPeter.Dunlap@Sun.COM
1269162SPeter.Dunlap@Sun.COM int
iser_idm_register()1279162SPeter.Dunlap@Sun.COM iser_idm_register()
1289162SPeter.Dunlap@Sun.COM {
1299162SPeter.Dunlap@Sun.COM idm_transport_attr_t attr;
1309162SPeter.Dunlap@Sun.COM idm_status_t status;
1319162SPeter.Dunlap@Sun.COM
1329162SPeter.Dunlap@Sun.COM attr.type = IDM_TRANSPORT_TYPE_ISER;
1339162SPeter.Dunlap@Sun.COM attr.it_ops = &iser_transport_ops;
1349162SPeter.Dunlap@Sun.COM attr.it_caps = &iser_transport_caps;
1359162SPeter.Dunlap@Sun.COM
1369162SPeter.Dunlap@Sun.COM status = idm_transport_register(&attr);
1379162SPeter.Dunlap@Sun.COM if (status != IDM_STATUS_SUCCESS) {
1389162SPeter.Dunlap@Sun.COM ISER_LOG(CE_WARN, "Failed to register iSER transport with IDM");
1399162SPeter.Dunlap@Sun.COM return (DDI_FAILURE);
1409162SPeter.Dunlap@Sun.COM }
1419162SPeter.Dunlap@Sun.COM
1429162SPeter.Dunlap@Sun.COM ISER_LOG(CE_NOTE, "Registered iSER transport with IDM");
1439162SPeter.Dunlap@Sun.COM
1449162SPeter.Dunlap@Sun.COM return (DDI_SUCCESS);
1459162SPeter.Dunlap@Sun.COM }
1469162SPeter.Dunlap@Sun.COM
1479162SPeter.Dunlap@Sun.COM /*
1489162SPeter.Dunlap@Sun.COM * iser_ini_conn_create()
1499162SPeter.Dunlap@Sun.COM * Allocate an iSER initiator connection context
1509162SPeter.Dunlap@Sun.COM */
1519162SPeter.Dunlap@Sun.COM static idm_status_t
iser_ini_conn_create(idm_conn_req_t * cr,idm_conn_t * ic)1529162SPeter.Dunlap@Sun.COM iser_ini_conn_create(idm_conn_req_t *cr, idm_conn_t *ic)
1539162SPeter.Dunlap@Sun.COM {
1549162SPeter.Dunlap@Sun.COM iser_chan_t *iser_chan = NULL;
1559162SPeter.Dunlap@Sun.COM iser_conn_t *iser_conn;
1569162SPeter.Dunlap@Sun.COM
1579162SPeter.Dunlap@Sun.COM /* Allocate and set up a connection handle */
1589162SPeter.Dunlap@Sun.COM iser_conn = kmem_zalloc(sizeof (iser_conn_t), KM_SLEEP);
1599162SPeter.Dunlap@Sun.COM mutex_init(&iser_conn->ic_lock, NULL, MUTEX_DRIVER, NULL);
1609162SPeter.Dunlap@Sun.COM
1619162SPeter.Dunlap@Sun.COM /* Allocate and open a channel to the target node */
1629162SPeter.Dunlap@Sun.COM iser_chan = iser_channel_alloc(NULL, &cr->cr_ini_dst_addr);
1639162SPeter.Dunlap@Sun.COM if (iser_chan == NULL) {
1649162SPeter.Dunlap@Sun.COM ISER_LOG(CE_WARN, "iser: failed to allocate channel");
1659162SPeter.Dunlap@Sun.COM mutex_destroy(&iser_conn->ic_lock);
1669162SPeter.Dunlap@Sun.COM kmem_free(iser_conn, sizeof (iser_conn_t));
1679162SPeter.Dunlap@Sun.COM return (IDM_STATUS_FAIL);
1689162SPeter.Dunlap@Sun.COM }
1699162SPeter.Dunlap@Sun.COM
1709162SPeter.Dunlap@Sun.COM /*
1719162SPeter.Dunlap@Sun.COM * The local IP and remote IP are filled in iser_channel_alloc. The
1729162SPeter.Dunlap@Sun.COM * remote port needs to be filled in from idm_conn_req_t. The local
1739162SPeter.Dunlap@Sun.COM * port is irrelevant. Internal representation of the port in the
1749162SPeter.Dunlap@Sun.COM * IDM sockaddr structure is in network byte order. IBT expects the
1759162SPeter.Dunlap@Sun.COM * port in host byte order.
1769162SPeter.Dunlap@Sun.COM */
1779162SPeter.Dunlap@Sun.COM switch (cr->cr_ini_dst_addr.sin.sa_family) {
1789162SPeter.Dunlap@Sun.COM case AF_INET:
1799162SPeter.Dunlap@Sun.COM iser_chan->ic_rport = ntohs(cr->cr_ini_dst_addr.sin4.sin_port);
1809162SPeter.Dunlap@Sun.COM break;
1819162SPeter.Dunlap@Sun.COM case AF_INET6:
1829162SPeter.Dunlap@Sun.COM iser_chan->ic_rport = ntohs(cr->cr_ini_dst_addr.sin6.sin6_port);
1839162SPeter.Dunlap@Sun.COM break;
1849162SPeter.Dunlap@Sun.COM default:
1859162SPeter.Dunlap@Sun.COM iser_chan->ic_rport = ISCSI_LISTEN_PORT;
1869162SPeter.Dunlap@Sun.COM }
1879162SPeter.Dunlap@Sun.COM iser_chan->ic_lport = 0;
1889162SPeter.Dunlap@Sun.COM
1899162SPeter.Dunlap@Sun.COM cv_init(&iser_conn->ic_stage_cv, NULL, CV_DEFAULT, NULL);
1909162SPeter.Dunlap@Sun.COM iser_conn->ic_type = ISER_CONN_TYPE_INI;
1919162SPeter.Dunlap@Sun.COM iser_conn->ic_stage = ISER_CONN_STAGE_ALLOCATED;
1929162SPeter.Dunlap@Sun.COM iser_conn->ic_chan = iser_chan;
1939162SPeter.Dunlap@Sun.COM iser_conn->ic_idmc = ic;
1949162SPeter.Dunlap@Sun.COM
1959162SPeter.Dunlap@Sun.COM /*
1969162SPeter.Dunlap@Sun.COM * Set a pointer to the iser_conn in the iser_chan for easy
1979162SPeter.Dunlap@Sun.COM * access during CM event handling
1989162SPeter.Dunlap@Sun.COM */
1999162SPeter.Dunlap@Sun.COM iser_chan->ic_conn = iser_conn;
2009162SPeter.Dunlap@Sun.COM
2019162SPeter.Dunlap@Sun.COM /* Set the iSER conn handle in the IDM conn private handle */
2029162SPeter.Dunlap@Sun.COM ic->ic_transport_private = (void *)iser_conn;
2039162SPeter.Dunlap@Sun.COM
2049162SPeter.Dunlap@Sun.COM /* Set the transport header length */
2059162SPeter.Dunlap@Sun.COM ic->ic_transport_hdrlen = ISER_HEADER_LENGTH;
2069162SPeter.Dunlap@Sun.COM
2079162SPeter.Dunlap@Sun.COM return (IDM_STATUS_SUCCESS);
2089162SPeter.Dunlap@Sun.COM }
2099162SPeter.Dunlap@Sun.COM
2109162SPeter.Dunlap@Sun.COM /*
2119162SPeter.Dunlap@Sun.COM * iser_internal_conn_destroy()
2129162SPeter.Dunlap@Sun.COM * Tear down iSER-specific connection resources. This is used below
2139162SPeter.Dunlap@Sun.COM * in iser_conn_destroy(), but also from the CM code when we may have
2149162SPeter.Dunlap@Sun.COM * some of the connection established, but not fully connected.
2159162SPeter.Dunlap@Sun.COM */
2169162SPeter.Dunlap@Sun.COM void
iser_internal_conn_destroy(iser_conn_t * ic)2179162SPeter.Dunlap@Sun.COM iser_internal_conn_destroy(iser_conn_t *ic)
2189162SPeter.Dunlap@Sun.COM {
2199162SPeter.Dunlap@Sun.COM mutex_enter(&ic->ic_lock);
2209162SPeter.Dunlap@Sun.COM iser_channel_free(ic->ic_chan);
2219162SPeter.Dunlap@Sun.COM if ((ic->ic_type == ISER_CONN_TYPE_TGT) &&
2229162SPeter.Dunlap@Sun.COM (ic->ic_stage == ISER_CONN_STAGE_ALLOCATED)) {
2239162SPeter.Dunlap@Sun.COM /*
2249162SPeter.Dunlap@Sun.COM * This is a target connection that has yet to be
2259162SPeter.Dunlap@Sun.COM * established. Free our reference on the target
2269162SPeter.Dunlap@Sun.COM * service handle.
2279162SPeter.Dunlap@Sun.COM */
2289162SPeter.Dunlap@Sun.COM iser_tgt_svc_rele(ic->ic_idms->is_iser_svc);
2299162SPeter.Dunlap@Sun.COM }
2309162SPeter.Dunlap@Sun.COM cv_destroy(&ic->ic_stage_cv);
2319162SPeter.Dunlap@Sun.COM mutex_exit(&ic->ic_lock);
2329162SPeter.Dunlap@Sun.COM mutex_destroy(&ic->ic_lock);
2339162SPeter.Dunlap@Sun.COM kmem_free(ic, sizeof (iser_conn_t));
2349162SPeter.Dunlap@Sun.COM }
2359162SPeter.Dunlap@Sun.COM
2369162SPeter.Dunlap@Sun.COM /*
2379162SPeter.Dunlap@Sun.COM * iser_conn_destroy()
2389162SPeter.Dunlap@Sun.COM * Tear down an initiator or target connection.
2399162SPeter.Dunlap@Sun.COM */
2409162SPeter.Dunlap@Sun.COM static void
iser_conn_destroy(idm_conn_t * ic)2419162SPeter.Dunlap@Sun.COM iser_conn_destroy(idm_conn_t *ic)
2429162SPeter.Dunlap@Sun.COM {
2439162SPeter.Dunlap@Sun.COM iser_conn_t *iser_conn;
2449162SPeter.Dunlap@Sun.COM iser_conn = (iser_conn_t *)ic->ic_transport_private;
2459162SPeter.Dunlap@Sun.COM
2469162SPeter.Dunlap@Sun.COM iser_internal_conn_destroy(iser_conn);
2479162SPeter.Dunlap@Sun.COM ic->ic_transport_private = NULL;
2489162SPeter.Dunlap@Sun.COM }
2499162SPeter.Dunlap@Sun.COM
2509162SPeter.Dunlap@Sun.COM /*
2519162SPeter.Dunlap@Sun.COM * iser_ini_conn_connect()
2529162SPeter.Dunlap@Sun.COM * Establish the connection referred to by the handle previously allocated via
2539162SPeter.Dunlap@Sun.COM * iser_ini_conn_create().
2549162SPeter.Dunlap@Sun.COM */
2559162SPeter.Dunlap@Sun.COM static idm_status_t
iser_ini_conn_connect(idm_conn_t * ic)2569162SPeter.Dunlap@Sun.COM iser_ini_conn_connect(idm_conn_t *ic)
2579162SPeter.Dunlap@Sun.COM {
2589162SPeter.Dunlap@Sun.COM iser_conn_t *iser_conn;
2599162SPeter.Dunlap@Sun.COM iser_status_t status;
2609162SPeter.Dunlap@Sun.COM
2619162SPeter.Dunlap@Sun.COM iser_conn = (iser_conn_t *)ic->ic_transport_private;
2629162SPeter.Dunlap@Sun.COM
2639162SPeter.Dunlap@Sun.COM status = iser_channel_open(iser_conn->ic_chan);
2649162SPeter.Dunlap@Sun.COM if (status != ISER_STATUS_SUCCESS) {
2659162SPeter.Dunlap@Sun.COM ISER_LOG(CE_WARN, "iser: failed to open channel");
2669162SPeter.Dunlap@Sun.COM return (IDM_STATUS_FAIL);
2679162SPeter.Dunlap@Sun.COM }
2689162SPeter.Dunlap@Sun.COM
2699162SPeter.Dunlap@Sun.COM /*
2709162SPeter.Dunlap@Sun.COM * Set the local and remote addresses in the idm conn handle.
2719162SPeter.Dunlap@Sun.COM */
2729162SPeter.Dunlap@Sun.COM iser_ib_conv_ibtaddr2sockaddr(&ic->ic_laddr,
2739162SPeter.Dunlap@Sun.COM &iser_conn->ic_chan->ic_localip, iser_conn->ic_chan->ic_lport);
2749162SPeter.Dunlap@Sun.COM iser_ib_conv_ibtaddr2sockaddr(&ic->ic_raddr,
2759162SPeter.Dunlap@Sun.COM &iser_conn->ic_chan->ic_remoteip, iser_conn->ic_chan->ic_rport);
2769162SPeter.Dunlap@Sun.COM
2779162SPeter.Dunlap@Sun.COM mutex_enter(&iser_conn->ic_lock);
2789162SPeter.Dunlap@Sun.COM /* Hold a reference on the IDM connection handle */
2799162SPeter.Dunlap@Sun.COM idm_conn_hold(ic);
2809162SPeter.Dunlap@Sun.COM iser_conn->ic_stage = ISER_CONN_STAGE_IC_CONNECTED;
2819162SPeter.Dunlap@Sun.COM mutex_exit(&iser_conn->ic_lock);
2829162SPeter.Dunlap@Sun.COM
2839162SPeter.Dunlap@Sun.COM return (IDM_STATUS_SUCCESS);
2849162SPeter.Dunlap@Sun.COM }
2859162SPeter.Dunlap@Sun.COM
2869162SPeter.Dunlap@Sun.COM /*
2879162SPeter.Dunlap@Sun.COM * iser_conn_disconnect()
2889162SPeter.Dunlap@Sun.COM * Shutdown this iSER connection
2899162SPeter.Dunlap@Sun.COM */
2909162SPeter.Dunlap@Sun.COM static void
iser_conn_disconnect(idm_conn_t * ic)2919162SPeter.Dunlap@Sun.COM iser_conn_disconnect(idm_conn_t *ic)
2929162SPeter.Dunlap@Sun.COM {
2939162SPeter.Dunlap@Sun.COM iser_conn_t *iser_conn;
2949162SPeter.Dunlap@Sun.COM
2959162SPeter.Dunlap@Sun.COM iser_conn = (iser_conn_t *)ic->ic_transport_private;
2969162SPeter.Dunlap@Sun.COM
2979162SPeter.Dunlap@Sun.COM mutex_enter(&iser_conn->ic_lock);
2989162SPeter.Dunlap@Sun.COM iser_conn->ic_stage = ISER_CONN_STAGE_CLOSING;
2999162SPeter.Dunlap@Sun.COM mutex_exit(&iser_conn->ic_lock);
3009162SPeter.Dunlap@Sun.COM
3019162SPeter.Dunlap@Sun.COM /* Close the channel */
3029162SPeter.Dunlap@Sun.COM iser_channel_close(iser_conn->ic_chan);
3039162SPeter.Dunlap@Sun.COM
3049162SPeter.Dunlap@Sun.COM /* Free our reference held on the IDM conn handle, and set CLOSED */
3059162SPeter.Dunlap@Sun.COM mutex_enter(&iser_conn->ic_lock);
3069162SPeter.Dunlap@Sun.COM idm_conn_rele(iser_conn->ic_idmc);
3079162SPeter.Dunlap@Sun.COM iser_conn->ic_stage = ISER_CONN_STAGE_CLOSED;
3089162SPeter.Dunlap@Sun.COM mutex_exit(&iser_conn->ic_lock);
3099162SPeter.Dunlap@Sun.COM }
3109162SPeter.Dunlap@Sun.COM
3119162SPeter.Dunlap@Sun.COM /*
3129162SPeter.Dunlap@Sun.COM * iser_tgt_svc_create()
3139162SPeter.Dunlap@Sun.COM * Establish the CM service for inbound iSER service requests on the port
3149162SPeter.Dunlap@Sun.COM * indicated by sr->sr_port.
3159162SPeter.Dunlap@Sun.COM * idm_svc_req_t contains the service parameters.
3169162SPeter.Dunlap@Sun.COM */
3179162SPeter.Dunlap@Sun.COM idm_status_t
iser_tgt_svc_create(idm_svc_req_t * sr,idm_svc_t * is)3189162SPeter.Dunlap@Sun.COM iser_tgt_svc_create(idm_svc_req_t *sr, idm_svc_t *is)
3199162SPeter.Dunlap@Sun.COM {
3209162SPeter.Dunlap@Sun.COM iser_svc_t *iser_svc;
3219162SPeter.Dunlap@Sun.COM
3229162SPeter.Dunlap@Sun.COM int rc;
3239162SPeter.Dunlap@Sun.COM
3249162SPeter.Dunlap@Sun.COM iser_svc = kmem_zalloc(sizeof (iser_svc_t), KM_SLEEP);
3259162SPeter.Dunlap@Sun.COM is->is_iser_svc = (void *)iser_svc;
3269162SPeter.Dunlap@Sun.COM
3279162SPeter.Dunlap@Sun.COM idm_refcnt_init(&iser_svc->is_refcnt, iser_svc);
3289162SPeter.Dunlap@Sun.COM
3299162SPeter.Dunlap@Sun.COM list_create(&iser_svc->is_sbindlist, sizeof (iser_sbind_t),
3309162SPeter.Dunlap@Sun.COM offsetof(iser_sbind_t, is_list_node));
3319162SPeter.Dunlap@Sun.COM iser_svc->is_svcid = ibt_get_ip_sid(IPPROTO_TCP, sr->sr_port);
3329162SPeter.Dunlap@Sun.COM
3339162SPeter.Dunlap@Sun.COM /*
3349162SPeter.Dunlap@Sun.COM * Register an iSER target service for the requested port
3359162SPeter.Dunlap@Sun.COM * and set the iser_svc structure in the idm_svc handle.
3369162SPeter.Dunlap@Sun.COM */
3379162SPeter.Dunlap@Sun.COM rc = iser_register_service(is);
3389162SPeter.Dunlap@Sun.COM if (rc != DDI_SUCCESS) {
3399162SPeter.Dunlap@Sun.COM ISER_LOG(CE_NOTE, "iser_tgt_svc_create: iser_register_service "
3409162SPeter.Dunlap@Sun.COM "failed on port (%d): rc (0x%x)", sr->sr_port, rc);
34111093SSrivijitha.Dugganapalli@Sun.COM (void) ibt_release_ip_sid(iser_svc->is_svcid);
3429162SPeter.Dunlap@Sun.COM list_destroy(&iser_svc->is_sbindlist);
3439162SPeter.Dunlap@Sun.COM idm_refcnt_destroy(&iser_svc->is_refcnt);
3449162SPeter.Dunlap@Sun.COM kmem_free(iser_svc, sizeof (iser_svc_t));
3459162SPeter.Dunlap@Sun.COM return (IDM_STATUS_FAIL);
3469162SPeter.Dunlap@Sun.COM }
3479162SPeter.Dunlap@Sun.COM
3489162SPeter.Dunlap@Sun.COM return (IDM_STATUS_SUCCESS);
3499162SPeter.Dunlap@Sun.COM }
3509162SPeter.Dunlap@Sun.COM
3519162SPeter.Dunlap@Sun.COM /* IDM refcnt utilities for the iSER service handle */
3529162SPeter.Dunlap@Sun.COM void
iser_tgt_svc_hold(iser_svc_t * is)3539162SPeter.Dunlap@Sun.COM iser_tgt_svc_hold(iser_svc_t *is)
3549162SPeter.Dunlap@Sun.COM {
3559162SPeter.Dunlap@Sun.COM idm_refcnt_hold(&is->is_refcnt);
3569162SPeter.Dunlap@Sun.COM }
3579162SPeter.Dunlap@Sun.COM
3589162SPeter.Dunlap@Sun.COM void
iser_tgt_svc_rele(iser_svc_t * is)3599162SPeter.Dunlap@Sun.COM iser_tgt_svc_rele(iser_svc_t *is)
3609162SPeter.Dunlap@Sun.COM {
3619162SPeter.Dunlap@Sun.COM idm_refcnt_rele(&is->is_refcnt);
3629162SPeter.Dunlap@Sun.COM }
3639162SPeter.Dunlap@Sun.COM
3649162SPeter.Dunlap@Sun.COM /*
3659162SPeter.Dunlap@Sun.COM * iser_tgt_svc_destroy()
3669162SPeter.Dunlap@Sun.COM * Teardown resources allocated in iser_tgt_svc_create()
3679162SPeter.Dunlap@Sun.COM */
3689162SPeter.Dunlap@Sun.COM static void
iser_tgt_svc_destroy(idm_svc_t * is)3699162SPeter.Dunlap@Sun.COM iser_tgt_svc_destroy(idm_svc_t *is)
3709162SPeter.Dunlap@Sun.COM {
3719162SPeter.Dunlap@Sun.COM iser_svc_t *iser_svc;
3729162SPeter.Dunlap@Sun.COM
3739162SPeter.Dunlap@Sun.COM iser_svc = (iser_svc_t *)is->is_iser_svc;
3749162SPeter.Dunlap@Sun.COM
3759162SPeter.Dunlap@Sun.COM /*
3769162SPeter.Dunlap@Sun.COM * Deregister the iSER target service on this port and free
3779162SPeter.Dunlap@Sun.COM * the iser_svc structure from the idm_svc handle.
3789162SPeter.Dunlap@Sun.COM */
3799162SPeter.Dunlap@Sun.COM iser_deregister_service(is);
3809162SPeter.Dunlap@Sun.COM
3819162SPeter.Dunlap@Sun.COM /* Wait for the iSER service handle's refcnt to zero */
3829162SPeter.Dunlap@Sun.COM idm_refcnt_wait_ref(&iser_svc->is_refcnt);
3839162SPeter.Dunlap@Sun.COM
3849162SPeter.Dunlap@Sun.COM list_destroy(&iser_svc->is_sbindlist);
3859162SPeter.Dunlap@Sun.COM
3869162SPeter.Dunlap@Sun.COM idm_refcnt_destroy(&iser_svc->is_refcnt);
3879162SPeter.Dunlap@Sun.COM
3889162SPeter.Dunlap@Sun.COM kmem_free(iser_svc, sizeof (iser_svc_t));
3899162SPeter.Dunlap@Sun.COM }
3909162SPeter.Dunlap@Sun.COM
3919162SPeter.Dunlap@Sun.COM /*
3929162SPeter.Dunlap@Sun.COM * iser_tgt_svc_online()
3939162SPeter.Dunlap@Sun.COM * Bind the CM service allocated via iser_tgt_svc_create().
3949162SPeter.Dunlap@Sun.COM */
3959162SPeter.Dunlap@Sun.COM static idm_status_t
iser_tgt_svc_online(idm_svc_t * is)3969162SPeter.Dunlap@Sun.COM iser_tgt_svc_online(idm_svc_t *is)
3979162SPeter.Dunlap@Sun.COM {
3989162SPeter.Dunlap@Sun.COM iser_status_t status;
3999162SPeter.Dunlap@Sun.COM
4009162SPeter.Dunlap@Sun.COM mutex_enter(&is->is_mutex);
4019162SPeter.Dunlap@Sun.COM
4029162SPeter.Dunlap@Sun.COM /*
4039162SPeter.Dunlap@Sun.COM * Pass the IDM service handle as the client private data for
4049162SPeter.Dunlap@Sun.COM * later use.
4059162SPeter.Dunlap@Sun.COM */
4069162SPeter.Dunlap@Sun.COM status = iser_bind_service(is);
4079162SPeter.Dunlap@Sun.COM if (status != ISER_STATUS_SUCCESS) {
4089162SPeter.Dunlap@Sun.COM ISER_LOG(CE_NOTE, "iser_tgt_svc_online: failed bind service");
4099162SPeter.Dunlap@Sun.COM mutex_exit(&is->is_mutex);
4109162SPeter.Dunlap@Sun.COM return (IDM_STATUS_FAIL);
4119162SPeter.Dunlap@Sun.COM }
4129162SPeter.Dunlap@Sun.COM
4139162SPeter.Dunlap@Sun.COM mutex_exit(&is->is_mutex);
4149162SPeter.Dunlap@Sun.COM return (IDM_STATUS_SUCCESS);
4159162SPeter.Dunlap@Sun.COM }
4169162SPeter.Dunlap@Sun.COM
4179162SPeter.Dunlap@Sun.COM /*
4189162SPeter.Dunlap@Sun.COM * iser_tgt_svc_offline
4199162SPeter.Dunlap@Sun.COM * Unbind the service on all available HCA ports.
4209162SPeter.Dunlap@Sun.COM */
4219162SPeter.Dunlap@Sun.COM static void
iser_tgt_svc_offline(idm_svc_t * is)4229162SPeter.Dunlap@Sun.COM iser_tgt_svc_offline(idm_svc_t *is)
4239162SPeter.Dunlap@Sun.COM {
4249162SPeter.Dunlap@Sun.COM mutex_enter(&is->is_mutex);
4259162SPeter.Dunlap@Sun.COM
4269162SPeter.Dunlap@Sun.COM iser_unbind_service(is);
4279162SPeter.Dunlap@Sun.COM mutex_exit(&is->is_mutex);
4289162SPeter.Dunlap@Sun.COM
4299162SPeter.Dunlap@Sun.COM }
4309162SPeter.Dunlap@Sun.COM
4319162SPeter.Dunlap@Sun.COM /*
4329162SPeter.Dunlap@Sun.COM * iser_tgt_conn_connect()
4339162SPeter.Dunlap@Sun.COM * Establish the connection in ic, passed from idm_tgt_conn_finish(), which
4349162SPeter.Dunlap@Sun.COM * is invoked from the SM as a result of an inbound connection request.
4359162SPeter.Dunlap@Sun.COM */
4369162SPeter.Dunlap@Sun.COM /* ARGSUSED */
4379162SPeter.Dunlap@Sun.COM static idm_status_t
iser_tgt_conn_connect(idm_conn_t * ic)4389162SPeter.Dunlap@Sun.COM iser_tgt_conn_connect(idm_conn_t *ic)
4399162SPeter.Dunlap@Sun.COM {
4409162SPeter.Dunlap@Sun.COM /* No action required */
4419162SPeter.Dunlap@Sun.COM return (IDM_STATUS_SUCCESS);
4429162SPeter.Dunlap@Sun.COM }
4439162SPeter.Dunlap@Sun.COM
4449162SPeter.Dunlap@Sun.COM /*
4459162SPeter.Dunlap@Sun.COM * iser_tgt_enable_datamover() sets the transport private data on the
4469162SPeter.Dunlap@Sun.COM * idm_conn_t and move the conn stage to indicate logged in.
4479162SPeter.Dunlap@Sun.COM */
4489162SPeter.Dunlap@Sun.COM static idm_status_t
iser_tgt_enable_datamover(idm_conn_t * ic)4499162SPeter.Dunlap@Sun.COM iser_tgt_enable_datamover(idm_conn_t *ic)
4509162SPeter.Dunlap@Sun.COM {
4519162SPeter.Dunlap@Sun.COM iser_conn_t *iser_conn;
4529162SPeter.Dunlap@Sun.COM
4539162SPeter.Dunlap@Sun.COM iser_conn = (iser_conn_t *)ic->ic_transport_private;
4549162SPeter.Dunlap@Sun.COM mutex_enter(&iser_conn->ic_lock);
4559162SPeter.Dunlap@Sun.COM
4569162SPeter.Dunlap@Sun.COM iser_conn->ic_stage = ISER_CONN_STAGE_LOGGED_IN;
4579162SPeter.Dunlap@Sun.COM mutex_exit(&iser_conn->ic_lock);
4589162SPeter.Dunlap@Sun.COM
4599162SPeter.Dunlap@Sun.COM return (IDM_STATUS_SUCCESS);
4609162SPeter.Dunlap@Sun.COM }
4619162SPeter.Dunlap@Sun.COM
4629162SPeter.Dunlap@Sun.COM /*
4639162SPeter.Dunlap@Sun.COM * iser_ini_enable_datamover() is used by the iSCSI initator to request that a
4649162SPeter.Dunlap@Sun.COM * specified iSCSI connection be transitioned to iSER-assisted mode.
4659162SPeter.Dunlap@Sun.COM * In the case of iSER, the RDMA resources for a reliable connection have
4669162SPeter.Dunlap@Sun.COM * already been allocated at this time, and the 'RDMAExtensions' is set to 'Yes'
4679162SPeter.Dunlap@Sun.COM * so no further negotiations are required at this time.
4689162SPeter.Dunlap@Sun.COM * The initiator now sends the first iSER Message - 'Hello' to the target
4699162SPeter.Dunlap@Sun.COM * and waits for the 'HelloReply' Message from the target before directing
4709162SPeter.Dunlap@Sun.COM * the initiator to go into the Full Feature Phase.
4719162SPeter.Dunlap@Sun.COM *
4729162SPeter.Dunlap@Sun.COM * No transport op is required on the target side.
4739162SPeter.Dunlap@Sun.COM */
4749162SPeter.Dunlap@Sun.COM static idm_status_t
iser_ini_enable_datamover(idm_conn_t * ic)4759162SPeter.Dunlap@Sun.COM iser_ini_enable_datamover(idm_conn_t *ic)
4769162SPeter.Dunlap@Sun.COM {
4779162SPeter.Dunlap@Sun.COM
4789162SPeter.Dunlap@Sun.COM iser_conn_t *iser_conn;
4799162SPeter.Dunlap@Sun.COM clock_t delay;
4809162SPeter.Dunlap@Sun.COM int status;
4819162SPeter.Dunlap@Sun.COM
4829162SPeter.Dunlap@Sun.COM iser_conn = (iser_conn_t *)ic->ic_transport_private;
4839162SPeter.Dunlap@Sun.COM
4849162SPeter.Dunlap@Sun.COM mutex_enter(&iser_conn->ic_lock);
4859162SPeter.Dunlap@Sun.COM iser_conn->ic_stage = ISER_CONN_STAGE_HELLO_SENT;
4869162SPeter.Dunlap@Sun.COM mutex_exit(&iser_conn->ic_lock);
4879162SPeter.Dunlap@Sun.COM
4889162SPeter.Dunlap@Sun.COM /* Send the iSER Hello Message to the target */
4899162SPeter.Dunlap@Sun.COM status = iser_xfer_hello_msg(iser_conn->ic_chan);
4909162SPeter.Dunlap@Sun.COM if (status != ISER_STATUS_SUCCESS) {
4919162SPeter.Dunlap@Sun.COM
4929162SPeter.Dunlap@Sun.COM mutex_enter(&iser_conn->ic_lock);
4939162SPeter.Dunlap@Sun.COM iser_conn->ic_stage = ISER_CONN_STAGE_HELLO_SENT_FAIL;
4949162SPeter.Dunlap@Sun.COM mutex_exit(&iser_conn->ic_lock);
4959162SPeter.Dunlap@Sun.COM
4969162SPeter.Dunlap@Sun.COM return (IDM_STATUS_FAIL);
4979162SPeter.Dunlap@Sun.COM }
4989162SPeter.Dunlap@Sun.COM
4999162SPeter.Dunlap@Sun.COM /*
5009162SPeter.Dunlap@Sun.COM * Acquire the iser_conn->ic_lock and wait for the iSER HelloReply
5019162SPeter.Dunlap@Sun.COM * Message from the target, i.e. iser_conn_stage_t to be set to
5029162SPeter.Dunlap@Sun.COM * ISER_CONN_STAGE_HELLOREPLY_RCV. If the handshake does not
5039162SPeter.Dunlap@Sun.COM * complete within a specified time period (.5s), then return failure.
5049162SPeter.Dunlap@Sun.COM *
5059162SPeter.Dunlap@Sun.COM */
5069162SPeter.Dunlap@Sun.COM delay = ddi_get_lbolt() + drv_usectohz(500000);
5079162SPeter.Dunlap@Sun.COM
5089162SPeter.Dunlap@Sun.COM mutex_enter(&iser_conn->ic_lock);
5099162SPeter.Dunlap@Sun.COM while ((iser_conn->ic_stage != ISER_CONN_STAGE_HELLOREPLY_RCV) &&
5109162SPeter.Dunlap@Sun.COM (ddi_get_lbolt() < delay)) {
5119162SPeter.Dunlap@Sun.COM
5129162SPeter.Dunlap@Sun.COM (void) cv_timedwait(&iser_conn->ic_stage_cv,
5139162SPeter.Dunlap@Sun.COM &iser_conn->ic_lock, delay);
5149162SPeter.Dunlap@Sun.COM }
5159162SPeter.Dunlap@Sun.COM
5169162SPeter.Dunlap@Sun.COM switch (iser_conn->ic_stage) {
5179162SPeter.Dunlap@Sun.COM case ISER_CONN_STAGE_HELLOREPLY_RCV:
5189162SPeter.Dunlap@Sun.COM iser_conn->ic_stage = ISER_CONN_STAGE_LOGGED_IN;
5199162SPeter.Dunlap@Sun.COM mutex_exit(&iser_conn->ic_lock);
5209162SPeter.Dunlap@Sun.COM /*
5219162SPeter.Dunlap@Sun.COM * Return suceess to indicate that the initiator connection can
5229162SPeter.Dunlap@Sun.COM * go to the next phase - FFP
5239162SPeter.Dunlap@Sun.COM */
5249162SPeter.Dunlap@Sun.COM return (IDM_STATUS_SUCCESS);
5259162SPeter.Dunlap@Sun.COM default:
5269162SPeter.Dunlap@Sun.COM iser_conn->ic_stage = ISER_CONN_STAGE_HELLOREPLY_RCV_FAIL;
5279162SPeter.Dunlap@Sun.COM mutex_exit(&iser_conn->ic_lock);
5289162SPeter.Dunlap@Sun.COM return (IDM_STATUS_FAIL);
5299162SPeter.Dunlap@Sun.COM
5309162SPeter.Dunlap@Sun.COM }
5319162SPeter.Dunlap@Sun.COM
5329162SPeter.Dunlap@Sun.COM /* STATEMENT_NEVER_REACHED */
5339162SPeter.Dunlap@Sun.COM }
5349162SPeter.Dunlap@Sun.COM
5359162SPeter.Dunlap@Sun.COM /*
5369162SPeter.Dunlap@Sun.COM * iser_free_task_rsrcs()
5379162SPeter.Dunlap@Sun.COM * This routine does not currently need to do anything. It is used in
5389162SPeter.Dunlap@Sun.COM * the sockets transport to explicitly complete any buffers on the task,
5399162SPeter.Dunlap@Sun.COM * but we can rely on our RCaP layer to finish up it's work without any
5409162SPeter.Dunlap@Sun.COM * intervention.
5419162SPeter.Dunlap@Sun.COM */
5429162SPeter.Dunlap@Sun.COM /* ARGSUSED */
5439162SPeter.Dunlap@Sun.COM idm_status_t
iser_free_task_rsrcs(idm_task_t * idt)5449162SPeter.Dunlap@Sun.COM iser_free_task_rsrcs(idm_task_t *idt)
5459162SPeter.Dunlap@Sun.COM {
5469162SPeter.Dunlap@Sun.COM return (IDM_STATUS_SUCCESS);
5479162SPeter.Dunlap@Sun.COM }
5489162SPeter.Dunlap@Sun.COM
5499162SPeter.Dunlap@Sun.COM /*
5509162SPeter.Dunlap@Sun.COM * iser_negotiate_key_values() validates the key values for this connection
5519162SPeter.Dunlap@Sun.COM */
5529162SPeter.Dunlap@Sun.COM /* ARGSUSED */
5539162SPeter.Dunlap@Sun.COM static kv_status_t
iser_negotiate_key_values(idm_conn_t * ic,nvlist_t * request_nvl,nvlist_t * response_nvl,nvlist_t * negotiated_nvl)5549162SPeter.Dunlap@Sun.COM iser_negotiate_key_values(idm_conn_t *ic, nvlist_t *request_nvl,
5559162SPeter.Dunlap@Sun.COM nvlist_t *response_nvl, nvlist_t *negotiated_nvl)
5569162SPeter.Dunlap@Sun.COM {
5579162SPeter.Dunlap@Sun.COM kv_status_t kvrc = KV_HANDLED;
5589162SPeter.Dunlap@Sun.COM
5599162SPeter.Dunlap@Sun.COM /* Process the request nvlist */
5609162SPeter.Dunlap@Sun.COM kvrc = iser_process_request_nvlist(request_nvl, response_nvl,
5619162SPeter.Dunlap@Sun.COM negotiated_nvl);
5629162SPeter.Dunlap@Sun.COM
5639162SPeter.Dunlap@Sun.COM /* We must be using RDMA, so set the flag on the ic handle */
5649162SPeter.Dunlap@Sun.COM ic->ic_rdma_extensions = B_TRUE;
5659162SPeter.Dunlap@Sun.COM
5669162SPeter.Dunlap@Sun.COM return (kvrc);
5679162SPeter.Dunlap@Sun.COM }
5689162SPeter.Dunlap@Sun.COM
5699162SPeter.Dunlap@Sun.COM /* Process a list of key=value pairs from a login request */
5709162SPeter.Dunlap@Sun.COM static kv_status_t
iser_process_request_nvlist(nvlist_t * request_nvl,nvlist_t * response_nvl,nvlist_t * negotiated_nvl)5719162SPeter.Dunlap@Sun.COM iser_process_request_nvlist(nvlist_t *request_nvl, nvlist_t *response_nvl,
5729162SPeter.Dunlap@Sun.COM nvlist_t *negotiated_nvl)
5739162SPeter.Dunlap@Sun.COM {
5749162SPeter.Dunlap@Sun.COM const idm_kv_xlate_t *ikvx;
5759162SPeter.Dunlap@Sun.COM char *nvp_name;
5769162SPeter.Dunlap@Sun.COM nvpair_t *nvp;
5779162SPeter.Dunlap@Sun.COM nvpair_t *next_nvp;
5789162SPeter.Dunlap@Sun.COM kv_status_t kvrc = KV_HANDLED;
5799162SPeter.Dunlap@Sun.COM boolean_t transit = B_TRUE;
5809162SPeter.Dunlap@Sun.COM
5819162SPeter.Dunlap@Sun.COM /* Process the list */
5829162SPeter.Dunlap@Sun.COM nvp = nvlist_next_nvpair(request_nvl, NULL);
5839162SPeter.Dunlap@Sun.COM while (nvp != NULL) {
5849162SPeter.Dunlap@Sun.COM next_nvp = nvlist_next_nvpair(request_nvl, nvp);
5859162SPeter.Dunlap@Sun.COM
5869162SPeter.Dunlap@Sun.COM nvp_name = nvpair_name(nvp);
5879162SPeter.Dunlap@Sun.COM ikvx = idm_lookup_kv_xlate(nvp_name, strlen(nvp_name));
5889162SPeter.Dunlap@Sun.COM
5899162SPeter.Dunlap@Sun.COM kvrc = iser_handle_key(nvp, ikvx, request_nvl, response_nvl,
5909162SPeter.Dunlap@Sun.COM negotiated_nvl);
5919162SPeter.Dunlap@Sun.COM if (kvrc != KV_HANDLED) {
5929162SPeter.Dunlap@Sun.COM if (kvrc == KV_HANDLED_NO_TRANSIT) {
5939162SPeter.Dunlap@Sun.COM /* we countered, clear the transit flag */
5949162SPeter.Dunlap@Sun.COM transit = B_FALSE;
5959162SPeter.Dunlap@Sun.COM } else {
5969162SPeter.Dunlap@Sun.COM /* error, bail out */
5979162SPeter.Dunlap@Sun.COM break;
5989162SPeter.Dunlap@Sun.COM }
5999162SPeter.Dunlap@Sun.COM }
6009162SPeter.Dunlap@Sun.COM
6019162SPeter.Dunlap@Sun.COM nvp = next_nvp;
6029162SPeter.Dunlap@Sun.COM }
6039162SPeter.Dunlap@Sun.COM /*
6049162SPeter.Dunlap@Sun.COM * If the current kv_status_t indicates success, we've handled
6059162SPeter.Dunlap@Sun.COM * the entire list. Explicitly set kvrc to NO_TRANSIT if we've
6069162SPeter.Dunlap@Sun.COM * cleared the transit flag along the way.
6079162SPeter.Dunlap@Sun.COM */
6089162SPeter.Dunlap@Sun.COM if ((kvrc == KV_HANDLED) && (transit == B_FALSE)) {
6099162SPeter.Dunlap@Sun.COM kvrc = KV_HANDLED_NO_TRANSIT;
6109162SPeter.Dunlap@Sun.COM }
6119162SPeter.Dunlap@Sun.COM
6129162SPeter.Dunlap@Sun.COM return (kvrc);
6139162SPeter.Dunlap@Sun.COM }
6149162SPeter.Dunlap@Sun.COM
6159162SPeter.Dunlap@Sun.COM /* Handle a given list, boolean or numerical key=value pair */
6169162SPeter.Dunlap@Sun.COM static kv_status_t
iser_handle_key(nvpair_t * nvp,const idm_kv_xlate_t * ikvx,nvlist_t * request_nvl,nvlist_t * response_nvl,nvlist_t * negotiated_nvl)6179162SPeter.Dunlap@Sun.COM iser_handle_key(nvpair_t *nvp, const idm_kv_xlate_t *ikvx,
6189162SPeter.Dunlap@Sun.COM nvlist_t *request_nvl, nvlist_t *response_nvl, nvlist_t *negotiated_nvl)
6199162SPeter.Dunlap@Sun.COM {
6209162SPeter.Dunlap@Sun.COM kv_status_t kvrc = KV_UNHANDLED;
6219162SPeter.Dunlap@Sun.COM boolean_t bool_val;
6229162SPeter.Dunlap@Sun.COM uint64_t num_val;
6239162SPeter.Dunlap@Sun.COM int nvrc;
6249162SPeter.Dunlap@Sun.COM
6259162SPeter.Dunlap@Sun.COM /* Retrieve values for booleans and numericals */
6269162SPeter.Dunlap@Sun.COM switch (ikvx->ik_key_id) {
6279162SPeter.Dunlap@Sun.COM /* Booleans */
6289162SPeter.Dunlap@Sun.COM case KI_RDMA_EXTENSIONS:
6299162SPeter.Dunlap@Sun.COM case KI_IMMEDIATE_DATA:
6309162SPeter.Dunlap@Sun.COM nvrc = nvpair_value_boolean_value(nvp, &bool_val);
6319162SPeter.Dunlap@Sun.COM ASSERT(nvrc == 0);
6329162SPeter.Dunlap@Sun.COM break;
6339162SPeter.Dunlap@Sun.COM /* Numericals */
6349162SPeter.Dunlap@Sun.COM case KI_INITIATOR_RECV_DATA_SEGMENT_LENGTH:
6359162SPeter.Dunlap@Sun.COM case KI_TARGET_RECV_DATA_SEGMENT_LENGTH:
6369162SPeter.Dunlap@Sun.COM case KI_MAX_OUTSTANDING_UNEXPECTED_PDUS:
6379162SPeter.Dunlap@Sun.COM nvrc = nvpair_value_uint64(nvp, &num_val);
6389162SPeter.Dunlap@Sun.COM ASSERT(nvrc == 0);
6399162SPeter.Dunlap@Sun.COM break;
6409162SPeter.Dunlap@Sun.COM default:
6419162SPeter.Dunlap@Sun.COM break;
6429162SPeter.Dunlap@Sun.COM }
6439162SPeter.Dunlap@Sun.COM
64412485SPeter.Gill@Sun.COM /*
64512485SPeter.Gill@Sun.COM * Now handle the values according to the key name. Keys not
64612485SPeter.Gill@Sun.COM * specifically handled here will be negotiated by the iscsi
64712485SPeter.Gill@Sun.COM * target. Negotiated values take effect when
64812485SPeter.Gill@Sun.COM * iser_notice_key_values gets called.
64912485SPeter.Gill@Sun.COM */
6509162SPeter.Dunlap@Sun.COM switch (ikvx->ik_key_id) {
6519162SPeter.Dunlap@Sun.COM case KI_RDMA_EXTENSIONS:
6529162SPeter.Dunlap@Sun.COM /* Ensure "Yes" */
6539162SPeter.Dunlap@Sun.COM kvrc = iser_handle_boolean(nvp, bool_val, ikvx, B_TRUE,
6549162SPeter.Dunlap@Sun.COM request_nvl, response_nvl, negotiated_nvl);
6559162SPeter.Dunlap@Sun.COM break;
6569162SPeter.Dunlap@Sun.COM case KI_TARGET_RECV_DATA_SEGMENT_LENGTH:
6579162SPeter.Dunlap@Sun.COM /* Validate the proposed value */
6589162SPeter.Dunlap@Sun.COM kvrc = iser_handle_numerical(nvp, num_val, ikvx,
6599162SPeter.Dunlap@Sun.COM ISER_TARGET_RECV_DATA_SEGMENT_LENGTH_MIN,
6609162SPeter.Dunlap@Sun.COM ISER_TARGET_RECV_DATA_SEGMENT_LENGTH_MAX,
6619162SPeter.Dunlap@Sun.COM ISER_TARGET_RECV_DATA_SEGMENT_LENGTH_IMPL_MAX,
6629162SPeter.Dunlap@Sun.COM request_nvl, response_nvl, negotiated_nvl);
6639162SPeter.Dunlap@Sun.COM break;
6649162SPeter.Dunlap@Sun.COM case KI_INITIATOR_RECV_DATA_SEGMENT_LENGTH:
6659162SPeter.Dunlap@Sun.COM /* Validate the proposed value */
6669162SPeter.Dunlap@Sun.COM kvrc = iser_handle_numerical(nvp, num_val, ikvx,
6679162SPeter.Dunlap@Sun.COM ISER_INITIATOR_RECV_DATA_SEGMENT_LENGTH_MIN,
6689162SPeter.Dunlap@Sun.COM ISER_INITIATOR_RECV_DATA_SEGMENT_LENGTH_MAX,
6699162SPeter.Dunlap@Sun.COM ISER_INITIATOR_RECV_DATA_SEGMENT_LENGTH_IMPL_MAX,
6709162SPeter.Dunlap@Sun.COM request_nvl, response_nvl, negotiated_nvl);
6719162SPeter.Dunlap@Sun.COM break;
6729162SPeter.Dunlap@Sun.COM case KI_IMMEDIATE_DATA:
6739162SPeter.Dunlap@Sun.COM /* Ensure "No" */
6749162SPeter.Dunlap@Sun.COM kvrc = iser_handle_boolean(nvp, bool_val, ikvx, B_FALSE,
6759162SPeter.Dunlap@Sun.COM request_nvl, response_nvl, negotiated_nvl);
6769162SPeter.Dunlap@Sun.COM break;
6779162SPeter.Dunlap@Sun.COM case KI_MAX_OUTSTANDING_UNEXPECTED_PDUS:
6789162SPeter.Dunlap@Sun.COM /* Validate the proposed value */
6799162SPeter.Dunlap@Sun.COM kvrc = iser_handle_numerical(nvp, num_val, ikvx,
6809162SPeter.Dunlap@Sun.COM ISER_MAX_OUTSTANDING_UNEXPECTED_PDUS_MIN,
6819162SPeter.Dunlap@Sun.COM ISER_MAX_OUTSTANDING_UNEXPECTED_PDUS_MAX,
6829162SPeter.Dunlap@Sun.COM ISER_MAX_OUTSTANDING_UNEXPECTED_PDUS_IMPL_MAX,
6839162SPeter.Dunlap@Sun.COM request_nvl, response_nvl, negotiated_nvl);
6849162SPeter.Dunlap@Sun.COM break;
6859162SPeter.Dunlap@Sun.COM default:
6869162SPeter.Dunlap@Sun.COM /*
6879162SPeter.Dunlap@Sun.COM * All other keys, including invalid keys, will be
6889162SPeter.Dunlap@Sun.COM * handled at the client layer.
6899162SPeter.Dunlap@Sun.COM */
6909162SPeter.Dunlap@Sun.COM kvrc = KV_HANDLED;
6919162SPeter.Dunlap@Sun.COM break;
6929162SPeter.Dunlap@Sun.COM }
6939162SPeter.Dunlap@Sun.COM
6949162SPeter.Dunlap@Sun.COM return (kvrc);
6959162SPeter.Dunlap@Sun.COM }
6969162SPeter.Dunlap@Sun.COM
6979162SPeter.Dunlap@Sun.COM
6989162SPeter.Dunlap@Sun.COM /* Validate a proposed boolean value, and set the alternate if necessary */
6999162SPeter.Dunlap@Sun.COM static kv_status_t
iser_handle_boolean(nvpair_t * nvp,boolean_t value,const idm_kv_xlate_t * ikvx,boolean_t iser_value,nvlist_t * request_nvl,nvlist_t * response_nvl,nvlist_t * negotiated_nvl)7009162SPeter.Dunlap@Sun.COM iser_handle_boolean(nvpair_t *nvp, boolean_t value, const idm_kv_xlate_t *ikvx,
7019162SPeter.Dunlap@Sun.COM boolean_t iser_value, nvlist_t *request_nvl, nvlist_t *response_nvl,
7029162SPeter.Dunlap@Sun.COM nvlist_t *negotiated_nvl)
7039162SPeter.Dunlap@Sun.COM {
704*12935SPeter.Gill@Sun.COM kv_status_t kvrc = KV_UNHANDLED;
7059162SPeter.Dunlap@Sun.COM int nvrc;
706*12935SPeter.Gill@Sun.COM boolean_t respond = B_FALSE;
7079162SPeter.Dunlap@Sun.COM
7089162SPeter.Dunlap@Sun.COM if (value != iser_value) {
7099162SPeter.Dunlap@Sun.COM /*
7109162SPeter.Dunlap@Sun.COM * Respond back to initiator with our value, and
7119162SPeter.Dunlap@Sun.COM * set the return value to unset the transit bit.
7129162SPeter.Dunlap@Sun.COM */
7139162SPeter.Dunlap@Sun.COM value = iser_value;
714*12935SPeter.Gill@Sun.COM nvrc = nvlist_add_boolean_value(negotiated_nvl,
715*12935SPeter.Gill@Sun.COM ikvx->ik_key_name, value);
716*12935SPeter.Gill@Sun.COM if (nvrc == 0) {
717*12935SPeter.Gill@Sun.COM kvrc = KV_HANDLED_NO_TRANSIT;
718*12935SPeter.Gill@Sun.COM respond = B_TRUE;
719*12935SPeter.Gill@Sun.COM }
7209162SPeter.Dunlap@Sun.COM
7219162SPeter.Dunlap@Sun.COM } else {
7229162SPeter.Dunlap@Sun.COM /* Add this to our negotiated values */
7239162SPeter.Dunlap@Sun.COM nvrc = nvlist_add_nvpair(negotiated_nvl, nvp);
7249162SPeter.Dunlap@Sun.COM /* Respond if this is not a declarative */
7259162SPeter.Dunlap@Sun.COM respond = (ikvx->ik_declarative == B_FALSE);
7269162SPeter.Dunlap@Sun.COM }
7279162SPeter.Dunlap@Sun.COM
7289162SPeter.Dunlap@Sun.COM /* Response of Simple-value Negotiation */
7299162SPeter.Dunlap@Sun.COM if (nvrc == 0 && respond) {
7309162SPeter.Dunlap@Sun.COM nvrc = nvlist_add_boolean_value(response_nvl,
7319162SPeter.Dunlap@Sun.COM ikvx->ik_key_name, value);
7329162SPeter.Dunlap@Sun.COM /* Remove from the request (we've handled it) */
7339162SPeter.Dunlap@Sun.COM (void) nvlist_remove_all(request_nvl, ikvx->ik_key_name);
7349162SPeter.Dunlap@Sun.COM }
7359162SPeter.Dunlap@Sun.COM
7369162SPeter.Dunlap@Sun.COM if (kvrc == KV_HANDLED_NO_TRANSIT) {
7379162SPeter.Dunlap@Sun.COM return (kvrc);
7389162SPeter.Dunlap@Sun.COM }
7399162SPeter.Dunlap@Sun.COM
7409162SPeter.Dunlap@Sun.COM return (idm_nvstat_to_kvstat(nvrc));
7419162SPeter.Dunlap@Sun.COM }
7429162SPeter.Dunlap@Sun.COM
7439162SPeter.Dunlap@Sun.COM /*
7449162SPeter.Dunlap@Sun.COM * Validate a proposed value against the iSER and/or iSCSI RFC's minimum and
7459162SPeter.Dunlap@Sun.COM * maximum values, and set an alternate, if necessary. Note that the value
7469162SPeter.Dunlap@Sun.COM * 'iser_max_value" represents our implementation maximum (typically the max).
7479162SPeter.Dunlap@Sun.COM */
7489162SPeter.Dunlap@Sun.COM static kv_status_t
iser_handle_numerical(nvpair_t * nvp,uint64_t value,const idm_kv_xlate_t * ikvx,uint64_t min_value,uint64_t max_value,uint64_t iser_max_value,nvlist_t * request_nvl,nvlist_t * response_nvl,nvlist_t * negotiated_nvl)7499162SPeter.Dunlap@Sun.COM iser_handle_numerical(nvpair_t *nvp, uint64_t value, const idm_kv_xlate_t *ikvx,
7509162SPeter.Dunlap@Sun.COM uint64_t min_value, uint64_t max_value, uint64_t iser_max_value,
7519162SPeter.Dunlap@Sun.COM nvlist_t *request_nvl, nvlist_t *response_nvl, nvlist_t *negotiated_nvl)
7529162SPeter.Dunlap@Sun.COM {
753*12935SPeter.Gill@Sun.COM kv_status_t kvrc = KV_UNHANDLED;
7549162SPeter.Dunlap@Sun.COM int nvrc;
755*12935SPeter.Gill@Sun.COM boolean_t respond = B_FALSE;
7569162SPeter.Dunlap@Sun.COM
7579162SPeter.Dunlap@Sun.COM /* Validate against standard */
7589162SPeter.Dunlap@Sun.COM if ((value < min_value) || (value > max_value)) {
7599162SPeter.Dunlap@Sun.COM kvrc = KV_VALUE_ERROR;
7609162SPeter.Dunlap@Sun.COM } else {
7619162SPeter.Dunlap@Sun.COM if (value > iser_max_value) {
7629162SPeter.Dunlap@Sun.COM /*
7639162SPeter.Dunlap@Sun.COM * Respond back to initiator with our value, and
7649162SPeter.Dunlap@Sun.COM * set the return value to unset the transit bit.
7659162SPeter.Dunlap@Sun.COM */
7669162SPeter.Dunlap@Sun.COM value = iser_max_value;
767*12935SPeter.Gill@Sun.COM nvrc = nvlist_add_uint64(negotiated_nvl,
768*12935SPeter.Gill@Sun.COM ikvx->ik_key_name, value);
769*12935SPeter.Gill@Sun.COM if (nvrc == 0) {
770*12935SPeter.Gill@Sun.COM kvrc = KV_HANDLED_NO_TRANSIT;
771*12935SPeter.Gill@Sun.COM respond = B_TRUE;
772*12935SPeter.Gill@Sun.COM }
7739162SPeter.Dunlap@Sun.COM } else {
7749162SPeter.Dunlap@Sun.COM /* Add this to our negotiated values */
7759162SPeter.Dunlap@Sun.COM nvrc = nvlist_add_nvpair(negotiated_nvl, nvp);
7769162SPeter.Dunlap@Sun.COM /* Respond if this is not a declarative */
7779162SPeter.Dunlap@Sun.COM respond = (ikvx->ik_declarative == B_FALSE);
7789162SPeter.Dunlap@Sun.COM }
7799162SPeter.Dunlap@Sun.COM
7809162SPeter.Dunlap@Sun.COM /* Response of Simple-value Negotiation */
7819162SPeter.Dunlap@Sun.COM if (nvrc == 0 && respond) {
7829162SPeter.Dunlap@Sun.COM nvrc = nvlist_add_uint64(response_nvl,
7839162SPeter.Dunlap@Sun.COM ikvx->ik_key_name, value);
7849162SPeter.Dunlap@Sun.COM /* Remove from the request (we've handled it) */
7859162SPeter.Dunlap@Sun.COM (void) nvlist_remove_all(request_nvl,
7869162SPeter.Dunlap@Sun.COM ikvx->ik_key_name);
7879162SPeter.Dunlap@Sun.COM }
7889162SPeter.Dunlap@Sun.COM }
7899162SPeter.Dunlap@Sun.COM
7909162SPeter.Dunlap@Sun.COM if (kvrc == KV_HANDLED_NO_TRANSIT) {
7919162SPeter.Dunlap@Sun.COM return (kvrc);
7929162SPeter.Dunlap@Sun.COM }
7939162SPeter.Dunlap@Sun.COM
7949162SPeter.Dunlap@Sun.COM return (idm_nvstat_to_kvstat(nvrc));
7959162SPeter.Dunlap@Sun.COM }
7969162SPeter.Dunlap@Sun.COM
7979162SPeter.Dunlap@Sun.COM /*
79810261SCharles.Ting@Sun.COM * iser_declare_key_values() declares the declarative key values for
79910261SCharles.Ting@Sun.COM * this connection.
80010261SCharles.Ting@Sun.COM */
80110261SCharles.Ting@Sun.COM /* ARGSUSED */
80210261SCharles.Ting@Sun.COM static kv_status_t
iser_declare_key_values(idm_conn_t * ic,nvlist_t * config_nvl,nvlist_t * outgoing_nvl)80310261SCharles.Ting@Sun.COM iser_declare_key_values(idm_conn_t *ic, nvlist_t *config_nvl,
80410261SCharles.Ting@Sun.COM nvlist_t *outgoing_nvl)
80510261SCharles.Ting@Sun.COM {
80610261SCharles.Ting@Sun.COM kv_status_t kvrc;
80710712SCharles.Ting@Sun.COM int nvrc = 0;
80810712SCharles.Ting@Sun.COM int rc;
80910261SCharles.Ting@Sun.COM uint64_t uint64_val;
81010261SCharles.Ting@Sun.COM
81110712SCharles.Ting@Sun.COM if ((rc = nvlist_lookup_uint64(config_nvl,
81210261SCharles.Ting@Sun.COM ISER_KV_KEY_NAME_MAX_OUTSTANDING_PDU, &uint64_val)) != ENOENT) {
81310712SCharles.Ting@Sun.COM ASSERT(rc == 0);
81410261SCharles.Ting@Sun.COM if (outgoing_nvl) {
81510261SCharles.Ting@Sun.COM nvrc = nvlist_add_uint64(outgoing_nvl,
81610261SCharles.Ting@Sun.COM ISER_KV_KEY_NAME_MAX_OUTSTANDING_PDU, uint64_val);
81710261SCharles.Ting@Sun.COM }
81810261SCharles.Ting@Sun.COM }
81910261SCharles.Ting@Sun.COM kvrc = idm_nvstat_to_kvstat(nvrc);
82010261SCharles.Ting@Sun.COM return (kvrc);
82110261SCharles.Ting@Sun.COM }
82210261SCharles.Ting@Sun.COM
82310261SCharles.Ting@Sun.COM /*
8249162SPeter.Dunlap@Sun.COM * iser_notice_key_values() activates the negotiated key values for
8259162SPeter.Dunlap@Sun.COM * this connection.
8269162SPeter.Dunlap@Sun.COM */
8279162SPeter.Dunlap@Sun.COM static void
iser_notice_key_values(idm_conn_t * ic,nvlist_t * negotiated_nvl)8289162SPeter.Dunlap@Sun.COM iser_notice_key_values(idm_conn_t *ic, nvlist_t *negotiated_nvl)
8299162SPeter.Dunlap@Sun.COM {
8309162SPeter.Dunlap@Sun.COM iser_conn_t *iser_conn;
8319162SPeter.Dunlap@Sun.COM boolean_t boolean_val;
8329162SPeter.Dunlap@Sun.COM uint64_t uint64_val;
8339162SPeter.Dunlap@Sun.COM int nvrc;
83412485SPeter.Gill@Sun.COM char *digest_choice_string;
8359162SPeter.Dunlap@Sun.COM
8369162SPeter.Dunlap@Sun.COM iser_conn = (iser_conn_t *)ic->ic_transport_private;
8379162SPeter.Dunlap@Sun.COM
8389162SPeter.Dunlap@Sun.COM /*
8399162SPeter.Dunlap@Sun.COM * Validate the final negotiated operational parameters,
8409162SPeter.Dunlap@Sun.COM * and save a copy.
8419162SPeter.Dunlap@Sun.COM */
84212485SPeter.Gill@Sun.COM if ((nvrc = nvlist_lookup_string(negotiated_nvl,
84312485SPeter.Gill@Sun.COM "HeaderDigest", &digest_choice_string)) != ENOENT) {
8449162SPeter.Dunlap@Sun.COM ASSERT(nvrc == 0);
84512485SPeter.Gill@Sun.COM
84612485SPeter.Gill@Sun.COM /*
84712485SPeter.Gill@Sun.COM * Per the iSER RFC, override the negotiated value with "None"
84812485SPeter.Gill@Sun.COM */
84912485SPeter.Gill@Sun.COM iser_conn->ic_op_params.op_header_digest = B_FALSE;
8509162SPeter.Dunlap@Sun.COM }
8519162SPeter.Dunlap@Sun.COM
85212485SPeter.Gill@Sun.COM if ((nvrc = nvlist_lookup_string(negotiated_nvl,
85312485SPeter.Gill@Sun.COM "DataDigest", &digest_choice_string)) != ENOENT) {
8549162SPeter.Dunlap@Sun.COM ASSERT(nvrc == 0);
85512485SPeter.Gill@Sun.COM
85612485SPeter.Gill@Sun.COM /*
85712485SPeter.Gill@Sun.COM * Per the iSER RFC, override the negotiated value with "None"
85812485SPeter.Gill@Sun.COM */
85912485SPeter.Gill@Sun.COM iser_conn->ic_op_params.op_data_digest = B_FALSE;
8609162SPeter.Dunlap@Sun.COM }
8619162SPeter.Dunlap@Sun.COM
8629162SPeter.Dunlap@Sun.COM if ((nvrc = nvlist_lookup_boolean_value(negotiated_nvl,
8639162SPeter.Dunlap@Sun.COM "RDMAExtensions", &boolean_val)) != ENOENT) {
8649162SPeter.Dunlap@Sun.COM ASSERT(nvrc == 0);
8659162SPeter.Dunlap@Sun.COM iser_conn->ic_op_params.op_rdma_extensions = boolean_val;
8669162SPeter.Dunlap@Sun.COM }
8679162SPeter.Dunlap@Sun.COM
8689162SPeter.Dunlap@Sun.COM if ((nvrc = nvlist_lookup_boolean_value(negotiated_nvl,
8699162SPeter.Dunlap@Sun.COM "OFMarker", &boolean_val)) != ENOENT) {
8709162SPeter.Dunlap@Sun.COM ASSERT(nvrc == 0);
87112485SPeter.Gill@Sun.COM /*
87212485SPeter.Gill@Sun.COM * Per the iSER RFC, override the negotiated value with "No"
87312485SPeter.Gill@Sun.COM */
87412485SPeter.Gill@Sun.COM iser_conn->ic_op_params.op_ofmarker = B_FALSE;
8759162SPeter.Dunlap@Sun.COM }
8769162SPeter.Dunlap@Sun.COM
8779162SPeter.Dunlap@Sun.COM if ((nvrc = nvlist_lookup_boolean_value(negotiated_nvl,
8789162SPeter.Dunlap@Sun.COM "IFMarker", &boolean_val)) != ENOENT) {
8799162SPeter.Dunlap@Sun.COM ASSERT(nvrc == 0);
88012485SPeter.Gill@Sun.COM /*
88112485SPeter.Gill@Sun.COM * Per the iSER RFC, override the negotiated value with "No"
88212485SPeter.Gill@Sun.COM */
88312485SPeter.Gill@Sun.COM iser_conn->ic_op_params.op_ifmarker = B_FALSE;
8849162SPeter.Dunlap@Sun.COM }
8859162SPeter.Dunlap@Sun.COM
8869162SPeter.Dunlap@Sun.COM if ((nvrc = nvlist_lookup_uint64(negotiated_nvl,
8879162SPeter.Dunlap@Sun.COM "TargetRecvDataSegmentLength", &uint64_val)) != ENOENT) {
8889162SPeter.Dunlap@Sun.COM ASSERT(nvrc == 0);
8899162SPeter.Dunlap@Sun.COM iser_conn->ic_op_params.op_target_recv_data_segment_length =
8909162SPeter.Dunlap@Sun.COM uint64_val;
8919162SPeter.Dunlap@Sun.COM }
8929162SPeter.Dunlap@Sun.COM
8939162SPeter.Dunlap@Sun.COM if ((nvrc = nvlist_lookup_uint64(negotiated_nvl,
8949162SPeter.Dunlap@Sun.COM "InitiatorRecvDataSegmentLength", &uint64_val)) != ENOENT) {
8959162SPeter.Dunlap@Sun.COM ASSERT(nvrc == 0);
8969162SPeter.Dunlap@Sun.COM iser_conn->ic_op_params.op_initiator_recv_data_segment_length =
8979162SPeter.Dunlap@Sun.COM uint64_val;
8989162SPeter.Dunlap@Sun.COM }
8999162SPeter.Dunlap@Sun.COM
9009162SPeter.Dunlap@Sun.COM if ((nvrc = nvlist_lookup_uint64(negotiated_nvl,
9019162SPeter.Dunlap@Sun.COM "MaxOutstandingUnexpectedPDUs", &uint64_val)) != ENOENT) {
9029162SPeter.Dunlap@Sun.COM ASSERT(nvrc == 0);
9039162SPeter.Dunlap@Sun.COM iser_conn->ic_op_params.op_max_outstanding_unexpected_pdus =
9049162SPeter.Dunlap@Sun.COM uint64_val;
9059162SPeter.Dunlap@Sun.COM }
9069162SPeter.Dunlap@Sun.COM
9079162SPeter.Dunlap@Sun.COM /* Test boolean values which are required by RFC 5046 */
9089162SPeter.Dunlap@Sun.COM #ifdef ISER_DEBUG
9099162SPeter.Dunlap@Sun.COM ASSERT(iser_conn->ic_op_params.op_rdma_extensions == B_TRUE);
9109162SPeter.Dunlap@Sun.COM ASSERT(iser_conn->ic_op_params.op_header_digest == B_FALSE);
9119162SPeter.Dunlap@Sun.COM ASSERT(iser_conn->ic_op_params.op_data_digest == B_FALSE);
9129162SPeter.Dunlap@Sun.COM ASSERT(iser_conn->ic_op_params.op_ofmarker == B_FALSE);
9139162SPeter.Dunlap@Sun.COM ASSERT(iser_conn->ic_op_params.op_ifmarker == B_FALSE);
9149162SPeter.Dunlap@Sun.COM #endif
9159162SPeter.Dunlap@Sun.COM }
9169162SPeter.Dunlap@Sun.COM
9179162SPeter.Dunlap@Sun.COM
9189162SPeter.Dunlap@Sun.COM /*
9199162SPeter.Dunlap@Sun.COM * iser_conn_is_capable() verifies that the passed connection is provided
9209162SPeter.Dunlap@Sun.COM * for by an iSER-capable link.
9219162SPeter.Dunlap@Sun.COM * NOTE: When utilizing InfiniBand RC as an RCaP, this routine will check
9229162SPeter.Dunlap@Sun.COM * if the link is on IPoIB. This only indicates a chance that the link is
9239162SPeter.Dunlap@Sun.COM * on an RCaP, and thus iSER-capable, since we may be running on an IB-Eth
9249162SPeter.Dunlap@Sun.COM * gateway, or other IB but non-RCaP link. Rather than fully establishing the
9259162SPeter.Dunlap@Sun.COM * link to verify RCaP here, we instead will return B_TRUE
9269162SPeter.Dunlap@Sun.COM * indicating the link is iSER-capable, if the link is IPoIB. If then in
9279162SPeter.Dunlap@Sun.COM * iser_ini_conn_create() the link proves not be RCaP, IDM will fall back
9289162SPeter.Dunlap@Sun.COM * to using the IDM Sockets transport.
9299162SPeter.Dunlap@Sun.COM */
9309162SPeter.Dunlap@Sun.COM /* ARGSUSED */
9319162SPeter.Dunlap@Sun.COM static boolean_t
iser_conn_is_capable(idm_conn_req_t * cr,idm_transport_caps_t * caps)9329162SPeter.Dunlap@Sun.COM iser_conn_is_capable(idm_conn_req_t *cr, idm_transport_caps_t *caps)
9339162SPeter.Dunlap@Sun.COM {
9349162SPeter.Dunlap@Sun.COM /* A NULL value for laddr indicates implicit source */
9359162SPeter.Dunlap@Sun.COM return (iser_path_exists(NULL, &cr->cr_ini_dst_addr));
9369162SPeter.Dunlap@Sun.COM }
9379162SPeter.Dunlap@Sun.COM
9389162SPeter.Dunlap@Sun.COM /*
9399162SPeter.Dunlap@Sun.COM * iser_pdu_tx() transmits a Control PDU via the iSER channel. We pull the
9409162SPeter.Dunlap@Sun.COM * channel out of the idm_conn_t passed in, and pass it and the pdu to the
9419162SPeter.Dunlap@Sun.COM * iser_xfer routine.
9429162SPeter.Dunlap@Sun.COM */
9439162SPeter.Dunlap@Sun.COM static void
iser_pdu_tx(idm_conn_t * ic,idm_pdu_t * pdu)9449162SPeter.Dunlap@Sun.COM iser_pdu_tx(idm_conn_t *ic, idm_pdu_t *pdu)
9459162SPeter.Dunlap@Sun.COM {
9469162SPeter.Dunlap@Sun.COM iser_conn_t *iser_conn;
9479162SPeter.Dunlap@Sun.COM iser_status_t iser_status;
9489162SPeter.Dunlap@Sun.COM
9499162SPeter.Dunlap@Sun.COM iser_conn = (iser_conn_t *)ic->ic_transport_private;
9509162SPeter.Dunlap@Sun.COM
9519162SPeter.Dunlap@Sun.COM iser_status = iser_xfer_ctrlpdu(iser_conn->ic_chan, pdu);
9529162SPeter.Dunlap@Sun.COM if (iser_status != ISER_STATUS_SUCCESS) {
9539162SPeter.Dunlap@Sun.COM ISER_LOG(CE_WARN, "iser_pdu_tx: failed iser_xfer_ctrlpdu: "
9549162SPeter.Dunlap@Sun.COM "ic (0x%p) pdu (0x%p)", (void *) ic, (void *) pdu);
9559162SPeter.Dunlap@Sun.COM /* Fail this PDU transmission */
9569162SPeter.Dunlap@Sun.COM idm_pdu_complete(pdu, IDM_STATUS_FAIL);
9579162SPeter.Dunlap@Sun.COM }
9589162SPeter.Dunlap@Sun.COM
9599162SPeter.Dunlap@Sun.COM /*
9609162SPeter.Dunlap@Sun.COM * We successfully posted this PDU for transmission.
9619162SPeter.Dunlap@Sun.COM * The completion handler will invoke idm_pdu_complete()
9629162SPeter.Dunlap@Sun.COM * with the completion status. See iser_cq.c for more
9639162SPeter.Dunlap@Sun.COM * information.
9649162SPeter.Dunlap@Sun.COM */
9659162SPeter.Dunlap@Sun.COM }
9669162SPeter.Dunlap@Sun.COM
9679162SPeter.Dunlap@Sun.COM /*
9689162SPeter.Dunlap@Sun.COM * iser_buf_tx_to_ini() transmits the data buffer encoded in idb to the
9699162SPeter.Dunlap@Sun.COM * initiator to fulfill SCSI Read commands. An iser_xfer routine is invoked
9709162SPeter.Dunlap@Sun.COM * to implement the RDMA operations.
9719162SPeter.Dunlap@Sun.COM *
9729162SPeter.Dunlap@Sun.COM * Caller holds idt->idt_mutex.
9739162SPeter.Dunlap@Sun.COM */
9749162SPeter.Dunlap@Sun.COM static idm_status_t
iser_buf_tx_to_ini(idm_task_t * idt,idm_buf_t * idb)9759162SPeter.Dunlap@Sun.COM iser_buf_tx_to_ini(idm_task_t *idt, idm_buf_t *idb)
9769162SPeter.Dunlap@Sun.COM {
9779162SPeter.Dunlap@Sun.COM iser_status_t iser_status;
9789162SPeter.Dunlap@Sun.COM idm_status_t idm_status = IDM_STATUS_SUCCESS;
9799162SPeter.Dunlap@Sun.COM
9809162SPeter.Dunlap@Sun.COM ASSERT(mutex_owned(&idt->idt_mutex));
9819162SPeter.Dunlap@Sun.COM
9829162SPeter.Dunlap@Sun.COM iser_status = iser_xfer_buf_to_ini(idt, idb);
9839162SPeter.Dunlap@Sun.COM
9849162SPeter.Dunlap@Sun.COM if (iser_status != ISER_STATUS_SUCCESS) {
9859162SPeter.Dunlap@Sun.COM ISER_LOG(CE_WARN, "iser_buf_tx_to_ini: failed "
9869162SPeter.Dunlap@Sun.COM "iser_xfer_buf_to_ini: idt (0x%p) idb (0x%p)",
9879162SPeter.Dunlap@Sun.COM (void *) idt, (void *) idb);
98811180SPriya.Krishnan@Sun.COM idm_buf_tx_to_ini_done(idt, idb, IDM_STATUS_ABORTED);
98911180SPriya.Krishnan@Sun.COM return (IDM_STATUS_FAIL);
9909162SPeter.Dunlap@Sun.COM }
9919162SPeter.Dunlap@Sun.COM
9929162SPeter.Dunlap@Sun.COM /*
9939162SPeter.Dunlap@Sun.COM * iSCSIt's Data Completion Notify callback is invoked from
9949162SPeter.Dunlap@Sun.COM * the Work Request Send completion Handler
9959162SPeter.Dunlap@Sun.COM */
9969162SPeter.Dunlap@Sun.COM
9979162SPeter.Dunlap@Sun.COM mutex_exit(&idt->idt_mutex);
9989162SPeter.Dunlap@Sun.COM return (idm_status);
9999162SPeter.Dunlap@Sun.COM }
10009162SPeter.Dunlap@Sun.COM
10019162SPeter.Dunlap@Sun.COM /*
10029162SPeter.Dunlap@Sun.COM * iser_buf_tx_from_ini() transmits data from the initiator into the buffer
10039162SPeter.Dunlap@Sun.COM * in idb to fulfill SCSI Write commands. An iser_xfer routine is invoked
10049162SPeter.Dunlap@Sun.COM * to implement the RDMA operations.
10059162SPeter.Dunlap@Sun.COM *
10069162SPeter.Dunlap@Sun.COM * Caller holds idt->idt_mutex.
10079162SPeter.Dunlap@Sun.COM */
10089162SPeter.Dunlap@Sun.COM static idm_status_t
iser_buf_rx_from_ini(idm_task_t * idt,idm_buf_t * idb)10099162SPeter.Dunlap@Sun.COM iser_buf_rx_from_ini(idm_task_t *idt, idm_buf_t *idb)
10109162SPeter.Dunlap@Sun.COM {
10119162SPeter.Dunlap@Sun.COM iser_status_t iser_status;
10129162SPeter.Dunlap@Sun.COM idm_status_t idm_status = IDM_STATUS_SUCCESS;
10139162SPeter.Dunlap@Sun.COM
10149162SPeter.Dunlap@Sun.COM ASSERT(mutex_owned(&idt->idt_mutex));
10159162SPeter.Dunlap@Sun.COM
10169162SPeter.Dunlap@Sun.COM iser_status = iser_xfer_buf_from_ini(idt, idb);
10179162SPeter.Dunlap@Sun.COM
10189162SPeter.Dunlap@Sun.COM if (iser_status != ISER_STATUS_SUCCESS) {
101911180SPriya.Krishnan@Sun.COM ISER_LOG(CE_WARN, "iser_buf_rx_from_ini: failed "
102011180SPriya.Krishnan@Sun.COM "iser_xfer_buf_from_ini: idt (0x%p) idb (0x%p)",
10219162SPeter.Dunlap@Sun.COM (void *) idt, (void *) idb);
102211180SPriya.Krishnan@Sun.COM idm_buf_rx_from_ini_done(idt, idb, IDM_STATUS_ABORTED);
102311180SPriya.Krishnan@Sun.COM return (IDM_STATUS_FAIL);
10249162SPeter.Dunlap@Sun.COM }
10259162SPeter.Dunlap@Sun.COM
10269162SPeter.Dunlap@Sun.COM /*
10279162SPeter.Dunlap@Sun.COM * iSCSIt's Data Completion Notify callback is invoked from
10289162SPeter.Dunlap@Sun.COM * the Work Request Send completion Handler
10299162SPeter.Dunlap@Sun.COM */
10309162SPeter.Dunlap@Sun.COM
10319162SPeter.Dunlap@Sun.COM mutex_exit(&idt->idt_mutex);
10329162SPeter.Dunlap@Sun.COM return (idm_status);
10339162SPeter.Dunlap@Sun.COM }
10349162SPeter.Dunlap@Sun.COM
10359162SPeter.Dunlap@Sun.COM /*
10369162SPeter.Dunlap@Sun.COM * iser_buf_alloc() allocates a buffer and registers it with the IBTF for
10379162SPeter.Dunlap@Sun.COM * use with iSER. Each HCA has it's own kmem cache for establishing a pool
10389162SPeter.Dunlap@Sun.COM * of registered buffers, when once initially allocated, will remain
10399162SPeter.Dunlap@Sun.COM * registered with the HCA. This routine is invoked only on the target,
10409162SPeter.Dunlap@Sun.COM * where we have the requirement to pre-allocate buffers for the upper layers.
10419162SPeter.Dunlap@Sun.COM * Note: buflen is compared to ISER_DEFAULT_BUFLEN, and allocation is failed
10429162SPeter.Dunlap@Sun.COM * if the requested buflen is larger than our default.
10439162SPeter.Dunlap@Sun.COM */
10449162SPeter.Dunlap@Sun.COM /* ARGSUSED */
10459162SPeter.Dunlap@Sun.COM static idm_status_t
iser_buf_alloc(idm_buf_t * idb,uint64_t buflen)10469162SPeter.Dunlap@Sun.COM iser_buf_alloc(idm_buf_t *idb, uint64_t buflen)
10479162SPeter.Dunlap@Sun.COM {
10489162SPeter.Dunlap@Sun.COM iser_conn_t *iser_conn;
10499162SPeter.Dunlap@Sun.COM iser_hca_t *iser_hca;
10509162SPeter.Dunlap@Sun.COM iser_buf_t *iser_buf;
10519162SPeter.Dunlap@Sun.COM
10529162SPeter.Dunlap@Sun.COM if (buflen > ISER_DEFAULT_BUFLEN) {
10539162SPeter.Dunlap@Sun.COM return (IDM_STATUS_FAIL);
10549162SPeter.Dunlap@Sun.COM }
10559162SPeter.Dunlap@Sun.COM
10569162SPeter.Dunlap@Sun.COM iser_conn = (iser_conn_t *)idb->idb_ic->ic_transport_private;
10579162SPeter.Dunlap@Sun.COM iser_hca = iser_conn->ic_chan->ic_hca;
10589162SPeter.Dunlap@Sun.COM
10599162SPeter.Dunlap@Sun.COM /*
10609162SPeter.Dunlap@Sun.COM * Allocate a buffer from this HCA's cache. Once initialized, these
10619162SPeter.Dunlap@Sun.COM * will remain allocated and registered (see above).
10629162SPeter.Dunlap@Sun.COM */
10639162SPeter.Dunlap@Sun.COM iser_buf = kmem_cache_alloc(iser_hca->iser_buf_cache, KM_NOSLEEP);
10649162SPeter.Dunlap@Sun.COM if (iser_buf == NULL) {
10659162SPeter.Dunlap@Sun.COM ISER_LOG(CE_NOTE, "iser_buf_alloc: alloc failed");
10669162SPeter.Dunlap@Sun.COM return (IDM_STATUS_FAIL);
10679162SPeter.Dunlap@Sun.COM }
10689162SPeter.Dunlap@Sun.COM
10699162SPeter.Dunlap@Sun.COM /* Set the allocated data buffer pointer in the IDM buf handle */
10709162SPeter.Dunlap@Sun.COM idb->idb_buf = iser_buf->buf;
10719162SPeter.Dunlap@Sun.COM
10729162SPeter.Dunlap@Sun.COM /* Set the private buf and reg handles in the IDM buf handle */
10739162SPeter.Dunlap@Sun.COM idb->idb_buf_private = (void *)iser_buf;
10749162SPeter.Dunlap@Sun.COM idb->idb_reg_private = (void *)iser_buf->iser_mr;
10759162SPeter.Dunlap@Sun.COM
10769162SPeter.Dunlap@Sun.COM return (IDM_STATUS_SUCCESS);
10779162SPeter.Dunlap@Sun.COM }
10789162SPeter.Dunlap@Sun.COM
10799162SPeter.Dunlap@Sun.COM /*
10809162SPeter.Dunlap@Sun.COM * iser_buf_free() frees the buffer handle passed in. Note that the cached
10819162SPeter.Dunlap@Sun.COM * kmem object has an HCA-registered buffer in it which will not be freed.
10829162SPeter.Dunlap@Sun.COM * This allows us to build up a cache of pre-allocated and registered
10839162SPeter.Dunlap@Sun.COM * buffers for use on the target.
10849162SPeter.Dunlap@Sun.COM */
10859162SPeter.Dunlap@Sun.COM static void
iser_buf_free(idm_buf_t * buf)10869162SPeter.Dunlap@Sun.COM iser_buf_free(idm_buf_t *buf)
10879162SPeter.Dunlap@Sun.COM {
10889162SPeter.Dunlap@Sun.COM iser_buf_t *iser_buf;
10899162SPeter.Dunlap@Sun.COM
10909162SPeter.Dunlap@Sun.COM iser_buf = buf->idb_buf_private;
10919162SPeter.Dunlap@Sun.COM kmem_cache_free(iser_buf->cache, iser_buf);
10929162SPeter.Dunlap@Sun.COM }
10939162SPeter.Dunlap@Sun.COM
10949162SPeter.Dunlap@Sun.COM /*
10959162SPeter.Dunlap@Sun.COM * iser_buf_setup() is invoked on the initiator in order to register memory
10969162SPeter.Dunlap@Sun.COM * on demand for use with the iSER layer.
10979162SPeter.Dunlap@Sun.COM */
10989162SPeter.Dunlap@Sun.COM static idm_status_t
iser_buf_setup(idm_buf_t * idb)10999162SPeter.Dunlap@Sun.COM iser_buf_setup(idm_buf_t *idb)
11009162SPeter.Dunlap@Sun.COM {
11019162SPeter.Dunlap@Sun.COM iser_conn_t *iser_conn;
11029162SPeter.Dunlap@Sun.COM iser_chan_t *iser_chan;
11039162SPeter.Dunlap@Sun.COM iser_hca_t *iser_hca;
11049162SPeter.Dunlap@Sun.COM iser_buf_t *iser_buf;
11059162SPeter.Dunlap@Sun.COM int status;
11069162SPeter.Dunlap@Sun.COM
11079162SPeter.Dunlap@Sun.COM ASSERT(idb->idb_buf != NULL);
11089162SPeter.Dunlap@Sun.COM
11099162SPeter.Dunlap@Sun.COM iser_conn = (iser_conn_t *)idb->idb_ic->ic_transport_private;
11109162SPeter.Dunlap@Sun.COM ASSERT(iser_conn != NULL);
11119162SPeter.Dunlap@Sun.COM
11129162SPeter.Dunlap@Sun.COM iser_hca = iser_conn->ic_chan->ic_hca;
11139162SPeter.Dunlap@Sun.COM
11149162SPeter.Dunlap@Sun.COM iser_chan = iser_conn->ic_chan;
11159162SPeter.Dunlap@Sun.COM ASSERT(iser_chan != NULL);
11169162SPeter.Dunlap@Sun.COM
11179162SPeter.Dunlap@Sun.COM /*
11189162SPeter.Dunlap@Sun.COM * Memory registration is known to be slow, so for small
11199162SPeter.Dunlap@Sun.COM * transfers, use pre-registered memory buffers and just
11209162SPeter.Dunlap@Sun.COM * copy the data into/from them at the appropriate time
11219162SPeter.Dunlap@Sun.COM */
11229162SPeter.Dunlap@Sun.COM if (idb->idb_buflen < ISER_BCOPY_THRESHOLD) {
11239162SPeter.Dunlap@Sun.COM iser_buf =
11249162SPeter.Dunlap@Sun.COM kmem_cache_alloc(iser_hca->iser_buf_cache, KM_NOSLEEP);
11259162SPeter.Dunlap@Sun.COM
11269162SPeter.Dunlap@Sun.COM if (iser_buf == NULL) {
11279162SPeter.Dunlap@Sun.COM
11289162SPeter.Dunlap@Sun.COM /* Fail over to dynamic registration */
11299162SPeter.Dunlap@Sun.COM status = iser_reg_rdma_mem(iser_chan->ic_hca, idb);
11309162SPeter.Dunlap@Sun.COM idb->idb_bufalloc = B_FALSE;
11319162SPeter.Dunlap@Sun.COM return (status);
11329162SPeter.Dunlap@Sun.COM }
11339162SPeter.Dunlap@Sun.COM
11349162SPeter.Dunlap@Sun.COM /*
11359162SPeter.Dunlap@Sun.COM * Set the allocated data buffer pointer in the IDM buf handle
11369162SPeter.Dunlap@Sun.COM * Data is to be copied from/to this buffer using bcopy
11379162SPeter.Dunlap@Sun.COM */
11389162SPeter.Dunlap@Sun.COM idb->idb_bufptr = idb->idb_buf;
11399162SPeter.Dunlap@Sun.COM idb->idb_bufbcopy = B_TRUE;
11409162SPeter.Dunlap@Sun.COM
11419162SPeter.Dunlap@Sun.COM idb->idb_buf = iser_buf->buf;
11429162SPeter.Dunlap@Sun.COM
11439162SPeter.Dunlap@Sun.COM /* Set the private buf and reg handles in the IDM buf handle */
11449162SPeter.Dunlap@Sun.COM idb->idb_buf_private = (void *)iser_buf;
11459162SPeter.Dunlap@Sun.COM idb->idb_reg_private = (void *)iser_buf->iser_mr;
11469162SPeter.Dunlap@Sun.COM
11479162SPeter.Dunlap@Sun.COM /* Ensure bufalloc'd flag is set */
11489162SPeter.Dunlap@Sun.COM idb->idb_bufalloc = B_TRUE;
11499162SPeter.Dunlap@Sun.COM
11509162SPeter.Dunlap@Sun.COM return (IDM_STATUS_SUCCESS);
11519162SPeter.Dunlap@Sun.COM
11529162SPeter.Dunlap@Sun.COM } else {
11539162SPeter.Dunlap@Sun.COM
11549162SPeter.Dunlap@Sun.COM /* Dynamically register the memory passed in on the idb */
11559162SPeter.Dunlap@Sun.COM status = iser_reg_rdma_mem(iser_chan->ic_hca, idb);
11569162SPeter.Dunlap@Sun.COM
11579162SPeter.Dunlap@Sun.COM /* Ensure bufalloc'd flag is unset */
11589162SPeter.Dunlap@Sun.COM idb->idb_bufalloc = B_FALSE;
11599162SPeter.Dunlap@Sun.COM
11609162SPeter.Dunlap@Sun.COM return (status);
11619162SPeter.Dunlap@Sun.COM }
11629162SPeter.Dunlap@Sun.COM }
11639162SPeter.Dunlap@Sun.COM
11649162SPeter.Dunlap@Sun.COM /*
11659162SPeter.Dunlap@Sun.COM * iser_buf_teardown() is invoked on the initiator in order to register memory
11669162SPeter.Dunlap@Sun.COM * on demand for use with the iSER layer.
11679162SPeter.Dunlap@Sun.COM */
11689162SPeter.Dunlap@Sun.COM static void
iser_buf_teardown(idm_buf_t * idb)11699162SPeter.Dunlap@Sun.COM iser_buf_teardown(idm_buf_t *idb)
11709162SPeter.Dunlap@Sun.COM {
11719162SPeter.Dunlap@Sun.COM iser_conn_t *iser_conn;
11729162SPeter.Dunlap@Sun.COM
11739162SPeter.Dunlap@Sun.COM iser_conn = (iser_conn_t *)idb->idb_ic->ic_transport_private;
11749162SPeter.Dunlap@Sun.COM
11759162SPeter.Dunlap@Sun.COM /* Deregister the memory passed in on the idb */
11769162SPeter.Dunlap@Sun.COM iser_dereg_rdma_mem(iser_conn->ic_chan->ic_hca, idb);
11779162SPeter.Dunlap@Sun.COM }
1178