c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * CDDL HEADER START
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * The contents of this file are subject to the terms of the
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * Common Development and Distribution License (the "License").
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * You may not use this file except in compliance with the License.
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * or http://www.opensolaris.org/os/licensing.
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * See the License for the specific language governing permissions
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * and limitations under the License.
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * When distributing Covered Code, include this CDDL HEADER in each
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * If applicable, add the following below this CDDL HEADER, with the
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * fields enclosed by brackets "[]" replaced with your own identifying
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * information: Portions Copyright [yyyy] [name of copyright owner]
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * CDDL HEADER END
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * sol_cma is a part of sol_ofs misc module. This file
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * provides interfaces for supporting the communication
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * management API defined in "rdma_cm.h". In-Kernel
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * consumers of the "rdma_cm.h" API should link sol_ofs
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * misc module using :
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * Solaris uCMA (sol_ucma) driver is the current consumer for
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar/* Standard driver includes */
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar#include <sys/ib/clients/of/sol_ofs/sol_cma.h>
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#include <sys/ib/clients/of/sol_ofs/sol_kverb_impl.h>
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar/* Modload support */
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar "Solaris OFS Misc module"
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarstatic void sol_cma_add_dev(struct ib_device *);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarstatic void sol_cma_rem_dev(struct ib_device *);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarstatic llist_head_t sol_cma_dev_list = LLIST_HEAD_INIT(sol_cma_dev_list);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * Local functions defines.
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarint sol_cma_req_cmid_cmp(const void *p1, const void *p2);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarint sol_cma_cmid_cmp(const void *p1, const void *p2);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarint sol_cma_svc_cmp(const void *, const void *);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarstatic struct rdma_cm_id *cma_alloc_chan(rdma_cm_event_handler,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarstatic void cma_set_chan_state(sol_cma_chan_t *, cma_chan_state_t);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarstatic int cma_cas_chan_state(sol_cma_chan_t *, cma_chan_state_t,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarstatic void cma_free_listen_list(struct rdma_cm_id *);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarstatic void cma_destroy_id(struct rdma_cm_id *);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarstatic void cma_handle_nomore_events(sol_cma_chan_t *);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarcma_chan_state_t cma_get_chan_state(sol_cma_chan_t *);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarextern int ibcma_init_root_chan(sol_cma_chan_t *, sol_cma_glbl_listen_t *);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarextern int ibcma_fini_root_chan(sol_cma_chan_t *);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarextern void ibcma_copy_srv_hdl(sol_cma_chan_t *, sol_cma_glbl_listen_t *);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarextern int ibcma_fini_ep_chan(sol_cma_chan_t *);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarextern uint64_t ibcma_init_root_sid(sol_cma_chan_t *);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarextern void rdma_ib_destroy_id(struct rdma_cm_id *);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarextern int rdma_ib_bind_addr(struct rdma_cm_id *, struct sockaddr *);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarextern int rdma_ib_resolve_addr(struct rdma_cm_id *, struct sockaddr *,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar struct sockaddr *, int);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarextern int rdma_ib_resolve_route(struct rdma_cm_id *, int);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarextern int rdma_ib_init_qp_attr(struct rdma_cm_id *, struct ib_qp_attr *,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarextern int rdma_ib_connect(struct rdma_cm_id *, struct rdma_conn_param *);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarextern int rdma_ib_listen(struct rdma_cm_id *, int);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarextern int rdma_ib_accept(struct rdma_cm_id *, struct rdma_conn_param *);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarextern int rdma_ib_reject(struct rdma_cm_id *, const void *, uint8_t);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarextern int rdma_ib_disconnect(struct rdma_cm_id *);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarextern int rdma_ib_join_multicast(struct rdma_cm_id *, struct sockaddr *,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarextern void rdma_ib_leave_multicast(struct rdma_cm_id *, struct sockaddr *);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L5(sol_ofs_dbg_str, "_init()");
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_init(&sol_cma_glob_mutex, NULL, MUTEX_DRIVER, NULL);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_init(&sol_cma_dev_mutex, NULL, MUTEX_DRIVER, NULL);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar sol_cma_svc_cmp, sizeof (sol_cma_glbl_listen_t),
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar offsetof(sol_cma_glbl_listen_t, cma_listen_node));
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota sol_cma_ib_client = kmem_zalloc(sizeof (ib_client_t), KM_NOSLEEP);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "_init() - mem alloc failed");
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if ((err = ib_register_client(sol_cma_ib_client)) != 0) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "_init() ib_register_client() failed with err %d",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota kmem_free(sol_cma_ib_client, sizeof (ib_client_t));
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if ((err = mod_install(&sol_ofs_modlinkage)) != 0) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "_init() - mod_install() failed");
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota kmem_free(sol_cma_ib_client, sizeof (ib_client_t));
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L5(sol_ofs_dbg_str, "_init() - ret");
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L5(sol_ofs_dbg_str, "_fini()");
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (avl_numnodes(&sol_cma_glbl_listen_tree)) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L2(sol_ofs_dbg_str, "_fini - "
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar "listen CMIDs still active");
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if ((err = mod_remove(&sol_ofs_modlinkage)) != 0) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar "_fini: mod_remove failed");
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota kmem_free(sol_cma_ib_client, sizeof (ib_client_t));
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L5(sol_ofs_dbg_str, "_fini() - ret");
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar return (mod_info(&sol_ofs_modlinkage, modinfop));
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung /* Ptr in the global sol_cma_dev_list */
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung /* List of listeners for this device */
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar new_device = kmem_zalloc(sizeof (cma_device_t), KM_NOSLEEP);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L2(sol_ofs_dbg_str, "sol_cma_add_dev() "
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar "alloc failed!!");
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_init(&new_device->cma_mutex, NULL, MUTEX_DRIVER, NULL);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar llist_head_init(&new_device->cma_list, new_device);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ib_set_client_data(dev, sol_cma_ib_client, new_device);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar llist_add_tail(&new_device->cma_list, &sol_cma_dev_list);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota SOL_OFS_DPRINTF_L5(sol_ofs_dbg_str, "sol_rem_dev(%p)", dev);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rem_device = (cma_device_t *)ib_get_client_data(dev, sol_cma_ib_client);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L2(sol_ofs_dbg_str, "sol_cma_rem_dev() "
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar "NULL cma_dev!!");
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar rem_device->cma_dev_state = SOL_CMA_DEV_REM_IN_PROGRESS;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L3(sol_ofs_dbg_str, "sol_cma_rem_dev() "
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar "BUSY cma_dev!!");
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar entry = remove_genlist_head(&rem_device->cma_epchan_list);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar entry1 = ep_chanp->chan_listenp->listen_ep_root_entry;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar root_chanp = (sol_cma_chan_t *)ep_chanp->listen_root;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar delete_genlist(&root_chanp->chan_listenp->listen_list,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar kmem_free(ep_chanp, sizeof (sol_cma_chan_t));
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar entry = remove_genlist_head(&rem_device->cma_epchan_list);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar kmem_free(rem_device, sizeof (cma_device_t));
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (cma_devp->cma_device->node_guid != hca_guid)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (cma_devp->cma_dev_state == SOL_CMA_DEV_REM_IN_PROGRESS) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar "sol_cma_acquire_dev() - Device getting removed!!");
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarsol_cma_release_device(struct rdma_cm_id *id)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (cma_devp->cma_dev_state == SOL_CMA_DEV_REM_IN_PROGRESS &&
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar "sol_cma_release_dev() - Device free removed!!");
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarsol_cma_add_hca_list(sol_cma_chan_t *ep_chanp, ib_guid_t hca_guid)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "add_hca_list(%p, %llx)",
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if ((cma_devp->cma_device)->node_guid != hca_guid)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar ep_chanp->chan_listenp->listen_ep_dev_entry =
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar ep_chanp->chan_listenp->listen_ep_device = cma_devp->cma_device;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L2(sol_rdmacm_dbg_str, "add_hca_list(%p, %llx): "
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar "No matching HCA in list!!", ep_chanp, hca_guid);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * rdma_cm.h API functions.
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarrdma_create_id(rdma_cm_event_handler evt_hdlr, void *context,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "rdma_create_id(%p, %p, %x)",
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (ps != RDMA_PS_TCP && ps != RDMA_PS_UDP && ps != RDMA_PS_IPOIB) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar "rdma_create_id: unsupported protocol %x", ps);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar rdma_idp = cma_alloc_chan(evt_hdlr, context, ps);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarrdma_map_id2clnthdl(struct rdma_cm_id *rdma_idp, void *ib_client_hdl,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar sol_cma_chan_t *chanp = (sol_cma_chan_t *)rdma_idp;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar "rdma_map_id2clnthdl(%p, %p, %p)",
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar ASSERT(ib_client_hdl != NULL || iw_client_hdl != NULL);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarrdma_map_id2qphdl(struct rdma_cm_id *rdma_idp, void *qp_hdl)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar sol_cma_chan_t *chanp = (sol_cma_chan_t *)rdma_idp;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "rdma_mapid2qphdl(%p, %p)",
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "rdma_destroy_id(%p)", rdma_idp);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar root_chanp = (sol_cma_chan_t *)chanp->listen_root;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "rdma_destroy_id(%p), %p",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota chanp->chan_cmid_destroy_state |= SOL_CMA_CALLER_CMID_DESTROYED;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * Wait in destroy of CMID when rdma_resolve_addr() / rdma_listen()
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * rdma_resolve_route() API is in progress.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota while (chanp->chan_cmid_destroy_state & SOL_CMA_CALLER_API_PROGRESS)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota cv_wait(&chanp->chan_destroy_cv, &chanp->chan_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar /* Wait if Event is been notified to consumer */
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar while (chanp->chan_cmid_destroy_state & SOL_CMA_CALLER_EVENT_PROGRESS)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar cv_wait(&chanp->chan_destroy_cv, &chanp->chan_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (chanp->chan_listenp && chanp->chan_listenp->listen_is_root)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (root_chanp == NULL && is_root_cmid == 0)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * Skip Active side handling for passive CMIDs and listen CMID
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * for which REQ CMIDs have not been created.
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (is_passive || (is_root_cmid && chanp->chan_req_state !=
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "rdma_destroy_id: "
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar "Skipping passive %p, %x, %x", chanp->chan_listenp,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * destroy_id() called for listening CMID and there are REQ
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * CMIDs not yet notified. Reject such CMIDs and decrement
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "rdma_destroy_id: "
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar "not notified handling");
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar for (req_cmid_chan = (sol_cma_chan_t *)avl_first(
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar &chanp->chan_req_avl_tree); req_cmid_chan &&
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar chanp->chan_req_cnt; req_cmid_chan = next_chan) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * destroy_id() called for :
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * listening CMID and all REQ CMIDs destroy_id() called
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * REQ CMID and 1 more REQ CMID not yet destroyed.
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * wait till the CMID is completly destroyed.
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (is_root_cmid && chanp->chan_req_total_cnt == 0) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "rdma_destroy_id: "
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar "root idp waiting");
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar cma_set_chan_state(chanp, SOL_CMA_CHAN_DESTROY_WAIT);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar cv_wait(&chanp->chan_destroy_cv, &chanp->chan_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "rdma_destroy_id: "
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar "root_idp %p, cnt %x, state %x", root_chanp,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar root_chanp ? root_chanp->chan_req_total_cnt : 0,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar root_chanp ? cma_get_chan_state(root_chanp) : 0);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (root_chanp && root_chanp->chan_req_total_cnt == 1 &&
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar cma_get_chan_state(root_chanp) == SOL_CMA_CHAN_DESTROY_PENDING)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (is_root_cmid == 0 && state != SOL_CMA_CHAN_DISCONNECT &&
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * A connected CM ID has not been disconnected.
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * Call rdma_disconnect() to disconnect it.
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar "rdma_destroy_id(%p)- disconnect failed!!",
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (root_chanp && chanp->listen_root == NULL)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar chanp->listen_root = (struct rdma_cm_id *)root_chanp;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar "rdma_destroy_id(chanp %p, connect %x, ps %x)",
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar chanp, chanp->chan_connect_flag, rdma_idp->ps);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * No more callbacks are expected for this CMID.
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * Free this CMID.
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung SOL_CMA_CHAN_DISCONNECT && SOL_CMAID_CONNECTED(chanp)) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * CM ID was connected and disconnect is process.
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * Free of this CM ID is done for the DISCONNECT
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * notification for this CMID.
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar cma_set_chan_state(chanp, SOL_CMA_CHAN_DESTROY_PENDING);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar } else if (state != SOL_CMA_CHAN_DESTROY_PENDING) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar /* CM ID, not connected, just free it. */
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "rdma_destroy_id: ret");
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * State transitions for Address resolution :
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * Active Side (Client) :
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * 1. CREATE_ID-->BIND_ADDR-->RESOLVE_ADDR-->RESOLVE_ROUTE
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * Passive Side (Server) :
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * 2. CREATE_ID-->RESOLVE_ADDR-->RESOLVE_ROUTE
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * IF_ADDR_ANY can be passed as local address in RESOLVE_ADDR
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarrdma_bind_addr(struct rdma_cm_id *idp, struct sockaddr *addr)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "rdma_bind_addr(%p, %p)",
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar ret = cma_cas_chan_state(chanp, SOL_CMA_CHAN_IDLE, SOL_CMA_CHAN_BOUND);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar /* Copy the local address to rdma_id structure */
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar bcopy((void *)addr, (void *)&(addrp->src_addr),
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar sizeof (struct sockaddr));
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * First call rdma_ib_bind_addr() to bind this address.
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * Next call rdma_iw_bind_addr() to bind this address.
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * For IF_ADDR_ANY, IB address is given priority over
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ofs_clnt = (ofs_client_t *)sol_cma_ib_client->clnt_hdl;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (chanp->chan_ib_client_hdl && rdma_ib_bind_addr(idp, addr) == 0) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar "rdma_bind_addr: ret IB @");
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar } else if (chanp->chan_iw_client_hdl && rdma_iw_bind_addr(idp, addr)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar "rdma_bind_addr: ret iWARP @");
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar#endif /* IWARP_SUPPORT */
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar cma_set_chan_state(chanp, SOL_CMA_CHAN_IDLE);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L4(sol_rdmacm_dbg_str, "rdma_bind_addr: ret failure!");
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarrdma_resolve_addr(struct rdma_cm_id *idp, struct sockaddr *src_addr,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "rdma_resolve_addr(%p, %p, "
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar "%p, %x)", idp, src_addr, dst_addr, timeout_ms);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (state != SOL_CMA_CHAN_IDLE && state != SOL_CMA_CHAN_BOUND) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar "rdma_resolve_addr : invalid chan state %x", state);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "rdma_resolve_addr : CMID %p, destroy called", chanp);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota chanp->chan_cmid_destroy_state |= SOL_CMA_CALLER_API_PROGRESS;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (chanp->chan_xport_type == SOL_CMA_XPORT_NONE) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar bcopy((void *)src_addr, (void *)&(addrp->src_addr),
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar sizeof (struct sockaddr));
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar bcopy((void *)dst_addr, (void *)&(addrp->dst_addr),
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar sizeof (struct sockaddr));
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * First resolve this as an @ corresponding to IB fabric
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * if this fails, resolve this as an @ corresponding to iWARP
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ofs_clnt = (ofs_client_t *)sol_cma_ib_client->clnt_hdl;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (chanp->chan_ib_client_hdl && rdma_ib_resolve_addr(idp, src_addr,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar "rdma_resolve_addr: ret IB @");
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar } else if (chanp->chan_iw_client_hdl && rdma_iw_resolve_addr(idp,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar "rdma_resolve_addr: ret iWARP @");
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar#endif /* IWARP_SUPPORT */
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar "rdma_resolve_addr: Invalid @");
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "rdma_resolve_addr: ret 0");
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (0);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otastatic void cma_generate_event_sync(struct rdma_cm_id *,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota enum rdma_cm_event_type, int, struct rdma_conn_param *,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otacma_resolve_addr_callback(sol_cma_chan_t *chanp, int rc)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "cma_resolve_addr : CMID %p, destroy called", chanp);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar cma_set_chan_state(chanp, SOL_CMA_CHAN_ADDR_RESLVD);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * Generate RDMA_CM_EVENT_ADDR_RESOLVED event
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * This will result in RDMA_USER_CM_CMD_RESOLVE_ROUTE in
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota chanp->chan_cmid_destroy_state |= SOL_CMA_CALLER_EVENT_PROGRESS;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota cma_generate_event_sync((struct rdma_cm_id *)chanp, event, 0,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota chanp->chan_cmid_destroy_state &= ~SOL_CMA_CALLER_API_PROGRESS;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (chanp->chan_cmid_destroy_state & SOL_CMA_CALLER_CMID_DESTROYED)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarrdma_resolve_route(struct rdma_cm_id *idp, int timeout_ms)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "resolve_route(%p, %x)", idp,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (cma_cas_chan_state(chanp, SOL_CMA_CHAN_ADDR_RESLVD,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar "resolve_route: Invalid state");
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "rdma_resolve_route : CMID %p, destroy called", chanp);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota chanp->chan_cmid_destroy_state |= SOL_CMA_CALLER_API_PROGRESS;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * Generate RDMA_CM_EVENT_ROUTE_RESOLVED event
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * This will result in RDMA_USER_CM_CMD_RESOLVE_ROUTE in
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar cma_generate_event(idp, RDMA_CM_EVENT_ROUTE_RESOLVED, 0,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota chanp->chan_cmid_destroy_state &= ~SOL_CMA_CALLER_API_PROGRESS;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (chanp->chan_cmid_destroy_state & SOL_CMA_CALLER_CMID_DESTROYED)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "resolve_route: ret 0");
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * Connect or Listen request should be send after Route is resolved
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * Active Side (Client) :
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * 1. (State ROUTE_RESOLVED)-->CONNECT-->ACCEPT/REJECT-->DISCONNECT
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * -->DESTROY_ID-->close(9E)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * 2. Same as (1), DESTROY_ID without DISCONNECT
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * 3. Same as (1), close(9e) without DESTROY_ID.
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * Passive Side (Server) :
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * 4. (State ROUTE_RESOLVED)-->LISTEN->DISCONNECT
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * -->DESTROY_ID-->close(9E)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * 5. Same as (4), DESTROY_ID without DISCONNECT
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * 6. Same as (4), close(9e) without DESTROY_ID.
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarrdma_connect(struct rdma_cm_id *idp, struct rdma_conn_param *conn_param)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "rdma_connect(%p, %p)", idp,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (chanp->chan_xport_type == SOL_CMA_XPORT_NONE) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar "rdma_connect, Invalid Xport");
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (cma_cas_chan_state(chanp, SOL_CMA_CHAN_ROUTE_RESLVD,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar "rdma_connect, Invalid state");
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (chanp->chan_xport_type == SOL_CMA_XPORT_IB) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar } else if (chanp->chan_xport_type == SOL_CMA_XPORT_IWARP) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar#endif /* IWARP_SUPPORT */
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "rdma_connect: ret %x", ret);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarstatic int cma_init_listen_root(sol_cma_chan_t *);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarstatic void cma_fini_listen_root(sol_cma_chan_t *);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarrdma_listen(struct rdma_cm_id *idp, int bklog)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "rdma_listen(%p, %x)",
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar cma_set_chan_state(chanp, SOL_CMA_CHAN_LISTEN);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota chanp->chan_cmid_destroy_state |= SOL_CMA_CALLER_API_PROGRESS;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar chanp->chan_listenp = kmem_zalloc(sizeof (sol_cma_listen_info_t),
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L2(sol_rdmacm_dbg_str, "rdma_listen: "
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar "cma_init_listen_root: failed");
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (chanp->chan_xport_type == SOL_CMA_XPORT_NONE) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar } else if (chanp->chan_xport_type == SOL_CMA_XPORT_IB) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar } else if (chanp->chan_xport_type == SOL_CMA_XPORT_IWARP) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar#endif /* IWARP_SUPPORT */
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (genlist_empty(&(CHAN_LISTEN_LIST(chanp)))) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L2(sol_rdmacm_dbg_str, "rdma_listen: "
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar "No listeners");
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (chanp->chan_cmid_destroy_state & SOL_CMA_CALLER_CMID_DESTROYED) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar genlist_for_each(entry, &(CHAN_LISTEN_LIST(chanp))) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (ep_chanp->chan_xport_type == SOL_CMA_XPORT_IB)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (ep_chanp->chan_xport_type == SOL_CMA_XPORT_IWARP)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota chanp->chan_cmid_destroy_state &= ~SOL_CMA_CALLER_API_PROGRESS;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (chanp->chan_cmid_destroy_state & SOL_CMA_CALLER_CMID_DESTROYED)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "rdma_listen: ret %x", ret);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarrdma_accept(struct rdma_cm_id *idp, struct rdma_conn_param *conn_param)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "rdma_accept(%p, %p)",
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (cma_cas_chan_state(chanp, SOL_CMA_CHAN_LISTEN,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_CMA_CHAN_ACCEPT) && cma_cas_chan_state(chanp,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_CMA_CHAN_CONNECT, SOL_CMA_CHAN_ACCEPT)) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar "rdma_accept, Invalid state");
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "accept: root_idp %p",
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung /* For TCP, delete from REQ AVL & insert to ACPT AVL */
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung if (root_idp && root_idp->ps == RDMA_PS_TCP) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "accept: root_idp %p"
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung * This CMID has been deleted, maybe because of timeout.
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung * Return EINVAL.
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung if (chanp->chan_req_state != REQ_CMID_NOTIFIED) {
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung "accept: root_idp %p chanp %p, not in REQ "
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung ASSERT(cma_get_req_idp(root_idp, chanp->chan_session_id));
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar avl_remove(&root_chanp->chan_req_avl_tree, idp);
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung "Add to ACPT AVL of %p IDP, idp %p, qp_hdl %p",
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung find_ret = avl_find(&root_chanp->chan_acpt_avl_tree,
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung "DUPLICATE ENTRY in ACPT AVL : root %p, "
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung "idp %p, qp_hdl %p",
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * Accepting the connect request, no more events for this
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * connection.
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar /* If rdma_destroy_id() was called, destroy CMID */
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung if (chan_state == SOL_CMA_CHAN_DESTROY_PENDING) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (chanp->chan_xport_type == SOL_CMA_XPORT_IB)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (chanp->chan_xport_type == SOL_CMA_XPORT_IWARP)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar#endif /* IWARP_SUPPORT */
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (ret && root_idp && idp->ps == RDMA_PS_TCP) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar "Delete from REQ AVL of %p IDP, idp %p",
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung if (chanp->chan_req_state == REQ_CMID_ACCEPTED) {
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung find_ret = avl_find(&root_chanp->chan_req_avl_tree,
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung "DUPLICATE ENTRY in REQ AVL : root %p, "
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung "idp %p, session_id %p",
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung avl_insert(&root_chanp->chan_req_avl_tree, idp, where);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "rdma_accept: ret %x", ret);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarrdma_notify(struct rdma_cm_id *idp, enum ib_event_type evt)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "rdma_notify(%p, %x)", idp, evt);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (cma_cas_chan_state(chanp, SOL_CMA_CHAN_ROUTE_RESLVD,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar "rdma_notify, Invalid state");
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "rdma_notify: ret 0");
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarrdma_reject(struct rdma_cm_id *idp, const void *priv_data,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "rdma_reject(%p, %p)", idp,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (cma_cas_chan_state(chanp, SOL_CMA_CHAN_LISTEN,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar "rdma_accept, Invalid state");
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "reject: root_idp %p"
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung * Remove from REQ AVL tree. If this CMID has been deleted,
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung * it maybe because of timeout. Return EINVAL.
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung if (chanp->chan_req_state != REQ_CMID_NOTIFIED &&
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung "reject: root_idp %p chanp %p, not in REQ "
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung ASSERT(cma_get_req_idp(root_idp, chanp->chan_session_id));
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung avl_remove(&root_chanp->chan_req_avl_tree, idp);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (chanp->chan_xport_type == SOL_CMA_XPORT_IB)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar ret = rdma_ib_reject(idp, priv_data, priv_data_len);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (chanp->chan_xport_type == SOL_CMA_XPORT_IWARP)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar ret = rdma_iw_reject(idp, priv_data, priv_data_len);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar#endif /* IWARP_SUPPORT */
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * Rejecting connect request, no more events for this
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * connection.
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar /* If rdma_destroy_id() was called, destroy CMID */
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (chan_state == SOL_CMA_CHAN_DESTROY_PENDING)
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung "reject fail: Add to Req AVL of %p IDP, idp %p,"
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung if (chanp->chan_req_state == REQ_CMID_SERVER_NONE) {
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung "DUPLICATE ENTRY in REQ AVL : root %p, "
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung "idp %p, session_id %p",
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "rdma_reject: ret %x", ret);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "rdma_disconnect(%p)", idp);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar "rdma_disconnect(%p) - Not connected!!", idp);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar cma_set_chan_state(chanp, SOL_CMA_CHAN_DISCONNECT);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (chanp->chan_xport_type == SOL_CMA_XPORT_IB) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar } else if (chanp->chan_xport_type == SOL_CMA_XPORT_IWARP) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar#endif /* IWARP_SUPPORT */
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "rdma_disconnect: ret %x", ret);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarrdma_init_qp_attr(struct rdma_cm_id *idp, struct ib_qp_attr *qpattr,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "rdma_init_qp_attr(%p, %p, %p)",
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (chanp->chan_xport_type == SOL_CMA_XPORT_IB) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar ret = rdma_ib_init_qp_attr(idp, qpattr, qp_attr_mask);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar } else if (chanp->chan_xport_type == SOL_CMA_XPORT_IWARP)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar ret = rdma_iw_init_qp_attr(idp, qpattr, qp_attr_mask);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar#endif /* IWARP_SUPPORT */
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarrdma_join_multicast(struct rdma_cm_id *idp, struct sockaddr *addr,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar "rdma_join_multicast(%p, %p, %p)",
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar "rdma_join_multicast, Invalid state");
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (chanp->chan_xport_type == SOL_CMA_XPORT_IB)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar ret = rdma_ib_join_multicast(idp, addr, context);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar /* No support for Multicast on iWARP */
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar else if (chanp->chan_xport_type == SOL_CMA_XPORT_IWARP)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar#endif /* IWARP_SUPPORT */
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarrdma_leave_multicast(struct rdma_cm_id *idp, struct sockaddr *addr)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "rdma_leave_multicast(%p, %p)",
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar "rdma_leave_multicast, Invalid state");
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (chanp->chan_xport_type == SOL_CMA_XPORT_IB)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar /* No support for Multicast on iWARP */
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar else if (chanp->chan_xport_type == SOL_CMA_XPORT_IWARP)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar "rdma_leave_multicast, iWARP");
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar#endif /* IWARP_SUPPORT */
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "rdma_join_multicast: ret");
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * Functions to compare to rdma_cm_id *, used by AVL tree
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarsol_cma_req_cmid_cmp(const void *p1, const void *p2)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarsol_cma_cmid_cmp(const void *p1, const void *p2)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * Function to compare two sol_cma_glbl_listen_t *, used by
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * AVL tree routines.
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarsol_cma_svc_cmp(const void *p1, const void *p2)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar else if (listenp->cma_listen_chan_sid < sid)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * First search for matching global listen_info for this SID.
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * If found with the same client handle, reuse the service
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * handle, if matching SID is found with different client
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * handle, return EINVAL.
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar "cma_init_listen_root: search SID 0x%llx",
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar cma_listenp = avl_find(&sol_cma_glbl_listen_tree,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (cma_listenp && cma_listenp->cma_listen_clnt_hdl ==
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar "cma_init_listen_root: matching listenp %p SID 0x%llx",
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar chan_listenp->chan_glbl_listen_info = cma_listenp;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar "cma_init_listen_root: listenp %p, SID 0x%llx match, "
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar "client hdl prev %p, new %p mismatch",
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar cma_listenp = kmem_zalloc(sizeof (sol_cma_glbl_listen_t), KM_SLEEP);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar init_genlist(&cma_listenp->cma_listen_chan_list);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar &cma_listenp->cma_listen_chan_list, (uintptr_t)chanp, NULL);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar chan_listenp->chan_glbl_listen_info = cma_listenp;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar cma_listenp->cma_listen_clnt_hdl = chanp->chan_ib_client_hdl;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar cma_listenp->cma_listen_chan_sid = listen_sid;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar rc = ibcma_init_root_chan(chanp, cma_listenp);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar "cma_init_listen_root: ibcma_init_root_chan failed!!");
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar delete_genlist(&cma_listenp->cma_listen_chan_list,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar kmem_free(cma_listenp, sizeof (sol_cma_glbl_listen_t));
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar avl_insert(&sol_cma_glbl_listen_tree, cma_listenp, where);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "cma_fini_listen_root(%p)",
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar cma_listenp = chan_listenp->chan_glbl_listen_info;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar delete_genlist(&cma_listenp->cma_listen_chan_list,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (genlist_empty(&cma_listenp->cma_listen_chan_list)) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar "cma_fini_listen_root: "
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar "ibcma_fini_root_chan failed");
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarstatic void cma_generate_event_sync(struct rdma_cm_id *,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar enum rdma_cm_event_type, int, struct rdma_conn_param *,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar cma_event_async_arg_t *event_arg = (cma_event_async_arg_t *)arg;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar cma_generate_event_sync(event_arg->idp, event_arg->event,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (event_arg->conn_param && event_arg->conn_param->private_data_len)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar kmem_free((void *)event_arg->conn_param->private_data,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (event_arg->ud_paramp && event_arg->ud_paramp->private_data_len)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar kmem_free((void *)event_arg->ud_paramp->private_data,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar kmem_free(arg, sizeof (cma_event_async_arg_t));
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarcma_generate_event(struct rdma_cm_id *idp, enum rdma_cm_event_type event,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar int status, struct rdma_conn_param *conn_param,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar sol_cma_chan_t *chanp = (sol_cma_chan_t *)idp;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * Set SOL_CMA_CALLER_EVENT_PROGRESS to indicate event
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * notification is in progress, so that races between
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * rdma_destroy_id() and event notification is taken care.
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * If rdma_destroy_id() has been called for this CMID, call
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * cma_generate_event_sync() which skips notification to the
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * consumer and handles the event.
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar chanp->chan_cmid_destroy_state |= SOL_CMA_CALLER_EVENT_PROGRESS;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (chanp->chan_cmid_destroy_state & SOL_CMA_CALLER_CMID_DESTROYED) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar cma_generate_event_sync(idp, event, status, conn_param,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar event_arg = kmem_zalloc(sizeof (cma_event_async_arg_t), KM_SLEEP);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (conn_param && conn_param->private_data_len) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar sizeof (struct rdma_conn_param));
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar event_arg->conn_param = &(event_arg->un.conn);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar event_arg->conn_param->private_data = kmem_zalloc(
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar (void *)event_arg->conn_param->private_data,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar } else if (conn_param && conn_param->private_data_len == 0) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar sizeof (struct rdma_conn_param));
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar sizeof (struct rdma_ud_param));
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar event_arg->ud_paramp = &(event_arg->un.param);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar event_arg->ud_paramp->private_data = kmem_zalloc(
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (taskq_dispatch(system_taskq, cma_generate_event_thr,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar "generate_event_async: taskq_dispatch() failed!!");
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarcma_generate_event_sync(struct rdma_cm_id *idp, enum rdma_cm_event_type event,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar int status, struct rdma_conn_param *conn_param,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar sol_cma_chan_t *chanp = (sol_cma_chan_t *)idp;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "generate_event_sync(%p, %x, "
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar "%x, %p, %p", idp, event, status, conn_param, ud_paramp);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar bcopy((void *)conn_param, (void *)(&(cm_event.param.conn)),
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar sizeof (struct rdma_conn_param));
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar bcopy((void *)ud_paramp, (void *)(&(cm_event.param.ud)),
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar sizeof (struct rdma_ud_param));
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * If the consumer has destroyed the context for this CMID -
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * do not notify, skip to handling the sol_ofs specific
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * handling of the event.
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (chanp->chan_cmid_destroy_state & SOL_CMA_CALLER_CMID_DESTROYED) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "gen_event: root_idp %p",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * Update chan_req_state for the REQ CMID. Decrement
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * count of REQ CMIDs not notifed to consumer.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "Dec req_cnt of %p IDP, idp %p, req_cnt %x",
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar /* Pass the event to the client */
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar ret = (idp->event_handler) (idp, &cm_event);
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung * If the consumer returned failure :
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung * CONNECT_REQUEST :
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung * 1. rdma_disconnect() to disconnect connection.
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung * 2. wakeup destroy, if destroy has been called
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung * for this CMID
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung * 3. Destroy CMID if rdma_destroy has not been
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung * DISCONNECTED :
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung * 1. call cma_handle_nomore_events() to cleanup
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung * Other Events :
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung * 1. Client is expected to destroy the CMID.
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (event == RDMA_CM_EVENT_CONNECT_REQUEST) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar "cma_generate_event_async: consumer failed %d "
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar "generate_event_async: rdma_disconnect "
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung } else if (event == RDMA_CM_EVENT_DISCONNECTED) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar "generate_event_async: consumer failed %d event",
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung } else if (chan_state == SOL_CMA_CHAN_DESTROY_PENDING) {
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung /* rdma_destroy_id() called: destroy CMID */
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung "generate_event_async: consumer failed %d event",
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar } else if (chan_state == SOL_CMA_CHAN_DESTROY_PENDING) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar /* If rdma_destroy_id() was called, destroy CMID */
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar } else if (IS_UDP_CMID(idp) && event == RDMA_CM_EVENT_UNREACHABLE) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * If rdma_destroy_id() was called, destroy CMID
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung * If not chan_connect_flag/ chan_req_state has already been
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung * set to indicate that it can be deleted.
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar } else if (chan_state == SOL_CMA_CHAN_DESTROY_PENDING) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar chanp->chan_cmid_destroy_state &= ~SOL_CMA_CALLER_EVENT_PROGRESS;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (chanp->chan_cmid_destroy_state & SOL_CMA_CALLER_CMID_DESTROYED)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar/* Local Static functions */
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarcma_alloc_chan(rdma_cm_event_handler evt_hdlr, void *context,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar chanp = kmem_zalloc(sizeof (sol_cma_chan_t), KM_SLEEP);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_init(&chanp->chan_mutex, NULL, MUTEX_DRIVER, NULL);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar cv_init(&chanp->chan_destroy_cv, NULL, CV_DRIVER, NULL);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar cma_set_chan_state(chanp, SOL_CMA_CHAN_IDLE);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar avl_create(&chanp->chan_req_avl_tree, sol_cma_req_cmid_cmp,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar offsetof(sol_cma_chan_t, chan_req_avl_node));
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar avl_create(&chanp->chan_acpt_avl_tree, sol_cma_cmid_cmp,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar offsetof(sol_cma_chan_t, chan_acpt_avl_node));
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar/* Change the state of sol_cma_chan_t */
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarcma_set_chan_state(sol_cma_chan_t *chanp, cma_chan_state_t newstate)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar/* Check & Swap the state of sol_ucma_chan_t */
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarcma_cas_chan_state(sol_cma_chan_t *chanp, cma_chan_state_t prevstate,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar sol_cma_chan_t *chanp = (sol_cma_chan_t *)idp;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "cma_free_listen_list(%p)", idp);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar entry = remove_genlist_head(&(CHAN_LISTEN_LIST(chanp)));
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "fini_ep_chan: %p",
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar entry1 = ep_chanp->chan_listenp->listen_ep_dev_entry;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar device = ep_chanp->chan_listenp->listen_ep_device;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar delete_genlist(&cma_device->cma_epchan_list,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar kmem_free(ep_chanp, sizeof (sol_cma_chan_t));
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar entry = remove_genlist_head(&(CHAN_LISTEN_LIST(chanp)));
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * Destroy a listening CMID when :
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * a. All CONNECTION REQUEST recieved have been rejected
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * b. No CONNECTION REQUEST recieved.
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * Do not destroy a listening CMID when :
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * a. CONNECTION REQUEST has been recieved and not been
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * accepted from the passive / server side.
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * b. CONNECTION REQUEST has been recieved and has been
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * accepted from the passive server side.
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * Mark the listening CMID as destroy pending.
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * For CMIDs created for rdma_connect() or created for a
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * CONNECT request, destroy the CMID only when :
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * CONNECTION has been closed or rejected.
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * Mark the CMID as destroy pending.
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * When a connection is rejected or closed :
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * Check if flag indicates - destroy pending,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * cma_destroy_id() is called, this also does
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * If there is a listening CMID assosiated with it,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * call cma_destroy_if(listen_cmid);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar sol_cma_chan_t *chanp = (sol_cma_chan_t *)idp;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar acpt_nodes = avl_numnodes(&chanp->chan_acpt_avl_tree);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar req_nodes = avl_numnodes(&chanp->chan_req_avl_tree);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "cma_destroy_id(%p)- "
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar "est CMIDs %ld, req CMID %ld, listen_root %p, state %x, %x",
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar idp, acpt_nodes, req_nodes, chanp->listen_root,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * If there are either REQ recieved or Established CMIDs just return.
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * rdma_destroy() for these CMIDs can be called by client later.
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar cma_set_chan_state(chanp, SOL_CMA_CHAN_DESTROY_PENDING);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar cma_set_chan_state(chanp, SOL_CMA_CHAN_DESTROYING);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar sizeof (struct ib_sa_path_rec) * idp->route.num_paths);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar#endif /* IWARP_SUPPORT */
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar "cma_destroy_id: Unsupported xport type %x",
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * Flush out & Free all listeners wrt to this ID
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * No locking is required as this code is executed
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * all REQ CMIDs have been destroyed. listen_list
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * will therefore not be modified during this loop.
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar acpt_nodes = avl_numnodes(&root_chanp->chan_acpt_avl_tree);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar req_nodes = avl_numnodes(&root_chanp->chan_req_avl_tree);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "cma_destroy_id(%p)-"
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar " root idp %p, state %x, acpt_nodes %ld, req_nodes %ld",
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar idp, root_idp, state, acpt_nodes, req_nodes);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (state == SOL_CMA_CHAN_DESTROY_PENDING &&
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung root_chanp->chan_req_state = REQ_CMID_SERVER_NONE;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar } else if (state == SOL_CMA_CHAN_DESTROY_WAIT &&
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung root_chanp->chan_req_state = REQ_CMID_SERVER_NONE;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * Server TCP disconnect for an established channel.
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * If destroy_id() has been called for the listening
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * CMID and there are no more CMIDs with pending
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * events corresponding to the listening CMID, free
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * the listening CMID.
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarcma_handle_nomore_events(sol_cma_chan_t *chanp)
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung * Removal of CMID from the AVL trees should already have been done
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung * by now. Below code mainly as a safety net.
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung if (chanp->chan_req_state == REQ_CMID_ACCEPTED) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar avl_remove(&root_chanp->chan_acpt_avl_tree, idp);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar avl_remove(&root_chanp->chan_req_avl_tree, idp);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar req_nodes = avl_numnodes(&root_chanp->chan_req_avl_tree);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar acpt_nodes = avl_numnodes(&root_chanp->chan_acpt_avl_tree);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (state == SOL_CMA_CHAN_DESTROY_PENDING && req_nodes == 0UL &&
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otaextern int ib_modify_qp(struct ib_qp *, struct ib_qp_attr *, int);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otaextern int rdma_init_qp_attr(struct rdma_cm_id *, struct ib_qp_attr *,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otacma_init_ud_qp(sol_cma_chan_t *chanp, struct ib_qp *qp)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ret = rdma_init_qp_attr(&chanp->chan_rdma_cm, &qp_attr, &qp_attr_mask);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ret = ib_modify_qp(qp, &qp_attr, IB_QP_STATE | IB_QP_SQ_PSN);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otacma_init_conn_qp(sol_cma_chan_t *chanp, struct ib_qp *qp)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ret = rdma_init_qp_attr(&chanp->chan_rdma_cm, &qp_attr, &qp_attr_mask);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otastatic inline int
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otardma_create_qp(struct rdma_cm_id *idp, struct ib_pd *pd,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (idp->device->node_guid != pd->device->node_guid)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota dev_ofs_client = (ofs_client_t *)pd->device->clnt_hdl;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rdma_map_id2clnthdl(idp, dev_ofs_client->ibt_hdl, NULL);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (0);