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