1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
3 *
4 * Copyright © 2021-2023 Dmitry Salychev
5 * Copyright © 2022 Mathew McBride
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 * The DPAA2 Network Interface (DPNI) driver.
32 *
33 * The DPNI object is a network interface that is configurable to support a wide
34 * range of features from a very basic Ethernet interface up to a
35 * high-functioning network interface. The DPNI supports features that are
36 * expected by standard network stacks, from basic features to offloads.
37 *
38 * DPNIs work with Ethernet traffic, starting with the L2 header. Additional
39 * functions are provided for standard network protocols (L2, L3, L4, etc.).
40 */
41
42 #include <sys/param.h>
43 #include <sys/systm.h>
44 #include <sys/kernel.h>
45 #include <sys/bus.h>
46 #include <sys/rman.h>
47 #include <sys/module.h>
48 #include <sys/malloc.h>
49 #include <sys/mutex.h>
50 #include <sys/socket.h>
51 #include <sys/sockio.h>
52 #include <sys/sysctl.h>
53 #include <sys/mbuf.h>
54 #include <sys/taskqueue.h>
55 #include <sys/sysctl.h>
56 #include <sys/buf_ring.h>
57 #include <sys/smp.h>
58 #include <sys/proc.h>
59
60 #include <vm/vm.h>
61 #include <vm/pmap.h>
62
63 #include <machine/bus.h>
64 #include <machine/resource.h>
65 #include <machine/atomic.h>
66 #include <machine/vmparam.h>
67
68 #include <net/ethernet.h>
69 #include <net/bpf.h>
70 #include <net/if.h>
71 #include <net/if_dl.h>
72 #include <net/if_media.h>
73 #include <net/if_types.h>
74 #include <net/if_var.h>
75
76 #include <dev/pci/pcivar.h>
77 #include <dev/mii/mii.h>
78 #include <dev/mii/miivar.h>
79 #include <dev/mdio/mdio.h>
80
81 #include "opt_acpi.h"
82 #include "opt_platform.h"
83
84 #include "pcib_if.h"
85 #include "pci_if.h"
86 #include "miibus_if.h"
87 #include "memac_mdio_if.h"
88
89 #include "dpaa2_types.h"
90 #include "dpaa2_mc.h"
91 #include "dpaa2_mc_if.h"
92 #include "dpaa2_mcp.h"
93 #include "dpaa2_swp.h"
94 #include "dpaa2_swp_if.h"
95 #include "dpaa2_cmd_if.h"
96 #include "dpaa2_ni.h"
97 #include "dpaa2_channel.h"
98 #include "dpaa2_buf.h"
99
100 #define BIT(x) (1ul << (x))
101 #define WRIOP_VERSION(x, y, z) ((x) << 10 | (y) << 5 | (z) << 0)
102 #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
103
104 /* Frame Dequeue Response status bits. */
105 #define IS_NULL_RESPONSE(stat) ((((stat) >> 4) & 1) == 0)
106
107 #define ALIGN_UP(x, y) roundup2((x), (y))
108 #define ALIGN_DOWN(x, y) rounddown2((x), (y))
109 #define CACHE_LINE_ALIGN(x) ALIGN_UP((x), CACHE_LINE_SIZE)
110
111 #define DPNI_LOCK(__sc) do { \
112 mtx_assert(&(__sc)->lock, MA_NOTOWNED); \
113 mtx_lock(&(__sc)->lock); \
114 } while (0)
115 #define DPNI_UNLOCK(__sc) do { \
116 mtx_assert(&(__sc)->lock, MA_OWNED); \
117 mtx_unlock(&(__sc)->lock); \
118 } while (0)
119 #define DPNI_LOCK_ASSERT(__sc) do { \
120 mtx_assert(&(__sc)->lock, MA_OWNED); \
121 } while (0)
122
123 #define DPAA2_TX_RING(sc, chan, tc) \
124 (&(sc)->channels[(chan)]->txc_queue.tx_rings[(tc)])
125
126 MALLOC_DEFINE(M_DPAA2_TXB, "dpaa2_txb", "DPAA2 DMA-mapped buffer (Tx)");
127
128 /*
129 * How many times channel cleanup routine will be repeated if the RX or TX
130 * budget was depleted.
131 */
132 #define DPAA2_CLEAN_BUDGET 64 /* sysctl(9)? */
133 /* TX/RX budget for the channel cleanup task */
134 #define DPAA2_TX_BUDGET 128 /* sysctl(9)? */
135 #define DPAA2_RX_BUDGET 256 /* sysctl(9)? */
136
137 #define DPNI_IRQ_INDEX 0 /* Index of the only DPNI IRQ. */
138 #define DPNI_IRQ_LINK_CHANGED 1 /* Link state changed */
139 #define DPNI_IRQ_EP_CHANGED 2 /* DPAA2 endpoint dis/connected */
140
141 /* Default maximum frame length. */
142 #define DPAA2_ETH_MFL (ETHER_MAX_LEN - ETHER_CRC_LEN)
143
144 /* Minimally supported version of the DPNI API. */
145 #define DPNI_VER_MAJOR 7
146 #define DPNI_VER_MINOR 0
147
148 /* Rx/Tx buffers configuration. */
149 #define BUF_ALIGN_V1 256 /* WRIOP v1.0.0 limitation */
150 #define BUF_ALIGN 64
151 #define BUF_SWA_SIZE 64 /* SW annotation size */
152 #define BUF_RX_HWA_SIZE 64 /* HW annotation size */
153 #define BUF_TX_HWA_SIZE 128 /* HW annotation size */
154
155 #define DPAA2_RX_BUFRING_SZ (4096u)
156 #define DPAA2_RXE_BUFRING_SZ (1024u)
157 #define DPAA2_TXC_BUFRING_SZ (4096u)
158 #define DPAA2_TX_SEGLIMIT (16u) /* arbitrary number */
159 #define DPAA2_TX_SEG_SZ (PAGE_SIZE)
160 #define DPAA2_TX_SEGS_MAXSZ (DPAA2_TX_SEGLIMIT * DPAA2_TX_SEG_SZ)
161 #define DPAA2_TX_SGT_SZ (PAGE_SIZE) /* bytes */
162
163 /* Size of a buffer to keep a QoS table key configuration. */
164 #define ETH_QOS_KCFG_BUF_SIZE (PAGE_SIZE)
165
166 /* Required by struct dpni_rx_tc_dist_cfg::key_cfg_iova */
167 #define DPAA2_CLASSIFIER_DMA_SIZE (PAGE_SIZE)
168
169 /* Buffers layout options. */
170 #define BUF_LOPT_TIMESTAMP 0x1
171 #define BUF_LOPT_PARSER_RESULT 0x2
172 #define BUF_LOPT_FRAME_STATUS 0x4
173 #define BUF_LOPT_PRIV_DATA_SZ 0x8
174 #define BUF_LOPT_DATA_ALIGN 0x10
175 #define BUF_LOPT_DATA_HEAD_ROOM 0x20
176 #define BUF_LOPT_DATA_TAIL_ROOM 0x40
177
178 #define DPAA2_NI_BUF_ADDR_MASK (0x1FFFFFFFFFFFFul) /* 49-bit addresses max. */
179 #define DPAA2_NI_BUF_CHAN_MASK (0xFu)
180 #define DPAA2_NI_BUF_CHAN_SHIFT (60)
181 #define DPAA2_NI_BUF_IDX_MASK (0x7FFFu)
182 #define DPAA2_NI_BUF_IDX_SHIFT (49)
183 #define DPAA2_NI_TX_IDX_MASK (0x7u)
184 #define DPAA2_NI_TX_IDX_SHIFT (57)
185 #define DPAA2_NI_TXBUF_IDX_MASK (0xFFu)
186 #define DPAA2_NI_TXBUF_IDX_SHIFT (49)
187
188 #define DPAA2_NI_FD_FMT_MASK (0x3u)
189 #define DPAA2_NI_FD_FMT_SHIFT (12)
190 #define DPAA2_NI_FD_ERR_MASK (0xFFu)
191 #define DPAA2_NI_FD_ERR_SHIFT (0)
192 #define DPAA2_NI_FD_SL_MASK (0x1u)
193 #define DPAA2_NI_FD_SL_SHIFT (14)
194 #define DPAA2_NI_FD_LEN_MASK (0x3FFFFu)
195 #define DPAA2_NI_FD_OFFSET_MASK (0x0FFFu)
196
197 /* Enables TCAM for Flow Steering and QoS look-ups. */
198 #define DPNI_OPT_HAS_KEY_MASKING 0x10
199
200 /* Unique IDs for the supported Rx classification header fields. */
201 #define DPAA2_ETH_DIST_ETHDST BIT(0)
202 #define DPAA2_ETH_DIST_ETHSRC BIT(1)
203 #define DPAA2_ETH_DIST_ETHTYPE BIT(2)
204 #define DPAA2_ETH_DIST_VLAN BIT(3)
205 #define DPAA2_ETH_DIST_IPSRC BIT(4)
206 #define DPAA2_ETH_DIST_IPDST BIT(5)
207 #define DPAA2_ETH_DIST_IPPROTO BIT(6)
208 #define DPAA2_ETH_DIST_L4SRC BIT(7)
209 #define DPAA2_ETH_DIST_L4DST BIT(8)
210 #define DPAA2_ETH_DIST_ALL (~0ULL)
211
212 /* L3-L4 network traffic flow hash options. */
213 #define RXH_L2DA (1 << 1)
214 #define RXH_VLAN (1 << 2)
215 #define RXH_L3_PROTO (1 << 3)
216 #define RXH_IP_SRC (1 << 4)
217 #define RXH_IP_DST (1 << 5)
218 #define RXH_L4_B_0_1 (1 << 6) /* src port in case of TCP/UDP/SCTP */
219 #define RXH_L4_B_2_3 (1 << 7) /* dst port in case of TCP/UDP/SCTP */
220 #define RXH_DISCARD (1 << 31)
221
222 /* Default Rx hash options, set during attaching. */
223 #define DPAA2_RXH_DEFAULT (RXH_IP_SRC | RXH_IP_DST | RXH_L4_B_0_1 | RXH_L4_B_2_3)
224
225 MALLOC_DEFINE(M_DPAA2_NI, "dpaa2_ni", "DPAA2 Network Interface");
226
227 /*
228 * DPAA2 Network Interface resource specification.
229 *
230 * NOTE: Don't forget to update macros in dpaa2_ni.h in case of any changes in
231 * the specification!
232 */
233 struct resource_spec dpaa2_ni_spec[] = {
234 /*
235 * DPMCP resources.
236 *
237 * NOTE: MC command portals (MCPs) are used to send commands to, and
238 * receive responses from, the MC firmware. One portal per DPNI.
239 */
240 { DPAA2_DEV_MCP, DPAA2_NI_MCP_RID(0), RF_ACTIVE | RF_SHAREABLE | RF_OPTIONAL },
241 /*
242 * DPIO resources (software portals).
243 *
244 * NOTE: One per running core. While DPIOs are the source of data
245 * availability interrupts, the DPCONs are used to identify the
246 * network interface that has produced ingress data to that core.
247 */
248 { DPAA2_DEV_IO, DPAA2_NI_IO_RID(0), RF_ACTIVE | RF_SHAREABLE },
249 { DPAA2_DEV_IO, DPAA2_NI_IO_RID(1), RF_ACTIVE | RF_SHAREABLE | RF_OPTIONAL },
250 { DPAA2_DEV_IO, DPAA2_NI_IO_RID(2), RF_ACTIVE | RF_SHAREABLE | RF_OPTIONAL },
251 { DPAA2_DEV_IO, DPAA2_NI_IO_RID(3), RF_ACTIVE | RF_SHAREABLE | RF_OPTIONAL },
252 { DPAA2_DEV_IO, DPAA2_NI_IO_RID(4), RF_ACTIVE | RF_SHAREABLE | RF_OPTIONAL },
253 { DPAA2_DEV_IO, DPAA2_NI_IO_RID(5), RF_ACTIVE | RF_SHAREABLE | RF_OPTIONAL },
254 { DPAA2_DEV_IO, DPAA2_NI_IO_RID(6), RF_ACTIVE | RF_SHAREABLE | RF_OPTIONAL },
255 { DPAA2_DEV_IO, DPAA2_NI_IO_RID(7), RF_ACTIVE | RF_SHAREABLE | RF_OPTIONAL },
256 { DPAA2_DEV_IO, DPAA2_NI_IO_RID(8), RF_ACTIVE | RF_SHAREABLE | RF_OPTIONAL },
257 { DPAA2_DEV_IO, DPAA2_NI_IO_RID(9), RF_ACTIVE | RF_SHAREABLE | RF_OPTIONAL },
258 { DPAA2_DEV_IO, DPAA2_NI_IO_RID(10), RF_ACTIVE | RF_SHAREABLE | RF_OPTIONAL },
259 { DPAA2_DEV_IO, DPAA2_NI_IO_RID(11), RF_ACTIVE | RF_SHAREABLE | RF_OPTIONAL },
260 { DPAA2_DEV_IO, DPAA2_NI_IO_RID(12), RF_ACTIVE | RF_SHAREABLE | RF_OPTIONAL },
261 { DPAA2_DEV_IO, DPAA2_NI_IO_RID(13), RF_ACTIVE | RF_SHAREABLE | RF_OPTIONAL },
262 { DPAA2_DEV_IO, DPAA2_NI_IO_RID(14), RF_ACTIVE | RF_SHAREABLE | RF_OPTIONAL },
263 { DPAA2_DEV_IO, DPAA2_NI_IO_RID(15), RF_ACTIVE | RF_SHAREABLE | RF_OPTIONAL },
264 /*
265 * DPBP resources (buffer pools).
266 *
267 * NOTE: One per network interface.
268 */
269 { DPAA2_DEV_BP, DPAA2_NI_BP_RID(0), RF_ACTIVE },
270 /*
271 * DPCON resources (channels).
272 *
273 * NOTE: One DPCON per core where Rx or Tx confirmation traffic to be
274 * distributed to.
275 * NOTE: Since it is necessary to distinguish between traffic from
276 * different network interfaces arriving on the same core, the
277 * DPCONs must be private to the DPNIs.
278 */
279 { DPAA2_DEV_CON, DPAA2_NI_CON_RID(0), RF_ACTIVE },
280 { DPAA2_DEV_CON, DPAA2_NI_CON_RID(1), RF_ACTIVE | RF_OPTIONAL },
281 { DPAA2_DEV_CON, DPAA2_NI_CON_RID(2), RF_ACTIVE | RF_OPTIONAL },
282 { DPAA2_DEV_CON, DPAA2_NI_CON_RID(3), RF_ACTIVE | RF_OPTIONAL },
283 { DPAA2_DEV_CON, DPAA2_NI_CON_RID(4), RF_ACTIVE | RF_OPTIONAL },
284 { DPAA2_DEV_CON, DPAA2_NI_CON_RID(5), RF_ACTIVE | RF_OPTIONAL },
285 { DPAA2_DEV_CON, DPAA2_NI_CON_RID(6), RF_ACTIVE | RF_OPTIONAL },
286 { DPAA2_DEV_CON, DPAA2_NI_CON_RID(7), RF_ACTIVE | RF_OPTIONAL },
287 { DPAA2_DEV_CON, DPAA2_NI_CON_RID(8), RF_ACTIVE | RF_OPTIONAL },
288 { DPAA2_DEV_CON, DPAA2_NI_CON_RID(9), RF_ACTIVE | RF_OPTIONAL },
289 { DPAA2_DEV_CON, DPAA2_NI_CON_RID(10), RF_ACTIVE | RF_OPTIONAL },
290 { DPAA2_DEV_CON, DPAA2_NI_CON_RID(11), RF_ACTIVE | RF_OPTIONAL },
291 { DPAA2_DEV_CON, DPAA2_NI_CON_RID(12), RF_ACTIVE | RF_OPTIONAL },
292 { DPAA2_DEV_CON, DPAA2_NI_CON_RID(13), RF_ACTIVE | RF_OPTIONAL },
293 { DPAA2_DEV_CON, DPAA2_NI_CON_RID(14), RF_ACTIVE | RF_OPTIONAL },
294 { DPAA2_DEV_CON, DPAA2_NI_CON_RID(15), RF_ACTIVE | RF_OPTIONAL },
295
296 RESOURCE_SPEC_END
297 };
298
299 /* Supported header fields for Rx hash distribution key */
300 static const struct dpaa2_eth_dist_fields dist_fields[] = {
301 {
302 /* L2 header */
303 .rxnfc_field = RXH_L2DA,
304 .cls_prot = NET_PROT_ETH,
305 .cls_field = NH_FLD_ETH_DA,
306 .id = DPAA2_ETH_DIST_ETHDST,
307 .size = 6,
308 }, {
309 .cls_prot = NET_PROT_ETH,
310 .cls_field = NH_FLD_ETH_SA,
311 .id = DPAA2_ETH_DIST_ETHSRC,
312 .size = 6,
313 }, {
314 /* This is the last ethertype field parsed:
315 * depending on frame format, it can be the MAC ethertype
316 * or the VLAN etype.
317 */
318 .cls_prot = NET_PROT_ETH,
319 .cls_field = NH_FLD_ETH_TYPE,
320 .id = DPAA2_ETH_DIST_ETHTYPE,
321 .size = 2,
322 }, {
323 /* VLAN header */
324 .rxnfc_field = RXH_VLAN,
325 .cls_prot = NET_PROT_VLAN,
326 .cls_field = NH_FLD_VLAN_TCI,
327 .id = DPAA2_ETH_DIST_VLAN,
328 .size = 2,
329 }, {
330 /* IP header */
331 .rxnfc_field = RXH_IP_SRC,
332 .cls_prot = NET_PROT_IP,
333 .cls_field = NH_FLD_IP_SRC,
334 .id = DPAA2_ETH_DIST_IPSRC,
335 .size = 4,
336 }, {
337 .rxnfc_field = RXH_IP_DST,
338 .cls_prot = NET_PROT_IP,
339 .cls_field = NH_FLD_IP_DST,
340 .id = DPAA2_ETH_DIST_IPDST,
341 .size = 4,
342 }, {
343 .rxnfc_field = RXH_L3_PROTO,
344 .cls_prot = NET_PROT_IP,
345 .cls_field = NH_FLD_IP_PROTO,
346 .id = DPAA2_ETH_DIST_IPPROTO,
347 .size = 1,
348 }, {
349 /* Using UDP ports, this is functionally equivalent to raw
350 * byte pairs from L4 header.
351 */
352 .rxnfc_field = RXH_L4_B_0_1,
353 .cls_prot = NET_PROT_UDP,
354 .cls_field = NH_FLD_UDP_PORT_SRC,
355 .id = DPAA2_ETH_DIST_L4SRC,
356 .size = 2,
357 }, {
358 .rxnfc_field = RXH_L4_B_2_3,
359 .cls_prot = NET_PROT_UDP,
360 .cls_field = NH_FLD_UDP_PORT_DST,
361 .id = DPAA2_ETH_DIST_L4DST,
362 .size = 2,
363 },
364 };
365
366 static struct dpni_stat {
367 int page;
368 int cnt;
369 char *name;
370 char *desc;
371 } dpni_stat_sysctls[DPAA2_NI_STAT_SYSCTLS] = {
372 /* PAGE, COUNTER, NAME, DESCRIPTION */
373 { 0, 0, "in_all_frames", "All accepted ingress frames" },
374 { 0, 1, "in_all_bytes", "Bytes in all accepted ingress frames" },
375 { 0, 2, "in_multi_frames", "Multicast accepted ingress frames" },
376 { 1, 0, "eg_all_frames", "All egress frames transmitted" },
377 { 1, 1, "eg_all_bytes", "Bytes in all frames transmitted" },
378 { 1, 2, "eg_multi_frames", "Multicast egress frames transmitted" },
379 { 2, 0, "in_filtered_frames", "All ingress frames discarded due to "
380 "filtering" },
381 { 2, 1, "in_discarded_frames", "All frames discarded due to errors" },
382 { 2, 2, "in_nobuf_discards", "Discards on ingress side due to buffer "
383 "depletion in DPNI buffer pools" },
384 };
385
386 struct dpaa2_ni_rx_ctx {
387 struct mbuf *head;
388 struct mbuf *tail;
389 int cnt;
390 bool last;
391 };
392
393 /* Device interface */
394 static int dpaa2_ni_probe(device_t);
395 static int dpaa2_ni_attach(device_t);
396 static int dpaa2_ni_detach(device_t);
397
398 /* DPAA2 network interface setup and configuration */
399 static int dpaa2_ni_setup(device_t);
400 static int dpaa2_ni_setup_channels(device_t);
401 static int dpaa2_ni_bind(device_t);
402 static int dpaa2_ni_setup_rx_dist(device_t);
403 static int dpaa2_ni_setup_irqs(device_t);
404 static int dpaa2_ni_setup_msi(struct dpaa2_ni_softc *);
405 static int dpaa2_ni_setup_if_caps(struct dpaa2_ni_softc *);
406 static int dpaa2_ni_setup_if_flags(struct dpaa2_ni_softc *);
407 static int dpaa2_ni_setup_sysctls(struct dpaa2_ni_softc *);
408 static int dpaa2_ni_setup_dma(struct dpaa2_ni_softc *);
409
410 /* Tx/Rx flow configuration */
411 static int dpaa2_ni_setup_rx_flow(device_t, struct dpaa2_ni_fq *);
412 static int dpaa2_ni_setup_tx_flow(device_t, struct dpaa2_ni_fq *);
413 static int dpaa2_ni_setup_rx_err_flow(device_t, struct dpaa2_ni_fq *);
414
415 /* Configuration subroutines */
416 static int dpaa2_ni_set_buf_layout(device_t);
417 static int dpaa2_ni_set_pause_frame(device_t);
418 static int dpaa2_ni_set_qos_table(device_t);
419 static int dpaa2_ni_set_mac_addr(device_t);
420 static int dpaa2_ni_set_hash(device_t, uint64_t);
421 static int dpaa2_ni_set_dist_key(device_t, enum dpaa2_ni_dist_mode, uint64_t);
422
423 /* Frame descriptor routines */
424 static int dpaa2_ni_build_fd(struct dpaa2_ni_softc *, struct dpaa2_ni_tx_ring *,
425 struct dpaa2_buf *, bus_dma_segment_t *, int, struct dpaa2_fd *);
426 static int dpaa2_ni_fd_err(struct dpaa2_fd *);
427 static uint32_t dpaa2_ni_fd_data_len(struct dpaa2_fd *);
428 static int dpaa2_ni_fd_format(struct dpaa2_fd *);
429 static bool dpaa2_ni_fd_short_len(struct dpaa2_fd *);
430 static int dpaa2_ni_fd_offset(struct dpaa2_fd *);
431
432 /* Various subroutines */
433 static int dpaa2_ni_cmp_api_version(struct dpaa2_ni_softc *, uint16_t, uint16_t);
434 static int dpaa2_ni_prepare_key_cfg(struct dpkg_profile_cfg *, uint8_t *);
435
436 /* Network interface routines */
437 static void dpaa2_ni_init(void *);
438 static int dpaa2_ni_transmit(if_t , struct mbuf *);
439 static void dpaa2_ni_qflush(if_t );
440 static int dpaa2_ni_ioctl(if_t , u_long, caddr_t);
441 static int dpaa2_ni_update_mac_filters(if_t );
442 static u_int dpaa2_ni_add_maddr(void *, struct sockaddr_dl *, u_int);
443
444 /* Interrupt handlers */
445 static void dpaa2_ni_intr(void *);
446
447 /* MII handlers */
448 static void dpaa2_ni_miibus_statchg(device_t);
449 static int dpaa2_ni_media_change(if_t );
450 static void dpaa2_ni_media_status(if_t , struct ifmediareq *);
451 static void dpaa2_ni_media_tick(void *);
452
453 /* Tx/Rx routines. */
454 static int dpaa2_ni_rx_cleanup(struct dpaa2_channel *);
455 static int dpaa2_ni_tx_cleanup(struct dpaa2_channel *);
456 static void dpaa2_ni_tx(struct dpaa2_ni_softc *, struct dpaa2_channel *,
457 struct dpaa2_ni_tx_ring *, struct mbuf *);
458 static void dpaa2_ni_cleanup_task(void *, int);
459
460 /* Tx/Rx subroutines */
461 static int dpaa2_ni_consume_frames(struct dpaa2_channel *, struct dpaa2_ni_fq **,
462 uint32_t *);
463 static int dpaa2_ni_rx(struct dpaa2_channel *, struct dpaa2_ni_fq *,
464 struct dpaa2_fd *, struct dpaa2_ni_rx_ctx *);
465 static int dpaa2_ni_rx_err(struct dpaa2_channel *, struct dpaa2_ni_fq *,
466 struct dpaa2_fd *);
467 static int dpaa2_ni_tx_conf(struct dpaa2_channel *, struct dpaa2_ni_fq *,
468 struct dpaa2_fd *);
469
470 /* sysctl(9) */
471 static int dpaa2_ni_collect_stats(SYSCTL_HANDLER_ARGS);
472 static int dpaa2_ni_collect_buf_num(SYSCTL_HANDLER_ARGS);
473 static int dpaa2_ni_collect_buf_free(SYSCTL_HANDLER_ARGS);
474
475 static int
dpaa2_ni_probe(device_t dev)476 dpaa2_ni_probe(device_t dev)
477 {
478 /* DPNI device will be added by a parent resource container itself. */
479 device_set_desc(dev, "DPAA2 Network Interface");
480 return (BUS_PROBE_DEFAULT);
481 }
482
483 static int
dpaa2_ni_attach(device_t dev)484 dpaa2_ni_attach(device_t dev)
485 {
486 device_t pdev = device_get_parent(dev);
487 device_t child = dev;
488 device_t mcp_dev;
489 struct dpaa2_ni_softc *sc = device_get_softc(dev);
490 struct dpaa2_devinfo *rcinfo = device_get_ivars(pdev);
491 struct dpaa2_devinfo *dinfo = device_get_ivars(dev);
492 struct dpaa2_devinfo *mcp_dinfo;
493 struct dpaa2_cmd cmd;
494 uint16_t rc_token, ni_token;
495 if_t ifp;
496 char tq_name[32];
497 int error;
498
499 sc->dev = dev;
500 sc->ifp = NULL;
501 sc->miibus = NULL;
502 sc->mii = NULL;
503 sc->media_status = 0;
504 sc->if_flags = 0;
505 sc->link_state = LINK_STATE_UNKNOWN;
506 sc->buf_align = 0;
507
508 /* For debug purposes only! */
509 sc->rx_anomaly_frames = 0;
510 sc->rx_single_buf_frames = 0;
511 sc->rx_sg_buf_frames = 0;
512 sc->rx_enq_rej_frames = 0;
513 sc->rx_ieoi_err_frames = 0;
514 sc->tx_single_buf_frames = 0;
515 sc->tx_sg_frames = 0;
516
517 DPAA2_ATOMIC_XCHG(&sc->buf_num, 0);
518 DPAA2_ATOMIC_XCHG(&sc->buf_free, 0);
519
520 sc->rxd_dmat = NULL;
521 sc->qos_dmat = NULL;
522
523 sc->qos_kcfg.dmap = NULL;
524 sc->qos_kcfg.paddr = 0;
525 sc->qos_kcfg.vaddr = NULL;
526
527 sc->rxd_kcfg.dmap = NULL;
528 sc->rxd_kcfg.paddr = 0;
529 sc->rxd_kcfg.vaddr = NULL;
530
531 sc->mac.dpmac_id = 0;
532 sc->mac.phy_dev = NULL;
533 memset(sc->mac.addr, 0, ETHER_ADDR_LEN);
534
535 error = bus_alloc_resources(sc->dev, dpaa2_ni_spec, sc->res);
536 if (error) {
537 device_printf(dev, "%s: failed to allocate resources: "
538 "error=%d\n", __func__, error);
539 goto err_exit;
540 }
541
542 /* Obtain MC portal. */
543 mcp_dev = (device_t) rman_get_start(sc->res[DPAA2_NI_MCP_RID(0)]);
544 mcp_dinfo = device_get_ivars(mcp_dev);
545 dinfo->portal = mcp_dinfo->portal;
546
547 mtx_init(&sc->lock, device_get_nameunit(dev), "dpaa2_ni", MTX_DEF);
548
549 /* Allocate network interface */
550 ifp = if_alloc(IFT_ETHER);
551 if (ifp == NULL) {
552 device_printf(dev, "%s: failed to allocate network interface\n",
553 __func__);
554 goto err_exit;
555 }
556 sc->ifp = ifp;
557 if_initname(ifp, DPAA2_NI_IFNAME, device_get_unit(sc->dev));
558
559 if_setsoftc(ifp, sc);
560 if_setflags(ifp, IFF_SIMPLEX | IFF_MULTICAST | IFF_BROADCAST);
561 if_setinitfn(ifp, dpaa2_ni_init);
562 if_setioctlfn(ifp, dpaa2_ni_ioctl);
563 if_settransmitfn(ifp, dpaa2_ni_transmit);
564 if_setqflushfn(ifp, dpaa2_ni_qflush);
565
566 if_setcapabilities(ifp, IFCAP_VLAN_MTU | IFCAP_HWCSUM | IFCAP_JUMBO_MTU);
567 if_setcapenable(ifp, if_getcapabilities(ifp));
568
569 DPAA2_CMD_INIT(&cmd);
570
571 /* Open resource container and network interface object. */
572 error = DPAA2_CMD_RC_OPEN(dev, child, &cmd, rcinfo->id, &rc_token);
573 if (error) {
574 device_printf(dev, "%s: failed to open resource container: "
575 "id=%d, error=%d\n", __func__, rcinfo->id, error);
576 goto err_exit;
577 }
578 error = DPAA2_CMD_NI_OPEN(dev, child, &cmd, dinfo->id, &ni_token);
579 if (error) {
580 device_printf(dev, "%s: failed to open network interface: "
581 "id=%d, error=%d\n", __func__, dinfo->id, error);
582 goto close_rc;
583 }
584
585 bzero(tq_name, sizeof(tq_name));
586 snprintf(tq_name, sizeof(tq_name), "%s_tqbp", device_get_nameunit(dev));
587
588 /*
589 * XXX-DSL: Release new buffers on Buffer Pool State Change Notification
590 * (BPSCN) returned as a result to the VDQ command instead.
591 * It is similar to CDAN processed in dpaa2_io_intr().
592 */
593 /* Create a taskqueue thread to release new buffers to the pool. */
594 sc->bp_taskq = taskqueue_create(tq_name, M_WAITOK,
595 taskqueue_thread_enqueue, &sc->bp_taskq);
596 if (sc->bp_taskq == NULL) {
597 device_printf(dev, "%s: failed to allocate task queue: %s\n",
598 __func__, tq_name);
599 goto close_ni;
600 }
601 taskqueue_start_threads(&sc->bp_taskq, 1, PI_NET, "%s", tq_name);
602
603 /* sc->cleanup_taskq = taskqueue_create("dpaa2_ch cleanup", M_WAITOK, */
604 /* taskqueue_thread_enqueue, &sc->cleanup_taskq); */
605 /* taskqueue_start_threads(&sc->cleanup_taskq, 1, PI_NET, */
606 /* "dpaa2_ch cleanup"); */
607
608 error = dpaa2_ni_setup(dev);
609 if (error) {
610 device_printf(dev, "%s: failed to setup DPNI: error=%d\n",
611 __func__, error);
612 goto close_ni;
613 }
614 error = dpaa2_ni_setup_channels(dev);
615 if (error) {
616 device_printf(dev, "%s: failed to setup QBMan channels: "
617 "error=%d\n", __func__, error);
618 goto close_ni;
619 }
620
621 error = dpaa2_ni_bind(dev);
622 if (error) {
623 device_printf(dev, "%s: failed to bind DPNI: error=%d\n",
624 __func__, error);
625 goto close_ni;
626 }
627 error = dpaa2_ni_setup_irqs(dev);
628 if (error) {
629 device_printf(dev, "%s: failed to setup IRQs: error=%d\n",
630 __func__, error);
631 goto close_ni;
632 }
633 error = dpaa2_ni_setup_sysctls(sc);
634 if (error) {
635 device_printf(dev, "%s: failed to setup sysctls: error=%d\n",
636 __func__, error);
637 goto close_ni;
638 }
639
640 ether_ifattach(sc->ifp, sc->mac.addr);
641 callout_init(&sc->mii_callout, 0);
642
643 return (0);
644
645 close_ni:
646 DPAA2_CMD_NI_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, ni_token));
647 close_rc:
648 DPAA2_CMD_RC_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, rc_token));
649 err_exit:
650 return (ENXIO);
651 }
652
653 static void
dpaa2_ni_fixed_media_status(if_t ifp,struct ifmediareq * ifmr)654 dpaa2_ni_fixed_media_status(if_t ifp, struct ifmediareq* ifmr)
655 {
656 struct dpaa2_ni_softc *sc = if_getsoftc(ifp);
657
658 DPNI_LOCK(sc);
659 ifmr->ifm_count = 0;
660 ifmr->ifm_mask = 0;
661 ifmr->ifm_status = IFM_AVALID | IFM_ACTIVE;
662 ifmr->ifm_current = ifmr->ifm_active =
663 sc->fixed_ifmedia.ifm_cur->ifm_media;
664
665 /*
666 * In non-PHY usecases, we need to signal link state up, otherwise
667 * certain things requiring a link event (e.g async DHCP client) from
668 * devd do not happen.
669 */
670 if (if_getlinkstate(ifp) == LINK_STATE_UNKNOWN) {
671 if_link_state_change(ifp, LINK_STATE_UP);
672 }
673
674 /*
675 * TODO: Check the status of the link partner (DPMAC, DPNI or other) and
676 * reset if down. This is different to the DPAA2_MAC_LINK_TYPE_PHY as
677 * the MC firmware sets the status, instead of us telling the MC what
678 * it is.
679 */
680 DPNI_UNLOCK(sc);
681
682 return;
683 }
684
685 static void
dpaa2_ni_setup_fixed_link(struct dpaa2_ni_softc * sc)686 dpaa2_ni_setup_fixed_link(struct dpaa2_ni_softc *sc)
687 {
688 /*
689 * FIXME: When the DPNI is connected to a DPMAC, we can get the
690 * 'apparent' speed from it.
691 */
692 sc->fixed_link = true;
693
694 ifmedia_init(&sc->fixed_ifmedia, 0, dpaa2_ni_media_change,
695 dpaa2_ni_fixed_media_status);
696 ifmedia_add(&sc->fixed_ifmedia, IFM_ETHER | IFM_1000_T, 0, NULL);
697 ifmedia_set(&sc->fixed_ifmedia, IFM_ETHER | IFM_1000_T);
698 }
699
700 static int
dpaa2_ni_detach(device_t dev)701 dpaa2_ni_detach(device_t dev)
702 {
703 /* TBD */
704 return (0);
705 }
706
707 /**
708 * @brief Configure DPAA2 network interface object.
709 */
710 static int
dpaa2_ni_setup(device_t dev)711 dpaa2_ni_setup(device_t dev)
712 {
713 device_t pdev = device_get_parent(dev);
714 device_t child = dev;
715 struct dpaa2_ni_softc *sc = device_get_softc(dev);
716 struct dpaa2_devinfo *rcinfo = device_get_ivars(pdev);
717 struct dpaa2_devinfo *dinfo = device_get_ivars(dev);
718 struct dpaa2_ep_desc ep1_desc, ep2_desc; /* endpoint descriptors */
719 struct dpaa2_cmd cmd;
720 uint8_t eth_bca[ETHER_ADDR_LEN]; /* broadcast physical address */
721 uint16_t rc_token, ni_token, mac_token;
722 struct dpaa2_mac_attr attr;
723 enum dpaa2_mac_link_type link_type;
724 uint32_t link;
725 int error;
726
727 DPAA2_CMD_INIT(&cmd);
728
729 error = DPAA2_CMD_RC_OPEN(dev, child, &cmd, rcinfo->id, &rc_token);
730 if (error) {
731 device_printf(dev, "%s: failed to open resource container: "
732 "id=%d, error=%d\n", __func__, rcinfo->id, error);
733 goto err_exit;
734 }
735 error = DPAA2_CMD_NI_OPEN(dev, child, &cmd, dinfo->id, &ni_token);
736 if (error) {
737 device_printf(dev, "%s: failed to open network interface: "
738 "id=%d, error=%d\n", __func__, dinfo->id, error);
739 goto close_rc;
740 }
741
742 /* Check if we can work with this DPNI object. */
743 error = DPAA2_CMD_NI_GET_API_VERSION(dev, child, &cmd, &sc->api_major,
744 &sc->api_minor);
745 if (error) {
746 device_printf(dev, "%s: failed to get DPNI API version\n",
747 __func__);
748 goto close_ni;
749 }
750 if (dpaa2_ni_cmp_api_version(sc, DPNI_VER_MAJOR, DPNI_VER_MINOR) < 0) {
751 device_printf(dev, "%s: DPNI API version %u.%u not supported, "
752 "need >= %u.%u\n", __func__, sc->api_major, sc->api_minor,
753 DPNI_VER_MAJOR, DPNI_VER_MINOR);
754 error = ENODEV;
755 goto close_ni;
756 }
757
758 /* Reset the DPNI object. */
759 error = DPAA2_CMD_NI_RESET(dev, child, &cmd);
760 if (error) {
761 device_printf(dev, "%s: failed to reset DPNI: id=%d\n",
762 __func__, dinfo->id);
763 goto close_ni;
764 }
765
766 /* Obtain attributes of the DPNI object. */
767 error = DPAA2_CMD_NI_GET_ATTRIBUTES(dev, child, &cmd, &sc->attr);
768 if (error) {
769 device_printf(dev, "%s: failed to obtain DPNI attributes: "
770 "id=%d\n", __func__, dinfo->id);
771 goto close_ni;
772 }
773 if (bootverbose) {
774 device_printf(dev, "\toptions=0x%#x queues=%d tx_channels=%d "
775 "wriop_version=%#x\n", sc->attr.options, sc->attr.num.queues,
776 sc->attr.num.channels, sc->attr.wriop_ver);
777 device_printf(dev, "\ttraffic classes: rx=%d tx=%d "
778 "cgs_groups=%d\n", sc->attr.num.rx_tcs, sc->attr.num.tx_tcs,
779 sc->attr.num.cgs);
780 device_printf(dev, "\ttable entries: mac=%d vlan=%d qos=%d "
781 "fs=%d\n", sc->attr.entries.mac, sc->attr.entries.vlan,
782 sc->attr.entries.qos, sc->attr.entries.fs);
783 device_printf(dev, "\tkey sizes: qos=%d fs=%d\n",
784 sc->attr.key_size.qos, sc->attr.key_size.fs);
785 }
786
787 /* Configure buffer layouts of the DPNI queues. */
788 error = dpaa2_ni_set_buf_layout(dev);
789 if (error) {
790 device_printf(dev, "%s: failed to configure buffer layout\n",
791 __func__);
792 goto close_ni;
793 }
794
795 /* Configure DMA resources. */
796 error = dpaa2_ni_setup_dma(sc);
797 if (error) {
798 device_printf(dev, "%s: failed to setup DMA\n", __func__);
799 goto close_ni;
800 }
801
802 /* Setup link between DPNI and an object it's connected to. */
803 ep1_desc.obj_id = dinfo->id;
804 ep1_desc.if_id = 0; /* DPNI has the only endpoint */
805 ep1_desc.type = dinfo->dtype;
806
807 error = DPAA2_CMD_RC_GET_CONN(dev, child, DPAA2_CMD_TK(&cmd, rc_token),
808 &ep1_desc, &ep2_desc, &link);
809 if (error) {
810 device_printf(dev, "%s: failed to obtain an object DPNI is "
811 "connected to: error=%d\n", __func__, error);
812 } else {
813 device_printf(dev, "connected to %s (id=%d)\n",
814 dpaa2_ttos(ep2_desc.type), ep2_desc.obj_id);
815
816 error = dpaa2_ni_set_mac_addr(dev);
817 if (error) {
818 device_printf(dev, "%s: failed to set MAC address: "
819 "error=%d\n", __func__, error);
820 }
821
822 if (ep2_desc.type == DPAA2_DEV_MAC) {
823 /*
824 * This is the simplest case when DPNI is connected to
825 * DPMAC directly.
826 */
827 sc->mac.dpmac_id = ep2_desc.obj_id;
828
829 link_type = DPAA2_MAC_LINK_TYPE_NONE;
830
831 /*
832 * Need to determine if DPMAC type is PHY (attached to
833 * conventional MII PHY) or FIXED (usually SFP/SerDes,
834 * link state managed by MC firmware).
835 */
836 error = DPAA2_CMD_MAC_OPEN(sc->dev, child,
837 DPAA2_CMD_TK(&cmd, rc_token), sc->mac.dpmac_id,
838 &mac_token);
839 /*
840 * Under VFIO, the DPMAC might be sitting in another
841 * container (DPRC) we don't have access to.
842 * Assume DPAA2_MAC_LINK_TYPE_FIXED if this is
843 * the case.
844 */
845 if (error) {
846 device_printf(dev, "%s: failed to open "
847 "connected DPMAC: %d (assuming in other DPRC)\n", __func__,
848 sc->mac.dpmac_id);
849 link_type = DPAA2_MAC_LINK_TYPE_FIXED;
850 } else {
851 error = DPAA2_CMD_MAC_GET_ATTRIBUTES(dev, child,
852 &cmd, &attr);
853 if (error) {
854 device_printf(dev, "%s: failed to get "
855 "DPMAC attributes: id=%d, "
856 "error=%d\n", __func__, dinfo->id,
857 error);
858 } else {
859 link_type = attr.link_type;
860 }
861 }
862 DPAA2_CMD_MAC_CLOSE(dev, child, &cmd);
863
864 if (link_type == DPAA2_MAC_LINK_TYPE_FIXED) {
865 device_printf(dev, "connected DPMAC is in FIXED "
866 "mode\n");
867 dpaa2_ni_setup_fixed_link(sc);
868 } else if (link_type == DPAA2_MAC_LINK_TYPE_PHY) {
869 device_printf(dev, "connected DPMAC is in PHY "
870 "mode\n");
871 error = DPAA2_MC_GET_PHY_DEV(dev,
872 &sc->mac.phy_dev, sc->mac.dpmac_id);
873 if (error == 0) {
874 error = MEMAC_MDIO_SET_NI_DEV(
875 sc->mac.phy_dev, dev);
876 if (error != 0) {
877 device_printf(dev, "%s: failed "
878 "to set dpni dev on memac "
879 "mdio dev %s: error=%d\n",
880 __func__,
881 device_get_nameunit(
882 sc->mac.phy_dev), error);
883 }
884 }
885 if (error == 0) {
886 error = MEMAC_MDIO_GET_PHY_LOC(
887 sc->mac.phy_dev, &sc->mac.phy_loc);
888 if (error == ENODEV) {
889 error = 0;
890 }
891 if (error != 0) {
892 device_printf(dev, "%s: failed "
893 "to get phy location from "
894 "memac mdio dev %s: error=%d\n",
895 __func__, device_get_nameunit(
896 sc->mac.phy_dev), error);
897 }
898 }
899 if (error == 0) {
900 error = mii_attach(sc->mac.phy_dev,
901 &sc->miibus, sc->ifp,
902 dpaa2_ni_media_change,
903 dpaa2_ni_media_status,
904 BMSR_DEFCAPMASK, sc->mac.phy_loc,
905 MII_OFFSET_ANY, 0);
906 if (error != 0) {
907 device_printf(dev, "%s: failed "
908 "to attach to miibus: "
909 "error=%d\n",
910 __func__, error);
911 }
912 }
913 if (error == 0) {
914 sc->mii = device_get_softc(sc->miibus);
915 }
916 } else {
917 device_printf(dev, "%s: DPMAC link type is not "
918 "supported\n", __func__);
919 }
920 } else if (ep2_desc.type == DPAA2_DEV_NI ||
921 ep2_desc.type == DPAA2_DEV_MUX ||
922 ep2_desc.type == DPAA2_DEV_SW) {
923 dpaa2_ni_setup_fixed_link(sc);
924 }
925 }
926
927 /* Select mode to enqueue frames. */
928 /* ... TBD ... */
929
930 /*
931 * Update link configuration to enable Rx/Tx pause frames support.
932 *
933 * NOTE: MC may generate an interrupt to the DPMAC and request changes
934 * in link configuration. It might be necessary to attach miibus
935 * and PHY before this point.
936 */
937 error = dpaa2_ni_set_pause_frame(dev);
938 if (error) {
939 device_printf(dev, "%s: failed to configure Rx/Tx pause "
940 "frames\n", __func__);
941 goto close_ni;
942 }
943
944 /* Configure ingress traffic classification. */
945 error = dpaa2_ni_set_qos_table(dev);
946 if (error) {
947 device_printf(dev, "%s: failed to configure QoS table: "
948 "error=%d\n", __func__, error);
949 goto close_ni;
950 }
951
952 /* Add broadcast physical address to the MAC filtering table. */
953 memset(eth_bca, 0xff, ETHER_ADDR_LEN);
954 error = DPAA2_CMD_NI_ADD_MAC_ADDR(dev, child, DPAA2_CMD_TK(&cmd,
955 ni_token), eth_bca);
956 if (error) {
957 device_printf(dev, "%s: failed to add broadcast physical "
958 "address to the MAC filtering table\n", __func__);
959 goto close_ni;
960 }
961
962 /* Set the maximum allowed length for received frames. */
963 error = DPAA2_CMD_NI_SET_MFL(dev, child, &cmd, DPAA2_ETH_MFL);
964 if (error) {
965 device_printf(dev, "%s: failed to set maximum length for "
966 "received frames\n", __func__);
967 goto close_ni;
968 }
969
970 (void)DPAA2_CMD_NI_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, ni_token));
971 (void)DPAA2_CMD_RC_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, rc_token));
972 return (0);
973
974 close_ni:
975 (void)DPAA2_CMD_NI_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, ni_token));
976 close_rc:
977 (void)DPAA2_CMD_RC_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, rc_token));
978 err_exit:
979 return (error);
980 }
981
982 /**
983 * @brief Сonfigure QBMan channels and register data availability notifications.
984 */
985 static int
dpaa2_ni_setup_channels(device_t dev)986 dpaa2_ni_setup_channels(device_t dev)
987 {
988 device_t iodev, condev, bpdev;
989 struct dpaa2_ni_softc *sc = device_get_softc(dev);
990 uint32_t i, num_chan;
991 int error;
992
993 /* Calculate number of the channels based on the allocated resources */
994 for (i = 0; i < DPAA2_NI_IO_RES_NUM; i++) {
995 if (!sc->res[DPAA2_NI_IO_RID(i)]) {
996 break;
997 }
998 }
999 num_chan = i;
1000 for (i = 0; i < DPAA2_NI_CON_RES_NUM; i++) {
1001 if (!sc->res[DPAA2_NI_CON_RID(i)]) {
1002 break;
1003 }
1004 }
1005 num_chan = i < num_chan ? i : num_chan;
1006 sc->chan_n = num_chan > DPAA2_MAX_CHANNELS
1007 ? DPAA2_MAX_CHANNELS : num_chan;
1008 sc->chan_n = sc->chan_n > sc->attr.num.queues
1009 ? sc->attr.num.queues : sc->chan_n;
1010
1011 KASSERT(sc->chan_n > 0u, ("%s: positive number of channels expected: "
1012 "chan_n=%d", __func__, sc->chan_n));
1013
1014 device_printf(dev, "channels=%d\n", sc->chan_n);
1015
1016 for (i = 0; i < sc->chan_n; i++) {
1017 iodev = (device_t)rman_get_start(sc->res[DPAA2_NI_IO_RID(i)]);
1018 condev = (device_t)rman_get_start(sc->res[DPAA2_NI_CON_RID(i)]);
1019 /* Only one buffer pool available at the moment */
1020 bpdev = (device_t)rman_get_start(sc->res[DPAA2_NI_BP_RID(0)]);
1021
1022 error = dpaa2_chan_setup(dev, iodev, condev, bpdev,
1023 &sc->channels[i], i, dpaa2_ni_cleanup_task);
1024 if (error != 0) {
1025 device_printf(dev, "%s: dpaa2_chan_setup() failed: "
1026 "error=%d, chan_id=%d\n", __func__, error, i);
1027 return (error);
1028 }
1029 }
1030
1031 /* There is exactly one Rx error queue per network interface */
1032 error = dpaa2_chan_setup_fq(dev, sc->channels[0], DPAA2_NI_QUEUE_RX_ERR);
1033 if (error != 0) {
1034 device_printf(dev, "%s: failed to prepare RxError queue: "
1035 "error=%d\n", __func__, error);
1036 return (error);
1037 }
1038
1039 return (0);
1040 }
1041
1042 /**
1043 * @brief Bind DPNI to DPBPs, DPIOs, frame queues and channels.
1044 */
1045 static int
dpaa2_ni_bind(device_t dev)1046 dpaa2_ni_bind(device_t dev)
1047 {
1048 device_t pdev = device_get_parent(dev);
1049 device_t child = dev;
1050 device_t bp_dev;
1051 struct dpaa2_ni_softc *sc = device_get_softc(dev);
1052 struct dpaa2_devinfo *rcinfo = device_get_ivars(pdev);
1053 struct dpaa2_devinfo *dinfo = device_get_ivars(dev);
1054 struct dpaa2_devinfo *bp_info;
1055 struct dpaa2_cmd cmd;
1056 struct dpaa2_ni_pools_cfg pools_cfg;
1057 struct dpaa2_ni_err_cfg err_cfg;
1058 struct dpaa2_channel *chan;
1059 uint16_t rc_token, ni_token;
1060 int error;
1061
1062 DPAA2_CMD_INIT(&cmd);
1063
1064 error = DPAA2_CMD_RC_OPEN(dev, child, &cmd, rcinfo->id, &rc_token);
1065 if (error) {
1066 device_printf(dev, "%s: failed to open resource container: "
1067 "id=%d, error=%d\n", __func__, rcinfo->id, error);
1068 goto err_exit;
1069 }
1070 error = DPAA2_CMD_NI_OPEN(dev, child, &cmd, dinfo->id, &ni_token);
1071 if (error) {
1072 device_printf(dev, "%s: failed to open network interface: "
1073 "id=%d, error=%d\n", __func__, dinfo->id, error);
1074 goto close_rc;
1075 }
1076
1077 /* Select buffer pool (only one available at the moment). */
1078 bp_dev = (device_t) rman_get_start(sc->res[DPAA2_NI_BP_RID(0)]);
1079 bp_info = device_get_ivars(bp_dev);
1080
1081 /* Configure buffers pool. */
1082 pools_cfg.pools_num = 1;
1083 pools_cfg.pools[0].bp_obj_id = bp_info->id;
1084 pools_cfg.pools[0].backup_flag = 0;
1085 pools_cfg.pools[0].buf_sz = sc->buf_sz;
1086 error = DPAA2_CMD_NI_SET_POOLS(dev, child, &cmd, &pools_cfg);
1087 if (error) {
1088 device_printf(dev, "%s: failed to set buffer pools\n", __func__);
1089 goto close_ni;
1090 }
1091
1092 /* Setup ingress traffic distribution. */
1093 error = dpaa2_ni_setup_rx_dist(dev);
1094 if (error && error != EOPNOTSUPP) {
1095 device_printf(dev, "%s: failed to setup ingress traffic "
1096 "distribution\n", __func__);
1097 goto close_ni;
1098 }
1099 if (bootverbose && error == EOPNOTSUPP) {
1100 device_printf(dev, "Ingress traffic distribution not "
1101 "supported\n");
1102 }
1103
1104 /* Configure handling of error frames. */
1105 err_cfg.err_mask = DPAA2_NI_FAS_RX_ERR_MASK;
1106 err_cfg.set_err_fas = false;
1107 err_cfg.action = DPAA2_NI_ERR_DISCARD;
1108 error = DPAA2_CMD_NI_SET_ERR_BEHAVIOR(dev, child, &cmd, &err_cfg);
1109 if (error) {
1110 device_printf(dev, "%s: failed to set errors behavior\n",
1111 __func__);
1112 goto close_ni;
1113 }
1114
1115 /* Configure channel queues to generate CDANs. */
1116 for (uint32_t i = 0; i < sc->chan_n; i++) {
1117 chan = sc->channels[i];
1118
1119 /* Setup Rx flows. */
1120 for (uint32_t j = 0; j < chan->rxq_n; j++) {
1121 error = dpaa2_ni_setup_rx_flow(dev, &chan->rx_queues[j]);
1122 if (error) {
1123 device_printf(dev, "%s: failed to setup Rx "
1124 "flow: error=%d\n", __func__, error);
1125 goto close_ni;
1126 }
1127 }
1128
1129 /* Setup Tx flow. */
1130 error = dpaa2_ni_setup_tx_flow(dev, &chan->txc_queue);
1131 if (error) {
1132 device_printf(dev, "%s: failed to setup Tx "
1133 "flow: error=%d\n", __func__, error);
1134 goto close_ni;
1135 }
1136 }
1137
1138 /* Configure RxError queue to generate CDAN. */
1139 error = dpaa2_ni_setup_rx_err_flow(dev, &sc->rxe_queue);
1140 if (error) {
1141 device_printf(dev, "%s: failed to setup RxError flow: "
1142 "error=%d\n", __func__, error);
1143 goto close_ni;
1144 }
1145
1146 /*
1147 * Get the Queuing Destination ID (QDID) that should be used for frame
1148 * enqueue operations.
1149 */
1150 error = DPAA2_CMD_NI_GET_QDID(dev, child, &cmd, DPAA2_NI_QUEUE_TX,
1151 &sc->tx_qdid);
1152 if (error) {
1153 device_printf(dev, "%s: failed to get Tx queuing destination "
1154 "ID\n", __func__);
1155 goto close_ni;
1156 }
1157
1158 (void)DPAA2_CMD_NI_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, ni_token));
1159 (void)DPAA2_CMD_RC_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, rc_token));
1160 return (0);
1161
1162 close_ni:
1163 (void)DPAA2_CMD_NI_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, ni_token));
1164 close_rc:
1165 (void)DPAA2_CMD_RC_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, rc_token));
1166 err_exit:
1167 return (error);
1168 }
1169
1170 /**
1171 * @brief Setup ingress traffic distribution.
1172 *
1173 * NOTE: Ingress traffic distribution is valid only when DPNI_OPT_NO_FS option
1174 * hasn't been set for DPNI and a number of DPNI queues > 1.
1175 */
1176 static int
dpaa2_ni_setup_rx_dist(device_t dev)1177 dpaa2_ni_setup_rx_dist(device_t dev)
1178 {
1179 /*
1180 * Have the interface implicitly distribute traffic based on the default
1181 * hash key.
1182 */
1183 return (dpaa2_ni_set_hash(dev, DPAA2_RXH_DEFAULT));
1184 }
1185
1186 static int
dpaa2_ni_setup_rx_flow(device_t dev,struct dpaa2_ni_fq * fq)1187 dpaa2_ni_setup_rx_flow(device_t dev, struct dpaa2_ni_fq *fq)
1188 {
1189 device_t pdev = device_get_parent(dev);
1190 device_t child = dev;
1191 struct dpaa2_devinfo *rcinfo = device_get_ivars(pdev);
1192 struct dpaa2_devinfo *dinfo = device_get_ivars(dev);
1193 struct dpaa2_devinfo *con_info;
1194 struct dpaa2_cmd cmd;
1195 struct dpaa2_ni_queue_cfg queue_cfg = {0};
1196 uint16_t rc_token, ni_token;
1197 int error;
1198
1199 DPAA2_CMD_INIT(&cmd);
1200
1201 error = DPAA2_CMD_RC_OPEN(dev, child, &cmd, rcinfo->id, &rc_token);
1202 if (error) {
1203 device_printf(dev, "%s: failed to open resource container: "
1204 "id=%d, error=%d\n", __func__, rcinfo->id, error);
1205 goto err_exit;
1206 }
1207 error = DPAA2_CMD_NI_OPEN(dev, child, &cmd, dinfo->id, &ni_token);
1208 if (error) {
1209 device_printf(dev, "%s: failed to open network interface: "
1210 "id=%d, error=%d\n", __func__, dinfo->id, error);
1211 goto close_rc;
1212 }
1213
1214 /* Obtain DPCON associated with the FQ's channel. */
1215 con_info = device_get_ivars(fq->chan->con_dev);
1216
1217 queue_cfg.type = DPAA2_NI_QUEUE_RX;
1218 queue_cfg.tc = fq->tc;
1219 queue_cfg.idx = fq->flowid;
1220 error = DPAA2_CMD_NI_GET_QUEUE(dev, child, &cmd, &queue_cfg);
1221 if (error) {
1222 device_printf(dev, "%s: failed to obtain Rx queue "
1223 "configuration: tc=%d, flowid=%d\n", __func__, queue_cfg.tc,
1224 queue_cfg.idx);
1225 goto close_ni;
1226 }
1227
1228 fq->fqid = queue_cfg.fqid;
1229
1230 queue_cfg.dest_id = con_info->id;
1231 queue_cfg.dest_type = DPAA2_NI_DEST_DPCON;
1232 queue_cfg.priority = 1;
1233 queue_cfg.user_ctx = (uint64_t)(uintmax_t) fq;
1234 queue_cfg.options =
1235 DPAA2_NI_QUEUE_OPT_USER_CTX |
1236 DPAA2_NI_QUEUE_OPT_DEST;
1237 error = DPAA2_CMD_NI_SET_QUEUE(dev, child, &cmd, &queue_cfg);
1238 if (error) {
1239 device_printf(dev, "%s: failed to update Rx queue "
1240 "configuration: tc=%d, flowid=%d\n", __func__, queue_cfg.tc,
1241 queue_cfg.idx);
1242 goto close_ni;
1243 }
1244
1245 if (bootverbose) {
1246 device_printf(dev, "RX queue idx=%d, tc=%d, chan=%d, fqid=%d, "
1247 "user_ctx=%#jx\n", fq->flowid, fq->tc, fq->chan->id,
1248 fq->fqid, (uint64_t) fq);
1249 }
1250
1251 (void)DPAA2_CMD_NI_CLOSE(dev, child, &cmd);
1252 (void)DPAA2_CMD_RC_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, rc_token));
1253 return (0);
1254
1255 close_ni:
1256 (void)DPAA2_CMD_NI_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, ni_token));
1257 close_rc:
1258 (void)DPAA2_CMD_RC_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, rc_token));
1259 err_exit:
1260 return (error);
1261 }
1262
1263 static int
dpaa2_ni_setup_tx_flow(device_t dev,struct dpaa2_ni_fq * fq)1264 dpaa2_ni_setup_tx_flow(device_t dev, struct dpaa2_ni_fq *fq)
1265 {
1266 device_t pdev = device_get_parent(dev);
1267 device_t child = dev;
1268 struct dpaa2_ni_softc *sc = device_get_softc(dev);
1269 struct dpaa2_channel *ch = fq->chan;
1270 struct dpaa2_devinfo *rcinfo = device_get_ivars(pdev);
1271 struct dpaa2_devinfo *dinfo = device_get_ivars(dev);
1272 struct dpaa2_devinfo *con_info;
1273 struct dpaa2_ni_queue_cfg queue_cfg = {0};
1274 struct dpaa2_ni_tx_ring *tx;
1275 struct dpaa2_buf *buf;
1276 struct dpaa2_cmd cmd;
1277 uint32_t tx_rings_n = 0;
1278 uint16_t rc_token, ni_token;
1279 int error;
1280
1281 DPAA2_CMD_INIT(&cmd);
1282
1283 error = DPAA2_CMD_RC_OPEN(dev, child, &cmd, rcinfo->id, &rc_token);
1284 if (error) {
1285 device_printf(dev, "%s: failed to open resource container: "
1286 "id=%d, error=%d\n", __func__, rcinfo->id, error);
1287 goto err_exit;
1288 }
1289 error = DPAA2_CMD_NI_OPEN(dev, child, &cmd, dinfo->id, &ni_token);
1290 if (error) {
1291 device_printf(dev, "%s: failed to open network interface: "
1292 "id=%d, error=%d\n", __func__, dinfo->id, error);
1293 goto close_rc;
1294 }
1295
1296 /* Obtain DPCON associated with the FQ's channel. */
1297 con_info = device_get_ivars(fq->chan->con_dev);
1298
1299 KASSERT(sc->attr.num.tx_tcs <= DPAA2_MAX_TCS,
1300 ("%s: too many Tx traffic classes: tx_tcs=%d\n", __func__,
1301 sc->attr.num.tx_tcs));
1302 KASSERT(DPAA2_NI_BUFS_PER_TX <= DPAA2_NI_MAX_BPTX,
1303 ("%s: too many Tx buffers (%d): max=%d\n", __func__,
1304 DPAA2_NI_BUFS_PER_TX, DPAA2_NI_MAX_BPTX));
1305
1306 /* Setup Tx rings. */
1307 for (int i = 0; i < sc->attr.num.tx_tcs; i++) {
1308 queue_cfg.type = DPAA2_NI_QUEUE_TX;
1309 queue_cfg.tc = i;
1310 queue_cfg.idx = fq->flowid;
1311 queue_cfg.chan_id = fq->chan->id;
1312
1313 error = DPAA2_CMD_NI_GET_QUEUE(dev, child, &cmd, &queue_cfg);
1314 if (error) {
1315 device_printf(dev, "%s: failed to obtain Tx queue "
1316 "configuration: tc=%d, flowid=%d\n", __func__,
1317 queue_cfg.tc, queue_cfg.idx);
1318 goto close_ni;
1319 }
1320
1321 tx = &fq->tx_rings[i];
1322 tx->fq = fq;
1323 tx->fqid = queue_cfg.fqid;
1324 tx->txid = tx_rings_n;
1325
1326 if (bootverbose) {
1327 device_printf(dev, "TX queue idx=%d, tc=%d, chan=%d, "
1328 "fqid=%d\n", fq->flowid, i, fq->chan->id,
1329 queue_cfg.fqid);
1330 }
1331
1332 mtx_init(&tx->lock, "dpaa2_tx_ring", NULL, MTX_DEF);
1333
1334 /* Allocate Tx ring buffer. */
1335 tx->br = buf_ring_alloc(DPAA2_TX_BUFRING_SZ, M_DEVBUF, M_NOWAIT,
1336 &tx->lock);
1337 if (tx->br == NULL) {
1338 device_printf(dev, "%s: failed to setup Tx ring buffer"
1339 " (2) fqid=%d\n", __func__, tx->fqid);
1340 goto close_ni;
1341 }
1342
1343 /* Configure Tx buffers */
1344 for (uint64_t j = 0; j < DPAA2_NI_BUFS_PER_TX; j++) {
1345 buf = malloc(sizeof(struct dpaa2_buf), M_DPAA2_TXB,
1346 M_WAITOK);
1347 if (buf == NULL) {
1348 device_printf(dev, "%s: malloc() failed (buf)\n",
1349 __func__);
1350 return (ENOMEM);
1351 }
1352 /* Keep DMA tag and Tx ring linked to the buffer */
1353 DPAA2_BUF_INIT_TAGOPT(buf, ch->tx_dmat, tx);
1354
1355 buf->sgt = malloc(sizeof(struct dpaa2_buf), M_DPAA2_TXB,
1356 M_WAITOK);
1357 if (buf->sgt == NULL) {
1358 device_printf(dev, "%s: malloc() failed (sgt)\n",
1359 __func__);
1360 return (ENOMEM);
1361 }
1362 /* Link SGT to DMA tag and back to its Tx buffer */
1363 DPAA2_BUF_INIT_TAGOPT(buf->sgt, ch->sgt_dmat, buf);
1364
1365 error = dpaa2_buf_seed_txb(dev, buf);
1366
1367 /* Add Tx buffer to the ring */
1368 buf_ring_enqueue(tx->br, buf);
1369 }
1370
1371 tx_rings_n++;
1372 }
1373
1374 /* All Tx queues which belong to the same flowid have the same qdbin. */
1375 fq->tx_qdbin = queue_cfg.qdbin;
1376
1377 queue_cfg.type = DPAA2_NI_QUEUE_TX_CONF;
1378 queue_cfg.tc = 0; /* ignored for TxConf queue */
1379 queue_cfg.idx = fq->flowid;
1380 error = DPAA2_CMD_NI_GET_QUEUE(dev, child, &cmd, &queue_cfg);
1381 if (error) {
1382 device_printf(dev, "%s: failed to obtain TxConf queue "
1383 "configuration: tc=%d, flowid=%d\n", __func__, queue_cfg.tc,
1384 queue_cfg.idx);
1385 goto close_ni;
1386 }
1387
1388 fq->fqid = queue_cfg.fqid;
1389
1390 queue_cfg.dest_id = con_info->id;
1391 queue_cfg.dest_type = DPAA2_NI_DEST_DPCON;
1392 queue_cfg.priority = 0;
1393 queue_cfg.user_ctx = (uint64_t)(uintmax_t) fq;
1394 queue_cfg.options =
1395 DPAA2_NI_QUEUE_OPT_USER_CTX |
1396 DPAA2_NI_QUEUE_OPT_DEST;
1397 error = DPAA2_CMD_NI_SET_QUEUE(dev, child, &cmd, &queue_cfg);
1398 if (error) {
1399 device_printf(dev, "%s: failed to update TxConf queue "
1400 "configuration: tc=%d, flowid=%d\n", __func__, queue_cfg.tc,
1401 queue_cfg.idx);
1402 goto close_ni;
1403 }
1404
1405 (void)DPAA2_CMD_NI_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, ni_token));
1406 (void)DPAA2_CMD_RC_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, rc_token));
1407 return (0);
1408
1409 close_ni:
1410 (void)DPAA2_CMD_NI_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, ni_token));
1411 close_rc:
1412 (void)DPAA2_CMD_RC_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, rc_token));
1413 err_exit:
1414 return (error);
1415 }
1416
1417 static int
dpaa2_ni_setup_rx_err_flow(device_t dev,struct dpaa2_ni_fq * fq)1418 dpaa2_ni_setup_rx_err_flow(device_t dev, struct dpaa2_ni_fq *fq)
1419 {
1420 device_t pdev = device_get_parent(dev);
1421 device_t child = dev;
1422 struct dpaa2_devinfo *rcinfo = device_get_ivars(pdev);
1423 struct dpaa2_devinfo *dinfo = device_get_ivars(dev);
1424 struct dpaa2_devinfo *con_info;
1425 struct dpaa2_ni_queue_cfg queue_cfg = {0};
1426 struct dpaa2_cmd cmd;
1427 uint16_t rc_token, ni_token;
1428 int error;
1429
1430 DPAA2_CMD_INIT(&cmd);
1431
1432 error = DPAA2_CMD_RC_OPEN(dev, child, &cmd, rcinfo->id, &rc_token);
1433 if (error) {
1434 device_printf(dev, "%s: failed to open resource container: "
1435 "id=%d, error=%d\n", __func__, rcinfo->id, error);
1436 goto err_exit;
1437 }
1438 error = DPAA2_CMD_NI_OPEN(dev, child, &cmd, dinfo->id, &ni_token);
1439 if (error) {
1440 device_printf(dev, "%s: failed to open network interface: "
1441 "id=%d, error=%d\n", __func__, dinfo->id, error);
1442 goto close_rc;
1443 }
1444
1445 /* Obtain DPCON associated with the FQ's channel. */
1446 con_info = device_get_ivars(fq->chan->con_dev);
1447
1448 queue_cfg.type = DPAA2_NI_QUEUE_RX_ERR;
1449 queue_cfg.tc = fq->tc; /* ignored */
1450 queue_cfg.idx = fq->flowid; /* ignored */
1451 error = DPAA2_CMD_NI_GET_QUEUE(dev, child, &cmd, &queue_cfg);
1452 if (error) {
1453 device_printf(dev, "%s: failed to obtain RxErr queue "
1454 "configuration\n", __func__);
1455 goto close_ni;
1456 }
1457
1458 fq->fqid = queue_cfg.fqid;
1459
1460 queue_cfg.dest_id = con_info->id;
1461 queue_cfg.dest_type = DPAA2_NI_DEST_DPCON;
1462 queue_cfg.priority = 1;
1463 queue_cfg.user_ctx = (uint64_t)(uintmax_t) fq;
1464 queue_cfg.options =
1465 DPAA2_NI_QUEUE_OPT_USER_CTX |
1466 DPAA2_NI_QUEUE_OPT_DEST;
1467 error = DPAA2_CMD_NI_SET_QUEUE(dev, child, &cmd, &queue_cfg);
1468 if (error) {
1469 device_printf(dev, "%s: failed to update RxErr queue "
1470 "configuration\n", __func__);
1471 goto close_ni;
1472 }
1473
1474 (void)DPAA2_CMD_NI_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, ni_token));
1475 (void)DPAA2_CMD_RC_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, rc_token));
1476 return (0);
1477
1478 close_ni:
1479 (void)DPAA2_CMD_NI_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, ni_token));
1480 close_rc:
1481 (void)DPAA2_CMD_RC_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, rc_token));
1482 err_exit:
1483 return (error);
1484 }
1485
1486 /**
1487 * @brief Configure DPNI object to generate interrupts.
1488 */
1489 static int
dpaa2_ni_setup_irqs(device_t dev)1490 dpaa2_ni_setup_irqs(device_t dev)
1491 {
1492 device_t pdev = device_get_parent(dev);
1493 device_t child = dev;
1494 struct dpaa2_ni_softc *sc = device_get_softc(dev);
1495 struct dpaa2_devinfo *rcinfo = device_get_ivars(pdev);
1496 struct dpaa2_devinfo *dinfo = device_get_ivars(dev);
1497 struct dpaa2_cmd cmd;
1498 uint16_t rc_token, ni_token;
1499 int error;
1500
1501 DPAA2_CMD_INIT(&cmd);
1502
1503 error = DPAA2_CMD_RC_OPEN(dev, child, &cmd, rcinfo->id, &rc_token);
1504 if (error) {
1505 device_printf(dev, "%s: failed to open resource container: "
1506 "id=%d, error=%d\n", __func__, rcinfo->id, error);
1507 goto err_exit;
1508 }
1509 error = DPAA2_CMD_NI_OPEN(dev, child, &cmd, dinfo->id, &ni_token);
1510 if (error) {
1511 device_printf(dev, "%s: failed to open network interface: "
1512 "id=%d, error=%d\n", __func__, dinfo->id, error);
1513 goto close_rc;
1514 }
1515
1516 /* Configure IRQs. */
1517 error = dpaa2_ni_setup_msi(sc);
1518 if (error) {
1519 device_printf(dev, "%s: failed to allocate MSI\n", __func__);
1520 goto close_ni;
1521 }
1522 if ((sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ,
1523 &sc->irq_rid[0], RF_ACTIVE | RF_SHAREABLE)) == NULL) {
1524 device_printf(dev, "%s: failed to allocate IRQ resource\n",
1525 __func__);
1526 goto close_ni;
1527 }
1528 if (bus_setup_intr(dev, sc->irq_res, INTR_TYPE_NET | INTR_MPSAFE,
1529 NULL, dpaa2_ni_intr, sc, &sc->intr)) {
1530 device_printf(dev, "%s: failed to setup IRQ resource\n",
1531 __func__);
1532 goto close_ni;
1533 }
1534
1535 error = DPAA2_CMD_NI_SET_IRQ_MASK(dev, child, &cmd, DPNI_IRQ_INDEX,
1536 DPNI_IRQ_LINK_CHANGED | DPNI_IRQ_EP_CHANGED);
1537 if (error) {
1538 device_printf(dev, "%s: failed to set DPNI IRQ mask\n",
1539 __func__);
1540 goto close_ni;
1541 }
1542
1543 error = DPAA2_CMD_NI_SET_IRQ_ENABLE(dev, child, &cmd, DPNI_IRQ_INDEX,
1544 true);
1545 if (error) {
1546 device_printf(dev, "%s: failed to enable DPNI IRQ\n", __func__);
1547 goto close_ni;
1548 }
1549
1550 (void)DPAA2_CMD_NI_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, ni_token));
1551 (void)DPAA2_CMD_RC_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, rc_token));
1552 return (0);
1553
1554 close_ni:
1555 (void)DPAA2_CMD_NI_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, ni_token));
1556 close_rc:
1557 (void)DPAA2_CMD_RC_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, rc_token));
1558 err_exit:
1559 return (error);
1560 }
1561
1562 /**
1563 * @brief Allocate MSI interrupts for DPNI.
1564 */
1565 static int
dpaa2_ni_setup_msi(struct dpaa2_ni_softc * sc)1566 dpaa2_ni_setup_msi(struct dpaa2_ni_softc *sc)
1567 {
1568 int val;
1569
1570 val = pci_msi_count(sc->dev);
1571 if (val < DPAA2_NI_MSI_COUNT)
1572 device_printf(sc->dev, "MSI: actual=%d, expected=%d\n", val,
1573 DPAA2_IO_MSI_COUNT);
1574 val = MIN(val, DPAA2_NI_MSI_COUNT);
1575
1576 if (pci_alloc_msi(sc->dev, &val) != 0)
1577 return (EINVAL);
1578
1579 for (int i = 0; i < val; i++)
1580 sc->irq_rid[i] = i + 1;
1581
1582 return (0);
1583 }
1584
1585 /**
1586 * @brief Update DPNI according to the updated interface capabilities.
1587 */
1588 static int
dpaa2_ni_setup_if_caps(struct dpaa2_ni_softc * sc)1589 dpaa2_ni_setup_if_caps(struct dpaa2_ni_softc *sc)
1590 {
1591 const bool en_rxcsum = if_getcapenable(sc->ifp) & IFCAP_RXCSUM;
1592 const bool en_txcsum = if_getcapenable(sc->ifp) & IFCAP_TXCSUM;
1593 device_t pdev = device_get_parent(sc->dev);
1594 device_t dev = sc->dev;
1595 device_t child = dev;
1596 struct dpaa2_devinfo *rcinfo = device_get_ivars(pdev);
1597 struct dpaa2_devinfo *dinfo = device_get_ivars(dev);
1598 struct dpaa2_cmd cmd;
1599 uint16_t rc_token, ni_token;
1600 int error;
1601
1602 DPAA2_CMD_INIT(&cmd);
1603
1604 error = DPAA2_CMD_RC_OPEN(dev, child, &cmd, rcinfo->id, &rc_token);
1605 if (error) {
1606 device_printf(dev, "%s: failed to open resource container: "
1607 "id=%d, error=%d\n", __func__, rcinfo->id, error);
1608 goto err_exit;
1609 }
1610 error = DPAA2_CMD_NI_OPEN(dev, child, &cmd, dinfo->id, &ni_token);
1611 if (error) {
1612 device_printf(dev, "%s: failed to open network interface: "
1613 "id=%d, error=%d\n", __func__, dinfo->id, error);
1614 goto close_rc;
1615 }
1616
1617 /* Setup checksums validation. */
1618 error = DPAA2_CMD_NI_SET_OFFLOAD(dev, child, &cmd,
1619 DPAA2_NI_OFL_RX_L3_CSUM, en_rxcsum);
1620 if (error) {
1621 device_printf(dev, "%s: failed to %s L3 checksum validation\n",
1622 __func__, en_rxcsum ? "enable" : "disable");
1623 goto close_ni;
1624 }
1625 error = DPAA2_CMD_NI_SET_OFFLOAD(dev, child, &cmd,
1626 DPAA2_NI_OFL_RX_L4_CSUM, en_rxcsum);
1627 if (error) {
1628 device_printf(dev, "%s: failed to %s L4 checksum validation\n",
1629 __func__, en_rxcsum ? "enable" : "disable");
1630 goto close_ni;
1631 }
1632
1633 /* Setup checksums generation. */
1634 error = DPAA2_CMD_NI_SET_OFFLOAD(dev, child, &cmd,
1635 DPAA2_NI_OFL_TX_L3_CSUM, en_txcsum);
1636 if (error) {
1637 device_printf(dev, "%s: failed to %s L3 checksum generation\n",
1638 __func__, en_txcsum ? "enable" : "disable");
1639 goto close_ni;
1640 }
1641 error = DPAA2_CMD_NI_SET_OFFLOAD(dev, child, &cmd,
1642 DPAA2_NI_OFL_TX_L4_CSUM, en_txcsum);
1643 if (error) {
1644 device_printf(dev, "%s: failed to %s L4 checksum generation\n",
1645 __func__, en_txcsum ? "enable" : "disable");
1646 goto close_ni;
1647 }
1648
1649 (void)DPAA2_CMD_NI_CLOSE(dev, child, &cmd);
1650 (void)DPAA2_CMD_RC_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, rc_token));
1651 return (0);
1652
1653 close_ni:
1654 (void)DPAA2_CMD_NI_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, ni_token));
1655 close_rc:
1656 (void)DPAA2_CMD_RC_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, rc_token));
1657 err_exit:
1658 return (error);
1659 }
1660
1661 /**
1662 * @brief Update DPNI according to the updated interface flags.
1663 */
1664 static int
dpaa2_ni_setup_if_flags(struct dpaa2_ni_softc * sc)1665 dpaa2_ni_setup_if_flags(struct dpaa2_ni_softc *sc)
1666 {
1667 const bool en_promisc = if_getflags(sc->ifp) & IFF_PROMISC;
1668 const bool en_allmulti = if_getflags(sc->ifp) & IFF_ALLMULTI;
1669 device_t pdev = device_get_parent(sc->dev);
1670 device_t dev = sc->dev;
1671 device_t child = dev;
1672 struct dpaa2_devinfo *rcinfo = device_get_ivars(pdev);
1673 struct dpaa2_devinfo *dinfo = device_get_ivars(dev);
1674 struct dpaa2_cmd cmd;
1675 uint16_t rc_token, ni_token;
1676 int error;
1677
1678 DPAA2_CMD_INIT(&cmd);
1679
1680 error = DPAA2_CMD_RC_OPEN(dev, child, &cmd, rcinfo->id, &rc_token);
1681 if (error) {
1682 device_printf(dev, "%s: failed to open resource container: "
1683 "id=%d, error=%d\n", __func__, rcinfo->id, error);
1684 goto err_exit;
1685 }
1686 error = DPAA2_CMD_NI_OPEN(dev, child, &cmd, dinfo->id, &ni_token);
1687 if (error) {
1688 device_printf(dev, "%s: failed to open network interface: "
1689 "id=%d, error=%d\n", __func__, dinfo->id, error);
1690 goto close_rc;
1691 }
1692
1693 error = DPAA2_CMD_NI_SET_MULTI_PROMISC(dev, child, &cmd,
1694 en_promisc ? true : en_allmulti);
1695 if (error) {
1696 device_printf(dev, "%s: failed to %s multicast promiscuous "
1697 "mode\n", __func__, en_allmulti ? "enable" : "disable");
1698 goto close_ni;
1699 }
1700
1701 error = DPAA2_CMD_NI_SET_UNI_PROMISC(dev, child, &cmd, en_promisc);
1702 if (error) {
1703 device_printf(dev, "%s: failed to %s unicast promiscuous mode\n",
1704 __func__, en_promisc ? "enable" : "disable");
1705 goto close_ni;
1706 }
1707
1708 (void)DPAA2_CMD_NI_CLOSE(dev, child, &cmd);
1709 (void)DPAA2_CMD_RC_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, rc_token));
1710 return (0);
1711
1712 close_ni:
1713 (void)DPAA2_CMD_NI_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, ni_token));
1714 close_rc:
1715 (void)DPAA2_CMD_RC_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, rc_token));
1716 err_exit:
1717 return (error);
1718 }
1719
1720 static int
dpaa2_ni_setup_sysctls(struct dpaa2_ni_softc * sc)1721 dpaa2_ni_setup_sysctls(struct dpaa2_ni_softc *sc)
1722 {
1723 struct sysctl_ctx_list *ctx;
1724 struct sysctl_oid *node, *node2;
1725 struct sysctl_oid_list *parent, *parent2;
1726 char cbuf[128];
1727 int i;
1728
1729 ctx = device_get_sysctl_ctx(sc->dev);
1730 parent = SYSCTL_CHILDREN(device_get_sysctl_tree(sc->dev));
1731
1732 /* Add DPNI statistics. */
1733 node = SYSCTL_ADD_NODE(ctx, parent, OID_AUTO, "stats",
1734 CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, "DPNI Statistics");
1735 parent = SYSCTL_CHILDREN(node);
1736 for (i = 0; i < DPAA2_NI_STAT_SYSCTLS; ++i) {
1737 SYSCTL_ADD_PROC(ctx, parent, i, dpni_stat_sysctls[i].name,
1738 CTLTYPE_U64 | CTLFLAG_RD, sc, 0, dpaa2_ni_collect_stats,
1739 "IU", dpni_stat_sysctls[i].desc);
1740 }
1741 SYSCTL_ADD_UQUAD(ctx, parent, OID_AUTO, "rx_anomaly_frames",
1742 CTLFLAG_RD, &sc->rx_anomaly_frames,
1743 "Rx frames in the buffers outside of the buffer pools");
1744 SYSCTL_ADD_UQUAD(ctx, parent, OID_AUTO, "rx_single_buf_frames",
1745 CTLFLAG_RD, &sc->rx_single_buf_frames,
1746 "Rx frames in single buffers");
1747 SYSCTL_ADD_UQUAD(ctx, parent, OID_AUTO, "rx_sg_buf_frames",
1748 CTLFLAG_RD, &sc->rx_sg_buf_frames,
1749 "Rx frames in scatter/gather list");
1750 SYSCTL_ADD_UQUAD(ctx, parent, OID_AUTO, "rx_enq_rej_frames",
1751 CTLFLAG_RD, &sc->rx_enq_rej_frames,
1752 "Enqueue rejected by QMan");
1753 SYSCTL_ADD_UQUAD(ctx, parent, OID_AUTO, "rx_ieoi_err_frames",
1754 CTLFLAG_RD, &sc->rx_ieoi_err_frames,
1755 "QMan IEOI error");
1756 SYSCTL_ADD_UQUAD(ctx, parent, OID_AUTO, "tx_single_buf_frames",
1757 CTLFLAG_RD, &sc->tx_single_buf_frames,
1758 "Tx single buffer frames");
1759 SYSCTL_ADD_UQUAD(ctx, parent, OID_AUTO, "tx_sg_frames",
1760 CTLFLAG_RD, &sc->tx_sg_frames,
1761 "Tx S/G frames");
1762
1763 SYSCTL_ADD_PROC(ctx, parent, OID_AUTO, "buf_num",
1764 CTLTYPE_U32 | CTLFLAG_RD, sc, 0, dpaa2_ni_collect_buf_num,
1765 "IU", "number of Rx buffers in the buffer pool");
1766 SYSCTL_ADD_PROC(ctx, parent, OID_AUTO, "buf_free",
1767 CTLTYPE_U32 | CTLFLAG_RD, sc, 0, dpaa2_ni_collect_buf_free,
1768 "IU", "number of free Rx buffers in the buffer pool");
1769
1770 parent = SYSCTL_CHILDREN(device_get_sysctl_tree(sc->dev));
1771
1772 /* Add channels statistics. */
1773 node = SYSCTL_ADD_NODE(ctx, parent, OID_AUTO, "channels",
1774 CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, "DPNI Channels");
1775 parent = SYSCTL_CHILDREN(node);
1776 for (int i = 0; i < sc->chan_n; i++) {
1777 snprintf(cbuf, sizeof(cbuf), "%d", i);
1778
1779 node2 = SYSCTL_ADD_NODE(ctx, parent, OID_AUTO, cbuf,
1780 CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, "DPNI Channel");
1781 parent2 = SYSCTL_CHILDREN(node2);
1782
1783 SYSCTL_ADD_UQUAD(ctx, parent2, OID_AUTO, "tx_frames",
1784 CTLFLAG_RD, &sc->channels[i]->tx_frames,
1785 "Tx frames counter");
1786 SYSCTL_ADD_UQUAD(ctx, parent2, OID_AUTO, "tx_dropped",
1787 CTLFLAG_RD, &sc->channels[i]->tx_dropped,
1788 "Tx dropped counter");
1789 }
1790
1791 return (0);
1792 }
1793
1794 static int
dpaa2_ni_setup_dma(struct dpaa2_ni_softc * sc)1795 dpaa2_ni_setup_dma(struct dpaa2_ni_softc *sc)
1796 {
1797 device_t dev = sc->dev;
1798 int error;
1799
1800 KASSERT((sc->buf_align == BUF_ALIGN) || (sc->buf_align == BUF_ALIGN_V1),
1801 ("unexpected buffer alignment: %d\n", sc->buf_align));
1802
1803 /* DMA tag for Rx distribution key. */
1804 error = bus_dma_tag_create(
1805 bus_get_dma_tag(dev),
1806 PAGE_SIZE, 0, /* alignment, boundary */
1807 BUS_SPACE_MAXADDR, /* low restricted addr */
1808 BUS_SPACE_MAXADDR, /* high restricted addr */
1809 NULL, NULL, /* filter, filterarg */
1810 DPAA2_CLASSIFIER_DMA_SIZE, 1, /* maxsize, nsegments */
1811 DPAA2_CLASSIFIER_DMA_SIZE, 0, /* maxsegsize, flags */
1812 NULL, NULL, /* lockfunc, lockarg */
1813 &sc->rxd_dmat);
1814 if (error) {
1815 device_printf(dev, "%s: failed to create DMA tag for Rx "
1816 "distribution key\n", __func__);
1817 return (error);
1818 }
1819
1820 error = bus_dma_tag_create(
1821 bus_get_dma_tag(dev),
1822 PAGE_SIZE, 0, /* alignment, boundary */
1823 BUS_SPACE_MAXADDR, /* low restricted addr */
1824 BUS_SPACE_MAXADDR, /* high restricted addr */
1825 NULL, NULL, /* filter, filterarg */
1826 ETH_QOS_KCFG_BUF_SIZE, 1, /* maxsize, nsegments */
1827 ETH_QOS_KCFG_BUF_SIZE, 0, /* maxsegsize, flags */
1828 NULL, NULL, /* lockfunc, lockarg */
1829 &sc->qos_dmat);
1830 if (error) {
1831 device_printf(dev, "%s: failed to create DMA tag for QoS key\n",
1832 __func__);
1833 return (error);
1834 }
1835
1836 return (0);
1837 }
1838
1839 /**
1840 * @brief Configure buffer layouts of the different DPNI queues.
1841 */
1842 static int
dpaa2_ni_set_buf_layout(device_t dev)1843 dpaa2_ni_set_buf_layout(device_t dev)
1844 {
1845 device_t pdev = device_get_parent(dev);
1846 device_t child = dev;
1847 struct dpaa2_devinfo *rcinfo = device_get_ivars(pdev);
1848 struct dpaa2_devinfo *dinfo = device_get_ivars(dev);
1849 struct dpaa2_ni_softc *sc = device_get_softc(dev);
1850 struct dpaa2_ni_buf_layout buf_layout = {0};
1851 struct dpaa2_cmd cmd;
1852 uint16_t rc_token, ni_token;
1853 int error;
1854
1855 DPAA2_CMD_INIT(&cmd);
1856
1857 error = DPAA2_CMD_RC_OPEN(dev, child, &cmd, rcinfo->id, &rc_token);
1858 if (error) {
1859 device_printf(dev, "%s: failed to open resource container: "
1860 "id=%d, error=%d\n", __func__, rcinfo->id, error);
1861 goto err_exit;
1862 }
1863 error = DPAA2_CMD_NI_OPEN(dev, child, &cmd, dinfo->id, &ni_token);
1864 if (error) {
1865 device_printf(sc->dev, "%s: failed to open DPMAC: id=%d, "
1866 "error=%d\n", __func__, dinfo->id, error);
1867 goto close_rc;
1868 }
1869
1870 /*
1871 * Select Rx/Tx buffer alignment. It's necessary to ensure that the
1872 * buffer size seen by WRIOP is a multiple of 64 or 256 bytes depending
1873 * on the WRIOP version.
1874 */
1875 sc->buf_align = (sc->attr.wriop_ver == WRIOP_VERSION(0, 0, 0) ||
1876 sc->attr.wriop_ver == WRIOP_VERSION(1, 0, 0))
1877 ? BUF_ALIGN_V1 : BUF_ALIGN;
1878
1879 /*
1880 * We need to ensure that the buffer size seen by WRIOP is a multiple
1881 * of 64 or 256 bytes depending on the WRIOP version.
1882 */
1883 sc->buf_sz = ALIGN_DOWN(DPAA2_RX_BUF_SIZE, sc->buf_align);
1884
1885 if (bootverbose) {
1886 device_printf(dev, "Rx/Tx buffers: size=%d, alignment=%d\n",
1887 sc->buf_sz, sc->buf_align);
1888 }
1889
1890 /*
1891 * Frame Descriptor Tx buffer layout
1892 *
1893 * ADDR -> |---------------------|
1894 * | SW FRAME ANNOTATION | BUF_SWA_SIZE bytes
1895 * |---------------------|
1896 * | HW FRAME ANNOTATION | BUF_TX_HWA_SIZE bytes
1897 * |---------------------|
1898 * | DATA HEADROOM |
1899 * ADDR + OFFSET -> |---------------------|
1900 * | |
1901 * | |
1902 * | FRAME DATA |
1903 * | |
1904 * | |
1905 * |---------------------|
1906 * | DATA TAILROOM |
1907 * |---------------------|
1908 *
1909 * NOTE: It's for a single buffer frame only.
1910 */
1911 buf_layout.queue_type = DPAA2_NI_QUEUE_TX;
1912 buf_layout.pd_size = BUF_SWA_SIZE;
1913 buf_layout.pass_timestamp = true;
1914 buf_layout.pass_frame_status = true;
1915 buf_layout.options =
1916 BUF_LOPT_PRIV_DATA_SZ |
1917 BUF_LOPT_TIMESTAMP | /* requires 128 bytes in HWA */
1918 BUF_LOPT_FRAME_STATUS;
1919 error = DPAA2_CMD_NI_SET_BUF_LAYOUT(dev, child, &cmd, &buf_layout);
1920 if (error) {
1921 device_printf(dev, "%s: failed to set Tx buffer layout\n",
1922 __func__);
1923 goto close_ni;
1924 }
1925
1926 /* Tx-confirmation buffer layout */
1927 buf_layout.queue_type = DPAA2_NI_QUEUE_TX_CONF;
1928 buf_layout.options =
1929 BUF_LOPT_TIMESTAMP |
1930 BUF_LOPT_FRAME_STATUS;
1931 error = DPAA2_CMD_NI_SET_BUF_LAYOUT(dev, child, &cmd, &buf_layout);
1932 if (error) {
1933 device_printf(dev, "%s: failed to set TxConf buffer layout\n",
1934 __func__);
1935 goto close_ni;
1936 }
1937
1938 /*
1939 * Driver should reserve the amount of space indicated by this command
1940 * as headroom in all Tx frames.
1941 */
1942 error = DPAA2_CMD_NI_GET_TX_DATA_OFF(dev, child, &cmd, &sc->tx_data_off);
1943 if (error) {
1944 device_printf(dev, "%s: failed to obtain Tx data offset\n",
1945 __func__);
1946 goto close_ni;
1947 }
1948
1949 if (bootverbose) {
1950 device_printf(dev, "Tx data offset=%d\n", sc->tx_data_off);
1951 }
1952 if ((sc->tx_data_off % 64) != 0) {
1953 device_printf(dev, "Tx data offset (%d) is not a multiplication "
1954 "of 64 bytes\n", sc->tx_data_off);
1955 }
1956
1957 /*
1958 * Frame Descriptor Rx buffer layout
1959 *
1960 * ADDR -> |---------------------|
1961 * | SW FRAME ANNOTATION | BUF_SWA_SIZE bytes
1962 * |---------------------|
1963 * | HW FRAME ANNOTATION | BUF_RX_HWA_SIZE bytes
1964 * |---------------------|
1965 * | DATA HEADROOM | OFFSET-BUF_RX_HWA_SIZE
1966 * ADDR + OFFSET -> |---------------------|
1967 * | |
1968 * | |
1969 * | FRAME DATA |
1970 * | |
1971 * | |
1972 * |---------------------|
1973 * | DATA TAILROOM | 0 bytes
1974 * |---------------------|
1975 *
1976 * NOTE: It's for a single buffer frame only.
1977 */
1978 buf_layout.queue_type = DPAA2_NI_QUEUE_RX;
1979 buf_layout.pd_size = BUF_SWA_SIZE;
1980 buf_layout.fd_align = sc->buf_align;
1981 buf_layout.head_size = sc->tx_data_off - BUF_RX_HWA_SIZE - BUF_SWA_SIZE;
1982 buf_layout.tail_size = 0;
1983 buf_layout.pass_frame_status = true;
1984 buf_layout.pass_parser_result = true;
1985 buf_layout.pass_timestamp = true;
1986 buf_layout.options =
1987 BUF_LOPT_PRIV_DATA_SZ |
1988 BUF_LOPT_DATA_ALIGN |
1989 BUF_LOPT_DATA_HEAD_ROOM |
1990 BUF_LOPT_DATA_TAIL_ROOM |
1991 BUF_LOPT_FRAME_STATUS |
1992 BUF_LOPT_PARSER_RESULT |
1993 BUF_LOPT_TIMESTAMP;
1994 error = DPAA2_CMD_NI_SET_BUF_LAYOUT(dev, child, &cmd, &buf_layout);
1995 if (error) {
1996 device_printf(dev, "%s: failed to set Rx buffer layout\n",
1997 __func__);
1998 goto close_ni;
1999 }
2000
2001 error = 0;
2002 close_ni:
2003 (void)DPAA2_CMD_NI_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, ni_token));
2004 close_rc:
2005 (void)DPAA2_CMD_RC_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, rc_token));
2006 err_exit:
2007 return (error);
2008 }
2009
2010 /**
2011 * @brief Enable Rx/Tx pause frames.
2012 *
2013 * NOTE: DPNI stops sending when a pause frame is received (Rx frame) or DPNI
2014 * itself generates pause frames (Tx frame).
2015 */
2016 static int
dpaa2_ni_set_pause_frame(device_t dev)2017 dpaa2_ni_set_pause_frame(device_t dev)
2018 {
2019 device_t pdev = device_get_parent(dev);
2020 device_t child = dev;
2021 struct dpaa2_devinfo *rcinfo = device_get_ivars(pdev);
2022 struct dpaa2_devinfo *dinfo = device_get_ivars(dev);
2023 struct dpaa2_ni_softc *sc = device_get_softc(dev);
2024 struct dpaa2_ni_link_cfg link_cfg = {0};
2025 struct dpaa2_cmd cmd;
2026 uint16_t rc_token, ni_token;
2027 int error;
2028
2029 DPAA2_CMD_INIT(&cmd);
2030
2031 error = DPAA2_CMD_RC_OPEN(dev, child, &cmd, rcinfo->id, &rc_token);
2032 if (error) {
2033 device_printf(dev, "%s: failed to open resource container: "
2034 "id=%d, error=%d\n", __func__, rcinfo->id, error);
2035 goto err_exit;
2036 }
2037 error = DPAA2_CMD_NI_OPEN(dev, child, &cmd, dinfo->id, &ni_token);
2038 if (error) {
2039 device_printf(sc->dev, "%s: failed to open DPMAC: id=%d, "
2040 "error=%d\n", __func__, dinfo->id, error);
2041 goto close_rc;
2042 }
2043
2044 error = DPAA2_CMD_NI_GET_LINK_CFG(dev, child, &cmd, &link_cfg);
2045 if (error) {
2046 device_printf(dev, "%s: failed to obtain link configuration: "
2047 "error=%d\n", __func__, error);
2048 goto close_ni;
2049 }
2050
2051 /* Enable both Rx and Tx pause frames by default. */
2052 link_cfg.options |= DPAA2_NI_LINK_OPT_PAUSE;
2053 link_cfg.options &= ~DPAA2_NI_LINK_OPT_ASYM_PAUSE;
2054
2055 error = DPAA2_CMD_NI_SET_LINK_CFG(dev, child, &cmd, &link_cfg);
2056 if (error) {
2057 device_printf(dev, "%s: failed to set link configuration: "
2058 "error=%d\n", __func__, error);
2059 goto close_ni;
2060 }
2061
2062 sc->link_options = link_cfg.options;
2063 error = 0;
2064 close_ni:
2065 (void)DPAA2_CMD_NI_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, ni_token));
2066 close_rc:
2067 (void)DPAA2_CMD_RC_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, rc_token));
2068 err_exit:
2069 return (error);
2070 }
2071
2072 /**
2073 * @brief Configure QoS table to determine the traffic class for the received
2074 * frame.
2075 */
2076 static int
dpaa2_ni_set_qos_table(device_t dev)2077 dpaa2_ni_set_qos_table(device_t dev)
2078 {
2079 device_t pdev = device_get_parent(dev);
2080 device_t child = dev;
2081 struct dpaa2_devinfo *rcinfo = device_get_ivars(pdev);
2082 struct dpaa2_devinfo *dinfo = device_get_ivars(dev);
2083 struct dpaa2_ni_softc *sc = device_get_softc(dev);
2084 struct dpaa2_ni_qos_table tbl;
2085 struct dpaa2_buf *buf = &sc->qos_kcfg;
2086 struct dpaa2_cmd cmd;
2087 uint16_t rc_token, ni_token;
2088 int error;
2089
2090 if (sc->attr.num.rx_tcs == 1 ||
2091 !(sc->attr.options & DPNI_OPT_HAS_KEY_MASKING)) {
2092 if (bootverbose) {
2093 device_printf(dev, "Ingress traffic classification is "
2094 "not supported\n");
2095 }
2096 return (0);
2097 }
2098
2099 /*
2100 * Allocate a buffer visible to the device to hold the QoS table key
2101 * configuration.
2102 */
2103
2104 if (__predict_true(buf->dmat == NULL)) {
2105 buf->dmat = sc->qos_dmat;
2106 }
2107
2108 error = bus_dmamem_alloc(buf->dmat, (void **)&buf->vaddr,
2109 BUS_DMA_ZERO | BUS_DMA_COHERENT, &buf->dmap);
2110 if (error) {
2111 device_printf(dev, "%s: failed to allocate a buffer for QoS key "
2112 "configuration\n", __func__);
2113 goto err_exit;
2114 }
2115
2116 error = bus_dmamap_load(buf->dmat, buf->dmap, buf->vaddr,
2117 ETH_QOS_KCFG_BUF_SIZE, dpaa2_dmamap_oneseg_cb, &buf->paddr,
2118 BUS_DMA_NOWAIT);
2119 if (error) {
2120 device_printf(dev, "%s: failed to map QoS key configuration "
2121 "buffer into bus space\n", __func__);
2122 goto err_exit;
2123 }
2124
2125 DPAA2_CMD_INIT(&cmd);
2126
2127 error = DPAA2_CMD_RC_OPEN(dev, child, &cmd, rcinfo->id, &rc_token);
2128 if (error) {
2129 device_printf(dev, "%s: failed to open resource container: "
2130 "id=%d, error=%d\n", __func__, rcinfo->id, error);
2131 goto err_exit;
2132 }
2133 error = DPAA2_CMD_NI_OPEN(dev, child, &cmd, dinfo->id, &ni_token);
2134 if (error) {
2135 device_printf(sc->dev, "%s: failed to open DPMAC: id=%d, "
2136 "error=%d\n", __func__, dinfo->id, error);
2137 goto close_rc;
2138 }
2139
2140 tbl.default_tc = 0;
2141 tbl.discard_on_miss = false;
2142 tbl.keep_entries = false;
2143 tbl.kcfg_busaddr = buf->paddr;
2144 error = DPAA2_CMD_NI_SET_QOS_TABLE(dev, child, &cmd, &tbl);
2145 if (error) {
2146 device_printf(dev, "%s: failed to set QoS table\n", __func__);
2147 goto close_ni;
2148 }
2149
2150 error = DPAA2_CMD_NI_CLEAR_QOS_TABLE(dev, child, &cmd);
2151 if (error) {
2152 device_printf(dev, "%s: failed to clear QoS table\n", __func__);
2153 goto close_ni;
2154 }
2155
2156 error = 0;
2157 close_ni:
2158 (void)DPAA2_CMD_NI_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, ni_token));
2159 close_rc:
2160 (void)DPAA2_CMD_RC_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, rc_token));
2161 err_exit:
2162 return (error);
2163 }
2164
2165 static int
dpaa2_ni_set_mac_addr(device_t dev)2166 dpaa2_ni_set_mac_addr(device_t dev)
2167 {
2168 device_t pdev = device_get_parent(dev);
2169 device_t child = dev;
2170 struct dpaa2_ni_softc *sc = device_get_softc(dev);
2171 if_t ifp = sc->ifp;
2172 struct dpaa2_devinfo *rcinfo = device_get_ivars(pdev);
2173 struct dpaa2_devinfo *dinfo = device_get_ivars(dev);
2174 struct dpaa2_cmd cmd;
2175 struct ether_addr rnd_mac_addr;
2176 uint16_t rc_token, ni_token;
2177 uint8_t mac_addr[ETHER_ADDR_LEN];
2178 uint8_t dpni_mac_addr[ETHER_ADDR_LEN];
2179 int error;
2180
2181 DPAA2_CMD_INIT(&cmd);
2182
2183 error = DPAA2_CMD_RC_OPEN(dev, child, &cmd, rcinfo->id, &rc_token);
2184 if (error) {
2185 device_printf(dev, "%s: failed to open resource container: "
2186 "id=%d, error=%d\n", __func__, rcinfo->id, error);
2187 goto err_exit;
2188 }
2189 error = DPAA2_CMD_NI_OPEN(dev, child, &cmd, dinfo->id, &ni_token);
2190 if (error) {
2191 device_printf(sc->dev, "%s: failed to open DPMAC: id=%d, "
2192 "error=%d\n", __func__, dinfo->id, error);
2193 goto close_rc;
2194 }
2195
2196 /*
2197 * Get the MAC address associated with the physical port, if the DPNI is
2198 * connected to a DPMAC directly associated with one of the physical
2199 * ports.
2200 */
2201 error = DPAA2_CMD_NI_GET_PORT_MAC_ADDR(dev, child, &cmd, mac_addr);
2202 if (error) {
2203 device_printf(dev, "%s: failed to obtain the MAC address "
2204 "associated with the physical port\n", __func__);
2205 goto close_ni;
2206 }
2207
2208 /* Get primary MAC address from the DPNI attributes. */
2209 error = DPAA2_CMD_NI_GET_PRIM_MAC_ADDR(dev, child, &cmd, dpni_mac_addr);
2210 if (error) {
2211 device_printf(dev, "%s: failed to obtain primary MAC address\n",
2212 __func__);
2213 goto close_ni;
2214 }
2215
2216 if (!ETHER_IS_ZERO(mac_addr)) {
2217 /* Set MAC address of the physical port as DPNI's primary one. */
2218 error = DPAA2_CMD_NI_SET_PRIM_MAC_ADDR(dev, child, &cmd,
2219 mac_addr);
2220 if (error) {
2221 device_printf(dev, "%s: failed to set primary MAC "
2222 "address\n", __func__);
2223 goto close_ni;
2224 }
2225 for (int i = 0; i < ETHER_ADDR_LEN; i++) {
2226 sc->mac.addr[i] = mac_addr[i];
2227 }
2228 } else if (ETHER_IS_ZERO(dpni_mac_addr)) {
2229 /* Generate random MAC address as DPNI's primary one. */
2230 ether_gen_addr(ifp, &rnd_mac_addr);
2231 for (int i = 0; i < ETHER_ADDR_LEN; i++) {
2232 mac_addr[i] = rnd_mac_addr.octet[i];
2233 }
2234
2235 error = DPAA2_CMD_NI_SET_PRIM_MAC_ADDR(dev, child, &cmd,
2236 mac_addr);
2237 if (error) {
2238 device_printf(dev, "%s: failed to set random primary "
2239 "MAC address\n", __func__);
2240 goto close_ni;
2241 }
2242 for (int i = 0; i < ETHER_ADDR_LEN; i++) {
2243 sc->mac.addr[i] = mac_addr[i];
2244 }
2245 } else {
2246 for (int i = 0; i < ETHER_ADDR_LEN; i++) {
2247 sc->mac.addr[i] = dpni_mac_addr[i];
2248 }
2249 }
2250
2251 error = 0;
2252 close_ni:
2253 (void)DPAA2_CMD_NI_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, ni_token));
2254 close_rc:
2255 (void)DPAA2_CMD_RC_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, rc_token));
2256 err_exit:
2257 return (error);
2258 }
2259
2260 static void
dpaa2_ni_miibus_statchg(device_t dev)2261 dpaa2_ni_miibus_statchg(device_t dev)
2262 {
2263 device_t pdev = device_get_parent(dev);
2264 device_t child = dev;
2265 struct dpaa2_ni_softc *sc = device_get_softc(dev);
2266 struct dpaa2_mac_link_state mac_link = { 0 };
2267 struct dpaa2_devinfo *rcinfo = device_get_ivars(pdev);
2268 struct dpaa2_cmd cmd;
2269 uint16_t rc_token, mac_token;
2270 int error, link_state;
2271
2272 if (sc->fixed_link || sc->mii == NULL) {
2273 return;
2274 }
2275 if ((if_getdrvflags(sc->ifp) & IFF_DRV_RUNNING) == 0) {
2276 /*
2277 * We will receive calls and adjust the changes but
2278 * not have setup everything (called before dpaa2_ni_init()
2279 * really). This will then setup the link and internal
2280 * sc->link_state and not trigger the update once needed,
2281 * so basically dpmac never knows about it.
2282 */
2283 return;
2284 }
2285
2286 /*
2287 * Note: ifp link state will only be changed AFTER we are called so we
2288 * cannot rely on ifp->if_linkstate here.
2289 */
2290 if (sc->mii->mii_media_status & IFM_AVALID) {
2291 if (sc->mii->mii_media_status & IFM_ACTIVE) {
2292 link_state = LINK_STATE_UP;
2293 } else {
2294 link_state = LINK_STATE_DOWN;
2295 }
2296 } else {
2297 link_state = LINK_STATE_UNKNOWN;
2298 }
2299
2300 if (link_state != sc->link_state) {
2301 sc->link_state = link_state;
2302
2303 DPAA2_CMD_INIT(&cmd);
2304
2305 error = DPAA2_CMD_RC_OPEN(dev, child, &cmd, rcinfo->id,
2306 &rc_token);
2307 if (error) {
2308 device_printf(dev, "%s: failed to open resource "
2309 "container: id=%d, error=%d\n", __func__, rcinfo->id,
2310 error);
2311 goto err_exit;
2312 }
2313 error = DPAA2_CMD_MAC_OPEN(dev, child, &cmd, sc->mac.dpmac_id,
2314 &mac_token);
2315 if (error) {
2316 device_printf(sc->dev, "%s: failed to open DPMAC: "
2317 "id=%d, error=%d\n", __func__, sc->mac.dpmac_id,
2318 error);
2319 goto close_rc;
2320 }
2321
2322 if (link_state == LINK_STATE_UP ||
2323 link_state == LINK_STATE_DOWN) {
2324 /* Update DPMAC link state. */
2325 mac_link.supported = sc->mii->mii_media.ifm_media;
2326 mac_link.advert = sc->mii->mii_media.ifm_media;
2327 mac_link.rate = 1000; /* TODO: Where to get from? */ /* ifmedia_baudrate? */
2328 mac_link.options =
2329 DPAA2_MAC_LINK_OPT_AUTONEG |
2330 DPAA2_MAC_LINK_OPT_PAUSE;
2331 mac_link.up = (link_state == LINK_STATE_UP) ? true : false;
2332 mac_link.state_valid = true;
2333
2334 /* Inform DPMAC about link state. */
2335 error = DPAA2_CMD_MAC_SET_LINK_STATE(dev, child, &cmd,
2336 &mac_link);
2337 if (error) {
2338 device_printf(sc->dev, "%s: failed to set DPMAC "
2339 "link state: id=%d, error=%d\n", __func__,
2340 sc->mac.dpmac_id, error);
2341 }
2342 }
2343 (void)DPAA2_CMD_MAC_CLOSE(dev, child, &cmd);
2344 (void)DPAA2_CMD_RC_CLOSE(dev, child, DPAA2_CMD_TK(&cmd,
2345 rc_token));
2346 }
2347
2348 return;
2349
2350 close_rc:
2351 (void)DPAA2_CMD_RC_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, rc_token));
2352 err_exit:
2353 return;
2354 }
2355
2356 /**
2357 * @brief Callback function to process media change request.
2358 */
2359 static int
dpaa2_ni_media_change_locked(struct dpaa2_ni_softc * sc)2360 dpaa2_ni_media_change_locked(struct dpaa2_ni_softc *sc)
2361 {
2362
2363 DPNI_LOCK_ASSERT(sc);
2364 if (sc->mii) {
2365 mii_mediachg(sc->mii);
2366 sc->media_status = sc->mii->mii_media.ifm_media;
2367 } else if (sc->fixed_link) {
2368 if_printf(sc->ifp, "%s: can't change media in fixed mode\n",
2369 __func__);
2370 }
2371
2372 return (0);
2373 }
2374
2375 static int
dpaa2_ni_media_change(if_t ifp)2376 dpaa2_ni_media_change(if_t ifp)
2377 {
2378 struct dpaa2_ni_softc *sc = if_getsoftc(ifp);
2379 int error;
2380
2381 DPNI_LOCK(sc);
2382 error = dpaa2_ni_media_change_locked(sc);
2383 DPNI_UNLOCK(sc);
2384 return (error);
2385 }
2386
2387 /**
2388 * @brief Callback function to process media status request.
2389 */
2390 static void
dpaa2_ni_media_status(if_t ifp,struct ifmediareq * ifmr)2391 dpaa2_ni_media_status(if_t ifp, struct ifmediareq *ifmr)
2392 {
2393 struct dpaa2_ni_softc *sc = if_getsoftc(ifp);
2394
2395 DPNI_LOCK(sc);
2396 if (sc->mii) {
2397 mii_pollstat(sc->mii);
2398 ifmr->ifm_active = sc->mii->mii_media_active;
2399 ifmr->ifm_status = sc->mii->mii_media_status;
2400 }
2401 DPNI_UNLOCK(sc);
2402 }
2403
2404 /**
2405 * @brief Callout function to check and update media status.
2406 */
2407 static void
dpaa2_ni_media_tick(void * arg)2408 dpaa2_ni_media_tick(void *arg)
2409 {
2410 struct dpaa2_ni_softc *sc = (struct dpaa2_ni_softc *) arg;
2411
2412 /* Check for media type change */
2413 if (sc->mii) {
2414 mii_tick(sc->mii);
2415 if (sc->media_status != sc->mii->mii_media.ifm_media) {
2416 printf("%s: media type changed (ifm_media=%x)\n",
2417 __func__, sc->mii->mii_media.ifm_media);
2418 dpaa2_ni_media_change(sc->ifp);
2419 }
2420 }
2421
2422 /* Schedule another timeout one second from now */
2423 callout_reset(&sc->mii_callout, hz, dpaa2_ni_media_tick, sc);
2424 }
2425
2426 static void
dpaa2_ni_init(void * arg)2427 dpaa2_ni_init(void *arg)
2428 {
2429 struct dpaa2_ni_softc *sc = (struct dpaa2_ni_softc *) arg;
2430 if_t ifp = sc->ifp;
2431 device_t pdev = device_get_parent(sc->dev);
2432 device_t dev = sc->dev;
2433 device_t child = dev;
2434 struct dpaa2_devinfo *rcinfo = device_get_ivars(pdev);
2435 struct dpaa2_devinfo *dinfo = device_get_ivars(dev);
2436 struct dpaa2_cmd cmd;
2437 uint16_t rc_token, ni_token;
2438 int error;
2439
2440 DPNI_LOCK(sc);
2441 if ((if_getdrvflags(ifp) & IFF_DRV_RUNNING) != 0) {
2442 DPNI_UNLOCK(sc);
2443 return;
2444 }
2445 DPNI_UNLOCK(sc);
2446
2447 DPAA2_CMD_INIT(&cmd);
2448
2449 error = DPAA2_CMD_RC_OPEN(dev, child, &cmd, rcinfo->id, &rc_token);
2450 if (error) {
2451 device_printf(dev, "%s: failed to open resource container: "
2452 "id=%d, error=%d\n", __func__, rcinfo->id, error);
2453 goto err_exit;
2454 }
2455 error = DPAA2_CMD_NI_OPEN(dev, child, &cmd, dinfo->id, &ni_token);
2456 if (error) {
2457 device_printf(dev, "%s: failed to open network interface: "
2458 "id=%d, error=%d\n", __func__, dinfo->id, error);
2459 goto close_rc;
2460 }
2461
2462 error = DPAA2_CMD_NI_ENABLE(dev, child, &cmd);
2463 if (error) {
2464 device_printf(dev, "%s: failed to enable DPNI: error=%d\n",
2465 __func__, error);
2466 }
2467
2468 DPNI_LOCK(sc);
2469 /* Announce we are up and running and can queue packets. */
2470 if_setdrvflagbits(ifp, IFF_DRV_RUNNING, IFF_DRV_OACTIVE);
2471
2472 if (sc->mii) {
2473 /*
2474 * mii_mediachg() will trigger a call into
2475 * dpaa2_ni_miibus_statchg() to setup link state.
2476 */
2477 dpaa2_ni_media_change_locked(sc);
2478 }
2479 callout_reset(&sc->mii_callout, hz, dpaa2_ni_media_tick, sc);
2480
2481 DPNI_UNLOCK(sc);
2482
2483 (void)DPAA2_CMD_NI_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, ni_token));
2484 (void)DPAA2_CMD_RC_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, rc_token));
2485 return;
2486
2487 close_rc:
2488 (void)DPAA2_CMD_RC_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, rc_token));
2489 err_exit:
2490 return;
2491 }
2492
2493 static int
dpaa2_ni_transmit(if_t ifp,struct mbuf * m)2494 dpaa2_ni_transmit(if_t ifp, struct mbuf *m)
2495 {
2496 struct dpaa2_ni_softc *sc = if_getsoftc(ifp);
2497 struct dpaa2_channel *ch;
2498 uint32_t fqid;
2499 bool found = false;
2500 int chidx = 0, error;
2501
2502 if (__predict_false(!(if_getdrvflags(ifp) & IFF_DRV_RUNNING))) {
2503 return (0);
2504 }
2505
2506 if (M_HASHTYPE_GET(m) != M_HASHTYPE_NONE) {
2507 fqid = m->m_pkthdr.flowid;
2508 for (int i = 0; i < sc->chan_n; i++) {
2509 ch = sc->channels[i];
2510 for (int j = 0; j < ch->rxq_n; j++) {
2511 if (fqid == ch->rx_queues[j].fqid) {
2512 chidx = ch->flowid;
2513 found = true;
2514 break;
2515 }
2516 }
2517 if (found) {
2518 break;
2519 }
2520 }
2521 }
2522
2523 ch = sc->channels[chidx];
2524 error = buf_ring_enqueue(ch->xmit_br, m);
2525 if (__predict_false(error != 0)) {
2526 m_freem(m);
2527 } else {
2528 taskqueue_enqueue(ch->cleanup_tq, &ch->cleanup_task);
2529 }
2530
2531 return (error);
2532 }
2533
2534 static void
dpaa2_ni_qflush(if_t ifp)2535 dpaa2_ni_qflush(if_t ifp)
2536 {
2537 /* TODO: Find a way to drain Tx queues in QBMan. */
2538 if_qflush(ifp);
2539 }
2540
2541 static int
dpaa2_ni_ioctl(if_t ifp,u_long c,caddr_t data)2542 dpaa2_ni_ioctl(if_t ifp, u_long c, caddr_t data)
2543 {
2544 struct dpaa2_ni_softc *sc = if_getsoftc(ifp);
2545 struct ifreq *ifr = (struct ifreq *) data;
2546 device_t pdev = device_get_parent(sc->dev);
2547 device_t dev = sc->dev;
2548 device_t child = dev;
2549 struct dpaa2_devinfo *rcinfo = device_get_ivars(pdev);
2550 struct dpaa2_devinfo *dinfo = device_get_ivars(dev);
2551 struct dpaa2_cmd cmd;
2552 uint32_t changed = 0;
2553 uint16_t rc_token, ni_token;
2554 int mtu, error, rc = 0;
2555
2556 DPAA2_CMD_INIT(&cmd);
2557
2558 error = DPAA2_CMD_RC_OPEN(dev, child, &cmd, rcinfo->id, &rc_token);
2559 if (error) {
2560 device_printf(dev, "%s: failed to open resource container: "
2561 "id=%d, error=%d\n", __func__, rcinfo->id, error);
2562 goto err_exit;
2563 }
2564 error = DPAA2_CMD_NI_OPEN(dev, child, &cmd, dinfo->id, &ni_token);
2565 if (error) {
2566 device_printf(dev, "%s: failed to open network interface: "
2567 "id=%d, error=%d\n", __func__, dinfo->id, error);
2568 goto close_rc;
2569 }
2570
2571 switch (c) {
2572 case SIOCSIFMTU:
2573 DPNI_LOCK(sc);
2574 mtu = ifr->ifr_mtu;
2575 if (mtu < ETHERMIN || mtu > ETHERMTU_JUMBO) {
2576 DPNI_UNLOCK(sc);
2577 error = EINVAL;
2578 goto close_ni;
2579 }
2580 if_setmtu(ifp, mtu);
2581 DPNI_UNLOCK(sc);
2582
2583 /* Update maximum frame length. */
2584 error = DPAA2_CMD_NI_SET_MFL(dev, child, &cmd,
2585 mtu + ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN);
2586 if (error) {
2587 device_printf(dev, "%s: failed to update maximum frame "
2588 "length: error=%d\n", __func__, error);
2589 goto close_ni;
2590 }
2591 break;
2592 case SIOCSIFCAP:
2593 changed = if_getcapenable(ifp) ^ ifr->ifr_reqcap;
2594 if (changed & IFCAP_HWCSUM) {
2595 if ((ifr->ifr_reqcap & changed) & IFCAP_HWCSUM) {
2596 if_setcapenablebit(ifp, IFCAP_HWCSUM, 0);
2597 } else {
2598 if_setcapenablebit(ifp, 0, IFCAP_HWCSUM);
2599 }
2600 }
2601 rc = dpaa2_ni_setup_if_caps(sc);
2602 if (rc) {
2603 printf("%s: failed to update iface capabilities: "
2604 "error=%d\n", __func__, rc);
2605 rc = ENXIO;
2606 }
2607 break;
2608 case SIOCSIFFLAGS:
2609 DPNI_LOCK(sc);
2610 if (if_getflags(ifp) & IFF_UP) {
2611 if (if_getdrvflags(ifp) & IFF_DRV_RUNNING) {
2612 changed = if_getflags(ifp) ^ sc->if_flags;
2613 if (changed & IFF_PROMISC ||
2614 changed & IFF_ALLMULTI) {
2615 rc = dpaa2_ni_setup_if_flags(sc);
2616 }
2617 } else {
2618 DPNI_UNLOCK(sc);
2619 dpaa2_ni_init(sc);
2620 DPNI_LOCK(sc);
2621 }
2622 } else if (if_getdrvflags(ifp) & IFF_DRV_RUNNING) {
2623 /* FIXME: Disable DPNI. See dpaa2_ni_init(). */
2624 }
2625
2626 sc->if_flags = if_getflags(ifp);
2627 DPNI_UNLOCK(sc);
2628 break;
2629 case SIOCADDMULTI:
2630 case SIOCDELMULTI:
2631 DPNI_LOCK(sc);
2632 if (if_getdrvflags(ifp) & IFF_DRV_RUNNING) {
2633 DPNI_UNLOCK(sc);
2634 rc = dpaa2_ni_update_mac_filters(ifp);
2635 if (rc) {
2636 device_printf(dev, "%s: failed to update MAC "
2637 "filters: error=%d\n", __func__, rc);
2638 }
2639 DPNI_LOCK(sc);
2640 }
2641 DPNI_UNLOCK(sc);
2642 break;
2643 case SIOCGIFMEDIA:
2644 case SIOCSIFMEDIA:
2645 if (sc->mii)
2646 rc = ifmedia_ioctl(ifp, ifr, &sc->mii->mii_media, c);
2647 else if(sc->fixed_link) {
2648 rc = ifmedia_ioctl(ifp, ifr, &sc->fixed_ifmedia, c);
2649 }
2650 break;
2651 default:
2652 rc = ether_ioctl(ifp, c, data);
2653 break;
2654 }
2655
2656 (void)DPAA2_CMD_NI_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, ni_token));
2657 (void)DPAA2_CMD_RC_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, rc_token));
2658 return (rc);
2659
2660 close_ni:
2661 (void)DPAA2_CMD_NI_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, ni_token));
2662 close_rc:
2663 (void)DPAA2_CMD_RC_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, rc_token));
2664 err_exit:
2665 return (error);
2666 }
2667
2668 static int
dpaa2_ni_update_mac_filters(if_t ifp)2669 dpaa2_ni_update_mac_filters(if_t ifp)
2670 {
2671 struct dpaa2_ni_softc *sc = if_getsoftc(ifp);
2672 struct dpaa2_ni_mcaddr_ctx ctx;
2673 device_t pdev = device_get_parent(sc->dev);
2674 device_t dev = sc->dev;
2675 device_t child = dev;
2676 struct dpaa2_devinfo *rcinfo = device_get_ivars(pdev);
2677 struct dpaa2_devinfo *dinfo = device_get_ivars(dev);
2678 struct dpaa2_cmd cmd;
2679 uint16_t rc_token, ni_token;
2680 int error;
2681
2682 DPAA2_CMD_INIT(&cmd);
2683
2684 error = DPAA2_CMD_RC_OPEN(dev, child, &cmd, rcinfo->id, &rc_token);
2685 if (error) {
2686 device_printf(dev, "%s: failed to open resource container: "
2687 "id=%d, error=%d\n", __func__, rcinfo->id, error);
2688 goto err_exit;
2689 }
2690 error = DPAA2_CMD_NI_OPEN(dev, child, &cmd, dinfo->id, &ni_token);
2691 if (error) {
2692 device_printf(dev, "%s: failed to open network interface: "
2693 "id=%d, error=%d\n", __func__, dinfo->id, error);
2694 goto close_rc;
2695 }
2696
2697 /* Remove all multicast MAC filters. */
2698 error = DPAA2_CMD_NI_CLEAR_MAC_FILTERS(dev, child, &cmd, false, true);
2699 if (error) {
2700 device_printf(dev, "%s: failed to clear multicast MAC filters: "
2701 "error=%d\n", __func__, error);
2702 goto close_ni;
2703 }
2704
2705 ctx.ifp = ifp;
2706 ctx.error = 0;
2707 ctx.nent = 0;
2708
2709 if_foreach_llmaddr(ifp, dpaa2_ni_add_maddr, &ctx);
2710
2711 error = ctx.error;
2712 close_ni:
2713 (void)DPAA2_CMD_NI_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, ni_token));
2714 close_rc:
2715 (void)DPAA2_CMD_RC_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, rc_token));
2716 err_exit:
2717 return (error);
2718 }
2719
2720 static u_int
dpaa2_ni_add_maddr(void * arg,struct sockaddr_dl * sdl,u_int cnt)2721 dpaa2_ni_add_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt)
2722 {
2723 struct dpaa2_ni_mcaddr_ctx *ctx = arg;
2724 struct dpaa2_ni_softc *sc = if_getsoftc(ctx->ifp);
2725 device_t pdev = device_get_parent(sc->dev);
2726 device_t dev = sc->dev;
2727 device_t child = dev;
2728 struct dpaa2_devinfo *rcinfo = device_get_ivars(pdev);
2729 struct dpaa2_devinfo *dinfo = device_get_ivars(dev);
2730 struct dpaa2_cmd cmd;
2731 uint16_t rc_token, ni_token;
2732 int error;
2733
2734 if (ctx->error != 0) {
2735 return (0);
2736 }
2737
2738 if (ETHER_IS_MULTICAST(LLADDR(sdl))) {
2739 DPAA2_CMD_INIT(&cmd);
2740
2741 error = DPAA2_CMD_RC_OPEN(dev, child, &cmd, rcinfo->id,
2742 &rc_token);
2743 if (error) {
2744 device_printf(dev, "%s: failed to open resource "
2745 "container: id=%d, error=%d\n", __func__, rcinfo->id,
2746 error);
2747 return (0);
2748 }
2749 error = DPAA2_CMD_NI_OPEN(dev, child, &cmd, dinfo->id,
2750 &ni_token);
2751 if (error) {
2752 device_printf(dev, "%s: failed to open network interface: "
2753 "id=%d, error=%d\n", __func__, dinfo->id, error);
2754 (void)DPAA2_CMD_RC_CLOSE(dev, child, DPAA2_CMD_TK(&cmd,
2755 rc_token));
2756 return (0);
2757 }
2758
2759 ctx->error = DPAA2_CMD_NI_ADD_MAC_ADDR(dev, child, &cmd,
2760 LLADDR(sdl));
2761
2762 (void)DPAA2_CMD_NI_CLOSE(dev, child, DPAA2_CMD_TK(&cmd,
2763 ni_token));
2764 (void)DPAA2_CMD_RC_CLOSE(dev, child, DPAA2_CMD_TK(&cmd,
2765 rc_token));
2766
2767 if (ctx->error != 0) {
2768 device_printf(dev, "%s: can't add more then %d MAC "
2769 "addresses, switching to the multicast promiscuous "
2770 "mode\n", __func__, ctx->nent);
2771
2772 /* Enable multicast promiscuous mode. */
2773 DPNI_LOCK(sc);
2774 if_setflagbits(ctx->ifp, IFF_ALLMULTI, 0);
2775 sc->if_flags |= IFF_ALLMULTI;
2776 ctx->error = dpaa2_ni_setup_if_flags(sc);
2777 DPNI_UNLOCK(sc);
2778
2779 return (0);
2780 }
2781 ctx->nent++;
2782 }
2783
2784 return (1);
2785 }
2786
2787 static void
dpaa2_ni_intr(void * arg)2788 dpaa2_ni_intr(void *arg)
2789 {
2790 struct dpaa2_ni_softc *sc = (struct dpaa2_ni_softc *) arg;
2791 device_t pdev = device_get_parent(sc->dev);
2792 device_t dev = sc->dev;
2793 device_t child = dev;
2794 struct dpaa2_devinfo *rcinfo = device_get_ivars(pdev);
2795 struct dpaa2_devinfo *dinfo = device_get_ivars(dev);
2796 struct dpaa2_cmd cmd;
2797 uint32_t status = ~0u; /* clear all IRQ status bits */
2798 uint16_t rc_token, ni_token;
2799 int error;
2800
2801 DPAA2_CMD_INIT(&cmd);
2802
2803 error = DPAA2_CMD_RC_OPEN(dev, child, &cmd, rcinfo->id, &rc_token);
2804 if (error) {
2805 device_printf(dev, "%s: failed to open resource container: "
2806 "id=%d, error=%d\n", __func__, rcinfo->id, error);
2807 goto err_exit;
2808 }
2809 error = DPAA2_CMD_NI_OPEN(dev, child, &cmd, dinfo->id, &ni_token);
2810 if (error) {
2811 device_printf(dev, "%s: failed to open network interface: "
2812 "id=%d, error=%d\n", __func__, dinfo->id, error);
2813 goto close_rc;
2814 }
2815
2816 error = DPAA2_CMD_NI_GET_IRQ_STATUS(dev, child, &cmd, DPNI_IRQ_INDEX,
2817 &status);
2818 if (error) {
2819 device_printf(sc->dev, "%s: failed to obtain IRQ status: "
2820 "error=%d\n", __func__, error);
2821 }
2822
2823 (void)DPAA2_CMD_NI_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, ni_token));
2824 close_rc:
2825 (void)DPAA2_CMD_RC_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, rc_token));
2826 err_exit:
2827 return;
2828 }
2829
2830 /**
2831 * @brief Execute channel's Rx/Tx routines.
2832 *
2833 * NOTE: Should not be re-entrant for the same channel. It is achieved by
2834 * enqueuing the cleanup routine on a single-threaded taskqueue.
2835 */
2836 static void
dpaa2_ni_cleanup_task(void * arg,int count)2837 dpaa2_ni_cleanup_task(void *arg, int count)
2838 {
2839 struct dpaa2_channel *ch = (struct dpaa2_channel *)arg;
2840 struct dpaa2_ni_softc *sc = device_get_softc(ch->ni_dev);
2841 int error, rxc, txc;
2842
2843 for (int i = 0; i < DPAA2_CLEAN_BUDGET; i++) {
2844 rxc = dpaa2_ni_rx_cleanup(ch);
2845 txc = dpaa2_ni_tx_cleanup(ch);
2846
2847 if (__predict_false((if_getdrvflags(sc->ifp) &
2848 IFF_DRV_RUNNING) == 0)) {
2849 return;
2850 }
2851
2852 if ((txc != DPAA2_TX_BUDGET) && (rxc != DPAA2_RX_BUDGET)) {
2853 break;
2854 }
2855 }
2856
2857 /* Re-arm channel to generate CDAN */
2858 error = DPAA2_SWP_CONF_WQ_CHANNEL(ch->io_dev, &ch->ctx);
2859 if (error != 0) {
2860 panic("%s: failed to rearm channel: chan_id=%d, error=%d\n",
2861 __func__, ch->id, error);
2862 }
2863 }
2864
2865 /**
2866 * @brief Poll frames from a specific channel when CDAN is received.
2867 */
2868 static int
dpaa2_ni_rx_cleanup(struct dpaa2_channel * ch)2869 dpaa2_ni_rx_cleanup(struct dpaa2_channel *ch)
2870 {
2871 struct dpaa2_io_softc *iosc = device_get_softc(ch->io_dev);
2872 struct dpaa2_swp *swp = iosc->swp;
2873 struct dpaa2_ni_fq *fq;
2874 struct dpaa2_buf *buf = &ch->store;
2875 int budget = DPAA2_RX_BUDGET;
2876 int error, consumed = 0;
2877
2878 do {
2879 error = dpaa2_swp_pull(swp, ch->id, buf, DPAA2_ETH_STORE_FRAMES);
2880 if (error) {
2881 device_printf(ch->ni_dev, "%s: failed to pull frames: "
2882 "chan_id=%d, error=%d\n", __func__, ch->id, error);
2883 break;
2884 }
2885 error = dpaa2_ni_consume_frames(ch, &fq, &consumed);
2886 if (error == ENOENT || error == EALREADY) {
2887 break;
2888 }
2889 if (error == ETIMEDOUT) {
2890 device_printf(ch->ni_dev, "%s: timeout to consume "
2891 "frames: chan_id=%d\n", __func__, ch->id);
2892 }
2893 } while (--budget);
2894
2895 return (DPAA2_RX_BUDGET - budget);
2896 }
2897
2898 static int
dpaa2_ni_tx_cleanup(struct dpaa2_channel * ch)2899 dpaa2_ni_tx_cleanup(struct dpaa2_channel *ch)
2900 {
2901 struct dpaa2_ni_softc *sc = device_get_softc(ch->ni_dev);
2902 struct dpaa2_ni_tx_ring *tx = &ch->txc_queue.tx_rings[0];
2903 struct mbuf *m = NULL;
2904 int budget = DPAA2_TX_BUDGET;
2905
2906 do {
2907 mtx_assert(&ch->xmit_mtx, MA_NOTOWNED);
2908 mtx_lock(&ch->xmit_mtx);
2909 m = buf_ring_dequeue_sc(ch->xmit_br);
2910 mtx_unlock(&ch->xmit_mtx);
2911
2912 if (__predict_false(m == NULL)) {
2913 /* TODO: Do not give up easily */
2914 break;
2915 } else {
2916 dpaa2_ni_tx(sc, ch, tx, m);
2917 }
2918 } while (--budget);
2919
2920 return (DPAA2_TX_BUDGET - budget);
2921 }
2922
2923 static void
dpaa2_ni_tx(struct dpaa2_ni_softc * sc,struct dpaa2_channel * ch,struct dpaa2_ni_tx_ring * tx,struct mbuf * m)2924 dpaa2_ni_tx(struct dpaa2_ni_softc *sc, struct dpaa2_channel *ch,
2925 struct dpaa2_ni_tx_ring *tx, struct mbuf *m)
2926 {
2927 device_t dev = sc->dev;
2928 struct dpaa2_ni_fq *fq = tx->fq;
2929 struct dpaa2_buf *buf, *sgt;
2930 struct dpaa2_fd fd;
2931 struct mbuf *md;
2932 bus_dma_segment_t segs[DPAA2_TX_SEGLIMIT];
2933 int rc, nsegs;
2934 int error;
2935
2936 mtx_assert(&tx->lock, MA_NOTOWNED);
2937 mtx_lock(&tx->lock);
2938 buf = buf_ring_dequeue_sc(tx->br);
2939 mtx_unlock(&tx->lock);
2940 if (__predict_false(buf == NULL)) {
2941 /* TODO: Do not give up easily */
2942 m_freem(m);
2943 return;
2944 } else {
2945 DPAA2_BUF_ASSERT_TXREADY(buf);
2946 buf->m = m;
2947 sgt = buf->sgt;
2948 }
2949
2950 #if defined(INVARIANTS)
2951 struct dpaa2_ni_tx_ring *btx = (struct dpaa2_ni_tx_ring *)buf->opt;
2952 KASSERT(buf->opt == tx, ("%s: unexpected Tx ring", __func__));
2953 KASSERT(btx->fq->chan == ch, ("%s: unexpected channel", __func__));
2954 #endif /* INVARIANTS */
2955
2956 error = bus_dmamap_load_mbuf_sg(buf->dmat, buf->dmap, m, segs, &nsegs,
2957 BUS_DMA_NOWAIT);
2958 if (__predict_false(error != 0)) {
2959 /* Too many fragments, trying to defragment... */
2960 md = m_collapse(m, M_NOWAIT, DPAA2_TX_SEGLIMIT);
2961 if (md == NULL) {
2962 device_printf(dev, "%s: m_collapse() failed\n", __func__);
2963 fq->chan->tx_dropped++;
2964 goto err;
2965 }
2966
2967 buf->m = m = md;
2968 error = bus_dmamap_load_mbuf_sg(buf->dmat, buf->dmap, m, segs,
2969 &nsegs, BUS_DMA_NOWAIT);
2970 if (__predict_false(error != 0)) {
2971 device_printf(dev, "%s: bus_dmamap_load_mbuf_sg() "
2972 "failed: error=%d\n", __func__, error);
2973 fq->chan->tx_dropped++;
2974 goto err;
2975 }
2976 }
2977
2978 error = dpaa2_ni_build_fd(sc, tx, buf, segs, nsegs, &fd);
2979 if (__predict_false(error != 0)) {
2980 device_printf(dev, "%s: failed to build frame descriptor: "
2981 "error=%d\n", __func__, error);
2982 fq->chan->tx_dropped++;
2983 goto err_unload;
2984 }
2985
2986 /* TODO: Enqueue several frames in a single command */
2987 for (int i = 0; i < DPAA2_NI_ENQUEUE_RETRIES; i++) {
2988 /* TODO: Return error codes instead of # of frames */
2989 rc = DPAA2_SWP_ENQ_MULTIPLE_FQ(fq->chan->io_dev, tx->fqid, &fd, 1);
2990 if (rc == 1) {
2991 break;
2992 }
2993 }
2994
2995 bus_dmamap_sync(buf->dmat, buf->dmap, BUS_DMASYNC_PREWRITE);
2996 bus_dmamap_sync(sgt->dmat, sgt->dmap, BUS_DMASYNC_PREWRITE);
2997
2998 if (rc != 1) {
2999 fq->chan->tx_dropped++;
3000 goto err_unload;
3001 } else {
3002 fq->chan->tx_frames++;
3003 }
3004 return;
3005
3006 err_unload:
3007 bus_dmamap_unload(buf->dmat, buf->dmap);
3008 if (sgt->paddr != 0) {
3009 bus_dmamap_unload(sgt->dmat, sgt->dmap);
3010 }
3011 err:
3012 m_freem(buf->m);
3013 buf_ring_enqueue(tx->br, buf);
3014 }
3015
3016 static int
dpaa2_ni_consume_frames(struct dpaa2_channel * chan,struct dpaa2_ni_fq ** src,uint32_t * consumed)3017 dpaa2_ni_consume_frames(struct dpaa2_channel *chan, struct dpaa2_ni_fq **src,
3018 uint32_t *consumed)
3019 {
3020 struct dpaa2_ni_fq *fq = NULL;
3021 struct dpaa2_dq *dq;
3022 struct dpaa2_fd *fd;
3023 struct dpaa2_ni_rx_ctx ctx = {
3024 .head = NULL,
3025 .tail = NULL,
3026 .cnt = 0,
3027 .last = false
3028 };
3029 int rc, frames = 0;
3030
3031 do {
3032 rc = dpaa2_chan_next_frame(chan, &dq);
3033 if (rc == EINPROGRESS) {
3034 if (dq != NULL && !IS_NULL_RESPONSE(dq->fdr.desc.stat)) {
3035 fd = &dq->fdr.fd;
3036 fq = (struct dpaa2_ni_fq *) dq->fdr.desc.fqd_ctx;
3037
3038 switch (fq->type) {
3039 case DPAA2_NI_QUEUE_RX:
3040 (void)dpaa2_ni_rx(chan, fq, fd, &ctx);
3041 break;
3042 case DPAA2_NI_QUEUE_RX_ERR:
3043 (void)dpaa2_ni_rx_err(chan, fq, fd);
3044 break;
3045 case DPAA2_NI_QUEUE_TX_CONF:
3046 (void)dpaa2_ni_tx_conf(chan, fq, fd);
3047 break;
3048 default:
3049 panic("%s: unknown queue type (1)",
3050 __func__);
3051 }
3052 frames++;
3053 }
3054 } else if (rc == EALREADY || rc == ENOENT) {
3055 if (dq != NULL && !IS_NULL_RESPONSE(dq->fdr.desc.stat)) {
3056 fd = &dq->fdr.fd;
3057 fq = (struct dpaa2_ni_fq *) dq->fdr.desc.fqd_ctx;
3058
3059 switch (fq->type) {
3060 case DPAA2_NI_QUEUE_RX:
3061 /*
3062 * Last VDQ response (mbuf) in a chain
3063 * obtained from the Rx queue.
3064 */
3065 ctx.last = true;
3066 (void)dpaa2_ni_rx(chan, fq, fd, &ctx);
3067 break;
3068 case DPAA2_NI_QUEUE_RX_ERR:
3069 (void)dpaa2_ni_rx_err(chan, fq, fd);
3070 break;
3071 case DPAA2_NI_QUEUE_TX_CONF:
3072 (void)dpaa2_ni_tx_conf(chan, fq, fd);
3073 break;
3074 default:
3075 panic("%s: unknown queue type (2)",
3076 __func__);
3077 }
3078 frames++;
3079 }
3080 break;
3081 } else {
3082 panic("%s: should not reach here: rc=%d", __func__, rc);
3083 }
3084 } while (true);
3085
3086 KASSERT(chan->store_idx < chan->store_sz, ("%s: store_idx(%d) >= "
3087 "store_sz(%d)", __func__, chan->store_idx, chan->store_sz));
3088
3089 /*
3090 * VDQ operation pulls frames from a single queue into the store.
3091 * Return the frame queue and a number of consumed frames as an output.
3092 */
3093 if (src != NULL) {
3094 *src = fq;
3095 }
3096 if (consumed != NULL) {
3097 *consumed = frames;
3098 }
3099
3100 return (rc);
3101 }
3102
3103 /**
3104 * @brief Receive frames.
3105 */
3106 static int
dpaa2_ni_rx(struct dpaa2_channel * ch,struct dpaa2_ni_fq * fq,struct dpaa2_fd * fd,struct dpaa2_ni_rx_ctx * ctx)3107 dpaa2_ni_rx(struct dpaa2_channel *ch, struct dpaa2_ni_fq *fq, struct dpaa2_fd *fd,
3108 struct dpaa2_ni_rx_ctx *ctx)
3109 {
3110 bus_addr_t paddr = (bus_addr_t)fd->addr;
3111 struct dpaa2_fa *fa = (struct dpaa2_fa *)PHYS_TO_DMAP(paddr);
3112 struct dpaa2_buf *buf = fa->buf;
3113 struct dpaa2_channel *bch = (struct dpaa2_channel *)buf->opt;
3114 struct dpaa2_ni_softc *sc = device_get_softc(bch->ni_dev);
3115 struct dpaa2_bp_softc *bpsc;
3116 struct mbuf *m;
3117 device_t bpdev;
3118 bus_addr_t released[DPAA2_SWP_BUFS_PER_CMD];
3119 void *buf_data;
3120 int buf_len, error, released_n = 0;
3121
3122 KASSERT(fa->magic == DPAA2_MAGIC, ("%s: wrong magic", __func__));
3123 /*
3124 * NOTE: Current channel might not be the same as the "buffer" channel
3125 * and it's fine. It must not be NULL though.
3126 */
3127 KASSERT(bch != NULL, ("%s: buffer channel is NULL", __func__));
3128
3129 if (__predict_false(paddr != buf->paddr)) {
3130 panic("%s: unexpected physical address: fd(%#jx) != buf(%#jx)",
3131 __func__, paddr, buf->paddr);
3132 }
3133
3134 switch (dpaa2_ni_fd_err(fd)) {
3135 case 1: /* Enqueue rejected by QMan */
3136 sc->rx_enq_rej_frames++;
3137 break;
3138 case 2: /* QMan IEOI error */
3139 sc->rx_ieoi_err_frames++;
3140 break;
3141 default:
3142 break;
3143 }
3144 switch (dpaa2_ni_fd_format(fd)) {
3145 case DPAA2_FD_SINGLE:
3146 sc->rx_single_buf_frames++;
3147 break;
3148 case DPAA2_FD_SG:
3149 sc->rx_sg_buf_frames++;
3150 break;
3151 default:
3152 break;
3153 }
3154
3155 mtx_assert(&bch->dma_mtx, MA_NOTOWNED);
3156 mtx_lock(&bch->dma_mtx);
3157
3158 bus_dmamap_sync(buf->dmat, buf->dmap, BUS_DMASYNC_POSTREAD);
3159 bus_dmamap_unload(buf->dmat, buf->dmap);
3160 m = buf->m;
3161 buf_len = dpaa2_ni_fd_data_len(fd);
3162 buf_data = (uint8_t *)buf->vaddr + dpaa2_ni_fd_offset(fd);
3163 /* Prepare buffer to be re-cycled */
3164 buf->m = NULL;
3165 buf->paddr = 0;
3166 buf->vaddr = NULL;
3167 buf->seg.ds_addr = 0;
3168 buf->seg.ds_len = 0;
3169 buf->nseg = 0;
3170
3171 mtx_unlock(&bch->dma_mtx);
3172
3173 m->m_flags |= M_PKTHDR;
3174 m->m_data = buf_data;
3175 m->m_len = buf_len;
3176 m->m_pkthdr.len = buf_len;
3177 m->m_pkthdr.rcvif = sc->ifp;
3178 m->m_pkthdr.flowid = fq->fqid;
3179 M_HASHTYPE_SET(m, M_HASHTYPE_OPAQUE);
3180
3181 if (ctx->head == NULL) {
3182 KASSERT(ctx->tail == NULL, ("%s: tail already given?", __func__));
3183 ctx->head = m;
3184 ctx->tail = m;
3185 } else {
3186 KASSERT(ctx->head != NULL, ("%s: head is NULL", __func__));
3187 ctx->tail->m_nextpkt = m;
3188 ctx->tail = m;
3189 }
3190 ctx->cnt++;
3191
3192 if (ctx->last) {
3193 ctx->tail->m_nextpkt = NULL;
3194 if_input(sc->ifp, ctx->head);
3195 }
3196
3197 /* Keep the buffer to be recycled */
3198 ch->recycled[ch->recycled_n++] = buf;
3199
3200 /* Re-seed and release recycled buffers back to the pool */
3201 if (ch->recycled_n == DPAA2_SWP_BUFS_PER_CMD) {
3202 /* Release new buffers to the pool if needed */
3203 taskqueue_enqueue(sc->bp_taskq, &ch->bp_task);
3204
3205 for (int i = 0; i < ch->recycled_n; i++) {
3206 buf = ch->recycled[i];
3207 bch = (struct dpaa2_channel *)buf->opt;
3208
3209 mtx_assert(&bch->dma_mtx, MA_NOTOWNED);
3210 mtx_lock(&bch->dma_mtx);
3211 error = dpaa2_buf_seed_rxb(sc->dev, buf,
3212 DPAA2_RX_BUF_SIZE, &bch->dma_mtx);
3213 mtx_unlock(&bch->dma_mtx);
3214
3215 if (__predict_false(error != 0)) {
3216 /* TODO: What else to do with the buffer? */
3217 panic("%s: failed to recycle buffer: error=%d",
3218 __func__, error);
3219 }
3220
3221 /* Prepare buffer to be released in a single command */
3222 released[released_n++] = buf->paddr;
3223 }
3224
3225 /* There's only one buffer pool for now */
3226 bpdev = (device_t)rman_get_start(sc->res[DPAA2_NI_BP_RID(0)]);
3227 bpsc = device_get_softc(bpdev);
3228
3229 error = DPAA2_SWP_RELEASE_BUFS(ch->io_dev, bpsc->attr.bpid,
3230 released, released_n);
3231 if (__predict_false(error != 0)) {
3232 device_printf(sc->dev, "%s: failed to release buffers "
3233 "to the pool: error=%d\n", __func__, error);
3234 return (error);
3235 }
3236 ch->recycled_n = 0;
3237 }
3238
3239 return (0);
3240 }
3241
3242 /**
3243 * @brief Receive Rx error frames.
3244 */
3245 static int
dpaa2_ni_rx_err(struct dpaa2_channel * ch,struct dpaa2_ni_fq * fq,struct dpaa2_fd * fd)3246 dpaa2_ni_rx_err(struct dpaa2_channel *ch, struct dpaa2_ni_fq *fq,
3247 struct dpaa2_fd *fd)
3248 {
3249 bus_addr_t paddr = (bus_addr_t)fd->addr;
3250 struct dpaa2_fa *fa = (struct dpaa2_fa *)PHYS_TO_DMAP(paddr);
3251 struct dpaa2_buf *buf = fa->buf;
3252 struct dpaa2_channel *bch = (struct dpaa2_channel *)buf->opt;
3253 struct dpaa2_ni_softc *sc = device_get_softc(bch->ni_dev);
3254 device_t bpdev;
3255 struct dpaa2_bp_softc *bpsc;
3256 int error;
3257
3258 KASSERT(fa->magic == DPAA2_MAGIC, ("%s: wrong magic", __func__));
3259 /*
3260 * NOTE: Current channel might not be the same as the "buffer" channel
3261 * and it's fine. It must not be NULL though.
3262 */
3263 KASSERT(bch != NULL, ("%s: buffer channel is NULL", __func__));
3264
3265 if (__predict_false(paddr != buf->paddr)) {
3266 panic("%s: unexpected physical address: fd(%#jx) != buf(%#jx)",
3267 __func__, paddr, buf->paddr);
3268 }
3269
3270 /* There's only one buffer pool for now */
3271 bpdev = (device_t)rman_get_start(sc->res[DPAA2_NI_BP_RID(0)]);
3272 bpsc = device_get_softc(bpdev);
3273
3274 /* Release buffer to QBMan buffer pool */
3275 error = DPAA2_SWP_RELEASE_BUFS(ch->io_dev, bpsc->attr.bpid, &paddr, 1);
3276 if (error != 0) {
3277 device_printf(sc->dev, "%s: failed to release frame buffer to "
3278 "the pool: error=%d\n", __func__, error);
3279 return (error);
3280 }
3281
3282 return (0);
3283 }
3284
3285 /**
3286 * @brief Receive Tx confirmation frames.
3287 */
3288 static int
dpaa2_ni_tx_conf(struct dpaa2_channel * ch,struct dpaa2_ni_fq * fq,struct dpaa2_fd * fd)3289 dpaa2_ni_tx_conf(struct dpaa2_channel *ch, struct dpaa2_ni_fq *fq,
3290 struct dpaa2_fd *fd)
3291 {
3292 bus_addr_t paddr = (bus_addr_t)fd->addr;
3293 struct dpaa2_fa *fa = (struct dpaa2_fa *)PHYS_TO_DMAP(paddr);
3294 struct dpaa2_buf *buf = fa->buf;
3295 struct dpaa2_buf *sgt = buf->sgt;
3296 struct dpaa2_ni_tx_ring *tx = (struct dpaa2_ni_tx_ring *)buf->opt;
3297 struct dpaa2_channel *bch = tx->fq->chan;
3298
3299 KASSERT(fa->magic == DPAA2_MAGIC, ("%s: wrong magic", __func__));
3300 KASSERT(tx != NULL, ("%s: Tx ring is NULL", __func__));
3301 KASSERT(sgt != NULL, ("%s: S/G table is NULL", __func__));
3302 /*
3303 * NOTE: Current channel might not be the same as the "buffer" channel
3304 * and it's fine. It must not be NULL though.
3305 */
3306 KASSERT(bch != NULL, ("%s: buffer channel is NULL", __func__));
3307
3308 if (paddr != buf->paddr) {
3309 panic("%s: unexpected physical address: fd(%#jx) != buf(%#jx)",
3310 __func__, paddr, buf->paddr);
3311 }
3312
3313 mtx_assert(&bch->dma_mtx, MA_NOTOWNED);
3314 mtx_lock(&bch->dma_mtx);
3315
3316 bus_dmamap_sync(buf->dmat, buf->dmap, BUS_DMASYNC_POSTWRITE);
3317 bus_dmamap_sync(sgt->dmat, sgt->dmap, BUS_DMASYNC_POSTWRITE);
3318 bus_dmamap_unload(buf->dmat, buf->dmap);
3319 bus_dmamap_unload(sgt->dmat, sgt->dmap);
3320 m_freem(buf->m);
3321 buf->m = NULL;
3322 buf->paddr = 0;
3323 buf->vaddr = NULL;
3324 sgt->paddr = 0;
3325
3326 mtx_unlock(&bch->dma_mtx);
3327
3328 /* Return Tx buffer back to the ring */
3329 buf_ring_enqueue(tx->br, buf);
3330
3331 return (0);
3332 }
3333
3334 /**
3335 * @brief Compare versions of the DPAA2 network interface API.
3336 */
3337 static int
dpaa2_ni_cmp_api_version(struct dpaa2_ni_softc * sc,uint16_t major,uint16_t minor)3338 dpaa2_ni_cmp_api_version(struct dpaa2_ni_softc *sc, uint16_t major,
3339 uint16_t minor)
3340 {
3341 if (sc->api_major == major) {
3342 return sc->api_minor - minor;
3343 }
3344 return sc->api_major - major;
3345 }
3346
3347 /**
3348 * @brief Build a DPAA2 frame descriptor.
3349 */
3350 static int
dpaa2_ni_build_fd(struct dpaa2_ni_softc * sc,struct dpaa2_ni_tx_ring * tx,struct dpaa2_buf * buf,bus_dma_segment_t * segs,int nsegs,struct dpaa2_fd * fd)3351 dpaa2_ni_build_fd(struct dpaa2_ni_softc *sc, struct dpaa2_ni_tx_ring *tx,
3352 struct dpaa2_buf *buf, bus_dma_segment_t *segs, int nsegs, struct dpaa2_fd *fd)
3353 {
3354 struct dpaa2_buf *sgt = buf->sgt;
3355 struct dpaa2_sg_entry *sge;
3356 struct dpaa2_fa *fa;
3357 int i, error;
3358
3359 KASSERT(nsegs <= DPAA2_TX_SEGLIMIT, ("%s: too many segments", __func__));
3360 KASSERT(buf->opt != NULL, ("%s: no Tx ring?", __func__));
3361 KASSERT(sgt != NULL, ("%s: no S/G table?", __func__));
3362 KASSERT(sgt->vaddr != NULL, ("%s: no S/G vaddr?", __func__));
3363
3364 memset(fd, 0, sizeof(*fd));
3365
3366 /* Populate and map S/G table */
3367 if (__predict_true(nsegs <= DPAA2_TX_SEGLIMIT)) {
3368 sge = (struct dpaa2_sg_entry *)sgt->vaddr + sc->tx_data_off;
3369 for (i = 0; i < nsegs; i++) {
3370 sge[i].addr = (uint64_t)segs[i].ds_addr;
3371 sge[i].len = (uint32_t)segs[i].ds_len;
3372 sge[i].offset_fmt = 0u;
3373 }
3374 sge[i-1].offset_fmt |= 0x8000u; /* set final entry flag */
3375
3376 KASSERT(sgt->paddr == 0, ("%s: paddr(%#jx) != 0", __func__,
3377 sgt->paddr));
3378
3379 error = bus_dmamap_load(sgt->dmat, sgt->dmap, sgt->vaddr,
3380 DPAA2_TX_SGT_SZ, dpaa2_dmamap_oneseg_cb, &sgt->paddr,
3381 BUS_DMA_NOWAIT);
3382 if (__predict_false(error != 0)) {
3383 device_printf(sc->dev, "%s: bus_dmamap_load() failed: "
3384 "error=%d\n", __func__, error);
3385 return (error);
3386 }
3387
3388 buf->paddr = sgt->paddr;
3389 buf->vaddr = sgt->vaddr;
3390 sc->tx_sg_frames++; /* for sysctl(9) */
3391 } else {
3392 return (EINVAL);
3393 }
3394
3395 fa = (struct dpaa2_fa *)sgt->vaddr;
3396 fa->magic = DPAA2_MAGIC;
3397 fa->buf = buf;
3398
3399 fd->addr = buf->paddr;
3400 fd->data_length = (uint32_t)buf->m->m_pkthdr.len;
3401 fd->bpid_ivp_bmt = 0;
3402 fd->offset_fmt_sl = 0x2000u | sc->tx_data_off;
3403 fd->ctrl = 0x00800000u;
3404
3405 return (0);
3406 }
3407
3408 static int
dpaa2_ni_fd_err(struct dpaa2_fd * fd)3409 dpaa2_ni_fd_err(struct dpaa2_fd *fd)
3410 {
3411 return ((fd->ctrl >> DPAA2_NI_FD_ERR_SHIFT) & DPAA2_NI_FD_ERR_MASK);
3412 }
3413
3414 static uint32_t
dpaa2_ni_fd_data_len(struct dpaa2_fd * fd)3415 dpaa2_ni_fd_data_len(struct dpaa2_fd *fd)
3416 {
3417 if (dpaa2_ni_fd_short_len(fd)) {
3418 return (fd->data_length & DPAA2_NI_FD_LEN_MASK);
3419 }
3420 return (fd->data_length);
3421 }
3422
3423 static int
dpaa2_ni_fd_format(struct dpaa2_fd * fd)3424 dpaa2_ni_fd_format(struct dpaa2_fd *fd)
3425 {
3426 return ((enum dpaa2_fd_format)((fd->offset_fmt_sl >>
3427 DPAA2_NI_FD_FMT_SHIFT) & DPAA2_NI_FD_FMT_MASK));
3428 }
3429
3430 static bool
dpaa2_ni_fd_short_len(struct dpaa2_fd * fd)3431 dpaa2_ni_fd_short_len(struct dpaa2_fd *fd)
3432 {
3433 return (((fd->offset_fmt_sl >> DPAA2_NI_FD_SL_SHIFT)
3434 & DPAA2_NI_FD_SL_MASK) == 1);
3435 }
3436
3437 static int
dpaa2_ni_fd_offset(struct dpaa2_fd * fd)3438 dpaa2_ni_fd_offset(struct dpaa2_fd *fd)
3439 {
3440 return (fd->offset_fmt_sl & DPAA2_NI_FD_OFFSET_MASK);
3441 }
3442
3443 /**
3444 * @brief Collect statistics of the network interface.
3445 */
3446 static int
dpaa2_ni_collect_stats(SYSCTL_HANDLER_ARGS)3447 dpaa2_ni_collect_stats(SYSCTL_HANDLER_ARGS)
3448 {
3449 struct dpaa2_ni_softc *sc = (struct dpaa2_ni_softc *) arg1;
3450 struct dpni_stat *stat = &dpni_stat_sysctls[oidp->oid_number];
3451 device_t pdev = device_get_parent(sc->dev);
3452 device_t dev = sc->dev;
3453 device_t child = dev;
3454 struct dpaa2_devinfo *rcinfo = device_get_ivars(pdev);
3455 struct dpaa2_devinfo *dinfo = device_get_ivars(dev);
3456 struct dpaa2_cmd cmd;
3457 uint64_t cnt[DPAA2_NI_STAT_COUNTERS];
3458 uint64_t result = 0;
3459 uint16_t rc_token, ni_token;
3460 int error;
3461
3462 DPAA2_CMD_INIT(&cmd);
3463
3464 error = DPAA2_CMD_RC_OPEN(dev, child, &cmd, rcinfo->id, &rc_token);
3465 if (error) {
3466 device_printf(dev, "%s: failed to open resource container: "
3467 "id=%d, error=%d\n", __func__, rcinfo->id, error);
3468 goto exit;
3469 }
3470 error = DPAA2_CMD_NI_OPEN(dev, child, &cmd, dinfo->id, &ni_token);
3471 if (error) {
3472 device_printf(dev, "%s: failed to open network interface: "
3473 "id=%d, error=%d\n", __func__, dinfo->id, error);
3474 goto close_rc;
3475 }
3476
3477 error = DPAA2_CMD_NI_GET_STATISTICS(dev, child, &cmd, stat->page, 0, cnt);
3478 if (!error) {
3479 result = cnt[stat->cnt];
3480 }
3481
3482 (void)DPAA2_CMD_NI_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, ni_token));
3483 close_rc:
3484 (void)DPAA2_CMD_RC_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, rc_token));
3485 exit:
3486 return (sysctl_handle_64(oidp, &result, 0, req));
3487 }
3488
3489 static int
dpaa2_ni_collect_buf_num(SYSCTL_HANDLER_ARGS)3490 dpaa2_ni_collect_buf_num(SYSCTL_HANDLER_ARGS)
3491 {
3492 struct dpaa2_ni_softc *sc = (struct dpaa2_ni_softc *) arg1;
3493 uint32_t buf_num = DPAA2_ATOMIC_READ(&sc->buf_num);
3494
3495 return (sysctl_handle_32(oidp, &buf_num, 0, req));
3496 }
3497
3498 static int
dpaa2_ni_collect_buf_free(SYSCTL_HANDLER_ARGS)3499 dpaa2_ni_collect_buf_free(SYSCTL_HANDLER_ARGS)
3500 {
3501 struct dpaa2_ni_softc *sc = (struct dpaa2_ni_softc *) arg1;
3502 uint32_t buf_free = DPAA2_ATOMIC_READ(&sc->buf_free);
3503
3504 return (sysctl_handle_32(oidp, &buf_free, 0, req));
3505 }
3506
3507 static int
dpaa2_ni_set_hash(device_t dev,uint64_t flags)3508 dpaa2_ni_set_hash(device_t dev, uint64_t flags)
3509 {
3510 struct dpaa2_ni_softc *sc = device_get_softc(dev);
3511 uint64_t key = 0;
3512 int i;
3513
3514 if (!(sc->attr.num.queues > 1)) {
3515 return (EOPNOTSUPP);
3516 }
3517
3518 for (i = 0; i < ARRAY_SIZE(dist_fields); i++) {
3519 if (dist_fields[i].rxnfc_field & flags) {
3520 key |= dist_fields[i].id;
3521 }
3522 }
3523
3524 return (dpaa2_ni_set_dist_key(dev, DPAA2_NI_DIST_MODE_HASH, key));
3525 }
3526
3527 /**
3528 * @brief Set Rx distribution (hash or flow classification) key flags is a
3529 * combination of RXH_ bits.
3530 */
3531 static int
dpaa2_ni_set_dist_key(device_t dev,enum dpaa2_ni_dist_mode type,uint64_t flags)3532 dpaa2_ni_set_dist_key(device_t dev, enum dpaa2_ni_dist_mode type, uint64_t flags)
3533 {
3534 device_t pdev = device_get_parent(dev);
3535 device_t child = dev;
3536 struct dpaa2_ni_softc *sc = device_get_softc(dev);
3537 struct dpaa2_devinfo *rcinfo = device_get_ivars(pdev);
3538 struct dpaa2_devinfo *dinfo = device_get_ivars(dev);
3539 struct dpkg_profile_cfg cls_cfg;
3540 struct dpkg_extract *key;
3541 struct dpaa2_buf *buf = &sc->rxd_kcfg;
3542 struct dpaa2_cmd cmd;
3543 uint16_t rc_token, ni_token;
3544 int i, error = 0;
3545
3546 if (__predict_true(buf->dmat == NULL)) {
3547 buf->dmat = sc->rxd_dmat;
3548 }
3549
3550 memset(&cls_cfg, 0, sizeof(cls_cfg));
3551
3552 /* Configure extracts according to the given flags. */
3553 for (i = 0; i < ARRAY_SIZE(dist_fields); i++) {
3554 key = &cls_cfg.extracts[cls_cfg.num_extracts];
3555
3556 if (!(flags & dist_fields[i].id)) {
3557 continue;
3558 }
3559
3560 if (cls_cfg.num_extracts >= DPKG_MAX_NUM_OF_EXTRACTS) {
3561 device_printf(dev, "%s: failed to add key extraction "
3562 "rule\n", __func__);
3563 return (E2BIG);
3564 }
3565
3566 key->type = DPKG_EXTRACT_FROM_HDR;
3567 key->extract.from_hdr.prot = dist_fields[i].cls_prot;
3568 key->extract.from_hdr.type = DPKG_FULL_FIELD;
3569 key->extract.from_hdr.field = dist_fields[i].cls_field;
3570 cls_cfg.num_extracts++;
3571 }
3572
3573 error = bus_dmamem_alloc(buf->dmat, (void **)&buf->vaddr,
3574 BUS_DMA_ZERO | BUS_DMA_COHERENT, &buf->dmap);
3575 if (error != 0) {
3576 device_printf(dev, "%s: failed to allocate a buffer for Rx "
3577 "traffic distribution key configuration\n", __func__);
3578 return (error);
3579 }
3580
3581 error = dpaa2_ni_prepare_key_cfg(&cls_cfg, (uint8_t *)buf->vaddr);
3582 if (error != 0) {
3583 device_printf(dev, "%s: failed to prepare key configuration: "
3584 "error=%d\n", __func__, error);
3585 return (error);
3586 }
3587
3588 /* Prepare for setting the Rx dist. */
3589 error = bus_dmamap_load(buf->dmat, buf->dmap, buf->vaddr,
3590 DPAA2_CLASSIFIER_DMA_SIZE, dpaa2_dmamap_oneseg_cb, &buf->paddr,
3591 BUS_DMA_NOWAIT);
3592 if (error != 0) {
3593 device_printf(sc->dev, "%s: failed to map a buffer for Rx "
3594 "traffic distribution key configuration\n", __func__);
3595 return (error);
3596 }
3597
3598 if (type == DPAA2_NI_DIST_MODE_HASH) {
3599 DPAA2_CMD_INIT(&cmd);
3600
3601 error = DPAA2_CMD_RC_OPEN(dev, child, &cmd, rcinfo->id,
3602 &rc_token);
3603 if (error) {
3604 device_printf(dev, "%s: failed to open resource "
3605 "container: id=%d, error=%d\n", __func__, rcinfo->id,
3606 error);
3607 goto err_exit;
3608 }
3609 error = DPAA2_CMD_NI_OPEN(dev, child, &cmd, dinfo->id,
3610 &ni_token);
3611 if (error) {
3612 device_printf(dev, "%s: failed to open network "
3613 "interface: id=%d, error=%d\n", __func__, dinfo->id,
3614 error);
3615 goto close_rc;
3616 }
3617
3618 error = DPAA2_CMD_NI_SET_RX_TC_DIST(dev, child, &cmd,
3619 sc->attr.num.queues, 0, DPAA2_NI_DIST_MODE_HASH, buf->paddr);
3620 if (error != 0) {
3621 device_printf(dev, "%s: failed to set distribution mode "
3622 "and size for the traffic class\n", __func__);
3623 }
3624
3625 (void)DPAA2_CMD_NI_CLOSE(dev, child, DPAA2_CMD_TK(&cmd,
3626 ni_token));
3627 close_rc:
3628 (void)DPAA2_CMD_RC_CLOSE(dev, child, DPAA2_CMD_TK(&cmd,
3629 rc_token));
3630 }
3631
3632 err_exit:
3633 return (error);
3634 }
3635
3636 /**
3637 * @brief Prepares extract parameters.
3638 *
3639 * cfg: Defining a full Key Generation profile.
3640 * key_cfg_buf: Zeroed 256 bytes of memory before mapping it to DMA.
3641 */
3642 static int
dpaa2_ni_prepare_key_cfg(struct dpkg_profile_cfg * cfg,uint8_t * key_cfg_buf)3643 dpaa2_ni_prepare_key_cfg(struct dpkg_profile_cfg *cfg, uint8_t *key_cfg_buf)
3644 {
3645 struct dpni_ext_set_rx_tc_dist *dpni_ext;
3646 struct dpni_dist_extract *extr;
3647 int i, j;
3648
3649 if (cfg->num_extracts > DPKG_MAX_NUM_OF_EXTRACTS)
3650 return (EINVAL);
3651
3652 dpni_ext = (struct dpni_ext_set_rx_tc_dist *) key_cfg_buf;
3653 dpni_ext->num_extracts = cfg->num_extracts;
3654
3655 for (i = 0; i < cfg->num_extracts; i++) {
3656 extr = &dpni_ext->extracts[i];
3657
3658 switch (cfg->extracts[i].type) {
3659 case DPKG_EXTRACT_FROM_HDR:
3660 extr->prot = cfg->extracts[i].extract.from_hdr.prot;
3661 extr->efh_type =
3662 cfg->extracts[i].extract.from_hdr.type & 0x0Fu;
3663 extr->size = cfg->extracts[i].extract.from_hdr.size;
3664 extr->offset = cfg->extracts[i].extract.from_hdr.offset;
3665 extr->field = cfg->extracts[i].extract.from_hdr.field;
3666 extr->hdr_index =
3667 cfg->extracts[i].extract.from_hdr.hdr_index;
3668 break;
3669 case DPKG_EXTRACT_FROM_DATA:
3670 extr->size = cfg->extracts[i].extract.from_data.size;
3671 extr->offset =
3672 cfg->extracts[i].extract.from_data.offset;
3673 break;
3674 case DPKG_EXTRACT_FROM_PARSE:
3675 extr->size = cfg->extracts[i].extract.from_parse.size;
3676 extr->offset =
3677 cfg->extracts[i].extract.from_parse.offset;
3678 break;
3679 default:
3680 return (EINVAL);
3681 }
3682
3683 extr->num_of_byte_masks = cfg->extracts[i].num_of_byte_masks;
3684 extr->extract_type = cfg->extracts[i].type & 0x0Fu;
3685
3686 for (j = 0; j < DPKG_NUM_OF_MASKS; j++) {
3687 extr->masks[j].mask = cfg->extracts[i].masks[j].mask;
3688 extr->masks[j].offset =
3689 cfg->extracts[i].masks[j].offset;
3690 }
3691 }
3692
3693 return (0);
3694 }
3695
3696 static device_method_t dpaa2_ni_methods[] = {
3697 /* Device interface */
3698 DEVMETHOD(device_probe, dpaa2_ni_probe),
3699 DEVMETHOD(device_attach, dpaa2_ni_attach),
3700 DEVMETHOD(device_detach, dpaa2_ni_detach),
3701
3702 /* mii via memac_mdio */
3703 DEVMETHOD(miibus_statchg, dpaa2_ni_miibus_statchg),
3704
3705 DEVMETHOD_END
3706 };
3707
3708 static driver_t dpaa2_ni_driver = {
3709 "dpaa2_ni",
3710 dpaa2_ni_methods,
3711 sizeof(struct dpaa2_ni_softc),
3712 };
3713
3714 DRIVER_MODULE(miibus, dpaa2_ni, miibus_driver, 0, 0);
3715 DRIVER_MODULE(dpaa2_ni, dpaa2_rc, dpaa2_ni_driver, 0, 0);
3716
3717 MODULE_DEPEND(dpaa2_ni, miibus, 1, 1, 1);
3718 #ifdef DEV_ACPI
3719 MODULE_DEPEND(dpaa2_ni, memac_mdio_acpi, 1, 1, 1);
3720 #endif
3721 #ifdef FDT
3722 MODULE_DEPEND(dpaa2_ni, memac_mdio_fdt, 1, 1, 1);
3723 #endif
3724