xref: /freebsd/sys/dev/dpaa2/dpaa2_frame.c (revision 5254e16213ff1bb136ef24e0b0fe30625ac53563)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Copyright © 2026 Dmitry Salychev
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  */
27 
28 #include <sys/cdefs.h>
29 
30 #include <sys/param.h>
31 #include <sys/errno.h>
32 
33 #include <vm/vm.h>
34 #include <vm/pmap.h>
35 
36 #include <machine/vmparam.h>
37 
38 #include "dpaa2_types.h"
39 #include "dpaa2_frame.h"
40 #include "dpaa2_buf.h"
41 #include "dpaa2_swp.h"
42 
43 /**
44  * @brief Build a DPAA2 frame descriptor.
45  */
46 int
47 dpaa2_fd_build(device_t dev, const uint16_t tx_data_off, struct dpaa2_buf *buf,
48     bus_dma_segment_t *segs, const int nsegs, struct dpaa2_fd *fd)
49 {
50 	struct dpaa2_buf *sgt = buf->sgt;
51 	struct dpaa2_sg_entry *sge;
52 	struct dpaa2_swa *swa;
53 	int i, error;
54 
55 	if (buf == NULL || segs == NULL || nsegs == 0 || fd == NULL)
56 		return (EINVAL);
57 
58 	KASSERT(nsegs <= DPAA2_TX_SEGLIMIT, ("%s: too many segments", __func__));
59 	KASSERT(buf->opt != NULL, ("%s: no Tx ring?", __func__));
60 	KASSERT(sgt != NULL, ("%s: no S/G table?", __func__));
61 	KASSERT(sgt->vaddr != NULL, ("%s: no S/G vaddr?", __func__));
62 
63 	memset(fd, 0, sizeof(*fd));
64 
65 	/* Populate and map S/G table */
66 	if (__predict_true(nsegs <= DPAA2_TX_SEGLIMIT)) {
67 		sge = (struct dpaa2_sg_entry *)sgt->vaddr + tx_data_off;
68 		for (i = 0; i < nsegs; i++) {
69 			sge[i].addr = (uint64_t)segs[i].ds_addr;
70 			sge[i].len = (uint32_t)segs[i].ds_len;
71 			sge[i].offset_fmt = 0u;
72 		}
73 		sge[i-1].offset_fmt |= 0x8000u; /* set final entry flag */
74 
75 		KASSERT(sgt->paddr == 0, ("%s: paddr(%#jx) != 0", __func__,
76 		    sgt->paddr));
77 
78 		error = bus_dmamap_load(sgt->dmat, sgt->dmap, sgt->vaddr,
79 		    DPAA2_TX_SGT_SZ, dpaa2_dmamap_oneseg_cb, &sgt->paddr,
80 		    BUS_DMA_NOWAIT);
81 		if (__predict_false(error != 0)) {
82 			device_printf(dev, "%s: bus_dmamap_load() failed: "
83 			    "error=%d\n", __func__, error);
84 			return (error);
85 		}
86 
87 		buf->paddr = sgt->paddr;
88 		buf->vaddr = sgt->vaddr;
89 	} else {
90 		return (EINVAL);
91 	}
92 
93 	swa = (struct dpaa2_swa *)sgt->vaddr;
94 	swa->magic = DPAA2_MAGIC;
95 	swa->buf = buf;
96 
97 	fd->addr = buf->paddr;
98 	fd->data_length = (uint32_t)buf->m->m_pkthdr.len;
99 	fd->bpid_ivp_bmt = 0;
100 	fd->offset_fmt_sl = 0x2000u | tx_data_off;
101 	fd->ctrl = (0x4u & DPAA2_FD_PTAC_MASK) << DPAA2_FD_PTAC_SHIFT;
102 
103 	return (0);
104 }
105 
106 int
107 dpaa2_fd_err(struct dpaa2_fd *fd)
108 {
109 	return ((fd->ctrl >> DPAA2_FD_ERR_SHIFT) & DPAA2_FD_ERR_MASK);
110 }
111 
112 uint32_t
113 dpaa2_fd_data_len(struct dpaa2_fd *fd)
114 {
115 	if (dpaa2_fd_short_len(fd)) {
116 		return (fd->data_length & DPAA2_FD_LEN_MASK);
117 	}
118 	return (fd->data_length);
119 }
120 
121 int
122 dpaa2_fd_format(struct dpaa2_fd *fd)
123 {
124 	return ((enum dpaa2_fd_format)((fd->offset_fmt_sl >>
125 	    DPAA2_FD_FMT_SHIFT) & DPAA2_FD_FMT_MASK));
126 }
127 
128 bool
129 dpaa2_fd_short_len(struct dpaa2_fd *fd)
130 {
131 	return (((fd->offset_fmt_sl >> DPAA2_FD_SL_SHIFT)
132 	    & DPAA2_FD_SL_MASK) == 1);
133 }
134 
135 int
136 dpaa2_fd_offset(struct dpaa2_fd *fd)
137 {
138 	return (fd->offset_fmt_sl & DPAA2_FD_OFFSET_MASK);
139 }
140 
141 int
142 dpaa2_fa_get_swa(struct dpaa2_fd *fd, struct dpaa2_swa **swa)
143 {
144 	int rc;
145 
146 	if (fd == NULL || swa == NULL)
147 		return (EINVAL);
148 
149 	if (((fd->ctrl >> DPAA2_FD_PTAC_SHIFT) & DPAA2_FD_PTAC_MASK) >= 0x4u) {
150 		*swa = (struct dpaa2_swa *)PHYS_TO_DMAP((bus_addr_t)fd->addr);
151 		rc = 0;
152 	} else {
153 		*swa = NULL;
154 		rc = ENOENT;
155 	}
156 
157 	return (rc);
158 }
159 
160 int
161 dpaa2_fa_get_hwa(struct dpaa2_fd *fd, struct dpaa2_hwa **hwa)
162 {
163 	/* TODO: To be implemented next. */
164 	return (ENOENT);
165 }
166