xref: /netbsd-src/sys/arch/sparc64/dev/ldc.c (revision 181254a7b1bdde6873432bffef2d2decc4b5c22f)
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