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 25 #ifndef _RDSV3_IMPL_H 26 #define _RDSV3_IMPL_H 27 28 #include <sys/atomic.h> 29 30 /* 31 * This file is only present in Solaris 32 */ 33 34 #ifdef __cplusplus 35 extern "C" { 36 #endif 37 38 extern dev_info_t *rdsv3_dev_info; 39 40 #define uint16_be_t uint16_t 41 #define uint32_be_t uint32_t 42 #define uint64_be_t uint64_t 43 44 /* 45 * RDS Well known service id 46 * Format: 0x1h00144Fhhhhhhhh 47 * "00144F" is the Sun OUI 48 * 'h' can be any hex-decimal digit. 49 */ 50 #define RDS_SERVICE_ID 0x1000144F00000001ULL 51 52 /* 53 * Atomic operations 54 */ 55 typedef unsigned int atomic_t; 56 #define ATOMIC_INIT(a) a 57 58 #define atomic_get(p) (*(p)) 59 60 #define atomic_cmpset_long(p, c, n) \ 61 ((c == atomic_cas_uint(p, c, n)) ? c : -1) 62 63 #define atomic_dec_and_test(a) \ 64 (atomic_dec_uint_nv((a)) == 0) 65 66 #define atomic_cmpxchg(a, o, n) \ 67 atomic_cas_uint(a, o, n) 68 69 #ifdef _LP64 70 #define set_bit(b, p) \ 71 atomic_or_ulong(((volatile ulong_t *)(void *)(p)) + ((b) >> 6), \ 72 1ul << ((b) & 0x3f)) 73 74 #define clear_bit(b, p) \ 75 atomic_and_ulong(((volatile ulong_t *)(void *)(p)) + ((b) >> 6), \ 76 ~(1ul << ((b) & 0x3f))) 77 78 #define test_bit(b, p) \ 79 (((volatile ulong_t *)(void *)(p))[(b) >> 6] & (1ul << ((b) & 0x3f))) 80 81 #define test_and_set_bit(b, p) \ 82 atomic_set_long_excl(((ulong_t *)(void *)(p)) + \ 83 ((b) >> 6), ((b) & 0x3f)) 84 #define test_and_clear_bit(b, p) \ 85 !atomic_clear_long_excl(((ulong_t *)(void *)(p)) + ((b) >> 6), \ 86 ((b) & 0x3f)) 87 #else 88 #define set_bit(b, p) \ 89 atomic_or_uint(((volatile uint_t *)(void *)p) + (b >> 5), \ 90 1ul << (b & 0x1f)) 91 92 #define clear_bit(b, p) \ 93 atomic_and_uint(((volatile uint_t *)(void *)p) + (b >> 5), \ 94 ~(1ul << (b & 0x1f))) 95 96 #define test_bit(b, p) \ 97 (((volatile uint_t *)(void *)p)[b >> 5] & (1ul << (b & 0x1f))) 98 99 #define test_and_set_bit(b, p) \ 100 atomic_set_long_excl(((ulong_t *)(void *)p) + (b >> 5), (b & 0x1f)) 101 #define test_and_clear_bit(b, p) \ 102 !atomic_clear_long_excl(((ulong_t *)(void *)p) + (b >> 5), (b & 0x1f)) 103 #endif 104 105 106 uint_t rdsv3_one_sec_in_hz; 107 108 #define jiffies 100 109 #define HZ (drv_hztousec(1)) 110 #define container_of(m, s, name) \ 111 (void *)((uintptr_t)(m) - (uintptr_t)offsetof(s, name)) 112 #define ARRAY_SIZE(x) (sizeof (x) / sizeof (x[0])) 113 /* setting this to PAGESIZE throws build errors */ 114 #define PAGE_SIZE 4096 /* xxx - fix this */ 115 #define BITS_PER_LONG (sizeof (unsigned long) * 8) 116 117 /* debug */ 118 #define RDSV3_PANIC() cmn_err(CE_PANIC, "Panic forced by RDSV3"); 119 120 /* ERR */ 121 #define MAX_ERRNO 4095 122 #define ERR_PTR(x) ((void *)(uintptr_t)x) 123 #define IS_ERR(ptr) (((uintptr_t)ptr) >= (uintptr_t)-MAX_ERRNO) 124 #define PTR_ERR(ptr) (int)(uintptr_t)ptr 125 126 /* cpu */ 127 #define NR_CPUS 1 128 #define put_cpu() 129 #define get_cpu() 0 130 131 #define MAX_SCHEDULE_TIMEOUT (~0UL>>1) 132 133 #define RDMA_CM_EVENT_ADDR_CHANGE 14 134 135 /* list */ 136 /* copied and modified list_remove_node */ 137 #define list_remove_node(node) \ 138 if ((node)->list_next != NULL) { \ 139 (node)->list_prev->list_next = (node)->list_next; \ 140 (node)->list_next->list_prev = (node)->list_prev; \ 141 (node)->list_next = (node)->list_prev = NULL; \ 142 } 143 144 #define list_splice(src, dst) { \ 145 list_create(dst, (src)->list_size, (src)->list_offset); \ 146 list_move_tail(dst, src); \ 147 } 148 149 #define RDSV3_FOR_EACH_LIST_NODE(objp, listp, member) \ 150 for (objp = list_head(listp); objp; objp = list_next(listp, objp)) 151 #define RDSV3_FOR_EACH_LIST_NODE_SAFE(objp, tmp, listp, member) \ 152 for (objp = list_head(listp), tmp = (objp != NULL) ? \ 153 list_next(listp, objp) : NULL; \ 154 objp; \ 155 objp = tmp, tmp = (objp != NULL) ? \ 156 list_next(listp, objp) : NULL) 157 158 /* simulate wait_queue_head_t */ 159 typedef struct rdsv3_wait_queue_s { 160 kmutex_t waitq_mutex; 161 kcondvar_t waitq_cv; 162 } rdsv3_wait_queue_t; 163 164 #define rdsv3_init_waitqueue(waitqp) \ 165 mutex_init(&(waitqp)->waitq_mutex, NULL, MUTEX_DRIVER, NULL); \ 166 cv_init(&(waitqp)->waitq_cv, NULL, CV_DRIVER, NULL) 167 168 #define rdsv3_exit_waitqueue(waitqp) \ 169 mutex_destroy(&(waitqp)->waitq_mutex); \ 170 cv_destroy(&(waitqp)->waitq_cv) 171 172 #define rdsv3_wake_up(waitqp) { \ 173 mutex_enter(&(waitqp)->waitq_mutex); \ 174 cv_signal(&(waitqp)->waitq_cv); \ 175 mutex_exit(&(waitqp)->waitq_mutex); \ 176 } 177 178 #define rdsv3_wake_up_all(waitqp) { \ 179 mutex_enter(&(waitqp)->waitq_mutex); \ 180 cv_broadcast(&(waitqp)->waitq_cv); \ 181 mutex_exit(&(waitqp)->waitq_mutex); \ 182 } 183 184 #define rdsv3_wait_event(waitq, condition) \ 185 { \ 186 mutex_enter(&(waitq).waitq_mutex); \ 187 while (!(condition)) { \ 188 cv_wait(&(waitq).waitq_cv, &(waitq).waitq_mutex); \ 189 } \ 190 mutex_exit(&(waitq).waitq_mutex); \ 191 } \ 192 193 #ifndef __lock_lint 194 #define rdsv3_wait_event_interruptible_timeout(waitq, condition, timeo) \ 195 ( \ 196 { \ 197 long cv_return; \ 198 mutex_enter(&((waitq).waitq_mutex)); \ 199 cv_return = condition; \ 200 while (!(cv_return)) { \ 201 cv_return = cv_timedwait_sig(&((waitq).waitq_cv), \ 202 &((waitq).waitq_mutex), \ 203 timeo * drv_usectohz(1000000) + ddi_get_lbolt()); \ 204 if (cv_return == 0) { \ 205 break; \ 206 } \ 207 cv_return = condition; \ 208 } \ 209 mutex_exit(&((waitq).waitq_mutex)); \ 210 cv_return; \ 211 } \ 212 ) 213 #else 214 #define rdsv3_wait_event_interruptible(waitq, condition) 0 215 #define rdsv3_wait_event_interruptible_timeout(waitq, condition, timeo) 0 216 #endif 217 218 #define SOCK_DEAD 1ul 219 220 /* socket */ 221 typedef struct rsock { 222 sock_upper_handle_t sk_upper_handle; 223 sock_upcalls_t *sk_upcalls; 224 225 kmutex_t sk_lock; 226 ulong_t sk_flag; 227 rdsv3_wait_queue_t *sk_sleep; 228 int sk_sndbuf; 229 int sk_rcvbuf; 230 atomic_t sk_refcount; 231 232 struct rdsv3_sock *sk_protinfo; 233 } rsock_t; 234 235 typedef struct rdsv3_conn_info_s { 236 uint32_be_t c_laddr; 237 uint32_be_t c_faddr; 238 } rdsv3_conn_info_t; 239 240 /* WQ */ 241 typedef struct rdsv3_workqueue_struct_s { 242 kmutex_t wq_lock; 243 uint_t wq_state; 244 int wq_pending; 245 list_t wq_queue; 246 } rdsv3_workqueue_struct_t; 247 248 struct rdsv3_work_s; 249 typedef void (*rdsv3_work_func_t)(struct rdsv3_work_s *); 250 typedef struct rdsv3_work_s { 251 list_node_t work_item; 252 rdsv3_work_func_t func; 253 } rdsv3_work_t; 254 255 /* simulate delayed_work */ 256 typedef struct rdsv3_delayed_work_s { 257 kmutex_t lock; 258 rdsv3_work_t work; 259 timeout_id_t timeid; 260 rdsv3_workqueue_struct_t *wq; 261 } rdsv3_delayed_work_t; 262 263 #define RDSV3_INIT_WORK(wp, f) (wp)->func = f 264 #define RDSV3_INIT_DELAYED_WORK(dwp, f) \ 265 (dwp)->work.func = f; \ 266 mutex_init(&(dwp)->lock, NULL, MUTEX_DRIVER, NULL); \ 267 (dwp)->timeid = 0 268 269 /* simulate scatterlist */ 270 struct rdsv3_scatterlist { 271 caddr_t vaddr; 272 uint_t length; 273 ibt_wr_ds_t *sgl; 274 ibt_mi_hdl_t mihdl; 275 }; 276 #define rdsv3_sg_page(scat) (scat)->vaddr 277 #define rdsv3_sg_len(scat) (scat)->length 278 #define rdsv3_sg_set_page(scat, pg, len, off) \ 279 (scat)->vaddr = (caddr_t)(pg + off); \ 280 (scat)->length = len 281 #define rdsv3_ib_sg_dma_len(dev, scat) rdsv3_sg_len(scat) 282 283 /* copied from sys/socket.h */ 284 #if defined(__sparc) 285 /* To maintain backward compatibility, alignment needs to be 8 on sparc. */ 286 #define _CMSG_HDR_ALIGNMENT 8 287 #else 288 /* for __i386 (and other future architectures) */ 289 #define _CMSG_HDR_ALIGNMENT 4 290 #endif /* defined(__sparc) */ 291 292 /* 293 * The cmsg headers (and macros dealing with them) were made available as 294 * part of UNIX95 and hence need to be protected with a _XPG4_2 define. 295 */ 296 #define _CMSG_DATA_ALIGNMENT (sizeof (int)) 297 #define _CMSG_HDR_ALIGN(x) (((uintptr_t)(x) + _CMSG_HDR_ALIGNMENT - 1) & \ 298 ~(_CMSG_HDR_ALIGNMENT - 1)) 299 #define _CMSG_DATA_ALIGN(x) (((uintptr_t)(x) + _CMSG_DATA_ALIGNMENT - 1) & \ 300 ~(_CMSG_DATA_ALIGNMENT - 1)) 301 #define CMSG_DATA(c) \ 302 ((unsigned char *)_CMSG_DATA_ALIGN((struct cmsghdr *)(c) + 1)) 303 304 #define CMSG_FIRSTHDR(m) \ 305 (((m)->msg_controllen < sizeof (struct cmsghdr)) ? \ 306 (struct cmsghdr *)0 : (struct cmsghdr *)((m)->msg_control)) 307 308 #define CMSG_NXTHDR(m, c) \ 309 (((c) == 0) ? CMSG_FIRSTHDR(m) : \ 310 ((((uintptr_t)_CMSG_HDR_ALIGN((char *)(c) + \ 311 ((struct cmsghdr *)(c))->cmsg_len) + sizeof (struct cmsghdr)) > \ 312 (((uintptr_t)((struct msghdr *)(m))->msg_control) + \ 313 ((uintptr_t)((struct msghdr *)(m))->msg_controllen))) ? \ 314 ((struct cmsghdr *)0) : \ 315 ((struct cmsghdr *)_CMSG_HDR_ALIGN((char *)(c) + \ 316 ((struct cmsghdr *)(c))->cmsg_len)))) 317 318 /* Amount of space + padding needed for a message of length l */ 319 #define CMSG_SPACE(l) \ 320 ((unsigned int)_CMSG_HDR_ALIGN(sizeof (struct cmsghdr) + (l))) 321 322 /* Value to be used in cmsg_len, does not include trailing padding */ 323 #define CMSG_LEN(l) \ 324 ((unsigned int)_CMSG_DATA_ALIGN(sizeof (struct cmsghdr)) + (l)) 325 326 /* OFUV -> IB */ 327 #define RDSV3_IBDEV2HCAHDL(device) (device)->hca_hdl 328 #define RDSV3_QP2CHANHDL(qp) (qp)->ibt_qp 329 #define RDSV3_PD2PDHDL(pd) (pd)->ibt_pd 330 #define RDSV3_CQ2CQHDL(cq) (cq)->ibt_cq 331 332 struct rdsv3_hdrs_mr { 333 ibt_lkey_t lkey; 334 caddr_t addr; 335 size_t size; 336 ibt_mr_hdl_t hdl; 337 }; 338 339 /* rdsv3_impl.c */ 340 void rdsv3_trans_init(); 341 boolean_t rdsv3_capable_interface(struct lifreq *lifrp); 342 int rdsv3_do_ip_ioctl(ksocket_t so4, void **ipaddrs, int *size, int *nifs); 343 int rdsv3_do_ip_ioctl_old(ksocket_t so4, void **ipaddrs, int *size, int *nifs); 344 boolean_t rdsv3_isloopback(ipaddr_t addr); 345 void rdsv3_cancel_delayed_work(rdsv3_delayed_work_t *dwp); 346 void rdsv3_flush_workqueue(rdsv3_workqueue_struct_t *wq); 347 void rdsv3_queue_work(rdsv3_workqueue_struct_t *wq, rdsv3_work_t *wp); 348 void rdsv3_queue_delayed_work(rdsv3_workqueue_struct_t *wq, 349 rdsv3_delayed_work_t *dwp, uint_t delay); 350 struct rsock *rdsv3_sk_alloc(); 351 void rdsv3_sock_init_data(struct rsock *sk); 352 void rdsv3_sock_exit_data(struct rsock *sk); 353 void rdsv3_poll_wait(struct rsock *sk, rdsv3_wait_queue_t *waitq, short events); 354 void rdsv3_destroy_task_workqueue(rdsv3_workqueue_struct_t *wq); 355 rdsv3_workqueue_struct_t *rdsv3_create_task_workqueue(char *name); 356 int rdsv3_conn_constructor(void *buf, void *arg, int kmflags); 357 void rdsv3_conn_destructor(void *buf, void *arg); 358 int rdsv3_conn_compare(const void *conn1, const void *conn2); 359 void rdsv3_loop_init(); 360 int rdsv3_mr_compare(const void *mr1, const void *mr2); 361 int rdsv3_put_cmsg(struct nmsghdr *msg, int level, int type, size_t size, 362 void *payload); 363 int rdsv3_verify_bind_address(ipaddr_t addr); 364 int rdsv3_bind_node_compare(const void *a, const void *b); 365 void rdsv3_bind_tree_init(); 366 void rdsv3_bind_tree_exit(); 367 uint16_t rdsv3_ip_fast_csum(void *buffer, size_t length); 368 uint_t rdsv3_ib_dma_map_sg(struct ib_device *dev, struct rdsv3_scatterlist 369 *scat, uint_t num); 370 void rdsv3_ib_dma_unmap_sg(ib_device_t *dev, struct rdsv3_scatterlist *scat, 371 uint_t num); 372 inline void 373 rdsv3_sk_sock_hold(struct rsock *sk) 374 { 375 atomic_add_32(&sk->sk_refcount, 1); 376 } 377 inline void 378 rdsv3_sk_sock_put(struct rsock *sk) 379 { 380 if (atomic_dec_and_test(&sk->sk_refcount)) 381 rdsv3_sock_exit_data(sk); 382 } 383 inline int 384 rdsv3_sk_sock_flag(struct rsock *sk, uint_t flag) 385 { 386 return (test_bit(flag, &sk->sk_flag)); 387 } 388 inline void 389 rdsv3_sk_sock_orphan(struct rsock *sk) 390 { 391 set_bit(SOCK_DEAD, &sk->sk_flag); 392 } 393 394 #define rdsv3_rcvtimeo(a, b) 3600 /* check this value on linux */ 395 396 void rdsv3_ib_free_conn(void *arg); 397 398 #ifdef __cplusplus 399 } 400 #endif 401 402 #endif /* _RDSV3_IMPL_H */ 403