rdsv3_ddi.c revision 12198:4db936bda957
1/* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21/* 22 * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. 23 */ 24#include <sys/types.h> 25#include <sys/stat.h> 26#include <sys/conf.h> 27#include <sys/ddi.h> 28#include <sys/sunddi.h> 29#include <sys/modctl.h> 30#include <sys/strsubr.h> 31#include <sys/socketvar.h> 32#include <sys/rds.h> 33 34#include <sys/ib/ibtl/ibti.h> 35#include <sys/ib/clients/rdsv3/rdsv3.h> 36#include <sys/ib/clients/rdsv3/rdsv3_debug.h> 37 38extern int rdsv3_init(void); 39extern void rdsv3_exit(void); 40extern void rdsv3_cong_init(void); 41extern void rdsv3_cong_exit(void); 42extern void rdsv3_trans_init(void); 43extern void rdsv3_trans_exit(void); 44extern int rdsv3_sock_init(void); 45extern void rdsv3_sock_exit(void); 46 47/* global */ 48dev_info_t *rdsv3_dev_info = NULL; 49kmem_cache_t *rdsv3_alloc_cache = NULL; 50 51extern kmutex_t rdsv3_rdma_listen_id_lock; 52extern struct rdma_cm_id *rdsv3_rdma_listen_id; 53 54extern kmutex_t rdsv3_sock_lock; 55extern list_t rdsv3_sock_list; 56 57extern void rdsv3_bind_tree_init(); 58extern void rdsv3_bind_tree_exit(); 59 60int 61rdsv3_sock_init() 62{ 63 RDSV3_DPRINTF4("rdsv3_sock_init", "Enter"); 64 65 rdsv3_alloc_cache = kmem_cache_create("rdsv3_alloc_cache", 66 sizeof (struct rsock) + sizeof (struct rdsv3_sock), 0, NULL, 67 NULL, NULL, NULL, NULL, 0); 68 if (rdsv3_alloc_cache == NULL) { 69 RDSV3_DPRINTF1("rdsv3_alloc_cache", 70 "kmem_cache_create(rdsv3_alloc_cache) failed"); 71 return (-1); 72 } 73 rdsv3_bind_tree_init(); 74 75 mutex_init(&rdsv3_sock_lock, NULL, MUTEX_DRIVER, NULL); 76 list_create(&rdsv3_sock_list, sizeof (struct rdsv3_sock), 77 offsetof(struct rdsv3_sock, rs_item)); 78 79 RDSV3_DPRINTF4("rdsv3_sock_init", "Return"); 80 81 return (0); 82} 83 84void 85rdsv3_sock_exit() 86{ 87 RDSV3_DPRINTF2("rdsv3_sock_exit", "Enter"); 88 89 rdsv3_bind_tree_exit(); 90 91 kmem_cache_destroy(rdsv3_alloc_cache); 92 93 list_destroy(&rdsv3_sock_list); 94 mutex_destroy(&rdsv3_sock_lock); 95 96 RDSV3_DPRINTF2("rdsv3_sock_exit", "Return"); 97} 98 99static int 100rdsv3_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 101{ 102 int ret; 103 104 RDSV3_DPRINTF2("rdsv3_attach", "Enter (dip: %p)", dip); 105 106 if (cmd != DDI_ATTACH) 107 return (DDI_FAILURE); 108 109 if (rdsv3_dev_info != NULL) { 110 RDSV3_DPRINTF1("rdsv3_attach", "Multiple RDS instances are" 111 " not supported (rdsv3_dev_info: 0x%p)", rdsv3_dev_info); 112 return (DDI_FAILURE); 113 } 114 rdsv3_dev_info = dip; 115 116 mutex_init(&rdsv3_rdma_listen_id_lock, NULL, MUTEX_DRIVER, NULL); 117 rdsv3_rdma_listen_id = NULL; 118 119 rdsv3_trans_init(); 120 ret = rdsv3_init(); 121 if (ret) { 122 RDSV3_DPRINTF1("rdsv3_attach", "rdsv3_init failed: %d", ret); 123 rdsv3_trans_exit(); 124 mutex_destroy(&rdsv3_rdma_listen_id_lock); 125 rdsv3_dev_info = NULL; 126 return (DDI_FAILURE); 127 } 128 129 ret = rdsv3_sock_init(); 130 if (ret) { 131 rdsv3_exit(); 132 rdsv3_trans_exit(); 133 mutex_destroy(&rdsv3_rdma_listen_id_lock); 134 rdsv3_dev_info = NULL; 135 return (DDI_FAILURE); 136 } 137 138 ret = ddi_create_minor_node(dip, "rdsv3", S_IFCHR, 0, DDI_PSEUDO, 0); 139 if (ret != DDI_SUCCESS) { 140 cmn_err(CE_CONT, "ddi_create_minor_node failed: %d", ret); 141 rdsv3_sock_exit(); 142 rdsv3_exit(); 143 rdsv3_trans_exit(); 144 mutex_destroy(&rdsv3_rdma_listen_id_lock); 145 rdsv3_dev_info = NULL; 146 return (DDI_FAILURE); 147 } 148 149 RDSV3_DPRINTF2("rdsv3_attach", "Return"); 150 151 return (DDI_SUCCESS); 152} 153 154static int 155rdsv3_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 156{ 157 RDSV3_DPRINTF2("rdsv3_detach", "Enter (dip: %p)", dip); 158 159 if (cmd != DDI_DETACH) 160 return (DDI_FAILURE); 161 162 rdsv3_sock_exit(); 163 rdsv3_exit(); 164 rdsv3_trans_exit(); 165 ddi_remove_minor_node(dip, "rdsv3"); 166 rdsv3_dev_info = NULL; 167 168 RDSV3_DPRINTF2("rdsv3_detach", "Return"); 169 170 return (DDI_SUCCESS); 171} 172 173/* ARGSUSED */ 174static int 175rdsv3_info(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result) 176{ 177 int ret = DDI_FAILURE; 178 179 RDSV3_DPRINTF2("rdsv3_info", "Enter (dip: %p, cmd: %d)", dip, cmd); 180 181 switch (cmd) { 182 case DDI_INFO_DEVT2DEVINFO: 183 if (rdsv3_dev_info != NULL) { 184 *result = (void *)rdsv3_dev_info; 185 ret = DDI_SUCCESS; 186 } 187 break; 188 189 case DDI_INFO_DEVT2INSTANCE: 190 *result = NULL; 191 ret = DDI_SUCCESS; 192 break; 193 194 default: 195 break; 196 } 197 198 RDSV3_DPRINTF4("rdsv3_info", "Return"); 199 200 return (ret); 201} 202 203/* Driver entry points */ 204static struct cb_ops rdsv3_cb_ops = { 205 nulldev, /* open */ 206 nulldev, /* close */ 207 nodev, /* strategy */ 208 nodev, /* print */ 209 nodev, /* dump */ 210 nodev, /* read */ 211 nodev, /* write */ 212 nodev, /* ioctl */ 213 nodev, /* devmap */ 214 nodev, /* mmap */ 215 nodev, /* segmap */ 216 nochpoll, /* poll */ 217 ddi_prop_op, /* prop_op */ 218 NULL, /* stream */ 219 D_MP, /* cb_flag */ 220 CB_REV, /* rev */ 221 nodev, /* int (*cb_aread)() */ 222 nodev, /* int (*cb_awrite)() */ 223}; 224 225/* Device options */ 226static struct dev_ops rdsv3_ops = { 227 DEVO_REV, /* devo_rev, */ 228 0, /* refcnt */ 229 rdsv3_info, /* info */ 230 nulldev, /* identify */ 231 nulldev, /* probe */ 232 rdsv3_attach, /* attach */ 233 rdsv3_detach, /* detach */ 234 nodev, /* reset */ 235 &rdsv3_cb_ops, /* driver ops - devctl interfaces */ 236 NULL, /* bus operations */ 237 NULL, /* power */ 238 ddi_quiesce_not_needed /* quiesce */ 239}; 240 241/* 242 * Module linkage information. 243 */ 244#define RDSV3_DEVDESC "RDSv3 IB transport driver" 245static struct modldrv rdsv3_modldrv = { 246 &mod_driverops, /* Driver module */ 247 RDSV3_DEVDESC, /* Driver name and version */ 248 &rdsv3_ops, /* Driver ops */ 249}; 250 251static struct modlinkage rdsv3_modlinkage = { 252 MODREV_1, 253 (void *)&rdsv3_modldrv, 254 NULL 255}; 256 257int 258_init(void) 259{ 260 int ret; 261 262 if (ibt_hw_is_present() == 0) { 263 return (ENODEV); 264 } 265 266 /* Initialize logging */ 267 rdsv3_logging_initialization(); 268 269 ret = mod_install(&rdsv3_modlinkage); 270 if (ret != 0) { 271 /* 272 * Could not load module 273 */ 274 rdsv3_logging_destroy(); 275 return (ret); 276 } 277 278 return (0); 279} 280 281int 282_fini() 283{ 284 int ret; 285 286 /* 287 * Remove module 288 */ 289 if ((ret = mod_remove(&rdsv3_modlinkage)) != 0) { 290 return (ret); 291 } 292 293 /* Stop logging */ 294 rdsv3_logging_destroy(); 295 296 return (0); 297} 298 299int 300_info(struct modinfo *modinfop) 301{ 302 return (mod_info(&rdsv3_modlinkage, modinfop)); 303} 304