1 /* $NetBSD: ldc.c,v 1.6 2019/10/15 00:13:52 chs Exp $ */ 2 /* $OpenBSD: ldc.c,v 1.12 2015/03/21 18:02:58 kettenis Exp $ */ 3 /* 4 * Copyright (c) 2009 Mark Kettenis 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #include <sys/kmem.h> 20 #include <sys/malloc.h> 21 #include <sys/param.h> 22 #include <sys/systm.h> 23 24 #include <sys/bus.h> 25 #include <machine/hypervisor.h> 26 27 #include <uvm/uvm_extern.h> 28 29 #include <sparc64/dev/ldcvar.h> 30 31 #ifdef LDC_DEBUG 32 #define DPRINTF(x) printf x 33 #else 34 #define DPRINTF(x) 35 #endif 36 37 void ldc_rx_ctrl_vers(struct ldc_conn *, struct ldc_pkt *); 38 void ldc_rx_ctrl_rtr(struct ldc_conn *, struct ldc_pkt *); 39 void ldc_rx_ctrl_rts(struct ldc_conn *, struct ldc_pkt *); 40 void ldc_rx_ctrl_rdx(struct ldc_conn *, struct ldc_pkt *); 41 42 void ldc_send_ack(struct ldc_conn *); 43 void ldc_send_rtr(struct ldc_conn *); 44 void ldc_send_rts(struct ldc_conn *); 45 void ldc_send_rdx(struct ldc_conn *); 46 47 void 48 ldc_rx_ctrl(struct ldc_conn *lc, struct ldc_pkt *lp) 49 { 50 switch (lp->ctrl) { 51 case LDC_VERS: 52 ldc_rx_ctrl_vers(lc, lp); 53 break; 54 55 case LDC_RTS: 56 ldc_rx_ctrl_rts(lc, lp); 57 break; 58 59 case LDC_RTR: 60 ldc_rx_ctrl_rtr(lc, lp); 61 break; 62 63 case LDC_RDX: 64 ldc_rx_ctrl_rdx(lc, lp); 65 break; 66 67 default: 68 DPRINTF(("CTRL/0x%02x/0x%02x\n", lp->stype, lp->ctrl)); 69 ldc_reset(lc); 70 break; 71 } 72 } 73 74 void 75 ldc_rx_ctrl_vers(struct ldc_conn *lc, struct ldc_pkt *lp) 76 { 77 switch (lp->stype) { 78 case LDC_INFO: 79 DPRINTF(("CTRL/INFO/VERS\n")); 80 if (lp->major == LDC_VERSION_MAJOR && 81 lp->minor == LDC_VERSION_MINOR) 82 ldc_send_ack(lc); 83 else { 84 /* XXX do nothing for now. */ 85 } 86 break; 87 88 case LDC_ACK: 89 if (lc->lc_state != LDC_SND_VERS) { 90 DPRINTF(("Spurious CTRL/ACK/VERS: state %d\n", 91 lc->lc_state)); 92 ldc_reset(lc); 93 return; 94 } 95 DPRINTF(("CTRL/ACK/VERS\n")); 96 ldc_send_rts(lc); 97 break; 98 99 case LDC_NACK: 100 DPRINTF(("CTRL/NACK/VERS\n")); 101 ldc_reset(lc); 102 break; 103 104 default: 105 DPRINTF(("CTRL/0x%02x/VERS\n", lp->stype)); 106 ldc_reset(lc); 107 break; 108 } 109 } 110 111 void 112 ldc_rx_ctrl_rts(struct ldc_conn *lc, struct ldc_pkt *lp) 113 { 114 switch (lp->stype) { 115 case LDC_INFO: 116 if (lc->lc_state != LDC_RCV_VERS) { 117 DPRINTF(("Spurious CTRL/INFO/RTS: state %d\n", 118 lc->lc_state)); 119 ldc_reset(lc); 120 return; 121 } 122 DPRINTF(("CTRL/INFO/RTS\n")); 123 ldc_send_rtr(lc); 124 break; 125 126 case LDC_ACK: 127 DPRINTF(("CTRL/ACK/RTS\n")); 128 ldc_reset(lc); 129 break; 130 131 case LDC_NACK: 132 DPRINTF(("CTRL/NACK/RTS\n")); 133 ldc_reset(lc); 134 break; 135 136 default: 137 DPRINTF(("CTRL/0x%02x/RTS\n", lp->stype)); 138 ldc_reset(lc); 139 break; 140 } 141 } 142 143 void 144 ldc_rx_ctrl_rtr(struct ldc_conn *lc, struct ldc_pkt *lp) 145 { 146 switch (lp->stype) { 147 case LDC_INFO: 148 if (lc->lc_state != LDC_SND_RTS) { 149 DPRINTF(("Spurious CTRL/INFO/RTR: state %d\n", 150 lc->lc_state)); 151 ldc_reset(lc); 152 return; 153 } 154 DPRINTF(("CTRL/INFO/RTR\n")); 155 ldc_send_rdx(lc); 156 lc->lc_start(lc); 157 break; 158 159 case LDC_ACK: 160 DPRINTF(("CTRL/ACK/RTR\n")); 161 ldc_reset(lc); 162 break; 163 164 case LDC_NACK: 165 DPRINTF(("CTRL/NACK/RTR\n")); 166 ldc_reset(lc); 167 break; 168 169 default: 170 DPRINTF(("CTRL/0x%02x/RTR\n", lp->stype)); 171 ldc_reset(lc); 172 break; 173 } 174 } 175 176 void 177 ldc_rx_ctrl_rdx(struct ldc_conn *lc, struct ldc_pkt *lp) 178 { 179 switch (lp->stype) { 180 case LDC_INFO: 181 if (lc->lc_state != LDC_SND_RTR) { 182 DPRINTF(("Spurious CTRL/INFO/RTR: state %d\n", 183 lc->lc_state)); 184 ldc_reset(lc); 185 return; 186 } 187 DPRINTF(("CTRL/INFO/RDX\n")); 188 lc->lc_start(lc); 189 break; 190 191 case LDC_ACK: 192 DPRINTF(("CTRL/ACK/RDX\n")); 193 ldc_reset(lc); 194 break; 195 196 case LDC_NACK: 197 DPRINTF(("CTRL/NACK/RDX\n")); 198 ldc_reset(lc); 199 break; 200 201 default: 202 DPRINTF(("CTRL/0x%02x/RDX\n", lp->stype)); 203 ldc_reset(lc); 204 break; 205 } 206 } 207 208 void 209 ldc_rx_data(struct ldc_conn *lc, struct ldc_pkt *lp) 210 { 211 size_t len; 212 213 if (lp->stype != LDC_INFO) { 214 DPRINTF(("DATA/0x%02x\n", lp->stype)); 215 ldc_reset(lc); 216 return; 217 } 218 219 if (lc->lc_state != LDC_SND_RTR && 220 lc->lc_state != LDC_SND_RDX) { 221 DPRINTF(("Spurious DATA/INFO: state %d\n", lc->lc_state)); 222 ldc_reset(lc); 223 return; 224 } 225 226 if (lp->env & LDC_FRAG_START) { 227 lc->lc_len = (lp->env & LDC_LEN_MASK) + 8; 228 KASSERT(lc->lc_len <= sizeof(lc->lc_msg)); 229 memcpy((uint8_t *)lc->lc_msg, lp, lc->lc_len); 230 } else { 231 len = (lp->env & LDC_LEN_MASK); 232 if (lc->lc_len + len > sizeof(lc->lc_msg)) { 233 DPRINTF(("Buffer overrun\n")); 234 ldc_reset(lc); 235 return; 236 } 237 memcpy(((uint8_t *)lc->lc_msg) + lc->lc_len, &lp->major, len); 238 lc->lc_len += len; 239 } 240 241 if (lp->env & LDC_FRAG_STOP) 242 lc->lc_rx_data(lc, (struct ldc_pkt *)lc->lc_msg); 243 } 244 245 void 246 ldc_send_vers(struct ldc_conn *lc) 247 { 248 struct ldc_pkt *lp; 249 uint64_t tx_head, tx_tail, tx_state; 250 int err; 251 252 mutex_enter(&lc->lc_txq->lq_mtx); 253 err = hv_ldc_tx_get_state(lc->lc_id, &tx_head, &tx_tail, &tx_state); 254 if (err != H_EOK || tx_state != LDC_CHANNEL_UP) { 255 mutex_exit(&lc->lc_txq->lq_mtx); 256 return; 257 } 258 259 lp = (struct ldc_pkt *)(uintptr_t)(lc->lc_txq->lq_va + tx_tail); 260 bzero(lp, sizeof(struct ldc_pkt)); 261 lp->type = LDC_CTRL; 262 lp->stype = LDC_INFO; 263 lp->ctrl = LDC_VERS; 264 lp->major = 1; 265 lp->minor = 0; 266 267 tx_tail += sizeof(*lp); 268 tx_tail &= ((lc->lc_txq->lq_nentries * sizeof(*lp)) - 1); 269 err = hv_ldc_tx_set_qtail(lc->lc_id, tx_tail); 270 if (err != H_EOK) { 271 printf("%s: hv_ldc_tx_set_qtail: %d\n", __func__, err); 272 mutex_exit(&lc->lc_txq->lq_mtx); 273 return; 274 } 275 276 lc->lc_state = LDC_SND_VERS; 277 mutex_exit(&lc->lc_txq->lq_mtx); 278 } 279 280 void 281 ldc_send_ack(struct ldc_conn *lc) 282 { 283 struct ldc_pkt *lp; 284 uint64_t tx_head, tx_tail, tx_state; 285 int err; 286 287 mutex_enter(&lc->lc_txq->lq_mtx); 288 err = hv_ldc_tx_get_state(lc->lc_id, &tx_head, &tx_tail, &tx_state); 289 if (err != H_EOK || tx_state != LDC_CHANNEL_UP) { 290 mutex_exit(&lc->lc_txq->lq_mtx); 291 return; 292 } 293 294 lp = (struct ldc_pkt *)(uintptr_t)(lc->lc_txq->lq_va + tx_tail); 295 bzero(lp, sizeof(struct ldc_pkt)); 296 lp->type = LDC_CTRL; 297 lp->stype = LDC_ACK; 298 lp->ctrl = LDC_VERS; 299 lp->major = 1; 300 lp->minor = 0; 301 302 tx_tail += sizeof(*lp); 303 tx_tail &= ((lc->lc_txq->lq_nentries * sizeof(*lp)) - 1); 304 err = hv_ldc_tx_set_qtail(lc->lc_id, tx_tail); 305 if (err != H_EOK) { 306 printf("%s: hv_ldc_tx_set_qtail: %d\n", __func__, err); 307 mutex_exit(&lc->lc_txq->lq_mtx); 308 return; 309 } 310 311 lc->lc_state = LDC_RCV_VERS; 312 mutex_exit(&lc->lc_txq->lq_mtx); 313 } 314 315 void 316 ldc_send_rts(struct ldc_conn *lc) 317 { 318 struct ldc_pkt *lp; 319 uint64_t tx_head, tx_tail, tx_state; 320 int err; 321 322 mutex_enter(&lc->lc_txq->lq_mtx); 323 err = hv_ldc_tx_get_state(lc->lc_id, &tx_head, &tx_tail, &tx_state); 324 if (err != H_EOK || tx_state != LDC_CHANNEL_UP) { 325 mutex_exit(&lc->lc_txq->lq_mtx); 326 return; 327 } 328 329 lp = (struct ldc_pkt *)(uintptr_t)(lc->lc_txq->lq_va + tx_tail); 330 bzero(lp, sizeof(struct ldc_pkt)); 331 lp->type = LDC_CTRL; 332 lp->stype = LDC_INFO; 333 lp->ctrl = LDC_RTS; 334 lp->env = LDC_MODE_UNRELIABLE; 335 lp->seqid = lc->lc_tx_seqid++; 336 337 tx_tail += sizeof(*lp); 338 tx_tail &= ((lc->lc_txq->lq_nentries * sizeof(*lp)) - 1); 339 err = hv_ldc_tx_set_qtail(lc->lc_id, tx_tail); 340 if (err != H_EOK) { 341 printf("%s: hv_ldc_tx_set_qtail: %d\n", __func__, err); 342 mutex_exit(&lc->lc_txq->lq_mtx); 343 return; 344 } 345 346 lc->lc_state = LDC_SND_RTS; 347 mutex_exit(&lc->lc_txq->lq_mtx); 348 } 349 350 void 351 ldc_send_rtr(struct ldc_conn *lc) 352 { 353 struct ldc_pkt *lp; 354 uint64_t tx_head, tx_tail, tx_state; 355 int err; 356 357 mutex_enter(&lc->lc_txq->lq_mtx); 358 err = hv_ldc_tx_get_state(lc->lc_id, &tx_head, &tx_tail, &tx_state); 359 if (err != H_EOK || tx_state != LDC_CHANNEL_UP) { 360 mutex_exit(&lc->lc_txq->lq_mtx); 361 return; 362 } 363 364 lp = (struct ldc_pkt *)(uintptr_t)(lc->lc_txq->lq_va + tx_tail); 365 bzero(lp, sizeof(struct ldc_pkt)); 366 lp->type = LDC_CTRL; 367 lp->stype = LDC_INFO; 368 lp->ctrl = LDC_RTR; 369 lp->env = LDC_MODE_UNRELIABLE; 370 lp->seqid = lc->lc_tx_seqid++; 371 372 tx_tail += sizeof(*lp); 373 tx_tail &= ((lc->lc_txq->lq_nentries * sizeof(*lp)) - 1); 374 err = hv_ldc_tx_set_qtail(lc->lc_id, tx_tail); 375 if (err != H_EOK) { 376 printf("%s: hv_ldc_tx_set_qtail: %d\n", __func__, err); 377 mutex_exit(&lc->lc_txq->lq_mtx); 378 return; 379 } 380 381 lc->lc_state = LDC_SND_RTR; 382 mutex_exit(&lc->lc_txq->lq_mtx); 383 } 384 385 void 386 ldc_send_rdx(struct ldc_conn *lc) 387 { 388 struct ldc_pkt *lp; 389 uint64_t tx_head, tx_tail, tx_state; 390 int err; 391 392 mutex_enter(&lc->lc_txq->lq_mtx); 393 err = hv_ldc_tx_get_state(lc->lc_id, &tx_head, &tx_tail, &tx_state); 394 if (err != H_EOK || tx_state != LDC_CHANNEL_UP) { 395 mutex_exit(&lc->lc_txq->lq_mtx); 396 return; 397 } 398 399 lp = (struct ldc_pkt *)(uintptr_t)(lc->lc_txq->lq_va + tx_tail); 400 bzero(lp, sizeof(struct ldc_pkt)); 401 lp->type = LDC_CTRL; 402 lp->stype = LDC_INFO; 403 lp->ctrl = LDC_RDX; 404 lp->env = LDC_MODE_UNRELIABLE; 405 lp->seqid = lc->lc_tx_seqid++; 406 407 tx_tail += sizeof(*lp); 408 tx_tail &= ((lc->lc_txq->lq_nentries * sizeof(*lp)) - 1); 409 err = hv_ldc_tx_set_qtail(lc->lc_id, tx_tail); 410 if (err != H_EOK) { 411 printf("%s: hv_ldc_tx_set_qtail: %d\n", __func__, err); 412 mutex_exit(&lc->lc_txq->lq_mtx); 413 return; 414 } 415 416 lc->lc_state = LDC_SND_RDX; 417 mutex_exit(&lc->lc_txq->lq_mtx); 418 } 419 420 int 421 ldc_send_unreliable(struct ldc_conn *lc, void *msg, size_t len) 422 { 423 struct ldc_pkt *lp; 424 uint64_t tx_head, tx_tail, tx_state; 425 uint64_t tx_avail; 426 uint8_t *p = msg; 427 int err; 428 429 mutex_enter(&lc->lc_txq->lq_mtx); 430 err = hv_ldc_tx_get_state(lc->lc_id, &tx_head, &tx_tail, &tx_state); 431 if (err != H_EOK || tx_state != LDC_CHANNEL_UP) { 432 mutex_exit(&lc->lc_txq->lq_mtx); 433 return (EIO); 434 } 435 436 tx_avail = (tx_head - tx_tail) / sizeof(*lp) + 437 lc->lc_txq->lq_nentries - 1; 438 tx_avail %= lc->lc_txq->lq_nentries; 439 if (len > tx_avail * LDC_PKT_PAYLOAD) { 440 mutex_exit(&lc->lc_txq->lq_mtx); 441 return (EWOULDBLOCK); 442 } 443 444 while (len > 0) { 445 lp = (struct ldc_pkt *)(uintptr_t)(lc->lc_txq->lq_va + tx_tail); 446 bzero(lp, sizeof(struct ldc_pkt)); 447 lp->type = LDC_DATA; 448 lp->stype = LDC_INFO; 449 lp->env = uimin(len, LDC_PKT_PAYLOAD); 450 if (p == msg) 451 lp->env |= LDC_FRAG_START; 452 if (len <= LDC_PKT_PAYLOAD) 453 lp->env |= LDC_FRAG_STOP; 454 lp->seqid = lc->lc_tx_seqid++; 455 bcopy(p, &lp->major, uimin(len, LDC_PKT_PAYLOAD)); 456 457 tx_tail += sizeof(*lp); 458 tx_tail &= ((lc->lc_txq->lq_nentries * sizeof(*lp)) - 1); 459 err = hv_ldc_tx_set_qtail(lc->lc_id, tx_tail); 460 if (err != H_EOK) { 461 printf("%s: hv_ldc_tx_set_qtail: %d\n", __func__, err); 462 mutex_exit(&lc->lc_txq->lq_mtx); 463 return (EIO); 464 } 465 p += uimin(len, LDC_PKT_PAYLOAD); 466 len -= uimin(len, LDC_PKT_PAYLOAD); 467 } 468 469 mutex_exit(&lc->lc_txq->lq_mtx); 470 return (0); 471 } 472 473 void 474 ldc_reset(struct ldc_conn *lc) 475 { 476 int err; 477 vaddr_t va; 478 paddr_t pa; 479 480 DPRINTF(("Resetting connection\n")); 481 482 mutex_enter(&lc->lc_txq->lq_mtx); 483 484 #if OPENBSD_BUSDMA 485 err = hv_ldc_tx_qconf(lc->lc_id, 486 lc->lc_txq->lq_map->dm_segs[0].ds_addr, lc->lc_txq->lq_nentries); 487 #else 488 va = lc->lc_txq->lq_va; 489 pa = 0; 490 if (pmap_extract(pmap_kernel(), va, &pa) == FALSE) 491 panic("pmap_extract failed %lx\n", va); 492 err = hv_ldc_tx_qconf(lc->lc_id, pa, lc->lc_txq->lq_nentries); 493 #endif 494 if (err != H_EOK) 495 printf("%s: hv_ldc_tx_qconf %d\n", __func__, err); 496 497 #if OPENBSD_BUSDMA 498 err = hv_ldc_rx_qconf(lc->lc_id, 499 lc->lc_rxq->lq_map->dm_segs[0].ds_addr, lc->lc_rxq->lq_nentries); 500 #else 501 va = lc->lc_rxq->lq_va; 502 pa = 0; 503 if (pmap_extract(pmap_kernel(), va, &pa) == FALSE) 504 panic("pmap_extract failed %lx\n", va); 505 err = hv_ldc_tx_qconf(lc->lc_id, pa, lc->lc_rxq->lq_nentries); 506 #endif 507 if (err != H_EOK) 508 printf("%s: hv_ldc_rx_qconf %d\n", __func__, err); 509 510 lc->lc_tx_seqid = 0; 511 lc->lc_state = 0; 512 lc->lc_tx_state = lc->lc_rx_state = LDC_CHANNEL_DOWN; 513 mutex_exit(&lc->lc_txq->lq_mtx); 514 515 lc->lc_reset(lc); 516 } 517 #if OPENBSD_BUSDMA 518 struct ldc_queue * 519 ldc_queue_alloc(bus_dma_tag_t t, int nentries) 520 #else 521 struct ldc_queue * 522 ldc_queue_alloc(int nentries) 523 #endif 524 { 525 struct ldc_queue *lq; 526 bus_size_t size; 527 vaddr_t va = 0; 528 #if OPENBSD_BUSDMA 529 int nsegs; 530 #endif 531 532 lq = kmem_zalloc(sizeof(struct ldc_queue), KM_SLEEP); 533 534 mutex_init(&lq->lq_mtx, MUTEX_DEFAULT, IPL_TTY); 535 536 size = roundup(nentries * sizeof(struct ldc_pkt), PAGE_SIZE); 537 #if OPENBSD_BUSDMA 538 if (bus_dmamap_create(t, size, 1, size, 0, 539 BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &lq->lq_map) != 0) 540 return (NULL); 541 542 if (bus_dmamem_alloc(t, size, PAGE_SIZE, 0, &lq->lq_seg, 1, 543 &nsegs, BUS_DMA_NOWAIT) != 0) 544 goto destroy; 545 546 if (bus_dmamem_map(t, &lq->lq_seg, 1, size, (void *)&va, 547 BUS_DMA_NOWAIT) != 0) 548 goto free; 549 550 if (bus_dmamap_load(t, lq->lq_map, (void*)va, size, NULL, 551 BUS_DMA_NOWAIT) != 0) 552 goto unmap; 553 #else 554 va = (vaddr_t)kmem_zalloc(size, KM_SLEEP); 555 #endif 556 lq->lq_va = (vaddr_t)va; 557 lq->lq_nentries = nentries; 558 return (lq); 559 #if OPENBSD_BUSDMA 560 unmap: 561 bus_dmamem_unmap(t, (void*)va, size); 562 free: 563 bus_dmamem_free(t, &lq->lq_seg, 1); 564 destroy: 565 bus_dmamap_destroy(t, lq->lq_map); 566 #endif 567 return (NULL); 568 } 569 570 void 571 #if OPENBSD_BUSDMA 572 ldc_queue_free(bus_dma_tag_t t, struct ldc_queue *lq) 573 #else 574 ldc_queue_free(struct ldc_queue *lq) 575 #endif 576 { 577 bus_size_t size; 578 579 size = roundup(lq->lq_nentries * sizeof(struct ldc_pkt), PAGE_SIZE); 580 581 #if OPENBSD_BUSDMA 582 bus_dmamap_unload(t, lq->lq_map); 583 bus_dmamem_unmap(t, &lq->lq_va, size); 584 bus_dmamem_free(t, &lq->lq_seg, 1); 585 bus_dmamap_destroy(t, lq->lq_map); 586 #else 587 kmem_free((void *)lq->lq_va, size); 588 #endif 589 kmem_free(lq, size); 590 } 591 592 #if OPENBSD_BUSDMA 593 struct ldc_map * 594 ldc_map_alloc(bus_dma_tag_t t, int nentries) 595 #else 596 struct ldc_map * 597 ldc_map_alloc(int nentries) 598 #endif 599 { 600 struct ldc_map *lm; 601 bus_size_t size; 602 vaddr_t va = 0; 603 604 #if OPENBSD_BUSDMA 605 int nsegs; 606 #endif 607 lm = kmem_zalloc(sizeof(struct ldc_map), KM_SLEEP); 608 size = roundup(nentries * sizeof(struct ldc_map_slot), PAGE_SIZE); 609 610 #if OPENBSD_BUSDMA 611 if (bus_dmamap_create(t, size, 1, size, 0, 612 BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &lm->lm_map) != 0) { 613 DPRINTF(("ldc_map_alloc() - bus_dmamap_create() failed\n")); 614 return (NULL); 615 } 616 617 if (bus_dmamem_alloc(t, size, PAGE_SIZE, 0, &lm->lm_seg, 1, 618 &nsegs, BUS_DMA_NOWAIT) != 0) { 619 DPRINTF(("ldc_map_alloc() - bus_dmamem_alloc() failed\n")); 620 goto destroy; 621 } 622 623 if (bus_dmamem_map(t, &lm->lm_seg, 1, size, (void *)&va, 624 BUS_DMA_NOWAIT) != 0) { 625 DPRINTF(("ldc_map_alloc() - bus_dmamem_map() failed\n")); 626 goto free; 627 } 628 if (bus_dmamap_load(t, lm->lm_map, (void*)va, size, NULL, 629 BUS_DMA_NOWAIT) != 0) { 630 DPRINTF(("ldc_map_alloc() - bus_dmamap_load() failed\n")); 631 goto unmap; 632 } 633 #else 634 va = (vaddr_t)kmem_zalloc(size, KM_SLEEP); 635 #endif 636 lm->lm_slot = (struct ldc_map_slot *)va; 637 lm->lm_nentries = nentries; 638 bzero(lm->lm_slot, nentries * sizeof(struct ldc_map_slot)); 639 return (lm); 640 641 #if OPENBSD_BUSDMA 642 unmap: 643 bus_dmamem_unmap(t, (void*)va, size); 644 free: 645 bus_dmamem_free(t, &lm->lm_seg, 1); 646 destroy: 647 bus_dmamap_destroy(t, lm->lm_map); 648 #endif 649 return (NULL); 650 } 651 652 #if OPENBSD_BUSDMA 653 void 654 ldc_map_free(bus_dma_tag_t t, struct ldc_map *lm) 655 #else 656 void 657 ldc_map_free(struct ldc_map *lm) 658 #endif 659 { 660 bus_size_t size; 661 662 size = lm->lm_nentries * sizeof(struct ldc_map_slot); 663 size = roundup(size, PAGE_SIZE); 664 665 #if OPENBSD_BUSDMA 666 bus_dmamap_unload(t, lm->lm_map); 667 bus_dmamem_unmap(t, lm->lm_slot, size); 668 bus_dmamem_free(t, &lm->lm_seg, 1); 669 bus_dmamap_destroy(t, lm->lm_map); 670 #else 671 kmem_free(lm->lm_slot, size); 672 #endif 673 kmem_free(lm, size); 674 } 675