Print this page
5045 use atomic_{inc,dec}_* instead of atomic_add_*
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/common/io/ib/clients/rdsv3/message.c
+++ new/usr/src/uts/common/io/ib/clients/rdsv3/message.c
1 1 /*
2 2 * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
3 3 */
4 4
5 5 /*
6 6 * This file contains code imported from the OFED rds source file message.c
7 7 * Oracle elects to have and use the contents of message.c under and governed
8 8 * by the OpenIB.org BSD license (see below for full license text). However,
9 9 * the following notice accompanied the original version of this file:
10 10 */
11 11
12 12 /*
13 13 * Copyright (c) 2006 Oracle. All rights reserved.
14 14 *
15 15 * This software is available to you under a choice of one of two
16 16 * licenses. You may choose to be licensed under the terms of the GNU
17 17 * General Public License (GPL) Version 2, available from the file
18 18 * COPYING in the main directory of this source tree, or the
19 19 * OpenIB.org BSD license below:
20 20 *
21 21 * Redistribution and use in source and binary forms, with or
22 22 * without modification, are permitted provided that the following
23 23 * conditions are met:
24 24 *
25 25 * - Redistributions of source code must retain the above
26 26 * copyright notice, this list of conditions and the following
27 27 * disclaimer.
28 28 *
29 29 * - Redistributions in binary form must reproduce the above
30 30 * copyright notice, this list of conditions and the following
31 31 * disclaimer in the documentation and/or other materials
32 32 * provided with the distribution.
33 33 *
34 34 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
35 35 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
36 36 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
37 37 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
38 38 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
39 39 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
40 40 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
41 41 * SOFTWARE.
42 42 *
43 43 */
44 44 #include <sys/rds.h>
45 45
46 46 #include <sys/ib/clients/rdsv3/rdsv3.h>
47 47 #include <sys/ib/clients/rdsv3/rdma.h>
48 48 #include <sys/ib/clients/rdsv3/rdsv3_debug.h>
49 49
50 50 #ifndef __lock_lint
51 51 static unsigned int rdsv3_exthdr_size[__RDSV3_EXTHDR_MAX] = {
52 52 [RDSV3_EXTHDR_NONE] = 0,
53 53 [RDSV3_EXTHDR_VERSION] = sizeof (struct rdsv3_ext_header_version),
54 54 [RDSV3_EXTHDR_RDMA] = sizeof (struct rdsv3_ext_header_rdma),
55 55 [RDSV3_EXTHDR_RDMA_DEST] = sizeof (struct rdsv3_ext_header_rdma_dest),
56 56 };
57 57 #else
58 58 static unsigned int rdsv3_exthdr_size[__RDSV3_EXTHDR_MAX] = {
59 59 0,
60 60 sizeof (struct rdsv3_ext_header_version),
↓ open down ↓ |
60 lines elided |
↑ open up ↑ |
61 61 sizeof (struct rdsv3_ext_header_rdma),
62 62 sizeof (struct rdsv3_ext_header_rdma_dest),
63 63 };
64 64 #endif
65 65
66 66 void
67 67 rdsv3_message_addref(struct rdsv3_message *rm)
68 68 {
69 69 RDSV3_DPRINTF5("rdsv3_message_addref", "addref rm %p ref %d",
70 70 rm, atomic_get(&rm->m_refcount));
71 - atomic_add_32(&rm->m_refcount, 1);
71 + atomic_inc_32(&rm->m_refcount);
72 72 }
73 73
74 74 /*
75 75 * This relies on dma_map_sg() not touching sg[].page during merging.
76 76 */
77 77 static void
78 78 rdsv3_message_purge(struct rdsv3_message *rm)
79 79 {
80 80 unsigned long i;
81 81
82 82 RDSV3_DPRINTF4("rdsv3_message_purge", "Enter(rm: %p)", rm);
83 83
84 84 if (test_bit(RDSV3_MSG_PAGEVEC, &rm->m_flags))
85 85 return;
86 86
87 87 for (i = 0; i < rm->m_nents; i++) {
88 88 RDSV3_DPRINTF5("rdsv3_message_purge", "putting data page %p\n",
89 89 (void *)rdsv3_sg_page(&rm->m_sg[i]));
90 90 /* XXX will have to put_page for page refs */
91 91 kmem_free(rdsv3_sg_page(&rm->m_sg[i]),
92 92 rdsv3_sg_len(&rm->m_sg[i]));
93 93 }
94 94
95 95 if (rm->m_rdma_op)
96 96 rdsv3_rdma_free_op(rm->m_rdma_op);
97 97 if (rm->m_rdma_mr) {
98 98 struct rdsv3_mr *mr = rm->m_rdma_mr;
99 99 if (mr->r_refcount == 0) {
100 100 RDSV3_DPRINTF4("rdsv3_message_purge ASSERT 0",
101 101 "rm %p mr %p", rm, mr);
102 102 return;
103 103 }
104 104 if (mr->r_refcount == 0xdeadbeef) {
105 105 RDSV3_DPRINTF4("rdsv3_message_purge ASSERT deadbeef",
106 106 "rm %p mr %p", rm, mr);
107 107 return;
108 108 }
109 109 if (atomic_dec_and_test(&mr->r_refcount)) {
110 110 rm->m_rdma_mr = NULL;
111 111 __rdsv3_put_mr_final(mr);
112 112 }
113 113 }
114 114
115 115 RDSV3_DPRINTF4("rdsv3_message_purge", "Return(rm: %p)", rm);
116 116
117 117 }
118 118
119 119 void
120 120 rdsv3_message_put(struct rdsv3_message *rm)
121 121 {
122 122 RDSV3_DPRINTF5("rdsv3_message_put",
123 123 "put rm %p ref %d\n", rm, atomic_get(&rm->m_refcount));
124 124
125 125 if (atomic_dec_and_test(&rm->m_refcount)) {
126 126 ASSERT(!list_link_active(&rm->m_sock_item));
127 127 ASSERT(!list_link_active(&rm->m_conn_item));
128 128 rdsv3_message_purge(rm);
129 129
130 130 kmem_free(rm, sizeof (struct rdsv3_message) +
131 131 (rm->m_nents * sizeof (struct rdsv3_scatterlist)));
132 132 }
133 133 }
134 134
135 135 void
136 136 rdsv3_message_inc_free(struct rdsv3_incoming *inc)
137 137 {
138 138 struct rdsv3_message *rm =
139 139 container_of(inc, struct rdsv3_message, m_inc);
140 140 rdsv3_message_put(rm);
141 141 }
142 142
143 143 void
144 144 rdsv3_message_populate_header(struct rdsv3_header *hdr, uint16_be_t sport,
145 145 uint16_be_t dport, uint64_t seq)
146 146 {
147 147 hdr->h_flags = 0;
148 148 hdr->h_sport = sport;
149 149 hdr->h_dport = dport;
150 150 hdr->h_sequence = htonll(seq);
151 151 hdr->h_exthdr[0] = RDSV3_EXTHDR_NONE;
152 152 }
153 153
154 154 int
155 155 rdsv3_message_add_extension(struct rdsv3_header *hdr,
156 156 unsigned int type, const void *data, unsigned int len)
157 157 {
158 158 unsigned int ext_len = sizeof (uint8_t) + len;
159 159 unsigned char *dst;
160 160
161 161 RDSV3_DPRINTF4("rdsv3_message_add_extension", "Enter");
162 162
163 163 /* For now, refuse to add more than one extension header */
164 164 if (hdr->h_exthdr[0] != RDSV3_EXTHDR_NONE)
165 165 return (0);
166 166
167 167 if (type >= __RDSV3_EXTHDR_MAX ||
168 168 len != rdsv3_exthdr_size[type])
169 169 return (0);
170 170
171 171 if (ext_len >= RDSV3_HEADER_EXT_SPACE)
172 172 return (0);
173 173 dst = hdr->h_exthdr;
174 174
175 175 *dst++ = type;
176 176 (void) memcpy(dst, data, len);
177 177
178 178 dst[len] = RDSV3_EXTHDR_NONE;
179 179
180 180 RDSV3_DPRINTF4("rdsv3_message_add_extension", "Return");
181 181 return (1);
182 182 }
183 183
184 184 /*
185 185 * If a message has extension headers, retrieve them here.
186 186 * Call like this:
187 187 *
188 188 * unsigned int pos = 0;
189 189 *
190 190 * while (1) {
191 191 * buflen = sizeof(buffer);
192 192 * type = rdsv3_message_next_extension(hdr, &pos, buffer, &buflen);
193 193 * if (type == RDSV3_EXTHDR_NONE)
194 194 * break;
195 195 * ...
196 196 * }
197 197 */
198 198 int
199 199 rdsv3_message_next_extension(struct rdsv3_header *hdr,
200 200 unsigned int *pos, void *buf, unsigned int *buflen)
201 201 {
202 202 unsigned int offset, ext_type, ext_len;
203 203 uint8_t *src = hdr->h_exthdr;
204 204
205 205 RDSV3_DPRINTF4("rdsv3_message_next_extension", "Enter");
206 206
207 207 offset = *pos;
208 208 if (offset >= RDSV3_HEADER_EXT_SPACE)
209 209 goto none;
210 210
211 211 /*
212 212 * Get the extension type and length. For now, the
213 213 * length is implied by the extension type.
214 214 */
215 215 ext_type = src[offset++];
216 216
217 217 if (ext_type == RDSV3_EXTHDR_NONE || ext_type >= __RDSV3_EXTHDR_MAX)
218 218 goto none;
219 219 ext_len = rdsv3_exthdr_size[ext_type];
220 220 if (offset + ext_len > RDSV3_HEADER_EXT_SPACE)
221 221 goto none;
222 222
223 223 *pos = offset + ext_len;
224 224 if (ext_len < *buflen)
225 225 *buflen = ext_len;
226 226 (void) memcpy(buf, src + offset, *buflen);
227 227 return (ext_type);
228 228
229 229 none:
230 230 *pos = RDSV3_HEADER_EXT_SPACE;
231 231 *buflen = 0;
232 232 return (RDSV3_EXTHDR_NONE);
233 233 }
234 234
235 235 int
236 236 rdsv3_message_add_version_extension(struct rdsv3_header *hdr,
237 237 unsigned int version)
238 238 {
239 239 struct rdsv3_ext_header_version ext_hdr;
240 240
241 241 ext_hdr.h_version = htonl(version);
242 242 return (rdsv3_message_add_extension(hdr, RDSV3_EXTHDR_VERSION,
243 243 &ext_hdr, sizeof (ext_hdr)));
244 244 }
245 245
246 246 int
247 247 rdsv3_message_get_version_extension(struct rdsv3_header *hdr,
248 248 unsigned int *version)
249 249 {
250 250 struct rdsv3_ext_header_version ext_hdr;
251 251 unsigned int pos = 0, len = sizeof (ext_hdr);
252 252
253 253 RDSV3_DPRINTF4("rdsv3_message_get_version_extension", "Enter");
254 254
255 255 /*
256 256 * We assume the version extension is the only one present
257 257 */
258 258 if (rdsv3_message_next_extension(hdr, &pos, &ext_hdr, &len) !=
259 259 RDSV3_EXTHDR_VERSION)
260 260 return (0);
261 261 *version = ntohl(ext_hdr.h_version);
262 262 return (1);
263 263 }
264 264
265 265 int
266 266 rdsv3_message_add_rdma_dest_extension(struct rdsv3_header *hdr, uint32_t r_key,
267 267 uint32_t offset)
268 268 {
269 269 struct rdsv3_ext_header_rdma_dest ext_hdr;
270 270
271 271 ext_hdr.h_rdma_rkey = htonl(r_key);
272 272 ext_hdr.h_rdma_offset = htonl(offset);
273 273 return (rdsv3_message_add_extension(hdr, RDSV3_EXTHDR_RDMA_DEST,
274 274 &ext_hdr, sizeof (ext_hdr)));
275 275 }
276 276
277 277 struct rdsv3_message *
278 278 rdsv3_message_alloc(unsigned int nents, int gfp)
279 279 {
280 280 struct rdsv3_message *rm;
281 281
282 282 RDSV3_DPRINTF4("rdsv3_message_alloc", "Enter(nents: %d)", nents);
283 283
284 284 rm = kmem_zalloc(sizeof (struct rdsv3_message) +
285 285 (nents * sizeof (struct rdsv3_scatterlist)), gfp);
286 286 if (!rm)
287 287 goto out;
288 288
289 289 rm->m_refcount = 1;
290 290 list_link_init(&rm->m_sock_item);
291 291 list_link_init(&rm->m_conn_item);
292 292 mutex_init(&rm->m_rs_lock, NULL, MUTEX_DRIVER, NULL);
293 293 rdsv3_init_waitqueue(&rm->m_flush_wait);
294 294
295 295 RDSV3_DPRINTF4("rdsv3_message_alloc", "Return(rm: %p)", rm);
296 296 out:
297 297 return (rm);
298 298 }
299 299
300 300 struct rdsv3_message *
301 301 rdsv3_message_map_pages(unsigned long *page_addrs, unsigned int total_len)
302 302 {
303 303 struct rdsv3_message *rm;
304 304 unsigned int i;
305 305
306 306 RDSV3_DPRINTF4("rdsv3_message_map_pages", "Enter(len: %d)", total_len);
307 307
308 308 #ifndef __lock_lint
309 309 rm = rdsv3_message_alloc(ceil(total_len, PAGE_SIZE), KM_NOSLEEP);
310 310 #else
311 311 rm = NULL;
312 312 #endif
313 313 if (rm == NULL)
314 314 return (ERR_PTR(-ENOMEM));
315 315
316 316 set_bit(RDSV3_MSG_PAGEVEC, &rm->m_flags);
317 317 rm->m_inc.i_hdr.h_len = htonl(total_len);
318 318 #ifndef __lock_lint
319 319 rm->m_nents = ceil(total_len, PAGE_SIZE);
320 320 #else
321 321 rm->m_nents = 0;
322 322 #endif
323 323
324 324 for (i = 0; i < rm->m_nents; ++i) {
325 325 rdsv3_sg_set_page(&rm->m_sg[i],
326 326 page_addrs[i],
327 327 PAGE_SIZE, 0);
328 328 }
329 329
330 330 return (rm);
331 331 }
332 332
333 333 struct rdsv3_message *
334 334 rdsv3_message_copy_from_user(struct uio *uiop,
335 335 size_t total_len)
336 336 {
337 337 struct rdsv3_message *rm;
338 338 struct rdsv3_scatterlist *sg;
339 339 int ret;
340 340
341 341 RDSV3_DPRINTF4("rdsv3_message_copy_from_user", "Enter: %d", total_len);
342 342
343 343 #ifndef __lock_lint
344 344 rm = rdsv3_message_alloc(ceil(total_len, PAGE_SIZE), KM_NOSLEEP);
345 345 #else
346 346 rm = NULL;
347 347 #endif
348 348 if (rm == NULL) {
349 349 ret = -ENOMEM;
350 350 goto out;
351 351 }
352 352
353 353 rm->m_inc.i_hdr.h_len = htonl(total_len);
354 354
355 355 /*
356 356 * now allocate and copy in the data payload.
357 357 */
358 358 sg = rm->m_sg;
359 359
360 360 while (total_len) {
361 361 if (rdsv3_sg_page(sg) == NULL) {
362 362 ret = rdsv3_page_remainder_alloc(sg, total_len, 0);
363 363 if (ret)
364 364 goto out;
365 365 rm->m_nents++;
366 366 }
367 367
368 368 ret = uiomove(rdsv3_sg_page(sg), rdsv3_sg_len(sg), UIO_WRITE,
369 369 uiop);
370 370 if (ret) {
371 371 RDSV3_DPRINTF2("rdsv3_message_copy_from_user",
372 372 "uiomove failed");
373 373 ret = -ret;
374 374 goto out;
375 375 }
376 376
377 377 total_len -= rdsv3_sg_len(sg);
378 378 sg++;
379 379 }
380 380 ret = 0;
381 381 out:
382 382 if (ret) {
383 383 if (rm)
384 384 rdsv3_message_put(rm);
385 385 rm = ERR_PTR(ret);
386 386 }
387 387 return (rm);
388 388 }
389 389
390 390 int
391 391 rdsv3_message_inc_copy_to_user(struct rdsv3_incoming *inc,
392 392 uio_t *uiop, size_t size)
393 393 {
394 394 struct rdsv3_message *rm;
395 395 struct rdsv3_scatterlist *sg;
396 396 unsigned long to_copy;
397 397 unsigned long vec_off;
398 398 int copied;
399 399 int ret;
400 400 uint32_t len;
401 401
402 402 rm = container_of(inc, struct rdsv3_message, m_inc);
403 403 len = ntohl(rm->m_inc.i_hdr.h_len);
404 404
405 405 RDSV3_DPRINTF4("rdsv3_message_inc_copy_to_user",
406 406 "Enter(rm: %p, len: %d)", rm, len);
407 407
408 408 sg = rm->m_sg;
409 409 vec_off = 0;
410 410 copied = 0;
411 411
412 412 while (copied < size && copied < len) {
413 413
414 414 to_copy = min(len - copied, sg->length - vec_off);
415 415 to_copy = min(size - copied, to_copy);
416 416
417 417 RDSV3_DPRINTF5("rdsv3_message_inc_copy_to_user",
418 418 "copying %lu bytes to user iov %p from sg [%p, %u] + %lu\n",
419 419 to_copy, uiop,
420 420 rdsv3_sg_page(sg), sg->length, vec_off);
421 421
422 422 ret = uiomove(rdsv3_sg_page(sg), to_copy, UIO_READ, uiop);
423 423 if (ret)
424 424 break;
425 425
426 426 vec_off += to_copy;
427 427 copied += to_copy;
428 428
429 429 if (vec_off == sg->length) {
430 430 vec_off = 0;
431 431 sg++;
432 432 }
433 433 }
434 434
435 435 return (copied);
436 436 }
437 437
438 438 /*
439 439 * If the message is still on the send queue, wait until the transport
440 440 * is done with it. This is particularly important for RDMA operations.
441 441 */
442 442 /* ARGSUSED */
443 443 void
444 444 rdsv3_message_wait(struct rdsv3_message *rm)
445 445 {
446 446 rdsv3_wait_event(&rm->m_flush_wait,
447 447 !test_bit(RDSV3_MSG_MAPPED, &rm->m_flags));
448 448 }
449 449
450 450 void
451 451 rdsv3_message_unmapped(struct rdsv3_message *rm)
452 452 {
453 453 clear_bit(RDSV3_MSG_MAPPED, &rm->m_flags);
454 454 rdsv3_wake_up_all(&rm->m_flush_wait);
455 455 }
↓ open down ↓ |
374 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX