1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2026 Dmitry Salychev 5 * Copyright (c) 2026 Bjoern A. Zeeb 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29 #include <sys/cdefs.h> 30 31 #include <sys/param.h> 32 #include <sys/errno.h> 33 #include <sys/endian.h> 34 35 #include <vm/vm.h> 36 #include <vm/pmap.h> 37 38 #include <machine/vmparam.h> 39 40 #include "dpaa2_types.h" 41 #include "dpaa2_frame.h" 42 #include "dpaa2_buf.h" 43 #include "dpaa2_swp.h" 44 45 /** 46 * @brief Build a DPAA2 frame descriptor. 47 */ 48 int 49 dpaa2_fd_build(device_t dev, const uint16_t tx_data_off, struct dpaa2_buf *buf, 50 bus_dma_segment_t *segs, const int nsegs, struct dpaa2_fd *fd) 51 { 52 struct dpaa2_buf *sgt = buf->sgt; 53 struct dpaa2_sg_entry *sge; 54 struct dpaa2_swa *swa; 55 int i, error; 56 57 if (buf == NULL || segs == NULL || nsegs == 0 || fd == NULL) 58 return (EINVAL); 59 60 KASSERT(nsegs <= DPAA2_TX_SEGLIMIT, ("%s: too many segments", __func__)); 61 KASSERT(buf->opt != NULL, ("%s: no Tx ring?", __func__)); 62 KASSERT(sgt != NULL, ("%s: no S/G table?", __func__)); 63 KASSERT(sgt->vaddr != NULL, ("%s: no S/G vaddr?", __func__)); 64 65 memset(fd, 0, sizeof(*fd)); 66 67 /* Populate and map S/G table */ 68 if (__predict_true(nsegs <= DPAA2_TX_SEGLIMIT)) { 69 sge = (struct dpaa2_sg_entry *)sgt->vaddr + tx_data_off; 70 for (i = 0; i < nsegs; i++) { 71 sge[i].addr = (uint64_t)segs[i].ds_addr; 72 sge[i].len = (uint32_t)segs[i].ds_len; 73 sge[i].offset_fmt = 0u; 74 } 75 sge[i-1].offset_fmt |= 0x8000u; /* set final entry flag */ 76 77 KASSERT(sgt->paddr == 0, ("%s: paddr(%#jx) != 0", __func__, 78 sgt->paddr)); 79 80 error = bus_dmamap_load(sgt->dmat, sgt->dmap, sgt->vaddr, 81 DPAA2_TX_SGT_SZ, dpaa2_dmamap_oneseg_cb, &sgt->paddr, 82 BUS_DMA_NOWAIT); 83 if (__predict_false(error != 0)) { 84 device_printf(dev, "%s: bus_dmamap_load() failed: " 85 "error=%d\n", __func__, error); 86 return (error); 87 } 88 89 buf->paddr = sgt->paddr; 90 buf->vaddr = sgt->vaddr; 91 } else { 92 return (EINVAL); 93 } 94 95 swa = (struct dpaa2_swa *)sgt->vaddr; 96 swa->magic = DPAA2_MAGIC; 97 swa->buf = buf; 98 99 fd->addr = buf->paddr; 100 fd->data_length = (uint32_t)buf->m->m_pkthdr.len; 101 fd->bpid_ivp_bmt = 0; 102 fd->offset_fmt_sl = 0x2000u | tx_data_off; 103 fd->ctrl = (0x4u & DPAA2_FD_PTAC_MASK) << DPAA2_FD_PTAC_SHIFT; 104 105 return (0); 106 } 107 108 int 109 dpaa2_fd_err(struct dpaa2_fd *fd) 110 { 111 return ((fd->ctrl >> DPAA2_FD_ERR_SHIFT) & DPAA2_FD_ERR_MASK); 112 } 113 114 uint32_t 115 dpaa2_fd_data_len(struct dpaa2_fd *fd) 116 { 117 if (dpaa2_fd_short_len(fd)) { 118 return (fd->data_length & DPAA2_FD_LEN_MASK); 119 } 120 return (fd->data_length); 121 } 122 123 int 124 dpaa2_fd_format(struct dpaa2_fd *fd) 125 { 126 return ((enum dpaa2_fd_format)((fd->offset_fmt_sl >> 127 DPAA2_FD_FMT_SHIFT) & DPAA2_FD_FMT_MASK)); 128 } 129 130 bool 131 dpaa2_fd_short_len(struct dpaa2_fd *fd) 132 { 133 return (((fd->offset_fmt_sl >> DPAA2_FD_SL_SHIFT) 134 & DPAA2_FD_SL_MASK) == 1); 135 } 136 137 int 138 dpaa2_fd_offset(struct dpaa2_fd *fd) 139 { 140 return (fd->offset_fmt_sl & DPAA2_FD_OFFSET_MASK); 141 } 142 143 uint32_t 144 dpaa2_fd_get_frc(struct dpaa2_fd *fd) 145 { 146 /* TODO: Convert endiannes in the other functions as well. */ 147 return (le32toh(fd->frame_ctx)); 148 } 149 150 #ifdef _not_yet_ 151 void 152 dpaa2_fd_set_frc(struct dpaa2_fd *fd, uint32_t frc) 153 { 154 /* TODO: Convert endiannes in the other functions as well. */ 155 fd->frame_ctx = htole32(frc); 156 } 157 #endif 158 159 int 160 dpaa2_fa_get_swa(struct dpaa2_fd *fd, struct dpaa2_swa **swa) 161 { 162 if (__predict_false(fd == NULL || swa == NULL)) 163 return (EINVAL); 164 165 if (((fd->ctrl >> DPAA2_FD_PTAC_SHIFT) & DPAA2_FD_PTAC_PTA_MASK) == 0u) { 166 *swa = NULL; 167 return (ENOENT); 168 } 169 170 *swa = (struct dpaa2_swa *)PHYS_TO_DMAP((bus_addr_t)fd->addr); 171 172 return (0); 173 } 174 175 int 176 dpaa2_fa_get_hwa(struct dpaa2_fd *fd, struct dpaa2_hwa **hwa) 177 { 178 uint8_t *buf; 179 uint32_t hwo; /* HW annotation offset */ 180 181 if (__predict_false(fd == NULL || hwa == NULL)) 182 return (EINVAL); 183 184 /* 185 * As soon as the ASAL is in the 64-byte units, we don't need to 186 * calculate the exact length, but make sure that it isn't 0. 187 */ 188 if (((fd->ctrl >> DPAA2_FD_ASAL_SHIFT) & DPAA2_FD_ASAL_MASK) == 0u) { 189 *hwa = NULL; 190 return (ENOENT); 191 } 192 193 buf = (uint8_t *)PHYS_TO_DMAP((bus_addr_t)fd->addr); 194 hwo = ((fd->ctrl >> DPAA2_FD_PTAC_SHIFT) & DPAA2_FD_PTAC_PTA_MASK) > 0u 195 ? DPAA2_FA_SWA_SIZE : 0u; 196 *hwa = (struct dpaa2_hwa *)(buf + hwo); 197 198 return (0); 199 } 200 201 int 202 dpaa2_fa_get_fas(struct dpaa2_fd *fd, struct dpaa2_hwa_fas *fas) 203 { 204 struct dpaa2_hwa *hwa; 205 struct dpaa2_hwa_fas *fasp; 206 int rc; 207 208 if (__predict_false(fd == NULL || fas == NULL)) 209 return (EINVAL); 210 211 rc = dpaa2_fa_get_hwa(fd, &hwa); 212 if (__predict_false(rc != 0)) 213 return (rc); 214 215 fasp = (struct dpaa2_hwa_fas *)&hwa->fas; 216 *fas = *fasp; 217 218 return (rc); 219 } 220 221 #ifdef _not_yet_ 222 int 223 dpaa2_fa_set_fas(struct dpaa2_fd *fd, struct dpaa2_hwa_fas *fas) 224 { 225 struct dpaa2_hwa *hwa; 226 uint64_t *valp; 227 int rc; 228 229 if (__predict_false(fd == NULL || fas == NULL)) 230 return (EINVAL); 231 232 rc = dpaa2_fa_get_hwa(fd, &hwa); 233 if (__predict_false(rc != 0)) 234 return (rc); 235 236 valp = (uint64_t *)fas; 237 hwa->fas = *valp; 238 239 return (rc); 240 } 241 #endif 242