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