Print this page
XXXX introduce drv_sectohz
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/common/io/ib/clients/rdsv3/rdsv3_impl.c
+++ new/usr/src/uts/common/io/ib/clients/rdsv3/rdsv3_impl.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
23 23 */
24 24 #include <sys/types.h>
25 25 #include <sys/stream.h>
26 26 #include <sys/dlpi.h>
27 27 #include <sys/stropts.h>
28 28 #include <sys/strsun.h>
29 29 #include <sys/sysmacros.h>
30 30 #include <sys/strlog.h>
31 31 #include <sys/ddi.h>
32 32 #include <sys/cmn_err.h>
33 33 #include <sys/socket.h>
34 34 #include <net/if.h>
35 35 #include <net/if_types.h>
36 36 #include <netinet/in.h>
37 37 #include <sys/ethernet.h>
38 38 #include <inet/arp.h>
39 39 #include <inet/ip.h>
40 40 #include <inet/ip6.h>
41 41 #include <inet/ip_ire.h>
42 42 #include <inet/ip_if.h>
43 43 #include <inet/ip_ftable.h>
44 44
45 45 #include <sys/sunddi.h>
46 46 #include <sys/ksynch.h>
47 47
48 48 #include <sys/rds.h>
49 49 #include <sys/socket.h>
50 50 #include <sys/socketvar.h>
51 51 #include <sys/sockio.h>
52 52 #include <sys/sysmacros.h>
53 53 #include <inet/common.h>
54 54 #include <inet/ip.h>
55 55 #include <net/if_types.h>
56 56
57 57 #include <sys/ib/clients/rdsv3/rdsv3.h>
58 58 #include <sys/ib/clients/rdsv3/rdma.h>
59 59 #include <sys/ib/clients/rdsv3/ib.h>
60 60 #include <sys/ib/clients/rdsv3/rdsv3_impl.h>
61 61 #include <sys/ib/clients/rdsv3/rdsv3_debug.h>
62 62
63 63 #include <sys/dls.h>
64 64 #include <sys/mac.h>
65 65 #include <sys/mac_client.h>
66 66 #include <sys/mac_provider.h>
67 67 #include <sys/mac_client_priv.h>
68 68
69 69 ddi_taskq_t *rdsv3_taskq = NULL;
70 70 extern kmem_cache_t *rdsv3_alloc_cache;
71 71
72 72 extern unsigned int ip_ocsum(ushort_t *address, int halfword_count,
73 73 unsigned int sum);
74 74
75 75 /*
76 76 * Check if the IP interface named by `lifrp' is RDS-capable.
77 77 */
78 78 boolean_t
79 79 rdsv3_capable_interface(struct lifreq *lifrp)
80 80 {
81 81 char ifname[LIFNAMSIZ];
82 82 char drv[MAXLINKNAMELEN];
83 83 uint_t ppa;
84 84 char *cp;
85 85
86 86 RDSV3_DPRINTF4("rdsv3_capable_interface", "Enter");
87 87
88 88 if (lifrp->lifr_type == IFT_IB)
89 89 return (B_TRUE);
90 90
91 91 /*
92 92 * Strip off the logical interface portion before getting
93 93 * intimate with the name.
94 94 */
95 95 (void) strlcpy(ifname, lifrp->lifr_name, LIFNAMSIZ);
96 96 if ((cp = strchr(ifname, ':')) != NULL)
97 97 *cp = '\0';
98 98
99 99 if (strcmp("lo0", ifname) == 0) {
100 100 /*
101 101 * loopback is considered RDS-capable
102 102 */
103 103 return (B_TRUE);
104 104 }
105 105
106 106 return (ddi_parse(ifname, drv, &ppa) == DDI_SUCCESS &&
107 107 rdsv3_if_lookup_by_name(drv));
108 108 }
109 109
110 110 int
111 111 rdsv3_do_ip_ioctl(ksocket_t so4, void **ipaddrs, int *size, int *nifs)
112 112 {
113 113 struct lifnum lifn;
114 114 struct lifconf lifc;
115 115 struct lifreq *lp, *rlp, lifr;
116 116 int rval = 0;
117 117 int numifs;
118 118 int bufsize, rbufsize;
119 119 void *buf, *rbuf;
120 120 int i, j, n, rc;
121 121
122 122 *ipaddrs = NULL;
123 123 *size = 0;
124 124 *nifs = 0;
125 125
126 126 RDSV3_DPRINTF4("rdsv3_do_ip_ioctl", "Enter");
127 127
128 128 retry_count:
129 129 /* snapshot the current number of interfaces */
130 130 lifn.lifn_family = PF_UNSPEC;
131 131 lifn.lifn_flags = LIFC_NOXMIT | LIFC_TEMPORARY | LIFC_ALLZONES;
132 132 lifn.lifn_count = 0;
133 133 rval = ksocket_ioctl(so4, SIOCGLIFNUM, (intptr_t)&lifn, &rval,
134 134 CRED());
135 135 if (rval != 0) {
136 136 RDSV3_DPRINTF2("rdsv3_do_ip_ioctl",
137 137 "ksocket_ioctl returned: %d", rval);
138 138 return (rval);
139 139 }
140 140
141 141 numifs = lifn.lifn_count;
142 142 if (numifs <= 0) {
143 143 RDSV3_DPRINTF2("rdsv3_do_ip_ioctl", "No interfaces found");
144 144 return (0);
145 145 }
146 146
147 147 /* allocate extra room in case more interfaces appear */
148 148 numifs += 10;
149 149
150 150 /* get the interface names and ip addresses */
151 151 bufsize = numifs * sizeof (struct lifreq);
152 152 buf = kmem_alloc(bufsize, KM_SLEEP);
153 153
154 154 lifc.lifc_family = AF_UNSPEC;
155 155 lifc.lifc_flags = LIFC_NOXMIT | LIFC_TEMPORARY | LIFC_ALLZONES;
156 156 lifc.lifc_len = bufsize;
157 157 lifc.lifc_buf = buf;
158 158 rc = ksocket_ioctl(so4, SIOCGLIFCONF, (intptr_t)&lifc, &rval, CRED());
159 159 if (rc != 0) {
160 160 RDSV3_DPRINTF2("rdsv3_do_ip_ioctl", "SIOCGLIFCONF failed");
161 161 kmem_free(buf, bufsize);
162 162 return (rc);
163 163 }
164 164 /* if our extra room is used up, try again */
165 165 if (bufsize <= lifc.lifc_len) {
166 166 kmem_free(buf, bufsize);
167 167 buf = NULL;
168 168 goto retry_count;
169 169 }
170 170 /* calc actual number of ifconfs */
171 171 n = lifc.lifc_len / sizeof (struct lifreq);
172 172
173 173 /*
174 174 * Count the RDS interfaces
175 175 */
176 176 for (i = 0, j = 0, lp = lifc.lifc_req; i < n; i++, lp++) {
177 177
178 178 /*
179 179 * Copy as the SIOCGLIFFLAGS ioctl is destructive
180 180 */
181 181 bcopy(lp, &lifr, sizeof (struct lifreq));
182 182 /*
183 183 * fetch the flags using the socket of the correct family
184 184 */
185 185 switch (lifr.lifr_addr.ss_family) {
186 186 case AF_INET:
187 187 rc = ksocket_ioctl(so4, SIOCGLIFFLAGS, (intptr_t)&lifr,
188 188 &rval, CRED());
189 189 break;
190 190 default:
191 191 continue;
192 192 }
193 193
194 194 if (rc != 0) continue;
195 195
196 196 /*
197 197 * If we got the flags, skip uninteresting
198 198 * interfaces based on flags
199 199 */
200 200 if ((lifr.lifr_flags & IFF_UP) != IFF_UP)
201 201 continue;
202 202 if (lifr.lifr_flags &
203 203 (IFF_ANYCAST|IFF_NOLOCAL|IFF_DEPRECATED))
204 204 continue;
205 205 if (!rdsv3_capable_interface(&lifr))
206 206 continue;
207 207 j++;
208 208 }
209 209
210 210 if (j <= 0) {
211 211 RDSV3_DPRINTF2("rdsv3_do_ip_ioctl", "No RDS interfaces");
212 212 kmem_free(buf, bufsize);
213 213 return (rval);
214 214 }
215 215
216 216 numifs = j;
217 217
218 218 /* This is the buffer we pass back */
219 219 rbufsize = numifs * sizeof (struct lifreq);
220 220 rbuf = kmem_alloc(rbufsize, KM_SLEEP);
221 221 rlp = (struct lifreq *)rbuf;
222 222
223 223 /*
224 224 * Examine the array of interfaces and filter uninteresting ones
225 225 */
226 226 for (i = 0, lp = lifc.lifc_req; i < n; i++, lp++) {
227 227
228 228 /*
229 229 * Copy the address as the SIOCGLIFFLAGS ioctl is destructive
230 230 */
231 231 bcopy(lp, &lifr, sizeof (struct lifreq));
232 232 /*
233 233 * fetch the flags using the socket of the correct family
234 234 */
235 235 switch (lifr.lifr_addr.ss_family) {
236 236 case AF_INET:
237 237 rc = ksocket_ioctl(so4, SIOCGLIFFLAGS, (intptr_t)&lifr,
238 238 &rval, CRED());
239 239 break;
240 240 default:
241 241 continue;
242 242 }
243 243
244 244
245 245 if (rc != 0) {
246 246 RDSV3_DPRINTF2("rdsv3_do_ip_ioctl",
247 247 "ksocket_ioctl failed" " for %s", lifr.lifr_name);
248 248 continue;
249 249 }
250 250
251 251 /*
252 252 * If we got the flags, skip uninteresting
253 253 * interfaces based on flags
254 254 */
255 255 if ((lifr.lifr_flags & IFF_UP) != IFF_UP)
256 256 continue;
257 257 if (lifr.lifr_flags &
258 258 (IFF_ANYCAST|IFF_NOLOCAL|IFF_DEPRECATED))
259 259 continue;
260 260 if (!rdsv3_capable_interface(&lifr))
261 261 continue;
262 262
263 263 /* save the record */
264 264 bcopy(lp, rlp, sizeof (struct lifreq));
265 265 rlp->lifr_addr.ss_family = AF_INET_OFFLOAD;
266 266 rlp++;
267 267 }
268 268
269 269 kmem_free(buf, bufsize);
270 270
271 271 *ipaddrs = rbuf;
272 272 *size = rbufsize;
273 273 *nifs = numifs;
274 274
275 275 RDSV3_DPRINTF4("rdsv3_do_ip_ioctl", "Return");
276 276
277 277 return (rval);
278 278 }
279 279
280 280 /*
281 281 * Check if the IP interface named by `ifrp' is RDS-capable.
282 282 */
283 283 boolean_t
284 284 rdsv3_capable_interface_old(struct ifreq *ifrp)
285 285 {
286 286 char ifname[IFNAMSIZ];
287 287 char drv[MAXLINKNAMELEN];
288 288 uint_t ppa;
289 289 char *cp;
290 290
291 291 RDSV3_DPRINTF4("rdsv3_capable_interface_old", "Enter");
292 292
293 293 /*
294 294 * Strip off the logical interface portion before getting
295 295 * intimate with the name.
296 296 */
297 297 (void) strlcpy(ifname, ifrp->ifr_name, IFNAMSIZ);
298 298 if ((cp = strchr(ifname, ':')) != NULL)
299 299 *cp = '\0';
300 300
301 301 RDSV3_DPRINTF4("rdsv3_capable_interface_old", "ifname: %s", ifname);
302 302
303 303 if ((strcmp("lo0", ifname) == 0) ||
304 304 (strncmp("ibd", ifname, 3) == 0)) {
305 305 /*
306 306 * loopback and IB are considered RDS-capable
307 307 */
308 308 return (B_TRUE);
309 309 }
310 310
311 311 return (ddi_parse(ifname, drv, &ppa) == DDI_SUCCESS &&
312 312 rdsv3_if_lookup_by_name(drv));
313 313 }
314 314
315 315 int
316 316 rdsv3_do_ip_ioctl_old(ksocket_t so4, void **ipaddrs, int *size, int *nifs)
317 317 {
318 318 uint_t ifn;
319 319 struct ifconf ifc;
320 320 struct ifreq *lp, *rlp, ifr;
321 321 int rval = 0;
322 322 int numifs;
323 323 int bufsize, rbufsize;
324 324 void *buf, *rbuf;
325 325 int i, j, n, rc;
326 326
327 327 *ipaddrs = NULL;
328 328 *size = 0;
329 329 *nifs = 0;
330 330
331 331 RDSV3_DPRINTF4("rdsv3_do_ip_ioctl_old", "Enter");
332 332
333 333 retry_count:
334 334 rval = ksocket_ioctl(so4, SIOCGIFNUM, (intptr_t)&ifn, &rval,
335 335 CRED());
336 336 if (rval != 0) {
337 337 RDSV3_DPRINTF2("rdsv3_do_ip_ioctl_old",
338 338 "ksocket_ioctl(SIOCGIFNUM) returned: %d", rval);
339 339 return (rval);
340 340 }
341 341
342 342 numifs = ifn;
343 343 if (numifs <= 0) {
344 344 RDSV3_DPRINTF2("rdsv3_do_ip_ioctl_old", "No interfaces found");
345 345 return (0);
346 346 }
347 347
348 348 /* allocate extra room in case more interfaces appear */
349 349 numifs += 10;
350 350
351 351 /* get the interface names and ip addresses */
352 352 bufsize = numifs * sizeof (struct ifreq);
353 353 buf = kmem_alloc(bufsize, KM_SLEEP);
354 354
355 355 ifc.ifc_len = bufsize;
356 356 ifc.ifc_buf = buf;
357 357 rc = ksocket_ioctl(so4, SIOCGIFCONF, (intptr_t)&ifc, &rval, CRED());
358 358 if (rc != 0) {
359 359 RDSV3_DPRINTF2("rdsv3_do_ip_ioctl_old",
360 360 "SIOCGLIFCONF failed: %d", rc);
361 361 kmem_free(buf, bufsize);
362 362 return (rc);
363 363 }
364 364 /* if our extra room is used up, try again */
365 365 if (bufsize <= ifc.ifc_len) {
366 366 kmem_free(buf, bufsize);
367 367 buf = NULL;
368 368 goto retry_count;
369 369 }
370 370 /* calc actual number of ifconfs */
371 371 n = ifc.ifc_len / sizeof (struct ifreq);
372 372
373 373 /*
374 374 * Count the RDS interfaces
375 375 */
376 376 for (i = 0, j = 0, lp = ifc.ifc_req; i < n; i++, lp++) {
377 377
378 378 /*
379 379 * Copy as the SIOCGIFFLAGS ioctl is destructive
380 380 */
381 381 bcopy(lp, &ifr, sizeof (struct ifreq));
382 382 /*
383 383 * fetch the flags using the socket of the correct family
384 384 */
385 385 switch (ifr.ifr_addr.sa_family) {
386 386 case AF_INET:
387 387 rc = ksocket_ioctl(so4, SIOCGIFFLAGS, (intptr_t)&ifr,
388 388 &rval, CRED());
389 389 break;
390 390 default:
391 391 continue;
392 392 }
393 393
394 394 if (rc != 0) continue;
395 395
396 396 RDSV3_DPRINTF2("rdsv3_do_ip_ioctl_old",
397 397 "1. ifr_name: %s, flags: %d", ifr.ifr_name,
398 398 (ushort_t)ifr.ifr_flags);
399 399
400 400 /*
401 401 * If we got the flags, skip uninteresting
402 402 * interfaces based on flags
403 403 */
404 404 if ((((ushort_t)ifr.ifr_flags) & IFF_UP) != IFF_UP)
405 405 continue;
406 406 RDSV3_DPRINTF2("rdsv3_do_ip_ioctl_old",
407 407 "2. ifr_name: %s, flags: %d", ifr.ifr_name,
408 408 (ushort_t)ifr.ifr_flags);
409 409 if (((ushort_t)ifr.ifr_flags) &
410 410 (IFF_ANYCAST|IFF_NOLOCAL|IFF_DEPRECATED))
411 411 continue;
412 412 RDSV3_DPRINTF2("rdsv3_do_ip_ioctl_old",
413 413 "3. ifr_name: %s, flags: %d", ifr.ifr_name,
414 414 (ushort_t)ifr.ifr_flags);
415 415 if (!rdsv3_capable_interface_old(&ifr))
416 416 continue;
417 417 RDSV3_DPRINTF2("rdsv3_do_ip_ioctl_old",
418 418 "4. ifr_name: %s, flags: %d", ifr.ifr_name,
419 419 (ushort_t)ifr.ifr_flags);
420 420 j++;
421 421 }
422 422
423 423 if (j <= 0) {
424 424 RDSV3_DPRINTF2("rdsv3_do_ip_ioctl_old", "No RDS interfaces");
425 425 kmem_free(buf, bufsize);
426 426 return (rval);
427 427 }
428 428
429 429 numifs = j;
430 430
431 431 /* This is the buffer we pass back */
432 432 rbufsize = numifs * sizeof (struct ifreq);
433 433 rbuf = kmem_alloc(rbufsize, KM_SLEEP);
434 434 rlp = (struct ifreq *)rbuf;
435 435
436 436 /*
437 437 * Examine the array of interfaces and filter uninteresting ones
438 438 */
439 439 for (i = 0, lp = ifc.ifc_req; i < n; i++, lp++) {
440 440
441 441 /*
442 442 * Copy the address as the SIOCGIFFLAGS ioctl is destructive
443 443 */
444 444 bcopy(lp, &ifr, sizeof (struct ifreq));
445 445 /*
446 446 * fetch the flags using the socket of the correct family
447 447 */
448 448 switch (ifr.ifr_addr.sa_family) {
449 449 case AF_INET:
450 450 rc = ksocket_ioctl(so4, SIOCGIFFLAGS, (intptr_t)&ifr,
451 451 &rval, CRED());
452 452 break;
453 453 default:
454 454 continue;
455 455 }
456 456
457 457
458 458 if (rc != 0) {
459 459 RDSV3_DPRINTF2("rdsv3_do_ip_ioctl_old",
460 460 "ksocket_ioctl failed: %d for %s",
461 461 rc, ifr.ifr_name);
462 462 continue;
463 463 }
464 464
465 465 /*
466 466 * If we got the flags, skip uninteresting
467 467 * interfaces based on flags
468 468 */
469 469 if ((((ushort_t)ifr.ifr_flags) & IFF_UP) != IFF_UP)
470 470 continue;
471 471 if (((ushort_t)ifr.ifr_flags) &
472 472 (IFF_ANYCAST|IFF_NOLOCAL|IFF_DEPRECATED))
473 473 continue;
474 474 if (!rdsv3_capable_interface_old(&ifr))
475 475 continue;
476 476
477 477 /* save the record */
478 478 bcopy(lp, rlp, sizeof (struct ifreq));
479 479 rlp->ifr_addr.sa_family = AF_INET_OFFLOAD;
480 480 rlp++;
481 481 }
482 482
483 483 kmem_free(buf, bufsize);
484 484
485 485 *ipaddrs = rbuf;
486 486 *size = rbufsize;
487 487 *nifs = numifs;
488 488
489 489 RDSV3_DPRINTF4("rdsv3_do_ip_ioctl_old", "Return");
490 490
491 491 return (rval);
492 492 }
493 493
494 494 boolean_t
495 495 rdsv3_isloopback(ipaddr_t addr)
496 496 {
497 497 ip_stack_t *ipst;
498 498
499 499 ipst = netstack_find_by_zoneid(GLOBAL_ZONEID)->netstack_ip;
500 500 ASSERT(ipst != NULL);
501 501 if (ip_type_v4(addr, ipst) != IRE_LOOPBACK) {
502 502 netstack_rele(ipst->ips_netstack);
503 503 return (B_FALSE);
504 504 }
505 505 netstack_rele(ipst->ips_netstack);
506 506 return (B_TRUE);
507 507 }
508 508
509 509 /*
510 510 * Work Queue Implementation
511 511 */
512 512
513 513 #define RDSV3_WQ_THREAD_IDLE 0
514 514 #define RDSV3_WQ_THREAD_RUNNING 1
515 515 #define RDSV3_WQ_THREAD_FLUSHING 2
516 516 #define RDSV3_WQ_THREAD_EXITING 3
517 517
518 518 /* worker thread */
519 519 void
520 520 rdsv3_worker_thread(void *arg)
521 521 {
522 522 rdsv3_workqueue_struct_t *wq = arg;
523 523 rdsv3_work_t *work;
524 524
525 525 RDSV3_DPRINTF4("rdsv3_worker_thread", "Enter(wq: 0x%p)", wq);
526 526
527 527 mutex_enter(&wq->wq_lock);
528 528 work = list_remove_head(&wq->wq_queue);
529 529 while (work) {
530 530 mutex_exit(&wq->wq_lock);
531 531
532 532 /* process work */
533 533 work->func(work);
534 534
535 535 mutex_enter(&wq->wq_lock);
536 536 work = list_remove_head(&wq->wq_queue);
537 537 }
538 538
539 539 /* No more work, go home, until called again */
540 540 if (wq->wq_state != RDSV3_WQ_THREAD_EXITING) {
541 541 wq->wq_state = RDSV3_WQ_THREAD_IDLE;
542 542 }
543 543 mutex_exit(&wq->wq_lock);
544 544
545 545 RDSV3_DPRINTF4("rdsv3_worker_thread", "Return(wq: 0x%p)", wq);
546 546 }
547 547
548 548 /* XXX */
549 549 void
550 550 rdsv3_flush_workqueue(rdsv3_workqueue_struct_t *wq)
551 551 {
552 552 RDSV3_DPRINTF4("rdsv3_flush_workqueue", "Enter(wq: %p)", wq);
553 553
554 554 mutex_enter(&wq->wq_lock);
555 555 switch (wq->wq_state) {
556 556 case RDSV3_WQ_THREAD_IDLE:
557 557 /* nothing to do */
↓ open down ↓ |
557 lines elided |
↑ open up ↑ |
558 558 ASSERT(list_is_empty(&wq->wq_queue));
559 559 break;
560 560
561 561 case RDSV3_WQ_THREAD_RUNNING:
562 562 wq->wq_state = RDSV3_WQ_THREAD_FLUSHING;
563 563 /* FALLTHRU */
564 564 case RDSV3_WQ_THREAD_FLUSHING:
565 565 /* already flushing, wait until the flushing is complete */
566 566 do {
567 567 mutex_exit(&wq->wq_lock);
568 - delay(drv_usectohz(1000000));
568 + delay(drv_sectohz(1));
569 569 mutex_enter(&wq->wq_lock);
570 570 } while (wq->wq_state == RDSV3_WQ_THREAD_FLUSHING);
571 571 break;
572 572 case RDSV3_WQ_THREAD_EXITING:
573 573 mutex_exit(&wq->wq_lock);
574 574 rdsv3_worker_thread(wq);
575 575 return;
576 576 }
577 577 mutex_exit(&wq->wq_lock);
578 578
579 579 RDSV3_DPRINTF4("rdsv3_flush_workqueue", "Return(wq: %p)", wq);
580 580 }
581 581
582 582 void
583 583 rdsv3_queue_work(rdsv3_workqueue_struct_t *wq, rdsv3_work_t *wp)
584 584 {
585 585 RDSV3_DPRINTF4("rdsv3_queue_work", "Enter(wq: %p, wp: %p)", wq, wp);
586 586
587 587 mutex_enter(&wq->wq_lock);
588 588
589 589 if (list_link_active(&wp->work_item)) {
590 590 /* This is already in the queue, ignore this call */
591 591 mutex_exit(&wq->wq_lock);
592 592 RDSV3_DPRINTF3("rdsv3_queue_work", "already queued: %p", wp);
593 593 return;
594 594 }
↓ open down ↓ |
16 lines elided |
↑ open up ↑ |
595 595
596 596 switch (wq->wq_state) {
597 597 case RDSV3_WQ_THREAD_RUNNING:
598 598 list_insert_tail(&wq->wq_queue, wp);
599 599 mutex_exit(&wq->wq_lock);
600 600 break;
601 601
602 602 case RDSV3_WQ_THREAD_FLUSHING:
603 603 do {
604 604 mutex_exit(&wq->wq_lock);
605 - delay(drv_usectohz(1000000));
605 + delay(drv_sectohz(1));
606 606 mutex_enter(&wq->wq_lock);
607 607 } while (wq->wq_state == RDSV3_WQ_THREAD_FLUSHING);
608 608
609 609 if (wq->wq_state == RDSV3_WQ_THREAD_RUNNING) {
610 610 list_insert_tail(&wq->wq_queue, wp);
611 611 mutex_exit(&wq->wq_lock);
612 612 break;
613 613 }
614 614 /* FALLTHRU */
615 615
616 616 case RDSV3_WQ_THREAD_IDLE:
617 617 list_insert_tail(&wq->wq_queue, wp);
618 618 wq->wq_state = RDSV3_WQ_THREAD_RUNNING;
619 619 mutex_exit(&wq->wq_lock);
620 620
621 621 (void) ddi_taskq_dispatch(rdsv3_taskq, rdsv3_worker_thread, wq,
622 622 DDI_SLEEP);
623 623 break;
624 624
625 625 case RDSV3_WQ_THREAD_EXITING:
626 626 mutex_exit(&wq->wq_lock);
627 627 break;
628 628 }
629 629
630 630 RDSV3_DPRINTF4("rdsv3_queue_work", "Return(wq: %p, wp: %p)", wq, wp);
631 631 }
632 632
633 633 /* timeout handler for delayed work queuing */
634 634 void
635 635 rdsv3_work_timeout_handler(void *arg)
636 636 {
637 637 rdsv3_delayed_work_t *dwp = (rdsv3_delayed_work_t *)arg;
638 638
639 639 RDSV3_DPRINTF4("rdsv3_work_timeout_handler",
640 640 "Enter(wq: %p, wp: %p)", dwp->wq, &dwp->work);
641 641
642 642 mutex_enter(&dwp->lock);
643 643 dwp->timeid = 0;
644 644 mutex_exit(&dwp->lock);
645 645
646 646 mutex_enter(&dwp->wq->wq_lock);
647 647 dwp->wq->wq_pending--;
648 648 if (dwp->wq->wq_state == RDSV3_WQ_THREAD_EXITING) {
649 649 mutex_exit(&dwp->wq->wq_lock);
650 650 return;
651 651 }
652 652 mutex_exit(&dwp->wq->wq_lock);
653 653
654 654 rdsv3_queue_work(dwp->wq, &dwp->work);
655 655
656 656 RDSV3_DPRINTF4("rdsv3_work_timeout_handler",
657 657 "Return(wq: %p, wp: %p)", dwp->wq, &dwp->work);
658 658 }
659 659
660 660 void
661 661 rdsv3_queue_delayed_work(rdsv3_workqueue_struct_t *wq,
662 662 rdsv3_delayed_work_t *dwp, uint_t delay)
663 663 {
664 664 RDSV3_DPRINTF4("rdsv3_queue_delayed_work",
665 665 "Enter(wq: %p, wp: %p)", wq, dwp);
666 666
667 667 if (delay == 0) {
668 668 rdsv3_queue_work(wq, &dwp->work);
669 669 return;
670 670 }
671 671
672 672 mutex_enter(&wq->wq_lock);
673 673 if (wq->wq_state == RDSV3_WQ_THREAD_EXITING) {
674 674 mutex_exit(&wq->wq_lock);
675 675 RDSV3_DPRINTF4("rdsv3_queue_delayed_work",
676 676 "WQ exiting - don't queue (wq: %p, wp: %p)", wq, dwp);
677 677 return;
678 678 }
679 679 wq->wq_pending++;
680 680 mutex_exit(&wq->wq_lock);
681 681
682 682 mutex_enter(&dwp->lock);
683 683 if (dwp->timeid == 0) {
684 684 dwp->wq = wq;
685 685 dwp->timeid = timeout(rdsv3_work_timeout_handler, dwp,
686 686 jiffies + (delay * rdsv3_one_sec_in_hz));
687 687 mutex_exit(&dwp->lock);
688 688 } else {
689 689 mutex_exit(&dwp->lock);
690 690 RDSV3_DPRINTF4("rdsv3_queue_delayed_work", "Already queued: %p",
691 691 dwp);
692 692 mutex_enter(&wq->wq_lock);
693 693 wq->wq_pending--;
694 694 mutex_exit(&wq->wq_lock);
695 695 }
696 696
697 697 RDSV3_DPRINTF4("rdsv3_queue_delayed_work",
698 698 "Return(wq: %p, wp: %p)", wq, dwp);
699 699 }
700 700
701 701 void
702 702 rdsv3_cancel_delayed_work(rdsv3_delayed_work_t *dwp)
703 703 {
704 704 RDSV3_DPRINTF4("rdsv3_cancel_delayed_work",
705 705 "Enter(wq: %p, dwp: %p)", dwp->wq, dwp);
706 706
707 707 mutex_enter(&dwp->lock);
708 708 if (dwp->timeid != 0) {
709 709 (void) untimeout(dwp->timeid);
710 710 dwp->timeid = 0;
711 711 } else {
712 712 RDSV3_DPRINTF4("rdsv3_cancel_delayed_work",
713 713 "Nothing to cancel (wq: %p, dwp: %p)", dwp->wq, dwp);
714 714 mutex_exit(&dwp->lock);
715 715 return;
716 716 }
717 717 mutex_exit(&dwp->lock);
718 718
719 719 mutex_enter(&dwp->wq->wq_lock);
720 720 dwp->wq->wq_pending--;
721 721 mutex_exit(&dwp->wq->wq_lock);
722 722
723 723 RDSV3_DPRINTF4("rdsv3_cancel_delayed_work",
724 724 "Return(wq: %p, dwp: %p)", dwp->wq, dwp);
725 725 }
726 726
727 727 void
728 728 rdsv3_destroy_task_workqueue(rdsv3_workqueue_struct_t *wq)
↓ open down ↓ |
113 lines elided |
↑ open up ↑ |
729 729 {
730 730 RDSV3_DPRINTF2("rdsv3_destroy_workqueue", "Enter");
731 731
732 732 ASSERT(wq);
733 733
734 734 mutex_enter(&wq->wq_lock);
735 735 wq->wq_state = RDSV3_WQ_THREAD_EXITING;
736 736
737 737 while (wq->wq_pending > 0) {
738 738 mutex_exit(&wq->wq_lock);
739 - delay(drv_usectohz(1000000));
739 + delay(drv_sectohz(1));
740 740 mutex_enter(&wq->wq_lock);
741 741 };
742 742 mutex_exit(&wq->wq_lock);
743 743
744 744 rdsv3_flush_workqueue(wq);
745 745
746 746 list_destroy(&wq->wq_queue);
747 747 mutex_destroy(&wq->wq_lock);
748 748 kmem_free(wq, sizeof (rdsv3_workqueue_struct_t));
749 749
750 750 ASSERT(rdsv3_taskq);
751 751 ddi_taskq_destroy(rdsv3_taskq);
752 752
753 753 wq = NULL;
754 754 rdsv3_taskq = NULL;
755 755
756 756 RDSV3_DPRINTF2("rdsv3_destroy_workqueue", "Return");
757 757 }
758 758
759 759 /* ARGSUSED */
760 760 void
761 761 rdsv3_rdma_init_worker(struct rdsv3_work_s *work)
762 762 {
763 763 rdsv3_rdma_init();
764 764 }
765 765
766 766 #define RDSV3_NUM_TASKQ_THREADS 1
767 767 rdsv3_workqueue_struct_t *
768 768 rdsv3_create_task_workqueue(char *name)
769 769 {
770 770 rdsv3_workqueue_struct_t *wq;
771 771
772 772 RDSV3_DPRINTF2("create_singlethread_workqueue", "Enter (dip: %p)",
773 773 rdsv3_dev_info);
774 774
775 775 rdsv3_taskq = ddi_taskq_create(rdsv3_dev_info, name,
776 776 RDSV3_NUM_TASKQ_THREADS, TASKQ_DEFAULTPRI, 0);
777 777 if (rdsv3_taskq == NULL) {
778 778 RDSV3_DPRINTF2(__FILE__,
779 779 "ddi_taskq_create failed for rdsv3_taskq");
780 780 return (NULL);
781 781 }
782 782
783 783 wq = kmem_zalloc(sizeof (rdsv3_workqueue_struct_t), KM_NOSLEEP);
784 784 if (wq == NULL) {
↓ open down ↓ |
35 lines elided |
↑ open up ↑ |
785 785 RDSV3_DPRINTF2(__FILE__, "kmem_zalloc failed for wq");
786 786 ddi_taskq_destroy(rdsv3_taskq);
787 787 return (NULL);
788 788 }
789 789
790 790 list_create(&wq->wq_queue, sizeof (struct rdsv3_work_s),
791 791 offsetof(struct rdsv3_work_s, work_item));
792 792 mutex_init(&wq->wq_lock, NULL, MUTEX_DRIVER, NULL);
793 793 wq->wq_state = RDSV3_WQ_THREAD_IDLE;
794 794 wq->wq_pending = 0;
795 - rdsv3_one_sec_in_hz = drv_usectohz(1000000);
795 + rdsv3_one_sec_in_hz = drv_sectohz(1);
796 796
797 797 RDSV3_DPRINTF2("create_singlethread_workqueue", "Return");
798 798
799 799 return (wq);
800 800 }
801 801
802 802 /*
803 803 * Implementation for struct sock
804 804 */
805 805
806 806 void
807 807 rdsv3_sock_exit_data(struct rsock *sk)
808 808 {
809 809 struct rdsv3_sock *rs = sk->sk_protinfo;
810 810
811 811 RDSV3_DPRINTF4("rdsv3_sock_exit_data", "rs: %p sk: %p", rs, sk);
812 812
813 813 ASSERT(rs != NULL);
814 814 ASSERT(rdsv3_sk_sock_flag(sk, SOCK_DEAD));
815 815
816 816 rs->rs_sk = NULL;
817 817
818 818 list_destroy(&rs->rs_send_queue);
819 819 list_destroy(&rs->rs_notify_queue);
820 820 list_destroy(&rs->rs_recv_queue);
821 821
822 822 rw_destroy(&rs->rs_recv_lock);
823 823 mutex_destroy(&rs->rs_lock);
824 824
825 825 mutex_destroy(&rs->rs_rdma_lock);
826 826 avl_destroy(&rs->rs_rdma_keys);
827 827
828 828 mutex_destroy(&rs->rs_conn_lock);
829 829 mutex_destroy(&rs->rs_congested_lock);
830 830 cv_destroy(&rs->rs_congested_cv);
831 831
832 832 rdsv3_exit_waitqueue(sk->sk_sleep);
833 833 kmem_free(sk->sk_sleep, sizeof (rdsv3_wait_queue_t));
834 834 mutex_destroy(&sk->sk_lock);
835 835
836 836 kmem_cache_free(rdsv3_alloc_cache, sk);
837 837 RDSV3_DPRINTF4("rdsv3_sock_exit_data", "rs: %p sk: %p", rs, sk);
838 838 }
839 839
840 840 /* XXX - figure out right values */
841 841 #define RDSV3_RECV_HIWATER (256 * 1024)
842 842 #define RDSV3_RECV_LOWATER 128
843 843 #define RDSV3_XMIT_HIWATER (256 * 1024)
844 844 #define RDSV3_XMIT_LOWATER 1024
845 845
846 846 struct rsock *
847 847 rdsv3_sk_alloc()
848 848 {
849 849 struct rsock *sk;
850 850
851 851 sk = kmem_cache_alloc(rdsv3_alloc_cache, KM_SLEEP);
852 852 if (sk == NULL) {
853 853 RDSV3_DPRINTF2("rdsv3_create", "kmem_cache_alloc failed");
854 854 return (NULL);
855 855 }
856 856
857 857 bzero(sk, sizeof (struct rsock) + sizeof (struct rdsv3_sock));
858 858 return (sk);
859 859 }
860 860
861 861 void
862 862 rdsv3_sock_init_data(struct rsock *sk)
863 863 {
864 864 sk->sk_sleep = kmem_zalloc(sizeof (rdsv3_wait_queue_t), KM_SLEEP);
865 865 rdsv3_init_waitqueue(sk->sk_sleep);
866 866
867 867 mutex_init(&sk->sk_lock, NULL, MUTEX_DRIVER, NULL);
868 868 sk->sk_refcount = 1;
869 869 sk->sk_protinfo = (struct rdsv3_sock *)(sk + 1);
870 870 sk->sk_sndbuf = RDSV3_XMIT_HIWATER;
871 871 sk->sk_rcvbuf = RDSV3_RECV_HIWATER;
872 872 }
873 873
874 874 /*
875 875 * Connection cache
876 876 */
877 877 /* ARGSUSED */
878 878 int
879 879 rdsv3_conn_constructor(void *buf, void *arg, int kmflags)
880 880 {
881 881 struct rdsv3_connection *conn = buf;
882 882
883 883 bzero(conn, sizeof (struct rdsv3_connection));
884 884
885 885 conn->c_next_tx_seq = 1;
886 886 mutex_init(&conn->c_lock, NULL, MUTEX_DRIVER, NULL);
887 887 mutex_init(&conn->c_send_lock, NULL, MUTEX_DRIVER, NULL);
888 888 conn->c_send_generation = 1;
889 889 conn->c_senders = 0;
890 890
891 891 list_create(&conn->c_send_queue, sizeof (struct rdsv3_message),
892 892 offsetof(struct rdsv3_message, m_conn_item));
893 893 list_create(&conn->c_retrans, sizeof (struct rdsv3_message),
894 894 offsetof(struct rdsv3_message, m_conn_item));
895 895 return (0);
896 896 }
897 897
898 898 /* ARGSUSED */
899 899 void
900 900 rdsv3_conn_destructor(void *buf, void *arg)
901 901 {
902 902 struct rdsv3_connection *conn = buf;
903 903
904 904 ASSERT(list_is_empty(&conn->c_send_queue));
905 905 ASSERT(list_is_empty(&conn->c_retrans));
906 906 list_destroy(&conn->c_send_queue);
907 907 list_destroy(&conn->c_retrans);
908 908 mutex_destroy(&conn->c_send_lock);
909 909 mutex_destroy(&conn->c_lock);
910 910 }
911 911
912 912 int
913 913 rdsv3_conn_compare(const void *conn1, const void *conn2)
914 914 {
915 915 uint32_be_t laddr1, faddr1, laddr2, faddr2;
916 916
917 917 laddr1 = ((rdsv3_conn_info_t *)conn1)->c_laddr;
918 918 laddr2 = ((struct rdsv3_connection *)conn2)->c_laddr;
919 919
920 920 if (laddr1 == laddr2) {
921 921 faddr1 = ((rdsv3_conn_info_t *)conn1)->c_faddr;
922 922 faddr2 = ((struct rdsv3_connection *)conn2)->c_faddr;
923 923 if (faddr1 == faddr2)
924 924 return (0);
925 925 if (faddr1 < faddr2)
926 926 return (-1);
927 927 return (1);
928 928 }
929 929
930 930 if (laddr1 < laddr2)
931 931 return (-1);
932 932
933 933 return (1);
934 934 }
935 935
936 936 /* rdsv3_ib_incoming cache */
937 937 /* ARGSUSED */
938 938 int
939 939 rdsv3_ib_inc_constructor(void *buf, void *arg, int kmflags)
940 940 {
941 941 list_create(&((struct rdsv3_ib_incoming *)buf)->ii_frags,
942 942 sizeof (struct rdsv3_page_frag),
943 943 offsetof(struct rdsv3_page_frag, f_item));
944 944
945 945 return (0);
946 946 }
947 947
948 948 /* ARGSUSED */
949 949 void
950 950 rdsv3_ib_inc_destructor(void *buf, void *arg)
951 951 {
952 952 list_destroy(&((struct rdsv3_ib_incoming *)buf)->ii_frags);
953 953 }
954 954
955 955 /* ib_frag_slab cache */
956 956 /* ARGSUSED */
957 957 int
958 958 rdsv3_ib_frag_constructor(void *buf, void *arg, int kmflags)
959 959 {
960 960 struct rdsv3_page_frag *frag = (struct rdsv3_page_frag *)buf;
961 961 struct rdsv3_ib_device *rds_ibdev = (struct rdsv3_ib_device *)arg;
962 962 ibt_iov_attr_t iov_attr;
963 963 ibt_iov_t iov_arr[1];
964 964 ibt_all_wr_t wr;
965 965
966 966 bzero(frag, sizeof (struct rdsv3_page_frag));
967 967 list_link_init(&frag->f_item);
968 968
969 969 frag->f_page = kmem_alloc(PAGE_SIZE, kmflags);
970 970 if (frag->f_page == NULL) {
971 971 RDSV3_DPRINTF2("rdsv3_ib_frag_constructor",
972 972 "kmem_alloc for %d failed", PAGE_SIZE);
973 973 return (-1);
974 974 }
975 975 frag->f_offset = 0;
976 976
977 977 iov_attr.iov_as = NULL;
978 978 iov_attr.iov = &iov_arr[0];
979 979 iov_attr.iov_buf = NULL;
980 980 iov_attr.iov_list_len = 1;
981 981 iov_attr.iov_wr_nds = 1;
982 982 iov_attr.iov_lso_hdr_sz = 0;
983 983 iov_attr.iov_flags = IBT_IOV_SLEEP | IBT_IOV_RECV;
984 984
985 985 iov_arr[0].iov_addr = frag->f_page;
986 986 iov_arr[0].iov_len = PAGE_SIZE;
987 987
988 988 wr.recv.wr_nds = 1;
989 989 wr.recv.wr_sgl = &frag->f_sge;
990 990
991 991 if (ibt_map_mem_iov(ib_get_ibt_hca_hdl(rds_ibdev->dev),
992 992 &iov_attr, &wr, &frag->f_mapped) != IBT_SUCCESS) {
993 993 RDSV3_DPRINTF2("rdsv3_ib_frag_constructor",
994 994 "ibt_map_mem_iov failed");
995 995 kmem_free(frag->f_page, PAGE_SIZE);
996 996 return (-1);
997 997 }
998 998
999 999 return (0);
1000 1000 }
1001 1001
1002 1002 /* ARGSUSED */
1003 1003 void
1004 1004 rdsv3_ib_frag_destructor(void *buf, void *arg)
1005 1005 {
1006 1006 struct rdsv3_page_frag *frag = (struct rdsv3_page_frag *)buf;
1007 1007 struct rdsv3_ib_device *rds_ibdev = (struct rdsv3_ib_device *)arg;
1008 1008
1009 1009 /* unmap the page */
1010 1010 if (ibt_unmap_mem_iov(ib_get_ibt_hca_hdl(rds_ibdev->dev),
1011 1011 frag->f_mapped) != IBT_SUCCESS)
1012 1012 RDSV3_DPRINTF2("rdsv3_ib_frag_destructor",
1013 1013 "ibt_unmap_mem_iov failed");
1014 1014
1015 1015 /* free the page */
1016 1016 kmem_free(frag->f_page, PAGE_SIZE);
1017 1017 }
1018 1018
1019 1019 /* loop.c */
1020 1020 extern kmutex_t loop_conns_lock;
1021 1021 extern list_t loop_conns;
1022 1022
1023 1023 struct rdsv3_loop_connection
1024 1024 {
1025 1025 struct list_node loop_node;
1026 1026 struct rdsv3_connection *conn;
1027 1027 };
1028 1028
1029 1029 void
1030 1030 rdsv3_loop_init(void)
1031 1031 {
1032 1032 list_create(&loop_conns, sizeof (struct rdsv3_loop_connection),
1033 1033 offsetof(struct rdsv3_loop_connection, loop_node));
1034 1034 mutex_init(&loop_conns_lock, NULL, MUTEX_DRIVER, NULL);
1035 1035 }
1036 1036
1037 1037 /* rdma.c */
1038 1038 /* IB Rkey is used here for comparison */
1039 1039 int
1040 1040 rdsv3_mr_compare(const void *mr1, const void *mr2)
1041 1041 {
1042 1042 uint32_t key1 = *(uint32_t *)mr1;
1043 1043 uint32_t key2 = ((struct rdsv3_mr *)mr2)->r_key;
1044 1044
1045 1045 if (key1 < key2)
1046 1046 return (-1);
1047 1047 if (key1 > key2)
1048 1048 return (1);
1049 1049 return (0);
1050 1050 }
1051 1051
1052 1052 /* transport.c */
1053 1053 extern struct rdsv3_transport *transports[];
1054 1054 extern krwlock_t trans_sem;
1055 1055
1056 1056 void
1057 1057 rdsv3_trans_exit(void)
1058 1058 {
1059 1059 struct rdsv3_transport *trans;
1060 1060 int i;
1061 1061
1062 1062 RDSV3_DPRINTF2("rdsv3_trans_exit", "Enter");
1063 1063
1064 1064 /* currently, only IB transport */
1065 1065 rw_enter(&trans_sem, RW_READER);
1066 1066 trans = NULL;
1067 1067 for (i = 0; i < RDS_TRANS_COUNT; i++) {
1068 1068 if (transports[i]) {
1069 1069 trans = transports[i];
1070 1070 break;
1071 1071 }
1072 1072 }
1073 1073 rw_exit(&trans_sem);
1074 1074
1075 1075 /* trans->exit() will remove the trans from the list */
1076 1076 if (trans)
1077 1077 trans->exit();
1078 1078
1079 1079 rw_destroy(&trans_sem);
1080 1080
1081 1081 RDSV3_DPRINTF2("rdsv3_trans_exit", "Return");
1082 1082 }
1083 1083
1084 1084 void
1085 1085 rdsv3_trans_init()
1086 1086 {
1087 1087 RDSV3_DPRINTF2("rdsv3_trans_init", "Enter");
1088 1088
1089 1089 rw_init(&trans_sem, NULL, RW_DRIVER, NULL);
1090 1090
1091 1091 RDSV3_DPRINTF2("rdsv3_trans_init", "Return");
1092 1092 }
1093 1093
1094 1094 int
1095 1095 rdsv3_put_cmsg(struct nmsghdr *msg, int level, int type, size_t size,
1096 1096 void *payload)
1097 1097 {
1098 1098 struct cmsghdr *cp;
1099 1099 char *bp;
1100 1100 size_t cmlen;
1101 1101 size_t cmspace;
1102 1102 size_t bufsz;
1103 1103
1104 1104 RDSV3_DPRINTF4("rdsv3_put_cmsg",
1105 1105 "Enter(msg: %p level: %d type: %d sz: %d)",
1106 1106 msg, level, type, size);
1107 1107
1108 1108 if (msg == NULL || msg->msg_controllen == 0) {
1109 1109 return (0);
1110 1110 }
1111 1111 /* check for first cmsg or this is another cmsg to be appended */
1112 1112 if (msg->msg_control == NULL)
1113 1113 msg->msg_controllen = 0;
1114 1114
1115 1115 cmlen = CMSG_LEN(size);
1116 1116 cmspace = CMSG_SPACE(size);
1117 1117 bufsz = msg->msg_controllen + cmspace;
1118 1118
1119 1119 /* extend the existing cmsg to append the next cmsg */
1120 1120 bp = kmem_alloc(bufsz, KM_SLEEP);
1121 1121 if (msg->msg_control) {
1122 1122 bcopy(msg->msg_control, bp, msg->msg_controllen);
1123 1123 kmem_free(msg->msg_control, (size_t)msg->msg_controllen);
1124 1124 }
1125 1125
1126 1126 /* assign payload the proper cmsg location */
1127 1127 cp = (struct cmsghdr *)(bp + msg->msg_controllen);
1128 1128 cp->cmsg_len = cmlen;
1129 1129 cp->cmsg_level = level;
1130 1130 cp->cmsg_type = type;
1131 1131
1132 1132 bcopy(payload, CMSG_DATA(cp), cmlen -
1133 1133 (unsigned int)_CMSG_DATA_ALIGN(sizeof (struct cmsghdr)));
1134 1134
1135 1135 msg->msg_control = bp;
1136 1136 msg->msg_controllen = bufsz;
1137 1137
1138 1138 RDSV3_DPRINTF4("rdsv3_put_cmsg", "Return(cmsg_len: %d)", cp->cmsg_len);
1139 1139
1140 1140 return (0);
1141 1141 }
1142 1142
1143 1143 /* ARGSUSED */
1144 1144 int
1145 1145 rdsv3_verify_bind_address(ipaddr_t addr)
1146 1146 {
1147 1147 return (1);
1148 1148 }
1149 1149
1150 1150 /* checksum */
1151 1151 uint16_t
1152 1152 rdsv3_ip_fast_csum(void *hdr, size_t length)
1153 1153 {
1154 1154 return (0xffff &
1155 1155 (uint16_t)(~ip_ocsum((ushort_t *)hdr, (int)length <<1, 0)));
1156 1156 }
1157 1157
1158 1158 /* scatterlist implementation */
1159 1159 /* ARGSUSED */
1160 1160 caddr_t
1161 1161 rdsv3_ib_sg_dma_address(ib_device_t *dev, struct rdsv3_scatterlist *scat,
1162 1162 uint_t offset)
1163 1163 {
1164 1164 return (0);
1165 1165 }
1166 1166
1167 1167 uint_t
1168 1168 rdsv3_ib_dma_map_sg(struct ib_device *dev, struct rdsv3_scatterlist *scat,
1169 1169 uint_t num)
1170 1170 {
1171 1171 struct rdsv3_scatterlist *s, *first;
1172 1172 ibt_iov_t *iov;
1173 1173 ibt_wr_ds_t *sgl;
1174 1174 ibt_iov_attr_t iov_attr;
1175 1175 ibt_send_wr_t swr;
1176 1176 uint_t i;
1177 1177
1178 1178 RDSV3_DPRINTF4("rdsv3_ib_dma_map_sg", "scat %p, num: %d", scat, num);
1179 1179
1180 1180 s = first = &scat[0];
1181 1181 ASSERT(first->mihdl == NULL);
1182 1182
1183 1183 iov = kmem_alloc(num * sizeof (ibt_iov_t), KM_SLEEP);
1184 1184 sgl = kmem_zalloc((num * 2) * sizeof (ibt_wr_ds_t), KM_SLEEP);
1185 1185
1186 1186 for (i = 0; i < num; i++, s++) {
1187 1187 iov[i].iov_addr = s->vaddr;
1188 1188 iov[i].iov_len = s->length;
1189 1189 }
1190 1190
1191 1191 iov_attr.iov_as = NULL;
1192 1192 iov_attr.iov = iov;
1193 1193 iov_attr.iov_buf = NULL;
1194 1194 iov_attr.iov_list_len = num;
1195 1195 iov_attr.iov_wr_nds = num * 2;
1196 1196 iov_attr.iov_lso_hdr_sz = 0;
1197 1197 iov_attr.iov_flags = IBT_IOV_SLEEP;
1198 1198
1199 1199 swr.wr_sgl = sgl;
1200 1200
1201 1201 i = ibt_map_mem_iov(ib_get_ibt_hca_hdl(dev),
1202 1202 &iov_attr, (ibt_all_wr_t *)&swr, &first->mihdl);
1203 1203 kmem_free(iov, num * sizeof (ibt_iov_t));
1204 1204 if (i != IBT_SUCCESS) {
1205 1205 RDSV3_DPRINTF2("rdsv3_ib_dma_map_sg",
1206 1206 "ibt_map_mem_iov returned: %d", i);
1207 1207 return (0);
1208 1208 }
1209 1209
1210 1210 s = first;
1211 1211 for (i = 0; i < num; i++, s++, sgl++) {
1212 1212 s->sgl = sgl;
1213 1213 }
1214 1214
1215 1215 return (num);
1216 1216 }
1217 1217
1218 1218 void
1219 1219 rdsv3_ib_dma_unmap_sg(ib_device_t *dev, struct rdsv3_scatterlist *scat,
1220 1220 uint_t num)
1221 1221 {
1222 1222 /* Zero length messages have no scatter gather entries */
1223 1223 if (num != 0) {
1224 1224 ASSERT(scat->mihdl != NULL);
1225 1225 ASSERT(scat->sgl != NULL);
1226 1226
1227 1227 (void) ibt_unmap_mem_iov(ib_get_ibt_hca_hdl(dev), scat->mihdl);
1228 1228
1229 1229 kmem_free(scat->sgl, (num * 2) * sizeof (ibt_wr_ds_t));
1230 1230 scat->sgl = NULL;
1231 1231 scat->mihdl = NULL;
1232 1232 }
1233 1233 }
1234 1234
1235 1235 int
1236 1236 rdsv3_ib_alloc_hdrs(ib_device_t *dev, struct rdsv3_ib_connection *ic)
1237 1237 {
1238 1238 caddr_t addr;
1239 1239 size_t size;
1240 1240 ibt_mr_attr_t mr_attr;
1241 1241 ibt_mr_desc_t mr_desc;
1242 1242 ibt_mr_hdl_t mr_hdl;
1243 1243 int ret;
1244 1244
1245 1245 RDSV3_DPRINTF4("rdsv3_ib_alloc_hdrs", "Enter(dev: %p)", dev);
1246 1246
1247 1247 ASSERT(ic->i_mr == NULL);
1248 1248
1249 1249 size = (ic->i_send_ring.w_nr + ic->i_recv_ring.w_nr + 1) *
1250 1250 sizeof (struct rdsv3_header);
1251 1251
1252 1252 addr = kmem_zalloc(size, KM_NOSLEEP);
1253 1253 if (addr == NULL)
1254 1254 return (-1);
1255 1255
1256 1256 mr_attr.mr_vaddr = (ib_vaddr_t)(uintptr_t)addr;
1257 1257 mr_attr.mr_len = size;
1258 1258 mr_attr.mr_as = NULL;
1259 1259 mr_attr.mr_flags = IBT_MR_ENABLE_LOCAL_WRITE;
1260 1260 ret = ibt_register_mr(ib_get_ibt_hca_hdl(dev), RDSV3_PD2PDHDL(ic->i_pd),
1261 1261 &mr_attr, &mr_hdl, &mr_desc);
1262 1262 if (ret != IBT_SUCCESS) {
1263 1263 RDSV3_DPRINTF2("rdsv3_ib_alloc_hdrs",
1264 1264 "ibt_register_mr returned: " "%d", ret);
1265 1265 return (-1);
1266 1266 }
1267 1267
1268 1268 ic->i_mr =
1269 1269 (struct rdsv3_hdrs_mr *)kmem_alloc(sizeof (struct rdsv3_hdrs_mr),
1270 1270 KM_SLEEP);
1271 1271 ic->i_mr->addr = addr;
1272 1272 ic->i_mr->size = size;
1273 1273 ic->i_mr->hdl = mr_hdl;
1274 1274 ic->i_mr->lkey = mr_desc.md_lkey;
1275 1275
1276 1276 ic->i_send_hdrs = (struct rdsv3_header *)addr;
1277 1277 ic->i_send_hdrs_dma = (uint64_t)(uintptr_t)addr;
1278 1278
1279 1279 ic->i_recv_hdrs = (struct rdsv3_header *)(addr +
1280 1280 (ic->i_send_ring.w_nr * sizeof (struct rdsv3_header)));
1281 1281 ic->i_recv_hdrs_dma = (uint64_t)(uintptr_t)(addr +
1282 1282 (ic->i_send_ring.w_nr * sizeof (struct rdsv3_header)));
1283 1283
1284 1284 ic->i_ack = (struct rdsv3_header *)(addr +
1285 1285 ((ic->i_send_ring.w_nr + ic->i_recv_ring.w_nr) *
1286 1286 sizeof (struct rdsv3_header)));
1287 1287 ic->i_ack_dma = (uint64_t)(uintptr_t)(addr +
1288 1288 ((ic->i_send_ring.w_nr + ic->i_recv_ring.w_nr) *
1289 1289 sizeof (struct rdsv3_header)));
1290 1290
1291 1291 RDSV3_DPRINTF4("rdsv3_ib_alloc_hdrs", "Return(dev: %p)", dev);
1292 1292
1293 1293 return (0);
1294 1294 }
1295 1295
1296 1296 void
1297 1297 rdsv3_ib_free_hdrs(ib_device_t *dev, struct rdsv3_ib_connection *ic)
1298 1298 {
1299 1299 RDSV3_DPRINTF4("rdsv3_ib_free_hdrs", "Enter(dev: %p)", dev);
1300 1300 ASSERT(ic->i_mr != NULL);
1301 1301
1302 1302 ic->i_send_hdrs = NULL;
1303 1303 ic->i_send_hdrs_dma = NULL;
1304 1304
1305 1305 ic->i_recv_hdrs = NULL;
1306 1306 ic->i_recv_hdrs_dma = NULL;
1307 1307
1308 1308 ic->i_ack = NULL;
1309 1309 ic->i_ack_dma = NULL;
1310 1310
1311 1311 (void) ibt_deregister_mr(ib_get_ibt_hca_hdl(dev), ic->i_mr->hdl);
1312 1312
1313 1313 kmem_free(ic->i_mr->addr, ic->i_mr->size);
1314 1314 kmem_free(ic->i_mr, sizeof (struct rdsv3_hdrs_mr));
1315 1315
1316 1316 ic->i_mr = NULL;
1317 1317 RDSV3_DPRINTF4("rdsv3_ib_free_hdrs", "Return(dev: %p)", dev);
1318 1318 }
1319 1319
1320 1320 /*
1321 1321 * atomic_add_unless - add unless the number is a given value
1322 1322 * @v: pointer of type atomic_t
1323 1323 * @a: the amount to add to v...
1324 1324 * @u: ...unless v is equal to u.
1325 1325 *
1326 1326 * Atomically adds @a to @v, so long as it was not @u.
1327 1327 * Returns non-zero if @v was not @u, and zero otherwise.
1328 1328 */
1329 1329 int
1330 1330 atomic_add_unless(atomic_t *v, uint_t a, ulong_t u)
1331 1331 {
1332 1332 uint_t c, old;
1333 1333
1334 1334 c = *v;
1335 1335 while (c != u && (old = atomic_cas_uint(v, c, c + a)) != c) {
1336 1336 c = old;
1337 1337 }
1338 1338 return ((ulong_t)c != u);
1339 1339 }
↓ open down ↓ |
534 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX