From mboxrd@z Thu Jan 1 00:00:00 1970 From: Shreyansh Jain Subject: [PATCH v5 05/40] bus/dpaa: introducing FMan configurations Date: Thu, 28 Sep 2017 17:03:09 +0530 Message-ID: <20170928113344.12248-6-shreyansh.jain@nxp.com> References: <20170909112132.13936-1-shreyansh.jain@nxp.com> <20170928113344.12248-1-shreyansh.jain@nxp.com> Mime-Version: 1.0 Content-Type: text/plain Cc: , To: Return-path: Received: from NAM01-BY2-obe.outbound.protection.outlook.com (mail-by2nam01on0046.outbound.protection.outlook.com [104.47.34.46]) by dpdk.org (Postfix) with ESMTP id CAE151AEF4 for ; Thu, 28 Sep 2017 13:23:07 +0200 (CEST) In-Reply-To: <20170928113344.12248-1-shreyansh.jain@nxp.com> List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" FMan or Frame Manager, inspects traffic, splits it into queueson ingress. It is also responsible for directing traffic on queues on egress. This patch introduces FMan configurational interfaces. This layer is used by Bus driver for configuring the hardware block. Signed-off-by: Geoff Thorpe Signed-off-by: Hemant Agrawal Signed-off-by: Shreyansh Jain --- drivers/bus/dpaa/Makefile | 2 + drivers/bus/dpaa/base/fman/fman.c | 611 ++++++++++++++++++++++++++++++ drivers/bus/dpaa/base/fman/netcfg_layer.c | 214 +++++++++++ drivers/bus/dpaa/include/fman.h | 458 ++++++++++++++++++++++ drivers/bus/dpaa/include/netcfg.h | 96 +++++ 5 files changed, 1381 insertions(+) create mode 100644 drivers/bus/dpaa/base/fman/fman.c create mode 100644 drivers/bus/dpaa/base/fman/netcfg_layer.c create mode 100644 drivers/bus/dpaa/include/fman.h create mode 100644 drivers/bus/dpaa/include/netcfg.h diff --git a/drivers/bus/dpaa/Makefile b/drivers/bus/dpaa/Makefile index 30a3a5d..f6e504d 100644 --- a/drivers/bus/dpaa/Makefile +++ b/drivers/bus/dpaa/Makefile @@ -57,7 +57,9 @@ SRCS-$(CONFIG_RTE_LIBRTE_DPAA_BUS) += \ dpaa_bus.c SRCS-$(CONFIG_RTE_LIBRTE_DPAA_BUS) += \ + base/fman/fman.c \ base/fman/of.c \ + base/fman/netcfg_layer.c # Link Pthread LDLIBS += -lpthread diff --git a/drivers/bus/dpaa/base/fman/fman.c b/drivers/bus/dpaa/base/fman/fman.c new file mode 100644 index 0000000..2c6029e --- /dev/null +++ b/drivers/bus/dpaa/base/fman/fman.c @@ -0,0 +1,611 @@ +/*- + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * BSD LICENSE + * + * Copyright 2010-2016 Freescale Semiconductor Inc. + * Copyright 2017 NXP. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the above-listed copyright holders nor the + * names of any contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * GPL LICENSE SUMMARY + * + * ALTERNATIVELY, this software may be distributed under the terms of the + * GNU General Public License ("GPL") as published by the Free Software + * Foundation, either version 2 of that License or (at your option) any + * later version. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include + +#include + +/* This header declares the driver interface we implement */ +#include +#include +#include + +#define QMI_PORT_REGS_OFFSET 0x400 + +/* CCSR map address to access ccsr based register */ +void *fman_ccsr_map; +/* fman version info */ +u16 fman_ip_rev; +static int get_once; +u32 fman_dealloc_bufs_mask_hi; +u32 fman_dealloc_bufs_mask_lo; + +int fman_ccsr_map_fd = -1; +static COMPAT_LIST_HEAD(__ifs); + +/* This is the (const) global variable that callers have read-only access to. + * Internally, we have read-write access directly to __ifs. + */ +const struct list_head *fman_if_list = &__ifs; + +static void +if_destructor(struct __fman_if *__if) +{ + struct fman_if_bpool *bp, *tmpbp; + + if (__if->__if.mac_type == fman_offline) + goto cleanup; + + list_for_each_entry_safe(bp, tmpbp, &__if->__if.bpool_list, node) { + list_del(&bp->node); + rte_free(bp); + } +cleanup: + rte_free(__if); +} + +static int +fman_get_ip_rev(const struct device_node *fman_node) +{ + const uint32_t *fman_addr; + uint64_t phys_addr; + uint64_t regs_size; + uint32_t ip_rev_1; + int _errno; + + fman_addr = of_get_address(fman_node, 0, ®s_size, NULL); + if (!fman_addr) { + pr_err("of_get_address cannot return fman address\n"); + return -EINVAL; + } + phys_addr = of_translate_address(fman_node, fman_addr); + if (!phys_addr) { + pr_err("of_translate_address failed\n"); + return -EINVAL; + } + fman_ccsr_map = mmap(NULL, regs_size, PROT_READ | PROT_WRITE, + MAP_SHARED, fman_ccsr_map_fd, phys_addr); + if (fman_ccsr_map == MAP_FAILED) { + pr_err("Can not map FMan ccsr base"); + return -EINVAL; + } + + ip_rev_1 = in_be32(fman_ccsr_map + FMAN_IP_REV_1); + fman_ip_rev = (ip_rev_1 & FMAN_IP_REV_1_MAJOR_MASK) >> + FMAN_IP_REV_1_MAJOR_SHIFT; + + _errno = munmap(fman_ccsr_map, regs_size); + if (_errno) + pr_err("munmap() of FMan ccsr failed"); + + return 0; +} + +static int +fman_get_mac_index(uint64_t regs_addr_host, uint8_t *mac_idx) +{ + int ret = 0; + + /* + * MAC1 : E_0000h + * MAC2 : E_2000h + * MAC3 : E_4000h + * MAC4 : E_6000h + * MAC5 : E_8000h + * MAC6 : E_A000h + * MAC7 : E_C000h + * MAC8 : E_E000h + * MAC9 : F_0000h + * MAC10: F_2000h + */ + switch (regs_addr_host) { + case 0xE0000: + *mac_idx = 1; + break; + case 0xE2000: + *mac_idx = 2; + break; + case 0xE4000: + *mac_idx = 3; + break; + case 0xE6000: + *mac_idx = 4; + break; + case 0xE8000: + *mac_idx = 5; + break; + case 0xEA000: + *mac_idx = 6; + break; + case 0xEC000: + *mac_idx = 7; + break; + case 0xEE000: + *mac_idx = 8; + break; + case 0xF0000: + *mac_idx = 9; + break; + case 0xF2000: + *mac_idx = 10; + break; + default: + ret = -EINVAL; + } + + return ret; +} + +static int +fman_if_init(const struct device_node *dpa_node) +{ + const char *rprop, *mprop; + uint64_t phys_addr; + struct __fman_if *__if; + struct fman_if_bpool *bpool; + + const phandle *mac_phandle, *ports_phandle, *pools_phandle; + const phandle *tx_channel_id = NULL, *mac_addr, *cell_idx; + const phandle *rx_phandle, *tx_phandle; + uint64_t tx_phandle_host[4] = {0}; + uint64_t rx_phandle_host[4] = {0}; + uint64_t regs_addr_host = 0; + uint64_t cell_idx_host = 0; + + const struct device_node *mac_node = NULL, *tx_node; + const struct device_node *pool_node, *fman_node, *rx_node; + const uint32_t *regs_addr = NULL; + const char *mname, *fname; + const char *dname = dpa_node->full_name; + size_t lenp; + int _errno; + const char *char_prop; + uint32_t na; + + if (of_device_is_available(dpa_node) == false) + return 0; + + rprop = "fsl,qman-frame-queues-rx"; + mprop = "fsl,fman-mac"; + + /* Allocate an object for this network interface */ + __if = rte_malloc(NULL, sizeof(*__if), RTE_CACHE_LINE_SIZE); + if (!__if) { + FMAN_ERR(-ENOMEM, "malloc(%zu)\n", sizeof(*__if)); + goto err; + } + memset(__if, 0, sizeof(*__if)); + INIT_LIST_HEAD(&__if->__if.bpool_list); + strncpy(__if->node_path, dpa_node->full_name, PATH_MAX - 1); + __if->node_path[PATH_MAX - 1] = '\0'; + + /* Obtain the MAC node used by this interface except macless */ + mac_phandle = of_get_property(dpa_node, mprop, &lenp); + if (!mac_phandle) { + FMAN_ERR(-EINVAL, "%s: no %s\n", dname, mprop); + goto err; + } + assert(lenp == sizeof(phandle)); + mac_node = of_find_node_by_phandle(*mac_phandle); + if (!mac_node) { + FMAN_ERR(-ENXIO, "%s: bad 'fsl,fman-mac\n", dname); + goto err; + } + mname = mac_node->full_name; + + /* Map the CCSR regs for the MAC node */ + regs_addr = of_get_address(mac_node, 0, &__if->regs_size, NULL); + if (!regs_addr) { + FMAN_ERR(-EINVAL, "of_get_address(%s)\n", mname); + goto err; + } + phys_addr = of_translate_address(mac_node, regs_addr); + if (!phys_addr) { + FMAN_ERR(-EINVAL, "of_translate_address(%s, %p)\n", + mname, regs_addr); + __if->ccsr_map = mmap(NULL, __if->regs_size, + PROT_READ | PROT_WRITE, MAP_SHARED, + fman_ccsr_map_fd, phys_addr); + goto err; + } + if (__if->ccsr_map == MAP_FAILED) { + FMAN_ERR(-errno, "mmap(0x%"PRIx64")\n", phys_addr); + goto err; + } + na = of_n_addr_cells(mac_node); + /* Get rid of endianness (issues). Convert to host byte order */ + regs_addr_host = of_read_number(regs_addr, na); + + + /* Get the index of the Fman this i/f belongs to */ + fman_node = of_get_parent(mac_node); + na = of_n_addr_cells(mac_node); + if (!fman_node) { + FMAN_ERR(-ENXIO, "of_get_parent(%s)\n", mname); + goto err; + } + fname = fman_node->full_name; + cell_idx = of_get_property(fman_node, "cell-index", &lenp); + if (!cell_idx) { + FMAN_ERR(-ENXIO, "%s: no cell-index)\n", fname); + goto err; + } + assert(lenp == sizeof(*cell_idx)); + cell_idx_host = of_read_number(cell_idx, lenp / sizeof(phandle)); + __if->__if.fman_idx = cell_idx_host; + if (!get_once) { + _errno = fman_get_ip_rev(fman_node); + if (_errno) { + FMAN_ERR(-ENXIO, "%s: ip_rev is not available\n", + fname); + goto err; + } + } + + if (fman_ip_rev >= FMAN_V3) { + /* + * Set A2V, OVOM, EBD bits in contextA to allow external + * buffer deallocation by fman. + */ + fman_dealloc_bufs_mask_hi = FMAN_V3_CONTEXTA_EN_A2V | + FMAN_V3_CONTEXTA_EN_OVOM; + fman_dealloc_bufs_mask_lo = FMAN_V3_CONTEXTA_EN_EBD; + } else { + fman_dealloc_bufs_mask_hi = 0; + fman_dealloc_bufs_mask_lo = 0; + } + /* Is the MAC node 1G, 10G? */ + __if->__if.is_memac = 0; + + if (of_device_is_compatible(mac_node, "fsl,fman-1g-mac")) + __if->__if.mac_type = fman_mac_1g; + else if (of_device_is_compatible(mac_node, "fsl,fman-10g-mac")) + __if->__if.mac_type = fman_mac_10g; + else if (of_device_is_compatible(mac_node, "fsl,fman-memac")) { + __if->__if.is_memac = 1; + char_prop = of_get_property(mac_node, "phy-connection-type", + NULL); + if (!char_prop) { + printf("memac: unknown MII type assuming 1G\n"); + /* Right now forcing memac to 1g in case of error*/ + __if->__if.mac_type = fman_mac_1g; + } else { + if (strstr(char_prop, "sgmii")) + __if->__if.mac_type = fman_mac_1g; + else if (strstr(char_prop, "rgmii")) { + __if->__if.mac_type = fman_mac_1g; + __if->__if.is_rgmii = 1; + } else if (strstr(char_prop, "xgmii")) + __if->__if.mac_type = fman_mac_10g; + } + } else { + FMAN_ERR(-EINVAL, "%s: unknown MAC type\n", mname); + goto err; + } + + /* + * For MAC ports, we cannot rely on cell-index. In + * T2080, two of the 10G ports on single FMAN have same + * duplicate cell-indexes as the other two 10G ports on + * same FMAN. Hence, we now rely upon addresses of the + * ports from device tree to deduce the index. + */ + + _errno = fman_get_mac_index(regs_addr_host, &__if->__if.mac_idx); + if (_errno) { + FMAN_ERR(-EINVAL, "Invalid register address: %lu", + regs_addr_host); + goto err; + } + + /* Extract the MAC address for private and shared interfaces */ + mac_addr = of_get_property(mac_node, "local-mac-address", + &lenp); + if (!mac_addr) { + FMAN_ERR(-EINVAL, "%s: no local-mac-address\n", + mname); + goto err; + } + memcpy(&__if->__if.mac_addr, mac_addr, ETHER_ADDR_LEN); + + /* Extract the Tx port (it's the second of the two port handles) + * and get its channel ID + */ + ports_phandle = of_get_property(mac_node, "fsl,port-handles", + &lenp); + if (!ports_phandle) + ports_phandle = of_get_property(mac_node, "fsl,fman-ports", + &lenp); + if (!ports_phandle) { + FMAN_ERR(-EINVAL, "%s: no fsl,port-handles\n", + mname); + goto err; + } + assert(lenp == (2 * sizeof(phandle))); + tx_node = of_find_node_by_phandle(ports_phandle[1]); + if (!tx_node) { + FMAN_ERR(-ENXIO, "%s: bad fsl,port-handle[1]\n", mname); + goto err; + } + /* Extract the channel ID (from tx-port-handle) */ + tx_channel_id = of_get_property(tx_node, "fsl,qman-channel-id", + &lenp); + if (!tx_channel_id) { + FMAN_ERR(-EINVAL, "%s: no fsl-qman-channel-id\n", + tx_node->full_name); + goto err; + } + + rx_node = of_find_node_by_phandle(ports_phandle[0]); + if (!rx_node) { + FMAN_ERR(-ENXIO, "%s: bad fsl,port-handle[0]\n", mname); + goto err; + } + regs_addr = of_get_address(rx_node, 0, &__if->regs_size, NULL); + if (!regs_addr) { + FMAN_ERR(-EINVAL, "of_get_address(%s)\n", mname); + goto err; + } + phys_addr = of_translate_address(rx_node, regs_addr); + if (!phys_addr) { + FMAN_ERR(-EINVAL, "of_translate_address(%s, %p)\n", + mname, regs_addr); + goto err; + } + __if->bmi_map = mmap(NULL, __if->regs_size, + PROT_READ | PROT_WRITE, MAP_SHARED, + fman_ccsr_map_fd, phys_addr); + if (__if->bmi_map == MAP_FAILED) { + FMAN_ERR(-errno, "mmap(0x%"PRIx64")\n", phys_addr); + goto err; + } + + /* No channel ID for MAC-less */ + assert(lenp == sizeof(*tx_channel_id)); + na = of_n_addr_cells(mac_node); + __if->__if.tx_channel_id = of_read_number(tx_channel_id, na); + + /* Extract the Rx FQIDs. (Note, the device representation is silly, + * there are "counts" that must always be 1.) + */ + rx_phandle = of_get_property(dpa_node, rprop, &lenp); + if (!rx_phandle) { + FMAN_ERR(-EINVAL, "%s: no fsl,qman-frame-queues-rx\n", dname); + goto err; + } + + assert(lenp == (4 * sizeof(phandle))); + + na = of_n_addr_cells(mac_node); + /* Get rid of endianness (issues). Convert to host byte order */ + rx_phandle_host[0] = of_read_number(&rx_phandle[0], na); + rx_phandle_host[1] = of_read_number(&rx_phandle[1], na); + rx_phandle_host[2] = of_read_number(&rx_phandle[2], na); + rx_phandle_host[3] = of_read_number(&rx_phandle[3], na); + + assert((rx_phandle_host[1] == 1) && (rx_phandle_host[3] == 1)); + __if->__if.fqid_rx_err = rx_phandle_host[0]; + __if->__if.fqid_rx_def = rx_phandle_host[2]; + + /* Extract the Tx FQIDs */ + tx_phandle = of_get_property(dpa_node, + "fsl,qman-frame-queues-tx", &lenp); + if (!tx_phandle) { + FMAN_ERR(-EINVAL, "%s: no fsl,qman-frame-queues-tx\n", dname); + goto err; + } + + assert(lenp == (4 * sizeof(phandle))); + /*TODO: Fix for other cases also */ + na = of_n_addr_cells(mac_node); + /* Get rid of endianness (issues). Convert to host byte order */ + tx_phandle_host[0] = of_read_number(&tx_phandle[0], na); + tx_phandle_host[1] = of_read_number(&tx_phandle[1], na); + tx_phandle_host[2] = of_read_number(&tx_phandle[2], na); + tx_phandle_host[3] = of_read_number(&tx_phandle[3], na); + assert((tx_phandle_host[1] == 1) && (tx_phandle_host[3] == 1)); + __if->__if.fqid_tx_err = tx_phandle_host[0]; + __if->__if.fqid_tx_confirm = tx_phandle_host[2]; + + /* Obtain the buffer pool nodes used by this interface */ + pools_phandle = of_get_property(dpa_node, "fsl,bman-buffer-pools", + &lenp); + if (!pools_phandle) { + FMAN_ERR(-EINVAL, "%s: no fsl,bman-buffer-pools\n", dname); + goto err; + } + /* For each pool, parse the corresponding node and add a pool object + * to the interface's "bpool_list" + */ + assert(lenp && !(lenp % sizeof(phandle))); + while (lenp) { + size_t proplen; + const phandle *prop; + uint64_t bpid_host = 0; + uint64_t bpool_host[6] = {0}; + const char *pname; + /* Allocate an object for the pool */ + bpool = rte_malloc(NULL, sizeof(*bpool), RTE_CACHE_LINE_SIZE); + if (!bpool) { + FMAN_ERR(-ENOMEM, "malloc(%zu)\n", sizeof(*bpool)); + goto err; + } + /* Find the pool node */ + pool_node = of_find_node_by_phandle(*pools_phandle); + if (!pool_node) { + FMAN_ERR(-ENXIO, "%s: bad fsl,bman-buffer-pools\n", + dname); + goto err; + } + pname = pool_node->full_name; + /* Extract the BPID property */ + prop = of_get_property(pool_node, "fsl,bpid", &proplen); + if (!prop) { + FMAN_ERR(-EINVAL, "%s: no fsl,bpid\n", pname); + goto err; + } + assert(proplen == sizeof(*prop)); + na = of_n_addr_cells(mac_node); + /* Get rid of endianness (issues). + * Convert to host byte-order + */ + bpid_host = of_read_number(prop, na); + bpool->bpid = bpid_host; + /* Extract the cfg property (count/size/addr). "fsl,bpool-cfg" + * indicates for the Bman driver to seed the pool. + * "fsl,bpool-ethernet-cfg" is used by the network driver. The + * two are mutually exclusive, so check for either of them. + */ + prop = of_get_property(pool_node, "fsl,bpool-cfg", + &proplen); + if (!prop) + prop = of_get_property(pool_node, + "fsl,bpool-ethernet-cfg", + &proplen); + if (!prop) { + /* It's OK for there to be no bpool-cfg */ + bpool->count = bpool->size = bpool->addr = 0; + } else { + assert(proplen == (6 * sizeof(*prop))); + na = of_n_addr_cells(mac_node); + /* Get rid of endianness (issues). + * Convert to host byte order + */ + bpool_host[0] = of_read_number(&prop[0], na); + bpool_host[1] = of_read_number(&prop[1], na); + bpool_host[2] = of_read_number(&prop[2], na); + bpool_host[3] = of_read_number(&prop[3], na); + bpool_host[4] = of_read_number(&prop[4], na); + bpool_host[5] = of_read_number(&prop[5], na); + + bpool->count = ((uint64_t)bpool_host[0] << 32) | + bpool_host[1]; + bpool->size = ((uint64_t)bpool_host[2] << 32) | + bpool_host[3]; + bpool->addr = ((uint64_t)bpool_host[4] << 32) | + bpool_host[5]; + } + /* Parsing of the pool is complete, add it to the interface + * list. + */ + list_add_tail(&bpool->node, &__if->__if.bpool_list); + lenp -= sizeof(phandle); + pools_phandle++; + } + + /* Parsing of the network interface is complete, add it to the list */ + DPAA_BUS_LOG(DEBUG, "Found %s, Tx Channel = %x, FMAN = %x," + "Port ID = %x\n", + dname, __if->__if.tx_channel_id, __if->__if.fman_idx, + __if->__if.mac_idx); + + list_add_tail(&__if->__if.node, &__ifs); + return 0; +err: + if_destructor(__if); + return _errno; +} + +int +fman_init(void) +{ + const struct device_node *dpa_node; + int _errno; + + /* If multiple dependencies try to initialise the Fman driver, don't + * panic. + */ + if (fman_ccsr_map_fd != -1) + return 0; + + fman_ccsr_map_fd = open(FMAN_DEVICE_PATH, O_RDWR); + if (unlikely(fman_ccsr_map_fd < 0)) { + DPAA_BUS_LOG(ERR, "Unable to open (/dev/mem)"); + return fman_ccsr_map_fd; + } + + for_each_compatible_node(dpa_node, NULL, "fsl,dpa-ethernet-init") { + _errno = fman_if_init(dpa_node); + if (_errno) { + FMAN_ERR(_errno, "if_init(%s)\n", dpa_node->full_name); + goto err; + } + } + + return 0; +err: + fman_finish(); + return _errno; +} + +void +fman_finish(void) +{ + struct __fman_if *__if, *tmpif; + + assert(fman_ccsr_map_fd != -1); + + list_for_each_entry_safe(__if, tmpif, &__ifs, __if.node) { + int _errno; + + /* disable Rx and Tx */ + if ((__if->__if.mac_type == fman_mac_1g) && + (!__if->__if.is_memac)) + out_be32(__if->ccsr_map + 0x100, + in_be32(__if->ccsr_map + 0x100) & ~(u32)0x5); + else + out_be32(__if->ccsr_map + 8, + in_be32(__if->ccsr_map + 8) & ~(u32)3); + /* release the mapping */ + _errno = munmap(__if->ccsr_map, __if->regs_size); + if (unlikely(_errno < 0)) + fprintf(stderr, "%s:%hu:%s(): munmap() = %d (%s)\n", + __FILE__, __LINE__, __func__, + -errno, strerror(errno)); + printf("Tearing down %s\n", __if->node_path); + list_del(&__if->__if.node); + rte_free(__if); + } + + close(fman_ccsr_map_fd); + fman_ccsr_map_fd = -1; +} diff --git a/drivers/bus/dpaa/base/fman/netcfg_layer.c b/drivers/bus/dpaa/base/fman/netcfg_layer.c new file mode 100644 index 0000000..26cff84 --- /dev/null +++ b/drivers/bus/dpaa/base/fman/netcfg_layer.c @@ -0,0 +1,214 @@ +/*- + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * BSD LICENSE + * + * Copyright 2010-2016 Freescale Semiconductor Inc. + * Copyright 2017 NXP. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the above-listed copyright holders nor the + * names of any contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * GPL LICENSE SUMMARY + * + * ALTERNATIVELY, this software may be distributed under the terms of the + * GNU General Public License ("GPL") as published by the Free Software + * Foundation, either version 2 of that License or (at your option) any + * later version. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +/* Structure contains information about all the interfaces given by user + * on command line. + */ +struct netcfg_interface *netcfg_interface; + +/* This data structure contaings all configurations information + * related to usages of DPA devices. + */ +struct netcfg_info *netcfg; +/* fd to open a socket for making ioctl request to disable/enable shared + * interfaces. + */ +static int skfd = -1; + +#ifdef RTE_LIBRTE_DPAA_DEBUG_DRIVER +void +dump_netcfg(struct netcfg_info *cfg_ptr) +{ + int i; + + printf(".......... DPAA Configuration ..........\n\n"); + + /* Network interfaces */ + printf("Network interfaces: %d\n", cfg_ptr->num_ethports); + for (i = 0; i < cfg_ptr->num_ethports; i++) { + struct fman_if_bpool *bpool; + struct fm_eth_port_cfg *p_cfg = &cfg_ptr->port_cfg[i]; + struct fman_if *__if = p_cfg->fman_if; + + printf("\n+ Fman %d, MAC %d (%s);\n", + __if->fman_idx, __if->mac_idx, + (__if->mac_type == fman_mac_1g) ? "1G" : "10G"); + + printf("\tmac_addr: %02x:%02x:%02x:%02x:%02x:%02x\n", + (&__if->mac_addr)->addr_bytes[0], + (&__if->mac_addr)->addr_bytes[1], + (&__if->mac_addr)->addr_bytes[2], + (&__if->mac_addr)->addr_bytes[3], + (&__if->mac_addr)->addr_bytes[4], + (&__if->mac_addr)->addr_bytes[5]); + + printf("\ttx_channel_id: 0x%02x\n", + __if->tx_channel_id); + + printf("\tfqid_rx_def: 0x%x\n", p_cfg->rx_def); + printf("\tfqid_rx_err: 0x%x\n", __if->fqid_rx_err); + + printf("\tfqid_tx_err: 0x%x\n", __if->fqid_tx_err); + printf("\tfqid_tx_confirm: 0x%x\n", __if->fqid_tx_confirm); + fman_if_for_each_bpool(bpool, __if) + printf("\tbuffer pool: (bpid=%d, count=%"PRId64 + " size=%"PRId64", addr=0x%"PRIx64")\n", + bpool->bpid, bpool->count, bpool->size, + bpool->addr); + } +} +#endif /* RTE_LIBRTE_DPAA_DEBUG_DRIVER */ + +static inline int +get_num_netcfg_interfaces(char *str) +{ + char *pch; + uint8_t count = 0; + + if (str == NULL) + return -EINVAL; + pch = strtok(str, ","); + while (pch != NULL) { + count++; + pch = strtok(NULL, ","); + } + return count; +} + +struct netcfg_info * +netcfg_acquire(void) +{ + struct fman_if *__if; + int _errno, idx = 0; + uint8_t num_ports = 0; + uint8_t num_cfg_ports = 0; + size_t size; + + /* Extract dpa configuration from fman driver and FMC configuration + * for command-line interfaces. + */ + + /* Open a basic socket to enable/disable shared + * interfaces. + */ + skfd = socket(AF_PACKET, SOCK_RAW, 0); + if (unlikely(skfd < 0)) { + error(0, errno, "%s(): open(SOCK_RAW)", __func__); + return NULL; + } + + /* Initialise the Fman driver */ + _errno = fman_init(); + if (_errno) { + DPAA_BUS_LOG(ERR, "FMAN driver init failed (%d)", errno); + close(skfd); + skfd = -1; + return NULL; + } + + /* Number of MAC ports */ + list_for_each_entry(__if, fman_if_list, node) + num_ports++; + + if (!num_ports) { + DPAA_BUS_LOG(ERR, "FMAN ports not available"); + return NULL; + } + /* Allocate space for all enabled mac ports */ + size = sizeof(*netcfg) + + (num_ports * sizeof(struct fm_eth_port_cfg)); + + netcfg = calloc(1, size); + if (unlikely(netcfg == NULL)) { + DPAA_BUS_LOG(ERR, "Unable to allocat mem for netcfg"); + goto error; + } + + netcfg->num_ethports = num_ports; + + list_for_each_entry(__if, fman_if_list, node) { + struct fm_eth_port_cfg *cfg = &netcfg->port_cfg[idx]; + /* Hook in the fman driver interface */ + cfg->fman_if = __if; + cfg->rx_def = __if->fqid_rx_def; + num_cfg_ports++; + idx++; + } + + if (!num_cfg_ports) { + DPAA_BUS_LOG(ERR, "No FMAN ports found"); + goto error; + } else if (num_ports != num_cfg_ports) + netcfg->num_ethports = num_cfg_ports; + + return netcfg; + +error: + if (netcfg) { + free(netcfg); + netcfg = NULL; + } + + return NULL; +} + +void +netcfg_release(struct netcfg_info *cfg_ptr) +{ + free(cfg_ptr); + /* Close socket for shared interfaces */ + if (skfd >= 0) { + close(skfd); + skfd = -1; + } +} diff --git a/drivers/bus/dpaa/include/fman.h b/drivers/bus/dpaa/include/fman.h new file mode 100644 index 0000000..9890e09 --- /dev/null +++ b/drivers/bus/dpaa/include/fman.h @@ -0,0 +1,458 @@ +/*- + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * BSD LICENSE + * + * Copyright 2010-2012 Freescale Semiconductor, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the above-listed copyright holders nor the + * names of any contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * GPL LICENSE SUMMARY + * + * ALTERNATIVELY, this software may be distributed under the terms of the + * GNU General Public License ("GPL") as published by the Free Software + * Foundation, either version 2 of that License or (at your option) any + * later version. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __FMAN_H +#define __FMAN_H + +#include +#include + +#include +#include + +#include + +#ifndef FMAN_DEVICE_PATH +#define FMAN_DEVICE_PATH "/dev/mem" +#endif + +#define MEMAC_NUM_OF_PADDRS 7 /* Num of additional exact match MAC adr regs */ + +/* Control and Configuration Register (COMMAND_CONFIG) for MEMAC */ +#define CMD_CFG_LOOPBACK_EN 0x00000400 +/**< 21 XGMII/GMII loopback enable */ +#define CMD_CFG_PROMIS_EN 0x00000010 +/**< 27 Promiscuous operation enable */ +#define CMD_CFG_PAUSE_IGNORE 0x00000100 +/**< 23 Ignore Pause frame quanta */ + +/* Statistics Configuration Register (STATN_CONFIG) */ +#define STATS_CFG_CLR 0x00000004 +/**< 29 Reset all counters */ +#define STATS_CFG_CLR_ON_RD 0x00000002 +/**< 30 Clear on read */ +#define STATS_CFG_SATURATE 0x00000001 +/**< 31 Saturate at the maximum val */ + +/**< Max receive frame length mask */ +#define MAXFRM_SIZE_MEMAC 0x00007fe0 +#define MAXFRM_RX_MASK 0x0000ffff + +/**< Interface Mode Register Register for MEMAC */ +#define IF_MODE_RLP 0x00000820 + +/**< Pool Limits */ +#define FMAN_PORT_MAX_EXT_POOLS_NUM 8 +#define FMAN_PORT_OBS_EXT_POOLS_NUM 2 + +#define FMAN_PORT_CG_MAP_NUM 8 +#define FMAN_PORT_PRS_RESULT_WORDS_NUM 8 +#define FMAN_PORT_BMI_FIFO_UNITS 0x100 +#define FMAN_PORT_IC_OFFSET_UNITS 0x10 + +#define FMAN_ENABLE_BPOOL_DEPLETION 0xF00000F0 + +#define HASH_CTRL_MCAST_EN 0x00000100 +#define GROUP_ADDRESS 0x0000010000000000LL +#define HASH_CTRL_ADDR_MASK 0x0000003F + +/* Pre definitions of FMAN interface and Bpool structures */ +struct __fman_if; +struct fman_if_bpool; +/* Lists of fman interfaces and bpools */ +TAILQ_HEAD(rte_fman_if_list, __fman_if); + +/* Represents the different flavour of network interface */ +enum fman_mac_type { + fman_offline = 0, + fman_mac_1g, + fman_mac_10g, +}; + +struct mac_addr { + uint32_t mac_addr_l; /**< Lower 32 bits of 48-bit MAC address */ + uint32_t mac_addr_u; /**< Upper 16 bits of 48-bit MAC address */ +}; + +struct memac_regs { + /* General Control and Status */ + uint32_t res0000[2]; + uint32_t command_config; /**< 0x008 Ctrl and cfg */ + struct mac_addr mac_addr0; /**< 0x00C-0x010 MAC_ADDR_0...1 */ + uint32_t maxfrm; /**< 0x014 Max frame length */ + uint32_t res0018[5]; + uint32_t hashtable_ctrl; /**< 0x02C Hash table control */ + uint32_t res0030[4]; + uint32_t ievent; /**< 0x040 Interrupt event */ + uint32_t tx_ipg_length; + /**< 0x044 Transmitter inter-packet-gap */ + uint32_t res0048; + uint32_t imask; /**< 0x04C Interrupt mask */ + uint32_t res0050; + uint32_t pause_quanta[4]; /**< 0x054 Pause quanta */ + uint32_t pause_thresh[4]; /**< 0x064 Pause quanta threshold */ + uint32_t rx_pause_status; /**< 0x074 Receive pause status */ + uint32_t res0078[2]; + struct mac_addr mac_addr[MEMAC_NUM_OF_PADDRS]; + /**< 0x80-0x0B4 mac padr */ + uint32_t lpwake_timer; + /**< 0x0B8 Low Power Wakeup Timer */ + uint32_t sleep_timer; + /**< 0x0BC Transmit EEE Low Power Timer */ + uint32_t res00c0[8]; + uint32_t statn_config; + /**< 0x0E0 Statistics configuration */ + uint32_t res00e4[7]; + /* Rx Statistics Counter */ + uint32_t reoct_l; /**bpid); + * [...] + * } + */ +#define fman_if_for_each_bpool(bp, __if) \ + list_for_each_entry(bp, &(__if)->bpool_list, node) + +#define FMAN_ERR(rc, fmt, args...) \ + do { \ + _errno = (rc); \ + DPAA_BUS_LOG(ERR, fmt "(%d)", ##args, errno); \ + } while (0) + +#define FMAN_IP_REV_1 0xC30C4 +#define FMAN_IP_REV_1_MAJOR_MASK 0x0000FF00 +#define FMAN_IP_REV_1_MAJOR_SHIFT 8 +#define FMAN_V3 0x06 +#define FMAN_V3_CONTEXTA_EN_A2V 0x10000000 +#define FMAN_V3_CONTEXTA_EN_OVOM 0x02000000 +#define FMAN_V3_CONTEXTA_EN_EBD 0x80000000 +#define FMAN_CONTEXTA_DIS_CHECKSUM 0x7ull +#define FMAN_CONTEXTA_SET_OPCODE11 0x2000000b00000000 +extern u16 fman_ip_rev; +extern u32 fman_dealloc_bufs_mask_hi; +extern u32 fman_dealloc_bufs_mask_lo; + +/** + * Initialize the FMAN driver + * + * @args void + * @return + * 0 for success; error OTHERWISE + */ +int fman_init(void); + +/** + * Teardown the FMAN driver + * + * @args void + * @return void + */ +void fman_finish(void); + +#endif /* __FMAN_H */ diff --git a/drivers/bus/dpaa/include/netcfg.h b/drivers/bus/dpaa/include/netcfg.h new file mode 100644 index 0000000..b77a678 --- /dev/null +++ b/drivers/bus/dpaa/include/netcfg.h @@ -0,0 +1,96 @@ +/*- + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * BSD LICENSE + * + * Copyright 2010-2012 Freescale Semiconductor, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the above-listed copyright holders nor the + * names of any contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * GPL LICENSE SUMMARY + * + * ALTERNATIVELY, this software may be distributed under the terms of the + * GNU General Public License ("GPL") as published by the Free Software + * Foundation, either version 2 of that License or (at your option) any + * later version. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __NETCFG_H +#define __NETCFG_H + +#include +#include + +/* Configuration information related to a specific ethernet port */ +struct fm_eth_port_cfg { + /**< A list of PCD FQ ranges, obtained from FMC configuration */ + struct list_head *list; + /**< The "Rx default" FQID, obtained from FMC configuration */ + uint32_t rx_def; + /**< Other interface details are in the fman driver interface */ + struct fman_if *fman_if; +}; + +struct netcfg_info { + uint8_t num_ethports; + /**< Number of ports */ + struct fm_eth_port_cfg port_cfg[0]; + /**< Variable structure array of size num_ethports */ +}; + +struct interface_info { + char *name; + struct ether_addr mac_addr; + struct ether_addr peer_mac; + int mac_present; + int fman_enabled_mac_interface; +}; + +struct netcfg_interface { + uint8_t numof_netcfg_interface; + uint8_t numof_fman_enabled_macless; + struct interface_info interface_info[0]; +}; + +/* pcd_file: FMC netpcd XML ("policy") file, that contains PCD information. + * cfg_file: FMC config XML file + * Returns the configuration information in newly allocated memory. + */ +struct netcfg_info *netcfg_acquire(void); + +/* cfg_ptr: configuration information pointer. + * Frees the resources allocated by the configuration layer. + */ +void netcfg_release(struct netcfg_info *cfg_ptr); + +#ifdef RTE_LIBRTE_DPAA_DEBUG_DRIVER +/* cfg_ptr: configuration information pointer. + * This function dumps configuration data to stdout. + */ +void dump_netcfg(struct netcfg_info *cfg_ptr); +#endif + +#endif /* __NETCFG_H */ -- 2.9.3