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 /* 228695SRajkumar.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 /* 278695SRajkumar.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 */ 568695SRajkumar.Sivaprakasam@Sun.COM 578695SRajkumar.Sivaprakasam@Sun.COM rdma_svc_wait_t rdma_wait; 588695SRajkumar.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 */ 688695SRajkumar.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) { 1028695SRajkumar.Sivaprakasam@Sun.COM if ((*mp)->r_mod_state == RDMA_MOD_INACTIVE) { 1038695SRajkumar.Sivaprakasam@Sun.COM (*mp)->r_mod_state = RDMA_MOD_ACTIVE; 1048695SRajkumar.Sivaprakasam@Sun.COM (*mp)->r_mod->rdma_ops = mod->rdma_ops; 1058695SRajkumar.Sivaprakasam@Sun.COM (*mp)->r_mod->rdma_count = mod->rdma_count; 1068695SRajkumar.Sivaprakasam@Sun.COM goto announce_hca; 1078695SRajkumar.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'; 1248695SRajkumar.Sivaprakasam@Sun.COM m->r_mod_state = RDMA_MOD_ACTIVE; 1250Sstevel@tonic-gate *mp = m; 1268695SRajkumar.Sivaprakasam@Sun.COM 1278695SRajkumar.Sivaprakasam@Sun.COM announce_hca: 1280Sstevel@tonic-gate rw_exit(&rdma_lock); 1298695SRajkumar.Sivaprakasam@Sun.COM /* 1308695SRajkumar.Sivaprakasam@Sun.COM * Start the nfs service on the rdma xprts. 1318695SRajkumar.Sivaprakasam@Sun.COM * (this notification mechanism will need to change when we support 1328695SRajkumar.Sivaprakasam@Sun.COM * multiple hcas and have support for multiple rdma plugins). 1338695SRajkumar.Sivaprakasam@Sun.COM */ 1348695SRajkumar.Sivaprakasam@Sun.COM mutex_enter(&rdma_wait.svc_lock); 1358695SRajkumar.Sivaprakasam@Sun.COM rdma_wait.svc_stat = RDMA_HCA_ATTACH; 1368695SRajkumar.Sivaprakasam@Sun.COM cv_signal(&rdma_wait.svc_cv); 1378695SRajkumar.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 */ 1648695SRajkumar.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 /* 1698695SRajkumar.Sivaprakasam@Sun.COM * Found entry. Mark it inactive. 1700Sstevel@tonic-gate */ 1710Sstevel@tonic-gate mmod = *m; 1728695SRajkumar.Sivaprakasam@Sun.COM mmod->r_mod->rdma_count = 0; 1738695SRajkumar.Sivaprakasam@Sun.COM mmod->r_mod_state = RDMA_MOD_INACTIVE; 1748695SRajkumar.Sivaprakasam@Sun.COM break; 1750Sstevel@tonic-gate } 1760Sstevel@tonic-gate 1778695SRajkumar.Sivaprakasam@Sun.COM rdma_modloaded = 0; 1788695SRajkumar.Sivaprakasam@Sun.COM rdma_dev_available = 0; 1798695SRajkumar.Sivaprakasam@Sun.COM rw_exit(&rdma_lock); 1808695SRajkumar.Sivaprakasam@Sun.COM 1818695SRajkumar.Sivaprakasam@Sun.COM /* 1828695SRajkumar.Sivaprakasam@Sun.COM * Stop the nfs service running on the rdma xprts. 1838695SRajkumar.Sivaprakasam@Sun.COM * (this notification mechanism will need to change when we support 1848695SRajkumar.Sivaprakasam@Sun.COM * multiple hcas and have support for multiple rdma plugins). 1858695SRajkumar.Sivaprakasam@Sun.COM */ 1868695SRajkumar.Sivaprakasam@Sun.COM mutex_enter(&rdma_wait.svc_lock); 1878695SRajkumar.Sivaprakasam@Sun.COM rdma_wait.svc_stat = RDMA_HCA_DETACH; 1888695SRajkumar.Sivaprakasam@Sun.COM cv_signal(&rdma_wait.svc_cv); 1898695SRajkumar.Sivaprakasam@Sun.COM mutex_exit(&rdma_wait.svc_lock); 1908695SRajkumar.Sivaprakasam@Sun.COM 1910Sstevel@tonic-gate /* 1920Sstevel@tonic-gate * Not found. 1930Sstevel@tonic-gate */ 1948695SRajkumar.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 209*9348SSiddheshwar.Mahesh@Sun.COM uint32_t 210*9348SSiddheshwar.Mahesh@Sun.COM clist_len(struct clist *cl) 211*9348SSiddheshwar.Mahesh@Sun.COM { 212*9348SSiddheshwar.Mahesh@Sun.COM uint32_t len = 0; 213*9348SSiddheshwar.Mahesh@Sun.COM while (cl) { 214*9348SSiddheshwar.Mahesh@Sun.COM len += cl->c_len; 215*9348SSiddheshwar.Mahesh@Sun.COM cl = cl->c_next; 216*9348SSiddheshwar.Mahesh@Sun.COM } 217*9348SSiddheshwar.Mahesh@Sun.COM return (len); 218*9348SSiddheshwar.Mahesh@Sun.COM } 219*9348SSiddheshwar.Mahesh@Sun.COM 220*9348SSiddheshwar.Mahesh@Sun.COM void 221*9348SSiddheshwar.Mahesh@Sun.COM clist_zero_len(struct clist *cl) 222*9348SSiddheshwar.Mahesh@Sun.COM { 223*9348SSiddheshwar.Mahesh@Sun.COM while (cl != NULL) { 224*9348SSiddheshwar.Mahesh@Sun.COM if (cl->c_dmemhandle.mrc_rmr == 0) 225*9348SSiddheshwar.Mahesh@Sun.COM break; 226*9348SSiddheshwar.Mahesh@Sun.COM cl->c_len = 0; 227*9348SSiddheshwar.Mahesh@Sun.COM cl = cl->c_next; 228*9348SSiddheshwar.Mahesh@Sun.COM } 229*9348SSiddheshwar.Mahesh@Sun.COM } 230*9348SSiddheshwar.Mahesh@Sun.COM 2310Sstevel@tonic-gate /* 2320Sstevel@tonic-gate * Creates a new chunk list entry, and 2330Sstevel@tonic-gate * adds it to the end of a chunk list. 2340Sstevel@tonic-gate */ 2350Sstevel@tonic-gate void 2360Sstevel@tonic-gate clist_add(struct clist **clp, uint32_t xdroff, int len, 2370Sstevel@tonic-gate struct mrc *shandle, caddr_t saddr, 2380Sstevel@tonic-gate struct mrc *dhandle, caddr_t daddr) 2390Sstevel@tonic-gate { 2400Sstevel@tonic-gate struct clist *cl; 2410Sstevel@tonic-gate 2420Sstevel@tonic-gate /* Find the end of the list */ 2430Sstevel@tonic-gate 2440Sstevel@tonic-gate while (*clp != NULL) 2450Sstevel@tonic-gate clp = &((*clp)->c_next); 2460Sstevel@tonic-gate 2477387SRobert.Gordon@Sun.COM cl = clist_alloc(); 2480Sstevel@tonic-gate cl->c_xdroff = xdroff; 2490Sstevel@tonic-gate cl->c_len = len; 2507387SRobert.Gordon@Sun.COM cl->w.c_saddr = (uint64_t)(uintptr_t)saddr; 2510Sstevel@tonic-gate if (shandle) 2520Sstevel@tonic-gate cl->c_smemhandle = *shandle; 2537387SRobert.Gordon@Sun.COM cl->u.c_daddr = (uint64_t)(uintptr_t)daddr; 2540Sstevel@tonic-gate if (dhandle) 2550Sstevel@tonic-gate cl->c_dmemhandle = *dhandle; 2560Sstevel@tonic-gate cl->c_next = NULL; 2570Sstevel@tonic-gate 2580Sstevel@tonic-gate *clp = cl; 2590Sstevel@tonic-gate } 2600Sstevel@tonic-gate 2617387SRobert.Gordon@Sun.COM rdma_stat 2627387SRobert.Gordon@Sun.COM clist_register(CONN *conn, struct clist *cl, clist_dstsrc dstsrc) 2630Sstevel@tonic-gate { 2640Sstevel@tonic-gate struct clist *c; 2650Sstevel@tonic-gate int status; 2660Sstevel@tonic-gate 2670Sstevel@tonic-gate for (c = cl; c; c = c->c_next) { 2687387SRobert.Gordon@Sun.COM if (c->c_len <= 0) 2697387SRobert.Gordon@Sun.COM continue; 270*9348SSiddheshwar.Mahesh@Sun.COM 271*9348SSiddheshwar.Mahesh@Sun.COM c->c_regtype = dstsrc; 272*9348SSiddheshwar.Mahesh@Sun.COM 2737387SRobert.Gordon@Sun.COM switch (dstsrc) { 2747387SRobert.Gordon@Sun.COM case CLIST_REG_SOURCE: 2750Sstevel@tonic-gate status = RDMA_REGMEMSYNC(conn, 276*9348SSiddheshwar.Mahesh@Sun.COM (caddr_t)(struct as *)c->c_adspc, 2777387SRobert.Gordon@Sun.COM (caddr_t)(uintptr_t)c->w.c_saddr3, c->c_len, 2787387SRobert.Gordon@Sun.COM &c->c_smemhandle, (void **)&c->c_ssynchandle, 2797387SRobert.Gordon@Sun.COM (void *)c->rb_longbuf.rb_private); 2807387SRobert.Gordon@Sun.COM break; 2817387SRobert.Gordon@Sun.COM case CLIST_REG_DST: 2820Sstevel@tonic-gate status = RDMA_REGMEMSYNC(conn, 283*9348SSiddheshwar.Mahesh@Sun.COM (caddr_t)(struct as *)c->c_adspc, 2847387SRobert.Gordon@Sun.COM (caddr_t)(uintptr_t)c->u.c_daddr3, c->c_len, 2857387SRobert.Gordon@Sun.COM &c->c_dmemhandle, (void **)&c->c_dsynchandle, 2867387SRobert.Gordon@Sun.COM (void *)c->rb_longbuf.rb_private); 2877387SRobert.Gordon@Sun.COM break; 2887387SRobert.Gordon@Sun.COM default: 2897387SRobert.Gordon@Sun.COM return (RDMA_INVAL); 2900Sstevel@tonic-gate } 2910Sstevel@tonic-gate if (status != RDMA_SUCCESS) { 292*9348SSiddheshwar.Mahesh@Sun.COM (void) clist_deregister(conn, cl); 2930Sstevel@tonic-gate return (status); 2940Sstevel@tonic-gate } 2950Sstevel@tonic-gate } 2960Sstevel@tonic-gate 2970Sstevel@tonic-gate return (RDMA_SUCCESS); 2980Sstevel@tonic-gate } 2990Sstevel@tonic-gate 3007387SRobert.Gordon@Sun.COM rdma_stat 301*9348SSiddheshwar.Mahesh@Sun.COM clist_deregister(CONN *conn, struct clist *cl) 3020Sstevel@tonic-gate { 3030Sstevel@tonic-gate struct clist *c; 3040Sstevel@tonic-gate 3050Sstevel@tonic-gate for (c = cl; c; c = c->c_next) { 306*9348SSiddheshwar.Mahesh@Sun.COM switch (c->c_regtype) { 3077387SRobert.Gordon@Sun.COM case CLIST_REG_SOURCE: 3080Sstevel@tonic-gate if (c->c_smemhandle.mrc_rmr != 0) { 3090Sstevel@tonic-gate (void) RDMA_DEREGMEMSYNC(conn, 3107387SRobert.Gordon@Sun.COM (caddr_t)(uintptr_t)c->w.c_saddr3, 3110Sstevel@tonic-gate c->c_smemhandle, 3127387SRobert.Gordon@Sun.COM (void *)(uintptr_t)c->c_ssynchandle, 3137387SRobert.Gordon@Sun.COM (void *)c->rb_longbuf.rb_private); 3140Sstevel@tonic-gate c->c_smemhandle.mrc_rmr = 0; 3150Sstevel@tonic-gate c->c_ssynchandle = NULL; 3160Sstevel@tonic-gate } 3177387SRobert.Gordon@Sun.COM break; 3187387SRobert.Gordon@Sun.COM case CLIST_REG_DST: 3190Sstevel@tonic-gate if (c->c_dmemhandle.mrc_rmr != 0) { 3200Sstevel@tonic-gate (void) RDMA_DEREGMEMSYNC(conn, 3217387SRobert.Gordon@Sun.COM (caddr_t)(uintptr_t)c->u.c_daddr3, 3220Sstevel@tonic-gate c->c_dmemhandle, 3237387SRobert.Gordon@Sun.COM (void *)(uintptr_t)c->c_dsynchandle, 3247387SRobert.Gordon@Sun.COM (void *)c->rb_longbuf.rb_private); 3250Sstevel@tonic-gate c->c_dmemhandle.mrc_rmr = 0; 3260Sstevel@tonic-gate c->c_dsynchandle = NULL; 3270Sstevel@tonic-gate } 3287387SRobert.Gordon@Sun.COM break; 3297387SRobert.Gordon@Sun.COM default: 330*9348SSiddheshwar.Mahesh@Sun.COM /* clist unregistered. continue */ 331*9348SSiddheshwar.Mahesh@Sun.COM break; 3320Sstevel@tonic-gate } 3330Sstevel@tonic-gate } 3340Sstevel@tonic-gate 3350Sstevel@tonic-gate return (RDMA_SUCCESS); 3360Sstevel@tonic-gate } 3370Sstevel@tonic-gate 3387387SRobert.Gordon@Sun.COM rdma_stat 3397387SRobert.Gordon@Sun.COM clist_syncmem(CONN *conn, struct clist *cl, clist_dstsrc dstsrc) 3407387SRobert.Gordon@Sun.COM { 3417387SRobert.Gordon@Sun.COM struct clist *c; 3427387SRobert.Gordon@Sun.COM rdma_stat status; 3437387SRobert.Gordon@Sun.COM 3447387SRobert.Gordon@Sun.COM c = cl; 3457387SRobert.Gordon@Sun.COM switch (dstsrc) { 3467387SRobert.Gordon@Sun.COM case CLIST_REG_SOURCE: 3477387SRobert.Gordon@Sun.COM while (c != NULL) { 3487387SRobert.Gordon@Sun.COM if (c->c_ssynchandle) { 3497387SRobert.Gordon@Sun.COM status = RDMA_SYNCMEM(conn, 3507387SRobert.Gordon@Sun.COM (void *)(uintptr_t)c->c_ssynchandle, 3517387SRobert.Gordon@Sun.COM (caddr_t)(uintptr_t)c->w.c_saddr3, 3527387SRobert.Gordon@Sun.COM c->c_len, 0); 3537387SRobert.Gordon@Sun.COM if (status != RDMA_SUCCESS) 3547387SRobert.Gordon@Sun.COM return (status); 3557387SRobert.Gordon@Sun.COM } 3567387SRobert.Gordon@Sun.COM c = c->c_next; 3577387SRobert.Gordon@Sun.COM } 3587387SRobert.Gordon@Sun.COM break; 3597387SRobert.Gordon@Sun.COM case CLIST_REG_DST: 3607387SRobert.Gordon@Sun.COM while (c != NULL) { 3617387SRobert.Gordon@Sun.COM if (c->c_ssynchandle) { 3627387SRobert.Gordon@Sun.COM status = RDMA_SYNCMEM(conn, 3637387SRobert.Gordon@Sun.COM (void *)(uintptr_t)c->c_dsynchandle, 3647387SRobert.Gordon@Sun.COM (caddr_t)(uintptr_t)c->u.c_daddr3, 3657387SRobert.Gordon@Sun.COM c->c_len, 1); 3667387SRobert.Gordon@Sun.COM if (status != RDMA_SUCCESS) 3677387SRobert.Gordon@Sun.COM return (status); 3687387SRobert.Gordon@Sun.COM } 3697387SRobert.Gordon@Sun.COM c = c->c_next; 3707387SRobert.Gordon@Sun.COM } 3717387SRobert.Gordon@Sun.COM break; 3727387SRobert.Gordon@Sun.COM default: 3737387SRobert.Gordon@Sun.COM return (RDMA_INVAL); 3747387SRobert.Gordon@Sun.COM } 3757387SRobert.Gordon@Sun.COM 3767387SRobert.Gordon@Sun.COM return (RDMA_SUCCESS); 3777387SRobert.Gordon@Sun.COM } 3787387SRobert.Gordon@Sun.COM 3790Sstevel@tonic-gate /* 3800Sstevel@tonic-gate * Frees up entries in chunk list 3810Sstevel@tonic-gate */ 3820Sstevel@tonic-gate void 3830Sstevel@tonic-gate clist_free(struct clist *cl) 3840Sstevel@tonic-gate { 3850Sstevel@tonic-gate struct clist *c = cl; 3860Sstevel@tonic-gate 3870Sstevel@tonic-gate while (c != NULL) { 3880Sstevel@tonic-gate cl = cl->c_next; 3897387SRobert.Gordon@Sun.COM kmem_cache_free(clist_cache, c); 3900Sstevel@tonic-gate c = cl; 3910Sstevel@tonic-gate } 3920Sstevel@tonic-gate } 3930Sstevel@tonic-gate 3940Sstevel@tonic-gate rdma_stat 3950Sstevel@tonic-gate rdma_clnt_postrecv(CONN *conn, uint32_t xid) 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)) { 4037387SRobert.Gordon@Sun.COM return (RDMA_NORESOURCE); 4040Sstevel@tonic-gate } 4057387SRobert.Gordon@Sun.COM 4067387SRobert.Gordon@Sun.COM clist_add(&cl, 0, rbuf.len, &rbuf.handle, rbuf.addr, 4077387SRobert.Gordon@Sun.COM NULL, NULL); 4087387SRobert.Gordon@Sun.COM retval = RDMA_CLNT_RECVBUF(conn, cl, xid); 4097387SRobert.Gordon@Sun.COM clist_free(cl); 4107387SRobert.Gordon@Sun.COM 4110Sstevel@tonic-gate return (retval); 4120Sstevel@tonic-gate } 4130Sstevel@tonic-gate 4140Sstevel@tonic-gate rdma_stat 4157387SRobert.Gordon@Sun.COM rdma_clnt_postrecv_remove(CONN *conn, uint32_t xid) 4167387SRobert.Gordon@Sun.COM { 4177387SRobert.Gordon@Sun.COM return (RDMA_CLNT_RECVBUF_REMOVE(conn, xid)); 4187387SRobert.Gordon@Sun.COM } 4197387SRobert.Gordon@Sun.COM 4207387SRobert.Gordon@Sun.COM rdma_stat 4210Sstevel@tonic-gate rdma_svc_postrecv(CONN *conn) 4220Sstevel@tonic-gate { 4230Sstevel@tonic-gate struct clist *cl = NULL; 4240Sstevel@tonic-gate rdma_stat retval; 4257387SRobert.Gordon@Sun.COM rdma_buf_t rbuf = {0}; 4260Sstevel@tonic-gate 4270Sstevel@tonic-gate rbuf.type = RECV_BUFFER; 4280Sstevel@tonic-gate if (RDMA_BUF_ALLOC(conn, &rbuf)) { 4290Sstevel@tonic-gate retval = RDMA_NORESOURCE; 4300Sstevel@tonic-gate } else { 4310Sstevel@tonic-gate clist_add(&cl, 0, rbuf.len, &rbuf.handle, rbuf.addr, 4327387SRobert.Gordon@Sun.COM NULL, NULL); 4330Sstevel@tonic-gate retval = RDMA_SVC_RECVBUF(conn, cl); 4340Sstevel@tonic-gate clist_free(cl); 4350Sstevel@tonic-gate } 4360Sstevel@tonic-gate return (retval); 4370Sstevel@tonic-gate } 4380Sstevel@tonic-gate 4390Sstevel@tonic-gate rdma_stat 4407387SRobert.Gordon@Sun.COM rdma_buf_alloc(CONN *conn, rdma_buf_t *rbuf) 4410Sstevel@tonic-gate { 4427387SRobert.Gordon@Sun.COM return (RDMA_BUF_ALLOC(conn, rbuf)); 4430Sstevel@tonic-gate } 4440Sstevel@tonic-gate 4450Sstevel@tonic-gate void 4460Sstevel@tonic-gate rdma_buf_free(CONN *conn, rdma_buf_t *rbuf) 4470Sstevel@tonic-gate { 4480Sstevel@tonic-gate if (!rbuf || rbuf->addr == NULL) { 4490Sstevel@tonic-gate return; 4500Sstevel@tonic-gate } 4517387SRobert.Gordon@Sun.COM RDMA_BUF_FREE(conn, rbuf); 4527387SRobert.Gordon@Sun.COM bzero(rbuf, sizeof (rdma_buf_t)); 4530Sstevel@tonic-gate } 4540Sstevel@tonic-gate 4550Sstevel@tonic-gate /* 4560Sstevel@tonic-gate * Caller is holding rdma_modload_lock mutex 4570Sstevel@tonic-gate */ 4580Sstevel@tonic-gate int 4590Sstevel@tonic-gate rdma_modload() 4600Sstevel@tonic-gate { 4610Sstevel@tonic-gate int status; 4620Sstevel@tonic-gate ASSERT(MUTEX_HELD(&rdma_modload_lock)); 4630Sstevel@tonic-gate /* 4640Sstevel@tonic-gate * Load all available RDMA plugins which right now is only IB plugin. 4650Sstevel@tonic-gate * If no IB hardware is present, then quit right away. 4660Sstevel@tonic-gate * ENODEV -- For no device on the system 4670Sstevel@tonic-gate * EPROTONOSUPPORT -- For module not avilable either due to failure to 4680Sstevel@tonic-gate * load or some other reason. 4690Sstevel@tonic-gate */ 4700Sstevel@tonic-gate rdma_modloaded = 1; 4710Sstevel@tonic-gate if (ibt_hw_is_present() == 0) { 4720Sstevel@tonic-gate rdma_dev_available = 0; 4730Sstevel@tonic-gate return (ENODEV); 4740Sstevel@tonic-gate } 4750Sstevel@tonic-gate 4760Sstevel@tonic-gate rdma_dev_available = 1; 4770Sstevel@tonic-gate if (rpcmod_li == NULL) 4780Sstevel@tonic-gate return (EPROTONOSUPPORT); 4790Sstevel@tonic-gate 4800Sstevel@tonic-gate status = ldi_open_by_name("/devices/ib/rpcib@0:rpcib", 4810Sstevel@tonic-gate FREAD | FWRITE, kcred, 4820Sstevel@tonic-gate &rpcib_handle, rpcmod_li); 4838695SRajkumar.Sivaprakasam@Sun.COM 4840Sstevel@tonic-gate if (status != 0) 4850Sstevel@tonic-gate return (EPROTONOSUPPORT); 4860Sstevel@tonic-gate 4877387SRobert.Gordon@Sun.COM 4888695SRajkumar.Sivaprakasam@Sun.COM /* 4898695SRajkumar.Sivaprakasam@Sun.COM * We will need to reload the plugin module after it was unregistered 4908695SRajkumar.Sivaprakasam@Sun.COM * but the resources below need to allocated only the first time. 4918695SRajkumar.Sivaprakasam@Sun.COM */ 4928695SRajkumar.Sivaprakasam@Sun.COM if (!clist_cache) { 4938695SRajkumar.Sivaprakasam@Sun.COM clist_cache = kmem_cache_create("rdma_clist", 4948695SRajkumar.Sivaprakasam@Sun.COM sizeof (struct clist), _POINTER_ALIGNMENT, NULL, 4958695SRajkumar.Sivaprakasam@Sun.COM NULL, NULL, NULL, 0, 0); 4968695SRajkumar.Sivaprakasam@Sun.COM rdma_kstat_init(); 4978695SRajkumar.Sivaprakasam@Sun.COM } 4988695SRajkumar.Sivaprakasam@Sun.COM 4998695SRajkumar.Sivaprakasam@Sun.COM (void) ldi_close(rpcib_handle, FREAD|FWRITE, kcred); 5007387SRobert.Gordon@Sun.COM 5010Sstevel@tonic-gate return (0); 5020Sstevel@tonic-gate } 5030Sstevel@tonic-gate 5040Sstevel@tonic-gate void 5050Sstevel@tonic-gate rdma_kstat_init(void) 5060Sstevel@tonic-gate { 5070Sstevel@tonic-gate kstat_t *ksp; 5080Sstevel@tonic-gate 5090Sstevel@tonic-gate /* 5100Sstevel@tonic-gate * The RDMA framework doesn't know how to deal with Zones, and is 5110Sstevel@tonic-gate * only available in the global zone. 5120Sstevel@tonic-gate */ 5130Sstevel@tonic-gate ASSERT(INGLOBALZONE(curproc)); 5140Sstevel@tonic-gate ksp = kstat_create_zone("unix", 0, "rpc_rdma_client", "rpc", 5150Sstevel@tonic-gate KSTAT_TYPE_NAMED, rdmarcstat_ndata, 5160Sstevel@tonic-gate KSTAT_FLAG_VIRTUAL | KSTAT_FLAG_WRITABLE, GLOBAL_ZONEID); 5170Sstevel@tonic-gate if (ksp) { 5180Sstevel@tonic-gate ksp->ks_data = (void *) rdmarcstat_ptr; 5190Sstevel@tonic-gate kstat_install(ksp); 5200Sstevel@tonic-gate } 5210Sstevel@tonic-gate 5220Sstevel@tonic-gate ksp = kstat_create_zone("unix", 0, "rpc_rdma_server", "rpc", 5230Sstevel@tonic-gate KSTAT_TYPE_NAMED, rdmarsstat_ndata, 5240Sstevel@tonic-gate KSTAT_FLAG_VIRTUAL | KSTAT_FLAG_WRITABLE, GLOBAL_ZONEID); 5250Sstevel@tonic-gate if (ksp) { 5260Sstevel@tonic-gate ksp->ks_data = (void *) rdmarsstat_ptr; 5270Sstevel@tonic-gate kstat_install(ksp); 5280Sstevel@tonic-gate } 5290Sstevel@tonic-gate } 5308695SRajkumar.Sivaprakasam@Sun.COM 5318695SRajkumar.Sivaprakasam@Sun.COM rdma_stat 5328695SRajkumar.Sivaprakasam@Sun.COM rdma_kwait(void) 5338695SRajkumar.Sivaprakasam@Sun.COM { 5348695SRajkumar.Sivaprakasam@Sun.COM int ret; 5358695SRajkumar.Sivaprakasam@Sun.COM rdma_stat stat; 5368695SRajkumar.Sivaprakasam@Sun.COM 5378695SRajkumar.Sivaprakasam@Sun.COM mutex_enter(&rdma_wait.svc_lock); 5388695SRajkumar.Sivaprakasam@Sun.COM 5398695SRajkumar.Sivaprakasam@Sun.COM ret = cv_wait_sig(&rdma_wait.svc_cv, &rdma_wait.svc_lock); 5408695SRajkumar.Sivaprakasam@Sun.COM 5418695SRajkumar.Sivaprakasam@Sun.COM /* 5428695SRajkumar.Sivaprakasam@Sun.COM * If signalled by a hca attach/detach, pass the right 5438695SRajkumar.Sivaprakasam@Sun.COM * stat back. 5448695SRajkumar.Sivaprakasam@Sun.COM */ 5458695SRajkumar.Sivaprakasam@Sun.COM 5468695SRajkumar.Sivaprakasam@Sun.COM if (ret) 5478695SRajkumar.Sivaprakasam@Sun.COM stat = rdma_wait.svc_stat; 5488695SRajkumar.Sivaprakasam@Sun.COM else 5498695SRajkumar.Sivaprakasam@Sun.COM stat = RDMA_INTR; 5508695SRajkumar.Sivaprakasam@Sun.COM 5518695SRajkumar.Sivaprakasam@Sun.COM mutex_exit(&rdma_wait.svc_lock); 5528695SRajkumar.Sivaprakasam@Sun.COM 5538695SRajkumar.Sivaprakasam@Sun.COM return (stat); 5548695SRajkumar.Sivaprakasam@Sun.COM } 555