c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar/*
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * CDDL HEADER START
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar *
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 *
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 *
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 *
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * CDDL HEADER END
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar */
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar/*
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar */
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar/*
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 * -N misc/sol_ofs
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * Solaris uCMA (sol_ucma) driver is the current consumer for
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * sol_cma.
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar */
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar/* Standard driver includes */
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar#include <sys/types.h>
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar#include <sys/modctl.h>
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar#include <sys/errno.h>
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar#include <sys/stat.h>
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar#include <sys/ddi.h>
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar#include <sys/sunddi.h>
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar#include <sys/modctl.h>
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar#include <sys/ib/clients/of/ofed_kernel.h>
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar#include <sys/ib/clients/of/rdma/ib_addr.h>
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
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
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar/* Modload support */
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarstatic struct modlmisc sol_ofs_modmisc = {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar &mod_miscops,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar "Solaris OFS Misc module"
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar};
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarstruct modlinkage sol_ofs_modlinkage = {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar MODREV_1,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar (void *)&sol_ofs_modmisc,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar NULL
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar};
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otastatic ib_client_t *sol_cma_ib_client;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarsol_cma_glbl_listen_t sol_cma_glbl_listen;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikaravl_tree_t sol_cma_glbl_listen_tree;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarstatic void sol_cma_add_dev(struct ib_device *);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarstatic void sol_cma_rem_dev(struct ib_device *);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarstatic llist_head_t sol_cma_dev_list = LLIST_HEAD_INIT(sol_cma_dev_list);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarkmutex_t sol_cma_dev_mutex;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarkmutex_t sol_cma_glob_mutex;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarchar *sol_rdmacm_dbg_str = "sol_rdmacm";
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarchar *sol_ofs_dbg_str = "sol_ofs_mod";
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar/*
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * Local functions defines.
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar */
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 Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarstatic struct rdma_cm_id *cma_alloc_chan(rdma_cm_event_handler,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar void *, enum rdma_port_space);
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 Gunjikar 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 Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarextern void sol_ofs_dprintf_init();
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarextern void sol_ofs_dprintf_fini();
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
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 Gunjikar int *);
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 Gunjikar void *);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarextern void rdma_ib_leave_multicast(struct rdma_cm_id *, struct sockaddr *);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarint
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar_init(void)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar{
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar int err;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar sol_ofs_dprintf_init();
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L5(sol_ofs_dbg_str, "_init()");
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
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 avl_create(&sol_cma_glbl_listen_tree,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar sol_cma_svc_cmp, sizeof (sol_cma_glbl_listen_t),
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar offsetof(sol_cma_glbl_listen_t, cma_listen_node));
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota sol_cma_ib_client = kmem_zalloc(sizeof (ib_client_t), KM_NOSLEEP);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (!sol_cma_ib_client) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota SOL_OFS_DPRINTF_L2(sol_ofs_dbg_str,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "_init() - mem alloc failed");
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota avl_destroy(&sol_cma_glbl_listen_tree);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_destroy(&sol_cma_dev_mutex);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_destroy(&sol_cma_glob_mutex);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota sol_ofs_dprintf_fini();
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (ENOMEM);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota sol_cma_ib_client->name = "sol_ofs";
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota sol_cma_ib_client->add = sol_cma_add_dev;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota sol_cma_ib_client->remove = sol_cma_rem_dev;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota sol_cma_ib_client->dip = NULL;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if ((err = ib_register_client(sol_cma_ib_client)) != 0) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L2(sol_ofs_dbg_str,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "_init() ib_register_client() failed with err %d",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota err);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota kmem_free(sol_cma_ib_client, sizeof (ib_client_t));
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar avl_destroy(&sol_cma_glbl_listen_tree);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_destroy(&sol_cma_dev_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_destroy(&sol_cma_glob_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar sol_ofs_dprintf_fini();
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (err);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar }
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if ((err = mod_install(&sol_ofs_modlinkage)) != 0) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota SOL_OFS_DPRINTF_L2(sol_ofs_dbg_str,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "_init() - mod_install() failed");
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ib_unregister_client(sol_cma_ib_client);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota kmem_free(sol_cma_ib_client, sizeof (ib_client_t));
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar avl_destroy(&sol_cma_glbl_listen_tree);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_destroy(&sol_cma_dev_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_destroy(&sol_cma_glob_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar sol_ofs_dprintf_fini();
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar return (err);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar }
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L5(sol_ofs_dbg_str, "_init() - ret");
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar return (err);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar}
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarint
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar_fini(void)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar{
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar int err;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L5(sol_ofs_dbg_str, "_fini()");
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
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 return (EBUSY);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar }
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if ((err = mod_remove(&sol_ofs_modlinkage)) != 0) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L3(sol_ofs_dbg_str,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar "_fini: mod_remove failed");
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar return (err);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ib_unregister_client(sol_cma_ib_client);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota kmem_free(sol_cma_ib_client, sizeof (ib_client_t));
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar avl_destroy(&sol_cma_glbl_listen_tree);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_destroy(&sol_cma_dev_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_destroy(&sol_cma_glob_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L5(sol_ofs_dbg_str, "_fini() - ret");
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar sol_ofs_dprintf_fini();
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar return (err);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar}
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarint
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar_info(struct modinfo *modinfop)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar{
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar return (mod_info(&sol_ofs_modlinkage, modinfop));
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar}
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikartypedef struct cma_device {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar kmutex_t cma_mutex;
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung /* Ptr in the global sol_cma_dev_list */
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar llist_head_t cma_list;
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung /* List of listeners for this device */
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar genlist_t cma_epchan_list;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar struct ib_device *cma_device;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar uint_t cma_ref_count;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar enum {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_CMA_DEV_ADDED,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_CMA_DEV_REM_IN_PROGRESS
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar } cma_dev_state;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar} cma_device_t;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarstatic void
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarsol_cma_add_dev(struct ib_device *dev)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar{
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar cma_device_t *new_device;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar new_device = kmem_zalloc(sizeof (cma_device_t), KM_NOSLEEP);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (!new_device) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L2(sol_ofs_dbg_str, "sol_cma_add_dev() "
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar "alloc failed!!");
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar return;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar }
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_init(&new_device->cma_mutex, NULL, MUTEX_DRIVER, NULL);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar llist_head_init(&new_device->cma_list, new_device);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar init_genlist(&new_device->cma_epchan_list);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar new_device->cma_device = dev;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ib_set_client_data(dev, sol_cma_ib_client, new_device);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_enter(&sol_cma_dev_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar llist_add_tail(&new_device->cma_list, &sol_cma_dev_list);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_exit(&sol_cma_dev_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar}
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarstatic void
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarsol_cma_rem_dev(struct ib_device *dev)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar{
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar cma_device_t *rem_device;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar genlist_entry_t *entry;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota SOL_OFS_DPRINTF_L5(sol_ofs_dbg_str, "sol_rem_dev(%p)", dev);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rem_device = (cma_device_t *)ib_get_client_data(dev, sol_cma_ib_client);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (!rem_device) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L2(sol_ofs_dbg_str, "sol_cma_rem_dev() "
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar "NULL cma_dev!!");
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar return;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar }
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_enter(&rem_device->cma_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar rem_device->cma_dev_state = SOL_CMA_DEV_REM_IN_PROGRESS;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (rem_device->cma_ref_count) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_exit(&rem_device->cma_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L3(sol_ofs_dbg_str, "sol_cma_rem_dev() "
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar "BUSY cma_dev!!");
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar return;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar }
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar entry = remove_genlist_head(&rem_device->cma_epchan_list);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar while (entry) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar sol_cma_chan_t *ep_chanp;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar ep_chanp = (sol_cma_chan_t *)entry->data;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (ibcma_fini_ep_chan(ep_chanp) == 0) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar genlist_entry_t *entry1;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar sol_cma_chan_t *root_chanp;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar ASSERT(ep_chanp->chan_listenp);
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 root_chanp->chan_listenp->listen_eps--;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar delete_genlist(&root_chanp->chan_listenp->listen_list,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar entry1);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar kmem_free(ep_chanp, sizeof (sol_cma_chan_t));
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar kmem_free(entry, sizeof (genlist_entry_t));
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar }
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar entry = remove_genlist_head(&rem_device->cma_epchan_list);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar }
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_exit(&rem_device->cma_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_enter(&sol_cma_dev_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar llist_del(&rem_device->cma_list);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_exit(&sol_cma_dev_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar kmem_free(rem_device, sizeof (cma_device_t));
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar}
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarstruct ib_device *
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarsol_cma_acquire_device(ib_guid_t hca_guid)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar{
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar llist_head_t *entry;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar cma_device_t *cma_devp;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_enter(&sol_cma_dev_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar list_for_each(entry, &sol_cma_dev_list) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar cma_devp = (cma_device_t *)entry->ptr;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (cma_devp->cma_device->node_guid != hca_guid)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar continue;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_enter(&cma_devp->cma_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (cma_devp->cma_dev_state == SOL_CMA_DEV_REM_IN_PROGRESS) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L3(sol_ofs_dbg_str,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar "sol_cma_acquire_dev() - Device getting removed!!");
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_exit(&cma_devp->cma_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_exit(&sol_cma_dev_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar return (NULL);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar }
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar cma_devp->cma_ref_count++;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_exit(&cma_devp->cma_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_exit(&sol_cma_dev_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar return (cma_devp->cma_device);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar }
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_exit(&sol_cma_dev_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar return (NULL);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar}
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarstatic void
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarsol_cma_release_device(struct rdma_cm_id *id)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar{
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar ib_device_t *device = id->device;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar llist_head_t *entry;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar cma_device_t *cma_devp;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_enter(&sol_cma_dev_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar list_for_each(entry, &sol_cma_dev_list) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar cma_devp = (cma_device_t *)entry->ptr;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (cma_devp->cma_device != device)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar continue;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_enter(&cma_devp->cma_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar cma_devp->cma_ref_count--;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (cma_devp->cma_dev_state == SOL_CMA_DEV_REM_IN_PROGRESS &&
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar cma_devp->cma_ref_count == 0) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L3(sol_ofs_dbg_str,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar "sol_cma_release_dev() - Device free removed!!");
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_exit(&cma_devp->cma_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar llist_del(&cma_devp->cma_list);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar kmem_free(cma_devp, sizeof (cma_device_t));
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_exit(&sol_cma_dev_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar return;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar }
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_exit(&cma_devp->cma_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar }
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_exit(&sol_cma_dev_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar}
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarvoid
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarsol_cma_add_hca_list(sol_cma_chan_t *ep_chanp, ib_guid_t hca_guid)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar{
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar llist_head_t *entry;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar cma_device_t *cma_devp;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "add_hca_list(%p, %llx)",
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar ep_chanp, hca_guid);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_enter(&sol_cma_dev_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar list_for_each(entry, &sol_cma_dev_list) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar cma_devp = (cma_device_t *)entry->ptr;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if ((cma_devp->cma_device)->node_guid != hca_guid)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar continue;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_enter(&cma_devp->cma_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar ep_chanp->chan_listenp->listen_ep_dev_entry =
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar add_genlist(&cma_devp->cma_epchan_list,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar (uintptr_t)ep_chanp, NULL);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar ep_chanp->chan_listenp->listen_ep_device = cma_devp->cma_device;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_exit(&cma_devp->cma_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_exit(&sol_cma_dev_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar return;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar }
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_exit(&sol_cma_dev_mutex);
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}
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar/*
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * rdma_cm.h API functions.
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar */
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarstruct rdma_cm_id *
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarrdma_create_id(rdma_cm_event_handler evt_hdlr, void *context,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar enum rdma_port_space ps)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar{
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar struct rdma_cm_id *rdma_idp;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "rdma_create_id(%p, %p, %x)",
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar evt_hdlr, context, ps);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (ps != RDMA_PS_TCP && ps != RDMA_PS_UDP && ps != RDMA_PS_IPOIB) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L2(sol_rdmacm_dbg_str,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar "rdma_create_id: unsupported protocol %x", ps);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar return (NULL);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar }
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar rdma_idp = cma_alloc_chan(evt_hdlr, context, ps);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar "rdma_create_id : ret %p", rdma_idp);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar return (rdma_idp);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar}
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarvoid
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarrdma_map_id2clnthdl(struct rdma_cm_id *rdma_idp, void *ib_client_hdl,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar void *iw_client_hdl)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar{
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar sol_cma_chan_t *chanp = (sol_cma_chan_t *)rdma_idp;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar "rdma_map_id2clnthdl(%p, %p, %p)",
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar rdma_idp, ib_client_hdl, iw_client_hdl);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar ASSERT(ib_client_hdl != NULL || iw_client_hdl != NULL);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar chanp->chan_ib_client_hdl = ib_client_hdl;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar chanp->chan_iw_client_hdl = iw_client_hdl;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar}
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarvoid
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarrdma_map_id2qphdl(struct rdma_cm_id *rdma_idp, void *qp_hdl)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar{
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar sol_cma_chan_t *chanp = (sol_cma_chan_t *)rdma_idp;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar ASSERT(rdma_idp);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar ASSERT(qp_hdl);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "rdma_mapid2qphdl(%p, %p)",
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar rdma_idp, qp_hdl);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar chanp->chan_qp_hdl = qp_hdl;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar}
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarvoid
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarrdma_destroy_id(struct rdma_cm_id *rdma_idp)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar{
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar sol_cma_chan_t *chanp, *root_chanp;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar cma_chan_state_t state;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar int rc, is_root_cmid, do_wait, is_passive;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "rdma_destroy_id(%p)", rdma_idp);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (!rdma_idp)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar return;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar is_root_cmid = do_wait = is_passive = 0;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar chanp = (sol_cma_chan_t *)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",
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar rdma_idp, root_chanp);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_enter(&chanp->chan_mutex);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota chanp->chan_cmid_destroy_state |= SOL_CMA_CALLER_CMID_DESTROYED;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /*
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * Wait in destroy of CMID when rdma_resolve_addr() / rdma_listen()
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * rdma_resolve_route() API is in progress.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota while (chanp->chan_cmid_destroy_state & SOL_CMA_CALLER_API_PROGRESS)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota cv_wait(&chanp->chan_destroy_cv, &chanp->chan_mutex);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
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
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (rdma_idp->device)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar sol_cma_release_device(rdma_idp);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (chanp->chan_listenp && chanp->chan_listenp->listen_is_root)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar is_root_cmid = 1;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (root_chanp == NULL && is_root_cmid == 0)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar is_passive = 1;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar /*
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * Skip Active side handling for passive CMIDs and listen CMID
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * for which REQ CMIDs have not been created.
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar */
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (is_passive || (is_root_cmid && chanp->chan_req_state !=
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung REQ_CMID_QUEUED)) {
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 is_root_cmid, chanp->chan_req_state);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar goto skip_passive_handling;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar }
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar /*
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 * the count.
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar */
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (is_root_cmid && chanp->chan_req_cnt) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar sol_cma_chan_t *req_cmid_chan, *next_chan;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
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 next_chan = AVL_NEXT(
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar &chanp->chan_req_avl_tree, req_cmid_chan);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (req_cmid_chan->chan_req_state ==
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung REQ_CMID_NOTIFIED) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar avl_remove(&chanp->chan_req_avl_tree,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar req_cmid_chan);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar chanp->chan_req_cnt--;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar chanp->chan_req_total_cnt--;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_exit(&chanp->chan_mutex);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_enter(&req_cmid_chan->chan_mutex);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota req_cmid_chan->chan_req_state =
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung REQ_CMID_SERVER_NONE;
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung if (rdma_idp->ps == RDMA_PS_TCP)
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung cma_set_chan_state(req_cmid_chan,
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung SOL_CMA_CHAN_DESTROY_PENDING);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_exit(&req_cmid_chan->chan_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar (void) rdma_disconnect(
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar (struct rdma_cm_id *)req_cmid_chan);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_enter(&chanp->chan_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (rdma_idp->ps == RDMA_PS_TCP) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_enter(
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar &req_cmid_chan->chan_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar req_cmid_chan->listen_root =
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar rdma_idp;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_exit(
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar &req_cmid_chan->chan_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar } else {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_destroy(
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar &req_cmid_chan->chan_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar cv_destroy(
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar &req_cmid_chan->chan_destroy_cv);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar kmem_free(req_cmid_chan,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar sizeof (sol_cma_chan_t));
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar }
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar }
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar }
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar }
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar /*
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 */
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 }
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung mutex_exit(&chanp->chan_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (root_chanp)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_enter(&root_chanp->chan_mutex);
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung mutex_enter(&chanp->chan_mutex);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#ifdef DEBUG
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);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#endif
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
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 do_wait = 1;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (root_chanp)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_exit(&root_chanp->chan_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarskip_passive_handling :
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar state = cma_get_chan_state(chanp);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (is_root_cmid == 0 && state != SOL_CMA_CHAN_DISCONNECT &&
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung SOL_CMAID_CONNECTED(chanp)) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar /*
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * A connected CM ID has not been disconnected.
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * Call rdma_disconnect() to disconnect it.
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar */
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_exit(&chanp->chan_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar rc = rdma_disconnect(rdma_idp);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (rc) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L2(sol_rdmacm_dbg_str,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar "rdma_destroy_id(%p)- disconnect failed!!",
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar rdma_idp);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar return;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar }
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_enter(&chanp->chan_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (root_chanp && chanp->listen_root == NULL)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar chanp->listen_root = (struct rdma_cm_id *)root_chanp;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar "rdma_destroy_id(chanp %p, connect %x, ps %x)",
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar chanp, chanp->chan_connect_flag, rdma_idp->ps);
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung if (SOL_CMAID_CONNECTED(chanp)) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (do_wait) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar cma_set_chan_state(chanp,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_CMA_CHAN_DESTROY_WAIT);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar cv_wait(&chanp->chan_destroy_cv,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar &chanp->chan_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_exit(&chanp->chan_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar cma_destroy_id(rdma_idp);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar } else {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar cma_set_chan_state(chanp,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_CMA_CHAN_DESTROY_PENDING);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_exit(&chanp->chan_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar }
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar } else {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar /*
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * No more callbacks are expected for this CMID.
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * Free this CMID.
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar */
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung mutex_exit(&chanp->chan_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar cma_destroy_id(rdma_idp);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar }
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar } else if (is_root_cmid == 0 && state ==
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung SOL_CMA_CHAN_DISCONNECT && SOL_CMAID_CONNECTED(chanp)) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar /*
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 */
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar cma_set_chan_state(chanp, SOL_CMA_CHAN_DESTROY_PENDING);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_exit(&chanp->chan_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar } else if (state != SOL_CMA_CHAN_DESTROY_PENDING) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar /* CM ID, not connected, just free it. */
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_exit(&chanp->chan_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar cma_destroy_id(rdma_idp);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar } else
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_exit(&chanp->chan_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "rdma_destroy_id: ret");
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar}
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar/*
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 *
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 Gunjikar */
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarint
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarrdma_bind_addr(struct rdma_cm_id *idp, struct sockaddr *addr)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar{
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar sol_cma_chan_t *chanp;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar struct rdma_addr *addrp;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar int ret;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar ASSERT(idp);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar ASSERT(addr);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar chanp = (sol_cma_chan_t *)idp;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar addrp = &(idp->route.addr);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "rdma_bind_addr(%p, %p)",
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar idp, addr);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_enter(&chanp->chan_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar ret = cma_cas_chan_state(chanp, SOL_CMA_CHAN_IDLE, SOL_CMA_CHAN_BOUND);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (ret) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_exit(&chanp->chan_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar return (ret);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar }
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 mutex_exit(&chanp->chan_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar /*
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
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * iWARP.
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar */
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (chanp->chan_ib_client_hdl == NULL) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ofs_client_t *ofs_clnt;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ofs_clnt = (ofs_client_t *)sol_cma_ib_client->clnt_hdl;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota chanp->chan_ib_client_hdl = ofs_clnt->ibt_hdl;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar }
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (chanp->chan_ib_client_hdl && rdma_ib_bind_addr(idp, addr) == 0) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar "rdma_bind_addr: ret IB @");
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar return (0);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar#ifdef IWARP_SUPPORT
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar } else if (chanp->chan_iw_client_hdl && rdma_iw_bind_addr(idp, addr)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar == 0) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar "rdma_bind_addr: ret iWARP @");
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar return (0);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar#endif /* IWARP_SUPPORT */
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar }
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_enter(&chanp->chan_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar cma_set_chan_state(chanp, SOL_CMA_CHAN_IDLE);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_exit(&chanp->chan_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L4(sol_rdmacm_dbg_str, "rdma_bind_addr: ret failure!");
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar return (EINVAL);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar}
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarint
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarrdma_resolve_addr(struct rdma_cm_id *idp, struct sockaddr *src_addr,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar struct sockaddr *dst_addr, int timeout_ms)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar{
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar sol_cma_chan_t *chanp;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar struct rdma_addr *addrp;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar cma_chan_state_t state;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar ASSERT(idp);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar chanp = (sol_cma_chan_t *)idp;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar addrp = &(idp->route.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
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_enter(&chanp->chan_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar state = cma_get_chan_state(chanp);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (state != SOL_CMA_CHAN_IDLE && state != SOL_CMA_CHAN_BOUND) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L2(sol_rdmacm_dbg_str,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar "rdma_resolve_addr : invalid chan state %x", state);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_exit(&chanp->chan_mutex);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (EINVAL);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (chanp->chan_cmid_destroy_state &
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota SOL_CMA_CALLER_CMID_DESTROYED) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota SOL_OFS_DPRINTF_L3(sol_rdmacm_dbg_str,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "rdma_resolve_addr : CMID %p, destroy called", chanp);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_exit(&chanp->chan_mutex);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (EINVAL);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota chanp->chan_cmid_destroy_state |= SOL_CMA_CALLER_API_PROGRESS;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
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 }
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar bcopy((void *)dst_addr, (void *)&(addrp->dst_addr),
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar sizeof (struct sockaddr));
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_exit(&chanp->chan_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar /*
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * First resolve this as an @ corresponding to IB fabric
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * if this fails, resolve this as an @ corresponding to iWARP
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar */
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (chanp->chan_ib_client_hdl == NULL) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ofs_client_t *ofs_clnt;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ofs_clnt = (ofs_client_t *)sol_cma_ib_client->clnt_hdl;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota chanp->chan_ib_client_hdl = ofs_clnt->ibt_hdl;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar }
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (chanp->chan_ib_client_hdl && rdma_ib_resolve_addr(idp, src_addr,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar dst_addr, timeout_ms) == 0) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L4(sol_rdmacm_dbg_str,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar "rdma_resolve_addr: ret IB @");
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar#ifdef IWARP_SUPPORT
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar } else if (chanp->chan_iw_client_hdl && rdma_iw_resolve_addr(idp,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar src_addr, dst_addr, timeout_ms) == 0) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L2(sol_rdmacm_dbg_str,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar "rdma_resolve_addr: ret iWARP @");
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar#endif /* IWARP_SUPPORT */
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar } else {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L2(sol_rdmacm_dbg_str,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar "rdma_resolve_addr: Invalid @");
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (EINVAL);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "rdma_resolve_addr: ret 0");
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (0);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otastatic void cma_generate_event_sync(struct rdma_cm_id *,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota enum rdma_cm_event_type, int, struct rdma_conn_param *,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota struct rdma_ud_param *);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otavoid
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otacma_resolve_addr_callback(sol_cma_chan_t *chanp, int rc)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota enum rdma_cm_event_type event;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_enter(&chanp->chan_mutex);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (chanp->chan_cmid_destroy_state &
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota SOL_CMA_CALLER_CMID_DESTROYED) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota SOL_OFS_DPRINTF_L3(sol_rdmacm_dbg_str,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "cma_resolve_addr : CMID %p, destroy called", chanp);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota chanp->chan_cmid_destroy_state &=
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ~SOL_CMA_CALLER_API_PROGRESS;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota cv_broadcast(&chanp->chan_destroy_cv);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_exit(&chanp->chan_mutex);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (rc == 0) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar cma_set_chan_state(chanp, SOL_CMA_CHAN_ADDR_RESLVD);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar event = RDMA_CM_EVENT_ADDR_RESOLVED;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar } else
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar event = RDMA_CM_EVENT_ADDR_ERROR;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar /*
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * Generate RDMA_CM_EVENT_ADDR_RESOLVED event
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * This will result in RDMA_USER_CM_CMD_RESOLVE_ROUTE in
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * userland.
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota chanp->chan_cmid_destroy_state |= SOL_CMA_CALLER_EVENT_PROGRESS;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_exit(&chanp->chan_mutex);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota cma_generate_event_sync((struct rdma_cm_id *)chanp, event, 0,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota NULL, NULL);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_enter(&chanp->chan_mutex);
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)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota cv_broadcast(&chanp->chan_destroy_cv);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_exit(&chanp->chan_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar}
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarint
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarrdma_resolve_route(struct rdma_cm_id *idp, int timeout_ms)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar{
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar sol_cma_chan_t *chanp;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar ASSERT(idp);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar chanp = (sol_cma_chan_t *)idp;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "resolve_route(%p, %x)", idp,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar timeout_ms);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_enter(&chanp->chan_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (cma_cas_chan_state(chanp, SOL_CMA_CHAN_ADDR_RESLVD,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_CMA_CHAN_ROUTE_RESLVD) != 0) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_exit(&chanp->chan_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L2(sol_rdmacm_dbg_str,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar "resolve_route: Invalid state");
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar return (EINVAL);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (chanp->chan_cmid_destroy_state &
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota SOL_CMA_CALLER_CMID_DESTROYED) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota SOL_OFS_DPRINTF_L3(sol_rdmacm_dbg_str,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "rdma_resolve_route : CMID %p, destroy called", chanp);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_exit(&chanp->chan_mutex);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (EINVAL);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota chanp->chan_cmid_destroy_state |= SOL_CMA_CALLER_API_PROGRESS;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_exit(&chanp->chan_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar /*
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * Generate RDMA_CM_EVENT_ROUTE_RESOLVED event
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * This will result in RDMA_USER_CM_CMD_RESOLVE_ROUTE in
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * userland
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar */
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar cma_generate_event(idp, RDMA_CM_EVENT_ROUTE_RESOLVED, 0,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar NULL, NULL);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_enter(&chanp->chan_mutex);
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)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota cv_broadcast(&chanp->chan_destroy_cv);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_exit(&chanp->chan_mutex);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "resolve_route: ret 0");
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar return (0);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar}
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar/*
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * Connect or Listen request should be send after Route is resolved
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar *
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 *
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 Gunjikar */
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarint
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarrdma_connect(struct rdma_cm_id *idp, struct rdma_conn_param *conn_param)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar{
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar sol_cma_chan_t *chanp;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar int ret = EINVAL;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar ASSERT(idp);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar chanp = (sol_cma_chan_t *)idp;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "rdma_connect(%p, %p)", idp,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar conn_param);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_enter(&chanp->chan_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (chanp->chan_xport_type == SOL_CMA_XPORT_NONE) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_exit(&chanp->chan_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L2(sol_rdmacm_dbg_str,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar "rdma_connect, Invalid Xport");
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar return (EINVAL);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar }
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (cma_cas_chan_state(chanp, SOL_CMA_CHAN_ROUTE_RESLVD,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_CMA_CHAN_CONNECT)) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_exit(&chanp->chan_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L2(sol_rdmacm_dbg_str,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar "rdma_connect, Invalid state");
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar return (EINVAL);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar }
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (chanp->chan_xport_type == SOL_CMA_XPORT_IB) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar ret = rdma_ib_connect(idp, conn_param);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar#ifdef IWARP_SUPPORT
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar } else if (chanp->chan_xport_type == SOL_CMA_XPORT_IWARP) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar ret = rdma_iw_connect(idp, conn_param);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar#endif /* IWARP_SUPPORT */
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar }
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_exit(&chanp->chan_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "rdma_connect: ret %x", ret);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar return (ret);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar}
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarstatic int cma_init_listen_root(sol_cma_chan_t *);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarstatic void cma_fini_listen_root(sol_cma_chan_t *);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarint
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarrdma_listen(struct rdma_cm_id *idp, int bklog)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar{
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar sol_cma_chan_t *chanp;
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung int ret = 0;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar genlist_entry_t *entry;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar cma_chan_state_t state;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar ASSERT(idp);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar chanp = (sol_cma_chan_t *)idp;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "rdma_listen(%p, %x)",
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar idp, bklog);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_enter(&chanp->chan_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar state = cma_get_chan_state(chanp);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (state == SOL_CMA_CHAN_IDLE) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_exit(&chanp->chan_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar return (EINVAL);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar }
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar cma_set_chan_state(chanp, SOL_CMA_CHAN_LISTEN);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (chanp->chan_cmid_destroy_state &
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota SOL_CMA_CALLER_CMID_DESTROYED) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota SOL_OFS_DPRINTF_L3(sol_rdmacm_dbg_str,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "rdma_listen : CMID %p, destroy called", chanp);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_exit(&chanp->chan_mutex);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (EINVAL);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota chanp->chan_cmid_destroy_state |= SOL_CMA_CALLER_API_PROGRESS;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ASSERT(chanp->chan_listenp == NULL);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar chanp->chan_listenp = kmem_zalloc(sizeof (sol_cma_listen_info_t),
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar KM_SLEEP);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar init_genlist(&(CHAN_LISTEN_LIST(chanp)));
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar (chanp->chan_listenp)->listen_is_root = 1;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar ret = cma_init_listen_root(chanp);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (ret) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota chanp->chan_listenp = NULL;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_exit(&chanp->chan_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L2(sol_rdmacm_dbg_str, "rdma_listen: "
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar "cma_init_listen_root: failed");
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar kmem_free(chanp->chan_listenp,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar sizeof (sol_cma_listen_info_t));
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar return (EINVAL);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar }
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (chanp->chan_xport_type == SOL_CMA_XPORT_NONE) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar ibcma_append_listen_list(idp);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar#ifdef IWARP_SUPPORT
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar iwcma_append_listen_list(idp);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar#endif
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar } else if (chanp->chan_xport_type == SOL_CMA_XPORT_IB) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar ibcma_append_listen_list(idp);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar#ifdef IWARP_SUPPORT
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar } else if (chanp->chan_xport_type == SOL_CMA_XPORT_IWARP) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar iwcma_append_listen_list(idp);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar#endif /* IWARP_SUPPORT */
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar }
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (genlist_empty(&(CHAN_LISTEN_LIST(chanp)))) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar cma_fini_listen_root(chanp);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar kmem_free((void *)chanp->chan_listenp,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar sizeof (sol_cma_listen_info_t));
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar chanp->chan_listenp = NULL;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L2(sol_rdmacm_dbg_str, "rdma_listen: "
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar "No listeners");
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_exit(&chanp->chan_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar return (0);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (chanp->chan_cmid_destroy_state & SOL_CMA_CALLER_CMID_DESTROYED) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota chanp->chan_cmid_destroy_state &=
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ~SOL_CMA_CALLER_API_PROGRESS;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota cv_broadcast(&chanp->chan_destroy_cv);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar genlist_for_each(entry, &(CHAN_LISTEN_LIST(chanp))) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar struct rdma_cm_id *ep_idp;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar sol_cma_chan_t *ep_chanp;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar ep_idp = (struct rdma_cm_id *)entry->data;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar ep_chanp = (sol_cma_chan_t *)ep_idp;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (ep_chanp->chan_xport_type == SOL_CMA_XPORT_IB)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar ret = rdma_ib_listen(ep_idp, bklog);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar#ifdef IWARP_SUPPORT
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (ep_chanp->chan_xport_type == SOL_CMA_XPORT_IWARP)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar ret = rdma_iw_listen(ep_idp, bklog);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar#endif
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (ret)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar break;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
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)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota cv_broadcast(&chanp->chan_destroy_cv);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_exit(&chanp->chan_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "rdma_listen: ret %x", ret);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar return (ret);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar}
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarint
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarrdma_accept(struct rdma_cm_id *idp, struct rdma_conn_param *conn_param)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar{
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar struct rdma_cm_id *root_idp;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar sol_cma_chan_t *root_chanp, *chanp;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar int ret = EINVAL;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar ASSERT(idp);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar chanp = (sol_cma_chan_t *)idp;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "rdma_accept(%p, %p)",
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar idp, conn_param);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_enter(&chanp->chan_mutex);
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 SOL_OFS_DPRINTF_L2(sol_rdmacm_dbg_str,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar "rdma_accept, Invalid state");
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_exit(&chanp->chan_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar return (EINVAL);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar }
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_exit(&chanp->chan_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar root_idp = CHAN_LISTEN_ROOT(chanp);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar root_chanp = (sol_cma_chan_t *)root_idp;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "accept: root_idp %p",
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar root_idp);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung /* For TCP, delete from REQ AVL & insert to ACPT AVL */
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung if (root_idp && root_idp->ps == RDMA_PS_TCP) {
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung void *find_ret;
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung avl_index_t where;
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "accept: root_idp %p"
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar "REQ AVL remove %p", root_chanp, idp);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_enter(&root_chanp->chan_mutex);
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung mutex_enter(&chanp->chan_mutex);
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung /*
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung * This CMID has been deleted, maybe because of timeout.
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung * Return EINVAL.
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung */
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung if (chanp->chan_req_state != REQ_CMID_NOTIFIED) {
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung mutex_exit(&chanp->chan_mutex);
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung mutex_exit(&root_chanp->chan_mutex);
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung SOL_OFS_DPRINTF_L3(sol_rdmacm_dbg_str,
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung "accept: root_idp %p chanp %p, not in REQ "
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung "AVL tree", root_chanp, chanp);
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung return (EINVAL);
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung }
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung ASSERT(cma_get_req_idp(root_idp, chanp->chan_session_id));
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar avl_remove(&root_chanp->chan_req_avl_tree, idp);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str,
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung "Add to ACPT AVL of %p IDP, idp %p, qp_hdl %p",
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung root_idp, idp, chanp->chan_qp_hdl);
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung find_ret = avl_find(&root_chanp->chan_acpt_avl_tree,
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung (void *)chanp->chan_qp_hdl, &where);
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung if (find_ret) {
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung chanp->chan_req_state = REQ_CMID_SERVER_NONE;
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung mutex_exit(&chanp->chan_mutex);
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung mutex_exit(&root_chanp->chan_mutex);
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung SOL_OFS_DPRINTF_L2(sol_rdmacm_dbg_str,
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung "DUPLICATE ENTRY in ACPT AVL : root %p, "
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung "idp %p, qp_hdl %p",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota root_idp, idp, chanp->chan_qp_hdl);
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung return (EINVAL);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung avl_insert(&root_chanp->chan_acpt_avl_tree,
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung (void *)idp, where);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar chanp->chan_req_state = REQ_CMID_ACCEPTED;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_exit(&chanp->chan_mutex);
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung mutex_exit(&root_chanp->chan_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar }
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (root_idp && IS_UDP_CMID(root_idp)) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar cma_chan_state_t chan_state;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar /*
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * Accepting the connect request, no more events for this
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * connection.
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar */
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar cma_handle_nomore_events(chanp);
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung mutex_enter(&chanp->chan_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar chan_state = cma_get_chan_state(chanp);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_exit(&chanp->chan_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar /* If rdma_destroy_id() was called, destroy CMID */
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung if (chan_state == SOL_CMA_CHAN_DESTROY_PENDING) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar cma_destroy_id((struct rdma_cm_id *)chanp);
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung return (EINVAL);
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung }
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar }
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (chanp->chan_xport_type == SOL_CMA_XPORT_IB)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar ret = rdma_ib_accept(idp, conn_param);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar#ifdef IWARP_SUPPORT
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (chanp->chan_xport_type == SOL_CMA_XPORT_IWARP)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar ret = rdma_iw_accept(idp, conn_param);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar#endif /* IWARP_SUPPORT */
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (ret && root_idp && idp->ps == RDMA_PS_TCP) {
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung void *find_ret;
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung avl_index_t where;
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar "Delete from REQ AVL of %p IDP, idp %p",
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar root_idp, idp);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_enter(&root_chanp->chan_mutex);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_enter(&chanp->chan_mutex);
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung if (chanp->chan_req_state == REQ_CMID_ACCEPTED) {
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung ASSERT(cma_get_acpt_idp(root_idp,
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung chanp->chan_qp_hdl));
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung avl_remove(&root_chanp->chan_acpt_avl_tree,
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung idp);
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung find_ret = avl_find(&root_chanp->chan_req_avl_tree,
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung (void *)chanp->chan_qp_hdl, &where);
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung if (find_ret) {
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung chanp->chan_req_state = REQ_CMID_SERVER_NONE;
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung mutex_exit(&chanp->chan_mutex);
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung mutex_exit(&root_chanp->chan_mutex);
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung SOL_OFS_DPRINTF_L2(sol_rdmacm_dbg_str,
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung "DUPLICATE ENTRY in REQ AVL : root %p, "
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung "idp %p, session_id %p",
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung root_idp, idp, chanp->chan_session_id);
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung return (EINVAL);
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung }
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung avl_insert(&root_chanp->chan_req_avl_tree, idp, where);
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung chanp->chan_req_state = REQ_CMID_NOTIFIED;
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_exit(&chanp->chan_mutex);
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung mutex_exit(&root_chanp->chan_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar }
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "rdma_accept: ret %x", ret);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar return (ret);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar}
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarint
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarrdma_notify(struct rdma_cm_id *idp, enum ib_event_type evt)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar{
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar sol_cma_chan_t *chanp;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar ASSERT(idp);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar chanp = (sol_cma_chan_t *)idp;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "rdma_notify(%p, %x)", idp, evt);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_enter(&chanp->chan_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (cma_cas_chan_state(chanp, SOL_CMA_CHAN_ROUTE_RESLVD,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_CMA_CHAN_EVENT_NOTIFIED)) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L2(sol_rdmacm_dbg_str,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar "rdma_notify, Invalid state");
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_exit(&chanp->chan_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar return (EINVAL);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar }
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_exit(&chanp->chan_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "rdma_notify: ret 0");
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar return (0);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar}
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarint
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarrdma_reject(struct rdma_cm_id *idp, const void *priv_data,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar uint8_t priv_data_len)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar{
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar struct rdma_cm_id *root_idp;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar sol_cma_chan_t *root_chanp, *chanp;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar int ret = EINVAL;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar ASSERT(idp);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar chanp = (sol_cma_chan_t *)idp;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar root_idp = CHAN_LISTEN_ROOT(chanp);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar root_chanp = (sol_cma_chan_t *)root_idp;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "rdma_reject(%p, %p)", idp,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar priv_data, priv_data_len);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_enter(&chanp->chan_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (cma_cas_chan_state(chanp, SOL_CMA_CHAN_LISTEN,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_CMA_CHAN_REJECT)) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L2(sol_rdmacm_dbg_str,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar "rdma_accept, Invalid state");
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_exit(&chanp->chan_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar return (EINVAL);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar }
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_exit(&chanp->chan_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung if (root_idp) {
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "reject: root_idp %p"
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung "REQ AVL remove %p", root_chanp, idp);
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung /*
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung * Remove from REQ AVL tree. If this CMID has been deleted,
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung * it maybe because of timeout. Return EINVAL.
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung */
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung mutex_enter(&root_chanp->chan_mutex);
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung mutex_enter(&chanp->chan_mutex);
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung if (chanp->chan_req_state != REQ_CMID_NOTIFIED &&
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung chanp->chan_req_state != REQ_CMID_QUEUED) {
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung mutex_exit(&chanp->chan_mutex);
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung mutex_exit(&root_chanp->chan_mutex);
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung SOL_OFS_DPRINTF_L3(sol_rdmacm_dbg_str,
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung "reject: root_idp %p chanp %p, not in REQ "
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung "AVL tree", root_chanp, chanp);
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung return (EINVAL);
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung }
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung ASSERT(cma_get_req_idp(root_idp, chanp->chan_session_id));
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung avl_remove(&root_chanp->chan_req_avl_tree, idp);
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung chanp->chan_req_state = REQ_CMID_SERVER_NONE;
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung mutex_exit(&chanp->chan_mutex);
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung mutex_exit(&root_chanp->chan_mutex);
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung }
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung
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#ifdef IWARP_SUPPORT
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
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (!ret && root_idp) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar cma_chan_state_t chan_state;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar /*
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * Rejecting connect request, no more events for this
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * connection.
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar */
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar cma_handle_nomore_events(chanp);
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung mutex_enter(&chanp->chan_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar chan_state = cma_get_chan_state(chanp);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_exit(&chanp->chan_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar /* If rdma_destroy_id() was called, destroy CMID */
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (chan_state == SOL_CMA_CHAN_DESTROY_PENDING)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar cma_destroy_id((struct rdma_cm_id *)chanp);
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung } else if (ret && root_idp) {
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung avl_index_t where;
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str,
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung "reject fail: Add to Req AVL of %p IDP, idp %p,"
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung "session_id %p", root_idp, idp,
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung chanp->chan_session_id);
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung mutex_enter(&root_chanp->chan_mutex);
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung mutex_enter(&chanp->chan_mutex);
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung if (chanp->chan_req_state == REQ_CMID_SERVER_NONE) {
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung if (avl_find(&root_chanp->chan_req_avl_tree,
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung (void *)chanp->chan_session_id, &where)) {
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung mutex_exit(&chanp->chan_mutex);
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung mutex_exit(&root_chanp->chan_mutex);
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung SOL_OFS_DPRINTF_L2(sol_rdmacm_dbg_str,
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung "DUPLICATE ENTRY in REQ AVL : root %p, "
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung "idp %p, session_id %p",
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung root_idp, idp, chanp->chan_session_id);
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung return (EINVAL);
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung }
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung avl_insert(&root_chanp->chan_req_avl_tree,
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung (void *)idp, where);
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung chanp->chan_req_state = REQ_CMID_NOTIFIED;
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung }
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung mutex_exit(&chanp->chan_mutex);
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung mutex_exit(&root_chanp->chan_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar }
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "rdma_reject: ret %x", ret);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar return (ret);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar}
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarint
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarrdma_disconnect(struct rdma_cm_id *idp)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar{
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar sol_cma_chan_t *chanp;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar int ret = EINVAL;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar cma_chan_state_t state;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar chanp = (sol_cma_chan_t *)idp;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "rdma_disconnect(%p)", idp);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (!idp)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar return (0);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_enter(&chanp->chan_mutex);
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung if (!(SOL_CMAID_CONNECTED(chanp))) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L3(sol_rdmacm_dbg_str,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar "rdma_disconnect(%p) - Not connected!!", idp);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_exit(&chanp->chan_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar return (EINVAL);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar }
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar state = cma_get_chan_state(chanp);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar cma_set_chan_state(chanp, SOL_CMA_CHAN_DISCONNECT);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_exit(&chanp->chan_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (chanp->chan_xport_type == SOL_CMA_XPORT_IB) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar ret = rdma_ib_disconnect(idp);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar#ifdef IWARP_SUPPORT
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar } else if (chanp->chan_xport_type == SOL_CMA_XPORT_IWARP) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar ret = rdma_iw_disconnect(idp);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar#endif /* IWARP_SUPPORT */
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar }
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (ret) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_enter(&chanp->chan_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar cma_set_chan_state(chanp, state);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_exit(&chanp->chan_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar return (ret);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar }
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "rdma_disconnect: ret %x", ret);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar return (ret);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar}
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarint
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarrdma_init_qp_attr(struct rdma_cm_id *idp, struct ib_qp_attr *qpattr,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar int *qp_attr_mask)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar{
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar sol_cma_chan_t *chanp;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar int ret = EINVAL;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar ASSERT(idp);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar chanp = (sol_cma_chan_t *)idp;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "rdma_init_qp_attr(%p, %p, %p)",
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar idp, qpattr, qp_attr_mask);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
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#ifdef IWARP_SUPPORT
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 Gunjikar } else {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar ret = EINVAL;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar }
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar "rdma_init_qp_attr: ret %x", ret);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar return (ret);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar}
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarint
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarrdma_join_multicast(struct rdma_cm_id *idp, struct sockaddr *addr,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar void *context)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar{
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar sol_cma_chan_t *chanp;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar int ret = ENODEV;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar cma_chan_state_t state;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar ASSERT(idp);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar chanp = (sol_cma_chan_t *)idp;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar "rdma_join_multicast(%p, %p, %p)",
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar idp, addr, context);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_enter(&chanp->chan_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar state = cma_get_chan_state(chanp);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (state != SOL_CMA_CHAN_BOUND &&
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar state != SOL_CMA_CHAN_ROUTE_RESLVD &&
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar state != SOL_CMA_CHAN_ADDR_RESLVD) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L2(sol_rdmacm_dbg_str,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar "rdma_join_multicast, Invalid state");
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_exit(&chanp->chan_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar return (EINVAL);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar }
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (chanp->chan_xport_type == SOL_CMA_XPORT_IB)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar ret = rdma_ib_join_multicast(idp, addr, context);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar#ifdef IWARP_SUPPORT
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar /* No support for Multicast on iWARP */
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar else if (chanp->chan_xport_type == SOL_CMA_XPORT_IWARP)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar ret = ENOTSUP;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar#endif /* IWARP_SUPPORT */
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_exit(&chanp->chan_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar "rdma_join_multicast: ret %x", ret);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar return (ret);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar}
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarvoid
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarrdma_leave_multicast(struct rdma_cm_id *idp, struct sockaddr *addr)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar{
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar sol_cma_chan_t *chanp;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar cma_chan_state_t state;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar ASSERT(idp);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar chanp = (sol_cma_chan_t *)idp;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "rdma_leave_multicast(%p, %p)",
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar idp, addr);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_enter(&chanp->chan_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar state = cma_get_chan_state(chanp);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (state != SOL_CMA_CHAN_BOUND &&
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar state != SOL_CMA_CHAN_ROUTE_RESLVD &&
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar state != SOL_CMA_CHAN_ADDR_RESLVD) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L2(sol_rdmacm_dbg_str,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar "rdma_leave_multicast, Invalid state");
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_exit(&chanp->chan_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar return;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar }
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (chanp->chan_xport_type == SOL_CMA_XPORT_IB)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar rdma_ib_leave_multicast(idp, addr);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar#ifdef IWARP_SUPPORT
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar /* No support for Multicast on iWARP */
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar else if (chanp->chan_xport_type == SOL_CMA_XPORT_IWARP)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L2(sol_rdmacm_dbg_str,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar "rdma_leave_multicast, iWARP");
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar#endif /* IWARP_SUPPORT */
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_exit(&chanp->chan_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "rdma_join_multicast: ret");
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar}
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar/*
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * Functions to compare to rdma_cm_id *, used by AVL tree
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * routines.
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar */
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarint
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarsol_cma_req_cmid_cmp(const void *p1, const void *p2)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar{
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar sol_cma_chan_t *chanp;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar chanp = (sol_cma_chan_t *)p2;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (chanp->chan_session_id > p1)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar return (+1);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar else if (chanp->chan_session_id < p1)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar return (-1);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar else
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar return (0);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar}
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarint
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarsol_cma_cmid_cmp(const void *p1, const void *p2)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar{
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar sol_cma_chan_t *chanp;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar chanp = (sol_cma_chan_t *)p2;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (chanp->chan_qp_hdl > p1)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar return (+1);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar else if (chanp->chan_qp_hdl < p1)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar return (-1);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar else
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar return (0);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar}
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar/*
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * Function to compare two sol_cma_glbl_listen_t *, used by
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * AVL tree routines.
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar */
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarint
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarsol_cma_svc_cmp(const void *p1, const void *p2)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar{
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar sol_cma_glbl_listen_t *listenp;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar uint64_t sid;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar sid = *(uint64_t *)p1;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar listenp = (sol_cma_glbl_listen_t *)p2;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (listenp->cma_listen_chan_sid > sid)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar return (+1);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar else if (listenp->cma_listen_chan_sid < sid)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar return (-1);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar else
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar return (0);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar}
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarstatic int
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarcma_init_listen_root(sol_cma_chan_t *chanp)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar{
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar sol_cma_glbl_listen_t *cma_listenp;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar sol_cma_listen_info_t *chan_listenp;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar int rc = 0;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar avl_index_t where = 0;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar uint64_t listen_sid;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar ASSERT(chanp);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar ASSERT(chanp->chan_listenp);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar chan_listenp = chanp->chan_listenp;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar "cma_init_listen_root(%p)", chanp);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar /*
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 */
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar listen_sid = ibcma_init_root_sid(chanp);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar "cma_init_listen_root: search SID 0x%llx",
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar listen_sid);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_enter(&sol_cma_glob_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar cma_listenp = avl_find(&sol_cma_glbl_listen_tree,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar (void *) &listen_sid, &where);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (cma_listenp && cma_listenp->cma_listen_clnt_hdl ==
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar chanp->chan_ib_client_hdl) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar "cma_init_listen_root: matching listenp %p SID 0x%llx",
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar cma_listenp, listen_sid);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar chan_listenp->listen_entry = add_genlist(
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar &cma_listenp->cma_listen_chan_list,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar (uintptr_t)chanp, NULL);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar chan_listenp->chan_glbl_listen_info = cma_listenp;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar ibcma_copy_srv_hdl(chanp, cma_listenp);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_exit(&sol_cma_glob_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar return (0);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar } else if (cma_listenp) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L2(sol_rdmacm_dbg_str,
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, listen_sid,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar cma_listenp->cma_listen_clnt_hdl,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar chanp->chan_ib_client_hdl);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_exit(&sol_cma_glob_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar return (EINVAL);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar }
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
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 chan_listenp->listen_entry = add_genlist(
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
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar rc = ibcma_init_root_chan(chanp, cma_listenp);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (rc) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_exit(&sol_cma_glob_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L2(sol_rdmacm_dbg_str,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar "cma_init_listen_root: ibcma_init_root_chan failed!!");
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar delete_genlist(&cma_listenp->cma_listen_chan_list,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar chan_listenp->listen_entry);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar kmem_free(cma_listenp, sizeof (sol_cma_glbl_listen_t));
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar return (rc);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar }
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar avl_insert(&sol_cma_glbl_listen_tree, cma_listenp, where);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_exit(&sol_cma_glob_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar return (0);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar}
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarstatic void
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarcma_fini_listen_root(sol_cma_chan_t *chanp)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar{
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar sol_cma_glbl_listen_t *cma_listenp;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar sol_cma_listen_info_t *chan_listenp;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar ASSERT(chanp);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar ASSERT(chanp->chan_listenp);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "cma_fini_listen_root(%p)",
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar chanp);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar chan_listenp = chanp->chan_listenp;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar cma_listenp = chan_listenp->chan_glbl_listen_info;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar ASSERT(cma_listenp);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_enter(&sol_cma_glob_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar delete_genlist(&cma_listenp->cma_listen_chan_list,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar chan_listenp->listen_entry);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (genlist_empty(&cma_listenp->cma_listen_chan_list)) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (ibcma_fini_root_chan(chanp) == 0) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar avl_remove(&sol_cma_glbl_listen_tree,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar cma_listenp);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar kmem_free(cma_listenp,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar sizeof (sol_cma_glbl_listen_t));
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar } else
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L2(sol_rdmacm_dbg_str,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar "cma_fini_listen_root: "
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar "ibcma_fini_root_chan failed");
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar }
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_exit(&sol_cma_glob_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar}
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikartypedef struct cma_event_async_arg {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar struct rdma_cm_id *idp;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar enum rdma_cm_event_type event;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar int status;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar union {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar struct rdma_conn_param conn;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar struct rdma_ud_param param;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar } un;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar struct rdma_conn_param *conn_param;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar struct rdma_ud_param *ud_paramp;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar} cma_event_async_arg_t;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
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 struct rdma_ud_param *);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarvoid
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarcma_generate_event_thr(void *arg)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar{
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar cma_event_async_arg_t *event_arg = (cma_event_async_arg_t *)arg;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar cma_generate_event_sync(event_arg->idp, event_arg->event,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar event_arg->status, event_arg->conn_param,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar event_arg->ud_paramp);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
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 event_arg->conn_param->private_data_len);
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 event_arg->ud_paramp->private_data_len);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar kmem_free(arg, sizeof (cma_event_async_arg_t));
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar}
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarvoid
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 struct rdma_ud_param *ud_paramp)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar{
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar cma_event_async_arg_t *event_arg;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar sol_cma_chan_t *chanp = (sol_cma_chan_t *)idp;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar /*
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 *
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 */
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_enter(&chanp->chan_mutex);
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 mutex_exit(&chanp->chan_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar cma_generate_event_sync(idp, event, status, conn_param,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar ud_paramp);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar return;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar }
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_exit(&chanp->chan_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar event_arg = kmem_zalloc(sizeof (cma_event_async_arg_t), KM_SLEEP);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar event_arg->idp = idp;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar event_arg->event = event;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar event_arg->status = status;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar event_arg->conn_param = NULL;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar event_arg->ud_paramp = NULL;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (conn_param && conn_param->private_data_len) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar bcopy(conn_param, &(event_arg->un.conn),
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 conn_param->private_data_len, KM_SLEEP);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar bcopy(conn_param->private_data,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar (void *)event_arg->conn_param->private_data,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar conn_param->private_data_len);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar } else if (conn_param && conn_param->private_data_len == 0) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar bcopy(conn_param, &(event_arg->un.conn),
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar sizeof (struct rdma_conn_param));
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar } else if (ud_paramp) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar bcopy(ud_paramp, &(event_arg->un.param),
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar sizeof (struct rdma_ud_param));
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar event_arg->ud_paramp = &(event_arg->un.param);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (ud_paramp->private_data_len) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar event_arg->ud_paramp->private_data = kmem_zalloc(
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar ud_paramp->private_data_len, KM_SLEEP);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar bcopy(ud_paramp->private_data,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar (void *)event_arg->ud_paramp->private_data,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar ud_paramp->private_data_len);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar } else if (ud_paramp->private_data) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar event_arg->ud_paramp->private_data =
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar ud_paramp->private_data;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar }
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar }
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (taskq_dispatch(system_taskq, cma_generate_event_thr,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar (void *)event_arg, TQ_SLEEP) == 0) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L2(sol_rdmacm_dbg_str,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar "generate_event_async: taskq_dispatch() failed!!");
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_enter(&chanp->chan_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar chanp->chan_cmid_destroy_state &=
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar ~SOL_CMA_CALLER_EVENT_PROGRESS;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (chanp->chan_cmid_destroy_state &
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_CMA_CALLER_CMID_DESTROYED)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar cv_broadcast(&chanp->chan_destroy_cv);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_exit(&chanp->chan_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar }
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar}
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarstatic void
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 struct rdma_ud_param *ud_paramp)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar{
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar struct rdma_cm_event cm_event;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar sol_cma_chan_t *chanp = (sol_cma_chan_t *)idp;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar struct rdma_cm_id *root_idp = NULL;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar sol_cma_chan_t *root_chanp;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar int ret;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar cma_chan_state_t chan_state;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
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
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar bzero(&cm_event, sizeof (cm_event));
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar cm_event.event = event;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar cm_event.status = status;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (conn_param)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar bcopy((void *)conn_param, (void *)(&(cm_event.param.conn)),
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar sizeof (struct rdma_conn_param));
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar else if (ud_paramp)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar bcopy((void *)ud_paramp, (void *)(&(cm_event.param.ud)),
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar sizeof (struct rdma_ud_param));
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar /*
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 */
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_enter(&chanp->chan_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (chanp->chan_cmid_destroy_state & SOL_CMA_CALLER_CMID_DESTROYED) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_exit(&chanp->chan_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar goto ofs_consume_event;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar }
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_exit(&chanp->chan_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota root_idp = CHAN_LISTEN_ROOT(chanp);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota root_chanp = (sol_cma_chan_t *)root_idp;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "gen_event: root_idp %p",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota root_idp);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (event == RDMA_CM_EVENT_CONNECT_REQUEST) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /*
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * Update chan_req_state for the REQ CMID. Decrement
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * count of REQ CMIDs not notifed to consumer.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ASSERT(root_idp);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_enter(&root_chanp->chan_mutex);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota root_chanp->chan_req_cnt--;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#ifdef DEBUG
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "Dec req_cnt of %p IDP, idp %p, req_cnt %x",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota root_idp, idp, root_chanp->chan_req_cnt);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#endif
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_exit(&root_chanp->chan_mutex);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar /* Pass the event to the client */
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar ret = (idp->event_handler) (idp, &cm_event);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (ret) {
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung /*
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 * called.
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.
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung */
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (event == RDMA_CM_EVENT_CONNECT_REQUEST) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L4(sol_rdmacm_dbg_str,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar "cma_generate_event_async: consumer failed %d "
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar "event", event);
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung if (rdma_disconnect(idp)) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L2(sol_rdmacm_dbg_str,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar "generate_event_async: rdma_disconnect "
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar "failed");
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung }
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung mutex_enter(&chanp->chan_mutex);
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung ASSERT(SOL_IS_SERVER_CMID(chanp));
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung chanp->chan_req_state = REQ_CMID_SERVER_NONE;
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung chanp->chan_cmid_destroy_state &=
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung ~SOL_CMA_CALLER_EVENT_PROGRESS;
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung if (chanp->chan_cmid_destroy_state &
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung SOL_CMA_CALLER_CMID_DESTROYED) {
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung cv_broadcast(&chanp->chan_destroy_cv);
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung mutex_exit(&chanp->chan_mutex);
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung } else {
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung mutex_exit(&chanp->chan_mutex);
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung rdma_destroy_id(idp);
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung }
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung } else if (event == RDMA_CM_EVENT_DISCONNECTED) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L2(sol_rdmacm_dbg_str,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar "generate_event_async: consumer failed %d event",
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar event);
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung cma_handle_nomore_events(chanp);
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung mutex_enter(&chanp->chan_mutex);
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung chan_state = cma_get_chan_state(chanp);
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung chanp->chan_cmid_destroy_state &=
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung ~SOL_CMA_CALLER_EVENT_PROGRESS;
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung if (chanp->chan_cmid_destroy_state &
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung SOL_CMA_CALLER_CMID_DESTROYED) {
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung cv_broadcast(&chanp->chan_destroy_cv);
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung mutex_exit(&chanp->chan_mutex);
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung } else if (chan_state == SOL_CMA_CHAN_DESTROY_PENDING) {
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung /* rdma_destroy_id() called: destroy CMID */
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung mutex_exit(&chanp->chan_mutex);
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung cma_destroy_id((struct rdma_cm_id *)chanp);
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung } else
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung mutex_exit(&chanp->chan_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar } else {
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung SOL_OFS_DPRINTF_L2(sol_rdmacm_dbg_str,
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung "generate_event_async: consumer failed %d event",
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung event);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar }
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar return;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar }
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarofs_consume_event:
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung if (event == RDMA_CM_EVENT_DISCONNECTED) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar cma_chan_state_t chan_state;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar cma_handle_nomore_events(chanp);
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung mutex_enter(&chanp->chan_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar chan_state = cma_get_chan_state(chanp);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar chanp->chan_cmid_destroy_state &=
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar ~SOL_CMA_CALLER_EVENT_PROGRESS;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (chanp->chan_cmid_destroy_state &
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_CMA_CALLER_CMID_DESTROYED) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar cv_broadcast(&chanp->chan_destroy_cv);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_exit(&chanp->chan_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar } else if (chan_state == SOL_CMA_CHAN_DESTROY_PENDING) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar /* If rdma_destroy_id() was called, destroy CMID */
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_exit(&chanp->chan_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar cma_destroy_id((struct rdma_cm_id *)chanp);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar } else
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_exit(&chanp->chan_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar return;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar } else if (IS_UDP_CMID(idp) && event == RDMA_CM_EVENT_UNREACHABLE) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar /*
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 */
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_enter(&chanp->chan_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar chan_state = cma_get_chan_state(chanp);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar chanp->chan_cmid_destroy_state &=
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar ~SOL_CMA_CALLER_EVENT_PROGRESS;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (chanp->chan_cmid_destroy_state &
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_CMA_CALLER_CMID_DESTROYED) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar cv_broadcast(&chanp->chan_destroy_cv);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_exit(&chanp->chan_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar } else if (chan_state == SOL_CMA_CHAN_DESTROY_PENDING) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_exit(&chanp->chan_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar cma_destroy_id(idp);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar } else
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_exit(&chanp->chan_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar return;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar }
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_enter(&chanp->chan_mutex);
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 cv_broadcast(&chanp->chan_destroy_cv);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_exit(&chanp->chan_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar}
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar/* Local Static functions */
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarstatic struct rdma_cm_id *
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarcma_alloc_chan(rdma_cm_event_handler evt_hdlr, void *context,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar enum rdma_port_space ps)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar{
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar struct rdma_cm_id *rdma_idp;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar sol_cma_chan_t *chanp;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
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 rdma_idp = &(chanp->chan_rdma_cm);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar rdma_idp->context = context;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar rdma_idp->ps = ps;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar rdma_idp->event_handler = evt_hdlr;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_enter(&chanp->chan_mutex);
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 sizeof (sol_cma_chan_t),
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 sizeof (sol_cma_chan_t),
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar offsetof(sol_cma_chan_t, chan_acpt_avl_node));
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_exit(&chanp->chan_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar return (rdma_idp);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar}
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar/* Change the state of sol_cma_chan_t */
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarstatic void
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarcma_set_chan_state(sol_cma_chan_t *chanp, cma_chan_state_t newstate)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar{
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar ASSERT(MUTEX_HELD(&chanp->chan_mutex));
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar chanp->chan_state = newstate;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar}
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarcma_chan_state_t
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarcma_get_chan_state(sol_cma_chan_t *chanp)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar{
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar ASSERT(MUTEX_HELD(&chanp->chan_mutex));
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar return (chanp->chan_state);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar}
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar/* Check & Swap the state of sol_ucma_chan_t */
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarstatic int
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarcma_cas_chan_state(sol_cma_chan_t *chanp, cma_chan_state_t prevstate,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar cma_chan_state_t newstate)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar{
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar int ret = 0;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar ASSERT(MUTEX_HELD(&chanp->chan_mutex));
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (chanp->chan_state != prevstate)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar ret = -1;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar else
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar chanp->chan_state = newstate;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar return (ret);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar}
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarstatic void
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarcma_free_listen_list(struct rdma_cm_id *idp)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar{
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar genlist_entry_t *entry;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar sol_cma_chan_t *chanp = (sol_cma_chan_t *)idp;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "cma_free_listen_list(%p)", idp);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_enter(&chanp->chan_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar entry = remove_genlist_head(&(CHAN_LISTEN_LIST(chanp)));
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_exit(&chanp->chan_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar while (entry) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar sol_cma_chan_t *ep_chanp;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar ep_chanp = (sol_cma_chan_t *)entry->data;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "fini_ep_chan: %p",
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar ep_chanp);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (ibcma_fini_ep_chan(ep_chanp) == 0) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar genlist_entry_t *entry1;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar struct ib_device *device;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar cma_device_t *cma_device;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar ASSERT(ep_chanp->chan_listenp);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_enter(&ep_chanp->chan_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar entry1 = ep_chanp->chan_listenp->listen_ep_dev_entry;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar device = ep_chanp->chan_listenp->listen_ep_device;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar ASSERT(device);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar cma_device = device->data;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar delete_genlist(&cma_device->cma_epchan_list,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar entry1);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar sol_cma_release_device(
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar (struct rdma_cm_id *)ep_chanp);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_exit(&ep_chanp->chan_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (ep_chanp->chan_listenp)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar kmem_free(ep_chanp->chan_listenp,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar sizeof (sol_cma_listen_info_t));
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_destroy(&ep_chanp->chan_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar cv_destroy(&ep_chanp->chan_destroy_cv);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar kmem_free(ep_chanp, sizeof (sol_cma_chan_t));
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar kmem_free(entry, sizeof (genlist_entry_t));
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar }
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_enter(&chanp->chan_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar entry = remove_genlist_head(&(CHAN_LISTEN_LIST(chanp)));
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_exit(&chanp->chan_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar }
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar}
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar/*
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * Destroy a listening CMID when :
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * a. All CONNECTION REQUEST recieved have been rejected
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * or closed.
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 *
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 *
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * Mark the CMID as destroy pending.
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar *
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 *
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * If there is a listening CMID assosiated with it,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * call cma_destroy_if(listen_cmid);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar */
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarvoid
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarcma_destroy_id(struct rdma_cm_id *idp)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar{
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar sol_cma_chan_t *chanp = (sol_cma_chan_t *)idp;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar cma_chan_state_t state;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar ulong_t acpt_nodes, req_nodes;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_enter(&chanp->chan_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar acpt_nodes = avl_numnodes(&chanp->chan_acpt_avl_tree);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar req_nodes = avl_numnodes(&chanp->chan_req_avl_tree);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar state = cma_get_chan_state(chanp);
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 state, chanp->chan_req_state);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar /*
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 */
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (acpt_nodes || req_nodes) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar cma_set_chan_state(chanp, SOL_CMA_CHAN_DESTROY_PENDING);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_exit(&chanp->chan_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar return;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar }
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar cma_set_chan_state(chanp, SOL_CMA_CHAN_DESTROYING);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar avl_destroy(&chanp->chan_req_avl_tree);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar avl_destroy(&chanp->chan_acpt_avl_tree);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_exit(&chanp->chan_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (idp->route.path_rec) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar kmem_free(idp->route.path_rec,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar sizeof (struct ib_sa_path_rec) * idp->route.num_paths);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar idp->route.path_rec = NULL;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar }
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar switch (chanp->chan_xport_type) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar case SOL_CMA_XPORT_NONE :
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar break;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar case SOL_CMA_XPORT_IB :
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar rdma_ib_destroy_id(idp);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar break;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar#ifdef IWARP_SUPPORT
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar case SOL_CMA_XPORT_IWARP :
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar rdma_iw_destroy_id(idp);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar break;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar#endif /* IWARP_SUPPORT */
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar default :
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_OFS_DPRINTF_L2(sol_rdmacm_dbg_str,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar "cma_destroy_id: Unsupported xport type %x",
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar chanp->chan_xport_type);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar break;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar }
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar /*
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 */
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (chanp->chan_listenp) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar cma_free_listen_list(idp);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar cma_fini_listen_root(chanp);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar kmem_free((void *)chanp->chan_listenp,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar sizeof (sol_cma_listen_info_t));
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar chanp->chan_listenp = NULL;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar }
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (chanp->listen_root) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar struct rdma_cm_id *root_idp;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar sol_cma_chan_t *root_chanp;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar root_idp = chanp->listen_root;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar root_chanp = (sol_cma_chan_t *)root_idp;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_enter(&root_chanp->chan_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar state = cma_get_chan_state(root_chanp);
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 mutex_exit(&root_chanp->chan_mutex);
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
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (state == SOL_CMA_CHAN_DESTROY_PENDING &&
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar req_nodes == 0UL && acpt_nodes == 0UL) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_enter(&root_chanp->chan_mutex);
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung root_chanp->chan_req_state = REQ_CMID_SERVER_NONE;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_exit(&root_chanp->chan_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar cma_destroy_id(root_idp);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar } else if (state == SOL_CMA_CHAN_DESTROY_WAIT &&
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar req_nodes == 0UL && acpt_nodes == 0UL) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_enter(&root_chanp->chan_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar cma_set_chan_state(root_chanp,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar SOL_CMA_CHAN_DESTROY_PENDING);
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung root_chanp->chan_req_state = REQ_CMID_SERVER_NONE;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar cv_broadcast(&root_chanp->chan_destroy_cv);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_exit(&root_chanp->chan_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar }
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar }
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_destroy(&chanp->chan_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar cv_destroy(&chanp->chan_destroy_cv);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar kmem_free(chanp, sizeof (sol_cma_chan_t));
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar}
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar/*
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 Gunjikar *
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar */
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarstatic void
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarcma_handle_nomore_events(sol_cma_chan_t *chanp)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar{
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar struct rdma_cm_id *idp, *root_idp;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar sol_cma_chan_t *root_chanp;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar cma_chan_state_t state;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar ulong_t req_nodes, acpt_nodes;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar idp = (struct rdma_cm_id *)chanp;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar root_idp = CHAN_LISTEN_ROOT(chanp);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar root_chanp = (sol_cma_chan_t *)root_idp;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (!root_chanp)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar return;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_enter(&root_chanp->chan_mutex);
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung mutex_enter(&chanp->chan_mutex);
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung CHAN_LISTEN_ROOT(chanp) = NULL;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar root_chanp->chan_req_total_cnt--;
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung /*
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 */
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung if (chanp->chan_req_state == REQ_CMID_ACCEPTED) {
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung ASSERT(chanp->chan_qp_hdl);
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung ASSERT(cma_get_acpt_idp(root_idp,
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung chanp->chan_qp_hdl));
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar avl_remove(&root_chanp->chan_acpt_avl_tree, idp);
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung chanp->chan_req_state = REQ_CMID_SERVER_NONE;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung if (REQ_CMID_IN_REQ_AVL_TREE(chanp)) {
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung ASSERT(chanp->chan_session_id);
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung ASSERT(cma_get_req_idp(root_idp,
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung chanp->chan_session_id));
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar avl_remove(&root_chanp->chan_req_avl_tree, idp);
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung chanp->chan_req_state = REQ_CMID_SERVER_NONE;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar state = cma_get_chan_state(root_chanp);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar req_nodes = avl_numnodes(&root_chanp->chan_req_avl_tree);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar acpt_nodes = avl_numnodes(&root_chanp->chan_acpt_avl_tree);
fffafeb2cc01732fd6a28ed530e4424094685eceJohnny Cheung mutex_exit(&chanp->chan_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar mutex_exit(&root_chanp->chan_mutex);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (state == SOL_CMA_CHAN_DESTROY_PENDING && req_nodes == 0UL &&
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar acpt_nodes == 0UL)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar cma_destroy_id(root_idp);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
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 Ota int *);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otastatic int
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otacma_init_ud_qp(sol_cma_chan_t *chanp, struct ib_qp *qp)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota struct ib_qp_attr qp_attr;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota int qp_attr_mask, ret;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota qp_attr.qp_state = IB_QPS_INIT;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ret = rdma_init_qp_attr(&chanp->chan_rdma_cm, &qp_attr, &qp_attr_mask);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (ret)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (ret);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ret = ib_modify_qp(qp, &qp_attr, qp_attr_mask);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (ret)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (ret);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota qp_attr.qp_state = IB_QPS_RTR;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ret = ib_modify_qp(qp, &qp_attr, IB_QP_STATE);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (ret)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (ret);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota qp_attr.qp_state = IB_QPS_RTS;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota qp_attr.sq_psn = 0;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ret = ib_modify_qp(qp, &qp_attr, IB_QP_STATE | IB_QP_SQ_PSN);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (ret);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otastatic int
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otacma_init_conn_qp(sol_cma_chan_t *chanp, struct ib_qp *qp)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota struct ib_qp_attr qp_attr;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota int qp_attr_mask, ret;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota qp_attr.qp_state = IB_QPS_INIT;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ret = rdma_init_qp_attr(&chanp->chan_rdma_cm, &qp_attr, &qp_attr_mask);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (ret)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (ret);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (ib_modify_qp(qp, &qp_attr, qp_attr_mask));
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otastatic inline int
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otacma_is_ud_ps(enum rdma_port_space ps)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (ps == RDMA_PS_UDP || ps == RDMA_PS_IPOIB);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otaint
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otardma_create_qp(struct rdma_cm_id *idp, struct ib_pd *pd,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota struct ib_qp_init_attr *qp_init_attr)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota sol_cma_chan_t *chanp;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota struct ib_qp *qp;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota int ret;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ofs_client_t *dev_ofs_client;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ASSERT(idp);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota chanp = (sol_cma_chan_t *)idp;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (idp->device->node_guid != pd->device->node_guid)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (-EINVAL);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
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
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota qp = ib_create_qp(pd, qp_init_attr);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if ((uintptr_t)qp >= (uintptr_t)-0xFFF) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return ((intptr_t)qp);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rdma_map_id2qphdl(idp, (void *)qp->ibt_qp);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (cma_is_ud_ps(idp->ps)) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ret = cma_init_ud_qp(chanp, qp);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota } else {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ret = cma_init_conn_qp(chanp, qp);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (ret) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota goto err;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota idp->qp = qp;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota chanp->chan_qp_num = qp->qp_num;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota chanp->chan_is_srq = (qp->srq != NULL);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (0);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otaerr:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota (void) ib_destroy_qp(qp);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (ret);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otavoid
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otardma_destroy_qp(struct rdma_cm_id *idp)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ASSERT(idp);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota (void) ib_destroy_qp(idp->qp);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota idp->qp = NULL;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}