Home | History | Annotate | Line # | Download | only in dev
ldc.c revision 1.2
      1 /*	$NetBSD: ldc.c,v 1.2 2016/08/20 18:21:18 nakayama 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 = 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