10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 57387SRobert.Gordon@Sun.COM * Common Development and Distribution License (the "License"). 67387SRobert.Gordon@Sun.COM * You may not use this file except in compliance with the License. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 100Sstevel@tonic-gate * See the License for the specific language governing permissions 110Sstevel@tonic-gate * and limitations under the License. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * CDDL HEADER END 200Sstevel@tonic-gate */ 210Sstevel@tonic-gate /* 22*8695SRajkumar.Sivaprakasam@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 230Sstevel@tonic-gate * Use is subject to license terms. 240Sstevel@tonic-gate */ 250Sstevel@tonic-gate 267387SRobert.Gordon@Sun.COM /* 27*8695SRajkumar.Sivaprakasam@Sun.COM * Copyright (c) 2008, The Ohio State University. All rights reserved. 287387SRobert.Gordon@Sun.COM * 297387SRobert.Gordon@Sun.COM * Portions of this source code is developed by the team members of 307387SRobert.Gordon@Sun.COM * The Ohio State University's Network-Based Computing Laboratory (NBCL), 317387SRobert.Gordon@Sun.COM * headed by Professor Dhabaleswar K. (DK) Panda. 327387SRobert.Gordon@Sun.COM * 337387SRobert.Gordon@Sun.COM * Acknowledgements to contributions from developors: 347387SRobert.Gordon@Sun.COM * Ranjit Noronha: noronha@cse.ohio-state.edu 357387SRobert.Gordon@Sun.COM * Lei Chai : chail@cse.ohio-state.edu 367387SRobert.Gordon@Sun.COM * Weikuan Yu : yuw@cse.ohio-state.edu 377387SRobert.Gordon@Sun.COM * 387387SRobert.Gordon@Sun.COM */ 390Sstevel@tonic-gate 400Sstevel@tonic-gate #include <sys/systm.h> 410Sstevel@tonic-gate #include <sys/kstat.h> 420Sstevel@tonic-gate #include <sys/modctl.h> 437387SRobert.Gordon@Sun.COM #include <sys/sdt.h> 440Sstevel@tonic-gate #include <rpc/rpc_rdma.h> 450Sstevel@tonic-gate 460Sstevel@tonic-gate #include <sys/ib/ibtl/ibti.h> 470Sstevel@tonic-gate 480Sstevel@tonic-gate uint_t rdma_minchunk = RDMA_MINCHUNK; 490Sstevel@tonic-gate 500Sstevel@tonic-gate /* 510Sstevel@tonic-gate * Globals 520Sstevel@tonic-gate */ 530Sstevel@tonic-gate int rdma_modloaded = 0; /* flag to load RDMA plugin modules */ 540Sstevel@tonic-gate int rdma_dev_available = 0; /* if any RDMA device is loaded */ 550Sstevel@tonic-gate kmutex_t rdma_modload_lock; /* protects rdma_modloaded flag */ 56*8695SRajkumar.Sivaprakasam@Sun.COM 57*8695SRajkumar.Sivaprakasam@Sun.COM rdma_svc_wait_t rdma_wait; 58*8695SRajkumar.Sivaprakasam@Sun.COM 590Sstevel@tonic-gate rdma_registry_t *rdma_mod_head = NULL; /* head for RDMA modules */ 600Sstevel@tonic-gate krwlock_t rdma_lock; /* protects rdma_mod_head list */ 610Sstevel@tonic-gate ldi_ident_t rpcmod_li = NULL; /* identifies us with ldi_ framework */ 620Sstevel@tonic-gate 637387SRobert.Gordon@Sun.COM kmem_cache_t *clist_cache = NULL; 647387SRobert.Gordon@Sun.COM 650Sstevel@tonic-gate /* 660Sstevel@tonic-gate * Statics 670Sstevel@tonic-gate */ 68*8695SRajkumar.Sivaprakasam@Sun.COM ldi_handle_t rpcib_handle = NULL; 690Sstevel@tonic-gate 700Sstevel@tonic-gate /* 710Sstevel@tonic-gate * Externs 720Sstevel@tonic-gate */ 730Sstevel@tonic-gate extern kstat_named_t *rdmarcstat_ptr; 740Sstevel@tonic-gate extern uint_t rdmarcstat_ndata; 750Sstevel@tonic-gate extern kstat_named_t *rdmarsstat_ptr; 760Sstevel@tonic-gate extern uint_t rdmarsstat_ndata; 770Sstevel@tonic-gate 780Sstevel@tonic-gate void rdma_kstat_init(); 790Sstevel@tonic-gate 800Sstevel@tonic-gate /* 810Sstevel@tonic-gate * RDMATF module registration routine. 820Sstevel@tonic-gate * This routine is expected to be called by the init routine in 830Sstevel@tonic-gate * the plugin modules. 840Sstevel@tonic-gate */ 850Sstevel@tonic-gate rdma_stat 860Sstevel@tonic-gate rdma_register_mod(rdma_mod_t *mod) 870Sstevel@tonic-gate { 880Sstevel@tonic-gate rdma_registry_t **mp, *m; 890Sstevel@tonic-gate 900Sstevel@tonic-gate if (mod->rdma_version != RDMATF_VERS) { 910Sstevel@tonic-gate return (RDMA_BADVERS); 920Sstevel@tonic-gate } 930Sstevel@tonic-gate 940Sstevel@tonic-gate rw_enter(&rdma_lock, RW_WRITER); 950Sstevel@tonic-gate /* 960Sstevel@tonic-gate * Ensure not already registered 970Sstevel@tonic-gate */ 980Sstevel@tonic-gate mp = &rdma_mod_head; 990Sstevel@tonic-gate while (*mp != NULL) { 1000Sstevel@tonic-gate if (strncmp((*mp)->r_mod->rdma_api, mod->rdma_api, 1010Sstevel@tonic-gate KNC_STRSIZE) == 0) { 102*8695SRajkumar.Sivaprakasam@Sun.COM if ((*mp)->r_mod_state == RDMA_MOD_INACTIVE) { 103*8695SRajkumar.Sivaprakasam@Sun.COM (*mp)->r_mod_state = RDMA_MOD_ACTIVE; 104*8695SRajkumar.Sivaprakasam@Sun.COM (*mp)->r_mod->rdma_ops = mod->rdma_ops; 105*8695SRajkumar.Sivaprakasam@Sun.COM (*mp)->r_mod->rdma_count = mod->rdma_count; 106*8695SRajkumar.Sivaprakasam@Sun.COM goto announce_hca; 107*8695SRajkumar.Sivaprakasam@Sun.COM } 1080Sstevel@tonic-gate rw_exit(&rdma_lock); 1090Sstevel@tonic-gate return (RDMA_REG_EXIST); 1100Sstevel@tonic-gate } 1110Sstevel@tonic-gate mp = &((*mp)->r_next); 1120Sstevel@tonic-gate } 1130Sstevel@tonic-gate 1140Sstevel@tonic-gate /* 1150Sstevel@tonic-gate * New one, create and add to registry 1160Sstevel@tonic-gate */ 1170Sstevel@tonic-gate m = kmem_alloc(sizeof (rdma_registry_t), KM_SLEEP); 1180Sstevel@tonic-gate m->r_mod = kmem_alloc(sizeof (rdma_mod_t), KM_SLEEP); 1190Sstevel@tonic-gate *m->r_mod = *mod; 1200Sstevel@tonic-gate m->r_next = NULL; 1210Sstevel@tonic-gate m->r_mod->rdma_api = kmem_zalloc(KNC_STRSIZE, KM_SLEEP); 1220Sstevel@tonic-gate (void) strncpy(m->r_mod->rdma_api, mod->rdma_api, KNC_STRSIZE); 1230Sstevel@tonic-gate m->r_mod->rdma_api[KNC_STRSIZE - 1] = '\0'; 124*8695SRajkumar.Sivaprakasam@Sun.COM m->r_mod_state = RDMA_MOD_ACTIVE; 1250Sstevel@tonic-gate *mp = m; 126*8695SRajkumar.Sivaprakasam@Sun.COM 127*8695SRajkumar.Sivaprakasam@Sun.COM announce_hca: 1280Sstevel@tonic-gate rw_exit(&rdma_lock); 129*8695SRajkumar.Sivaprakasam@Sun.COM /* 130*8695SRajkumar.Sivaprakasam@Sun.COM * Start the nfs service on the rdma xprts. 131*8695SRajkumar.Sivaprakasam@Sun.COM * (this notification mechanism will need to change when we support 132*8695SRajkumar.Sivaprakasam@Sun.COM * multiple hcas and have support for multiple rdma plugins). 133*8695SRajkumar.Sivaprakasam@Sun.COM */ 134*8695SRajkumar.Sivaprakasam@Sun.COM mutex_enter(&rdma_wait.svc_lock); 135*8695SRajkumar.Sivaprakasam@Sun.COM rdma_wait.svc_stat = RDMA_HCA_ATTACH; 136*8695SRajkumar.Sivaprakasam@Sun.COM cv_signal(&rdma_wait.svc_cv); 137*8695SRajkumar.Sivaprakasam@Sun.COM mutex_exit(&rdma_wait.svc_lock); 1380Sstevel@tonic-gate 1390Sstevel@tonic-gate return (RDMA_SUCCESS); 1400Sstevel@tonic-gate } 1410Sstevel@tonic-gate 1420Sstevel@tonic-gate /* 1430Sstevel@tonic-gate * RDMATF module unregistration routine. 1440Sstevel@tonic-gate * This routine is expected to be called by the fini routine in 1450Sstevel@tonic-gate * the plugin modules. 1460Sstevel@tonic-gate */ 1470Sstevel@tonic-gate rdma_stat 1480Sstevel@tonic-gate rdma_unregister_mod(rdma_mod_t *mod) 1490Sstevel@tonic-gate { 1500Sstevel@tonic-gate rdma_registry_t **m, *mmod = NULL; 1510Sstevel@tonic-gate 1520Sstevel@tonic-gate rw_enter(&rdma_lock, RW_WRITER); 1530Sstevel@tonic-gate 1540Sstevel@tonic-gate m = &rdma_mod_head; 1550Sstevel@tonic-gate while (*m != NULL) { 1560Sstevel@tonic-gate if (strncmp((*m)->r_mod->rdma_api, mod->rdma_api, 1570Sstevel@tonic-gate KNC_STRSIZE) != 0) { 1580Sstevel@tonic-gate m = &((*m)->r_next); 1590Sstevel@tonic-gate continue; 1600Sstevel@tonic-gate } 1610Sstevel@tonic-gate /* 1620Sstevel@tonic-gate * Check if any device attached, if so return error 1630Sstevel@tonic-gate */ 164*8695SRajkumar.Sivaprakasam@Sun.COM if (mod->rdma_count != 0) { 1650Sstevel@tonic-gate rw_exit(&rdma_lock); 1660Sstevel@tonic-gate return (RDMA_FAILED); 1670Sstevel@tonic-gate } 1680Sstevel@tonic-gate /* 169*8695SRajkumar.Sivaprakasam@Sun.COM * Found entry. Mark it inactive. 1700Sstevel@tonic-gate */ 1710Sstevel@tonic-gate mmod = *m; 172*8695SRajkumar.Sivaprakasam@Sun.COM mmod->r_mod->rdma_count = 0; 173*8695SRajkumar.Sivaprakasam@Sun.COM mmod->r_mod_state = RDMA_MOD_INACTIVE; 174*8695SRajkumar.Sivaprakasam@Sun.COM break; 1750Sstevel@tonic-gate } 1760Sstevel@tonic-gate 177*8695SRajkumar.Sivaprakasam@Sun.COM rdma_modloaded = 0; 178*8695SRajkumar.Sivaprakasam@Sun.COM rdma_dev_available = 0; 179*8695SRajkumar.Sivaprakasam@Sun.COM rw_exit(&rdma_lock); 180*8695SRajkumar.Sivaprakasam@Sun.COM 181*8695SRajkumar.Sivaprakasam@Sun.COM /* 182*8695SRajkumar.Sivaprakasam@Sun.COM * Stop the nfs service running on the rdma xprts. 183*8695SRajkumar.Sivaprakasam@Sun.COM * (this notification mechanism will need to change when we support 184*8695SRajkumar.Sivaprakasam@Sun.COM * multiple hcas and have support for multiple rdma plugins). 185*8695SRajkumar.Sivaprakasam@Sun.COM */ 186*8695SRajkumar.Sivaprakasam@Sun.COM mutex_enter(&rdma_wait.svc_lock); 187*8695SRajkumar.Sivaprakasam@Sun.COM rdma_wait.svc_stat = RDMA_HCA_DETACH; 188*8695SRajkumar.Sivaprakasam@Sun.COM cv_signal(&rdma_wait.svc_cv); 189*8695SRajkumar.Sivaprakasam@Sun.COM mutex_exit(&rdma_wait.svc_lock); 190*8695SRajkumar.Sivaprakasam@Sun.COM 1910Sstevel@tonic-gate /* 1920Sstevel@tonic-gate * Not found. 1930Sstevel@tonic-gate */ 194*8695SRajkumar.Sivaprakasam@Sun.COM return (RDMA_SUCCESS); 1950Sstevel@tonic-gate } 1960Sstevel@tonic-gate 1977387SRobert.Gordon@Sun.COM struct clist * 1987387SRobert.Gordon@Sun.COM clist_alloc(void) 1997387SRobert.Gordon@Sun.COM { 2007387SRobert.Gordon@Sun.COM struct clist *clp; 2017387SRobert.Gordon@Sun.COM 2027387SRobert.Gordon@Sun.COM clp = kmem_cache_alloc(clist_cache, KM_SLEEP); 2037387SRobert.Gordon@Sun.COM 2047387SRobert.Gordon@Sun.COM bzero(clp, sizeof (*clp)); 2057387SRobert.Gordon@Sun.COM 2067387SRobert.Gordon@Sun.COM return (clp); 2077387SRobert.Gordon@Sun.COM } 2087387SRobert.Gordon@Sun.COM 2090Sstevel@tonic-gate /* 2100Sstevel@tonic-gate * Creates a new chunk list entry, and 2110Sstevel@tonic-gate * adds it to the end of a chunk list. 2120Sstevel@tonic-gate */ 2130Sstevel@tonic-gate void 2140Sstevel@tonic-gate clist_add(struct clist **clp, uint32_t xdroff, int len, 2150Sstevel@tonic-gate struct mrc *shandle, caddr_t saddr, 2160Sstevel@tonic-gate struct mrc *dhandle, caddr_t daddr) 2170Sstevel@tonic-gate { 2180Sstevel@tonic-gate struct clist *cl; 2190Sstevel@tonic-gate 2200Sstevel@tonic-gate /* Find the end of the list */ 2210Sstevel@tonic-gate 2220Sstevel@tonic-gate while (*clp != NULL) 2230Sstevel@tonic-gate clp = &((*clp)->c_next); 2240Sstevel@tonic-gate 2257387SRobert.Gordon@Sun.COM cl = clist_alloc(); 2260Sstevel@tonic-gate cl->c_xdroff = xdroff; 2270Sstevel@tonic-gate cl->c_len = len; 2287387SRobert.Gordon@Sun.COM cl->w.c_saddr = (uint64_t)(uintptr_t)saddr; 2290Sstevel@tonic-gate if (shandle) 2300Sstevel@tonic-gate cl->c_smemhandle = *shandle; 2317387SRobert.Gordon@Sun.COM cl->u.c_daddr = (uint64_t)(uintptr_t)daddr; 2320Sstevel@tonic-gate if (dhandle) 2330Sstevel@tonic-gate cl->c_dmemhandle = *dhandle; 2340Sstevel@tonic-gate cl->c_next = NULL; 2350Sstevel@tonic-gate 2360Sstevel@tonic-gate *clp = cl; 2370Sstevel@tonic-gate } 2380Sstevel@tonic-gate 2397387SRobert.Gordon@Sun.COM rdma_stat 2407387SRobert.Gordon@Sun.COM clist_register(CONN *conn, struct clist *cl, clist_dstsrc dstsrc) 2410Sstevel@tonic-gate { 2420Sstevel@tonic-gate struct clist *c; 2430Sstevel@tonic-gate int status; 2440Sstevel@tonic-gate 2450Sstevel@tonic-gate for (c = cl; c; c = c->c_next) { 2467387SRobert.Gordon@Sun.COM if (c->c_len <= 0) 2477387SRobert.Gordon@Sun.COM continue; 2487387SRobert.Gordon@Sun.COM switch (dstsrc) { 2497387SRobert.Gordon@Sun.COM case CLIST_REG_SOURCE: 2500Sstevel@tonic-gate status = RDMA_REGMEMSYNC(conn, 2517387SRobert.Gordon@Sun.COM (caddr_t)(struct as *)cl->c_adspc, 2527387SRobert.Gordon@Sun.COM (caddr_t)(uintptr_t)c->w.c_saddr3, c->c_len, 2537387SRobert.Gordon@Sun.COM &c->c_smemhandle, (void **)&c->c_ssynchandle, 2547387SRobert.Gordon@Sun.COM (void *)c->rb_longbuf.rb_private); 2557387SRobert.Gordon@Sun.COM break; 2567387SRobert.Gordon@Sun.COM case CLIST_REG_DST: 2570Sstevel@tonic-gate status = RDMA_REGMEMSYNC(conn, 2587387SRobert.Gordon@Sun.COM (caddr_t)(struct as *)cl->c_adspc, 2597387SRobert.Gordon@Sun.COM (caddr_t)(uintptr_t)c->u.c_daddr3, c->c_len, 2607387SRobert.Gordon@Sun.COM &c->c_dmemhandle, (void **)&c->c_dsynchandle, 2617387SRobert.Gordon@Sun.COM (void *)c->rb_longbuf.rb_private); 2627387SRobert.Gordon@Sun.COM break; 2637387SRobert.Gordon@Sun.COM default: 2647387SRobert.Gordon@Sun.COM return (RDMA_INVAL); 2650Sstevel@tonic-gate } 2660Sstevel@tonic-gate if (status != RDMA_SUCCESS) { 2677387SRobert.Gordon@Sun.COM (void) clist_deregister(conn, cl, dstsrc); 2680Sstevel@tonic-gate return (status); 2690Sstevel@tonic-gate } 2700Sstevel@tonic-gate } 2710Sstevel@tonic-gate 2720Sstevel@tonic-gate return (RDMA_SUCCESS); 2730Sstevel@tonic-gate } 2740Sstevel@tonic-gate 2757387SRobert.Gordon@Sun.COM rdma_stat 2767387SRobert.Gordon@Sun.COM clist_deregister(CONN *conn, struct clist *cl, clist_dstsrc dstsrc) 2770Sstevel@tonic-gate { 2780Sstevel@tonic-gate struct clist *c; 2790Sstevel@tonic-gate 2800Sstevel@tonic-gate for (c = cl; c; c = c->c_next) { 2817387SRobert.Gordon@Sun.COM switch (dstsrc) { 2827387SRobert.Gordon@Sun.COM case CLIST_REG_SOURCE: 2830Sstevel@tonic-gate if (c->c_smemhandle.mrc_rmr != 0) { 2840Sstevel@tonic-gate (void) RDMA_DEREGMEMSYNC(conn, 2857387SRobert.Gordon@Sun.COM (caddr_t)(uintptr_t)c->w.c_saddr3, 2860Sstevel@tonic-gate c->c_smemhandle, 2877387SRobert.Gordon@Sun.COM (void *)(uintptr_t)c->c_ssynchandle, 2887387SRobert.Gordon@Sun.COM (void *)c->rb_longbuf.rb_private); 2890Sstevel@tonic-gate c->c_smemhandle.mrc_rmr = 0; 2900Sstevel@tonic-gate c->c_ssynchandle = NULL; 2910Sstevel@tonic-gate } 2927387SRobert.Gordon@Sun.COM break; 2937387SRobert.Gordon@Sun.COM case CLIST_REG_DST: 2940Sstevel@tonic-gate if (c->c_dmemhandle.mrc_rmr != 0) { 2950Sstevel@tonic-gate (void) RDMA_DEREGMEMSYNC(conn, 2967387SRobert.Gordon@Sun.COM (caddr_t)(uintptr_t)c->u.c_daddr3, 2970Sstevel@tonic-gate c->c_dmemhandle, 2987387SRobert.Gordon@Sun.COM (void *)(uintptr_t)c->c_dsynchandle, 2997387SRobert.Gordon@Sun.COM (void *)c->rb_longbuf.rb_private); 3000Sstevel@tonic-gate c->c_dmemhandle.mrc_rmr = 0; 3010Sstevel@tonic-gate c->c_dsynchandle = NULL; 3020Sstevel@tonic-gate } 3037387SRobert.Gordon@Sun.COM break; 3047387SRobert.Gordon@Sun.COM default: 3057387SRobert.Gordon@Sun.COM return (RDMA_INVAL); 3060Sstevel@tonic-gate } 3070Sstevel@tonic-gate } 3080Sstevel@tonic-gate 3090Sstevel@tonic-gate return (RDMA_SUCCESS); 3100Sstevel@tonic-gate } 3110Sstevel@tonic-gate 3127387SRobert.Gordon@Sun.COM rdma_stat 3137387SRobert.Gordon@Sun.COM clist_syncmem(CONN *conn, struct clist *cl, clist_dstsrc dstsrc) 3147387SRobert.Gordon@Sun.COM { 3157387SRobert.Gordon@Sun.COM struct clist *c; 3167387SRobert.Gordon@Sun.COM rdma_stat status; 3177387SRobert.Gordon@Sun.COM 3187387SRobert.Gordon@Sun.COM c = cl; 3197387SRobert.Gordon@Sun.COM switch (dstsrc) { 3207387SRobert.Gordon@Sun.COM case CLIST_REG_SOURCE: 3217387SRobert.Gordon@Sun.COM while (c != NULL) { 3227387SRobert.Gordon@Sun.COM if (c->c_ssynchandle) { 3237387SRobert.Gordon@Sun.COM status = RDMA_SYNCMEM(conn, 3247387SRobert.Gordon@Sun.COM (void *)(uintptr_t)c->c_ssynchandle, 3257387SRobert.Gordon@Sun.COM (caddr_t)(uintptr_t)c->w.c_saddr3, 3267387SRobert.Gordon@Sun.COM c->c_len, 0); 3277387SRobert.Gordon@Sun.COM if (status != RDMA_SUCCESS) 3287387SRobert.Gordon@Sun.COM return (status); 3297387SRobert.Gordon@Sun.COM } 3307387SRobert.Gordon@Sun.COM c = c->c_next; 3317387SRobert.Gordon@Sun.COM } 3327387SRobert.Gordon@Sun.COM break; 3337387SRobert.Gordon@Sun.COM case CLIST_REG_DST: 3347387SRobert.Gordon@Sun.COM while (c != NULL) { 3357387SRobert.Gordon@Sun.COM if (c->c_ssynchandle) { 3367387SRobert.Gordon@Sun.COM status = RDMA_SYNCMEM(conn, 3377387SRobert.Gordon@Sun.COM (void *)(uintptr_t)c->c_dsynchandle, 3387387SRobert.Gordon@Sun.COM (caddr_t)(uintptr_t)c->u.c_daddr3, 3397387SRobert.Gordon@Sun.COM c->c_len, 1); 3407387SRobert.Gordon@Sun.COM if (status != RDMA_SUCCESS) 3417387SRobert.Gordon@Sun.COM return (status); 3427387SRobert.Gordon@Sun.COM } 3437387SRobert.Gordon@Sun.COM c = c->c_next; 3447387SRobert.Gordon@Sun.COM } 3457387SRobert.Gordon@Sun.COM break; 3467387SRobert.Gordon@Sun.COM default: 3477387SRobert.Gordon@Sun.COM return (RDMA_INVAL); 3487387SRobert.Gordon@Sun.COM } 3497387SRobert.Gordon@Sun.COM 3507387SRobert.Gordon@Sun.COM return (RDMA_SUCCESS); 3517387SRobert.Gordon@Sun.COM } 3527387SRobert.Gordon@Sun.COM 3530Sstevel@tonic-gate /* 3540Sstevel@tonic-gate * Frees up entries in chunk list 3550Sstevel@tonic-gate */ 3560Sstevel@tonic-gate void 3570Sstevel@tonic-gate clist_free(struct clist *cl) 3580Sstevel@tonic-gate { 3590Sstevel@tonic-gate struct clist *c = cl; 3600Sstevel@tonic-gate 3610Sstevel@tonic-gate while (c != NULL) { 3620Sstevel@tonic-gate cl = cl->c_next; 3637387SRobert.Gordon@Sun.COM kmem_cache_free(clist_cache, c); 3640Sstevel@tonic-gate c = cl; 3650Sstevel@tonic-gate } 3660Sstevel@tonic-gate } 3670Sstevel@tonic-gate 3680Sstevel@tonic-gate rdma_stat 3690Sstevel@tonic-gate rdma_clnt_postrecv(CONN *conn, uint32_t xid) 3700Sstevel@tonic-gate { 3710Sstevel@tonic-gate struct clist *cl = NULL; 3720Sstevel@tonic-gate rdma_stat retval; 3737387SRobert.Gordon@Sun.COM rdma_buf_t rbuf = {0}; 3740Sstevel@tonic-gate 3750Sstevel@tonic-gate rbuf.type = RECV_BUFFER; 3760Sstevel@tonic-gate if (RDMA_BUF_ALLOC(conn, &rbuf)) { 3777387SRobert.Gordon@Sun.COM return (RDMA_NORESOURCE); 3780Sstevel@tonic-gate } 3797387SRobert.Gordon@Sun.COM 3807387SRobert.Gordon@Sun.COM clist_add(&cl, 0, rbuf.len, &rbuf.handle, rbuf.addr, 3817387SRobert.Gordon@Sun.COM NULL, NULL); 3827387SRobert.Gordon@Sun.COM retval = RDMA_CLNT_RECVBUF(conn, cl, xid); 3837387SRobert.Gordon@Sun.COM clist_free(cl); 3847387SRobert.Gordon@Sun.COM 3850Sstevel@tonic-gate return (retval); 3860Sstevel@tonic-gate } 3870Sstevel@tonic-gate 3880Sstevel@tonic-gate rdma_stat 3897387SRobert.Gordon@Sun.COM rdma_clnt_postrecv_remove(CONN *conn, uint32_t xid) 3907387SRobert.Gordon@Sun.COM { 3917387SRobert.Gordon@Sun.COM return (RDMA_CLNT_RECVBUF_REMOVE(conn, xid)); 3927387SRobert.Gordon@Sun.COM } 3937387SRobert.Gordon@Sun.COM 3947387SRobert.Gordon@Sun.COM rdma_stat 3950Sstevel@tonic-gate rdma_svc_postrecv(CONN *conn) 3960Sstevel@tonic-gate { 3970Sstevel@tonic-gate struct clist *cl = NULL; 3980Sstevel@tonic-gate rdma_stat retval; 3997387SRobert.Gordon@Sun.COM rdma_buf_t rbuf = {0}; 4000Sstevel@tonic-gate 4010Sstevel@tonic-gate rbuf.type = RECV_BUFFER; 4020Sstevel@tonic-gate if (RDMA_BUF_ALLOC(conn, &rbuf)) { 4030Sstevel@tonic-gate retval = RDMA_NORESOURCE; 4040Sstevel@tonic-gate } else { 4050Sstevel@tonic-gate clist_add(&cl, 0, rbuf.len, &rbuf.handle, rbuf.addr, 4067387SRobert.Gordon@Sun.COM NULL, NULL); 4070Sstevel@tonic-gate retval = RDMA_SVC_RECVBUF(conn, cl); 4080Sstevel@tonic-gate clist_free(cl); 4090Sstevel@tonic-gate } 4100Sstevel@tonic-gate return (retval); 4110Sstevel@tonic-gate } 4120Sstevel@tonic-gate 4130Sstevel@tonic-gate rdma_stat 4147387SRobert.Gordon@Sun.COM rdma_buf_alloc(CONN *conn, rdma_buf_t *rbuf) 4150Sstevel@tonic-gate { 4167387SRobert.Gordon@Sun.COM return (RDMA_BUF_ALLOC(conn, rbuf)); 4170Sstevel@tonic-gate } 4180Sstevel@tonic-gate 4190Sstevel@tonic-gate void 4200Sstevel@tonic-gate rdma_buf_free(CONN *conn, rdma_buf_t *rbuf) 4210Sstevel@tonic-gate { 4220Sstevel@tonic-gate if (!rbuf || rbuf->addr == NULL) { 4230Sstevel@tonic-gate return; 4240Sstevel@tonic-gate } 4257387SRobert.Gordon@Sun.COM RDMA_BUF_FREE(conn, rbuf); 4267387SRobert.Gordon@Sun.COM bzero(rbuf, sizeof (rdma_buf_t)); 4270Sstevel@tonic-gate } 4280Sstevel@tonic-gate 4290Sstevel@tonic-gate /* 4300Sstevel@tonic-gate * Caller is holding rdma_modload_lock mutex 4310Sstevel@tonic-gate */ 4320Sstevel@tonic-gate int 4330Sstevel@tonic-gate rdma_modload() 4340Sstevel@tonic-gate { 4350Sstevel@tonic-gate int status; 4360Sstevel@tonic-gate ASSERT(MUTEX_HELD(&rdma_modload_lock)); 4370Sstevel@tonic-gate /* 4380Sstevel@tonic-gate * Load all available RDMA plugins which right now is only IB plugin. 4390Sstevel@tonic-gate * If no IB hardware is present, then quit right away. 4400Sstevel@tonic-gate * ENODEV -- For no device on the system 4410Sstevel@tonic-gate * EPROTONOSUPPORT -- For module not avilable either due to failure to 4420Sstevel@tonic-gate * load or some other reason. 4430Sstevel@tonic-gate */ 4440Sstevel@tonic-gate rdma_modloaded = 1; 4450Sstevel@tonic-gate if (ibt_hw_is_present() == 0) { 4460Sstevel@tonic-gate rdma_dev_available = 0; 4470Sstevel@tonic-gate return (ENODEV); 4480Sstevel@tonic-gate } 4490Sstevel@tonic-gate 4500Sstevel@tonic-gate rdma_dev_available = 1; 4510Sstevel@tonic-gate if (rpcmod_li == NULL) 4520Sstevel@tonic-gate return (EPROTONOSUPPORT); 4530Sstevel@tonic-gate 4540Sstevel@tonic-gate status = ldi_open_by_name("/devices/ib/rpcib@0:rpcib", 4550Sstevel@tonic-gate FREAD | FWRITE, kcred, 4560Sstevel@tonic-gate &rpcib_handle, rpcmod_li); 457*8695SRajkumar.Sivaprakasam@Sun.COM 4580Sstevel@tonic-gate if (status != 0) 4590Sstevel@tonic-gate return (EPROTONOSUPPORT); 4600Sstevel@tonic-gate 4617387SRobert.Gordon@Sun.COM 462*8695SRajkumar.Sivaprakasam@Sun.COM /* 463*8695SRajkumar.Sivaprakasam@Sun.COM * We will need to reload the plugin module after it was unregistered 464*8695SRajkumar.Sivaprakasam@Sun.COM * but the resources below need to allocated only the first time. 465*8695SRajkumar.Sivaprakasam@Sun.COM */ 466*8695SRajkumar.Sivaprakasam@Sun.COM if (!clist_cache) { 467*8695SRajkumar.Sivaprakasam@Sun.COM clist_cache = kmem_cache_create("rdma_clist", 468*8695SRajkumar.Sivaprakasam@Sun.COM sizeof (struct clist), _POINTER_ALIGNMENT, NULL, 469*8695SRajkumar.Sivaprakasam@Sun.COM NULL, NULL, NULL, 0, 0); 470*8695SRajkumar.Sivaprakasam@Sun.COM rdma_kstat_init(); 471*8695SRajkumar.Sivaprakasam@Sun.COM } 472*8695SRajkumar.Sivaprakasam@Sun.COM 473*8695SRajkumar.Sivaprakasam@Sun.COM (void) ldi_close(rpcib_handle, FREAD|FWRITE, kcred); 4747387SRobert.Gordon@Sun.COM 4750Sstevel@tonic-gate return (0); 4760Sstevel@tonic-gate } 4770Sstevel@tonic-gate 4780Sstevel@tonic-gate void 4790Sstevel@tonic-gate rdma_kstat_init(void) 4800Sstevel@tonic-gate { 4810Sstevel@tonic-gate kstat_t *ksp; 4820Sstevel@tonic-gate 4830Sstevel@tonic-gate /* 4840Sstevel@tonic-gate * The RDMA framework doesn't know how to deal with Zones, and is 4850Sstevel@tonic-gate * only available in the global zone. 4860Sstevel@tonic-gate */ 4870Sstevel@tonic-gate ASSERT(INGLOBALZONE(curproc)); 4880Sstevel@tonic-gate ksp = kstat_create_zone("unix", 0, "rpc_rdma_client", "rpc", 4890Sstevel@tonic-gate KSTAT_TYPE_NAMED, rdmarcstat_ndata, 4900Sstevel@tonic-gate KSTAT_FLAG_VIRTUAL | KSTAT_FLAG_WRITABLE, GLOBAL_ZONEID); 4910Sstevel@tonic-gate if (ksp) { 4920Sstevel@tonic-gate ksp->ks_data = (void *) rdmarcstat_ptr; 4930Sstevel@tonic-gate kstat_install(ksp); 4940Sstevel@tonic-gate } 4950Sstevel@tonic-gate 4960Sstevel@tonic-gate ksp = kstat_create_zone("unix", 0, "rpc_rdma_server", "rpc", 4970Sstevel@tonic-gate KSTAT_TYPE_NAMED, rdmarsstat_ndata, 4980Sstevel@tonic-gate KSTAT_FLAG_VIRTUAL | KSTAT_FLAG_WRITABLE, GLOBAL_ZONEID); 4990Sstevel@tonic-gate if (ksp) { 5000Sstevel@tonic-gate ksp->ks_data = (void *) rdmarsstat_ptr; 5010Sstevel@tonic-gate kstat_install(ksp); 5020Sstevel@tonic-gate } 5030Sstevel@tonic-gate } 504*8695SRajkumar.Sivaprakasam@Sun.COM 505*8695SRajkumar.Sivaprakasam@Sun.COM rdma_stat 506*8695SRajkumar.Sivaprakasam@Sun.COM rdma_kwait(void) 507*8695SRajkumar.Sivaprakasam@Sun.COM { 508*8695SRajkumar.Sivaprakasam@Sun.COM int ret; 509*8695SRajkumar.Sivaprakasam@Sun.COM rdma_stat stat; 510*8695SRajkumar.Sivaprakasam@Sun.COM 511*8695SRajkumar.Sivaprakasam@Sun.COM mutex_enter(&rdma_wait.svc_lock); 512*8695SRajkumar.Sivaprakasam@Sun.COM 513*8695SRajkumar.Sivaprakasam@Sun.COM ret = cv_wait_sig(&rdma_wait.svc_cv, &rdma_wait.svc_lock); 514*8695SRajkumar.Sivaprakasam@Sun.COM 515*8695SRajkumar.Sivaprakasam@Sun.COM /* 516*8695SRajkumar.Sivaprakasam@Sun.COM * If signalled by a hca attach/detach, pass the right 517*8695SRajkumar.Sivaprakasam@Sun.COM * stat back. 518*8695SRajkumar.Sivaprakasam@Sun.COM */ 519*8695SRajkumar.Sivaprakasam@Sun.COM 520*8695SRajkumar.Sivaprakasam@Sun.COM if (ret) 521*8695SRajkumar.Sivaprakasam@Sun.COM stat = rdma_wait.svc_stat; 522*8695SRajkumar.Sivaprakasam@Sun.COM else 523*8695SRajkumar.Sivaprakasam@Sun.COM stat = RDMA_INTR; 524*8695SRajkumar.Sivaprakasam@Sun.COM 525*8695SRajkumar.Sivaprakasam@Sun.COM mutex_exit(&rdma_wait.svc_lock); 526*8695SRajkumar.Sivaprakasam@Sun.COM 527*8695SRajkumar.Sivaprakasam@Sun.COM return (stat); 528*8695SRajkumar.Sivaprakasam@Sun.COM } 529