New upstream version 17.11.5
[deb_dpdk.git] / drivers / bus / dpaa / base / fman / fman.c
1 /*-
2  * This file is provided under a dual BSD/GPLv2 license. When using or
3  * redistributing this file, you may do so under either license.
4  *
5  *   BSD LICENSE
6  *
7  * Copyright 2010-2016 Freescale Semiconductor Inc.
8  * Copyright 2017 NXP.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions are met:
12  * * Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  * * Redistributions in binary form must reproduce the above copyright
15  * notice, this list of conditions and the following disclaimer in the
16  * documentation and/or other materials provided with the distribution.
17  * * Neither the name of the above-listed copyright holders nor the
18  * names of any contributors may be used to endorse or promote products
19  * derived from this software without specific prior written permission.
20  *
21  *   GPL LICENSE SUMMARY
22  *
23  * ALTERNATIVELY, this software may be distributed under the terms of the
24  * GNU General Public License ("GPL") as published by the Free Software
25  * Foundation, either version 2 of that License or (at your option) any
26  * later version.
27  *
28  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
29  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
32  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
33  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
34  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
35  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
36  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
37  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38  * POSSIBILITY OF SUCH DAMAGE.
39  */
40
41 #include <sys/types.h>
42 #include <sys/ioctl.h>
43 #include <ifaddrs.h>
44
45 /* This header declares the driver interface we implement */
46 #include <fman.h>
47 #include <of.h>
48 #include <rte_dpaa_logs.h>
49 #include <rte_string_fns.h>
50
51 #define QMI_PORT_REGS_OFFSET            0x400
52
53 /* CCSR map address to access ccsr based register */
54 void *fman_ccsr_map;
55 /* fman version info */
56 u16 fman_ip_rev;
57 static int get_once;
58 u32 fman_dealloc_bufs_mask_hi;
59 u32 fman_dealloc_bufs_mask_lo;
60
61 int fman_ccsr_map_fd = -1;
62 static COMPAT_LIST_HEAD(__ifs);
63
64 /* This is the (const) global variable that callers have read-only access to.
65  * Internally, we have read-write access directly to __ifs.
66  */
67 const struct list_head *fman_if_list = &__ifs;
68
69 static void
70 if_destructor(struct __fman_if *__if)
71 {
72         struct fman_if_bpool *bp, *tmpbp;
73
74         if (!__if)
75                 return;
76
77         if (__if->__if.mac_type == fman_offline)
78                 goto cleanup;
79
80         list_for_each_entry_safe(bp, tmpbp, &__if->__if.bpool_list, node) {
81                 list_del(&bp->node);
82                 free(bp);
83         }
84 cleanup:
85         free(__if);
86 }
87
88 static int
89 fman_get_ip_rev(const struct device_node *fman_node)
90 {
91         const uint32_t *fman_addr;
92         uint64_t phys_addr;
93         uint64_t regs_size;
94         uint32_t ip_rev_1;
95         int _errno;
96
97         fman_addr = of_get_address(fman_node, 0, &regs_size, NULL);
98         if (!fman_addr) {
99                 pr_err("of_get_address cannot return fman address\n");
100                 return -EINVAL;
101         }
102         phys_addr = of_translate_address(fman_node, fman_addr);
103         if (!phys_addr) {
104                 pr_err("of_translate_address failed\n");
105                 return -EINVAL;
106         }
107         fman_ccsr_map = mmap(NULL, regs_size, PROT_READ | PROT_WRITE,
108                              MAP_SHARED, fman_ccsr_map_fd, phys_addr);
109         if (fman_ccsr_map == MAP_FAILED) {
110                 pr_err("Can not map FMan ccsr base");
111                 return -EINVAL;
112         }
113
114         ip_rev_1 = in_be32(fman_ccsr_map + FMAN_IP_REV_1);
115         fman_ip_rev = (ip_rev_1 & FMAN_IP_REV_1_MAJOR_MASK) >>
116                         FMAN_IP_REV_1_MAJOR_SHIFT;
117
118         _errno = munmap(fman_ccsr_map, regs_size);
119         if (_errno)
120                 pr_err("munmap() of FMan ccsr failed");
121
122         return 0;
123 }
124
125 static int
126 fman_get_mac_index(uint64_t regs_addr_host, uint8_t *mac_idx)
127 {
128         int ret = 0;
129
130         /*
131          * MAC1 : E_0000h
132          * MAC2 : E_2000h
133          * MAC3 : E_4000h
134          * MAC4 : E_6000h
135          * MAC5 : E_8000h
136          * MAC6 : E_A000h
137          * MAC7 : E_C000h
138          * MAC8 : E_E000h
139          * MAC9 : F_0000h
140          * MAC10: F_2000h
141          */
142         switch (regs_addr_host) {
143         case 0xE0000:
144                 *mac_idx = 1;
145                 break;
146         case 0xE2000:
147                 *mac_idx = 2;
148                 break;
149         case 0xE4000:
150                 *mac_idx = 3;
151                 break;
152         case 0xE6000:
153                 *mac_idx = 4;
154                 break;
155         case 0xE8000:
156                 *mac_idx = 5;
157                 break;
158         case 0xEA000:
159                 *mac_idx = 6;
160                 break;
161         case 0xEC000:
162                 *mac_idx = 7;
163                 break;
164         case 0xEE000:
165                 *mac_idx = 8;
166                 break;
167         case 0xF0000:
168                 *mac_idx = 9;
169                 break;
170         case 0xF2000:
171                 *mac_idx = 10;
172                 break;
173         default:
174                 ret = -EINVAL;
175         }
176
177         return ret;
178 }
179
180 static int
181 fman_if_init(const struct device_node *dpa_node)
182 {
183         const char *rprop, *mprop;
184         uint64_t phys_addr;
185         struct __fman_if *__if;
186         struct fman_if_bpool *bpool;
187
188         const phandle *mac_phandle, *ports_phandle, *pools_phandle;
189         const phandle *tx_channel_id = NULL, *mac_addr, *cell_idx;
190         const phandle *rx_phandle, *tx_phandle;
191         uint64_t tx_phandle_host[4] = {0};
192         uint64_t rx_phandle_host[4] = {0};
193         uint64_t regs_addr_host = 0;
194         uint64_t cell_idx_host = 0;
195
196         const struct device_node *mac_node = NULL, *tx_node;
197         const struct device_node *pool_node, *fman_node, *rx_node;
198         const uint32_t *regs_addr = NULL;
199         const char *mname, *fname;
200         const char *dname = dpa_node->full_name;
201         size_t lenp;
202         int _errno;
203         const char *char_prop;
204         uint32_t na;
205
206         if (of_device_is_available(dpa_node) == false)
207                 return 0;
208
209         rprop = "fsl,qman-frame-queues-rx";
210         mprop = "fsl,fman-mac";
211
212         /* Allocate an object for this network interface */
213         __if = malloc(sizeof(*__if));
214         if (!__if) {
215                 FMAN_ERR(-ENOMEM, "malloc(%zu)\n", sizeof(*__if));
216                 goto err;
217         }
218         memset(__if, 0, sizeof(*__if));
219         INIT_LIST_HEAD(&__if->__if.bpool_list);
220         strlcpy(__if->node_path, dpa_node->full_name, PATH_MAX - 1);
221         __if->node_path[PATH_MAX - 1] = '\0';
222
223         /* Obtain the MAC node used by this interface except macless */
224         mac_phandle = of_get_property(dpa_node, mprop, &lenp);
225         if (!mac_phandle) {
226                 FMAN_ERR(-EINVAL, "%s: no %s\n", dname, mprop);
227                 goto err;
228         }
229         assert(lenp == sizeof(phandle));
230         mac_node = of_find_node_by_phandle(*mac_phandle);
231         if (!mac_node) {
232                 FMAN_ERR(-ENXIO, "%s: bad 'fsl,fman-mac\n", dname);
233                 goto err;
234         }
235         mname = mac_node->full_name;
236
237         /* Map the CCSR regs for the MAC node */
238         regs_addr = of_get_address(mac_node, 0, &__if->regs_size, NULL);
239         if (!regs_addr) {
240                 FMAN_ERR(-EINVAL, "of_get_address(%s)\n", mname);
241                 goto err;
242         }
243         phys_addr = of_translate_address(mac_node, regs_addr);
244         if (!phys_addr) {
245                 FMAN_ERR(-EINVAL, "of_translate_address(%s, %p)\n",
246                          mname, regs_addr);
247                 goto err;
248         }
249         __if->ccsr_map = mmap(NULL, __if->regs_size,
250                               PROT_READ | PROT_WRITE, MAP_SHARED,
251                               fman_ccsr_map_fd, phys_addr);
252         if (__if->ccsr_map == MAP_FAILED) {
253                 FMAN_ERR(-errno, "mmap(0x%"PRIx64")\n", phys_addr);
254                 goto err;
255         }
256         na = of_n_addr_cells(mac_node);
257         /* Get rid of endianness (issues). Convert to host byte order */
258         regs_addr_host = of_read_number(regs_addr, na);
259
260
261         /* Get the index of the Fman this i/f belongs to */
262         fman_node = of_get_parent(mac_node);
263         na = of_n_addr_cells(mac_node);
264         if (!fman_node) {
265                 FMAN_ERR(-ENXIO, "of_get_parent(%s)\n", mname);
266                 goto err;
267         }
268         fname = fman_node->full_name;
269         cell_idx = of_get_property(fman_node, "cell-index", &lenp);
270         if (!cell_idx) {
271                 FMAN_ERR(-ENXIO, "%s: no cell-index)\n", fname);
272                 goto err;
273         }
274         assert(lenp == sizeof(*cell_idx));
275         cell_idx_host = of_read_number(cell_idx, lenp / sizeof(phandle));
276         __if->__if.fman_idx = cell_idx_host;
277         if (!get_once) {
278                 _errno = fman_get_ip_rev(fman_node);
279                 if (_errno) {
280                         FMAN_ERR(-ENXIO, "%s: ip_rev is not available\n",
281                                  fname);
282                         goto err;
283                 }
284         }
285
286         if (fman_ip_rev >= FMAN_V3) {
287                 /*
288                  * Set A2V, OVOM, EBD bits in contextA to allow external
289                  * buffer deallocation by fman.
290                  */
291                 fman_dealloc_bufs_mask_hi = FMAN_V3_CONTEXTA_EN_A2V |
292                                                 FMAN_V3_CONTEXTA_EN_OVOM;
293                 fman_dealloc_bufs_mask_lo = FMAN_V3_CONTEXTA_EN_EBD;
294         } else {
295                 fman_dealloc_bufs_mask_hi = 0;
296                 fman_dealloc_bufs_mask_lo = 0;
297         }
298         /* Is the MAC node 1G, 10G? */
299         __if->__if.is_memac = 0;
300
301         if (of_device_is_compatible(mac_node, "fsl,fman-1g-mac"))
302                 __if->__if.mac_type = fman_mac_1g;
303         else if (of_device_is_compatible(mac_node, "fsl,fman-10g-mac"))
304                 __if->__if.mac_type = fman_mac_10g;
305         else if (of_device_is_compatible(mac_node, "fsl,fman-memac")) {
306                 __if->__if.is_memac = 1;
307                 char_prop = of_get_property(mac_node, "phy-connection-type",
308                                             NULL);
309                 if (!char_prop) {
310                         printf("memac: unknown MII type assuming 1G\n");
311                         /* Right now forcing memac to 1g in case of error*/
312                         __if->__if.mac_type = fman_mac_1g;
313                 } else {
314                         if (strstr(char_prop, "sgmii"))
315                                 __if->__if.mac_type = fman_mac_1g;
316                         else if (strstr(char_prop, "rgmii")) {
317                                 __if->__if.mac_type = fman_mac_1g;
318                                 __if->__if.is_rgmii = 1;
319                         } else if (strstr(char_prop, "xgmii"))
320                                 __if->__if.mac_type = fman_mac_10g;
321                 }
322         } else {
323                 FMAN_ERR(-EINVAL, "%s: unknown MAC type\n", mname);
324                 goto err;
325         }
326
327         /*
328          * For MAC ports, we cannot rely on cell-index. In
329          * T2080, two of the 10G ports on single FMAN have same
330          * duplicate cell-indexes as the other two 10G ports on
331          * same FMAN. Hence, we now rely upon addresses of the
332          * ports from device tree to deduce the index.
333          */
334
335         _errno = fman_get_mac_index(regs_addr_host, &__if->__if.mac_idx);
336         if (_errno) {
337                 FMAN_ERR(-EINVAL, "Invalid register address: %lu",
338                          regs_addr_host);
339                 goto err;
340         }
341
342         /* Extract the MAC address for private and shared interfaces */
343         mac_addr = of_get_property(mac_node, "local-mac-address",
344                                    &lenp);
345         if (!mac_addr) {
346                 FMAN_ERR(-EINVAL, "%s: no local-mac-address\n",
347                          mname);
348                 goto err;
349         }
350         memcpy(&__if->__if.mac_addr, mac_addr, ETHER_ADDR_LEN);
351
352         /* Extract the Tx port (it's the second of the two port handles)
353          * and get its channel ID
354          */
355         ports_phandle = of_get_property(mac_node, "fsl,port-handles",
356                                         &lenp);
357         if (!ports_phandle)
358                 ports_phandle = of_get_property(mac_node, "fsl,fman-ports",
359                                                 &lenp);
360         if (!ports_phandle) {
361                 FMAN_ERR(-EINVAL, "%s: no fsl,port-handles\n",
362                          mname);
363                 goto err;
364         }
365         assert(lenp == (2 * sizeof(phandle)));
366         tx_node = of_find_node_by_phandle(ports_phandle[1]);
367         if (!tx_node) {
368                 FMAN_ERR(-ENXIO, "%s: bad fsl,port-handle[1]\n", mname);
369                 goto err;
370         }
371         /* Extract the channel ID (from tx-port-handle) */
372         tx_channel_id = of_get_property(tx_node, "fsl,qman-channel-id",
373                                         &lenp);
374         if (!tx_channel_id) {
375                 FMAN_ERR(-EINVAL, "%s: no fsl-qman-channel-id\n",
376                          tx_node->full_name);
377                 goto err;
378         }
379
380         rx_node = of_find_node_by_phandle(ports_phandle[0]);
381         if (!rx_node) {
382                 FMAN_ERR(-ENXIO, "%s: bad fsl,port-handle[0]\n", mname);
383                 goto err;
384         }
385         regs_addr = of_get_address(rx_node, 0, &__if->regs_size, NULL);
386         if (!regs_addr) {
387                 FMAN_ERR(-EINVAL, "of_get_address(%s)\n", mname);
388                 goto err;
389         }
390         phys_addr = of_translate_address(rx_node, regs_addr);
391         if (!phys_addr) {
392                 FMAN_ERR(-EINVAL, "of_translate_address(%s, %p)\n",
393                          mname, regs_addr);
394                 goto err;
395         }
396         __if->bmi_map = mmap(NULL, __if->regs_size,
397                                  PROT_READ | PROT_WRITE, MAP_SHARED,
398                                  fman_ccsr_map_fd, phys_addr);
399         if (__if->bmi_map == MAP_FAILED) {
400                 FMAN_ERR(-errno, "mmap(0x%"PRIx64")\n", phys_addr);
401                 goto err;
402         }
403
404         /* No channel ID for MAC-less */
405         assert(lenp == sizeof(*tx_channel_id));
406         na = of_n_addr_cells(mac_node);
407         __if->__if.tx_channel_id = of_read_number(tx_channel_id, na);
408
409         /* Extract the Rx FQIDs. (Note, the device representation is silly,
410          * there are "counts" that must always be 1.)
411          */
412         rx_phandle = of_get_property(dpa_node, rprop, &lenp);
413         if (!rx_phandle) {
414                 FMAN_ERR(-EINVAL, "%s: no fsl,qman-frame-queues-rx\n", dname);
415                 goto err;
416         }
417
418         assert(lenp == (4 * sizeof(phandle)));
419
420         na = of_n_addr_cells(mac_node);
421         /* Get rid of endianness (issues). Convert to host byte order */
422         rx_phandle_host[0] = of_read_number(&rx_phandle[0], na);
423         rx_phandle_host[1] = of_read_number(&rx_phandle[1], na);
424         rx_phandle_host[2] = of_read_number(&rx_phandle[2], na);
425         rx_phandle_host[3] = of_read_number(&rx_phandle[3], na);
426
427         assert((rx_phandle_host[1] == 1) && (rx_phandle_host[3] == 1));
428         __if->__if.fqid_rx_err = rx_phandle_host[0];
429         __if->__if.fqid_rx_def = rx_phandle_host[2];
430
431         /* Extract the Tx FQIDs */
432         tx_phandle = of_get_property(dpa_node,
433                                      "fsl,qman-frame-queues-tx", &lenp);
434         if (!tx_phandle) {
435                 FMAN_ERR(-EINVAL, "%s: no fsl,qman-frame-queues-tx\n", dname);
436                 goto err;
437         }
438
439         assert(lenp == (4 * sizeof(phandle)));
440         /*TODO: Fix for other cases also */
441         na = of_n_addr_cells(mac_node);
442         /* Get rid of endianness (issues). Convert to host byte order */
443         tx_phandle_host[0] = of_read_number(&tx_phandle[0], na);
444         tx_phandle_host[1] = of_read_number(&tx_phandle[1], na);
445         tx_phandle_host[2] = of_read_number(&tx_phandle[2], na);
446         tx_phandle_host[3] = of_read_number(&tx_phandle[3], na);
447         assert((tx_phandle_host[1] == 1) && (tx_phandle_host[3] == 1));
448         __if->__if.fqid_tx_err = tx_phandle_host[0];
449         __if->__if.fqid_tx_confirm = tx_phandle_host[2];
450
451         /* Obtain the buffer pool nodes used by this interface */
452         pools_phandle = of_get_property(dpa_node, "fsl,bman-buffer-pools",
453                                         &lenp);
454         if (!pools_phandle) {
455                 FMAN_ERR(-EINVAL, "%s: no fsl,bman-buffer-pools\n", dname);
456                 goto err;
457         }
458         /* For each pool, parse the corresponding node and add a pool object
459          * to the interface's "bpool_list"
460          */
461         assert(lenp && !(lenp % sizeof(phandle)));
462         while (lenp) {
463                 size_t proplen;
464                 const phandle *prop;
465                 uint64_t bpid_host = 0;
466                 uint64_t bpool_host[6] = {0};
467                 const char *pname;
468                 /* Allocate an object for the pool */
469                 bpool = malloc(sizeof(*bpool));
470                 if (!bpool) {
471                         FMAN_ERR(-ENOMEM, "malloc(%zu)\n", sizeof(*bpool));
472                         goto err;
473                 }
474                 /* Find the pool node */
475                 pool_node = of_find_node_by_phandle(*pools_phandle);
476                 if (!pool_node) {
477                         FMAN_ERR(-ENXIO, "%s: bad fsl,bman-buffer-pools\n",
478                                  dname);
479                         free(bpool);
480                         goto err;
481                 }
482                 pname = pool_node->full_name;
483                 /* Extract the BPID property */
484                 prop = of_get_property(pool_node, "fsl,bpid", &proplen);
485                 if (!prop) {
486                         FMAN_ERR(-EINVAL, "%s: no fsl,bpid\n", pname);
487                         free(bpool);
488                         goto err;
489                 }
490                 assert(proplen == sizeof(*prop));
491                 na = of_n_addr_cells(mac_node);
492                 /* Get rid of endianness (issues).
493                  * Convert to host byte-order
494                  */
495                 bpid_host = of_read_number(prop, na);
496                 bpool->bpid = bpid_host;
497                 /* Extract the cfg property (count/size/addr). "fsl,bpool-cfg"
498                  * indicates for the Bman driver to seed the pool.
499                  * "fsl,bpool-ethernet-cfg" is used by the network driver. The
500                  * two are mutually exclusive, so check for either of them.
501                  */
502                 prop = of_get_property(pool_node, "fsl,bpool-cfg",
503                                        &proplen);
504                 if (!prop)
505                         prop = of_get_property(pool_node,
506                                                "fsl,bpool-ethernet-cfg",
507                                                &proplen);
508                 if (!prop) {
509                         /* It's OK for there to be no bpool-cfg */
510                         bpool->count = bpool->size = bpool->addr = 0;
511                 } else {
512                         assert(proplen == (6 * sizeof(*prop)));
513                         na = of_n_addr_cells(mac_node);
514                         /* Get rid of endianness (issues).
515                          * Convert to host byte order
516                          */
517                         bpool_host[0] = of_read_number(&prop[0], na);
518                         bpool_host[1] = of_read_number(&prop[1], na);
519                         bpool_host[2] = of_read_number(&prop[2], na);
520                         bpool_host[3] = of_read_number(&prop[3], na);
521                         bpool_host[4] = of_read_number(&prop[4], na);
522                         bpool_host[5] = of_read_number(&prop[5], na);
523
524                         bpool->count = ((uint64_t)bpool_host[0] << 32) |
525                                         bpool_host[1];
526                         bpool->size = ((uint64_t)bpool_host[2] << 32) |
527                                         bpool_host[3];
528                         bpool->addr = ((uint64_t)bpool_host[4] << 32) |
529                                         bpool_host[5];
530                 }
531                 /* Parsing of the pool is complete, add it to the interface
532                  * list.
533                  */
534                 list_add_tail(&bpool->node, &__if->__if.bpool_list);
535                 lenp -= sizeof(phandle);
536                 pools_phandle++;
537         }
538
539         /* Parsing of the network interface is complete, add it to the list */
540         DPAA_BUS_LOG(DEBUG, "Found %s, Tx Channel = %x, FMAN = %x,"
541                     "Port ID = %x\n",
542                     dname, __if->__if.tx_channel_id, __if->__if.fman_idx,
543                     __if->__if.mac_idx);
544
545         list_add_tail(&__if->__if.node, &__ifs);
546         return 0;
547 err:
548         if_destructor(__if);
549         return _errno;
550 }
551
552 int
553 fman_init(void)
554 {
555         const struct device_node *dpa_node;
556         int _errno;
557
558         /* If multiple dependencies try to initialise the Fman driver, don't
559          * panic.
560          */
561         if (fman_ccsr_map_fd != -1)
562                 return 0;
563
564         fman_ccsr_map_fd = open(FMAN_DEVICE_PATH, O_RDWR);
565         if (unlikely(fman_ccsr_map_fd < 0)) {
566                 DPAA_BUS_LOG(ERR, "Unable to open (/dev/mem)");
567                 return fman_ccsr_map_fd;
568         }
569
570         for_each_compatible_node(dpa_node, NULL, "fsl,dpa-ethernet-init") {
571                 _errno = fman_if_init(dpa_node);
572                 if (_errno) {
573                         FMAN_ERR(_errno, "if_init(%s)\n", dpa_node->full_name);
574                         goto err;
575                 }
576         }
577
578         return 0;
579 err:
580         fman_finish();
581         return _errno;
582 }
583
584 void
585 fman_finish(void)
586 {
587         struct __fman_if *__if, *tmpif;
588
589         assert(fman_ccsr_map_fd != -1);
590
591         list_for_each_entry_safe(__if, tmpif, &__ifs, __if.node) {
592                 int _errno;
593
594                 /* disable Rx and Tx */
595                 if ((__if->__if.mac_type == fman_mac_1g) &&
596                     (!__if->__if.is_memac))
597                         out_be32(__if->ccsr_map + 0x100,
598                                  in_be32(__if->ccsr_map + 0x100) & ~(u32)0x5);
599                 else
600                         out_be32(__if->ccsr_map + 8,
601                                  in_be32(__if->ccsr_map + 8) & ~(u32)3);
602                 /* release the mapping */
603                 _errno = munmap(__if->ccsr_map, __if->regs_size);
604                 if (unlikely(_errno < 0))
605                         fprintf(stderr, "%s:%hu:%s(): munmap() = %d (%s)\n",
606                                 __FILE__, __LINE__, __func__,
607                                 -errno, strerror(errno));
608                 printf("Tearing down %s\n", __if->node_path);
609                 list_del(&__if->__if.node);
610                 free(__if);
611         }
612
613         close(fman_ccsr_map_fd);
614         fman_ccsr_map_fd = -1;
615 }