1 /* $NetBSD: ldc.c,v 1.1 2016/08/19 19:02:07 palle 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 *)(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 *)(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 *)(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 *)(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 *)(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 *)(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 = min(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, min(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 += min(len, LDC_PKT_PAYLOAD); 466 len -= min(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_NOSLEEP); 533 if (lq == NULL) 534 return NULL; 535 536 mutex_init(&lq->lq_mtx, MUTEX_DEFAULT, IPL_TTY); 537 538 size = roundup(nentries * sizeof(struct ldc_pkt), PAGE_SIZE); 539 #if OPENBSD_BUSDMA 540 if (bus_dmamap_create(t, size, 1, size, 0, 541 BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &lq->lq_map) != 0) 542 return (NULL); 543 544 if (bus_dmamem_alloc(t, size, PAGE_SIZE, 0, &lq->lq_seg, 1, 545 &nsegs, BUS_DMA_NOWAIT) != 0) 546 goto destroy; 547 548 if (bus_dmamem_map(t, &lq->lq_seg, 1, size, (void *)&va, 549 BUS_DMA_NOWAIT) != 0) 550 goto free; 551 552 if (bus_dmamap_load(t, lq->lq_map, (void*)va, size, NULL, 553 BUS_DMA_NOWAIT) != 0) 554 goto unmap; 555 #else 556 va = (vaddr_t)kmem_zalloc(size, KM_NOSLEEP); 557 #endif 558 lq->lq_va = (vaddr_t)va; 559 lq->lq_nentries = nentries; 560 return (lq); 561 #if OPENBSD_BUSDMA 562 unmap: 563 bus_dmamem_unmap(t, (void*)va, size); 564 free: 565 bus_dmamem_free(t, &lq->lq_seg, 1); 566 destroy: 567 bus_dmamap_destroy(t, lq->lq_map); 568 #endif 569 return (NULL); 570 } 571 572 void 573 #if OPENBSD_BUSDMA 574 ldc_queue_free(bus_dma_tag_t t, struct ldc_queue *lq) 575 #else 576 ldc_queue_free(struct ldc_queue *lq) 577 #endif 578 { 579 bus_size_t size; 580 581 size = roundup(lq->lq_nentries * sizeof(struct ldc_pkt), PAGE_SIZE); 582 583 #if OPENBSD_BUSDMA 584 bus_dmamap_unload(t, lq->lq_map); 585 bus_dmamem_unmap(t, &lq->lq_va, size); 586 bus_dmamem_free(t, &lq->lq_seg, 1); 587 bus_dmamap_destroy(t, lq->lq_map); 588 #else 589 kmem_free((void *)lq->lq_va, size); 590 #endif 591 kmem_free(lq, size); 592 } 593 594 #if OPENBSD_BUSDMA 595 struct ldc_map * 596 ldc_map_alloc(bus_dma_tag_t t, int nentries) 597 #else 598 struct ldc_map * 599 ldc_map_alloc(int nentries) 600 #endif 601 { 602 struct ldc_map *lm; 603 bus_size_t size; 604 vaddr_t va = 0; 605 606 #if OPENBSD_BUSDMA 607 int nsegs; 608 #endif 609 lm = kmem_zalloc(sizeof(struct ldc_map), KM_NOSLEEP); 610 if (lm == NULL) 611 return NULL; 612 613 size = roundup(nentries * sizeof(struct ldc_map_slot), PAGE_SIZE); 614 615 #if OPENBSD_BUSDMA 616 if (bus_dmamap_create(t, size, 1, size, 0, 617 BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &lm->lm_map) != 0) { 618 DPRINTF(("ldc_map_alloc() - bus_dmamap_create() failed\n")); 619 return (NULL); 620 } 621 622 if (bus_dmamem_alloc(t, size, PAGE_SIZE, 0, &lm->lm_seg, 1, 623 &nsegs, BUS_DMA_NOWAIT) != 0) { 624 DPRINTF(("ldc_map_alloc() - bus_dmamem_alloc() failed\n")); 625 goto destroy; 626 } 627 628 if (bus_dmamem_map(t, &lm->lm_seg, 1, size, (void *)&va, 629 BUS_DMA_NOWAIT) != 0) { 630 DPRINTF(("ldc_map_alloc() - bus_dmamem_map() failed\n")); 631 goto free; 632 } 633 if (bus_dmamap_load(t, lm->lm_map, (void*)va, size, NULL, 634 BUS_DMA_NOWAIT) != 0) { 635 DPRINTF(("ldc_map_alloc() - bus_dmamap_load() failed\n")); 636 goto unmap; 637 } 638 #else 639 va = (vaddr_t)kmem_zalloc(size, KM_NOSLEEP); 640 #endif 641 lm->lm_slot = (struct ldc_map_slot *)va; 642 lm->lm_nentries = nentries; 643 bzero(lm->lm_slot, nentries * sizeof(struct ldc_map_slot)); 644 return (lm); 645 646 #if OPENBSD_BUSDMA 647 unmap: 648 bus_dmamem_unmap(t, (void*)va, size); 649 free: 650 bus_dmamem_free(t, &lm->lm_seg, 1); 651 destroy: 652 bus_dmamap_destroy(t, lm->lm_map); 653 #endif 654 return (NULL); 655 } 656 657 #if OPENBSD_BUSDMA 658 void 659 ldc_map_free(bus_dma_tag_t t, struct ldc_map *lm) 660 #else 661 void 662 ldc_map_free(struct ldc_map *lm) 663 #endif 664 { 665 bus_size_t size; 666 667 size = lm->lm_nentries * sizeof(struct ldc_map_slot); 668 size = roundup(size, PAGE_SIZE); 669 670 #if OPENBSD_BUSDMA 671 bus_dmamap_unload(t, lm->lm_map); 672 bus_dmamem_unmap(t, lm->lm_slot, size); 673 bus_dmamem_free(t, &lm->lm_seg, 1); 674 bus_dmamap_destroy(t, lm->lm_map); 675 #else 676 kmem_free(lm->lm_slot, size); 677 #endif 678 kmem_free(lm, size); 679 } 680