Branch data Line data Source code
1 : : /* SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0)
2 : : *
3 : : * Copyright 2010-2016 Freescale Semiconductor Inc.
4 : : * Copyright 2017-2024 NXP
5 : : *
6 : : */
7 : :
8 : : #include <sys/types.h>
9 : : #include <sys/ioctl.h>
10 : : #include <ifaddrs.h>
11 : :
12 : : /* This header declares the driver interface we implement */
13 : : #include <fman.h>
14 : : #include <dpaa_of.h>
15 : : #include <rte_malloc.h>
16 : : #include <rte_dpaa_logs.h>
17 : : #include <rte_string_fns.h>
18 : :
19 : : #define QMI_PORT_REGS_OFFSET 0x400
20 : :
21 : : /* CCSR map address to access ccsr based register */
22 : : void *fman_ccsr_map;
23 : : /* fman version info */
24 : : u16 fman_ip_rev;
25 : : static int get_once;
26 : : u32 fman_dealloc_bufs_mask_hi;
27 : : u32 fman_dealloc_bufs_mask_lo;
28 : :
29 : : int fman_ccsr_map_fd = -1;
30 : : static COMPAT_LIST_HEAD(__ifs);
31 : : void *rtc_map;
32 : :
33 : : /* This is the (const) global variable that callers have read-only access to.
34 : : * Internally, we have read-write access directly to __ifs.
35 : : */
36 : : const struct list_head *fman_if_list = &__ifs;
37 : :
38 : : static void
39 : 0 : if_destructor(struct __fman_if *__if)
40 : : {
41 : : struct fman_if_bpool *bp, *tmpbp;
42 : :
43 [ # # ]: 0 : if (!__if)
44 : : return;
45 : :
46 [ # # ]: 0 : if (__if->__if.mac_type == fman_offline_internal)
47 : 0 : goto cleanup;
48 : :
49 [ # # ]: 0 : list_for_each_entry_safe(bp, tmpbp, &__if->__if.bpool_list, node) {
50 : 0 : list_del(&bp->node);
51 : 0 : free(bp);
52 : : }
53 : 0 : cleanup:
54 : 0 : rte_free(__if);
55 : : }
56 : :
57 : : static int
58 : 0 : fman_get_ip_rev(const struct device_node *fman_node)
59 : : {
60 : : const uint32_t *fman_addr;
61 : : uint64_t phys_addr;
62 : : uint64_t regs_size;
63 : : uint32_t ip_rev_1;
64 : : int _errno;
65 : :
66 : 0 : fman_addr = of_get_address(fman_node, 0, ®s_size, NULL);
67 [ # # ]: 0 : if (!fman_addr) {
68 : 0 : pr_err("of_get_address cannot return fman address\n");
69 : 0 : return -EINVAL;
70 : : }
71 : 0 : phys_addr = of_translate_address(fman_node, fman_addr);
72 [ # # ]: 0 : if (!phys_addr) {
73 : 0 : pr_err("of_translate_address failed\n");
74 : 0 : return -EINVAL;
75 : : }
76 : 0 : fman_ccsr_map = mmap(NULL, regs_size, PROT_READ | PROT_WRITE,
77 : : MAP_SHARED, fman_ccsr_map_fd, phys_addr);
78 [ # # ]: 0 : if (fman_ccsr_map == MAP_FAILED) {
79 : 0 : pr_err("Can not map FMan ccsr base");
80 : 0 : return -EINVAL;
81 : : }
82 : :
83 : : ip_rev_1 = in_be32(fman_ccsr_map + FMAN_IP_REV_1);
84 : 0 : fman_ip_rev = (ip_rev_1 & FMAN_IP_REV_1_MAJOR_MASK) >>
85 : : FMAN_IP_REV_1_MAJOR_SHIFT;
86 : :
87 : 0 : _errno = munmap(fman_ccsr_map, regs_size);
88 [ # # ]: 0 : if (_errno)
89 : 0 : pr_err("munmap() of FMan ccsr failed");
90 : :
91 : : return 0;
92 : : }
93 : :
94 : : static int
95 : 0 : fman_get_mac_index(uint64_t regs_addr_host, uint8_t *mac_idx)
96 : : {
97 : : int ret = 0;
98 : :
99 : : /*
100 : : * MAC1 : E_0000h
101 : : * MAC2 : E_2000h
102 : : * MAC3 : E_4000h
103 : : * MAC4 : E_6000h
104 : : * MAC5 : E_8000h
105 : : * MAC6 : E_A000h
106 : : * MAC7 : E_C000h
107 : : * MAC8 : E_E000h
108 : : * MAC9 : F_0000h
109 : : * MAC10: F_2000h
110 : : */
111 [ # # # # : 0 : switch (regs_addr_host) {
# # # # #
# # ]
112 : 0 : case 0xE0000:
113 : 0 : *mac_idx = 1;
114 : 0 : break;
115 : 0 : case 0xE2000:
116 : 0 : *mac_idx = 2;
117 : 0 : break;
118 : 0 : case 0xE4000:
119 : 0 : *mac_idx = 3;
120 : 0 : break;
121 : 0 : case 0xE6000:
122 : 0 : *mac_idx = 4;
123 : 0 : break;
124 : 0 : case 0xE8000:
125 : 0 : *mac_idx = 5;
126 : 0 : break;
127 : 0 : case 0xEA000:
128 : 0 : *mac_idx = 6;
129 : 0 : break;
130 : 0 : case 0xEC000:
131 : 0 : *mac_idx = 7;
132 : 0 : break;
133 : 0 : case 0xEE000:
134 : 0 : *mac_idx = 8;
135 : 0 : break;
136 : 0 : case 0xF0000:
137 : 0 : *mac_idx = 9;
138 : 0 : break;
139 : 0 : case 0xF2000:
140 : 0 : *mac_idx = 10;
141 : 0 : break;
142 : : default:
143 : : ret = -EINVAL;
144 : : }
145 : :
146 : 0 : return ret;
147 : : }
148 : :
149 : 0 : static void fman_if_vsp_init(struct __fman_if *__if)
150 : : {
151 : : const phandle *prop;
152 : : int cell_index;
153 : : const struct device_node *dev;
154 : : size_t lenp;
155 : 0 : const uint8_t mac_idx[] = {-1, 0, 1, 2, 3, 4, 5, 6, 7, 0, 1};
156 : :
157 [ # # ]: 0 : if (__if->__if.mac_idx <= 8) {
158 [ # # ]: 0 : for_each_compatible_node(dev, NULL,
159 : : "fsl,fman-port-1g-rx-extended-args") {
160 : 0 : prop = of_get_property(dev, "cell-index", &lenp);
161 [ # # ]: 0 : if (prop) {
162 : 0 : cell_index = of_read_number(
163 : : &prop[0],
164 : 0 : lenp / sizeof(phandle));
165 [ # # ]: 0 : if (cell_index == mac_idx[__if->__if.mac_idx]) {
166 : 0 : prop = of_get_property(
167 : : dev,
168 : : "vsp-window", &lenp);
169 [ # # ]: 0 : if (prop) {
170 : 0 : __if->__if.num_profiles =
171 : : of_read_number(
172 : : &prop[0], 1);
173 : 0 : __if->__if.base_profile_id =
174 : : of_read_number(
175 : 0 : &prop[1], 1);
176 : : }
177 : : }
178 : : }
179 : : }
180 : :
181 [ # # ]: 0 : for_each_compatible_node(dev, NULL,
182 : : "fsl,fman-port-op-extended-args") {
183 : 0 : prop = of_get_property(dev, "cell-index", &lenp);
184 : :
185 [ # # ]: 0 : if (prop) {
186 : 0 : cell_index = of_read_number(&prop[0],
187 : 0 : lenp / sizeof(phandle));
188 : :
189 [ # # ]: 0 : if (cell_index == __if->__if.mac_idx) {
190 : 0 : prop = of_get_property(dev,
191 : : "vsp-window",
192 : : &lenp);
193 : :
194 [ # # ]: 0 : if (prop) {
195 : 0 : __if->__if.num_profiles =
196 : : of_read_number(&prop[0],
197 : : 1);
198 : 0 : __if->__if.base_profile_id =
199 : 0 : of_read_number(&prop[1],
200 : : 1);
201 : : }
202 : : }
203 : : }
204 : : }
205 : : } else {
206 [ # # ]: 0 : for_each_compatible_node(dev, NULL,
207 : : "fsl,fman-port-10g-rx-extended-args") {
208 : 0 : prop = of_get_property(dev, "cell-index", &lenp);
209 [ # # ]: 0 : if (prop) {
210 : 0 : cell_index = of_read_number(
211 : 0 : &prop[0], lenp / sizeof(phandle));
212 [ # # ]: 0 : if (cell_index == mac_idx[__if->__if.mac_idx]) {
213 : 0 : prop = of_get_property(
214 : : dev, "vsp-window", &lenp);
215 [ # # ]: 0 : if (prop) {
216 : 0 : __if->__if.num_profiles =
217 : : of_read_number(
218 : : &prop[0], 1);
219 : 0 : __if->__if.base_profile_id =
220 : : of_read_number(
221 : 0 : &prop[1], 1);
222 : : }
223 : : }
224 : : }
225 : : }
226 : : }
227 : 0 : }
228 : :
229 : : static int
230 : 0 : fman_if_init(const struct device_node *dpa_node)
231 : : {
232 : : const char *rprop, *mprop;
233 : : uint64_t phys_addr;
234 : : struct __fman_if *__if;
235 : : struct fman_if_bpool *bpool;
236 : :
237 : : const phandle *mac_phandle, *ports_phandle, *pools_phandle;
238 : : const phandle *tx_channel_id = NULL, *mac_addr, *cell_idx;
239 : : const phandle *rx_phandle, *tx_phandle;
240 : : const phandle *port_cell_idx, *ext_args_cell_idx;
241 : : const struct device_node *parent_node_ext_args;
242 : : uint64_t tx_phandle_host[4] = {0};
243 : : uint64_t rx_phandle_host[6] = {0};
244 : : uint64_t regs_addr_host = 0;
245 : : uint64_t cell_idx_host = 0;
246 : : uint64_t port_cell_idx_val = 0;
247 : : uint64_t ext_args_cell_idx_val = 0;
248 : :
249 : : const struct device_node *mac_node = NULL, *ext_args_node;
250 : : const struct device_node *pool_node, *fman_node;
251 : : const struct device_node *rx_node = NULL, *tx_node = NULL;
252 : : const struct device_node *oh_node = NULL;
253 : : const uint32_t *regs_addr = NULL;
254 : : const char *mname, *fname;
255 : 0 : const char *dname = dpa_node->full_name;
256 : : size_t lenp;
257 : : int _errno, is_shared = 0, is_offline = 0;
258 : : const char *char_prop;
259 : : uint32_t na;
260 : :
261 [ # # ]: 0 : if (of_device_is_available(dpa_node) == false)
262 : : return 0;
263 : :
264 [ # # ]: 0 : if (of_device_is_compatible(dpa_node, "fsl,dpa-oh"))
265 : : is_offline = 1;
266 : :
267 [ # # # # ]: 0 : if (!of_device_is_compatible(dpa_node, "fsl,dpa-oh") &&
268 [ # # ]: 0 : !of_device_is_compatible(dpa_node, "fsl,dpa-ethernet-init") &&
269 : 0 : !of_device_is_compatible(dpa_node, "fsl,dpa-ethernet")) {
270 : : return 0;
271 : : }
272 : :
273 [ # # ]: 0 : rprop = is_offline ? "fsl,qman-frame-queues-oh" :
274 : : "fsl,qman-frame-queues-rx";
275 [ # # ]: 0 : mprop = is_offline ? "fsl,fman-oh-port" :
276 : : "fsl,fman-mac";
277 : :
278 : : /* Obtain the MAC node used by this interface except macless */
279 : 0 : mac_phandle = of_get_property(dpa_node, mprop, &lenp);
280 [ # # ]: 0 : if (!mac_phandle) {
281 : 0 : FMAN_ERR(-EINVAL, "%s: no %s", dname, mprop);
282 : 0 : return -EINVAL;
283 : : }
284 [ # # ]: 0 : assert(lenp == sizeof(phandle));
285 : 0 : mac_node = of_find_node_by_phandle(*mac_phandle);
286 [ # # ]: 0 : if (!mac_node) {
287 : 0 : FMAN_ERR(-ENXIO, "%s: bad 'fsl,fman-mac", dname);
288 : 0 : return -ENXIO;
289 : : }
290 : 0 : mname = mac_node->full_name;
291 : :
292 [ # # ]: 0 : if (!is_offline) {
293 : : /* Extract the Rx and Tx ports */
294 : 0 : ports_phandle = of_get_property(mac_node, "fsl,port-handles",
295 : : &lenp);
296 [ # # ]: 0 : if (!ports_phandle)
297 : 0 : ports_phandle = of_get_property(mac_node, "fsl,fman-ports",
298 : : &lenp);
299 [ # # ]: 0 : if (!ports_phandle) {
300 : 0 : FMAN_ERR(-EINVAL, "%s: no fsl,port-handles",
301 : : mname);
302 : 0 : return -EINVAL;
303 : : }
304 [ # # ]: 0 : assert(lenp == (2 * sizeof(phandle)));
305 : 0 : rx_node = of_find_node_by_phandle(ports_phandle[0]);
306 [ # # ]: 0 : if (!rx_node) {
307 : 0 : FMAN_ERR(-ENXIO, "%s: bad fsl,port-handle[0]", mname);
308 : 0 : return -ENXIO;
309 : : }
310 : 0 : tx_node = of_find_node_by_phandle(ports_phandle[1]);
311 [ # # ]: 0 : if (!tx_node) {
312 : 0 : FMAN_ERR(-ENXIO, "%s: bad fsl,port-handle[1]", mname);
313 : 0 : return -ENXIO;
314 : : }
315 : : } else {
316 : : /* Extract the OH ports */
317 : 0 : ports_phandle = of_get_property(dpa_node, "fsl,fman-oh-port",
318 : : &lenp);
319 [ # # ]: 0 : if (!ports_phandle) {
320 : 0 : FMAN_ERR(-EINVAL, "%s: no fsl,fman-oh-port", dname);
321 : 0 : return -EINVAL;
322 : : }
323 [ # # ]: 0 : assert(lenp == (sizeof(phandle)));
324 : 0 : oh_node = of_find_node_by_phandle(ports_phandle[0]);
325 [ # # ]: 0 : if (!oh_node) {
326 : 0 : FMAN_ERR(-ENXIO, "%s: bad fsl,port-handle[0]", mname);
327 : 0 : return -ENXIO;
328 : : }
329 : : }
330 : :
331 : : /* Check if the port is shared interface */
332 [ # # ]: 0 : if (of_device_is_compatible(dpa_node, "fsl,dpa-ethernet")) {
333 : 0 : port_cell_idx = of_get_property(rx_node, "cell-index", &lenp);
334 [ # # ]: 0 : if (!port_cell_idx) {
335 : 0 : FMAN_ERR(-ENXIO, "%s: no cell-index for port", mname);
336 : 0 : return -ENXIO;
337 : : }
338 [ # # ]: 0 : assert(lenp == sizeof(*port_cell_idx));
339 : : port_cell_idx_val =
340 : : of_read_number(port_cell_idx, lenp / sizeof(phandle));
341 : :
342 [ # # ]: 0 : if (of_device_is_compatible(rx_node, "fsl,fman-port-1g-rx"))
343 : 0 : port_cell_idx_val -= 0x8;
344 [ # # ]: 0 : else if (of_device_is_compatible(
345 : : rx_node, "fsl,fman-port-10g-rx"))
346 : 0 : port_cell_idx_val -= 0x10;
347 : :
348 : 0 : parent_node_ext_args = of_find_compatible_node(NULL,
349 : : NULL, "fsl,fman-extended-args");
350 [ # # ]: 0 : if (!parent_node_ext_args)
351 : : return 0;
352 : :
353 [ # # ]: 0 : for_each_child_node(parent_node_ext_args, ext_args_node) {
354 : 0 : ext_args_cell_idx = of_get_property(ext_args_node,
355 : : "cell-index", &lenp);
356 [ # # ]: 0 : if (!ext_args_cell_idx) {
357 : 0 : FMAN_ERR(-ENXIO, "%s: no cell-index for ext args",
358 : : mname);
359 : 0 : return -ENXIO;
360 : : }
361 [ # # ]: 0 : assert(lenp == sizeof(*ext_args_cell_idx));
362 : : ext_args_cell_idx_val =
363 : : of_read_number(ext_args_cell_idx, lenp /
364 : : sizeof(phandle));
365 : :
366 [ # # ]: 0 : if (port_cell_idx_val == ext_args_cell_idx_val) {
367 [ # # ]: 0 : if (of_device_is_compatible(ext_args_node,
368 [ # # ]: 0 : "fsl,fman-port-1g-rx-extended-args") &&
369 : 0 : of_device_is_compatible(rx_node,
370 : : "fsl,fman-port-1g-rx")) {
371 [ # # ]: 0 : if (of_get_property(ext_args_node,
372 : : "vsp-window", &lenp))
373 : : is_shared = 1;
374 : : break;
375 : : }
376 [ # # ]: 0 : if (of_device_is_compatible(ext_args_node,
377 [ # # ]: 0 : "fsl,fman-port-10g-rx-extended-args") &&
378 : 0 : of_device_is_compatible(rx_node,
379 : : "fsl,fman-port-10g-rx")) {
380 [ # # ]: 0 : if (of_get_property(ext_args_node,
381 : : "vsp-window", &lenp))
382 : : is_shared = 1;
383 : : break;
384 : : }
385 : : }
386 : : }
387 : : if (!is_shared)
388 : 0 : return 0;
389 : : }
390 : :
391 : : /* Allocate an object for this network interface */
392 : 0 : __if = rte_malloc(NULL, sizeof(*__if), RTE_CACHE_LINE_SIZE);
393 [ # # ]: 0 : if (!__if) {
394 : 0 : FMAN_ERR(-ENOMEM, "malloc(%zu)", sizeof(*__if));
395 : 0 : goto err;
396 : : }
397 : : memset(__if, 0, sizeof(*__if));
398 : 0 : INIT_LIST_HEAD(&__if->__if.bpool_list);
399 : 0 : strlcpy(__if->node_name, dpa_node->name, IF_NAME_MAX_LEN - 1);
400 : 0 : __if->node_name[IF_NAME_MAX_LEN - 1] = '\0';
401 : 0 : strlcpy(__if->node_path, dpa_node->full_name, PATH_MAX - 1);
402 : 0 : __if->node_path[PATH_MAX - 1] = '\0';
403 : :
404 : : /* Map the CCSR regs for the MAC node */
405 : 0 : regs_addr = of_get_address(mac_node, 0, &__if->regs_size, NULL);
406 [ # # ]: 0 : if (!regs_addr) {
407 : 0 : FMAN_ERR(-EINVAL, "of_get_address(%s)", mname);
408 : 0 : goto err;
409 : : }
410 : 0 : phys_addr = of_translate_address(mac_node, regs_addr);
411 [ # # ]: 0 : if (!phys_addr) {
412 : 0 : FMAN_ERR(-EINVAL, "of_translate_address(%s, %p)",
413 : : mname, regs_addr);
414 : 0 : goto err;
415 : : }
416 : 0 : __if->ccsr_map = mmap(NULL, __if->regs_size,
417 : : PROT_READ | PROT_WRITE, MAP_SHARED,
418 : : fman_ccsr_map_fd, phys_addr);
419 [ # # ]: 0 : if (__if->ccsr_map == MAP_FAILED) {
420 : 0 : FMAN_ERR(-errno, "mmap(0x%"PRIx64")", phys_addr);
421 : 0 : goto err;
422 : : }
423 : 0 : na = of_n_addr_cells(mac_node);
424 : : /* Get rid of endianness (issues). Convert to host byte order */
425 : 0 : regs_addr_host = of_read_number(regs_addr, na);
426 : :
427 : : /* Get the index of the Fman this i/f belongs to */
428 : 0 : fman_node = of_get_parent(mac_node);
429 : 0 : na = of_n_addr_cells(mac_node);
430 [ # # ]: 0 : if (!fman_node) {
431 : 0 : FMAN_ERR(-ENXIO, "of_get_parent(%s)", mname);
432 : 0 : goto err;
433 : : }
434 : 0 : fname = fman_node->full_name;
435 : 0 : cell_idx = of_get_property(fman_node, "cell-index", &lenp);
436 [ # # ]: 0 : if (!cell_idx) {
437 : 0 : FMAN_ERR(-ENXIO, "%s: no cell-index)", fname);
438 : 0 : goto err;
439 : : }
440 [ # # ]: 0 : assert(lenp == sizeof(*cell_idx));
441 : : cell_idx_host = of_read_number(cell_idx, lenp / sizeof(phandle));
442 : 0 : __if->__if.fman_idx = cell_idx_host;
443 [ # # ]: 0 : if (!get_once) {
444 : 0 : _errno = fman_get_ip_rev(fman_node);
445 [ # # ]: 0 : if (_errno) {
446 : 0 : FMAN_ERR(-ENXIO, "%s: ip_rev is not available",
447 : : fname);
448 : 0 : goto err;
449 : : }
450 : : }
451 : :
452 [ # # ]: 0 : if (fman_ip_rev >= FMAN_V3) {
453 : : /*
454 : : * Set A2V, OVOM, EBD bits in contextA to allow external
455 : : * buffer deallocation by fman.
456 : : */
457 : 0 : fman_dealloc_bufs_mask_hi = DPAA_FQD_CTX_A_A2_FIELD_VALID |
458 : : DPAA_FQD_CTX_A_OVERRIDE_OMB;
459 : 0 : fman_dealloc_bufs_mask_lo = DPAA_FQD_CTX_A2_EBD_BIT;
460 : : } else {
461 : 0 : fman_dealloc_bufs_mask_hi = 0;
462 : 0 : fman_dealloc_bufs_mask_lo = 0;
463 : : }
464 : : /* Is the MAC node 1G, 2.5G, 10G or offline? */
465 : 0 : __if->__if.is_memac = 0;
466 : :
467 [ # # ]: 0 : if (is_offline)
468 : 0 : __if->__if.mac_type = fman_offline_internal;
469 [ # # ]: 0 : else if (of_device_is_compatible(mac_node, "fsl,fman-1g-mac"))
470 : 0 : __if->__if.mac_type = fman_mac_1g;
471 [ # # ]: 0 : else if (of_device_is_compatible(mac_node, "fsl,fman-10g-mac"))
472 : 0 : __if->__if.mac_type = fman_mac_10g;
473 [ # # ]: 0 : else if (of_device_is_compatible(mac_node, "fsl,fman-memac")) {
474 : 0 : __if->__if.is_memac = 1;
475 : 0 : char_prop = of_get_property(mac_node, "phy-connection-type",
476 : : NULL);
477 [ # # ]: 0 : if (!char_prop) {
478 : 0 : FMAN_ERR(-EINVAL, "memac: unknown MII type assuming 1G");
479 : : /* Right now forcing memac to 1g in case of error*/
480 : 0 : __if->__if.mac_type = fman_mac_1g;
481 : : } else {
482 [ # # ]: 0 : if (strstr(char_prop, "sgmii-2500"))
483 : 0 : __if->__if.mac_type = fman_mac_2_5g;
484 [ # # ]: 0 : else if (strstr(char_prop, "sgmii"))
485 : 0 : __if->__if.mac_type = fman_mac_1g;
486 [ # # ]: 0 : else if (strstr(char_prop, "rgmii")) {
487 : 0 : __if->__if.mac_type = fman_mac_1g;
488 : 0 : __if->__if.is_rgmii = 1;
489 [ # # ]: 0 : } else if (strstr(char_prop, "xgmii"))
490 : 0 : __if->__if.mac_type = fman_mac_10g;
491 : : }
492 : : } else {
493 : 0 : FMAN_ERR(-EINVAL, "%s: unknown MAC type", mname);
494 : 0 : goto err;
495 : : }
496 : :
497 [ # # ]: 0 : if (!is_offline) {
498 : : /*
499 : : * For MAC ports, we cannot rely on cell-index. In
500 : : * T2080, two of the 10G ports on single FMAN have same
501 : : * duplicate cell-indexes as the other two 10G ports on
502 : : * same FMAN. Hence, we now rely upon addresses of the
503 : : * ports from device tree to deduce the index.
504 : : */
505 : :
506 : 0 : _errno = fman_get_mac_index(regs_addr_host, &__if->__if.mac_idx);
507 [ # # ]: 0 : if (_errno) {
508 : 0 : FMAN_ERR(-EINVAL, "Invalid register address: %" PRIx64,
509 : : regs_addr_host);
510 : 0 : goto err;
511 : : }
512 : : } else {
513 : 0 : cell_idx = of_get_property(oh_node, "cell-index", &lenp);
514 [ # # ]: 0 : if (!cell_idx) {
515 : 0 : FMAN_ERR(-ENXIO, "%s: no cell-index)",
516 : : oh_node->full_name);
517 : 0 : goto err;
518 : : }
519 [ # # ]: 0 : assert(lenp == sizeof(*cell_idx));
520 : : cell_idx_host = of_read_number(cell_idx,
521 : : lenp / sizeof(phandle));
522 : :
523 : 0 : __if->__if.mac_idx = cell_idx_host;
524 : : }
525 : :
526 [ # # ]: 0 : if (!is_offline) {
527 : : /* Extract the MAC address for private and shared interfaces */
528 : 0 : mac_addr = of_get_property(mac_node, "local-mac-address",
529 : : &lenp);
530 [ # # ]: 0 : if (!mac_addr) {
531 : 0 : FMAN_ERR(-EINVAL, "%s: no local-mac-address",
532 : : mname);
533 : 0 : goto err;
534 : : }
535 : 0 : memcpy(&__if->__if.mac_addr, mac_addr, ETHER_ADDR_LEN);
536 : :
537 : : /* Extract the channel ID (from tx-port-handle) */
538 : 0 : tx_channel_id = of_get_property(tx_node, "fsl,qman-channel-id",
539 : : &lenp);
540 [ # # ]: 0 : if (!tx_channel_id) {
541 : 0 : FMAN_ERR(-EINVAL, "%s: no fsl-qman-channel-id",
542 : : tx_node->full_name);
543 : 0 : goto err;
544 : : }
545 : : } else {
546 : : /* Extract the channel ID (from mac) */
547 : 0 : tx_channel_id = of_get_property(mac_node, "fsl,qman-channel-id",
548 : : &lenp);
549 [ # # ]: 0 : if (!tx_channel_id) {
550 : 0 : FMAN_ERR(-EINVAL, "%s: no fsl-qman-channel-id",
551 : : tx_node->full_name);
552 : 0 : goto err;
553 : : }
554 : : }
555 : :
556 : 0 : na = of_n_addr_cells(mac_node);
557 : 0 : __if->__if.tx_channel_id = of_read_number(tx_channel_id, na);
558 : :
559 [ # # ]: 0 : if (!is_offline)
560 : 0 : regs_addr = of_get_address(rx_node, 0, &__if->regs_size, NULL);
561 : : else
562 : 0 : regs_addr = of_get_address(oh_node, 0, &__if->regs_size, NULL);
563 [ # # ]: 0 : if (!regs_addr) {
564 : 0 : FMAN_ERR(-EINVAL, "of_get_address(%s)", mname);
565 : 0 : goto err;
566 : : }
567 : :
568 [ # # ]: 0 : if (!is_offline)
569 : 0 : phys_addr = of_translate_address(rx_node, regs_addr);
570 : : else
571 : 0 : phys_addr = of_translate_address(oh_node, regs_addr);
572 [ # # ]: 0 : if (!phys_addr) {
573 : 0 : FMAN_ERR(-EINVAL, "of_translate_address(%s, %p)",
574 : : mname, regs_addr);
575 : 0 : goto err;
576 : : }
577 : 0 : __if->bmi_map = mmap(NULL, __if->regs_size,
578 : : PROT_READ | PROT_WRITE, MAP_SHARED,
579 : : fman_ccsr_map_fd, phys_addr);
580 [ # # ]: 0 : if (__if->bmi_map == MAP_FAILED) {
581 : 0 : FMAN_ERR(-errno, "mmap(0x%"PRIx64")", phys_addr);
582 : 0 : goto err;
583 : : }
584 : :
585 [ # # ]: 0 : if (!is_offline) {
586 : 0 : regs_addr = of_get_address(tx_node, 0, &__if->regs_size, NULL);
587 [ # # ]: 0 : if (!regs_addr) {
588 : 0 : FMAN_ERR(-EINVAL, "of_get_address(%s)", mname);
589 : 0 : goto err;
590 : : }
591 : :
592 : 0 : phys_addr = of_translate_address(tx_node, regs_addr);
593 [ # # ]: 0 : if (!phys_addr) {
594 : 0 : FMAN_ERR(-EINVAL, "of_translate_address(%s, %p)",
595 : : mname, regs_addr);
596 : 0 : goto err;
597 : : }
598 : :
599 : 0 : __if->tx_bmi_map = mmap(NULL, __if->regs_size,
600 : : PROT_READ | PROT_WRITE, MAP_SHARED,
601 : : fman_ccsr_map_fd, phys_addr);
602 [ # # ]: 0 : if (__if->tx_bmi_map == MAP_FAILED) {
603 : 0 : FMAN_ERR(-errno, "mmap(0x%"PRIx64")", phys_addr);
604 : 0 : goto err;
605 : : }
606 : : }
607 : :
608 [ # # ]: 0 : if (!rtc_map) {
609 : 0 : __if->rtc_map = mmap(NULL, FMAN_IEEE_1588_SIZE,
610 : : PROT_READ | PROT_WRITE, MAP_SHARED,
611 : : fman_ccsr_map_fd, FMAN_IEEE_1588_OFFSET);
612 [ # # ]: 0 : if (__if->rtc_map == MAP_FAILED) {
613 : 0 : pr_err("Can not map FMan RTC regs base\n");
614 : : _errno = -EINVAL;
615 : 0 : goto err;
616 : : }
617 : 0 : rtc_map = __if->rtc_map;
618 : : } else {
619 : 0 : __if->rtc_map = rtc_map;
620 : : }
621 : :
622 : : /* Extract the Rx FQIDs. (Note, the device representation is silly,
623 : : * there are "counts" that must always be 1.)
624 : : */
625 : 0 : rx_phandle = of_get_property(dpa_node, rprop, &lenp);
626 [ # # ]: 0 : if (!rx_phandle) {
627 : 0 : FMAN_ERR(-EINVAL, "%s: no fsl,qman-frame-queues-rx", dname);
628 : 0 : goto err;
629 : : }
630 : :
631 : : /*
632 : : * Check if "fsl,qman-frame-queues-rx/oh" in dtb file is valid entry or
633 : : * not.
634 : : *
635 : : * A valid rx entry contains either 4 or 6 entries. Mandatory entries
636 : : * are rx_error_queue, rx_error_queue_count, fqid_rx_def and
637 : : * fqid_rx_def_count. Optional entries are fqid_rx_pcd and
638 : : * fqid_rx_pcd_count.
639 : : *
640 : : * A valid oh entry contains 4 entries. Those entries are
641 : : * rx_error_queue, rx_error_queue_count, fqid_rx_def and
642 : : * fqid_rx_def_count.
643 : : */
644 : :
645 [ # # ]: 0 : if (!is_offline)
646 [ # # ]: 0 : assert(lenp == (4 * sizeof(phandle)) ||
647 : : lenp == (6 * sizeof(phandle)));
648 : : else
649 [ # # ]: 0 : assert(lenp == (4 * sizeof(phandle)));
650 : :
651 : : /* Get rid of endianness (issues). Convert to host byte order */
652 : : rx_phandle_host[0] = of_read_number(&rx_phandle[0], na);
653 : 0 : rx_phandle_host[1] = of_read_number(&rx_phandle[1], na);
654 : 0 : rx_phandle_host[2] = of_read_number(&rx_phandle[2], na);
655 : 0 : rx_phandle_host[3] = of_read_number(&rx_phandle[3], na);
656 : 0 : rx_phandle_host[4] = of_read_number(&rx_phandle[4], na);
657 : 0 : rx_phandle_host[5] = of_read_number(&rx_phandle[5], na);
658 : :
659 [ # # # # ]: 0 : assert((rx_phandle_host[1] == 1) && (rx_phandle_host[3] == 1));
660 : 0 : __if->__if.fqid_rx_err = rx_phandle_host[0];
661 : 0 : __if->__if.fqid_rx_def = rx_phandle_host[2];
662 : :
663 : : /* If there are 6 entries in "fsl,qman-frame-queues-rx" in dtb file, it
664 : : * means PCD queues are also available. Hence, store that information.
665 : : */
666 [ # # ]: 0 : if (lenp == 6 * sizeof(phandle)) {
667 : 0 : __if->__if.fqid_rx_pcd = rx_phandle_host[4];
668 : 0 : __if->__if.fqid_rx_pcd_count = rx_phandle_host[5];
669 : : }
670 : :
671 [ # # ]: 0 : if (is_offline)
672 : 0 : goto oh_init_done;
673 : :
674 : : /* Extract the Tx FQIDs */
675 : 0 : tx_phandle = of_get_property(dpa_node,
676 : : "fsl,qman-frame-queues-tx", &lenp);
677 [ # # ]: 0 : if (!tx_phandle) {
678 : 0 : FMAN_ERR(-EINVAL, "%s: no fsl,qman-frame-queues-tx", dname);
679 : 0 : goto err;
680 : : }
681 : :
682 [ # # ]: 0 : assert(lenp >= (4 * sizeof(phandle)));
683 : : /*TODO: Fix for other cases also */
684 : 0 : na = of_n_addr_cells(mac_node);
685 : : /* Get rid of endianness (issues). Convert to host byte order */
686 : 0 : tx_phandle_host[0] = of_read_number(&tx_phandle[0], na);
687 : 0 : tx_phandle_host[1] = of_read_number(&tx_phandle[1], na);
688 : 0 : tx_phandle_host[2] = of_read_number(&tx_phandle[2], na);
689 : 0 : tx_phandle_host[3] = of_read_number(&tx_phandle[3], na);
690 [ # # # # ]: 0 : assert((tx_phandle_host[1] == 1) && (tx_phandle_host[3] == 1));
691 : 0 : __if->__if.fqid_tx_err = tx_phandle_host[0];
692 : 0 : __if->__if.fqid_tx_confirm = tx_phandle_host[2];
693 : :
694 : : /* Obtain the buffer pool nodes used by this interface */
695 : 0 : pools_phandle = of_get_property(dpa_node, "fsl,bman-buffer-pools",
696 : : &lenp);
697 [ # # ]: 0 : if (!pools_phandle) {
698 : 0 : FMAN_ERR(-EINVAL, "%s: no fsl,bman-buffer-pools", dname);
699 : 0 : goto err;
700 : : }
701 : : /* For each pool, parse the corresponding node and add a pool object
702 : : * to the interface's "bpool_list"
703 : : */
704 [ # # # # ]: 0 : assert(lenp && !(lenp % sizeof(phandle)));
705 [ # # ]: 0 : while (lenp) {
706 : : size_t proplen;
707 : : const phandle *prop;
708 : : uint64_t bpid_host = 0;
709 : : uint64_t bpool_host[6] = {0};
710 : : const char *pname;
711 : : /* Allocate an object for the pool */
712 : 0 : bpool = rte_malloc(NULL, sizeof(*bpool), RTE_CACHE_LINE_SIZE);
713 [ # # ]: 0 : if (!bpool) {
714 : 0 : FMAN_ERR(-ENOMEM, "malloc(%zu)", sizeof(*bpool));
715 : 0 : goto err;
716 : : }
717 : : /* Find the pool node */
718 : 0 : pool_node = of_find_node_by_phandle(*pools_phandle);
719 [ # # ]: 0 : if (!pool_node) {
720 : 0 : FMAN_ERR(-ENXIO, "%s: bad fsl,bman-buffer-pools",
721 : : dname);
722 : 0 : rte_free(bpool);
723 : 0 : goto err;
724 : : }
725 : 0 : pname = pool_node->full_name;
726 : : /* Extract the BPID property */
727 : 0 : prop = of_get_property(pool_node, "fsl,bpid", &proplen);
728 [ # # ]: 0 : if (!prop) {
729 : 0 : FMAN_ERR(-EINVAL, "%s: no fsl,bpid", pname);
730 : 0 : rte_free(bpool);
731 : 0 : goto err;
732 : : }
733 [ # # ]: 0 : assert(proplen == sizeof(*prop));
734 : 0 : na = of_n_addr_cells(mac_node);
735 : : /* Get rid of endianness (issues).
736 : : * Convert to host byte-order
737 : : */
738 : 0 : bpid_host = of_read_number(prop, na);
739 : 0 : bpool->bpid = bpid_host;
740 : : /* Extract the cfg property (count/size/addr). "fsl,bpool-cfg"
741 : : * indicates for the Bman driver to seed the pool.
742 : : * "fsl,bpool-ethernet-cfg" is used by the network driver. The
743 : : * two are mutually exclusive, so check for either of them.
744 : : */
745 : 0 : prop = of_get_property(pool_node, "fsl,bpool-cfg",
746 : : &proplen);
747 [ # # ]: 0 : if (!prop)
748 : 0 : prop = of_get_property(pool_node,
749 : : "fsl,bpool-ethernet-cfg",
750 : : &proplen);
751 [ # # ]: 0 : if (!prop) {
752 : : /* It's OK for there to be no bpool-cfg */
753 : 0 : bpool->count = bpool->size = bpool->addr = 0;
754 : : } else {
755 [ # # ]: 0 : assert(proplen == (6 * sizeof(*prop)));
756 : 0 : na = of_n_addr_cells(mac_node);
757 : : /* Get rid of endianness (issues).
758 : : * Convert to host byte order
759 : : */
760 : 0 : bpool_host[0] = of_read_number(&prop[0], na);
761 : 0 : bpool_host[1] = of_read_number(&prop[1], na);
762 : 0 : bpool_host[2] = of_read_number(&prop[2], na);
763 : 0 : bpool_host[3] = of_read_number(&prop[3], na);
764 : 0 : bpool_host[4] = of_read_number(&prop[4], na);
765 : 0 : bpool_host[5] = of_read_number(&prop[5], na);
766 : :
767 : 0 : bpool->count = ((uint64_t)bpool_host[0] << 32) |
768 : : bpool_host[1];
769 : 0 : bpool->size = ((uint64_t)bpool_host[2] << 32) |
770 : : bpool_host[3];
771 : 0 : bpool->addr = ((uint64_t)bpool_host[4] << 32) |
772 : : bpool_host[5];
773 : : }
774 : : /* Parsing of the pool is complete, add it to the interface
775 : : * list.
776 : : */
777 : 0 : list_add_tail(&bpool->node, &__if->__if.bpool_list);
778 : 0 : lenp -= sizeof(phandle);
779 : 0 : pools_phandle++;
780 : : }
781 : :
782 [ # # ]: 0 : if (is_shared)
783 : 0 : __if->__if.is_shared_mac = 1;
784 : :
785 : 0 : oh_init_done:
786 : 0 : fman_if_vsp_init(__if);
787 : :
788 : : /* Parsing of the network interface is complete, add it to the list */
789 : 0 : DPAA_BUS_LOG(DEBUG, "Found %s, Tx Channel = %x, FMAN = %x,"
790 : : "Port ID = %x",
791 : : dname, __if->__if.tx_channel_id, __if->__if.fman_idx,
792 : : __if->__if.mac_idx);
793 : :
794 : : /* Don't add OH port to the port list since they will be used by ONIC
795 : : * ports.
796 : : */
797 [ # # ]: 0 : if (!is_offline)
798 : 0 : list_add_tail(&__if->__if.node, &__ifs);
799 : :
800 : : return 0;
801 : 0 : err:
802 : 0 : if_destructor(__if);
803 : 0 : return _errno;
804 : : }
805 : :
806 : 0 : static int fman_if_init_onic(const struct device_node *dpa_node)
807 : : {
808 : : struct __fman_if *__if;
809 : : struct fman_if_bpool *bpool;
810 : : const phandle *tx_pools_phandle;
811 : : const phandle *tx_channel_id, *mac_addr, *cell_idx;
812 : : const phandle *rx_phandle;
813 : : const struct device_node *pool_node;
814 : : size_t lenp;
815 : : int _errno;
816 : : const phandle *p_onic_oh_nodes = NULL;
817 : : const struct device_node *rx_oh_node = NULL;
818 : : const struct device_node *tx_oh_node = NULL;
819 : : const phandle *p_fman_rx_oh_node = NULL, *p_fman_tx_oh_node = NULL;
820 : : const struct device_node *fman_rx_oh_node = NULL;
821 : : const struct device_node *fman_tx_oh_node = NULL;
822 : : const struct device_node *fman_node;
823 : : uint32_t na = OF_DEFAULT_NA;
824 : : uint64_t rx_phandle_host[4] = {0};
825 : : uint64_t cell_idx_host = 0;
826 : :
827 [ # # ]: 0 : if (of_device_is_available(dpa_node) == false)
828 : : return 0;
829 : :
830 [ # # ]: 0 : if (!of_device_is_compatible(dpa_node, "fsl,dpa-ethernet-generic"))
831 : : return 0;
832 : :
833 : : /* Allocate an object for this network interface */
834 : 0 : __if = rte_malloc(NULL, sizeof(*__if), RTE_CACHE_LINE_SIZE);
835 [ # # ]: 0 : if (!__if) {
836 : 0 : FMAN_ERR(-ENOMEM, "malloc(%zu)", sizeof(*__if));
837 : 0 : goto err;
838 : : }
839 : : memset(__if, 0, sizeof(*__if));
840 : :
841 : 0 : INIT_LIST_HEAD(&__if->__if.bpool_list);
842 : :
843 : 0 : strlcpy(__if->node_name, dpa_node->name, IF_NAME_MAX_LEN - 1);
844 : 0 : __if->node_name[IF_NAME_MAX_LEN - 1] = '\0';
845 : :
846 : 0 : strlcpy(__if->node_path, dpa_node->full_name, PATH_MAX - 1);
847 : 0 : __if->node_path[PATH_MAX - 1] = '\0';
848 : :
849 : : /* Mac node is onic */
850 : 0 : __if->__if.is_memac = 0;
851 : 0 : __if->__if.mac_type = fman_onic;
852 : :
853 : : /* Extract the MAC address for linux peer */
854 : 0 : mac_addr = of_get_property(dpa_node, "local-mac-address", &lenp);
855 [ # # ]: 0 : if (!mac_addr) {
856 : 0 : FMAN_ERR(-EINVAL, "%s: no local-mac-address",
857 : : dpa_node->full_name);
858 : 0 : goto err;
859 : : }
860 : :
861 : 0 : memcpy(&__if->__if.onic_info.peer_mac, mac_addr, ETHER_ADDR_LEN);
862 : :
863 : : /* Extract the Rx port (it's the first of the two port handles)
864 : : * and get its channel ID.
865 : : */
866 : 0 : p_onic_oh_nodes = of_get_property(dpa_node, "fsl,oh-ports", &lenp);
867 [ # # ]: 0 : if (!p_onic_oh_nodes) {
868 : 0 : FMAN_ERR(-EINVAL, "%s: couldn't get p_onic_oh_nodes",
869 : : dpa_node->full_name);
870 : 0 : goto err;
871 : : }
872 : :
873 : 0 : rx_oh_node = of_find_node_by_phandle(p_onic_oh_nodes[0]);
874 [ # # ]: 0 : if (!rx_oh_node) {
875 : 0 : FMAN_ERR(-EINVAL, "%s: couldn't get rx_oh_node",
876 : : dpa_node->full_name);
877 : 0 : goto err;
878 : : }
879 : :
880 : 0 : p_fman_rx_oh_node = of_get_property(rx_oh_node, "fsl,fman-oh-port",
881 : : &lenp);
882 [ # # ]: 0 : if (!p_fman_rx_oh_node) {
883 : 0 : FMAN_ERR(-EINVAL, "%s: couldn't get p_fman_rx_oh_node",
884 : : rx_oh_node->full_name);
885 : 0 : goto err;
886 : : }
887 : :
888 : 0 : fman_rx_oh_node = of_find_node_by_phandle(*p_fman_rx_oh_node);
889 [ # # ]: 0 : if (!fman_rx_oh_node) {
890 : 0 : FMAN_ERR(-EINVAL, "%s: couldn't get fman_rx_oh_node",
891 : : rx_oh_node->full_name);
892 : 0 : goto err;
893 : : }
894 : :
895 : 0 : tx_channel_id = of_get_property(fman_rx_oh_node, "fsl,qman-channel-id",
896 : : &lenp);
897 [ # # ]: 0 : if (!tx_channel_id) {
898 : 0 : FMAN_ERR(-EINVAL, "%s: no fsl-qman-channel-id",
899 : : rx_oh_node->full_name);
900 : 0 : goto err;
901 : : }
902 [ # # ]: 0 : assert(lenp == sizeof(*tx_channel_id));
903 : :
904 : 0 : __if->__if.tx_channel_id = of_read_number(tx_channel_id, na);
905 : :
906 : : /* Extract the FQs from which oNIC driver in Linux is dequeuing */
907 : 0 : rx_phandle = of_get_property(rx_oh_node, "fsl,qman-frame-queues-oh",
908 : : &lenp);
909 [ # # ]: 0 : if (!rx_phandle) {
910 : 0 : FMAN_ERR(-EINVAL, "%s: no fsl,qman-frame-queues-oh",
911 : : rx_oh_node->full_name);
912 : 0 : goto err;
913 : : }
914 [ # # ]: 0 : assert(lenp == (4 * sizeof(phandle)));
915 : :
916 : 0 : __if->__if.onic_info.rx_start = of_read_number(&rx_phandle[2], na);
917 : 0 : __if->__if.onic_info.rx_count = of_read_number(&rx_phandle[3], na);
918 : :
919 : : /* Extract the Rx FQIDs */
920 : 0 : tx_oh_node = of_find_node_by_phandle(p_onic_oh_nodes[1]);
921 [ # # ]: 0 : if (!tx_oh_node) {
922 : 0 : FMAN_ERR(-EINVAL, "%s: couldn't get tx_oh_node",
923 : : dpa_node->full_name);
924 : 0 : goto err;
925 : : }
926 : :
927 : 0 : p_fman_tx_oh_node = of_get_property(tx_oh_node, "fsl,fman-oh-port",
928 : : &lenp);
929 [ # # ]: 0 : if (!p_fman_tx_oh_node) {
930 : 0 : FMAN_ERR(-EINVAL, "%s: couldn't get p_fman_tx_oh_node",
931 : : tx_oh_node->full_name);
932 : 0 : goto err;
933 : : }
934 : :
935 : 0 : fman_tx_oh_node = of_find_node_by_phandle(*p_fman_tx_oh_node);
936 [ # # ]: 0 : if (!fman_tx_oh_node) {
937 : 0 : FMAN_ERR(-EINVAL, "%s: couldn't get fman_tx_oh_node",
938 : : tx_oh_node->full_name);
939 : 0 : goto err;
940 : : }
941 : :
942 : 0 : cell_idx = of_get_property(fman_tx_oh_node, "cell-index", &lenp);
943 [ # # ]: 0 : if (!cell_idx) {
944 : 0 : FMAN_ERR(-ENXIO, "%s: no cell-index)", tx_oh_node->full_name);
945 : 0 : goto err;
946 : : }
947 [ # # ]: 0 : assert(lenp == sizeof(*cell_idx));
948 : :
949 : : cell_idx_host = of_read_number(cell_idx, lenp / sizeof(phandle));
950 : 0 : __if->__if.mac_idx = cell_idx_host;
951 : :
952 : 0 : fman_node = of_get_parent(fman_tx_oh_node);
953 : 0 : cell_idx = of_get_property(fman_node, "cell-index", &lenp);
954 [ # # ]: 0 : if (!cell_idx) {
955 : 0 : FMAN_ERR(-ENXIO, "%s: no cell-index)", tx_oh_node->full_name);
956 : 0 : goto err;
957 : : }
958 [ # # ]: 0 : assert(lenp == sizeof(*cell_idx));
959 : :
960 : : cell_idx_host = of_read_number(cell_idx, lenp / sizeof(phandle));
961 : 0 : __if->__if.fman_idx = cell_idx_host;
962 : :
963 : 0 : rx_phandle = of_get_property(tx_oh_node, "fsl,qman-frame-queues-oh",
964 : : &lenp);
965 [ # # ]: 0 : if (!rx_phandle) {
966 : 0 : FMAN_ERR(-EINVAL, "%s: no fsl,qman-frame-queues-oh",
967 : : dpa_node->full_name);
968 : 0 : goto err;
969 : : }
970 [ # # ]: 0 : assert(lenp == (4 * sizeof(phandle)));
971 : :
972 : : rx_phandle_host[0] = of_read_number(&rx_phandle[0], na);
973 : 0 : rx_phandle_host[1] = of_read_number(&rx_phandle[1], na);
974 : 0 : rx_phandle_host[2] = of_read_number(&rx_phandle[2], na);
975 : 0 : rx_phandle_host[3] = of_read_number(&rx_phandle[3], na);
976 : :
977 [ # # # # ]: 0 : assert((rx_phandle_host[1] == 1) && (rx_phandle_host[3] == 1));
978 : :
979 : 0 : __if->__if.fqid_rx_err = rx_phandle_host[0];
980 : 0 : __if->__if.fqid_rx_def = rx_phandle_host[2];
981 : :
982 : : /* Don't Extract the Tx FQIDs */
983 : 0 : __if->__if.fqid_tx_err = 0;
984 : 0 : __if->__if.fqid_tx_confirm = 0;
985 : :
986 : : /* Obtain the buffer pool nodes used by Tx OH port */
987 : 0 : tx_pools_phandle = of_get_property(tx_oh_node, "fsl,bman-buffer-pools",
988 : : &lenp);
989 [ # # ]: 0 : if (!tx_pools_phandle) {
990 : 0 : FMAN_ERR(-EINVAL, "%s: no fsl,bman-buffer-pools",
991 : : tx_oh_node->full_name);
992 : 0 : goto err;
993 : : }
994 [ # # # # ]: 0 : assert(lenp && !(lenp % sizeof(phandle)));
995 : :
996 : : /* For each pool, parse the corresponding node and add a pool object to
997 : : * the interface's "bpool_list".
998 : : */
999 : :
1000 [ # # ]: 0 : while (lenp) {
1001 : : size_t proplen;
1002 : : const phandle *prop;
1003 : : uint64_t bpool_host[6] = {0};
1004 : :
1005 : : /* Allocate an object for the pool */
1006 : 0 : bpool = rte_malloc(NULL, sizeof(*bpool), RTE_CACHE_LINE_SIZE);
1007 [ # # ]: 0 : if (!bpool) {
1008 : 0 : FMAN_ERR(-ENOMEM, "malloc(%zu)", sizeof(*bpool));
1009 : 0 : goto err;
1010 : : }
1011 : :
1012 : : /* Find the pool node */
1013 : 0 : pool_node = of_find_node_by_phandle(*tx_pools_phandle);
1014 [ # # ]: 0 : if (!pool_node) {
1015 : 0 : FMAN_ERR(-ENXIO, "%s: bad fsl,bman-buffer-pools",
1016 : : tx_oh_node->full_name);
1017 : 0 : rte_free(bpool);
1018 : 0 : goto err;
1019 : : }
1020 : :
1021 : : /* Extract the BPID property */
1022 : 0 : prop = of_get_property(pool_node, "fsl,bpid", &proplen);
1023 [ # # ]: 0 : if (!prop) {
1024 : 0 : FMAN_ERR(-EINVAL, "%s: no fsl,bpid",
1025 : : pool_node->full_name);
1026 : 0 : rte_free(bpool);
1027 : 0 : goto err;
1028 : : }
1029 [ # # ]: 0 : assert(proplen == sizeof(*prop));
1030 : :
1031 : 0 : bpool->bpid = of_read_number(prop, na);
1032 : :
1033 : : /* Extract the cfg property (count/size/addr). "fsl,bpool-cfg"
1034 : : * indicates for the Bman driver to seed the pool.
1035 : : * "fsl,bpool-ethernet-cfg" is used by the network driver. The
1036 : : * two are mutually exclusive, so check for either of them.
1037 : : */
1038 : :
1039 : 0 : prop = of_get_property(pool_node, "fsl,bpool-cfg", &proplen);
1040 [ # # ]: 0 : if (!prop)
1041 : 0 : prop = of_get_property(pool_node,
1042 : : "fsl,bpool-ethernet-cfg",
1043 : : &proplen);
1044 [ # # ]: 0 : if (!prop) {
1045 : : /* It's OK for there to be no bpool-cfg */
1046 : 0 : bpool->count = bpool->size = bpool->addr = 0;
1047 : : } else {
1048 [ # # ]: 0 : assert(proplen == (6 * sizeof(*prop)));
1049 : :
1050 : : bpool_host[0] = of_read_number(&prop[0], na);
1051 : 0 : bpool_host[1] = of_read_number(&prop[1], na);
1052 : 0 : bpool_host[2] = of_read_number(&prop[2], na);
1053 : 0 : bpool_host[3] = of_read_number(&prop[3], na);
1054 : 0 : bpool_host[4] = of_read_number(&prop[4], na);
1055 : 0 : bpool_host[5] = of_read_number(&prop[5], na);
1056 : :
1057 : 0 : bpool->count = ((uint64_t)bpool_host[0] << 32) |
1058 : : bpool_host[1];
1059 : 0 : bpool->size = ((uint64_t)bpool_host[2] << 32) |
1060 : : bpool_host[3];
1061 : 0 : bpool->addr = ((uint64_t)bpool_host[4] << 32) |
1062 : : bpool_host[5];
1063 : : }
1064 : :
1065 : : /* Parsing of the pool is complete, add it to the interface
1066 : : * list.
1067 : : */
1068 : 0 : list_add_tail(&bpool->node, &__if->__if.bpool_list);
1069 : 0 : lenp -= sizeof(phandle);
1070 : 0 : tx_pools_phandle++;
1071 : : }
1072 : :
1073 : 0 : fman_if_vsp_init(__if);
1074 : :
1075 : : /* Parsing of the network interface is complete, add it to the list. */
1076 : 0 : DPAA_BUS_DEBUG("Found %s, Tx Channel = %x, FMAN = %x, Port ID = %x",
1077 : : dpa_node->full_name, __if->__if.tx_channel_id,
1078 : : __if->__if.fman_idx, __if->__if.mac_idx);
1079 : :
1080 : 0 : list_add_tail(&__if->__if.node, &__ifs);
1081 : 0 : return 0;
1082 : 0 : err:
1083 : 0 : if_destructor(__if);
1084 : 0 : return _errno;
1085 : : }
1086 : :
1087 : : int
1088 : 0 : fman_init(void)
1089 : : {
1090 : : const struct device_node *dpa_node, *parent_node;
1091 : : int _errno;
1092 : :
1093 : : /* If multiple dependencies try to initialise the Fman driver, don't
1094 : : * panic.
1095 : : */
1096 [ # # ]: 0 : if (fman_ccsr_map_fd != -1)
1097 : : return 0;
1098 : :
1099 : 0 : fman_ccsr_map_fd = open(FMAN_DEVICE_PATH, O_RDWR);
1100 [ # # ]: 0 : if (unlikely(fman_ccsr_map_fd < 0)) {
1101 : 0 : DPAA_BUS_LOG(ERR, "Unable to open (/dev/mem)");
1102 : 0 : return fman_ccsr_map_fd;
1103 : : }
1104 : :
1105 : 0 : parent_node = of_find_compatible_node(NULL, NULL, "fsl,dpaa");
1106 [ # # ]: 0 : if (!parent_node) {
1107 : 0 : DPAA_BUS_LOG(ERR, "Unable to find fsl,dpaa node");
1108 : 0 : return -ENODEV;
1109 : : }
1110 : :
1111 [ # # ]: 0 : for_each_child_node(parent_node, dpa_node) {
1112 : 0 : _errno = fman_if_init(dpa_node);
1113 [ # # ]: 0 : if (_errno) {
1114 : 0 : FMAN_ERR(_errno, "if_init(%s)", dpa_node->full_name);
1115 : 0 : goto err;
1116 : : }
1117 : : }
1118 : :
1119 [ # # ]: 0 : for_each_compatible_node(dpa_node, NULL, "fsl,dpa-ethernet-generic") {
1120 : : /* it is a oNIC interface */
1121 : 0 : _errno = fman_if_init_onic(dpa_node);
1122 [ # # ]: 0 : if (_errno)
1123 : 0 : FMAN_ERR(_errno, "if_init(%s)", dpa_node->full_name);
1124 : : }
1125 : :
1126 : : return 0;
1127 : : err:
1128 : 0 : fman_finish();
1129 : 0 : return _errno;
1130 : : }
1131 : :
1132 : : void
1133 : 0 : fman_finish(void)
1134 : : {
1135 : : struct __fman_if *__if, *tmpif;
1136 : :
1137 [ # # ]: 0 : assert(fman_ccsr_map_fd != -1);
1138 : :
1139 [ # # ]: 0 : list_for_each_entry_safe(__if, tmpif, &__ifs, __if.node) {
1140 : : int _errno;
1141 : :
1142 : : /* No need to disable Offline port */
1143 [ # # ]: 0 : if (__if->__if.mac_type == fman_offline_internal)
1144 : 0 : continue;
1145 : :
1146 : : /* disable Rx and Tx */
1147 [ # # ]: 0 : if ((__if->__if.mac_type == fman_mac_1g) &&
1148 [ # # ]: 0 : (!__if->__if.is_memac))
1149 [ # # ]: 0 : out_be32(__if->ccsr_map + 0x100,
1150 : 0 : in_be32(__if->ccsr_map + 0x100) & ~(u32)0x5);
1151 : : else
1152 [ # # ]: 0 : out_be32(__if->ccsr_map + 8,
1153 : 0 : in_be32(__if->ccsr_map + 8) & ~(u32)3);
1154 : : /* release the mapping */
1155 : 0 : _errno = munmap(__if->ccsr_map, __if->regs_size);
1156 [ # # ]: 0 : if (unlikely(_errno < 0))
1157 : 0 : FMAN_ERR(_errno, "munmap() = (%s)", strerror(errno));
1158 : 0 : DPAA_BUS_INFO("Tearing down %s", __if->node_path);
1159 : 0 : list_del(&__if->__if.node);
1160 : 0 : rte_free(__if);
1161 : : }
1162 : :
1163 : 0 : close(fman_ccsr_map_fd);
1164 : 0 : fman_ccsr_map_fd = -1;
1165 : 0 : }
|