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