summaryrefslogtreecommitdiff
path: root/drivers/net/ethernet/freescale/fman/src
diff options
context:
space:
mode:
authorMandy Lavi <mandy.lavi@freescale.com>2013-03-24 16:40:18 (GMT)
committerFleming Andrew-AFLEMING <AFLEMING@freescale.com>2013-04-08 23:07:26 (GMT)
commit3cc514986cb4e457458cc826288b6c2107c97907 (patch)
tree2985e48afc5dd20f44d51ef6aafdae917ce2698f /drivers/net/ethernet/freescale/fman/src
parent5767d52cec831b0e2927d34e91acd738cc1cb0ef (diff)
downloadlinux-fsl-qoriq-3cc514986cb4e457458cc826288b6c2107c97907.tar.xz
fmd: fmd19 integration
Add fmd19 codebase, plus a minimal set of sources from dpaa-eth, necessary for bare compilation Change-Id: I390df8717671204e3d98a987135393bef4534e95 Signed-off-by: Mandy Lavi <mandy.lavi@freescale.com> Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com> Reviewed-on: http://git.am.freescale.net:8181/1029 Reviewed-by: Fleming Andrew-AFLEMING <AFLEMING@freescale.com> Tested-by: Fleming Andrew-AFLEMING <AFLEMING@freescale.com>
Diffstat (limited to 'drivers/net/ethernet/freescale/fman/src')
-rw-r--r--drivers/net/ethernet/freescale/fman/src/Makefile11
-rw-r--r--drivers/net/ethernet/freescale/fman/src/inc/system/sys_ext.h118
-rw-r--r--drivers/net/ethernet/freescale/fman/src/inc/system/sys_io_ext.h46
-rw-r--r--drivers/net/ethernet/freescale/fman/src/inc/types_linux.h200
-rw-r--r--drivers/net/ethernet/freescale/fman/src/inc/wrapper/fsl_fman.h322
-rw-r--r--drivers/net/ethernet/freescale/fman/src/inc/wrapper/fsl_fman_test.h84
-rw-r--r--drivers/net/ethernet/freescale/fman/src/inc/wrapper/lnxwrp_exp_sym.h125
-rw-r--r--drivers/net/ethernet/freescale/fman/src/inc/wrapper/lnxwrp_fm_ext.h163
-rw-r--r--drivers/net/ethernet/freescale/fman/src/inc/xx/xx.h50
-rw-r--r--drivers/net/ethernet/freescale/fman/src/system/Makefile10
-rw-r--r--drivers/net/ethernet/freescale/fman/src/system/sys_io.c171
-rw-r--r--drivers/net/ethernet/freescale/fman/src/wrapper/Makefile20
-rw-r--r--drivers/net/ethernet/freescale/fman/src/wrapper/fman_test.c1665
-rw-r--r--drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_fm.c1308
-rw-r--r--drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_fm.h275
-rw-r--r--drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_fm_port.c1332
-rw-r--r--drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_ioctls_fm.c4423
-rw-r--r--drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_ioctls_fm_compat.c1223
-rw-r--r--drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_ioctls_fm_compat.h679
-rw-r--r--drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_resources.c1196
-rw-r--r--drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_resources.h121
-rw-r--r--drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_resources_ut.c191
-rw-r--r--drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_resources_ut.h144
-rw-r--r--drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_resources_ut.make28
-rw-r--r--drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_sysfs.c60
-rw-r--r--drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_sysfs.h67
-rw-r--r--drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_sysfs_fm.c573
-rw-r--r--drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_sysfs_fm.h48
-rw-r--r--drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_sysfs_fm_port.c365
-rw-r--r--drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_sysfs_fm_port.h48
-rw-r--r--drivers/net/ethernet/freescale/fman/src/xx/Makefile12
-rw-r--r--drivers/net/ethernet/freescale/fman/src/xx/module_strings.c45
-rw-r--r--drivers/net/ethernet/freescale/fman/src/xx/stdlib.c264
-rw-r--r--drivers/net/ethernet/freescale/fman/src/xx/udivdi3.c132
-rw-r--r--drivers/net/ethernet/freescale/fman/src/xx/xx_linux.c901
35 files changed, 16420 insertions, 0 deletions
diff --git a/drivers/net/ethernet/freescale/fman/src/Makefile b/drivers/net/ethernet/freescale/fman/src/Makefile
new file mode 100644
index 0000000..af5d2e7
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/src/Makefile
@@ -0,0 +1,11 @@
+#
+# Makefile for the Freescale Ethernet controllers
+#
+EXTRA_CFLAGS += -DVERSION=\"\"
+#
+#Include netcomm SW specific definitions
+include $(srctree)/drivers/net/ethernet/freescale/fman/ncsw_config.mk
+#
+obj-y += system/
+obj-y += wrapper/
+obj-y += xx/
diff --git a/drivers/net/ethernet/freescale/fman/src/inc/system/sys_ext.h b/drivers/net/ethernet/freescale/fman/src/inc/system/sys_ext.h
new file mode 100644
index 0000000..20f27d2
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/src/inc/system/sys_ext.h
@@ -0,0 +1,118 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * 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 Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * 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 Freescale Semiconductor ``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 Freescale Semiconductor 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 __SYS_EXT_H
+#define __SYS_EXT_H
+
+#include "std_ext.h"
+
+
+/**************************************************************************//**
+ @Group sys_grp System Interfaces
+
+ @Description Linux system programming interfaces.
+
+ @{
+*//***************************************************************************/
+
+/**************************************************************************//**
+ @Group sys_gen_grp System General Interface
+
+ @Description General definitions, structures and routines of the linux
+ system programming interface.
+
+ @{
+*//***************************************************************************/
+
+/**************************************************************************//**
+ @Collection Macros for Advanced Configuration Requests
+ @{
+*//***************************************************************************/
+#define SYS_MAX_ADV_CONFIG_ARGS 4
+ /**< Maximum number of arguments in
+ an advanced configuration entry */
+/* @} */
+
+/**************************************************************************//**
+ @Description System Object Advanced Configuration Entry
+
+ This structure represents a single request for an advanced
+ configuration call on the initialized object. An array of such
+ requests may be contained in the settings structure of the
+ corresponding object.
+
+ The maximum number of arguments is limited to #SYS_MAX_ADV_CONFIG_ARGS.
+*//***************************************************************************/
+typedef struct t_SysObjectAdvConfigEntry
+{
+ void *p_Function; /**< Pointer to advanced configuration routine */
+
+ uintptr_t args[SYS_MAX_ADV_CONFIG_ARGS];
+ /**< Array of arguments for the specified routine;
+ All arguments should be casted to uint32_t. */
+} t_SysObjectAdvConfigEntry;
+
+
+/** @} */ /* end of sys_gen_grp */
+/** @} */ /* end of sys_grp */
+
+#define NCSW_PARAMS(_num, _params) ADV_CONFIG_PARAMS_##_num _params
+
+#define ADV_CONFIG_PARAMS_1(_type) \
+ , (_type)p_Entry->args[0]
+
+#define SET_ADV_CONFIG_ARGS_1(_arg0) \
+ p_Entry->args[0] = (uintptr_t )(_arg0); \
+
+#define ARGS(_num, _params) SET_ADV_CONFIG_ARGS_##_num _params
+
+#define ADD_ADV_CONFIG_START(_p_Entries, _maxEntries) \
+ { \
+ t_SysObjectAdvConfigEntry *p_Entry; \
+ t_SysObjectAdvConfigEntry *p_Entrys = (_p_Entries); \
+ int i=0, max = (_maxEntries); \
+
+#define ADD_ADV_CONFIG_END \
+ }
+
+#define ADV_CONFIG_CHECK_START(_p_Entry) \
+ { \
+ t_SysObjectAdvConfigEntry *p_Entry = _p_Entry; \
+ t_Error errCode; \
+
+#define ADV_CONFIG_CHECK(_handle, _func, _params) \
+ if (p_Entry->p_Function == _func) \
+ { \
+ errCode = _func(_handle _params); \
+ } else
+
+#endif /* __SYS_EXT_H */
diff --git a/drivers/net/ethernet/freescale/fman/src/inc/system/sys_io_ext.h b/drivers/net/ethernet/freescale/fman/src/inc/system/sys_io_ext.h
new file mode 100644
index 0000000..d6aa9d4
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/src/inc/system/sys_io_ext.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * 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 Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * 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 Freescale Semiconductor ``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 Freescale Semiconductor 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 __SYS_IO_EXT_H
+#define __SYS_IO_EXT_H
+
+#include "std_ext.h"
+#include "error_ext.h"
+
+
+t_Error SYS_RegisterIoMap (uint64_t virtAddr, uint64_t physAddr, uint32_t size);
+t_Error SYS_UnregisterIoMap (uint64_t virtAddr);
+uint64_t SYS_PhysToVirt (uint64_t addr);
+uint64_t SYS_VirtToPhys (uint64_t addr);
+
+
+#endif /* __SYS_IO_EXT_H */
diff --git a/drivers/net/ethernet/freescale/fman/src/inc/types_linux.h b/drivers/net/ethernet/freescale/fman/src/inc/types_linux.h
new file mode 100644
index 0000000..ac15d66
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/src/inc/types_linux.h
@@ -0,0 +1,200 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * 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 Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * 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 Freescale Semiconductor ``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 Freescale Semiconductor 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 __TYPES_LINUX_H__
+#define __TYPES_LINUX_H__
+
+#include <linux/version.h>
+
+#if defined(CONFIG_MODVERSIONS) && !defined(MODVERSIONS)
+#define MODVERSIONS
+#endif
+#ifdef MODVERSIONS
+#include <config/modversions.h>
+#endif /* MODVERSIONS */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <asm/io.h>
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11)
+ #error "This kernel is probably not supported!!!"
+#elif (!((LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19)) || \
+ (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,27)) || \
+ (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,30))))
+ #warning "This kernel is probably not supported!!! You may need to add some fixes."
+#endif /* LINUX_VERSION_CODE */
+
+
+typedef float float_t; /* Single precision floating point */
+typedef double double_t; /* Double precision floating point */
+
+
+#define _Packed
+#define _PackedType __attribute__ ((packed))
+
+typedef phys_addr_t physAddress_t;
+
+#define UINT8_MAX 0xFF
+#define UINT8_MIN 0
+#define UINT16_MAX 0xFFFF
+#define UINT16_MIN 0
+#define UINT32_MAX 0xFFFFFFFF
+#define UINT32_MIN 0
+#define UINT64_MAX 0xFFFFFFFFFFFFFFFFLL
+#define UINT64_MIN 0
+#define INT8_MAX 0x7F
+#define INT8_MIN 0x80
+#define INT16_MAX 0x7FFF
+#define INT16_MIN 0x8000
+#define INT32_MAX 0x7FFFFFFF
+#define INT32_MIN 0x80000000
+#define INT64_MAX 0x7FFFFFFFFFFFFFFFLL
+#define INT64_MIN 0x8000000000000000LL
+
+#define ON 1
+#define OFF 0
+
+#define FALSE false
+#define TRUE true
+
+
+/************************/
+/* memory access macros */
+/************************/
+#define GET_UINT8(arg) *(volatile uint8_t *)(&(arg))
+#define GET_UINT16(arg) in_be16(&(arg))//*(volatile uint16_t*)(&(arg))
+#define GET_UINT32(arg) in_be32(&(arg))//*(volatile uint32_t*)(&(arg))
+#define GET_UINT64(arg) *(volatile uint64_t*)(&(arg))
+
+#ifdef VERBOSE_WRITE
+void XX_Print(char *str, ...);
+#define WRITE_UINT8(arg, data) \
+ do { XX_Print("ADDR: 0x%08x, VAL: 0x%02x\r\n", (uint32_t)&(arg), (data)); *(volatile uint8_t *)(&(arg)) = (data); } while (0)
+#define WRITE_UINT16(arg, data) \
+ do { XX_Print("ADDR: 0x%08x, VAL: 0x%04x\r\n", (uint32_t)&(arg), (data)); out_be16(&(arg), data); /* *(volatile uint16_t*)(&(arg)) = (data);*/ } while (0)
+#define WRITE_UINT32(arg, data) \
+ do { XX_Print("ADDR: 0x%08x, VAL: 0x%08x\r\n", (uint32_t)&(arg), (data)); out_be32(&(arg), data); /* *(volatile uint32_t*)(&(arg)) = (data);*/ } while (0)
+#define WRITE_UINT64(arg, data) \
+ do { XX_Print("ADDR: 0x%08x, VAL: 0x%016llx\r\n", (uint32_t)&(arg), (data)); *(volatile uint64_t*)(&(arg)) = (data); } while (0)
+
+#else /* not VERBOSE_WRITE */
+#define WRITE_UINT8(arg, data) *(volatile uint8_t *)(&(arg)) = (data)
+#define WRITE_UINT16(arg, data) out_be16(&(arg), data)//*(volatile uint16_t*)(&(arg)) = (data)
+#define WRITE_UINT32(arg, data) out_be32(&(arg), data)//*(volatile unsigned int *)(&(arg)) = (data)
+#define WRITE_UINT64(arg, data) *(volatile uint64_t*)(&(arg)) = (data)
+#endif /* not VERBOSE_WRITE */
+
+
+/*****************************************************************************/
+/* General stuff */
+/*****************************************************************************/
+#ifdef ARRAY_SIZE
+#undef ARRAY_SIZE
+#endif /* ARRAY_SIZE */
+
+#ifdef MAJOR
+#undef MAJOR
+#endif /* MAJOR */
+
+#ifdef MINOR
+#undef MINOR
+#endif /* MINOR */
+
+#ifdef QE_SIZEOF_BD
+#undef QE_SIZEOF_BD
+#endif /* QE_SIZEOF_BD */
+
+#ifdef BD_BUFFER_CLEAR
+#undef BD_BUFFER_CLEAR
+#endif /* BD_BUFFER_CLEAR */
+
+#ifdef BD_BUFFER
+#undef BD_BUFFER
+#endif /* BD_BUFFER */
+
+#ifdef BD_STATUS_AND_LENGTH_SET
+#undef BD_STATUS_AND_LENGTH_SET
+#endif /* BD_STATUS_AND_LENGTH_SET */
+
+#ifdef BD_STATUS_AND_LENGTH
+#undef BD_STATUS_AND_LENGTH
+#endif /* BD_STATUS_AND_LENGTH */
+
+#ifdef BD_BUFFER_ARG
+#undef BD_BUFFER_ARG
+#endif /* BD_BUFFER_ARG */
+
+#ifdef BD_GET_NEXT
+#undef BD_GET_NEXT
+#endif /* BD_GET_NEXT */
+
+#ifdef QE_SDEBCR_BA_MASK
+#undef QE_SDEBCR_BA_MASK
+#endif /* QE_SDEBCR_BA_MASK */
+
+#ifdef BD_BUFFER_SET
+#undef BD_BUFFER_SET
+#endif /* BD_BUFFER_SET */
+
+#ifdef UPGCR_PROTOCOL
+#undef UPGCR_PROTOCOL
+#endif /* UPGCR_PROTOCOL */
+
+#ifdef UPGCR_TMS
+#undef UPGCR_TMS
+#endif /* UPGCR_TMS */
+
+#ifdef UPGCR_RMS
+#undef UPGCR_RMS
+#endif /* UPGCR_RMS */
+
+#ifdef UPGCR_ADDR
+#undef UPGCR_ADDR
+#endif /* UPGCR_ADDR */
+
+#ifdef UPGCR_DIAG
+#undef UPGCR_DIAG
+#endif /* UPGCR_DIAG */
+
+#ifdef NCSW_PARAMS
+#undef NCSW_PARAMS
+#endif /* NCSW_PARAMS */
+
+#ifdef NO_IRQ
+#undef NO_IRQ
+#endif /* NO_IRQ */
+
+#define PRINT_LINE XX_Print("%s:\n %s [%d]\n",__FILE__,__FUNCTION__,__LINE__);
+
+
+#endif /* __TYPES_LINUX_H__ */
diff --git a/drivers/net/ethernet/freescale/fman/src/inc/wrapper/fsl_fman.h b/drivers/net/ethernet/freescale/fman/src/inc/wrapper/fsl_fman.h
new file mode 100644
index 0000000..3efc8ce
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/src/inc/wrapper/fsl_fman.h
@@ -0,0 +1,322 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * 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 Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * 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 Freescale Semiconductor ``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 Freescale Semiconductor 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.
+ */
+
+/******************************************************************************
+ @File fsl_fman.h
+
+ @Description Linux internal kernel API
+*//***************************************************************************/
+
+#ifndef __FSL_FMAN_H
+#define __FSL_FMAN_H
+
+#include <linux/types.h>
+#include <linux/device.h> /* struct device */
+#include <linux/fsl_qman.h> /* struct qman_fq */
+#include "dpaa_integration_ext.h"
+#include "fm_port_ext.h"
+
+/**************************************************************************//**
+ @Group FM_LnxKern_grp Frame Manager Linux wrapper API
+
+ @Description FM API functions, definitions and enums.
+
+ @{
+*//***************************************************************************/
+
+/**************************************************************************//**
+ @Group FM_LnxKern_ctrl_grp Control Unit
+
+ @Description Control Unit
+
+ Internal Kernel Control Unit API
+ @{
+*//***************************************************************************/
+
+/*****************************************************************************/
+/* Internal Linux kernel routines */
+/*****************************************************************************/
+
+/**************************************************************************//**
+ @Description A structure ..,
+*//***************************************************************************/
+struct fm;
+
+/**************************************************************************//**
+ @Description A structure ..,
+*//***************************************************************************/
+struct fm_port;
+
+typedef int (*alloc_pcd_fqids)(struct device *dev, uint32_t num,
+ uint8_t alignment, uint32_t *base_fqid);
+
+typedef int (*free_pcd_fqids)(struct device *dev, uint32_t base_fqid);
+
+struct fm_port_pcd_param {
+ alloc_pcd_fqids cba;
+ free_pcd_fqids cbf;
+ struct device *dev;
+};
+
+/**************************************************************************//**
+ @Description A structure of information about each of the external
+ buffer pools used by the port,
+*//***************************************************************************/
+struct fm_port_pool_param {
+ uint8_t id; /**< External buffer pool id */
+ uint16_t size; /**< External buffer pool buffer size */
+};
+
+/**************************************************************************//**
+ @Description structure for additional port parameters
+*//***************************************************************************/
+struct fm_port_params {
+ uint32_t errq; /**< Error Queue Id. */
+ uint32_t defq; /**< For Tx and HC - Default Confirmation queue,
+ 0 means no Tx conf for processed frames.
+ For Rx and OP - default Rx queue. */
+ uint8_t num_pools; /**< Number of pools use by this port */
+ struct fm_port_pool_param pool_param[FM_PORT_MAX_NUM_OF_EXT_POOLS];
+ /**< Parameters for each pool */
+ uint16_t priv_data_size; /**< Area that user may save for his own
+ need (E.g. save the SKB) */
+ bool parse_results; /**< Put the parser-results in the Rx/Tx buffer */
+ bool hash_results; /**< Put the hash-results in the Rx/Tx buffer */
+ bool time_stamp; /**< Put the time-stamp in the Rx/Tx buffer */
+ bool frag_enable; /**< Fragmentation support, for OP only */
+ uint16_t data_align; /**< value for selecting a data alignment (must be a power of 2);
+ if write optimization is used, must be >= 16. */
+ uint8_t manip_extra_space; /**< Maximum extra size needed (insertion-size minus removal-size);
+ Note that this field impacts the size of the buffer-prefix
+ (i.e. it pushes the data offset); */
+};
+
+/**************************************************************************//**
+ @Function fm_bind
+
+ @Description Bind to a specific FM device.
+
+ @Param[in] fm_dev - the OF handle of the FM device.
+
+ @Return A handle of the FM device.
+
+ @Cautions Allowed only after the port was created.
+*//***************************************************************************/
+struct fm *fm_bind(struct device *fm_dev);
+
+/**************************************************************************//**
+ @Function fm_unbind
+
+ @Description Un-bind from a specific FM device.
+
+ @Param[in] fm - A handle of the FM device.
+
+ @Cautions Allowed only after the port was created.
+*//***************************************************************************/
+void fm_unbind(struct fm *fm);
+
+void *fm_get_handle(struct fm *fm);
+void *fm_get_rtc_handle(struct fm *fm);
+struct resource *fm_get_mem_region(struct fm *fm);
+
+/**************************************************************************//**
+ @Function fm_port_bind
+
+ @Description Bind to a specific FM-port device (may be Rx or Tx port).
+
+ @Param[in] fm_port_dev - the OF handle of the FM port device.
+
+ @Return A handle of the FM port device.
+
+ @Cautions Allowed only after the port was created.
+*//***************************************************************************/
+struct fm_port *fm_port_bind(struct device *fm_port_dev);
+
+/**************************************************************************//**
+ @Function fm_port_unbind
+
+ @Description Un-bind from a specific FM-port device (may be Rx or Tx port).
+
+ @Param[in] port - A handle of the FM port device.
+
+ @Cautions Allowed only after the port was created.
+*//***************************************************************************/
+void fm_port_unbind(struct fm_port *port);
+
+/**************************************************************************//**
+ @Function fm_set_rx_port_params
+
+ @Description Configure parameters for a specific Rx FM-port device.
+
+ @Param[in] port - A handle of the FM port device.
+ @Param[in] params - Rx port parameters
+
+ @Cautions Allowed only after the port is binded.
+*//***************************************************************************/
+void fm_set_rx_port_params(struct fm_port *port,
+ struct fm_port_params *params);
+
+/**************************************************************************//**
+ @Function fm_port_pcd_bind
+
+ @Description Bind as a listener on a port PCD.
+
+ @Param[in] port - A handle of the FM port device.
+ @Param[in] params - PCD port parameters
+
+ @Cautions Allowed only after the port is binded.
+*//***************************************************************************/
+void fm_port_pcd_bind (struct fm_port *port, struct fm_port_pcd_param *params);
+
+/**************************************************************************//**
+ @Function fm_port_get_buff_layout_ext_params
+
+ @Description Get data_align and manip_extra_space from the device tree
+ chosen node if aplied.
+ This function will only update these two parameters.
+ When this port has no such parameters in the device tree
+ values will be set to 0.
+
+ @Param[in] port - A handle of the FM port device.
+ @Param[in] params - PCD port parameters
+
+ @Cautions Allowed only after the port is binded.
+*//***************************************************************************/
+void fm_port_get_buff_layout_ext_params(struct fm_port *port, struct fm_port_params *params);
+
+/**************************************************************************//**
+ @Function fm_get_tx_port_channel
+
+ @Description Get qman-channel number for this Tx port.
+
+ @Param[in] port - A handle of the FM port device.
+
+ @Return qman-channel number for this Tx port.
+
+ @Cautions Allowed only after the port is binded.
+*//***************************************************************************/
+int fm_get_tx_port_channel(struct fm_port *port);
+
+/**************************************************************************//**
+ @Function fm_set_tx_port_params
+
+ @Description Configure parameters for a specific Tx FM-port device
+
+ @Param[in] port - A handle of the FM port device.
+ @Param[in] params - Tx port parameters
+
+ @Cautions Allowed only after the port is binded.
+*//***************************************************************************/
+void fm_set_tx_port_params(struct fm_port *port, struct fm_port_params *params);
+
+
+/**************************************************************************//**
+ @Function fm_mac_set_handle
+
+ @Description Set mac handle
+
+ @Param[in] h_lnx_wrp_fm_dev - A handle of the LnxWrp FM device.
+ @Param[in] h_fm_mac - A handle of the LnxWrp FM MAC device.
+ @Param[in] mac_id - MAC id.
+*//***************************************************************************/
+void fm_mac_set_handle(t_Handle h_lnx_wrp_fm_dev, t_Handle h_fm_mac,
+ int mac_id);
+
+/**************************************************************************//**
+ @Function fm_port_enable
+
+ @Description Enable specific FM-port device (may be Rx or Tx port).
+
+ @Param[in] port - A handle of the FM port device.
+
+ @Cautions Allowed only after the port is initialized.
+*//***************************************************************************/
+int fm_port_enable(struct fm_port *port);
+
+/**************************************************************************//**
+ @Function fm_port_disable
+
+ @Description Disable specific FM-port device (may be Rx or Tx port).
+
+ @Param[in] port - A handle of the FM port device.
+
+ @Cautions Allowed only after the port is initialized.
+*//***************************************************************************/
+void fm_port_disable(struct fm_port *port);
+
+void *fm_port_get_handle(struct fm_port *port);
+
+/**************************************************************************//**
+ @Function fm_port_get_base_address
+
+ @Description Get base address of this port. Useful for accessing
+ port-specific registers (i.e., not common ones).
+
+ @Param[in] port - A handle of the FM port device.
+
+ @Param[out] base_addr - The port's base addr (virtual address).
+*//***************************************************************************/
+void fm_port_get_base_addr(const struct fm_port *port, uint64_t *base_addr);
+
+/**************************************************************************//**
+ @Function fm_mutex_lock
+
+ @Description Lock function required before any FMD/LLD call.
+*//***************************************************************************/
+void fm_mutex_lock(void);
+
+/**************************************************************************//**
+ @Function fm_mutex_unlock
+
+ @Description Unlock function required after any FMD/LLD call.
+*//***************************************************************************/
+void fm_mutex_unlock(void);
+
+/**************************************************************************//**
+ @Function fm_get_max_frm
+
+ @Description Get the maximum frame size
+*//***************************************************************************/
+int fm_get_max_frm(void);
+
+/**************************************************************************//**
+ @Function fm_get_rx_extra_headroom
+
+ @Description Get the extra headroom size
+*//***************************************************************************/
+int fm_get_rx_extra_headroom(void);
+
+/** @} */ /* end of FM_LnxKern_ctrl_grp group */
+/** @} */ /* end of FM_LnxKern_grp group */
+
+
+#endif /* __FSL_FMAN_H */
diff --git a/drivers/net/ethernet/freescale/fman/src/inc/wrapper/fsl_fman_test.h b/drivers/net/ethernet/freescale/fman/src/inc/wrapper/fsl_fman_test.h
new file mode 100644
index 0000000..0466a47
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/src/inc/wrapper/fsl_fman_test.h
@@ -0,0 +1,84 @@
+/* Copyright (c) 2008-2011 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 Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * 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 Freescale Semiconductor ``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 Freescale Semiconductor 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.
+ */
+
+/******************************************************************************
+ @File fsl_fman_test.h
+
+ @Description
+*//***************************************************************************/
+
+#ifndef __FSL_FMAN_TEST_H
+#define __FSL_FMAN_TEST_H
+
+#include <linux/types.h>
+#include <linux/smp.h> /* raw_smp_processor_id() */
+
+//#define FMT_K_DBG
+//#define FMT_K_DBG_RUNTIME
+
+#define _fmt_prk(stage, format, arg...) \
+ printk(stage "fmt (cpu:%u): " format, raw_smp_processor_id(), ##arg)
+
+#define _fmt_inf(format, arg...) _fmt_prk(KERN_INFO, format, ##arg)
+#define _fmt_wrn(format, arg...) _fmt_prk(KERN_WARNING, format, ##arg)
+#define _fmt_err(format, arg...) _fmt_prk(KERN_ERR, format, ##arg)
+
+/* there are two macros for debugging: for runtime and generic.
+ * Helps when the runtime functions are not targeted for debugging,
+ * thus all the unnecessary information will be skipped.
+ */
+/* used for generic debugging */
+#if defined(FMT_K_DBG)
+ #define _fmt_dbg(format, arg...) \
+ printk("fmt [%s:%u](cpu:%u) - " format, \
+ __func__, __LINE__, raw_smp_processor_id(), ##arg)
+#else
+# define _fmt_dbg(arg...)
+#endif
+
+/* used for debugging runtime functions */
+#if defined(FMT_K_DBG_RUNTIME)
+ #define _fmt_dbgr(format, arg...) \
+ printk("fmt [%s:%u](cpu:%u) - " format, \
+ __func__, __LINE__, raw_smp_processor_id(), ##arg)
+#else
+# define _fmt_dbgr(arg...)
+#endif
+
+#define FMT_RX_ERR_Q 0xffffffff
+#define FMT_RX_DFLT_Q 0xfffffffe
+#define FMT_TX_ERR_Q 0xfffffffd
+#define FMT_TX_CONF_Q 0xfffffffc
+
+#define FMAN_TEST_MAX_TX_FQS 8
+
+#endif /* __FSL_FMAN_TEST_H */
diff --git a/drivers/net/ethernet/freescale/fman/src/inc/wrapper/lnxwrp_exp_sym.h b/drivers/net/ethernet/freescale/fman/src/inc/wrapper/lnxwrp_exp_sym.h
new file mode 100644
index 0000000..4c60893
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/src/inc/wrapper/lnxwrp_exp_sym.h
@@ -0,0 +1,125 @@
+/* Copyright (c) 2008-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 Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * 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 Freescale Semiconductor ``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 Freescale Semiconductor 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.
+ */
+
+/*
+ @File lnxwrp_exp_sym.h
+ @Description FMan exported routines
+*/
+
+#ifndef __LNXWRP_EXP_SYM_H
+#define __LNXWRP_EXP_SYM_H
+
+#include "fm_port_ext.h"
+#include "fm_pcd_ext.h"
+#include "fm_mac_ext.h"
+
+
+/* FMAN Port exported routines */
+EXPORT_SYMBOL(FM_PORT_Disable);
+EXPORT_SYMBOL(FM_PORT_Enable);
+EXPORT_SYMBOL(FM_PORT_SetPCD);
+
+/* Runtime PCD exported routines */
+EXPORT_SYMBOL(FM_PCD_Enable);
+EXPORT_SYMBOL(FM_PCD_Disable);
+EXPORT_SYMBOL(FM_PCD_GetCounter);
+EXPORT_SYMBOL(FM_PCD_PrsLoadSw);
+EXPORT_SYMBOL(FM_PCD_KgSetDfltValue);
+EXPORT_SYMBOL(FM_PCD_KgSetAdditionalDataAfterParsing);
+EXPORT_SYMBOL(FM_PCD_SetException);
+EXPORT_SYMBOL(FM_PCD_ModifyCounter);
+EXPORT_SYMBOL(FM_PCD_SetPlcrStatistics);
+EXPORT_SYMBOL(FM_PCD_SetPrsStatistics);
+EXPORT_SYMBOL(FM_PCD_ForceIntr);
+EXPORT_SYMBOL(FM_PCD_HcTxConf);
+
+EXPORT_SYMBOL(FM_PCD_NetEnvCharacteristicsSet);
+EXPORT_SYMBOL(FM_PCD_NetEnvCharacteristicsDelete);
+EXPORT_SYMBOL(FM_PCD_KgSchemeSet);
+EXPORT_SYMBOL(FM_PCD_KgSchemeDelete);
+EXPORT_SYMBOL(FM_PCD_KgSchemeGetCounter);
+EXPORT_SYMBOL(FM_PCD_KgSchemeSetCounter);
+EXPORT_SYMBOL(FM_PCD_CcRootBuild);
+EXPORT_SYMBOL(FM_PCD_CcRootDelete);
+EXPORT_SYMBOL(FM_PCD_MatchTableSet);
+EXPORT_SYMBOL(FM_PCD_MatchTableDelete);
+EXPORT_SYMBOL(FM_PCD_CcRootModifyNextEngine);
+EXPORT_SYMBOL(FM_PCD_MatchTableModifyNextEngine);
+EXPORT_SYMBOL(FM_PCD_MatchTableFindNModifyNextEngine);
+EXPORT_SYMBOL(FM_PCD_MatchTableModifyMissNextEngine);
+EXPORT_SYMBOL(FM_PCD_MatchTableRemoveKey);
+EXPORT_SYMBOL(FM_PCD_MatchTableFindNRemoveKey);
+EXPORT_SYMBOL(FM_PCD_MatchTableAddKey);
+EXPORT_SYMBOL(FM_PCD_MatchTableModifyKeyAndNextEngine);
+EXPORT_SYMBOL(FM_PCD_MatchTableFindNModifyKeyAndNextEngine);
+EXPORT_SYMBOL(FM_PCD_MatchTableModifyKey);
+EXPORT_SYMBOL(FM_PCD_MatchTableFindNModifyKey);
+EXPORT_SYMBOL(FM_PCD_MatchTableGetIndexedHashBucket);
+EXPORT_SYMBOL(FM_PCD_MatchTableGetNextEngine);
+EXPORT_SYMBOL(FM_PCD_MatchTableGetKeyCounter);
+EXPORT_SYMBOL(FM_PCD_MatchTableGetKeyStatistics);
+EXPORT_SYMBOL(FM_PCD_MatchTableFindNGetKeyStatistics);
+EXPORT_SYMBOL(FM_PCD_HashTableSet);
+EXPORT_SYMBOL(FM_PCD_HashTableDelete);
+EXPORT_SYMBOL(FM_PCD_HashTableAddKey);
+EXPORT_SYMBOL(FM_PCD_HashTableRemoveKey);
+EXPORT_SYMBOL(FM_PCD_HashTableModifyNextEngine);
+EXPORT_SYMBOL(FM_PCD_HashTableModifyMissNextEngine);
+EXPORT_SYMBOL(FM_PCD_HashTableGetMissNextEngine);
+EXPORT_SYMBOL(FM_PCD_HashTableFindNGetKeyStatistics);
+EXPORT_SYMBOL(FM_PCD_PlcrProfileSet);
+EXPORT_SYMBOL(FM_PCD_PlcrProfileDelete);
+EXPORT_SYMBOL(FM_PCD_PlcrProfileGetCounter);
+EXPORT_SYMBOL(FM_PCD_PlcrProfileSetCounter);
+EXPORT_SYMBOL(FM_PCD_ManipNodeSet);
+EXPORT_SYMBOL(FM_PCD_ManipNodeDelete);
+EXPORT_SYMBOL(FM_PCD_ManipGetStatistics);
+EXPORT_SYMBOL(FM_PCD_ManipNodeReplace);
+#if (DPAA_VERSION >= 11)
+EXPORT_SYMBOL(FM_PCD_FrmReplicSetGroup);
+EXPORT_SYMBOL(FM_PCD_FrmReplicDeleteGroup);
+EXPORT_SYMBOL(FM_PCD_FrmReplicAddMember);
+EXPORT_SYMBOL(FM_PCD_FrmReplicRemoveMember);
+#endif /* DPAA_VERSION >= 11 */
+
+#ifdef FM_CAPWAP_SUPPORT
+EXPORT_SYMBOL(FM_PCD_StatisticsSetNode);
+#endif /* FM_CAPWAP_SUPPORT */
+
+EXPORT_SYMBOL(FM_PCD_SetAdvancedOffloadSupport);
+
+/* FMAN MAC exported routines */
+EXPORT_SYMBOL(FM_MAC_GetStatistics);
+
+EXPORT_SYMBOL(FM_GetSpecialOperationCoding);
+
+#endif /* __LNXWRP_EXP_SYM_H */
diff --git a/drivers/net/ethernet/freescale/fman/src/inc/wrapper/lnxwrp_fm_ext.h b/drivers/net/ethernet/freescale/fman/src/inc/wrapper/lnxwrp_fm_ext.h
new file mode 100644
index 0000000..8dda657
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/src/inc/wrapper/lnxwrp_fm_ext.h
@@ -0,0 +1,163 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * 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 Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * 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 Freescale Semiconductor ``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 Freescale Semiconductor 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.
+ */
+
+/******************************************************************************
+ @File lnxwrp_fm_ext.h
+
+ @Description TODO
+*//***************************************************************************/
+
+#ifndef __LNXWRP_FM_EXT_H
+#define __LNXWRP_FM_EXT_H
+
+#include "std_ext.h"
+#include "sys_ext.h"
+#include "fm_ext.h"
+#include "fm_muram_ext.h"
+#include "fm_pcd_ext.h"
+#include "fm_port_ext.h"
+#include "fm_mac_ext.h"
+#include "fm_rtc_ext.h"
+
+
+/**************************************************************************//**
+ @Group FM_LnxKern_grp Frame Manager Linux wrapper API
+
+ @Description FM API functions, definitions and enums.
+
+ @{
+*//***************************************************************************/
+
+/**************************************************************************//**
+ @Group FM_LnxKern_init_grp Initialization Unit
+
+ @Description Initialization Unit
+
+ Initialization Flow:
+ Initialization of the FM Module will be carried out by the Linux
+ kernel according to the following sequence:
+ a. Calling the initialization routine with no parameters.
+ b. The driver will register to the Device-Tree.
+ c. The Linux Device-Tree will initiate a call to the driver for
+ initialization.
+ d. The driver will read the appropriate information from the Device-Tree
+ e. [Optional] Calling the advance initialization routines to change
+ driver's defaults.
+ f. Initialization of the device will be automatically upon using it.
+
+ @{
+*//***************************************************************************/
+
+typedef struct t_WrpFmDevSettings
+{
+ t_FmParams param;
+ t_SysObjectAdvConfigEntry *advConfig;
+} t_WrpFmDevSettings;
+
+typedef struct t_WrpFmPcdDevSettings
+{
+ t_FmPcdParams param;
+ t_SysObjectAdvConfigEntry *advConfig;
+} t_WrpFmPcdDevSettings;
+
+typedef struct t_WrpFmPortDevSettings
+{
+ bool frag_enabled;
+ t_FmPortParams param;
+ t_SysObjectAdvConfigEntry *advConfig;
+} t_WrpFmPortDevSettings;
+
+typedef struct t_WrpFmMacDevSettings
+{
+ t_FmMacParams param;
+ t_SysObjectAdvConfigEntry *advConfig;
+} t_WrpFmMacDevSettings;
+
+
+/**************************************************************************//**
+ @Function LNXWRP_FM_Init
+
+ @Description Initialize the FM linux wrapper.
+
+ @Return A handle (descriptor) of the newly created FM Linux wrapper
+ structure.
+*//***************************************************************************/
+t_Handle LNXWRP_FM_Init(void);
+
+/**************************************************************************//**
+ @Function LNXWRP_FM_Free
+
+ @Description Free the FM linux wrapper.
+
+ @Param[in] h_LnxWrpFm - A handle to the FM linux wrapper.
+
+ @Return E_OK on success; Error code otherwise.
+*//***************************************************************************/
+t_Error LNXWRP_FM_Free(t_Handle h_LnxWrpFm);
+
+/**************************************************************************//**
+ @Function LNXWRP_FM_GetMacHandle
+
+ @Description Get the FM-MAC LLD handle from the FM linux wrapper.
+
+ @Param[in] h_LnxWrpFm - A handle to the FM linux wrapper.
+ @Param[in] fmId - Index of the FM device to get the MAC handle from.
+ @Param[in] macId - Index of the mac handle.
+
+ @Return A handle of the LLD compressor.
+*//***************************************************************************/
+t_Handle LNXWRP_FM_GetMacHandle(t_Handle h_LnxWrpFm, uint8_t fmId, uint8_t macId);
+
+#ifdef CONFIG_FSL_FMAN_TEST
+t_Handle LNXWRP_FM_TEST_Init(void);
+t_Error LNXWRP_FM_TEST_Free(t_Handle h_FmTestLnxWrp);
+#endif /* CONFIG_FSL_FMAN_TEST */
+
+/** @} */ /* end of FM_LnxKern_init_grp group */
+
+
+/**************************************************************************//**
+ @Group FM_LnxKern_ctrl_grp Control Unit
+
+ @Description Control Unit
+
+ TODO
+ @{
+*//***************************************************************************/
+
+#include "fsl_fman.h"
+
+/** @} */ /* end of FM_LnxKern_ctrl_grp group */
+/** @} */ /* end of FM_LnxKern_grp group */
+
+
+#endif /* __LNXWRP_FM_EXT_H */
diff --git a/drivers/net/ethernet/freescale/fman/src/inc/xx/xx.h b/drivers/net/ethernet/freescale/fman/src/inc/xx/xx.h
new file mode 100644
index 0000000..b183c86
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/src/inc/xx/xx.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * 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 Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * 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 Freescale Semiconductor ``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 Freescale Semiconductor 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 __XX_H
+#define __XX_H
+
+#include "xx_ext.h"
+
+void * xx_Malloc(uint32_t n);
+void xx_Free(void *p);
+
+void *xx_MallocSmart(uint32_t size, int memPartitionId, uint32_t align);
+void xx_FreeSmart(void *p);
+
+/* never used: */
+#define GetDeviceName(irq) ((char *)NULL)
+
+int GetDeviceIrqNum(int irq);
+
+
+#endif /* __XX_H */
diff --git a/drivers/net/ethernet/freescale/fman/src/system/Makefile b/drivers/net/ethernet/freescale/fman/src/system/Makefile
new file mode 100644
index 0000000..f1aa763
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/src/system/Makefile
@@ -0,0 +1,10 @@
+#
+# Makefile for the Freescale Ethernet controllers
+#
+EXTRA_CFLAGS += -DVERSION=\"\"
+#
+#Include netcomm SW specific definitions
+include $(srctree)/drivers/net/ethernet/freescale/fman/ncsw_config.mk
+#
+
+obj-y += sys_io.o
diff --git a/drivers/net/ethernet/freescale/fman/src/system/sys_io.c b/drivers/net/ethernet/freescale/fman/src/system/sys_io.c
new file mode 100644
index 0000000..c106a8b
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/src/system/sys_io.c
@@ -0,0 +1,171 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * 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 Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * 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 Freescale Semiconductor ``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 Freescale Semiconductor 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 <linux/version.h>
+
+#if defined(CONFIG_MODVERSIONS) && !defined(MODVERSIONS)
+#define MODVERSIONS
+#endif
+#ifdef MODVERSIONS
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+#include <linux/modversions.h>
+#else
+#include <config/modversions.h>
+#endif /* LINUX_VERSION_CODE */
+#endif /* MODVERSIONS */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+
+#include <asm/io.h>
+
+#include "std_ext.h"
+#include "error_ext.h"
+#include "string_ext.h"
+#include "list_ext.h"
+#include "sys_io_ext.h"
+
+
+#define __ERR_MODULE__ MODULE_UNKNOWN
+
+
+typedef struct {
+ uint64_t virtAddr;
+ uint64_t physAddr;
+ uint32_t size;
+ t_List node;
+} t_IoMap;
+#define IOMAP_OBJECT(ptr) LIST_OBJECT(ptr, t_IoMap, node)
+
+LIST(mapsList);
+
+
+static void EnqueueIoMap(t_IoMap *p_IoMap)
+{
+ uint32_t intFlags;
+
+ intFlags = XX_DisableAllIntr();
+ LIST_AddToTail(&p_IoMap->node, &mapsList);
+ XX_RestoreAllIntr(intFlags);
+}
+
+static t_IoMap * FindIoMapByVirtAddr(uint64_t addr)
+{
+ t_IoMap *p_IoMap;
+ t_List *p_Pos;
+
+ LIST_FOR_EACH(p_Pos, &mapsList)
+ {
+ p_IoMap = IOMAP_OBJECT(p_Pos);
+ if ((addr >= p_IoMap->virtAddr) && (addr < p_IoMap->virtAddr+p_IoMap->size))
+ return p_IoMap;
+ }
+
+ return NULL;
+}
+
+static t_IoMap * FindIoMapByPhysAddr(uint64_t addr)
+{
+ t_IoMap *p_IoMap;
+ t_List *p_Pos;
+
+ LIST_FOR_EACH(p_Pos, &mapsList)
+ {
+ p_IoMap = IOMAP_OBJECT(p_Pos);
+ if ((addr >= p_IoMap->physAddr) && (addr < p_IoMap->physAddr+p_IoMap->size))
+ return p_IoMap;
+ }
+
+ return NULL;
+}
+
+t_Error SYS_RegisterIoMap (uint64_t virtAddr, uint64_t physAddr, uint32_t size)
+{
+ t_IoMap *p_IoMap;
+
+ p_IoMap = (t_IoMap*)XX_Malloc(sizeof(t_IoMap));
+ if (!p_IoMap)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("message handler object!!!"));
+ memset(p_IoMap, 0, sizeof(t_IoMap));
+
+ p_IoMap->virtAddr = virtAddr;
+ p_IoMap->physAddr = physAddr;
+ p_IoMap->size = size;
+
+ INIT_LIST(&p_IoMap->node);
+ EnqueueIoMap(p_IoMap);
+
+ return E_OK;
+}
+
+t_Error SYS_UnregisterIoMap (uint64_t virtAddr)
+{
+ t_IoMap *p_IoMap = FindIoMapByVirtAddr(virtAddr);
+ if (!p_IoMap)
+ RETURN_ERROR(MINOR, E_NO_DEVICE, ("message handler not found in list!!!"));
+
+ LIST_Del(&p_IoMap->node);
+ XX_Free(p_IoMap);
+
+ return E_OK;
+}
+
+uint64_t SYS_PhysToVirt(uint64_t addr)
+{
+ t_IoMap *p_IoMap = FindIoMapByPhysAddr(addr);
+ if (p_IoMap)
+ {
+ /* This is optimization - put the latest in the list-head - like a cache */
+ if (mapsList.p_Next != &p_IoMap->node)
+ {
+ uint32_t intFlags = XX_DisableAllIntr();
+ LIST_DelAndInit(&p_IoMap->node);
+ LIST_Add(&p_IoMap->node, &mapsList);
+ XX_RestoreAllIntr(intFlags);
+ }
+ return (uint64_t)(addr - p_IoMap->physAddr + p_IoMap->virtAddr);
+ }
+ return PTR_TO_UINT(phys_to_virt((unsigned long)addr));
+}
+
+uint64_t SYS_VirtToPhys(uint64_t addr)
+{
+ t_IoMap *p_IoMap;
+
+ if (addr == 0)
+ return 0;
+
+ p_IoMap = FindIoMapByVirtAddr(addr);
+ if (p_IoMap)
+ return (uint64_t)(addr - p_IoMap->virtAddr + p_IoMap->physAddr);
+ return (uint64_t)virt_to_phys(UINT_TO_PTR(addr));
+}
diff --git a/drivers/net/ethernet/freescale/fman/src/wrapper/Makefile b/drivers/net/ethernet/freescale/fman/src/wrapper/Makefile
new file mode 100644
index 0000000..22fe2e2
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/src/wrapper/Makefile
@@ -0,0 +1,20 @@
+#
+# Makefile for the Freescale Ethernet controllers
+#
+EXTRA_CFLAGS += -DVERSION=\"\"
+#
+#Include netcomm SW specific definitions
+include $(srctree)/drivers/net/ethernet/freescale/fman/ncsw_config.mk
+
+NCSW_FM_INC = $(srctree)/drivers/net/ethernet/freescale/fman/Peripherals/FM/inc
+
+EXTRA_CFLAGS += -I$(NCSW_FM_INC)
+EXTRA_CFLAGS += -I$(NET_DPA)
+
+obj-y += fsl-ncsw-PFM.o
+obj-$(CONFIG_FSL_FMAN_TEST) += fman_test.o
+
+fsl-ncsw-PFM-objs := lnxwrp_fm.o lnxwrp_fm_port.o lnxwrp_ioctls_fm.o \
+ lnxwrp_sysfs.o lnxwrp_sysfs_fm.o lnxwrp_sysfs_fm_port.o \
+ lnxwrp_resources.o
+obj-$(CONFIG_COMPAT) += lnxwrp_ioctls_fm_compat.o
diff --git a/drivers/net/ethernet/freescale/fman/src/wrapper/fman_test.c b/drivers/net/ethernet/freescale/fman/src/wrapper/fman_test.c
new file mode 100644
index 0000000..81edc9a
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/src/wrapper/fman_test.c
@@ -0,0 +1,1665 @@
+/* Copyright (c) 2008-2011 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 Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * 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 Freescale Semiconductor ``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 Freescale Semiconductor 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.
+ */
+
+/*
+ @File fman_test.c
+ @Authors Pistirica Sorin Andrei
+ @Description FM Linux test environment
+*/
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/cdev.h>
+#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/of_platform.h>
+#include <linux/ip.h>
+#include <linux/compat.h>
+#include <linux/uaccess.h>
+#include <linux/errno.h>
+#include <linux/netdevice.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+#include <linux/fsl_qman.h>
+#include <linux/fsl_bman.h>
+
+/* private headers */
+#include "fm_ext.h"
+#include "fsl_fman.h"
+#include "fm_port_ext.h"
+#if (DPAA_VERSION == 11)
+#include "../../Peripherals/FM/MAC/memac.h"
+#endif
+#include "fm_test_ioctls.h"
+#include "fsl_fman_test.h"
+
+#include "dpaa_eth.h"
+#include "dpaa_eth-common.h"
+
+#define FMT_FRM_WATERMARK 0xdeadbeefdeadbeeaLL
+
+struct fmt_frame_s {
+ ioc_fmt_buff_desc_t buff;
+ struct list_head list;
+};
+
+struct fmt_fqs_s {
+ struct qman_fq fq_base;
+ bool init;
+ struct fmt_port_s *fmt_port_priv;
+};
+
+struct fmt_port_pcd_s {
+ int num_queues;
+ struct fmt_fqs_s *fmt_pcd_fqs;
+ uint32_t fqid_base;
+};
+
+/* char dev structure: fm test port */
+struct fmt_port_s {
+ bool valid;
+ uint8_t id;
+ ioc_fmt_port_type port_type;
+ ioc_diag_mode diag;
+ bool compat_test_type;
+
+ /* fm ports */
+ /* ! for oh ports p_tx_fm_port_dev == p_rx_fm_port_dev &&
+ * p_tx_port == p_rx_port */
+ /* t_LnxWrpFmPortDev */
+ struct fm_port *p_tx_port;
+ /* t_LnxWrpFmPortDev->h_Dev: t_FmPort */
+ void *p_tx_fm_port_dev;
+ /* t_LnxWrpFmPortDev */
+ struct fm_port *p_rx_port;
+ /* t_LnxWrpFmPortDev->h_Dev: t_FmPort */
+ void *p_rx_fm_port_dev;
+
+ void *p_mac_dev;
+ uint64_t fm_phys_base_addr;
+
+ /* read/write queue manipulation */
+ spinlock_t rx_q_lock;
+ struct list_head rx_q;
+
+ /* tx queuee for injecting trafic */
+ int num_of_tx_fqs;
+ struct fmt_fqs_s p_tx_fqs[FMAN_TEST_MAX_TX_FQS];
+
+ /* pcd private queues manipulation */
+ struct fmt_port_pcd_s fmt_port_pcd;
+
+ /* debugging stuff */
+
+#if defined(FMT_K_DBG) || defined(FMT_K_DBG_RUNTIME)
+ atomic_t enqueue_to_qman_frm;
+ atomic_t enqueue_to_rxq;
+ atomic_t dequeue_from_rxq;
+ atomic_t not_enqueue_to_rxq_wrong_frm;
+#endif
+
+};
+
+/* The devices. */
+struct fmt_s {
+ int major;
+ struct fmt_port_s ports[IOC_FMT_MAX_NUM_OF_PORTS];
+ struct class *fmt_class;
+};
+
+/* fm test structure */
+static struct fmt_s fm_test;
+
+#if (DPAA_VERSION == 11)
+struct mac_priv_s {
+ t_Handle mac;
+};
+#endif
+
+#define DTSEC_BASE_ADDR 0x000e0000
+#define DTSEC_MEM_RANGE 0x00002000
+#define MAC_1G_MACCFG1 0x00000100
+#define MAC_1G_LOOP_MASK 0x00000100
+static int set_1gmac_loopback(
+ struct fmt_port_s *fmt_port,
+ bool en)
+{
+#if (DPAA_VERSION <= 10)
+ uint32_t dtsec_idx = fmt_port->id; /* dtsec for which port */
+ uint32_t dtsec_idx_off = dtsec_idx * DTSEC_MEM_RANGE;
+ phys_addr_t maccfg1_hw;
+ void *maccfg1_map;
+ uint32_t maccfg1_val;
+
+ /* compute the maccfg1 register address */
+ maccfg1_hw = fmt_port->fm_phys_base_addr +
+ (phys_addr_t)(DTSEC_BASE_ADDR +
+ dtsec_idx_off +
+ MAC_1G_MACCFG1);
+
+ /* map register */
+ maccfg1_map = ioremap(maccfg1_hw, sizeof(u32));
+
+ /* set register */
+ maccfg1_val = in_be32(maccfg1_map);
+ if (en)
+ maccfg1_val |= MAC_1G_LOOP_MASK;
+ else
+ maccfg1_val &= ~MAC_1G_LOOP_MASK;
+ out_be32(maccfg1_map, maccfg1_val);
+
+ /* unmap register */
+ iounmap(maccfg1_map);
+#else
+ struct mac_device *mac_dev;
+ struct mac_priv_s *priv;
+ t_Memac *p_memac;
+
+ if (!fmt_port)
+ return -EINVAL;
+
+ mac_dev = (struct mac_device *)fmt_port->p_mac_dev;
+
+ if (!mac_dev)
+ return -EINVAL;
+
+ priv = macdev_priv(mac_dev);
+
+ if (!priv)
+ return -EINVAL;
+
+ p_memac = priv->mac;
+
+ if (!p_memac)
+ return -EINVAL;
+
+ memac_set_loopback(p_memac->p_MemMap, en);
+#endif
+ return 0;
+}
+
+/* TODO: re-write this function */
+static int set_10gmac_int_loopback(
+ struct fmt_port_s *fmt_port,
+ bool en)
+{
+#ifndef FM_10G_MAC_NO_CTRL_LOOPBACK
+#define FM_10GMAC0_OFFSET 0x000f0000
+#define FM_10GMAC_CMD_CONF_CTRL_OFFSET 0x8
+#define CMD_CFG_LOOPBACK_EN 0x00000400
+
+ uint64_t base_addr, reg_addr;
+ uint32_t tmp_val;
+
+ base_addr = fmt_port->fm_phys_base_addr + (FM_10GMAC0_OFFSET +
+ ((fmt_port->id-FM_MAX_NUM_OF_1G_RX_PORTS)*0x2000));
+
+ base_addr = PTR_TO_UINT(ioremap(base_addr, 0x1000));
+
+ reg_addr = base_addr + FM_10GMAC_CMD_CONF_CTRL_OFFSET;
+ tmp_val = GET_UINT32(*((uint32_t *)UINT_TO_PTR(reg_addr)));
+ if (en)
+ tmp_val |= CMD_CFG_LOOPBACK_EN;
+ else
+ tmp_val &= ~CMD_CFG_LOOPBACK_EN;
+ WRITE_UINT32(*((uint32_t *)UINT_TO_PTR(reg_addr)), tmp_val);
+
+ iounmap(UINT_TO_PTR(base_addr));
+
+ return 0;
+#else
+ _fmt_err("TGEC don't have internal-loopback.\n");
+ return -EPERM;
+#endif
+}
+
+static int set_mac_int_loopback(struct fmt_port_s *fmt_port, bool en)
+{
+ int _err = 0;
+
+ switch (fmt_port->port_type) {
+
+ case e_IOC_FMT_PORT_T_RXTX:
+ /* 1G port */
+ if (fmt_port->id < FM_MAX_NUM_OF_1G_RX_PORTS)
+ _err = set_1gmac_loopback(fmt_port, en);
+ /* 10g port */
+ else if ((fmt_port->id >= FM_MAX_NUM_OF_1G_RX_PORTS) &&
+ (fmt_port->id < FM_MAX_NUM_OF_1G_RX_PORTS +
+ FM_MAX_NUM_OF_10G_RX_PORTS)) {
+
+ _err = set_10gmac_int_loopback(fmt_port, en);
+ } else
+ _err = -EINVAL;
+ break;
+ /* op port does not have MAC (loopback mode) */
+ case e_IOC_FMT_PORT_T_OP:
+
+ _err = 0;
+ break;
+ default:
+
+ _err = -EPERM;
+ break;
+ }
+
+ return _err;
+}
+
+static void enqueue_fmt_frame(
+ struct fmt_port_s *fmt_port,
+ struct fmt_frame_s *p_fmt_frame)
+{
+ spinlock_t *rx_q_lock = NULL;
+
+ rx_q_lock = &fmt_port->rx_q_lock;
+
+ spin_lock(rx_q_lock);
+ list_add_tail(&p_fmt_frame->list, &fmt_port->rx_q);
+ spin_unlock(rx_q_lock);
+
+#if defined(FMT_K_DBG) || defined(FMT_K_DBG_RUNTIME)
+ atomic_inc(&fmt_port->enqueue_to_rxq);
+#endif
+}
+
+static struct fmt_frame_s *dequeue_fmt_frame(
+ struct fmt_port_s *fmt_port)
+{
+ struct fmt_frame_s *p_fmt_frame = NULL;
+ spinlock_t *rx_q_lock = NULL;
+
+ rx_q_lock = &fmt_port->rx_q_lock;
+
+ spin_lock(rx_q_lock);
+
+#define list_last_entry(ptr, type, member) list_entry((ptr)->prev, type, member)
+
+ if (!list_empty(&fmt_port->rx_q)) {
+ p_fmt_frame = list_last_entry(&fmt_port->rx_q,
+ struct fmt_frame_s,
+ list);
+ list_del(&p_fmt_frame->list);
+
+#if defined(FMT_K_DBG) || defined(FMT_K_DBG_RUNTIME)
+ atomic_inc(&fmt_port->dequeue_from_rxq);
+#endif
+ }
+
+ spin_unlock(rx_q_lock);
+
+ return p_fmt_frame;
+}
+
+/* eth-dev -to- fmt port association */
+struct fmt_port_s *match_dpa_to_fmt_port(
+ struct dpa_priv_s *dpa_priv) {
+ struct mac_device *mac_dev = dpa_priv->mac_dev;
+ struct fm_port *fm_port = (struct fm_port *) mac_dev;
+ struct fmt_port_s *fmt_port = NULL;
+ int i;
+
+ _fmt_dbgr("calling...\n");
+
+ /* find the FM-test-port object */
+ for (i = 0; i < IOC_FMT_MAX_NUM_OF_PORTS; i++)
+ if ((fm_test.ports[i].p_mac_dev &&
+ mac_dev == fm_test.ports[i].p_mac_dev) ||
+ fm_port == fm_test.ports[i].p_tx_port) {
+
+ fmt_port = &fm_test.ports[i];
+ break;
+ }
+
+ _fmt_dbgr("called\n");
+ return fmt_port;
+}
+
+void dump_frame(
+ uint8_t *buffer,
+ uint32_t size)
+{
+#if defined(FMT_K_DBG) || defined(FMT_K_DBG_RUNTIME)
+ unsigned int i;
+
+ for (i = 0; i < size; i++) {
+ if (i%16 == 0)
+ printk(KERN_DEBUG "\n");
+ printk(KERN_DEBUG "%2x ", *(buffer+i));
+ }
+#endif
+ return;
+}
+
+bool test_and_steal_frame(struct fmt_port_s *fmt_port,
+ uint32_t fqid,
+ uint8_t *buffer,
+ uint32_t size)
+{
+ struct fmt_frame_s *p_fmt_frame = NULL;
+ bool test_and_steal_frame_frame;
+ uint32_t data_offset;
+ uint32_t i;
+
+ _fmt_dbgr("calling...\n");
+
+ if (!fmt_port || !fmt_port->p_rx_fm_port_dev)
+ return false;
+
+ /* check watermark */
+ test_and_steal_frame_frame = false;
+ for (i = 0; i < size; i++) {
+ uint64_t temp = *((uint64_t *)(buffer + i));
+
+ if (temp == (uint64_t) FMT_FRM_WATERMARK) {
+ _fmt_dbgr("watermark found!\n");
+ test_and_steal_frame_frame = true;
+ break;
+ }
+ }
+
+ if (!test_and_steal_frame_frame) {
+#if defined(FMT_K_DBG) || defined(FMT_K_DBG_RUNTIME)
+ atomic_inc(&fmt_port->not_enqueue_to_rxq_wrong_frm);
+#endif
+ _fmt_dbgr("NOT watermark found!\n");
+ return false;
+ }
+
+ /* do not enqueue the tx conf/err frames */
+ if ((fqid == FMT_TX_CONF_Q) || (fqid == FMT_TX_ERR_Q))
+ goto _test_and_steal_frame_return_true;
+
+ _fmt_dbgr("on port %d got FMUC frame\n", fmt_port->id);
+ data_offset = FM_PORT_GetBufferDataOffset(
+ fmt_port->p_rx_fm_port_dev);
+
+ p_fmt_frame = kmalloc(sizeof(struct fmt_frame_s), GFP_KERNEL);
+
+ /* dump frame... no more space left on device */
+ if (p_fmt_frame == NULL) {
+ _fmt_err("no space left on device!\n");
+ goto _test_and_steal_frame_return_true;
+ }
+
+ memset(p_fmt_frame, 0, sizeof(struct fmt_frame_s));
+ p_fmt_frame->buff.p_data = kmalloc(size * sizeof(uint8_t), GFP_KERNEL);
+
+ /* No more space left on device*/
+ if (p_fmt_frame->buff.p_data == NULL) {
+ _fmt_err("no space left on device!\n");
+ kfree(p_fmt_frame);
+ goto _test_and_steal_frame_return_true;
+ }
+
+ p_fmt_frame->buff.size = size-data_offset;
+ p_fmt_frame->buff.qid = fqid;
+
+ memcpy(p_fmt_frame->buff.p_data,
+ (uint8_t *)PTR_MOVE(buffer, data_offset),
+ p_fmt_frame->buff.size);
+
+ memcpy(p_fmt_frame->buff.buff_context.fm_prs_res,
+ FM_PORT_GetBufferPrsResult(fmt_port->p_rx_fm_port_dev,
+ (char *)buffer),
+ 32);
+
+ /* enqueue frame - this frame will go to us */
+ enqueue_fmt_frame(fmt_port, p_fmt_frame);
+
+_test_and_steal_frame_return_true:
+ return true;
+}
+
+static int fmt_fq_release(const struct qm_fd *fd)
+{
+ struct dpa_bp *_dpa_bp;
+ struct bm_buffer _bmb;
+
+ if (fd->format == qm_fd_contig) {
+ _dpa_bp = dpa_bpid2pool(fd->bpid);
+ BUG_ON(IS_ERR(_dpa_bp));
+
+ _bmb.hi = fd->addr_hi;
+ _bmb.lo = fd->addr_lo;
+
+ while (bman_release(_dpa_bp->pool, &_bmb, 1, 0))
+ cpu_relax();
+
+ } else {
+ _fmt_err("frame not supported !\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+/* sync it w/ dpaa_eth.c: DPA_BP_HEAD */
+#define DPA_BP_HEADROOM (DPA_TX_PRIV_DATA_SIZE + \
+ fm_get_rx_extra_headroom() + \
+ DPA_PARSE_RESULTS_SIZE + \
+ DPA_HASH_RESULTS_SIZE)
+#define MAC_HEADER_LENGTH 14
+#define L2_AND_HEADROOM_OFF ((DPA_BP_HEADROOM) + (MAC_HEADER_LENGTH))
+
+/* dpa ingress hooks definition */
+enum dpaa_eth_hook_result fmt_rx_default_hook(
+ struct sk_buff *skb,
+ struct net_device *net_dev,
+ u32 fqid)
+{
+ struct dpa_priv_s *dpa_priv = NULL;
+ struct fmt_port_s *fmt_port = NULL;
+ uint8_t *buffer;
+ uint32_t buffer_len;
+
+ _fmt_dbgr("calling...\n");
+
+ dpa_priv = netdev_priv(net_dev);
+ fmt_port = match_dpa_to_fmt_port(dpa_priv);
+
+ /* conversion from skb to fd:
+ * skb cames processed for L3, so we need to go back for
+ * layer 2 offset */
+ buffer = (uint8_t *)(skb->data - ((int)L2_AND_HEADROOM_OFF));
+ buffer_len = skb->len + ((int)L2_AND_HEADROOM_OFF);
+
+ /* if is not out frame let dpa to handle it */
+ if (test_and_steal_frame(fmt_port,
+ FMT_RX_DFLT_Q,
+ buffer,
+ buffer_len))
+ goto _fmt_rx_default_hook_stolen;
+
+ _fmt_dbgr("called:DPAA_ETH_CONTINUE.\n");
+ return DPAA_ETH_CONTINUE;
+
+_fmt_rx_default_hook_stolen:
+ dev_kfree_skb(skb);
+
+ _fmt_dbgr("called:DPAA_ETH_STOLEN.\n");
+ return DPAA_ETH_STOLEN;
+}
+
+enum dpaa_eth_hook_result fmt_rx_error_hook(
+ struct net_device *net_dev,
+ const struct qm_fd *fd,
+ u32 fqid)
+{
+ struct dpa_priv_s *dpa_priv = NULL;
+ struct dpa_bp *dpa_bp = NULL;
+ struct fmt_port_s *fmt_port = NULL;
+ void *fd_virt_addr = NULL;
+ dma_addr_t addr = qm_fd_addr(fd);
+
+ _fmt_dbgr("calling...\n");
+
+ dpa_priv = netdev_priv(net_dev);
+ fmt_port = match_dpa_to_fmt_port(dpa_priv);
+
+ /* dpaa doesn't do this... we have to do it here */
+ dpa_bp = dpa_bpid2pool(fd->bpid);
+ dma_unmap_single(dpa_bp->dev, addr, dpa_bp->size, DMA_BIDIRECTIONAL);
+
+ fd_virt_addr = phys_to_virt(addr);
+ /* if is not out frame let dpa to handle it */
+ if (test_and_steal_frame(fmt_port,
+ FMT_RX_ERR_Q,
+ fd_virt_addr,
+ fd->length20 + fd->offset)) {
+ goto _fmt_rx_error_hook_stolen;
+ }
+
+ _fmt_dbgr("called:DPAA_ETH_CONTINUE.\n");
+ return DPAA_ETH_CONTINUE;
+
+_fmt_rx_error_hook_stolen:
+ /* the frame data doesn't matter,
+ * so, no mapping is needed */
+ fmt_fq_release(fd);
+
+ _fmt_dbgr("called:DPAA_ETH_STOLEN.\n");
+ return DPAA_ETH_STOLEN;
+}
+
+enum dpaa_eth_hook_result fmt_tx_confirm_hook(
+ struct net_device *net_dev,
+ const struct qm_fd *fd,
+ u32 fqid)
+{
+ struct dpa_priv_s *dpa_priv = NULL;
+ struct fmt_port_s *fmt_port = NULL;
+ dma_addr_t addr = qm_fd_addr(fd);
+ void *fd_virt_addr = NULL;
+ uint32_t fd_len = 0;
+
+ _fmt_dbgr("calling...\n");
+
+ dpa_priv = netdev_priv(net_dev);
+ fmt_port = match_dpa_to_fmt_port(dpa_priv);
+
+ fd_virt_addr = phys_to_virt(addr);
+ fd_len = fd->length20 + fd->offset;
+
+ if (fd_len > fm_get_max_frm()) {
+ _fmt_err("tx confirm bad frame size: %u!\n", fd_len);
+ goto _fmt_tx_confirm_hook_continue;
+ }
+
+ if (test_and_steal_frame(fmt_port,
+ FMT_TX_CONF_Q,
+ fd_virt_addr,
+ fd_len))
+ goto _fmt_tx_confirm_hook_stolen;
+
+_fmt_tx_confirm_hook_continue:
+ _fmt_dbgr("called:DPAA_ETH_CONTINUE.\n");
+ return DPAA_ETH_CONTINUE;
+
+_fmt_tx_confirm_hook_stolen:
+ kfree(fd_virt_addr);
+
+ _fmt_dbgr("called:DPAA_ETH_STOLEN.\n");
+ return DPAA_ETH_STOLEN;
+}
+
+enum dpaa_eth_hook_result fmt_tx_confirm_error_hook(
+ struct net_device *net_dev,
+ const struct qm_fd *fd,
+ u32 fqid)
+{
+ struct dpa_priv_s *dpa_priv = NULL;
+ struct fmt_port_s *fmt_port = NULL;
+ dma_addr_t addr = qm_fd_addr(fd);
+ void *fd_virt_addr = NULL;
+ uint32_t fd_len = 0;
+
+ _fmt_dbgr("calling...\n");
+
+ dpa_priv = netdev_priv(net_dev);
+ fmt_port = match_dpa_to_fmt_port(dpa_priv);
+
+ fd_virt_addr = phys_to_virt(addr);
+ fd_len = fd->length20 + fd->offset;
+
+ if (fd_len > fm_get_max_frm()) {
+ _fmt_err("tx confirm err bad frame size: %u !\n", fd_len);
+ goto _priv_ingress_tx_err_continue;
+ }
+
+ if (test_and_steal_frame(fmt_port, FMT_TX_ERR_Q, fd_virt_addr, fd_len))
+ goto _priv_ingress_tx_err_stolen;
+
+_priv_ingress_tx_err_continue:
+ _fmt_dbgr("called:DPAA_ETH_CONTINUE.\n");
+ return DPAA_ETH_CONTINUE;
+
+_priv_ingress_tx_err_stolen:
+ kfree(fd_virt_addr);
+
+ _fmt_dbgr("called:DPAA_ETH_STOLEN.\n");
+ return DPAA_ETH_STOLEN;
+}
+
+/* egress callbacks definition */
+enum qman_cb_dqrr_result fmt_egress_dqrr(
+ struct qman_portal *portal,
+ struct qman_fq *fq,
+ const struct qm_dqrr_entry *dqrr)
+{
+ /* this callback should never be called */
+ BUG();
+ return qman_cb_dqrr_consume;
+}
+
+static void fmt_egress_error_dqrr(
+ struct qman_portal *p,
+ struct qman_fq *fq,
+ const struct qm_mr_entry *msg)
+{
+ uint8_t *fd_virt_addr = NULL;
+
+ /* tx failure, on the ern callback - release buffer */
+ fd_virt_addr = (uint8_t *)phys_to_virt(qm_fd_addr(&msg->ern.fd));
+ kfree(fd_virt_addr);
+
+ return;
+}
+
+static const struct qman_fq fmt_egress_fq = {
+ .cb = { .dqrr = fmt_egress_dqrr,
+ .ern = fmt_egress_error_dqrr,
+ .fqs = NULL}
+};
+
+int fmt_fq_alloc(
+ struct fmt_fqs_s *fmt_fqs,
+ const struct qman_fq *qman_fq,
+ uint32_t fqid, uint32_t flags,
+ uint16_t channel, uint8_t wq)
+{
+ int _errno = 0;
+
+ _fmt_dbg("calling...\n");
+
+ fmt_fqs->fq_base = *qman_fq;
+
+ if (fqid == 0) {
+ flags |= QMAN_FQ_FLAG_DYNAMIC_FQID;
+ flags &= ~QMAN_FQ_FLAG_NO_MODIFY;
+ } else
+ flags &= ~QMAN_FQ_FLAG_DYNAMIC_FQID;
+
+ fmt_fqs->init = !(flags & QMAN_FQ_FLAG_NO_MODIFY);
+
+ _errno = qman_create_fq(fqid, flags, &fmt_fqs->fq_base);
+ if (_errno < 0) {
+ _fmt_err("frame queues create failed.\n");
+ return -EINVAL;
+ }
+
+ if (fmt_fqs->init) {
+ struct qm_mcc_initfq initfq;
+
+ initfq.we_mask = QM_INITFQ_WE_DESTWQ;
+ initfq.fqd.dest.channel = channel;
+ initfq.fqd.dest.wq = wq;
+
+ _errno = qman_init_fq(&fmt_fqs->fq_base,
+ QMAN_INITFQ_FLAG_SCHED,
+ &initfq);
+ if (_errno < 0) {
+ _fmt_err("frame queues init erorr.\n");
+ qman_destroy_fq(&fmt_fqs->fq_base, 0);
+ return -EINVAL;
+ }
+ }
+
+ _fmt_dbg("called.\n");
+ return 0;
+}
+
+static int fmt_fq_free(struct fmt_fqs_s *fmt_fq)
+{
+ int _err = 0;
+
+ _fmt_dbg("calling...\n");
+
+ if (fmt_fq->init) {
+ _err = qman_retire_fq(&fmt_fq->fq_base, NULL);
+ if (unlikely(_err < 0))
+ _fmt_err("qman_retire_fq(%u) = %d\n",
+ qman_fq_fqid(&fmt_fq->fq_base), _err);
+
+ _err = qman_oos_fq(&fmt_fq->fq_base);
+ if (unlikely(_err < 0))
+ _fmt_err("qman_oos_fq(%u) = %d\n",
+ qman_fq_fqid(&fmt_fq->fq_base), _err);
+ }
+
+ qman_destroy_fq(&fmt_fq->fq_base, 0);
+
+ _fmt_dbg("called.\n");
+ return _err;
+}
+
+/* private pcd dqrr calbacks */
+static enum qman_cb_dqrr_result fmt_pcd_dqrr(
+ struct qman_portal *portal,
+ struct qman_fq *fq,
+ const struct qm_dqrr_entry *dq)
+{
+ struct dpa_bp *dpa_bp = NULL;
+ dma_addr_t addr = qm_fd_addr(&dq->fd);
+ uint8_t *fd_virt_addr = NULL;
+ struct fmt_port_s *fmt_port;
+ struct fmt_port_pcd_s *fmt_port_pcd;
+ uint32_t relative_fqid = 0;
+ uint32_t fd_len = 0;
+
+ _fmt_dbgr("calling...\n");
+
+ /* upcast - from pcd_alloc_fq */
+ fmt_port = ((struct fmt_fqs_s *)fq)->fmt_port_priv;
+ if (!fmt_port) {
+ _fmt_err(" wrong fmt port -to- fq match.\n");
+ goto _fmt_pcd_dqrr_return;
+ }
+ fmt_port_pcd = &fmt_port->fmt_port_pcd;
+
+ relative_fqid = dq->fqid - fmt_port_pcd->fqid_base;
+ _fmt_dbgr("pcd dqrr got frame on relative fq:%u@base:%u\n",
+ relative_fqid, fmt_port_pcd->fqid_base);
+
+ fd_len = dq->fd.length20 + dq->fd.offset;
+
+ if (fd_len > fm_get_max_frm()) {
+ _fmt_err("pcd dqrr wrong frame size: %u (%u:%u)!\n",
+ fd_len, dq->fd.length20, dq->fd.offset);
+ goto _fmt_pcd_dqrr_return;
+ }
+
+ dpa_bp = dpa_bpid2pool(dq->fd.bpid);
+ dma_unmap_single(dpa_bp->dev, addr, dpa_bp->size, DMA_BIDIRECTIONAL);
+
+ fd_virt_addr = phys_to_virt(addr);
+ if (!test_and_steal_frame(fmt_port, relative_fqid, fd_virt_addr,
+ fd_len)) {
+
+#if defined(FMT_K_DBG) || defined(FMT_K_DBG_RUNTIME)
+ atomic_inc(&fmt_port->not_enqueue_to_rxq_wrong_frm);
+#endif
+ _fmt_wrn("pcd dqrr unrecognized frame@fqid: %u,"
+ " frame len: %u (dropped).\n",
+ dq->fqid, dq->fd.length20);
+ dump_frame(fd_virt_addr, fd_len);
+ }
+
+_fmt_pcd_dqrr_return:
+ /* no need to map again here */
+ fmt_fq_release(&dq->fd);
+
+ _fmt_dbgr("calle.\n");
+ return qman_cb_dqrr_consume;
+}
+
+static void fmt_pcd_err_dqrr(
+ struct qman_portal *qm,
+ struct qman_fq *fq,
+ const struct qm_mr_entry *msg)
+{
+ _fmt_err("this callback should never be called.\n");
+ BUG();
+ return;
+}
+
+static void fmt_pcd_fqs_dqrr(
+ struct qman_portal *qm,
+ struct qman_fq *fq,
+ const struct qm_mr_entry *msg)
+{
+ _fmt_dbg(" fq state(0x%x)@fqid(%u.\n", msg->fq.fqs, msg->fq.fqid);
+ return;
+}
+
+/* private pcd queue template */
+static const struct qman_fq pcd_fq = {
+ .cb = { .dqrr = fmt_pcd_dqrr,
+ .ern = fmt_pcd_err_dqrr,
+ .fqs = fmt_pcd_fqs_dqrr}
+};
+
+/* defined as weak in dpaa driver. */
+/* ! parameters come from IOCTL call - US */
+int dpa_alloc_pcd_fqids(
+ struct device *dev,
+ uint32_t num, uint8_t alignment,
+ uint32_t *base_fqid)
+{
+ int _err = 0, i;
+ struct net_device *net_dev = NULL;
+ struct dpa_priv_s *dpa_priv = NULL;
+ struct fmt_port_pcd_s *fmt_port_pcd = NULL;
+ struct fmt_fqs_s *fmt_fqs = NULL;
+ struct fmt_port_s *fmt_port = NULL;
+ int num_allocated = 0;
+
+ _fmt_dbg("calling...\n");
+
+ net_dev = (typeof(net_dev))dev_get_drvdata(dev);
+ dpa_priv = (typeof(dpa_priv))netdev_priv(net_dev);
+
+ if (!netif_msg_probe(dpa_priv)) {
+ _fmt_err("dpa not probe.\n");
+ _err = -ENODEV;
+ goto _pcd_alloc_fqs_err;
+ }
+
+ fmt_port = match_dpa_to_fmt_port(dpa_priv);
+ if (!fmt_port) {
+ _fmt_err("fmt port not found.");
+ _err = -EINVAL;
+ goto _pcd_alloc_fqs_err;
+ }
+
+ fmt_port_pcd = &fmt_port->fmt_port_pcd;
+
+ num_allocated = qman_alloc_fqid_range(base_fqid, num, alignment, 0);
+
+ if ((num_allocated <= 0) ||
+ (num_allocated < num) ||
+ (alignment && (*base_fqid) % alignment)) {
+ *base_fqid = 0;
+ _fmt_err("Failed to alloc pcd fqs rang.\n");
+ _err = -EINVAL;
+ goto _pcd_alloc_fqs_err;
+ }
+
+ _fmt_dbg("wanted %d fqs(align %d), got %d fqids@%u.\n",
+ num, alignment, num_allocated, *base_fqid);
+
+ /* alloc pcd queues */
+ fmt_port_pcd->fmt_pcd_fqs = kmalloc(num_allocated *
+ sizeof(struct fmt_fqs_s),
+ GFP_KERNEL);
+ fmt_port_pcd->num_queues = num_allocated;
+ fmt_port_pcd->fqid_base = *base_fqid;
+ fmt_fqs = fmt_port_pcd->fmt_pcd_fqs;
+
+ /* alloc the pcd queues */
+ for (i = 0; i < num_allocated; i++, fmt_fqs++) {
+ _err = fmt_fq_alloc(
+ fmt_fqs,
+ &pcd_fq,
+ (*base_fqid) + i, QMAN_FQ_FLAG_NO_ENQUEUE,
+ dpa_priv->channel, 7);
+
+ if (_err < 0)
+ goto _pcd_alloc_fqs_err;
+
+ /* upcast to identify from where the frames came from */
+ fmt_fqs->fmt_port_priv = fmt_port;
+ }
+
+ _fmt_dbg("called.\n");
+ return _err;
+_pcd_alloc_fqs_err:
+ if (num_allocated > 0)
+ qman_release_fqid_range(*base_fqid, num_allocated);
+ /*TODO: free fmt_pcd_fqs if are any */
+
+ _fmt_dbg("called(_err:%d).\n", _err);
+ return _err;
+}
+
+/* defined as weak in dpaa driver. */
+int dpa_free_pcd_fqids(
+ struct device *dev,
+ uint32_t base_fqid)
+{
+
+ int _err = 0, i;
+ struct net_device *net_dev = NULL;
+ struct dpa_priv_s *dpa_priv = NULL;
+ struct fmt_port_pcd_s *fmt_port_pcd = NULL;
+ struct fmt_fqs_s *fmt_fqs = NULL;
+ struct fmt_port_s *fmt_port = NULL;
+ int num_allocated = 0;
+
+ _fmt_dbg("calling...\n");
+
+ net_dev = (typeof(net_dev))dev_get_drvdata(dev);
+ dpa_priv = (typeof(dpa_priv))netdev_priv(net_dev);
+
+ if (!netif_msg_probe(dpa_priv)) {
+ _fmt_err("dpa not probe.\n");
+ _err = -ENODEV;
+ goto _pcd_free_fqs_err;
+ }
+
+ fmt_port = match_dpa_to_fmt_port(dpa_priv);
+ if (!fmt_port) {
+ _fmt_err("fmt port not found.");
+ _err = -EINVAL;
+ goto _pcd_free_fqs_err;
+ }
+
+ fmt_port_pcd = &fmt_port->fmt_port_pcd;
+ num_allocated = fmt_port_pcd->num_queues;
+ fmt_fqs = fmt_port_pcd->fmt_pcd_fqs;
+
+ for (i = 0; i < num_allocated; i++, fmt_fqs++)
+ fmt_fq_free(fmt_fqs);
+
+ qman_release_fqid_range(base_fqid,num_allocated);
+
+ kfree(fmt_port_pcd->fmt_pcd_fqs);
+ memset(fmt_port_pcd, 0, sizeof(*fmt_port_pcd));
+
+ /* debugging stuff */
+#if defined(FMT_K_DBG) || defined(FMT_K_DBG_RUNTIME)
+ _fmt_dbg(" portid: %u.\n", fmt_port->id);
+ _fmt_dbg(" frames enqueue to qman: %u.\n",
+ atomic_read(&fmt_port->enqueue_to_qman_frm));
+ _fmt_dbg(" frames enqueue to rxq: %u.\n",
+ atomic_read(&fmt_port->enqueue_to_rxq));
+ _fmt_dbg(" frames dequeue from rxq: %u.\n",
+ atomic_read(&fmt_port->dequeue_from_rxq));
+ _fmt_dbg(" frames not enqueue to rxq - wrong frm: %u.\n",
+ atomic_read(&fmt_port->not_enqueue_to_rxq_wrong_frm));
+ atomic_set(&fmt_port->enqueue_to_qman_frm, 0);
+ atomic_set(&fmt_port->enqueue_to_rxq, 0);
+ atomic_set(&fmt_port->dequeue_from_rxq, 0);
+ atomic_set(&fmt_port->not_enqueue_to_rxq_wrong_frm, 0);
+#endif
+ return 0;
+
+_pcd_free_fqs_err:
+ return _err;
+}
+
+static int fmt_port_init(
+ struct fmt_port_s *fmt_port,
+ ioc_fmt_port_param_t *p_Params)
+{
+ struct device_node *fm_node, *fm_port_node;
+ const uint32_t *uint32_prop;
+ int _errno = 0, lenp = 0, i;
+ static struct of_device_id fm_node_of_match[] = {
+ { .compatible = "fsl,fman", },
+ { /* end of list */ },
+ };
+
+ _fmt_dbg("calling...\n");
+
+ /* init send/receive tu US list */
+ INIT_LIST_HEAD(&fmt_port->rx_q);
+
+ /* check parameters */
+ if (p_Params->num_tx_queues > FMAN_TEST_MAX_TX_FQS ||
+ p_Params->fm_port_id > IOC_FMT_MAX_NUM_OF_PORTS) {
+ _fmt_dbg("wrong test parameters.\n");
+ return -EINVAL;
+ }
+
+ /* set port parameters */
+ fmt_port->num_of_tx_fqs = p_Params->num_tx_queues;
+ fmt_port->id = p_Params->fm_port_id;
+ fmt_port->port_type = p_Params->fm_port_type;
+ fmt_port->diag = e_IOC_DIAG_MODE_NONE;
+
+ /* init debugging stuff */
+#if defined(FMT_K_DBG) || defined(FMT_K_DBG_RUNTIME)
+ atomic_set(&fmt_port->enqueue_to_qman_frm, 0);
+ atomic_set(&fmt_port->enqueue_to_rxq, 0);
+ atomic_set(&fmt_port->dequeue_from_rxq, 0);
+ atomic_set(&fmt_port->not_enqueue_to_rxq_wrong_frm, 0);
+#endif
+
+ /* TODO: This should be done at probe time not at runtime
+ * very ugly function */
+ /* fill fmt port properties from dts */
+ for_each_matching_node(fm_node, fm_node_of_match) {
+
+ uint32_prop = (uint32_t *)of_get_property(fm_node,
+ "cell-index", &lenp);
+ if (unlikely(uint32_prop == NULL)) {
+ _fmt_wrn("of_get_property(%s, cell-index) invalid",
+ fm_node->full_name);
+ return -EINVAL;
+ }
+ if (WARN_ON(lenp != sizeof(uint32_t))) {
+ _fmt_wrn("of_get_property(%s, cell-index) invalid",
+ fm_node->full_name);
+ return -EINVAL;
+ }
+
+ if (*uint32_prop == p_Params->fm_id) {
+ struct resource res;
+
+ /* Get the FM address */
+ _errno = of_address_to_resource(fm_node, 0, &res);
+ if (unlikely(_errno < 0)) {
+ _fmt_wrn("of_address_to_resource() = %u.\n", _errno);
+ return -EINVAL;
+ }
+
+ fmt_port->fm_phys_base_addr = res.start;
+
+ for_each_child_of_node(fm_node, fm_port_node) {
+ struct platform_device *of_dev;
+
+ if (!of_device_is_available(fm_port_node))
+ continue;
+
+ uint32_prop = (uint32_t *)of_get_property(
+ fm_port_node,
+ "cell-index",
+ &lenp);
+ if (uint32_prop == NULL)
+ continue;
+
+ if (of_device_is_compatible(fm_port_node,
+ "fsl,fman-port-oh") &&
+ (fmt_port->port_type == e_IOC_FMT_PORT_T_OP)) {
+
+ if (*uint32_prop == fmt_port->id) {
+ of_dev = of_find_device_by_node(fm_port_node);
+ if (unlikely(of_dev == NULL)) {
+ _fmt_wrn("fm id invalid\n");
+ return -EINVAL;
+ }
+
+ fmt_port->p_tx_port =
+ fm_port_bind(&of_dev->dev);
+ fmt_port->p_tx_fm_port_dev =
+ (void *)fm_port_get_handle(
+ fmt_port->p_tx_port);
+ fmt_port->p_rx_port =
+ fmt_port->p_tx_port;
+ fmt_port->p_rx_fm_port_dev =
+ fmt_port->p_tx_fm_port_dev;
+ fmt_port->p_mac_dev = NULL;
+ break;
+ }
+ } else if ((*uint32_prop == fmt_port->id) &&
+ fmt_port->port_type == e_IOC_FMT_PORT_T_RXTX) {
+
+ of_dev = of_find_device_by_node(fm_port_node);
+ if (unlikely(of_dev == NULL)) {
+ _fmt_wrn("dtb fm id invalid value");
+ return -EINVAL;
+ }
+
+ if (of_device_is_compatible(fm_port_node,
+ "fsl,fman-port-1g-tx")) {
+ fmt_port->p_tx_port =
+ fm_port_bind(&of_dev->dev);
+ fmt_port->p_tx_fm_port_dev = (void *)
+ fm_port_get_handle(
+ fmt_port->p_tx_port);
+ } else if (of_device_is_compatible(fm_port_node,
+ "fsl,fman-port-1g-rx")) {
+ fmt_port->p_rx_port =
+ fm_port_bind(&of_dev->dev);
+ fmt_port->p_rx_fm_port_dev = (void *)
+ fm_port_get_handle(
+ fmt_port->p_rx_port);
+ } else if (of_device_is_compatible(fm_port_node,
+ "fsl,fman-1g-mac") ||
+ of_device_is_compatible(fm_port_node,
+ "fsl,fman-memac"))
+ fmt_port->p_mac_dev =
+ (typeof(fmt_port->p_mac_dev))
+ dev_get_drvdata(&of_dev->dev);
+ else
+ continue;
+
+ if (fmt_port->p_tx_fm_port_dev &&
+ fmt_port->p_rx_fm_port_dev && fmt_port->p_mac_dev)
+ break;
+ } else if (((*uint32_prop + FM_MAX_NUM_OF_1G_RX_PORTS) ==
+ fmt_port->id) &&
+ fmt_port->port_type == e_IOC_FMT_PORT_T_RXTX) {
+
+ of_dev = of_find_device_by_node(fm_port_node);
+ if (unlikely(of_dev == NULL)) {
+ _fmt_wrn("dtb fm id invalid value\n");
+ return -EINVAL;
+ }
+
+ if (of_device_is_compatible(fm_port_node,
+ "fsl,fman-port-10g-tx")) {
+ fmt_port->p_tx_port =
+ fm_port_bind(&of_dev->dev);
+ fmt_port->p_tx_fm_port_dev = (void *)
+ fm_port_get_handle(
+ fmt_port->p_tx_port);
+ } else if (of_device_is_compatible(fm_port_node,
+ "fsl,fman-port-10g-rx")) {
+ fmt_port->p_rx_port =
+ fm_port_bind(&of_dev->dev);
+ fmt_port->p_rx_fm_port_dev = (void *)
+ fm_port_get_handle(
+ fmt_port->p_rx_port);
+ } else if (of_device_is_compatible(fm_port_node,
+ "fsl,fman-10g-mac") ||
+ of_device_is_compatible(fm_port_node,
+ "fsl,fman-memac"))
+ fmt_port->p_mac_dev =
+ (typeof(fmt_port->p_mac_dev))
+ dev_get_drvdata(&of_dev->dev);
+ else
+ continue;
+
+ if (fmt_port->p_tx_fm_port_dev &&
+ fmt_port->p_rx_fm_port_dev && fmt_port->p_mac_dev)
+ break;
+ }
+ } /* for_each_child */
+ }
+ } /* for each matching node */
+
+ if (fmt_port->p_tx_fm_port_dev == 0 ||
+ fmt_port->p_rx_fm_port_dev == 0) {
+
+ _fmt_err("bad fm port pointers.\n");
+ return -EINVAL;
+ }
+
+ _fmt_dbg("alloc %u tx queues.\n", fmt_port->num_of_tx_fqs);
+
+ /* init fman test egress dynamic frame queues */
+ for (i = 0; i < fmt_port->num_of_tx_fqs; i++) {
+ int _errno;
+ _errno = fmt_fq_alloc(
+ &fmt_port->p_tx_fqs[i],
+ &fmt_egress_fq,
+ 0,
+ QMAN_FQ_FLAG_TO_DCPORTAL,
+ fm_get_tx_port_channel(fmt_port->p_tx_port),
+ i);
+
+ if (_errno < 0) {
+ _fmt_err("tx queues allocation failed.\n");
+ /* TODO: memory leak here if 1 queue is allocated and
+ * next queues are failing ... */
+ return -EINVAL;
+ }
+ }
+
+ /* port is valid and ready to use. */
+ fmt_port->valid = TRUE;
+
+ _fmt_dbg("called.\n");
+ return 0;
+}
+
+/* fm test chardev functions */
+static int fmt_open(struct inode *inode, struct file *file)
+{
+ unsigned int minor = iminor(inode);
+
+ _fmt_dbg("calling...\n");
+
+ if (file->private_data != NULL)
+ return 0;
+
+ /* The minor represent the port number.
+ * Set the port structure accordingly, thus all the operations
+ * will be done on this port. */
+ if ((minor >= DEV_FM_TEST_PORTS_MINOR_BASE) &&
+ (minor < DEV_FM_TEST_MAX_MINORS))
+ file->private_data = &fm_test.ports[minor];
+ else
+ return -ENXIO;
+
+ _fmt_dbg("called.\n");
+ return 0;
+}
+
+static int fmt_close(struct inode *inode, struct file *file)
+{
+ struct fmt_port_s *fmt_port = NULL;
+ struct fmt_frame_s *fmt_frame = NULL;
+
+ int err = 0;
+
+ _fmt_dbg("calling...\n");
+
+ fmt_port = file->private_data;
+ if (!fmt_port)
+ return -ENODEV;
+
+ /* Close the current test port by invalidating it. */
+ fmt_port->valid = FALSE;
+
+ /* clean the fmt port queue */
+ while ((fmt_frame = dequeue_fmt_frame(fmt_port)) != NULL) {
+ if (fmt_frame && fmt_frame->buff.p_data){
+ kfree(fmt_frame->buff.p_data);
+ kfree(fmt_frame);
+ }
+ }
+
+ /* !!! the qman queues are cleaning from fm_ioctl...
+ * - very ugly */
+
+ _fmt_dbg("called.\n");
+ return err;
+}
+
+static int fmt_ioctls(unsigned int minor,
+ struct file *file,
+ unsigned int cmd,
+ unsigned long arg,
+ bool compat)
+{
+ struct fmt_port_s *fmt_port = NULL;
+
+ _fmt_dbg("IOCTL minor:%u "
+ " arg:0x%08lx ioctl cmd (0x%08x):(0x%02x:0x%02x.\n",
+ minor, arg, cmd, _IOC_TYPE(cmd), _IOC_NR(cmd));
+
+ fmt_port = file->private_data;
+ if (!fmt_port) {
+ _fmt_err("invalid fmt port.\n");
+ return -ENODEV;
+ }
+
+ /* set test type properly */
+ if (compat)
+ fmt_port->compat_test_type = true;
+ else
+ fmt_port->compat_test_type = false;
+
+ switch (cmd) {
+ case FMT_PORT_IOC_INIT:
+ {
+ ioc_fmt_port_param_t param;
+
+ if (fmt_port->valid) {
+ _fmt_wrn("port is already initialized.\n");
+ return -EFAULT;
+ }
+#if defined(CONFIG_COMPAT)
+ if (compat) {
+ if (copy_from_user(&param,
+ (ioc_fmt_port_param_t *)compat_ptr(arg),
+ sizeof(ioc_fmt_port_param_t)))
+
+ return -EFAULT;
+ } else
+#endif
+ {
+ if (copy_from_user(&param,
+ (ioc_fmt_port_param_t *) arg,
+ sizeof(ioc_fmt_port_param_t)))
+
+ return -EFAULT;
+ }
+
+ return fmt_port_init(fmt_port, &param);
+ }
+
+ case FMT_PORT_IOC_SET_DIAG_MODE:
+ if (get_user(fmt_port->diag, (ioc_diag_mode *)arg))
+ return -EFAULT;
+
+ if (fmt_port->diag == e_IOC_DIAG_MODE_CTRL_LOOPBACK)
+ return set_mac_int_loopback(fmt_port, TRUE);
+ else
+ return set_mac_int_loopback(fmt_port, FALSE);
+ break;
+
+ case FMT_PORT_IOC_SET_DPAECHO_MODE:
+ case FMT_PORT_IOC_SET_IP_HEADER_MANIP:
+ default:
+ _fmt_wrn("ioctl unimplemented minor:%u@ioctl"
+ " cmd:0x%08x(type:0x%02x, nr:0x%02x.\n",
+ minor, cmd, _IOC_TYPE(cmd), _IOC_NR(cmd));
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
+#ifdef CONFIG_COMPAT
+static long fmt_compat_ioctl(
+ struct file *file,
+ unsigned int cmd,
+ unsigned long arg)
+{
+ unsigned int minor = iminor(file->f_path.dentry->d_inode);
+
+ _fmt_dbg("calling...\n");
+ return fmt_ioctls(minor, file, cmd, arg, true);
+}
+#endif
+
+static long fmt_ioctl(
+ struct file *file,
+ unsigned int cmd,
+ unsigned long arg)
+{
+ unsigned int minor = iminor(file->f_path.dentry->d_inode);
+ unsigned int res;
+
+ _fmt_dbg("calling...\n");
+
+ fm_mutex_lock();
+ res = fmt_ioctls(minor, file, cmd, arg, false);
+ fm_mutex_unlock();
+
+ _fmt_dbg("called.\n");
+
+ return res;
+}
+
+#ifdef CONFIG_COMPAT
+void copy_compat_test_frame_buffer(
+ ioc_fmt_buff_desc_t *buff,
+ ioc_fmt_compat_buff_desc_t *compat_buff)
+{
+ compat_buff->qid = buff->qid;
+ compat_buff->p_data = ptr_to_compat(buff->p_data);
+ compat_buff->size = buff->size;
+ compat_buff->status = buff->status;
+
+ compat_buff->buff_context.p_user_priv =
+ ptr_to_compat(buff->buff_context.p_user_priv);
+ memcpy(compat_buff->buff_context.fm_prs_res,
+ buff->buff_context.fm_prs_res,
+ FM_PRS_MAX * sizeof(uint8_t));
+ memcpy(compat_buff->buff_context.fm_time_stamp,
+ buff->buff_context.fm_time_stamp,
+ FM_TIME_STAMP_MAX * sizeof(uint8_t));
+}
+#endif
+
+ssize_t fmt_read(
+ struct file *file,
+ char __user *buf,
+ size_t size,
+ loff_t *ppos)
+{
+ struct fmt_port_s *fmt_port = NULL;
+ struct fmt_frame_s *p_fmt_frame = NULL;
+ ssize_t cnt = 0;
+
+ fmt_port = file->private_data;
+ if (!fmt_port || !fmt_port->valid) {
+ _fmt_err("fmt port not valid!\n");
+ return -ENODEV;
+ }
+
+ p_fmt_frame = dequeue_fmt_frame(fmt_port);
+ if (p_fmt_frame == NULL)
+ return 0;
+
+ _fmt_dbgr("calling...\n");
+
+#ifdef CONFIG_COMPAT
+ if (fmt_port->compat_test_type){
+ cnt = sizeof(ioc_fmt_compat_buff_desc_t);
+ }
+ else
+#endif
+ {
+ cnt = sizeof(ioc_fmt_buff_desc_t);
+ }
+
+ if (size < cnt) {
+ _fmt_err("illegal buffer-size!\n");
+ cnt = 0;
+ goto _fmt_read_return;
+ }
+
+ /* Copy structure */
+#ifdef CONFIG_COMPAT
+ if (fmt_port->compat_test_type) {
+ {
+ ioc_fmt_compat_buff_desc_t compat_buff;
+ copy_compat_test_frame_buffer(&p_fmt_frame->buff,
+ &compat_buff);
+
+ if (copy_to_user(buf, &compat_buff, cnt)) {
+ _fmt_err("copy_to_user failed!\n");
+ goto _fmt_read_return;
+ }
+ }
+
+ ((ioc_fmt_compat_buff_desc_t *)buf)->p_data =
+ ptr_to_compat(buf+sizeof(ioc_fmt_compat_buff_desc_t));
+ cnt += MIN(p_fmt_frame->buff.size, size-cnt);
+ } else
+#endif
+ {
+ if (copy_to_user(buf, &p_fmt_frame->buff, cnt)) {
+ _fmt_err("copy_to_user failed!\n");
+ goto _fmt_read_return;
+ }
+
+ ((ioc_fmt_buff_desc_t *)buf)->p_data =
+ buf + sizeof(ioc_fmt_buff_desc_t);
+ cnt += MIN(p_fmt_frame->buff.size, size-cnt);
+ }
+
+ if (size < cnt) {
+ _fmt_err("illegal buffer-size!\n");
+ goto _fmt_read_return;
+ }
+
+ /* copy frame */
+#ifdef CONFIG_COMPAT
+ if (fmt_port->compat_test_type) {
+ if (copy_to_user(buf+sizeof(ioc_fmt_compat_buff_desc_t),
+ p_fmt_frame->buff.p_data, cnt)) {
+ _fmt_err("copy_to_user failed!\n");
+ goto _fmt_read_return;
+ }
+ } else
+#endif
+ {
+ if (copy_to_user(buf+sizeof(ioc_fmt_buff_desc_t),
+ p_fmt_frame->buff.p_data, cnt)) {
+ _fmt_err("copy_to_user failed!\n");
+ goto _fmt_read_return;
+ }
+ }
+
+_fmt_read_return:
+ kfree(p_fmt_frame->buff.p_data);
+ kfree(p_fmt_frame);
+
+ _fmt_dbgr("called.\n");
+ return cnt;
+}
+
+ssize_t fmt_write(
+ struct file *file,
+ const char __user *buf,
+ size_t size,
+ loff_t *ppos)
+{
+ struct fmt_port_s *fmt_port = NULL;
+ ioc_fmt_buff_desc_t buff_desc;
+#ifdef CONFIG_COMPAT
+ ioc_fmt_compat_buff_desc_t buff_desc_compat;
+#endif
+ uint8_t *p_data = NULL;
+ uint32_t data_offset;
+ int _errno;
+ t_DpaaFD fd;
+
+ _fmt_dbgr("calling...\n");
+
+ fmt_port = file->private_data;
+ if (!fmt_port || !fmt_port->valid) {
+ _fmt_err("fmt port not valid.\n");
+ return -EINVAL;
+ }
+
+ /* If Compat (32B UserSpace - 64B KernelSpace) */
+#ifdef CONFIG_COMPAT
+ if (fmt_port->compat_test_type) {
+ if (size < sizeof(ioc_fmt_compat_buff_desc_t)) {
+ _fmt_err("invalid buff_desc size.\n");
+ return -EFAULT;
+ }
+
+ if (copy_from_user(&buff_desc_compat, buf,
+ sizeof(ioc_fmt_compat_buff_desc_t)))
+ return -EFAULT;
+
+ buff_desc.qid = buff_desc_compat.qid;
+ buff_desc.p_data = compat_ptr(buff_desc_compat.p_data);
+ buff_desc.size = buff_desc_compat.size;
+ buff_desc.status = buff_desc_compat.status;
+
+ buff_desc.buff_context.p_user_priv =
+ compat_ptr(buff_desc_compat.buff_context.p_user_priv);
+ memcpy(buff_desc.buff_context.fm_prs_res,
+ buff_desc_compat.buff_context.fm_prs_res,
+ FM_PRS_MAX * sizeof(uint8_t));
+ memcpy(buff_desc.buff_context.fm_time_stamp,
+ buff_desc_compat.buff_context.fm_time_stamp,
+ FM_TIME_STAMP_MAX * sizeof(uint8_t));
+ } else
+#endif
+ {
+ if (size < sizeof(ioc_fmt_buff_desc_t)) {
+ _fmt_err("invalid buff_desc size.\n");
+ return -EFAULT;
+ }
+
+ if (copy_from_user(&buff_desc, (ioc_fmt_buff_desc_t *)buf,
+ sizeof(ioc_fmt_buff_desc_t)))
+ return -EFAULT;
+ }
+
+ data_offset = FM_PORT_GetBufferDataOffset(fmt_port->p_tx_fm_port_dev);
+ p_data = kmalloc(buff_desc.size+data_offset, GFP_KERNEL);
+ if (!p_data)
+ return -ENOMEM;
+
+ /* If Compat (32UserSpace - 64KernelSpace) the buff_desc.p_data is ok */
+ if (copy_from_user((uint8_t *)PTR_MOVE(p_data, data_offset),
+ buff_desc.p_data,
+ buff_desc.size)) {
+ kfree(p_data);
+ return -EFAULT;
+ }
+
+ /* TODO: dma_map_single here (cannnot access the bpool struct) */
+
+ /* prepare fd */
+ memset(&fd, 0, sizeof(fd));
+ DPAA_FD_SET_ADDR(&fd, p_data);
+ DPAA_FD_SET_OFFSET(&fd, data_offset);
+ DPAA_FD_SET_LENGTH(&fd, buff_desc.size);
+
+ _errno = qman_enqueue(&fmt_port->p_tx_fqs[buff_desc.qid].fq_base,
+ (struct qm_fd *)&fd, 0);
+ if (_errno) {
+ buff_desc.status = (uint32_t)_errno;
+ if (copy_to_user((ioc_fmt_buff_desc_t *)buf, &buff_desc,
+ sizeof(ioc_fmt_buff_desc_t))) {
+ kfree(p_data);
+ return -EFAULT;
+ }
+ }
+
+ /* for debugging */
+#if defined(FMT_K_DBG) || defined(FMT_K_DBG_RUNTIME)
+ atomic_inc(&fmt_port->enqueue_to_qman_frm);
+#endif
+ _fmt_dbgr("called.\n");
+ return buff_desc.size;
+}
+
+/* fm test character device definition */
+static const struct file_operations fmt_fops =
+{
+ .owner = THIS_MODULE,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = fmt_compat_ioctl,
+#endif
+ .unlocked_ioctl = fmt_ioctl,
+ .open = fmt_open,
+ .release = fmt_close,
+ .read = fmt_read,
+ .write = fmt_write,
+};
+
+static int fmt_init(void)
+{
+ int id;
+
+ _fmt_dbg("calling...\n");
+
+ /* Register to the /dev for IOCTL API */
+ /* Register dynamically a new major number for the character device: */
+ fm_test.major = register_chrdev(0, DEV_FM_TEST_NAME, &fmt_fops);
+ if (fm_test.major <= 0) {
+ _fmt_wrn("Failed to allocate major number for device %s.\n",
+ DEV_FM_TEST_NAME);
+ return -ENODEV;
+ }
+
+ /* Creating class for FMan_test */
+ fm_test.fmt_class = class_create(THIS_MODULE, DEV_FM_TEST_NAME);
+ if (IS_ERR(fm_test.fmt_class)) {
+ unregister_chrdev(fm_test.major, DEV_FM_TEST_NAME);
+ _fmt_wrn("Error creating %s class.\n", DEV_FM_TEST_NAME);
+ return -ENODEV;
+ }
+
+ for (id = 0; id < IOC_FMT_MAX_NUM_OF_PORTS; id++)
+ if (NULL == device_create(fm_test.fmt_class, NULL,
+ MKDEV(fm_test.major,
+ DEV_FM_TEST_PORTS_MINOR_BASE + id), NULL,
+ DEV_FM_TEST_NAME "%d", id)) {
+
+ _fmt_err("Error creating %s device.\n",
+ DEV_FM_TEST_NAME);
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+static void fmt_free(void)
+{
+ int id;
+
+ for (id = 0; id < IOC_FMT_MAX_NUM_OF_PORTS; id++)
+ device_destroy(fm_test.fmt_class, MKDEV(fm_test.major,
+ DEV_FM_TEST_PORTS_MINOR_BASE + id));
+ class_destroy(fm_test.fmt_class);
+}
+
+static int __init __cold fmt_load(void)
+{
+ struct dpaa_eth_hooks_s priv_dpaa_eth_hooks;
+
+ /* set dpaa hooks for default queues */
+ memset(&priv_dpaa_eth_hooks, 0, sizeof(priv_dpaa_eth_hooks));
+ priv_dpaa_eth_hooks.rx_default = fmt_rx_default_hook;
+ priv_dpaa_eth_hooks.rx_error = fmt_rx_error_hook;
+ priv_dpaa_eth_hooks.tx_confirm = fmt_tx_confirm_hook;
+ priv_dpaa_eth_hooks.tx_error = fmt_tx_confirm_error_hook;
+
+ fsl_dpaa_eth_set_hooks(&priv_dpaa_eth_hooks);
+
+ /* initialize the fman test environment */
+ if (fmt_init() < 0) {
+ _fmt_err("Failed to init FM-test modul.\n");
+ fmt_free();
+ return -ENODEV;
+ }
+
+ _fmt_inf("FSL FM test module loaded.\n");
+
+ return 0;
+}
+
+static void __exit __cold fmt_unload(void)
+{
+ fmt_free();
+ _fmt_inf("FSL FM test module unloaded.\n");
+}
+
+module_init(fmt_load);
+module_exit(fmt_unload);
diff --git a/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_fm.c b/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_fm.c
new file mode 100644
index 0000000..b20f3a5
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_fm.c
@@ -0,0 +1,1308 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * 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 Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * 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 Freescale Semiconductor ``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 Freescale Semiconductor 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.
+ */
+
+/*
+ @File lnxwrp_fm.c
+ @Author Shlomi Gridish
+ @Description FM Linux wrapper functions.
+*/
+
+#include <linux/version.h>
+#include <linux/slab.h>
+#if defined(CONFIG_MODVERSIONS) && !defined(MODVERSIONS)
+#define MODVERSIONS
+#endif
+#ifdef MODVERSIONS
+#include <config/modversions.h>
+#endif /* MODVERSIONS */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/cdev.h>
+#include <linux/device.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/of_platform.h>
+#include <asm/uaccess.h>
+#include <asm/errno.h>
+#include <asm/qe.h> /* For struct qe_firmware */
+#include <sysdev/fsl_soc.h>
+#include <linux/stat.h> /* For file access mask */
+#include <linux/skbuff.h>
+
+/* NetCommSw Headers --------------- */
+#include "std_ext.h"
+#include "error_ext.h"
+#include "sprint_ext.h"
+#include "debug_ext.h"
+#include "sys_io_ext.h"
+
+#include "fm_ioctls.h"
+
+#include "lnxwrp_fm.h"
+#include "lnxwrp_resources.h"
+#include "lnxwrp_sysfs_fm.h"
+#include "lnxwrp_sysfs_fm_port.h"
+
+/* export LLD API to DPAA offload kernel module */
+#if defined(CONFIG_FSL_DPA_OFFLOAD_MODULE)
+#include "lnxwrp_exp_sym.h"
+#endif
+
+extern struct device_node *GetFmPortAdvArgsDevTreeNode (struct device_node *fm_node,
+ e_FmPortType portType,
+ uint8_t portId);
+
+#define PROC_PRINT(args...) offset += sprintf(buf+offset,args)
+
+#define ADD_ADV_CONFIG_NO_RET(_func, _param) \
+ do { \
+ if (i<max){ \
+ p_Entry = &p_Entrys[i]; \
+ p_Entry->p_Function = _func; \
+ _param \
+ i++; \
+ } \
+ else \
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE,\
+ ("Number of advanced-configuration entries exceeded"));\
+ } while (0)
+
+/* Bootarg used to override the Kconfig FSL_FM_MAX_FRAME_SIZE value */
+#define FSL_FM_MAX_FRM_BOOTARG "fsl_fm_max_frm"
+
+/* Bootarg used to override FSL_FM_RX_EXTRA_HEADROOM Kconfig value */
+#define FSL_FM_RX_EXTRA_HEADROOM_BOOTARG "fsl_fm_rx_extra_headroom"
+
+/* Maximum value for the fsl_fm_rx_extra_headroom bootarg */
+#define FSL_FM_RX_EXTRA_HEADROOM_MAX 384
+
+/*
+ * Max frame size, across all interfaces.
+ * Configurable from Kconfig or bootargs, to avoid allocating
+ * oversized (socket) buffers when not using jumbo frames.
+ * Must be large enough to accomodate the network MTU, but small enough
+ * to avoid wasting skb memory.
+ *
+ * Could be overridden once, at boot-time, via the
+ * fm_set_max_frm() callback.
+ */
+int fsl_fm_max_frm = CONFIG_FSL_FM_MAX_FRAME_SIZE;
+
+/*
+ * Extra headroom for Rx buffers.
+ * FMan is instructed to allocate, on the Rx path, this amount of
+ * space at the beginning of a data buffer, beside the DPA private
+ * data area and the IC fields.
+ * Does not impact Tx buffer layout.
+ *
+ * Configurable from Kconfig or bootargs. Zero by default, it's needed
+ * on particular forwarding scenarios that add extra headers to the
+ * forwarded frame.
+ */
+int fsl_fm_rx_extra_headroom = CONFIG_FSL_FM_RX_EXTRA_HEADROOM;
+
+static t_LnxWrpFm lnxWrpFm;
+
+int fm_get_max_frm()
+{
+ return fsl_fm_max_frm;
+}
+
+int fm_get_rx_extra_headroom()
+{
+ return fsl_fm_rx_extra_headroom;
+}
+
+static int __init fm_set_max_frm(char *str)
+{
+ int ret = 0;
+
+ ret = get_option(&str, &fsl_fm_max_frm);
+ if (ret != 1) {
+ /*
+ * This will only work if CONFIG_EARLY_PRINTK is compiled in,
+ * and something like "earlyprintk=serial,uart0,115200" is
+ * specified in the bootargs
+ */
+ printk(KERN_WARNING "No suitable %s=<int> prop in bootargs; "
+ "will use the default FSL_FM_MAX_FRAME_SIZE (%d) "
+ "from Kconfig.\n", FSL_FM_MAX_FRM_BOOTARG,
+ CONFIG_FSL_FM_MAX_FRAME_SIZE);
+
+ fsl_fm_max_frm = CONFIG_FSL_FM_MAX_FRAME_SIZE;
+ return 1;
+ }
+
+ /* Don't allow invalid bootargs; fallback to the Kconfig value */
+ if (fsl_fm_max_frm < 64 || fsl_fm_max_frm > 9600) {
+ printk(KERN_WARNING "Invalid %s=%d in bootargs, valid range is "
+ "64-9600. Falling back to the FSL_FM_MAX_FRAME_SIZE (%d) "
+ "from Kconfig.\n",
+ FSL_FM_MAX_FRM_BOOTARG, fsl_fm_max_frm,
+ CONFIG_FSL_FM_MAX_FRAME_SIZE);
+
+ fsl_fm_max_frm = CONFIG_FSL_FM_MAX_FRAME_SIZE;
+ return 1;
+ }
+
+ printk(KERN_INFO "Using fsl_fm_max_frm=%d from bootargs\n",
+ fsl_fm_max_frm);
+ return 0;
+}
+early_param(FSL_FM_MAX_FRM_BOOTARG, fm_set_max_frm);
+
+static int __init fm_set_rx_extra_headroom(char *str)
+{
+ int ret;
+
+ ret = get_option(&str, &fsl_fm_rx_extra_headroom);
+
+ if (ret != 1) {
+ printk(KERN_WARNING "No suitable %s=<int> prop in bootargs; "
+ "will use the default FSL_FM_RX_EXTRA_HEADROOM (%d) "
+ "from Kconfig.\n", FSL_FM_RX_EXTRA_HEADROOM_BOOTARG,
+ CONFIG_FSL_FM_RX_EXTRA_HEADROOM);
+ fsl_fm_rx_extra_headroom = CONFIG_FSL_FM_RX_EXTRA_HEADROOM;
+
+ return 1;
+ }
+
+ if (fsl_fm_rx_extra_headroom < 0 ||
+ fsl_fm_rx_extra_headroom > FSL_FM_RX_EXTRA_HEADROOM_MAX) {
+ printk(KERN_WARNING "Invalid value for %s=<int> prop in "
+ "bootargs; will use the default "
+ "FSL_FM_RX_EXTRA_HEADROOM (%d) from Kconfig.\n",
+ FSL_FM_RX_EXTRA_HEADROOM_BOOTARG,
+ CONFIG_FSL_FM_RX_EXTRA_HEADROOM);
+ fsl_fm_rx_extra_headroom = CONFIG_FSL_FM_RX_EXTRA_HEADROOM;
+ }
+
+ printk(KERN_INFO "Using fsl_fm_rx_extra_headroom=%d from bootargs\n",
+ fsl_fm_rx_extra_headroom);
+
+ return 0;
+}
+early_param(FSL_FM_RX_EXTRA_HEADROOM_BOOTARG, fm_set_rx_extra_headroom);
+
+static irqreturn_t fm_irq(int irq, void *_dev)
+{
+ t_LnxWrpFmDev *p_LnxWrpFmDev = (t_LnxWrpFmDev *)_dev;
+
+ if (!p_LnxWrpFmDev || !p_LnxWrpFmDev->h_Dev)
+ return IRQ_NONE;
+
+ FM_EventIsr(p_LnxWrpFmDev->h_Dev);
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t fm_err_irq(int irq, void *_dev)
+{
+ t_LnxWrpFmDev *p_LnxWrpFmDev = (t_LnxWrpFmDev *)_dev;
+
+ if (!p_LnxWrpFmDev || !p_LnxWrpFmDev->h_Dev)
+ return IRQ_NONE;
+
+ if (FM_ErrorIsr(p_LnxWrpFmDev->h_Dev) == E_OK)
+ return IRQ_HANDLED;
+
+ return IRQ_NONE;
+}
+
+/* used to protect FMD/LLD from concurrent calls in functions fm_mutex_lock / fm_mutex_unlock */
+static struct mutex lnxwrp_mutex;
+
+static t_LnxWrpFmDev * CreateFmDev(uint8_t id)
+{
+ t_LnxWrpFmDev *p_LnxWrpFmDev;
+ int j;
+
+ p_LnxWrpFmDev = (t_LnxWrpFmDev *)XX_Malloc(sizeof(t_LnxWrpFmDev));
+ if (!p_LnxWrpFmDev)
+ {
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, NO_MSG);
+ return NULL;
+ }
+
+ memset(p_LnxWrpFmDev, 0, sizeof(t_LnxWrpFmDev));
+ p_LnxWrpFmDev->fmDevSettings.advConfig = (t_SysObjectAdvConfigEntry*)XX_Malloc(FM_MAX_NUM_OF_ADV_SETTINGS*sizeof(t_SysObjectAdvConfigEntry));
+ memset(p_LnxWrpFmDev->fmDevSettings.advConfig, 0, (FM_MAX_NUM_OF_ADV_SETTINGS*sizeof(t_SysObjectAdvConfigEntry)));
+ p_LnxWrpFmDev->fmPcdDevSettings.advConfig = (t_SysObjectAdvConfigEntry*)XX_Malloc(FM_MAX_NUM_OF_ADV_SETTINGS*sizeof(t_SysObjectAdvConfigEntry));
+ memset(p_LnxWrpFmDev->fmPcdDevSettings.advConfig, 0, (FM_MAX_NUM_OF_ADV_SETTINGS*sizeof(t_SysObjectAdvConfigEntry)));
+ p_LnxWrpFmDev->hcPort.settings.advConfig = (t_SysObjectAdvConfigEntry*)XX_Malloc(FM_MAX_NUM_OF_ADV_SETTINGS*sizeof(t_SysObjectAdvConfigEntry));
+ memset(p_LnxWrpFmDev->hcPort.settings.advConfig, 0, (FM_MAX_NUM_OF_ADV_SETTINGS*sizeof(t_SysObjectAdvConfigEntry)));
+ for (j=0; j<FM_MAX_NUM_OF_RX_PORTS; j++)
+ {
+ p_LnxWrpFmDev->rxPorts[j].settings.advConfig = (t_SysObjectAdvConfigEntry*)XX_Malloc(FM_MAX_NUM_OF_ADV_SETTINGS*sizeof(t_SysObjectAdvConfigEntry));
+ memset(p_LnxWrpFmDev->rxPorts[j].settings.advConfig, 0, (FM_MAX_NUM_OF_ADV_SETTINGS*sizeof(t_SysObjectAdvConfigEntry)));
+ }
+ for (j=0; j<FM_MAX_NUM_OF_TX_PORTS; j++)
+ {
+ p_LnxWrpFmDev->txPorts[j].settings.advConfig = (t_SysObjectAdvConfigEntry*)XX_Malloc(FM_MAX_NUM_OF_ADV_SETTINGS*sizeof(t_SysObjectAdvConfigEntry));
+ memset(p_LnxWrpFmDev->txPorts[j].settings.advConfig, 0, (FM_MAX_NUM_OF_ADV_SETTINGS*sizeof(t_SysObjectAdvConfigEntry)));
+ }
+ for (j=0; j<FM_MAX_NUM_OF_OH_PORTS-1; j++)
+ {
+ p_LnxWrpFmDev->opPorts[j].settings.advConfig = (t_SysObjectAdvConfigEntry*)XX_Malloc(FM_MAX_NUM_OF_ADV_SETTINGS*sizeof(t_SysObjectAdvConfigEntry));
+ memset(p_LnxWrpFmDev->opPorts[j].settings.advConfig, 0, (FM_MAX_NUM_OF_ADV_SETTINGS*sizeof(t_SysObjectAdvConfigEntry)));
+ }
+
+ return p_LnxWrpFmDev;
+}
+
+static void DestroyFmDev(t_LnxWrpFmDev *p_LnxWrpFmDev)
+{
+ int j;
+
+ for (j=0; j<FM_MAX_NUM_OF_OH_PORTS-1; j++)
+ if (p_LnxWrpFmDev->opPorts[j].settings.advConfig)
+ XX_Free(p_LnxWrpFmDev->opPorts[j].settings.advConfig);
+ for (j=0; j<FM_MAX_NUM_OF_TX_PORTS; j++)
+ if (p_LnxWrpFmDev->txPorts[j].settings.advConfig)
+ XX_Free(p_LnxWrpFmDev->txPorts[j].settings.advConfig);
+ for (j=0; j<FM_MAX_NUM_OF_RX_PORTS; j++)
+ if (p_LnxWrpFmDev->rxPorts[j].settings.advConfig)
+ XX_Free(p_LnxWrpFmDev->rxPorts[j].settings.advConfig);
+ if (p_LnxWrpFmDev->hcPort.settings.advConfig)
+ XX_Free(p_LnxWrpFmDev->hcPort.settings.advConfig);
+ if (p_LnxWrpFmDev->fmPcdDevSettings.advConfig)
+ XX_Free(p_LnxWrpFmDev->fmPcdDevSettings.advConfig);
+ if (p_LnxWrpFmDev->fmDevSettings.advConfig)
+ XX_Free(p_LnxWrpFmDev->fmDevSettings.advConfig);
+
+ XX_Free(p_LnxWrpFmDev);
+}
+
+static t_Error FillRestFmInfo(t_LnxWrpFmDev *p_LnxWrpFmDev)
+{
+#define FM_BMI_PPIDS_OFFSET 0x00080304
+#define FM_DMA_PLR_OFFSET 0x000c2060
+#define FM_FPM_IP_REV_1_OFFSET 0x000c30c4
+#define DMA_HIGH_LIODN_MASK 0x0FFF0000
+#define DMA_LOW_LIODN_MASK 0x00000FFF
+#define DMA_LIODN_SHIFT 16
+
+typedef _Packed struct {
+ uint32_t plr[32];
+} _PackedType t_Plr;
+
+typedef _Packed struct {
+ volatile uint32_t fmbm_ppid[63];
+} _PackedType t_Ppids;
+
+ t_Plr *p_Plr;
+ t_Ppids *p_Ppids;
+ int i,j;
+ uint32_t fmRev;
+
+ static const uint8_t phys1GRxPortId[] = {0x8,0x9,0xa,0xb,0xc,0xd,0xe,0xf};
+ static const uint8_t phys10GRxPortId[] = {0x10,0x11};
+ static const uint8_t physOhPortId[] = {0x1,0x2,0x3,0x4,0x5,0x6,0x7};
+ static const uint8_t phys1GTxPortId[] = {0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f};
+ static const uint8_t phys10GTxPortId[] = {0x30,0x31};
+
+ fmRev = (uint32_t)(*((volatile uint32_t *)UINT_TO_PTR(p_LnxWrpFmDev->fmBaseAddr+FM_FPM_IP_REV_1_OFFSET)));
+ fmRev &= 0xffff;
+
+ p_Plr = (t_Plr *)UINT_TO_PTR(p_LnxWrpFmDev->fmBaseAddr+FM_DMA_PLR_OFFSET);
+#ifdef MODULE
+ for (i=0;i<FM_MAX_NUM_OF_PARTITIONS/2;i++)
+ p_Plr->plr[i] = 0;
+#endif /* MODULE */
+
+ for (i=0; i<FM_MAX_NUM_OF_PARTITIONS; i++)
+ {
+ uint16_t liodnBase = (uint16_t)((i%2) ?
+ (p_Plr->plr[i/2] & DMA_LOW_LIODN_MASK) :
+ ((p_Plr->plr[i/2] & DMA_HIGH_LIODN_MASK) >> DMA_LIODN_SHIFT));
+#ifdef FM_PARTITION_ARRAY
+ /* TODO: this was .liodnPerPartition[i] = liodnBase; is the index meaning the same? */
+ p_LnxWrpFmDev->fmDevSettings.param.liodnBasePerPort[i] = liodnBase;
+#endif /* FM_PARTITION_ARRAY */
+
+ if ((i >= phys1GRxPortId[0]) &&
+ (i <= phys1GRxPortId[FM_MAX_NUM_OF_1G_RX_PORTS-1]))
+ {
+ for (j=0; j<ARRAY_SIZE(phys1GRxPortId); j++)
+ if (phys1GRxPortId[j] == i)
+ break;
+ ASSERT_COND(j<ARRAY_SIZE(phys1GRxPortId));
+ p_LnxWrpFmDev->rxPorts[j].settings.param.liodnBase = liodnBase;
+ }
+ else if (FM_MAX_NUM_OF_10G_RX_PORTS &&
+ (i >= phys10GRxPortId[0]) &&
+ (i <= phys10GRxPortId[FM_MAX_NUM_OF_10G_RX_PORTS-1]))
+ {
+ for (j=0; j<ARRAY_SIZE(phys10GRxPortId); j++)
+ if (phys10GRxPortId[j] == i)
+ break;
+ ASSERT_COND(j<ARRAY_SIZE(phys10GRxPortId));
+ p_LnxWrpFmDev->rxPorts[FM_MAX_NUM_OF_1G_RX_PORTS+j].settings.param.liodnBase = liodnBase;
+ }
+ else if ((i >= physOhPortId[0]) &&
+ (i <= physOhPortId[FM_MAX_NUM_OF_OH_PORTS-1]))
+ {
+ for (j=0; j<ARRAY_SIZE(physOhPortId); j++)
+ if (physOhPortId[j] == i)
+ break;
+ ASSERT_COND(j<ARRAY_SIZE(physOhPortId));
+ if (j == 0)
+ p_LnxWrpFmDev->hcPort.settings.param.liodnBase = liodnBase;
+ else
+ p_LnxWrpFmDev->opPorts[j - 1].settings.param.liodnBase = liodnBase;
+ }
+ else if ((i >= phys1GTxPortId[0]) &&
+ (i <= phys1GTxPortId[FM_MAX_NUM_OF_1G_TX_PORTS-1]))
+ {
+ for (j=0; j<ARRAY_SIZE(phys1GTxPortId); j++)
+ if (phys1GTxPortId[j] == i)
+ break;
+ ASSERT_COND(j<ARRAY_SIZE(phys1GTxPortId));
+ p_LnxWrpFmDev->txPorts[j].settings.param.liodnBase = liodnBase;
+ }
+ else if (FM_MAX_NUM_OF_10G_TX_PORTS &&
+ (i >= phys10GTxPortId[0]) &&
+ (i <= phys10GTxPortId[FM_MAX_NUM_OF_10G_TX_PORTS-1]))
+ {
+ for (j=0; j<ARRAY_SIZE(phys10GTxPortId); j++)
+ if (phys10GTxPortId[j] == i)
+ break;
+ ASSERT_COND(j<ARRAY_SIZE(phys10GTxPortId));
+ p_LnxWrpFmDev->txPorts[FM_MAX_NUM_OF_1G_TX_PORTS+j].settings.param.liodnBase = liodnBase;
+ }
+ }
+
+ p_Ppids = (t_Ppids *)UINT_TO_PTR(p_LnxWrpFmDev->fmBaseAddr+FM_BMI_PPIDS_OFFSET);
+
+ for (i=0; i<FM_MAX_NUM_OF_1G_RX_PORTS; i++)
+ p_LnxWrpFmDev->rxPorts[i].settings.param.specificParams.rxParams.liodnOffset =
+ p_Ppids->fmbm_ppid[phys1GRxPortId[i]-1];
+
+ for (i=0; i<FM_MAX_NUM_OF_10G_RX_PORTS; i++)
+ p_LnxWrpFmDev->rxPorts[FM_MAX_NUM_OF_1G_RX_PORTS+i].settings.param.specificParams.rxParams.liodnOffset =
+ p_Ppids->fmbm_ppid[phys10GRxPortId[i]-1];
+
+ return E_OK;
+}
+
+/**
+ * FindFmanMicrocode - find the Fman microcode
+ *
+ * This function returns a pointer to the QE Firmware blob that holds
+ * the Fman microcode. We use the QE Firmware structure because Fman microcode
+ * is similar to QE microcode, so there's no point in defining a new layout.
+ *
+ * Current versions of U-Boot embed the Fman firmware into the device tree,
+ * so we check for that first. Each Fman node in the device tree contains a
+ * node or a pointer to node that holds the firmware. Technically, we should
+ * be fetching the firmware node for the current Fman, but we don't have that
+ * information any more, so we assume that there is only one firmware node in
+ * the device tree, and that all Fmen use the same firmware.
+ */
+static const struct qe_firmware *FindFmanMicrocode(void)
+{
+ static const struct qe_firmware *P4080_UCPatch;
+ struct device_node *np;
+
+ if (P4080_UCPatch)
+ return P4080_UCPatch;
+
+ /* The firmware should be inside the device tree. */
+ np = of_find_compatible_node(NULL, NULL, "fsl,fman-firmware");
+ if (np) {
+ P4080_UCPatch = of_get_property(np, "fsl,firmware", NULL);
+ of_node_put(np);
+ if (P4080_UCPatch)
+ return P4080_UCPatch;
+ else
+ REPORT_ERROR(WARNING, E_NOT_FOUND, ("firmware node is incomplete"));
+ }
+
+ /* Returning NULL here forces the reuse of the IRAM content */
+ return NULL;
+}
+
+static t_LnxWrpFmDev * ReadFmDevTreeNode (struct platform_device *of_dev)
+{
+ t_LnxWrpFmDev *p_LnxWrpFmDev;
+ struct device_node *fm_node, *dev_node;
+ struct of_device_id name;
+ struct resource res;
+ const uint32_t *uint32_prop;
+ int _errno=0, lenp;
+
+ fm_node = of_node_get(of_dev->dev.of_node);
+
+ uint32_prop = (uint32_t *)of_get_property(fm_node, "cell-index", &lenp);
+ if (unlikely(uint32_prop == NULL)) {
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("of_get_property(%s, cell-index) failed", fm_node->full_name));
+ return NULL;
+ }
+ if (WARN_ON(lenp != sizeof(uint32_t)))
+ return NULL;
+ if (*uint32_prop > INTG_MAX_NUM_OF_FM) {
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("fm id!"));
+ return NULL;
+ }
+ p_LnxWrpFmDev = CreateFmDev(*uint32_prop);
+ if (!p_LnxWrpFmDev) {
+ REPORT_ERROR(MAJOR, E_NULL_POINTER, NO_MSG);
+ return NULL;
+ }
+ p_LnxWrpFmDev->dev = &of_dev->dev;
+ p_LnxWrpFmDev->id = *uint32_prop;
+
+ /* Get the FM interrupt */
+ p_LnxWrpFmDev->irq = of_irq_to_resource(fm_node, 0, NULL);
+ if (unlikely(p_LnxWrpFmDev->irq == /*NO_IRQ*/0)) {
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("of_irq_to_resource() = %d", NO_IRQ));
+ return NULL;
+ }
+
+ /* Get the FM error interrupt */
+ p_LnxWrpFmDev->err_irq = of_irq_to_resource(fm_node, 1, NULL);
+ /* TODO - un-comment it once there will be err_irq in the DTS */
+#if 0
+ if (unlikely(p_LnxWrpFmDev->err_irq == /*NO_IRQ*/0)) {
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("of_irq_to_resource() = %d", NO_IRQ));
+ return NULL;
+ }
+#endif /* 0 */
+
+ /* Get the FM address */
+ _errno = of_address_to_resource(fm_node, 0, &res);
+ if (unlikely(_errno < 0)) {
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("of_address_to_resource() = %d", _errno));
+ return NULL;
+ }
+
+ p_LnxWrpFmDev->fmBaseAddr = 0;
+ p_LnxWrpFmDev->fmPhysBaseAddr = res.start;
+ p_LnxWrpFmDev->fmMemSize = res.end + 1 - res.start;
+
+ uint32_prop = (uint32_t *)of_get_property(fm_node, "clock-frequency", &lenp);
+ if (unlikely(uint32_prop == NULL)) {
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("of_get_property(%s, clock-frequency) failed", fm_node->full_name));
+ return NULL;
+ }
+ if (WARN_ON(lenp != sizeof(uint32_t)))
+ return NULL;
+ p_LnxWrpFmDev->fmDevSettings.param.fmClkFreq = (*uint32_prop + 500000)/1000000; /* In MHz, rounded */
+
+ /* Get the MURAM base address and size */
+ memset(&name, 0, sizeof(struct of_device_id));
+ if (WARN_ON(strlen("muram") >= sizeof(name.name)))
+ return NULL;
+ strcpy(name.name, "muram");
+ if (WARN_ON(strlen("fsl,fman-muram") >= sizeof(name.compatible)))
+ return NULL;
+ strcpy(name.compatible, "fsl,fman-muram");
+ for_each_child_of_node(fm_node, dev_node) {
+ if (likely(of_match_node(&name, dev_node) != NULL)) {
+ _errno = of_address_to_resource(dev_node, 0, &res);
+ if (unlikely(_errno < 0)) {
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("of_address_to_resource() = %d", _errno));
+ return NULL;
+ }
+
+ p_LnxWrpFmDev->fmMuramBaseAddr = 0;
+ p_LnxWrpFmDev->fmMuramPhysBaseAddr = res.start;
+ p_LnxWrpFmDev->fmMuramMemSize = res.end + 1 - res.start;
+ }
+ }
+
+ /* Get the RTC base address and size */
+ memset(&name, 0, sizeof(struct of_device_id));
+ if (WARN_ON(strlen("rtc") >= sizeof(name.name)))
+ return NULL;
+ strcpy(name.name, "rtc");
+ if (WARN_ON(strlen("fsl,fman-rtc") >= sizeof(name.compatible)))
+ return NULL;
+ strcpy(name.compatible, "fsl,fman-rtc");
+ for_each_child_of_node(fm_node, dev_node) {
+ if (likely(of_match_node(&name, dev_node) != NULL)) {
+ _errno = of_address_to_resource(dev_node, 0, &res);
+ if (unlikely(_errno < 0)) {
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("of_address_to_resource() = %d", _errno));
+ return NULL;
+ }
+
+ p_LnxWrpFmDev->fmRtcBaseAddr = 0;
+ p_LnxWrpFmDev->fmRtcPhysBaseAddr = res.start;
+ p_LnxWrpFmDev->fmRtcMemSize = res.end + 1 - res.start;
+ }
+ }
+
+#if (DPAA_VERSION >= 11)
+ /* Get the VSP base address */
+ for_each_child_of_node(fm_node, dev_node) {
+ if (of_device_is_compatible(dev_node, "fsl,fman-vsps")) {
+ _errno = of_address_to_resource(dev_node, 0, &res);
+ if (unlikely(_errno < 0)) {
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("of_address_to_resource() = %d", _errno));
+ return NULL;
+ }
+ p_LnxWrpFmDev->fmVspBaseAddr = 0;
+ p_LnxWrpFmDev->fmVspPhysBaseAddr = res.start;
+ p_LnxWrpFmDev->fmVspMemSize = res.end + 1 - res.start;
+ }
+ }
+#endif
+
+ /* Get all PCD nodes */
+ memset(&name, 0, sizeof(struct of_device_id));
+ if (WARN_ON(strlen("parser") >= sizeof(name.name)))
+ return NULL;
+ strcpy(name.name, "parser");
+ if (WARN_ON(strlen("fsl,fman-parser") >= sizeof(name.compatible)))
+ return NULL;
+ strcpy(name.compatible, "fsl,fman-parser");
+ for_each_child_of_node(fm_node, dev_node)
+ if (likely(of_match_node(&name, dev_node) != NULL))
+ p_LnxWrpFmDev->prsActive = TRUE;
+
+ memset(&name, 0, sizeof(struct of_device_id));
+ if (WARN_ON(strlen("keygen") >= sizeof(name.name)))
+ return NULL;
+ strcpy(name.name, "keygen");
+ if (WARN_ON(strlen("fsl,fman-keygen") >= sizeof(name.compatible)))
+ return NULL;
+ strcpy(name.compatible, "fsl,fman-keygen");
+ for_each_child_of_node(fm_node, dev_node)
+ if (likely(of_match_node(&name, dev_node) != NULL))
+ p_LnxWrpFmDev->kgActive = TRUE;
+
+ memset(&name, 0, sizeof(struct of_device_id));
+ if (WARN_ON(strlen("cc") >= sizeof(name.name)))
+ return NULL;
+ strcpy(name.name, "cc");
+ if (WARN_ON(strlen("fsl,fman-cc") >= sizeof(name.compatible)))
+ return NULL;
+ strcpy(name.compatible, "fsl,fman-cc");
+ for_each_child_of_node(fm_node, dev_node)
+ if (likely(of_match_node(&name, dev_node) != NULL))
+ p_LnxWrpFmDev->ccActive = TRUE;
+
+ memset(&name, 0, sizeof(struct of_device_id));
+ if (WARN_ON(strlen("policer") >= sizeof(name.name)))
+ return NULL;
+ strcpy(name.name, "policer");
+ if (WARN_ON(strlen("fsl,fman-policer") >= sizeof(name.compatible)))
+ return NULL;
+ strcpy(name.compatible, "fsl,fman-policer");
+ for_each_child_of_node(fm_node, dev_node)
+ if (likely(of_match_node(&name, dev_node) != NULL))
+ p_LnxWrpFmDev->plcrActive = TRUE;
+
+ if (p_LnxWrpFmDev->prsActive || p_LnxWrpFmDev->kgActive ||
+ p_LnxWrpFmDev->ccActive || p_LnxWrpFmDev->plcrActive)
+ p_LnxWrpFmDev->pcdActive = TRUE;
+
+ if (p_LnxWrpFmDev->pcdActive)
+ {
+ const char *str_prop = (char *)of_get_property(fm_node, "fsl,default-pcd", &lenp);
+ if (str_prop) {
+ if (strncmp(str_prop, "3-tuple", strlen("3-tuple")) == 0)
+ p_LnxWrpFmDev->defPcd = e_FM_PCD_3_TUPLE;
+ }
+ else
+ p_LnxWrpFmDev->defPcd = e_NO_PCD;
+ }
+
+ of_node_put(fm_node);
+
+ p_LnxWrpFmDev->hcCh =
+ qman_affine_channel(cpumask_first(qman_affine_cpus()));
+
+ p_LnxWrpFmDev->active = TRUE;
+
+ return p_LnxWrpFmDev;
+}
+
+struct device_node *GetFmAdvArgsDevTreeNode (uint8_t fmIndx)
+{
+ struct device_node *dev_node;
+ const uint32_t *uint32_prop;
+ int lenp;
+
+ for_each_compatible_node(dev_node, NULL, "fsl,fman-extended-args") {
+ uint32_prop = (uint32_t *)of_get_property(dev_node, "cell-index", &lenp);
+ if (unlikely(uint32_prop == NULL)) {
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE,
+ ("of_get_property(%s, cell-index) failed",
+ dev_node->full_name));
+ return NULL;
+ }
+ if (WARN_ON(lenp != sizeof(uint32_t)))
+ return NULL;
+ if (*uint32_prop > INTG_MAX_NUM_OF_FM) {
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("fm id!"));
+ return NULL;
+ }
+ if (fmIndx == *uint32_prop)
+ return dev_node;
+ }
+
+ return NULL;
+}
+
+static t_Error CheckNConfigFmAdvArgs (t_LnxWrpFmDev *p_LnxWrpFmDev)
+{
+ struct device_node *dev_node;
+ t_Error err = E_INVALID_VALUE;
+ /*const uint32_t *uint32_prop;*/
+ const char *str_prop;
+ int lenp;
+
+ dev_node = GetFmAdvArgsDevTreeNode(p_LnxWrpFmDev->id);
+ if (!dev_node) /* no advance parameters for FMan */
+ return E_OK;
+
+ str_prop = (char *)of_get_property(dev_node, "dma-aid-mode", &lenp);
+ if (str_prop) {
+ if (strcmp(str_prop, "port") == 0)
+ err = FM_ConfigDmaAidMode(p_LnxWrpFmDev->h_Dev, e_FM_DMA_AID_OUT_PORT_ID);
+ else if (strcmp(str_prop, "tnum") == 0)
+ err = FM_ConfigDmaAidMode(p_LnxWrpFmDev->h_Dev, e_FM_DMA_AID_OUT_TNUM);
+ }
+
+ if (err != E_OK)
+ RETURN_ERROR(MINOR, err, NO_MSG);
+
+ of_node_put(dev_node);
+
+ return E_OK;
+}
+
+static void LnxwrpFmDevExceptionsCb(t_Handle h_App, e_FmExceptions exception)
+{
+ t_LnxWrpFmDev *p_LnxWrpFmDev = (t_LnxWrpFmDev *)h_App;
+
+ ASSERT_COND(p_LnxWrpFmDev);
+
+ DBG(INFO, ("got fm exception %d", exception));
+
+ /* do nothing */
+ UNUSED(exception);
+}
+
+static void LnxwrpFmDevBusErrorCb(t_Handle h_App,
+ e_FmPortType portType,
+ uint8_t portId,
+ uint64_t addr,
+ uint8_t tnum,
+ uint16_t liodn)
+{
+ t_LnxWrpFmDev *p_LnxWrpFmDev = (t_LnxWrpFmDev *)h_App;
+
+ ASSERT_COND(p_LnxWrpFmDev);
+
+ /* do nothing */
+ UNUSED(portType);UNUSED(portId);UNUSED(addr);UNUSED(tnum);UNUSED(liodn);
+}
+
+static t_Error ConfigureFmDev(t_LnxWrpFmDev *p_LnxWrpFmDev)
+{
+ struct resource *dev_res;
+ int _errno;
+
+ if (!p_LnxWrpFmDev->active)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("FM not configured!!!"));
+
+#ifndef MODULE
+ _errno = can_request_irq(p_LnxWrpFmDev->irq, 0);
+ if (unlikely(_errno < 0))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("can_request_irq() = %d", _errno));
+#endif
+ _errno = devm_request_irq(p_LnxWrpFmDev->dev, p_LnxWrpFmDev->irq, fm_irq, 0, "fman", p_LnxWrpFmDev);
+ if (unlikely(_errno < 0))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("request_irq(%d) = %d", p_LnxWrpFmDev->irq, _errno));
+
+ if (p_LnxWrpFmDev->err_irq != 0) {
+#ifndef MODULE
+ _errno = can_request_irq(p_LnxWrpFmDev->err_irq, 0);
+ if (unlikely(_errno < 0))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("can_request_irq() = %d", _errno));
+#endif
+ _errno = devm_request_irq(p_LnxWrpFmDev->dev, p_LnxWrpFmDev->err_irq, fm_err_irq, IRQF_SHARED, "fman-err", p_LnxWrpFmDev);
+ if (unlikely(_errno < 0))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("request_irq(%d) = %d", p_LnxWrpFmDev->err_irq, _errno));
+ }
+
+ p_LnxWrpFmDev->res = devm_request_mem_region(p_LnxWrpFmDev->dev, p_LnxWrpFmDev->fmPhysBaseAddr, p_LnxWrpFmDev->fmMemSize, "fman");
+ if (unlikely(p_LnxWrpFmDev->res == NULL))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("request_mem_region() failed"));
+
+ p_LnxWrpFmDev->fmBaseAddr = PTR_TO_UINT(devm_ioremap(p_LnxWrpFmDev->dev, p_LnxWrpFmDev->fmPhysBaseAddr, p_LnxWrpFmDev->fmMemSize));
+ if (unlikely(p_LnxWrpFmDev->fmBaseAddr == 0))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("devm_ioremap() failed"));
+
+ if (SYS_RegisterIoMap((uint64_t)p_LnxWrpFmDev->fmBaseAddr, (uint64_t)p_LnxWrpFmDev->fmPhysBaseAddr, p_LnxWrpFmDev->fmMemSize) != E_OK)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("FM memory map"));
+
+ dev_res = __devm_request_region(p_LnxWrpFmDev->dev, p_LnxWrpFmDev->res, p_LnxWrpFmDev->fmMuramPhysBaseAddr, p_LnxWrpFmDev->fmMuramMemSize, "fman-muram");
+ if (unlikely(dev_res == NULL))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("__devm_request_region() failed"));
+
+ p_LnxWrpFmDev->fmMuramBaseAddr = PTR_TO_UINT(devm_ioremap(p_LnxWrpFmDev->dev, p_LnxWrpFmDev->fmMuramPhysBaseAddr, p_LnxWrpFmDev->fmMuramMemSize));
+ if (unlikely(p_LnxWrpFmDev->fmMuramBaseAddr == 0))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("devm_ioremap() failed"));
+
+ if (SYS_RegisterIoMap((uint64_t)p_LnxWrpFmDev->fmMuramBaseAddr, (uint64_t)p_LnxWrpFmDev->fmMuramPhysBaseAddr, p_LnxWrpFmDev->fmMuramMemSize) != E_OK)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("FM MURAM memory map"));
+
+ if (p_LnxWrpFmDev->fmRtcPhysBaseAddr)
+ {
+ dev_res = __devm_request_region(p_LnxWrpFmDev->dev, p_LnxWrpFmDev->res, p_LnxWrpFmDev->fmRtcPhysBaseAddr, p_LnxWrpFmDev->fmRtcMemSize, "fman-rtc");
+ if (unlikely(dev_res == NULL))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("__devm_request_region() failed"));
+
+ p_LnxWrpFmDev->fmRtcBaseAddr = PTR_TO_UINT(devm_ioremap(p_LnxWrpFmDev->dev, p_LnxWrpFmDev->fmRtcPhysBaseAddr, p_LnxWrpFmDev->fmRtcMemSize));
+ if (unlikely(p_LnxWrpFmDev->fmRtcBaseAddr == 0))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("devm_ioremap() failed"));
+
+ if (SYS_RegisterIoMap((uint64_t)p_LnxWrpFmDev->fmRtcBaseAddr, (uint64_t)p_LnxWrpFmDev->fmRtcPhysBaseAddr, p_LnxWrpFmDev->fmRtcMemSize) != E_OK)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("FM-RTC memory map"));
+ }
+
+#if (DPAA_VERSION >= 11)
+ if (p_LnxWrpFmDev->fmVspPhysBaseAddr) {
+ dev_res = __devm_request_region(p_LnxWrpFmDev->dev, p_LnxWrpFmDev->res, p_LnxWrpFmDev->fmVspPhysBaseAddr, p_LnxWrpFmDev->fmVspMemSize, "fman-vsp");
+ if (unlikely(dev_res == NULL))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("__devm_request_region() failed"));
+
+ p_LnxWrpFmDev->fmVspBaseAddr = PTR_TO_UINT(devm_ioremap(p_LnxWrpFmDev->dev, p_LnxWrpFmDev->fmVspPhysBaseAddr, p_LnxWrpFmDev->fmVspMemSize));
+ if (unlikely(p_LnxWrpFmDev->fmVspBaseAddr == 0))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("devm_ioremap() failed"));
+ }
+#endif
+
+ p_LnxWrpFmDev->fmDevSettings.param.baseAddr = p_LnxWrpFmDev->fmBaseAddr;
+ p_LnxWrpFmDev->fmDevSettings.param.fmId = p_LnxWrpFmDev->id;
+ p_LnxWrpFmDev->fmDevSettings.param.irq = NO_IRQ;
+ p_LnxWrpFmDev->fmDevSettings.param.errIrq = NO_IRQ;
+ p_LnxWrpFmDev->fmDevSettings.param.f_Exception = LnxwrpFmDevExceptionsCb;
+ p_LnxWrpFmDev->fmDevSettings.param.f_BusError = LnxwrpFmDevBusErrorCb;
+ p_LnxWrpFmDev->fmDevSettings.param.h_App = p_LnxWrpFmDev;
+
+ return FillRestFmInfo(p_LnxWrpFmDev);
+}
+
+static t_Error InitFmDev(t_LnxWrpFmDev *p_LnxWrpFmDev)
+{
+ const struct qe_firmware *fw;
+
+ if (!p_LnxWrpFmDev->active)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("FM not configured!!!"));
+
+ if ((p_LnxWrpFmDev->h_MuramDev = FM_MURAM_ConfigAndInit(p_LnxWrpFmDev->fmMuramBaseAddr, p_LnxWrpFmDev->fmMuramMemSize)) == NULL)
+ RETURN_ERROR(MAJOR, E_INVALID_HANDLE, ("FM-MURAM!"));
+
+ /* Loading the fman-controller code */
+ fw = FindFmanMicrocode();
+
+ if (!fw) {
+ /* this forces the reuse of the current IRAM content */
+ p_LnxWrpFmDev->fmDevSettings.param.firmware.size = 0;
+ p_LnxWrpFmDev->fmDevSettings.param.firmware.p_Code = NULL;
+ } else {
+ p_LnxWrpFmDev->fmDevSettings.param.firmware.p_Code =
+ (void *) fw + fw->microcode[0].code_offset;
+ p_LnxWrpFmDev->fmDevSettings.param.firmware.size =
+ sizeof(u32) * fw->microcode[0].count;
+ DBG(INFO, ("Loading fman-controller code version %d.%d.%d",
+ fw->microcode[0].major,
+ fw->microcode[0].minor,
+ fw->microcode[0].revision));
+ }
+
+ p_LnxWrpFmDev->fmDevSettings.param.h_FmMuram = p_LnxWrpFmDev->h_MuramDev;
+
+#if (DPAA_VERSION >= 11)
+ if (p_LnxWrpFmDev->fmVspBaseAddr) {
+ p_LnxWrpFmDev->fmDevSettings.param.vspBaseAddr = p_LnxWrpFmDev->fmVspBaseAddr;
+ p_LnxWrpFmDev->fmDevSettings.param.partVSPBase = 0;
+ p_LnxWrpFmDev->fmDevSettings.param.partNumOfVSPs = FM_VSP_MAX_NUM_OF_ENTRIES;
+ }
+#endif
+
+ if ((p_LnxWrpFmDev->h_Dev = FM_Config(&p_LnxWrpFmDev->fmDevSettings.param)) == NULL)
+ RETURN_ERROR(MAJOR, E_INVALID_HANDLE, ("FM"));
+
+
+ if (FM_ConfigResetOnInit(p_LnxWrpFmDev->h_Dev, TRUE) != E_OK)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("FM"));
+
+#ifdef CONFIG_FMAN_P1023
+ if (FM_ConfigDmaAidOverride(p_LnxWrpFmDev->h_Dev, TRUE) != E_OK)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("FM"));
+#endif
+
+
+#if defined(CONFIG_FMAN_RESOURCE_ALLOCATION_ALGORITHM) && defined(CONFIG_FMAN_P3040_P4080_P5020)
+ /* Enable 14g w/ jumbo frames following HW suggestion. */
+ FM_ConfigTotalFifoSize(p_LnxWrpFmDev->h_Dev, 128*KILOBYTE);
+#elif defined(CONFIG_FMAN_RESOURCE_ALLOCATION_ALGORITHM) && defined(CONFIG_FMAN_P1023)
+ FM_ConfigTotalFifoSize(p_LnxWrpFmDev->h_Dev, 48*KILOBYTE);
+#endif
+#if (DPAA_VERSION >= 11)
+#define DEFAULT_TOTAL_FIFO_SIZE_FOR_FMAN_V3H 295*KILOBYTE
+ FM_ConfigTotalFifoSize(p_LnxWrpFmDev->h_Dev,
+ DEFAULT_TOTAL_FIFO_SIZE_FOR_FMAN_V3H);
+#endif /* (DPAA_VERSION >= 11) */
+
+ CheckNConfigFmAdvArgs(p_LnxWrpFmDev);
+
+ if (FM_Init(p_LnxWrpFmDev->h_Dev) != E_OK)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("FM"));
+
+ /* TODO: Why we mask these interrupts? */
+ if (p_LnxWrpFmDev->err_irq == 0) {
+ FM_SetException(p_LnxWrpFmDev->h_Dev, e_FM_EX_DMA_BUS_ERROR,FALSE);
+ FM_SetException(p_LnxWrpFmDev->h_Dev,e_FM_EX_DMA_READ_ECC,FALSE);
+ FM_SetException(p_LnxWrpFmDev->h_Dev,e_FM_EX_DMA_SYSTEM_WRITE_ECC,FALSE);
+ FM_SetException(p_LnxWrpFmDev->h_Dev,e_FM_EX_DMA_FM_WRITE_ECC,FALSE);
+ FM_SetException(p_LnxWrpFmDev->h_Dev,e_FM_EX_DMA_SINGLE_PORT_ECC, FALSE);
+ FM_SetException(p_LnxWrpFmDev->h_Dev,e_FM_EX_FPM_STALL_ON_TASKS , FALSE);
+ FM_SetException(p_LnxWrpFmDev->h_Dev,e_FM_EX_FPM_SINGLE_ECC, FALSE);
+ FM_SetException(p_LnxWrpFmDev->h_Dev,e_FM_EX_FPM_DOUBLE_ECC,FALSE);
+ FM_SetException(p_LnxWrpFmDev->h_Dev,e_FM_EX_QMI_SINGLE_ECC, FALSE);
+ FM_SetException(p_LnxWrpFmDev->h_Dev,e_FM_EX_QMI_DOUBLE_ECC,FALSE);
+ FM_SetException(p_LnxWrpFmDev->h_Dev,e_FM_EX_QMI_DEQ_FROM_UNKNOWN_PORTID,FALSE);
+ FM_SetException(p_LnxWrpFmDev->h_Dev,e_FM_EX_BMI_LIST_RAM_ECC,FALSE);
+ FM_SetException(p_LnxWrpFmDev->h_Dev,e_FM_EX_BMI_STORAGE_PROFILE_ECC, FALSE);
+ FM_SetException(p_LnxWrpFmDev->h_Dev,e_FM_EX_BMI_STATISTICS_RAM_ECC, FALSE);
+ FM_SetException(p_LnxWrpFmDev->h_Dev,e_FM_EX_BMI_DISPATCH_RAM_ECC, FALSE);
+ FM_SetException(p_LnxWrpFmDev->h_Dev,e_FM_EX_IRAM_ECC,FALSE);
+ /* TODO: FmDisableRamsEcc assert for ramsEccOwners.
+ * FM_SetException(p_LnxWrpFmDev->h_Dev,e_FM_EX_MURAM_ECC,FALSE);*/
+ }
+
+ if (p_LnxWrpFmDev->fmRtcBaseAddr)
+ {
+ t_FmRtcParams fmRtcParam;
+
+ memset(&fmRtcParam, 0, sizeof(fmRtcParam));
+ fmRtcParam.h_App = p_LnxWrpFmDev;
+ fmRtcParam.h_Fm = p_LnxWrpFmDev->h_Dev;
+ fmRtcParam.baseAddress = p_LnxWrpFmDev->fmRtcBaseAddr;
+
+ if(!(p_LnxWrpFmDev->h_RtcDev = FM_RTC_Config(&fmRtcParam)))
+ RETURN_ERROR(MAJOR, E_INVALID_HANDLE, ("FM-RTC"));
+
+ if (FM_RTC_ConfigPeriod(p_LnxWrpFmDev->h_RtcDev, 5) != E_OK)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("FM-RTC"));
+
+ if (FM_RTC_Init(p_LnxWrpFmDev->h_RtcDev) != E_OK)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("FM-RTC"));
+ }
+
+ return E_OK;
+}
+
+/* TODO: to be moved back here */
+extern void FreeFmPcdDev(t_LnxWrpFmDev *p_LnxWrpFmDev);
+
+static void FreeFmDev(t_LnxWrpFmDev *p_LnxWrpFmDev)
+{
+ if (!p_LnxWrpFmDev->active)
+ return;
+
+ FreeFmPcdDev(p_LnxWrpFmDev);
+
+ if (p_LnxWrpFmDev->h_RtcDev)
+ FM_RTC_Free(p_LnxWrpFmDev->h_RtcDev);
+
+ if (p_LnxWrpFmDev->h_Dev)
+ FM_Free(p_LnxWrpFmDev->h_Dev);
+
+ if (p_LnxWrpFmDev->h_MuramDev)
+ FM_MURAM_Free(p_LnxWrpFmDev->h_MuramDev);
+
+ if (p_LnxWrpFmDev->fmRtcBaseAddr)
+ {
+ SYS_UnregisterIoMap(p_LnxWrpFmDev->fmRtcBaseAddr);
+ devm_iounmap(p_LnxWrpFmDev->dev, UINT_TO_PTR(p_LnxWrpFmDev->fmRtcBaseAddr));
+ __devm_release_region(p_LnxWrpFmDev->dev, p_LnxWrpFmDev->res, p_LnxWrpFmDev->fmRtcPhysBaseAddr, p_LnxWrpFmDev->fmRtcMemSize);
+ }
+ SYS_UnregisterIoMap(p_LnxWrpFmDev->fmMuramBaseAddr);
+ devm_iounmap(p_LnxWrpFmDev->dev, UINT_TO_PTR(p_LnxWrpFmDev->fmMuramBaseAddr));
+ __devm_release_region(p_LnxWrpFmDev->dev, p_LnxWrpFmDev->res, p_LnxWrpFmDev->fmMuramPhysBaseAddr, p_LnxWrpFmDev->fmMuramMemSize);
+ SYS_UnregisterIoMap(p_LnxWrpFmDev->fmBaseAddr);
+ devm_iounmap(p_LnxWrpFmDev->dev, UINT_TO_PTR(p_LnxWrpFmDev->fmBaseAddr));
+ devm_release_mem_region(p_LnxWrpFmDev->dev, p_LnxWrpFmDev->fmPhysBaseAddr, p_LnxWrpFmDev->fmMemSize);
+ if (p_LnxWrpFmDev->err_irq != 0) {
+ devm_free_irq(p_LnxWrpFmDev->dev, p_LnxWrpFmDev->err_irq, p_LnxWrpFmDev);
+ }
+
+ devm_free_irq(p_LnxWrpFmDev->dev, p_LnxWrpFmDev->irq, p_LnxWrpFmDev);
+}
+
+/* FMan character device file operations */
+extern struct file_operations fm_fops;
+
+static int /*__devinit*/ fm_probe(struct platform_device *of_dev)
+{
+ t_LnxWrpFmDev *p_LnxWrpFmDev;
+
+ if ((p_LnxWrpFmDev = ReadFmDevTreeNode(of_dev)) == NULL)
+ return -EIO;
+ if (ConfigureFmDev(p_LnxWrpFmDev) != E_OK)
+ return -EIO;
+ if (InitFmDev(p_LnxWrpFmDev) != E_OK)
+ return -EIO;
+
+ /* IOCTL ABI checking */
+ LnxWrpPCDIOCTLEnumChecking();
+ LnxWrpPCDIOCTLTypeChecking();
+
+ Sprint (p_LnxWrpFmDev->name, "%s%d", DEV_FM_NAME, p_LnxWrpFmDev->id);
+
+ /* Register to the /dev for IOCTL API */
+ /* Register dynamically a new major number for the character device: */
+ if ((p_LnxWrpFmDev->major = register_chrdev(0, p_LnxWrpFmDev->name, &fm_fops)) <= 0) {
+ REPORT_ERROR(MAJOR, E_INVALID_STATE, ("Failed to allocate a major number for device \"%s\"", p_LnxWrpFmDev->name));
+ return -EIO;
+ }
+
+ /* Creating classes for FM */
+ DBG(TRACE ,("class_create fm_class"));
+ p_LnxWrpFmDev->fm_class = class_create(THIS_MODULE, p_LnxWrpFmDev->name);
+ if (IS_ERR(p_LnxWrpFmDev->fm_class)) {
+ unregister_chrdev(p_LnxWrpFmDev->major, p_LnxWrpFmDev->name);
+ REPORT_ERROR(MAJOR, E_INVALID_STATE, ("class_create error fm_class"));
+ return -EIO;
+ }
+
+ device_create(p_LnxWrpFmDev->fm_class, NULL, MKDEV(p_LnxWrpFmDev->major, DEV_FM_MINOR_BASE), NULL,
+ "fm%d", p_LnxWrpFmDev->id);
+ device_create(p_LnxWrpFmDev->fm_class, NULL, MKDEV(p_LnxWrpFmDev->major, DEV_FM_PCD_MINOR_BASE), NULL,
+ "fm%d-pcd", p_LnxWrpFmDev->id);
+ dev_set_drvdata(p_LnxWrpFmDev->dev, p_LnxWrpFmDev);
+
+ /* create sysfs entries for stats and regs */
+ if ( fm_sysfs_create(p_LnxWrpFmDev->dev) !=0 )
+ {
+ FreeFmDev(p_LnxWrpFmDev);
+ REPORT_ERROR(MAJOR, E_INVALID_STATE, ("Unable to create sysfs entry - fm!!!"));
+ return -EIO;
+ }
+
+ DBG(TRACE, ("FM%d probed", p_LnxWrpFmDev->id));
+
+#if defined(CONFIG_FMAN_RESOURCE_ALLOCATION_ALGORITHM)
+ /* Precalculate resources for FMAN based on number of
+ * FMan ports available
+ */
+ if(fm_set_active_fman_ports(of_dev, p_LnxWrpFmDev)!= 0)
+ return -EIO;
+
+#if defined(CONFIG_FMAN_P3040_P4080_P5020)
+ /* 128K MURAM for p3,p4 and p5 */
+ if(fm_precalculate_fifosizes(
+ p_LnxWrpFmDev,
+ 128*KILOBYTE)
+ != 0)
+ return -EIO;
+#else
+ /* for all other platforms: MURAM Space for fifosize=3/4 * MURAM_SIZE*/
+ if(fm_precalculate_fifosizes(
+ p_LnxWrpFmDev,
+ 48*KILOBYTE)
+ != 0)
+ return -EIO;
+#endif
+ if(fm_precalculate_open_dma(
+ p_LnxWrpFmDev,
+ BMI_MAX_NUM_OF_DMAS, /* max open dmas:dpaa_integration_ext.h */
+ FM_DEFAULT_TX10G_OPENDMA, /* default TX 10g open dmas */
+ FM_DEFAULT_RX10G_OPENDMA, /* default RX 10g open dmas */
+ FM_10G_OPENDMA_MIN_TRESHOLD,/* TX 10g minimum treshold */
+ FM_10G_OPENDMA_MIN_TRESHOLD)/* RX 10g minimum treshold */
+ != 0)
+ return -EIO;
+ if(fm_precalculate_tnums(
+ p_LnxWrpFmDev,
+ BMI_MAX_NUM_OF_TASKS) /* max TNUMS: dpa integration file. */
+ != 0)
+ return -EIO;
+#endif
+
+ return 0;
+}
+
+static int fm_remove(struct platform_device *of_dev)
+{
+ t_LnxWrpFmDev *p_LnxWrpFmDev;
+ struct device *dev;
+
+ dev = &of_dev->dev;
+ p_LnxWrpFmDev = dev_get_drvdata(dev);
+
+ fm_sysfs_destroy(dev);
+
+ DBG(TRACE, ("destroy fm_class"));
+ device_destroy(p_LnxWrpFmDev->fm_class, MKDEV(p_LnxWrpFmDev->major, DEV_FM_MINOR_BASE));
+ device_destroy(p_LnxWrpFmDev->fm_class, MKDEV(p_LnxWrpFmDev->major, DEV_FM_PCD_MINOR_BASE));
+ class_destroy(p_LnxWrpFmDev->fm_class);
+
+ /* Destroy chardev */
+ unregister_chrdev(p_LnxWrpFmDev->major, p_LnxWrpFmDev->name);
+
+ FreeFmDev(p_LnxWrpFmDev);
+
+ DestroyFmDev(p_LnxWrpFmDev);
+
+ dev_set_drvdata(dev, NULL);
+
+ return 0;
+}
+
+static const struct of_device_id fm_match[] = {
+ {
+ .compatible = "fsl,fman"
+ },
+ {}
+};
+#ifndef MODULE
+MODULE_DEVICE_TABLE(of, fm_match);
+#endif /* !MODULE */
+
+static struct platform_driver fm_driver = {
+ .driver = {
+ .name = "fsl-fman",
+ .of_match_table = fm_match,
+ .owner = THIS_MODULE,
+ },
+ .probe = fm_probe,
+ .remove = fm_remove
+};
+
+t_Handle LNXWRP_FM_Init(void)
+{
+ memset(&lnxWrpFm, 0, sizeof(lnxWrpFm));
+ mutex_init(&lnxwrp_mutex);
+
+ /* Register to the DTB for basic FM API */
+ platform_driver_register(&fm_driver);
+
+ return &lnxWrpFm;
+}
+
+t_Error LNXWRP_FM_Free(t_Handle h_LnxWrpFm)
+{
+ platform_driver_unregister(&fm_driver);
+ mutex_destroy(&lnxwrp_mutex);
+
+ return E_OK;
+}
+
+
+struct fm * fm_bind(struct device *fm_dev)
+{
+ return (struct fm *)(dev_get_drvdata(get_device(fm_dev)));
+}
+EXPORT_SYMBOL(fm_bind);
+
+void fm_unbind(struct fm *fm)
+{
+ t_LnxWrpFmDev *p_LnxWrpFmDev = (t_LnxWrpFmDev*)fm;
+
+ put_device(p_LnxWrpFmDev->dev);
+}
+EXPORT_SYMBOL(fm_unbind);
+
+struct resource * fm_get_mem_region(struct fm *fm)
+{
+ t_LnxWrpFmDev *p_LnxWrpFmDev = (t_LnxWrpFmDev*)fm;
+
+ return p_LnxWrpFmDev->res;
+}
+EXPORT_SYMBOL(fm_get_mem_region);
+
+void * fm_get_handle(struct fm *fm)
+{
+ t_LnxWrpFmDev *p_LnxWrpFmDev = (t_LnxWrpFmDev*)fm;
+
+ return (void *)p_LnxWrpFmDev->h_Dev;
+}
+EXPORT_SYMBOL(fm_get_handle);
+
+void * fm_get_rtc_handle(struct fm *fm)
+{
+ t_LnxWrpFmDev *p_LnxWrpFmDev = (t_LnxWrpFmDev*)fm;
+
+ return (void *)p_LnxWrpFmDev->h_RtcDev;
+}
+EXPORT_SYMBOL(fm_get_rtc_handle);
+
+struct fm_port * fm_port_bind (struct device *fm_port_dev)
+{
+ return (struct fm_port *)(dev_get_drvdata(get_device(fm_port_dev)));
+}
+EXPORT_SYMBOL(fm_port_bind);
+
+void fm_port_unbind(struct fm_port *port)
+{
+ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev = (t_LnxWrpFmPortDev*)port;
+
+ put_device(p_LnxWrpFmPortDev->dev);
+}
+EXPORT_SYMBOL(fm_port_unbind);
+
+void * fm_port_get_handle(struct fm_port *port)
+{
+ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev = (t_LnxWrpFmPortDev*)port;
+
+ return (void *)p_LnxWrpFmPortDev->h_Dev;
+}
+EXPORT_SYMBOL(fm_port_get_handle);
+
+void fm_port_get_base_addr(const struct fm_port *port, uint64_t *base_addr)
+{
+ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev = (t_LnxWrpFmPortDev *)port;
+
+ *base_addr = p_LnxWrpFmPortDev->settings.param.baseAddr;
+}
+EXPORT_SYMBOL(fm_port_get_base_addr);
+
+void fm_port_pcd_bind (struct fm_port *port, struct fm_port_pcd_param *params)
+{
+ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev = (t_LnxWrpFmPortDev*)port;
+
+ p_LnxWrpFmPortDev->pcd_owner_params.cba = params->cba;
+ p_LnxWrpFmPortDev->pcd_owner_params.cbf = params->cbf;
+ p_LnxWrpFmPortDev->pcd_owner_params.dev = params->dev;
+}
+EXPORT_SYMBOL(fm_port_pcd_bind);
+
+void fm_port_get_buff_layout_ext_params(struct fm_port *port, struct fm_port_params *params)
+{
+ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev = (t_LnxWrpFmPortDev *)port;
+ struct device_node *fm_node, *port_node;
+ const uint32_t *uint32_prop;
+ int lenp;
+
+ params->data_align = 0;
+ params->manip_extra_space = 0;
+
+ fm_node = GetFmAdvArgsDevTreeNode(((t_LnxWrpFmDev *) p_LnxWrpFmPortDev->h_LnxWrpFmDev)->id);
+ if (!fm_node) /* no advance parameters for FMan */
+ return;
+
+ port_node = GetFmPortAdvArgsDevTreeNode(fm_node,
+ p_LnxWrpFmPortDev->settings.param.portType,
+ p_LnxWrpFmPortDev->settings.param.portId);
+ if (!port_node) /* no advance parameters for FMan-Port */
+ return;
+
+ uint32_prop = (uint32_t *)of_get_property(port_node, "buffer-layout", &lenp);
+ if (uint32_prop) {
+ if (WARN_ON(lenp != sizeof(uint32_t)*2))
+ return;
+
+ params->manip_extra_space = (uint8_t)uint32_prop[0];
+ params->data_align = (uint16_t)uint32_prop[1];
+ }
+
+ of_node_put(port_node);
+ of_node_put(fm_node);
+}
+EXPORT_SYMBOL(fm_port_get_buff_layout_ext_params);
+
+int fm_get_tx_port_channel(struct fm_port *port)
+{
+ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev = (t_LnxWrpFmPortDev*)port;
+
+ return p_LnxWrpFmPortDev->txCh;
+}
+EXPORT_SYMBOL(fm_get_tx_port_channel);
+
+int fm_port_enable (struct fm_port *port)
+{
+ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev = (t_LnxWrpFmPortDev*)port;
+
+ FM_PORT_Enable(p_LnxWrpFmPortDev->h_Dev);
+
+ return 0;
+}
+EXPORT_SYMBOL(fm_port_enable);
+
+void fm_port_disable(struct fm_port *port)
+{
+ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev = (t_LnxWrpFmPortDev*)port;
+
+ FM_PORT_Disable(p_LnxWrpFmPortDev->h_Dev);
+}
+EXPORT_SYMBOL(fm_port_disable);
+
+void fm_mutex_lock(void)
+{
+ mutex_lock(&lnxwrp_mutex);
+}
+EXPORT_SYMBOL(fm_mutex_lock);
+
+void fm_mutex_unlock(void)
+{
+ mutex_unlock(&lnxwrp_mutex);
+}
+EXPORT_SYMBOL(fm_mutex_unlock);
+
+static t_Handle h_FmLnxWrp;
+
+static int __init __cold fm_load (void)
+{
+ if ((h_FmLnxWrp = LNXWRP_FM_Init()) == NULL)
+ {
+ printk("Failed to init FM wrapper!\n");
+ return -ENODEV;
+ }
+
+ printk(KERN_CRIT "Freescale FM module ("__DATE__ ":"__TIME__")," \
+ " FMD API version %d.%d.%d\n",
+ FMD_API_VERSION_MAJOR,
+ FMD_API_VERSION_MINOR,
+ FMD_API_VERSION_RESPIN);
+ return 0;
+}
+
+static void __exit __cold fm_unload (void)
+{
+ if (h_FmLnxWrp)
+ LNXWRP_FM_Free(h_FmLnxWrp);
+}
+
+module_init (fm_load);
+module_exit (fm_unload);
diff --git a/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_fm.h b/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_fm.h
new file mode 100644
index 0000000..37c52c7
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_fm.h
@@ -0,0 +1,275 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * 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 Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * 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 Freescale Semiconductor ``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 Freescale Semiconductor 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.
+ */
+
+/*
+ @File lnxwrp_fm.h
+
+ @Author Shlomi Gridish
+
+ @Description FM Linux wrapper functions.
+
+*/
+
+#ifndef __LNXWRP_FM_H__
+#define __LNXWRP_FM_H__
+
+#include <linux/fsl_qman.h> /* struct qman_fq */
+
+#include "std_ext.h"
+#include "error_ext.h"
+#include "list_ext.h"
+
+#include "lnxwrp_fm_ext.h"
+
+#define __ERR_MODULE__ MODULE_FM
+
+#define FM_MAX_NUM_OF_ADV_SETTINGS 10
+
+#define LNXWRP_FM_NUM_OF_SHARED_PROFILES 16
+
+#if defined(CONFIG_FMAN_DISABLE_OH_TO_REUSE_RESOURCES)
+#define FM_10G_OPENDMA_MIN_TRESHOLD 8 /* 10g minimum treshold if only HC is enabled and no OH port enabled */
+#define FM_OPENDMA_RX_TX_RAPORT 2 /* RX = 2*TX */
+#else
+#define FM_10G_OPENDMA_MIN_TRESHOLD 7 /* 10g minimum treshold if 7 OH ports are enabled */
+#define FM_OPENDMA_RX_TX_RAPORT 1 /* RX = TX */
+#endif
+#define FM_DEFAULT_TX10G_OPENDMA 8 /* default TX 10g open dmas */
+#define FM_DEFAULT_RX10G_OPENDMA 8 /* default RX 10g open dmas */
+
+#define FRAG_MANIP_SPACE 128
+#define FRAG_DATA_ALIGN 64
+
+#ifndef CONFIG_FSL_FM_MAX_FRAME_SIZE
+#define CONFIG_FSL_FM_MAX_FRAME_SIZE 0
+#endif
+
+#ifndef CONFIG_FSL_FM_RX_EXTRA_HEADROOM
+#define CONFIG_FSL_FM_RX_EXTRA_HEADROOM 0
+#endif
+
+typedef enum {
+ e_NO_PCD = 0,
+ e_FM_PCD_3_TUPLE
+} e_LnxWrpFmPortPcdDefUseCase;
+
+
+typedef struct t_FmTestFq {
+ struct qman_fq fq_base;
+ t_Handle h_Arg;
+} t_FmTestFq;
+
+typedef struct {
+ uint8_t id; /* sw port id, see SW_PORT_ID_TO_HW_PORT_ID() in fm_common.h */
+ int minor;
+ char name[20];
+ bool active;
+ uint64_t phys_baseAddr;
+ uint64_t baseAddr; /* Port's *virtual* address */
+ uint32_t memSize;
+ t_WrpFmPortDevSettings settings;
+ t_FmExtPools opExtPools;
+ uint8_t totalNumOfSchemes;
+ uint8_t schemesBase;
+ uint8_t numOfSchemesUsed;
+ uint32_t pcdBaseQ;
+ uint16_t pcdNumOfQs;
+ struct fm_port_pcd_param pcd_owner_params;
+ e_LnxWrpFmPortPcdDefUseCase defPcd;
+ t_Handle h_DefNetEnv;
+ t_Handle h_Schemes[FM_PCD_KG_NUM_OF_SCHEMES];
+ t_FmBufferPrefixContent buffPrefixContent;
+ t_Handle h_Dev;
+ t_Handle h_DfltVsp;
+ t_Handle h_LnxWrpFmDev;
+ uint16_t txCh;
+ struct device *dev;
+ struct device_attribute *dev_attr_stats;
+ struct device_attribute *dev_attr_regs;
+} t_LnxWrpFmPortDev;
+
+typedef struct {
+ uint8_t id;
+ bool active;
+ uint64_t baseAddr;
+ uint32_t memSize;
+ t_WrpFmMacDevSettings settings;
+ t_Handle h_Dev;
+ t_Handle h_LnxWrpFmDev;
+} t_LnxWrpFmMacDev;
+
+/* information about all active ports for an FMan.
+ * !Some ports may be disabled by u-boot, thus will not be available */
+struct fm_active_ports {
+ uint32_t num_oh_ports;
+ uint32_t num_tx_ports;
+ uint32_t num_rx_ports;
+ uint32_t num_tx25_ports;
+ uint32_t num_rx25_ports;
+ uint32_t num_tx10_ports;
+ uint32_t num_rx10_ports;
+};
+
+/* FMan resources precalculated at fm probe based
+ * on available FMan port. */
+struct fm_resource_settings {
+ /* buffers - fifo sizes */
+ uint32_t tx1g_num_buffers;
+ uint32_t rx1g_num_buffers;
+ uint32_t tx2g5_num_buffers; /* Not supported yet by LLD */
+ uint32_t rx2g5_num_buffers; /* Not supported yet by LLD */
+ uint32_t tx10g_num_buffers;
+ uint32_t rx10g_num_buffers;
+ uint32_t oh_num_buffers;
+ uint32_t shared_ext_buffers;
+
+ /* open DMAs */
+ uint32_t tx_1g_dmas;
+ uint32_t rx_1g_dmas;
+ uint32_t tx_2g5_dmas; /* Not supported yet by LLD */
+ uint32_t rx_2g5_dmas; /* Not supported yet by LLD */
+ uint32_t tx_10g_dmas;
+ uint32_t rx_10g_dmas;
+ uint32_t oh_dmas;
+ uint32_t shared_ext_open_dma;
+
+ /* Tnums */
+ uint32_t tx_1g_tnums;
+ uint32_t rx_1g_tnums;
+ uint32_t tx_2g5_tnums; /* Not supported yet by LLD */
+ uint32_t rx_2g5_tnums; /* Not supported yet by LLD */
+ uint32_t tx_10g_tnums;
+ uint32_t rx_10g_tnums;
+ uint32_t oh_tnums;
+ uint32_t shared_ext_tnums;
+};
+
+typedef struct {
+ uint8_t id;
+ char name[10];
+ bool active;
+ bool pcdActive;
+ bool prsActive;
+ bool kgActive;
+ bool ccActive;
+ bool plcrActive;
+ e_LnxWrpFmPortPcdDefUseCase defPcd;
+ uint32_t usedSchemes;
+ uint8_t totalNumOfSharedSchemes;
+ uint8_t sharedSchemesBase;
+ uint8_t numOfSchemesUsed;
+ uint8_t defNetEnvId;
+ uint64_t fmPhysBaseAddr;
+ uint64_t fmBaseAddr;
+ uint32_t fmMemSize;
+ uint64_t fmMuramPhysBaseAddr;
+ uint64_t fmMuramBaseAddr;
+ uint32_t fmMuramMemSize;
+ uint64_t fmRtcPhysBaseAddr;
+ uint64_t fmRtcBaseAddr;
+ uint32_t fmRtcMemSize;
+ uint64_t fmVspPhysBaseAddr;
+ uint64_t fmVspBaseAddr;
+ uint32_t fmVspMemSize;
+ int irq;
+ int err_irq;
+ t_WrpFmDevSettings fmDevSettings;
+ t_WrpFmPcdDevSettings fmPcdDevSettings;
+ t_Handle h_Dev;
+ uint16_t hcCh;
+
+ t_Handle h_MuramDev;
+ t_Handle h_PcdDev;
+ t_Handle h_RtcDev;
+
+ t_LnxWrpFmPortDev hcPort;
+ t_LnxWrpFmPortDev opPorts[FM_MAX_NUM_OF_OH_PORTS-1];
+ t_LnxWrpFmPortDev rxPorts[FM_MAX_NUM_OF_RX_PORTS];
+ t_LnxWrpFmPortDev txPorts[FM_MAX_NUM_OF_TX_PORTS];
+ t_LnxWrpFmMacDev macs[FM_MAX_NUM_OF_MACS];
+ struct fm_active_ports fm_active_ports_info;
+ struct fm_resource_settings fm_resource_settings_info;
+
+ struct device *dev;
+ struct resource *res;
+ int major;
+ struct class *fm_class;
+ struct device_attribute *dev_attr_stats;
+ struct device_attribute *dev_attr_regs;
+
+ struct device_attribute *dev_pcd_attr_stats;
+ struct device_attribute *dev_pcd_attr_regs;
+
+ struct qman_fq *hc_tx_conf_fq, *hc_tx_err_fq, *hc_tx_fq;
+} t_LnxWrpFmDev;
+
+typedef struct {
+ t_LnxWrpFmDev *p_FmDevs[INTG_MAX_NUM_OF_FM];
+} t_LnxWrpFm;
+#define LNXWRP_FM_OBJECT(ptr) LIST_OBJECT(ptr, t_LnxWrpFm, fms[((t_LnxWrpFmDev *)ptr)->id])
+
+
+t_Error LnxwrpFmIOCTL(t_LnxWrpFmDev *p_LnxWrpFmDev, unsigned int cmd, unsigned long arg, bool compat);
+t_Error LnxwrpFmPortIOCTL(t_LnxWrpFmPortDev *p_LnxWrpFmPortDev, unsigned int cmd, unsigned long arg, bool compat);
+
+
+static __inline__ t_Error AllocSchemesForPort(t_LnxWrpFmDev *p_LnxWrpFmDev, uint8_t numSchemes, uint8_t *p_BaseSchemeNum)
+{
+ uint32_t schemeMask;
+ uint8_t i;
+
+ if (!numSchemes)
+ RETURN_ERROR(MINOR, E_INVALID_VALUE, NO_MSG);
+
+ schemeMask = 0x80000000;
+ *p_BaseSchemeNum = 0xff;
+
+ for (i=0; schemeMask && numSchemes; schemeMask>>=1, i++)
+ if ((p_LnxWrpFmDev->usedSchemes & schemeMask) == 0)
+ {
+ p_LnxWrpFmDev->usedSchemes |= schemeMask;
+ numSchemes--;
+ if (*p_BaseSchemeNum==0xff)
+ *p_BaseSchemeNum = i;
+ }
+ else if (*p_BaseSchemeNum!=0xff)
+ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Fragmentation on schemes array!!!"));
+
+ if (numSchemes)
+ RETURN_ERROR(MINOR, E_FULL, ("schemes!!!"));
+ return E_OK;
+}
+
+void LnxWrpPCDIOCTLTypeChecking(void);
+void LnxWrpPCDIOCTLEnumChecking(void);
+
+#endif /* __LNXWRP_FM_H__ */
diff --git a/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_fm_port.c b/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_fm_port.c
new file mode 100644
index 0000000..f9f3353
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_fm_port.c
@@ -0,0 +1,1332 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * 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 Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * 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 Freescale Semiconductor ``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 Freescale Semiconductor 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.
+ */
+
+/*
+ @File lnxwrp_fm_port.c
+
+ @Description FMD wrapper - FMan port functions.
+
+*/
+
+#include <linux/version.h>
+#if defined(CONFIG_MODVERSIONS) && !defined(MODVERSIONS)
+#define MODVERSIONS
+#endif
+#ifdef MODVERSIONS
+#include <config/modversions.h>
+#endif /* MODVERSIONS */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/cdev.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+
+#include "sprint_ext.h"
+#include "fm_common.h"
+#include "fm_port_ext.h"
+#if (DPAA_VERSION >= 11)
+#include "fm_vsp_ext.h"
+#endif /* DPAA_VERSION >= 11 */
+#include "fm_ioctls.h"
+#include "lnxwrp_resources.h"
+#include "lnxwrp_sysfs_fm_port.h"
+
+extern struct device_node *GetFmAdvArgsDevTreeNode (uint8_t fmIndx);
+
+/* TODO: duplicated, see lnxwrp_fm.c */
+#define ADD_ADV_CONFIG_NO_RET(_func, _param)\
+do {\
+ if (i < max) {\
+ p_Entry = &p_Entrys[i];\
+ p_Entry->p_Function = _func;\
+ _param\
+ i++;\
+ } else {\
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE,\
+ ("Number of advanced-configuration entries exceeded"));\
+ } \
+} while (0)
+
+
+static volatile int hcFrmRcv/* = 0 */;
+static spinlock_t lock;
+
+static enum qman_cb_dqrr_result qm_tx_conf_dqrr_cb(struct qman_portal *portal,
+ struct qman_fq *fq,
+ const struct qm_dqrr_entry
+ *dq)
+{
+ t_LnxWrpFmDev *p_LnxWrpFmDev = ((t_FmTestFq *) fq)->h_Arg;
+ unsigned long flags;
+
+ FM_PCD_HcTxConf(p_LnxWrpFmDev->h_PcdDev, (t_DpaaFD *)&dq->fd);
+ spin_lock_irqsave(&lock, flags);
+ hcFrmRcv--;
+ spin_unlock_irqrestore(&lock, flags);
+
+ return qman_cb_dqrr_consume;
+}
+
+static enum qman_cb_dqrr_result qm_tx_dqrr_cb(struct qman_portal *portal,
+ struct qman_fq *fq,
+ const struct qm_dqrr_entry *dq)
+{
+ WARN(1, "FMD: failure at %s:%d/%s()!\n", __FILE__, __LINE__,
+ __func__);
+ return qman_cb_dqrr_consume;
+}
+
+static void qm_err_cb(struct qman_portal *portal,
+ struct qman_fq *fq, const struct qm_mr_entry *msg)
+{
+ WARN(1, "FMD: failure at %s:%d/%s()!\n", __FILE__, __LINE__,
+ __func__);
+}
+
+static struct qman_fq *FqAlloc(t_LnxWrpFmDev * p_LnxWrpFmDev,
+ uint32_t fqid,
+ uint32_t flags, uint16_t channel, uint8_t wq)
+{
+ int _errno;
+ struct qman_fq *fq = NULL;
+ t_FmTestFq *p_FmtFq;
+ struct qm_mcc_initfq initfq;
+
+ p_FmtFq = (t_FmTestFq *) XX_Malloc(sizeof(t_FmTestFq));
+ if (!p_FmtFq) {
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FQ obj!!!"));
+ return NULL;
+ }
+
+ p_FmtFq->fq_base.cb.dqrr = ((flags & QMAN_FQ_FLAG_NO_ENQUEUE)
+ ? qm_tx_conf_dqrr_cb
+ : qm_tx_dqrr_cb);
+ p_FmtFq->fq_base.cb.ern = qm_err_cb;
+ /* p_FmtFq->fq_base.cb.fqs = qm_err_cb; */
+ /* qm_err_cb wrongly called when the FQ is parked */
+ p_FmtFq->fq_base.cb.fqs = NULL;
+ p_FmtFq->h_Arg = (t_Handle) p_LnxWrpFmDev;
+ if (fqid == 0) {
+ flags |= QMAN_FQ_FLAG_DYNAMIC_FQID;
+ flags &= ~QMAN_FQ_FLAG_NO_MODIFY;
+ } else {
+ flags &= ~QMAN_FQ_FLAG_DYNAMIC_FQID;
+ }
+
+ if (qman_create_fq(fqid, flags, &p_FmtFq->fq_base)) {
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FQ obj - qman_new_fq!!!"));
+ XX_Free(p_FmtFq);
+ return NULL;
+ }
+ fq = &p_FmtFq->fq_base;
+
+ if (!(flags & QMAN_FQ_FLAG_NO_MODIFY)) {
+ initfq.we_mask = QM_INITFQ_WE_DESTWQ;
+ initfq.fqd.dest.channel = channel;
+ initfq.fqd.dest.wq = wq;
+
+ _errno = qman_init_fq(fq, QMAN_INITFQ_FLAG_SCHED, &initfq);
+ if (unlikely(_errno < 0)) {
+ REPORT_ERROR(MAJOR, E_NO_MEMORY,
+ ("FQ obj - qman_init_fq!!!"));
+ qman_destroy_fq(fq, 0);
+ XX_Free(p_FmtFq);
+ return NULL;
+ }
+ }
+
+ DBG(TRACE,
+ ("fqid %d, flags 0x%08x, channel %d, wq %d", qman_fq_fqid(fq),
+ flags, channel, wq));
+
+ return fq;
+}
+
+static void FqFree(struct qman_fq *fq)
+{
+ int _errno;
+
+ _errno = qman_retire_fq(fq, NULL);
+ if (unlikely(_errno < 0))
+ printk(KERN_WARNING "qman_retire_fq(%u) = %d\n", qman_fq_fqid(fq), _errno);
+
+ _errno = qman_oos_fq(fq);
+ if (unlikely(_errno < 0))
+ printk(KERN_WARNING "qman_oos_fq(%u) = %d\n", qman_fq_fqid(fq), _errno);
+
+ qman_destroy_fq(fq, 0);
+ XX_Free((t_FmTestFq *) fq);
+}
+
+static t_Error QmEnqueueCB(t_Handle h_Arg, void *p_Fd)
+{
+ t_LnxWrpFmDev *p_LnxWrpFmDev = (t_LnxWrpFmDev *) h_Arg;
+ int _errno, timeout = 1000000;
+ unsigned long flags;
+
+ ASSERT_COND(p_LnxWrpFmDev);
+
+ spin_lock_irqsave(&lock, flags);
+ hcFrmRcv++;
+ spin_unlock_irqrestore(&lock, flags);
+
+ _errno = qman_enqueue(p_LnxWrpFmDev->hc_tx_fq, (struct qm_fd *) p_Fd,
+ 0);
+ if (_errno)
+ RETURN_ERROR(MINOR, E_INVALID_STATE,
+ ("qman_enqueue() failed"));
+
+ while (hcFrmRcv && --timeout) {
+ udelay(1);
+ cpu_relax();
+ }
+ if (timeout == 0) {
+ dump_stack();
+ RETURN_ERROR(MINOR, E_WRITE_FAILED,
+ ("timeout waiting for Tx confirmation"));
+ return E_WRITE_FAILED;
+ }
+
+ return E_OK;
+}
+
+static t_LnxWrpFmPortDev *ReadFmPortDevTreeNode(struct platform_device
+ *of_dev)
+{
+ t_LnxWrpFmDev *p_LnxWrpFmDev;
+ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev;
+ struct device_node *fm_node, *port_node;
+ struct resource res;
+ const uint32_t *uint32_prop;
+ int _errno = 0, lenp;
+#ifdef CONFIG_FMAN_P1023
+ static unsigned char have_oh_port/* = 0 */;
+#endif
+
+ port_node = of_node_get(of_dev->dev.of_node);
+
+ /* Get the FM node */
+ fm_node = of_get_parent(port_node);
+ if (unlikely(fm_node == NULL)) {
+ REPORT_ERROR(MAJOR, E_NO_DEVICE,
+ ("of_get_parent() = %d", _errno));
+ return NULL;
+ }
+
+ p_LnxWrpFmDev =
+ dev_get_drvdata(&of_find_device_by_node(fm_node)->dev);
+ of_node_put(fm_node);
+
+ /* if fm_probe() failed, no point in going further with port probing */
+ if (p_LnxWrpFmDev == NULL)
+ return NULL;
+
+ uint32_prop =
+ (uint32_t *) of_get_property(port_node, "cell-index", &lenp);
+ if (unlikely(uint32_prop == NULL)) {
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE,
+ ("of_get_property(%s, cell-index) failed",
+ port_node->full_name));
+ return NULL;
+ }
+ if (WARN_ON(lenp != sizeof(uint32_t)))
+ return NULL;
+ if (of_device_is_compatible(port_node, "fsl,fman-port-oh")) {
+ if (unlikely(*uint32_prop >= FM_MAX_NUM_OF_OH_PORTS)) {
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE,
+ ("of_get_property(%s, cell-index) failed",
+ port_node->full_name));
+ return NULL;
+ }
+
+#ifdef CONFIG_FMAN_P1023
+ /* Beware, this can be done when there is only
+ one FMan to be initialized */
+ if (!have_oh_port) {
+ have_oh_port = 1; /* first OP/HC port
+ is used for host command */
+#else
+ /* Here it is hardcoded the use of the OH port 1
+ (with cell-index 0) */
+ if (*uint32_prop == 0) {
+#endif
+ p_LnxWrpFmPortDev = &p_LnxWrpFmDev->hcPort;
+ p_LnxWrpFmPortDev->id = 0;
+ /*
+ p_LnxWrpFmPortDev->id = *uint32_prop-1;
+ p_LnxWrpFmPortDev->id = *uint32_prop;
+ */
+ p_LnxWrpFmPortDev->settings.param.portType =
+ e_FM_PORT_TYPE_OH_HOST_COMMAND;
+ } else {
+ p_LnxWrpFmPortDev =
+ &p_LnxWrpFmDev->opPorts[*uint32_prop - 1];
+ p_LnxWrpFmPortDev->id = *uint32_prop - 1;
+ p_LnxWrpFmPortDev->settings.param.portType =
+ e_FM_PORT_TYPE_OH_OFFLINE_PARSING;
+ }
+ p_LnxWrpFmPortDev->settings.param.portId = *uint32_prop;
+
+ uint32_prop =
+ (uint32_t *) of_get_property(port_node,
+ "fsl,qman-channel-id",
+ &lenp);
+ if (uint32_prop == NULL) {
+ /*
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("missing fsl,qman-channel-id"));
+ */
+ XX_Print("FM warning: missing fsl,qman-channel-id"
+ " for OH port.\n");
+ return NULL;
+ }
+ if (WARN_ON(lenp != sizeof(uint32_t)))
+ return NULL;
+ p_LnxWrpFmPortDev->txCh = *uint32_prop;
+
+ p_LnxWrpFmPortDev->settings.param.specificParams.nonRxParams.
+ qmChannel = p_LnxWrpFmPortDev->txCh;
+ } else if (of_device_is_compatible(port_node, "fsl,fman-port-1g-tx")) {
+ if (unlikely(*uint32_prop >= FM_MAX_NUM_OF_1G_TX_PORTS)) {
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE,
+ ("of_get_property(%s, cell-index) failed",
+ port_node->full_name));
+ return NULL;
+ }
+ p_LnxWrpFmPortDev = &p_LnxWrpFmDev->txPorts[*uint32_prop];
+
+ p_LnxWrpFmPortDev->id = *uint32_prop;
+ p_LnxWrpFmPortDev->settings.param.portId =
+ p_LnxWrpFmPortDev->id;
+ p_LnxWrpFmPortDev->settings.param.portType = e_FM_PORT_TYPE_TX;
+
+ uint32_prop = (uint32_t *) of_get_property(port_node,
+ "fsl,qman-channel-id", &lenp);
+ if (uint32_prop == NULL) {
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE,
+ ("missing fsl,qman-channel-id"));
+ return NULL;
+ }
+ if (WARN_ON(lenp != sizeof(uint32_t)))
+ return NULL;
+ p_LnxWrpFmPortDev->txCh = *uint32_prop;
+ p_LnxWrpFmPortDev->
+ settings.param.specificParams.nonRxParams.qmChannel =
+ p_LnxWrpFmPortDev->txCh;
+ } else if (of_device_is_compatible(port_node, "fsl,fman-port-10g-tx")) {
+ if (unlikely(*uint32_prop >= FM_MAX_NUM_OF_10G_TX_PORTS)) {
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE,
+ ("of_get_property(%s, cell-index) failed",
+ port_node->full_name));
+ return NULL;
+ }
+ p_LnxWrpFmPortDev = &p_LnxWrpFmDev->txPorts[*uint32_prop +
+ FM_MAX_NUM_OF_1G_TX_PORTS];
+
+ p_LnxWrpFmPortDev->id = *uint32_prop;
+ p_LnxWrpFmPortDev->settings.param.portId =
+ p_LnxWrpFmPortDev->id;
+ p_LnxWrpFmPortDev->settings.param.portType =
+ e_FM_PORT_TYPE_TX_10G;
+ uint32_prop = (uint32_t *) of_get_property(port_node,
+ "fsl,qman-channel-id", &lenp);
+ if (uint32_prop == NULL) {
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE,
+ ("missing fsl,qman-channel-id"));
+ return NULL;
+ }
+ if (WARN_ON(lenp != sizeof(uint32_t)))
+ return NULL;
+ p_LnxWrpFmPortDev->txCh = *uint32_prop;
+ p_LnxWrpFmPortDev->settings.param.specificParams.nonRxParams.
+ qmChannel = p_LnxWrpFmPortDev->txCh;
+ } else if (of_device_is_compatible(port_node, "fsl,fman-port-1g-rx")) {
+ if (unlikely(*uint32_prop >= FM_MAX_NUM_OF_1G_RX_PORTS)) {
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE,
+ ("of_get_property(%s, cell-index) failed",
+ port_node->full_name));
+ return NULL;
+ }
+ p_LnxWrpFmPortDev = &p_LnxWrpFmDev->rxPorts[*uint32_prop];
+
+ p_LnxWrpFmPortDev->id = *uint32_prop;
+ p_LnxWrpFmPortDev->settings.param.portId =
+ p_LnxWrpFmPortDev->id;
+ p_LnxWrpFmPortDev->settings.param.portType = e_FM_PORT_TYPE_RX;
+ if (p_LnxWrpFmDev->pcdActive)
+ p_LnxWrpFmPortDev->defPcd = p_LnxWrpFmDev->defPcd;
+ } else if (of_device_is_compatible(port_node, "fsl,fman-port-10g-rx")) {
+ if (unlikely(*uint32_prop >= FM_MAX_NUM_OF_10G_RX_PORTS)) {
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE,
+ ("of_get_property(%s, cell-index) failed",
+ port_node->full_name));
+ return NULL;
+ }
+ p_LnxWrpFmPortDev = &p_LnxWrpFmDev->rxPorts[*uint32_prop +
+ FM_MAX_NUM_OF_1G_RX_PORTS];
+
+ p_LnxWrpFmPortDev->id = *uint32_prop;
+ p_LnxWrpFmPortDev->settings.param.portId =
+ p_LnxWrpFmPortDev->id;
+ p_LnxWrpFmPortDev->settings.param.portType =
+ e_FM_PORT_TYPE_RX_10G;
+ if (p_LnxWrpFmDev->pcdActive)
+ p_LnxWrpFmPortDev->defPcd = p_LnxWrpFmDev->defPcd;
+ } else {
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("Illegal port type"));
+ return NULL;
+ }
+
+ _errno = of_address_to_resource(port_node, 0, &res);
+ if (unlikely(_errno < 0)) {
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE,
+ ("of_address_to_resource() = %d", _errno));
+ return NULL;
+ }
+
+ p_LnxWrpFmPortDev->dev = &of_dev->dev;
+ p_LnxWrpFmPortDev->baseAddr = 0;
+ p_LnxWrpFmPortDev->phys_baseAddr = res.start;
+ p_LnxWrpFmPortDev->memSize = res.end + 1 - res.start;
+ p_LnxWrpFmPortDev->settings.param.h_Fm = p_LnxWrpFmDev->h_Dev;
+ p_LnxWrpFmPortDev->h_LnxWrpFmDev = (t_Handle) p_LnxWrpFmDev;
+
+ of_node_put(port_node);
+
+ p_LnxWrpFmPortDev->active = TRUE;
+
+#if defined(CONFIG_FMAN_DISABLE_OH_TO_REUSE_RESOURCES)
+ /* for performance mode no OH port available. */
+ if (p_LnxWrpFmPortDev->settings.param.portType ==
+ e_FM_PORT_TYPE_OH_OFFLINE_PARSING)
+ p_LnxWrpFmPortDev->active = FALSE;
+#endif
+
+ return p_LnxWrpFmPortDev;
+}
+
+struct device_node * GetFmPortAdvArgsDevTreeNode (struct device_node *fm_node,
+ e_FmPortType portType,
+ uint8_t portId)
+{
+ struct device_node *port_node;
+ const uint32_t *uint32_prop;
+ int lenp;
+ char *portTypeString;
+
+ switch(portType) {
+ case e_FM_PORT_TYPE_OH_OFFLINE_PARSING:
+ portTypeString = "fsl,fman-port-op-extended-args";
+ break;
+ case e_FM_PORT_TYPE_TX:
+ portTypeString = "fsl,fman-port-1g-tx-extended-args";
+ break;
+ case e_FM_PORT_TYPE_TX_10G:
+ portTypeString = "fsl,fman-port-10g-tx-extended-args";
+ break;
+ case e_FM_PORT_TYPE_RX:
+ portTypeString = "fsl,fman-port-1g-rx-extended-args";
+ break;
+ case e_FM_PORT_TYPE_RX_10G:
+ portTypeString = "fsl,fman-port-10g-rx-extended-args";
+ break;
+ default:
+ return NULL;
+ }
+
+ for_each_child_of_node(fm_node, port_node) {
+ uint32_prop = (uint32_t *)of_get_property(port_node, "cell-index", &lenp);
+ if (unlikely(uint32_prop == NULL)) {
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE,
+ ("of_get_property(%s, cell-index) failed",
+ port_node->full_name));
+ return NULL;
+ }
+ if (WARN_ON(lenp != sizeof(uint32_t)))
+ return NULL;
+ if (unlikely(*uint32_prop >= FM_MAX_NUM_OF_OH_PORTS)) {
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE,
+ ("of_get_property(%s, cell-index) failed",
+ port_node->full_name));
+ return NULL;
+ }
+
+ if ((portId == *uint32_prop) &&
+ (of_device_is_compatible(port_node, portTypeString))) {
+ return port_node;
+ }
+ }
+
+ return NULL;
+}
+
+static t_Error CheckNConfigFmPortAdvArgs (t_LnxWrpFmPortDev *p_LnxWrpFmPortDev)
+{
+ struct device_node *fm_node, *port_node;
+ t_Error err;
+ t_FmPortRsrc portRsrc;
+ const uint32_t *uint32_prop;
+ /*const char *str_prop;*/
+ int lenp;
+
+ fm_node = GetFmAdvArgsDevTreeNode(((t_LnxWrpFmDev *) p_LnxWrpFmPortDev->h_LnxWrpFmDev)->id);
+ if (!fm_node) /* no advance parameters for FMan */
+ return E_OK;
+
+ port_node = GetFmPortAdvArgsDevTreeNode(fm_node,
+ p_LnxWrpFmPortDev->settings.param.portType,
+ p_LnxWrpFmPortDev->settings.param.portId);
+ if (!port_node) /* no advance parameters for FMan-Port */
+ return E_OK;
+
+ uint32_prop = (uint32_t *)of_get_property(port_node, "num-tnums", &lenp);
+ if (uint32_prop) {
+ if (WARN_ON(lenp != sizeof(uint32_t)*2))
+ RETURN_ERROR(MINOR, E_INVALID_VALUE, NO_MSG);
+
+ portRsrc.num = uint32_prop[0];
+ portRsrc.extra = uint32_prop[1];
+
+ if ((err = FM_PORT_ConfigNumOfTasks(p_LnxWrpFmPortDev->h_Dev,
+ &portRsrc)) != E_OK)
+ RETURN_ERROR(MINOR, err, NO_MSG);
+ }
+
+ uint32_prop = (uint32_t *)of_get_property(port_node, "num-dmas", &lenp);
+ if (uint32_prop) {
+ if (WARN_ON(lenp != sizeof(uint32_t)*2))
+ RETURN_ERROR(MINOR, E_INVALID_VALUE, NO_MSG);
+
+ portRsrc.num = uint32_prop[0];
+ portRsrc.extra = uint32_prop[1];
+
+ if ((err = FM_PORT_ConfigNumOfOpenDmas(p_LnxWrpFmPortDev->h_Dev,
+ &portRsrc)) != E_OK)
+ RETURN_ERROR(MINOR, err, NO_MSG);
+ }
+
+ uint32_prop = (uint32_t *)of_get_property(port_node, "fifo_size", &lenp);
+ if (uint32_prop) {
+ if (WARN_ON(lenp != sizeof(uint32_t)*2))
+ RETURN_ERROR(MINOR, E_INVALID_VALUE, NO_MSG);
+
+ portRsrc.num = uint32_prop[0];
+ portRsrc.extra = uint32_prop[1];
+
+ if ((err = FM_PORT_ConfigSizeOfFifo(p_LnxWrpFmPortDev->h_Dev,
+ &portRsrc)) != E_OK)
+ RETURN_ERROR(MINOR, err, NO_MSG);
+ }
+
+ of_node_put(port_node);
+ of_node_put(fm_node);
+
+ return E_OK;
+}
+
+static t_Error CheckNSetFmPortAdvArgs (t_LnxWrpFmPortDev *p_LnxWrpFmPortDev)
+{
+ struct device_node *fm_node, *port_node;
+ t_Error err;
+ const uint32_t *uint32_prop;
+ /*const char *str_prop;*/
+ int lenp;
+
+ fm_node = GetFmAdvArgsDevTreeNode(((t_LnxWrpFmDev *) p_LnxWrpFmPortDev->h_LnxWrpFmDev)->id);
+ if (!fm_node) /* no advance parameters for FMan */
+ return E_OK;
+
+ port_node = GetFmPortAdvArgsDevTreeNode(fm_node,
+ p_LnxWrpFmPortDev->settings.param.portType,
+ p_LnxWrpFmPortDev->settings.param.portId);
+ if (!port_node) /* no advance parameters for FMan-Port */
+ return E_OK;
+
+#if (DPAA_VERSION >= 11)
+ uint32_prop = (uint32_t *)of_get_property(port_node, "vsp-window", &lenp);
+ if (uint32_prop) {
+ t_FmPortVSPAllocParams portVSPAllocParams;
+ t_FmVspParams fmVspParams;
+ t_LnxWrpFmDev *p_LnxWrpFmDev;
+ uint8_t portId;
+
+ p_LnxWrpFmDev = ((t_LnxWrpFmDev *)p_LnxWrpFmPortDev->h_LnxWrpFmDev);
+
+ if (WARN_ON(lenp != sizeof(uint32_t)*2))
+ RETURN_ERROR(MINOR, E_INVALID_VALUE, NO_MSG);
+
+ if ((p_LnxWrpFmPortDev->settings.param.portType == e_FM_PORT_TYPE_TX) ||
+ (p_LnxWrpFmPortDev->settings.param.portType == e_FM_PORT_TYPE_TX_10G) ||
+ ((p_LnxWrpFmPortDev->settings.param.portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING) &&
+ p_LnxWrpFmPortDev->settings.frag_enabled))
+ return E_OK;
+
+ memset(&portVSPAllocParams, 0, sizeof(portVSPAllocParams));
+ memset(&fmVspParams, 0, sizeof(fmVspParams));
+
+ portVSPAllocParams.numOfProfiles = (uint8_t)uint32_prop[0];
+ portVSPAllocParams.dfltRelativeId = (uint8_t)uint32_prop[1];
+
+ fmVspParams.h_Fm = p_LnxWrpFmDev->h_Dev;
+
+ fmVspParams.portParams.portType = p_LnxWrpFmPortDev->settings.param.portType;
+ fmVspParams.portParams.portId = p_LnxWrpFmPortDev->settings.param.portId;
+ fmVspParams.relativeProfileId = portVSPAllocParams.dfltRelativeId;
+
+ if (p_LnxWrpFmPortDev->settings.param.portType != e_FM_PORT_TYPE_OH_OFFLINE_PARSING)
+ {
+ portId = fmVspParams.portParams.portId;
+ if (p_LnxWrpFmPortDev->settings.param.portType == e_FM_PORT_TYPE_RX_10G)
+ portId += FM_MAX_NUM_OF_1G_RX_PORTS;
+ portVSPAllocParams.h_FmTxPort =
+ p_LnxWrpFmDev->txPorts[portId].h_Dev;
+ fmVspParams.liodnOffset =
+ p_LnxWrpFmDev->rxPorts[portId].settings.param.specificParams.rxParams.liodnOffset;
+ memcpy(&fmVspParams.extBufPools,
+ &p_LnxWrpFmPortDev->settings.param.specificParams.rxParams.extBufPools,
+ sizeof(t_FmExtPools));
+ }
+ else
+ {
+ memcpy(&fmVspParams.extBufPools,
+ &p_LnxWrpFmPortDev->opExtPools,
+ sizeof(t_FmExtPools));
+ }
+
+ if ((err = FM_PORT_VSPAlloc(p_LnxWrpFmPortDev->h_Dev,
+ &portVSPAllocParams)) != E_OK)
+ RETURN_ERROR(MINOR, err, NO_MSG);
+
+ /* We're initializing only the default VSP that are being used by the Linux-Ethernet-driver */
+ if ((p_LnxWrpFmPortDev->settings.param.portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING) &&
+ !p_LnxWrpFmPortDev->opExtPools.numOfPoolsUsed)
+ return E_OK;
+
+ p_LnxWrpFmPortDev->h_DfltVsp = FM_VSP_Config(&fmVspParams);
+ if (!p_LnxWrpFmPortDev->h_DfltVsp)
+ RETURN_ERROR(MAJOR, E_INVALID_HANDLE, ("default-VSP for port!"));
+
+ if ((err = FM_VSP_ConfigBufferPrefixContent(p_LnxWrpFmPortDev->h_DfltVsp,
+ &p_LnxWrpFmPortDev->buffPrefixContent)) != E_OK)
+ RETURN_ERROR(MINOR, err, NO_MSG);
+
+ if ((err = FM_VSP_Init(p_LnxWrpFmPortDev->h_DfltVsp)) != E_OK)
+ RETURN_ERROR(MINOR, err, NO_MSG);
+ }
+#else
+UNUSED(err); UNUSED(uint32_prop); UNUSED(lenp);
+#endif /* (DPAA_VERSION >= 11) */
+
+ of_node_put(port_node);
+ of_node_put(fm_node);
+
+ return E_OK;
+}
+
+static t_Error ConfigureFmPortDev(t_LnxWrpFmPortDev *p_LnxWrpFmPortDev)
+{
+ t_LnxWrpFmDev *p_LnxWrpFmDev =
+ (t_LnxWrpFmDev *) p_LnxWrpFmPortDev->h_LnxWrpFmDev;
+ struct resource *dev_res;
+
+ if (!p_LnxWrpFmPortDev->active)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE,
+ ("FM port not configured!!!"));
+
+ dev_res =
+ __devm_request_region(p_LnxWrpFmDev->dev, p_LnxWrpFmDev->res,
+ p_LnxWrpFmPortDev->phys_baseAddr,
+ p_LnxWrpFmPortDev->memSize,
+ "fman-port-hc");
+ if (unlikely(dev_res == NULL))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE,
+ ("__devm_request_region() failed"));
+ p_LnxWrpFmPortDev->baseAddr =
+ PTR_TO_UINT(devm_ioremap
+ (p_LnxWrpFmDev->dev,
+ p_LnxWrpFmPortDev->phys_baseAddr,
+ p_LnxWrpFmPortDev->memSize));
+ if (unlikely(p_LnxWrpFmPortDev->baseAddr == 0))
+ REPORT_ERROR(MAJOR, E_INVALID_STATE,
+ ("devm_ioremap() failed"));
+
+ p_LnxWrpFmPortDev->settings.param.baseAddr =
+ p_LnxWrpFmPortDev->baseAddr;
+
+ return E_OK;
+}
+
+static t_Error InitFmPortDev(t_LnxWrpFmPortDev *p_LnxWrpFmPortDev)
+{
+#define MY_ADV_CONFIG_CHECK_END \
+ RETURN_ERROR(MAJOR, E_INVALID_SELECTION,\
+ ("Advanced configuration routine"));\
+ if (errCode != E_OK)\
+ RETURN_ERROR(MAJOR, errCode, NO_MSG);\
+ }
+
+ int i = 0;
+
+ if (!p_LnxWrpFmPortDev->active || p_LnxWrpFmPortDev->h_Dev)
+ return E_INVALID_STATE;
+
+ p_LnxWrpFmPortDev->h_Dev =
+ FM_PORT_Config(&p_LnxWrpFmPortDev->settings.param);
+ if (p_LnxWrpFmPortDev->h_Dev == NULL)
+ RETURN_ERROR(MAJOR, E_INVALID_HANDLE, ("FM-port"));
+
+#ifndef FM_QMI_NO_DEQ_OPTIONS_SUPPORT
+ if ((p_LnxWrpFmPortDev->settings.param.portType ==
+ e_FM_PORT_TYPE_TX_10G)
+ || (p_LnxWrpFmPortDev->settings.param.portType ==
+ e_FM_PORT_TYPE_TX)) {
+ t_Error errCode = E_OK;
+ errCode =
+ FM_PORT_ConfigDeqHighPriority(p_LnxWrpFmPortDev->h_Dev,
+ TRUE);
+ if (errCode != E_OK)
+ RETURN_ERROR(MAJOR, errCode, NO_MSG);
+ errCode =
+ FM_PORT_ConfigDeqPrefetchOption(p_LnxWrpFmPortDev->h_Dev,
+ e_FM_PORT_DEQ_FULL_PREFETCH);
+ if (errCode
+ != E_OK)
+ RETURN_ERROR(MAJOR, errCode, NO_MSG);
+ }
+#endif /* !FM_QMI_NO_DEQ_OPTIONS_SUPPORT */
+
+#ifdef FM_BCB_ERRATA_BMI_SW001
+/* Configure BCB workaround on Rx ports, only for B4860 rev1 */
+#define SVR_SECURITY_MASK 0x00080000
+#define SVR_PERSONALITY_MASK 0x0000FF00
+#define SVR_VER_IGNORE_MASK (SVR_SECURITY_MASK | SVR_PERSONALITY_MASK)
+#define SVR_B4860_REV1_VALUE 0x86800010
+
+ if ((p_LnxWrpFmPortDev->settings.param.portType ==
+ e_FM_PORT_TYPE_RX_10G) ||
+ (p_LnxWrpFmPortDev->settings.param.portType ==
+ e_FM_PORT_TYPE_RX)) {
+ unsigned int svr;
+
+ svr = mfspr(SPRN_SVR);
+
+ if ((svr & ~SVR_VER_IGNORE_MASK) == SVR_B4860_REV1_VALUE)
+ FM_PORT_ConfigBCBWorkaround(p_LnxWrpFmPortDev->h_Dev);
+ }
+#endif /* FM_BCB_ERRATA_BMI_SW001 */
+
+/* Call the driver's advanced configuration routines, if requested:
+ Compare the function pointer of each entry to the available routines,
+ and invoke the matching routine with proper casting of arguments. */
+ while (p_LnxWrpFmPortDev->settings.advConfig[i].p_Function
+ && (i < FM_MAX_NUM_OF_ADV_SETTINGS)) {
+
+/* TODO: Change this MACRO */
+ ADV_CONFIG_CHECK_START(
+ &(p_LnxWrpFmPortDev->settings.advConfig[i]))
+
+ ADV_CONFIG_CHECK(p_LnxWrpFmPortDev->h_Dev,
+ FM_PORT_ConfigBufferPrefixContent,
+ NCSW_PARAMS(1,
+ (t_FmBufferPrefixContent *)))
+
+ if ((p_LnxWrpFmPortDev->settings.param.portType ==
+ e_FM_PORT_TYPE_OH_OFFLINE_PARSING) &&
+ (p_LnxWrpFmPortDev->settings.frag_enabled == TRUE)) {
+
+ ADV_CONFIG_CHECK(p_LnxWrpFmPortDev->h_Dev,
+ FM_PORT_ConfigExtBufPools,
+ NCSW_PARAMS(1, (t_FmExtPools *)))
+
+ /* this define contains an else */
+ MY_ADV_CONFIG_CHECK_END
+ }
+
+ /* Advance to next advanced configuration entry */
+ i++;
+ }
+
+#if defined(CONFIG_FMAN_RESOURCE_ALLOCATION_ALGORITHM)
+#if (DPAA_VERSION >= 11)
+#warning The resource allocation algorithm is not available for FMan v3 platforms
+#else
+ /* even if these functions return w/ error, do not crash kernel.
+ Do not return anything because the container function is not
+ linux complient (it should return -EIO). */
+ fm_config_precalculate_fifosize(p_LnxWrpFmPortDev);
+ fm_config_precalculate_open_dma(p_LnxWrpFmPortDev);
+ fm_config_precalculate_tnums(p_LnxWrpFmPortDev);
+#endif
+#endif
+
+ if ((p_LnxWrpFmPortDev->settings.param.portType != e_FM_PORT_TYPE_TX) &&
+ (p_LnxWrpFmPortDev->settings.param.portType != e_FM_PORT_TYPE_TX_10G)) {
+ if (FM_PORT_ConfigErrorsToDiscard(p_LnxWrpFmPortDev->h_Dev, (FM_PORT_FRM_ERR_IPRE |
+ FM_PORT_FRM_ERR_IPR_NCSP |
+ FM_PORT_FRM_ERR_CLS_DISCARD)) !=E_OK)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, NO_MSG);
+ }
+
+ if (CheckNConfigFmPortAdvArgs(p_LnxWrpFmPortDev) != E_OK)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, NO_MSG);
+
+ if (FM_PORT_Init(p_LnxWrpFmPortDev->h_Dev) != E_OK)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, NO_MSG);
+
+ if (CheckNSetFmPortAdvArgs(p_LnxWrpFmPortDev) != E_OK)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, NO_MSG);
+
+/* FMan Fifo sizes behind the scene":
+ * Using the following formulae (*), under a set of simplifying assumptions (.):
+ * . all ports are configured in Normal Mode (rather than Independent Mode)
+ * . the DPAA Eth driver allocates buffers of size:
+ * . MAXFRM + NET_IP_ALIGN + DPA_PRIV_DATA_SIZE + DPA_PARSE_RESULTS_SIZE
+ * + DPA_HASH_RESULTS_SIZE, i.e.:
+ * MAXFRM + 2 + 16 + sizeof(t_FmPrsResult) + 16, i.e.:
+ * MAXFRM + 66
+ * . excessive buffer pools not accounted for
+ *
+ * * for Rx ports on P4080:
+ * . IFSZ = ceil(max(FMBM_EBMPI[PBS]) / 256) * 256 + 7 * 256
+ * . no internal frame offset (FMBM_RIM[FOF] == 0) - otherwise,
+ * add up to 256 to the above
+ *
+ * * for Rx ports on P1023:
+ * . IFSZ = ceil(second_largest(FMBM_EBMPI[PBS] / 256)) * 256 + 7 * 256,
+ * if at least 2 bpools are configured
+ * . IFSZ = 8 * 256, if only a single bpool is configured
+ *
+ * * for Tx ports:
+ * . IFSZ = ceil(frame_size / 256) * 256 + 3 * 256
+ * + FMBM_TFP[DPDE] * 256, i.e.:
+ * IFSZ = ceil(MAXFRM / 256) * 256 + 3 x 256 + FMBM_TFP[DPDE] * 256
+ *
+ * * for OH ports on P4080:
+ * . IFSZ = ceil(frame_size / 256) * 256 + 1 * 256 + FMBM_PP[MXT] * 256
+ * * for OH ports on P1023:
+ * . IFSZ = ceil(frame_size / 256) * 256 + 3 * 256 + FMBM_TFP[DPDE] * 256
+ * * for both P4080 and P1023:
+ * . (conservative decisions, assuming that BMI must bring the entire
+ * frame, not only the frame header)
+ * . no internal frame offset (FMBM_OIM[FOF] == 0) - otherwise,
+ * add up to 256 to the above
+ *
+ * . for P4080/P5020/P3041/P2040, DPDE is:
+ * > 0 or 1, for 1Gb ports, HW default: 0
+ * > 2..7 (recommended: 3..7) for 10Gb ports, HW default: 3
+ * . for P1023, DPDE should be 1
+ *
+ * . for P1023, MXT is in range (0..31)
+ * . for P4080, MXT is in range (0..63)
+ *
+ */
+#if 0
+ if ((p_LnxWrpFmPortDev->defPcd != e_NO_PCD) &&
+ (InitFmPort3TupleDefPcd(p_LnxWrpFmPortDev) != E_OK))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, NO_MSG);
+#endif
+ return E_OK;
+}
+
+void fm_set_rx_port_params(struct fm_port *port,
+ struct fm_port_params *params)
+{
+ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev = (t_LnxWrpFmPortDev *) port;
+ int i;
+
+ p_LnxWrpFmPortDev->settings.param.specificParams.rxParams.errFqid =
+ params->errq;
+ p_LnxWrpFmPortDev->settings.param.specificParams.rxParams.dfltFqid =
+ params->defq;
+ p_LnxWrpFmPortDev->settings.param.specificParams.rxParams.extBufPools.
+ numOfPoolsUsed = params->num_pools;
+ for (i = 0; i < params->num_pools; i++) {
+ p_LnxWrpFmPortDev->settings.param.specificParams.rxParams.
+ extBufPools.extBufPool[i].id =
+ params->pool_param[i].id;
+ p_LnxWrpFmPortDev->settings.param.specificParams.rxParams.
+ extBufPools.extBufPool[i].size =
+ params->pool_param[i].size;
+ }
+
+ p_LnxWrpFmPortDev->buffPrefixContent.privDataSize =
+ params->priv_data_size;
+ p_LnxWrpFmPortDev->buffPrefixContent.passPrsResult =
+ params->parse_results;
+ p_LnxWrpFmPortDev->buffPrefixContent.passHashResult =
+ params->hash_results;
+ p_LnxWrpFmPortDev->buffPrefixContent.passTimeStamp =
+ params->time_stamp;
+ p_LnxWrpFmPortDev->buffPrefixContent.dataAlign =
+ params->data_align;
+ p_LnxWrpFmPortDev->buffPrefixContent.manipExtraSpace =
+ params->manip_extra_space;
+
+ ADD_ADV_CONFIG_START(p_LnxWrpFmPortDev->settings.advConfig,
+ FM_MAX_NUM_OF_ADV_SETTINGS)
+
+ ADD_ADV_CONFIG_NO_RET(FM_PORT_ConfigBufferPrefixContent,
+ ARGS(1,
+ (&p_LnxWrpFmPortDev->
+ buffPrefixContent)));
+
+ ADD_ADV_CONFIG_END InitFmPortDev(p_LnxWrpFmPortDev);
+}
+EXPORT_SYMBOL(fm_set_rx_port_params);
+
+/* this function is called from oh_probe as well, thus it contains oh port
+ * specific parameters (make sure everything is checked) */
+void fm_set_tx_port_params(struct fm_port *port,
+ struct fm_port_params *params)
+{
+ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev = (t_LnxWrpFmPortDev *) port;
+
+ p_LnxWrpFmPortDev->settings.param.specificParams.nonRxParams.errFqid =
+ params->errq;
+ p_LnxWrpFmPortDev->settings.param.specificParams.nonRxParams.
+ dfltFqid = params->defq;
+
+ p_LnxWrpFmPortDev->buffPrefixContent.privDataSize =
+ params->priv_data_size;
+ p_LnxWrpFmPortDev->buffPrefixContent.passPrsResult =
+ params->parse_results;
+ p_LnxWrpFmPortDev->buffPrefixContent.passHashResult =
+ params->hash_results;
+ p_LnxWrpFmPortDev->buffPrefixContent.passTimeStamp =
+ params->time_stamp;
+ p_LnxWrpFmPortDev->settings.frag_enabled =
+ params->frag_enable;
+ p_LnxWrpFmPortDev->buffPrefixContent.dataAlign =
+ params->data_align;
+ p_LnxWrpFmPortDev->buffPrefixContent.manipExtraSpace =
+ params->manip_extra_space;
+
+ ADD_ADV_CONFIG_START(p_LnxWrpFmPortDev->settings.advConfig,
+ FM_MAX_NUM_OF_ADV_SETTINGS)
+
+ ADD_ADV_CONFIG_NO_RET(FM_PORT_ConfigBufferPrefixContent,
+ ARGS(1,
+ (&p_LnxWrpFmPortDev->
+ buffPrefixContent)));
+
+ /* oh port specific parameter (for fragmentation only) */
+ if ((p_LnxWrpFmPortDev->settings.param.portType ==
+ e_FM_PORT_TYPE_OH_OFFLINE_PARSING) &&
+ params->num_pools) {
+ int i;
+
+ p_LnxWrpFmPortDev->opExtPools.numOfPoolsUsed = params->num_pools;
+ for (i = 0; i < params->num_pools; i++) {
+ p_LnxWrpFmPortDev->opExtPools.extBufPool[i].id = params->pool_param[i].id;
+ p_LnxWrpFmPortDev->opExtPools.extBufPool[i].size = params->pool_param[i].size;
+ }
+
+ if (p_LnxWrpFmPortDev->settings.frag_enabled)
+ ADD_ADV_CONFIG_NO_RET(FM_PORT_ConfigExtBufPools,
+ ARGS(1, (&p_LnxWrpFmPortDev->opExtPools)));
+ }
+
+ ADD_ADV_CONFIG_END InitFmPortDev(p_LnxWrpFmPortDev);
+}
+EXPORT_SYMBOL(fm_set_tx_port_params);
+
+void fm_mac_set_handle(t_Handle h_lnx_wrp_fm_dev,
+ t_Handle h_fm_mac,
+ int mac_id)
+{
+ t_LnxWrpFmDev *p_lnx_wrp_fm_dev = (t_LnxWrpFmDev *)h_lnx_wrp_fm_dev;
+
+ p_lnx_wrp_fm_dev->macs[mac_id].h_Dev = h_fm_mac;
+ p_lnx_wrp_fm_dev->macs[mac_id].h_LnxWrpFmDev = h_lnx_wrp_fm_dev;
+}
+EXPORT_SYMBOL(fm_mac_set_handle);
+
+static void LnxwrpFmPcdDevExceptionsCb(t_Handle h_App,
+ e_FmPcdExceptions exception)
+{
+ t_LnxWrpFmDev *p_LnxWrpFmDev = (t_LnxWrpFmDev *) h_App;
+
+ ASSERT_COND(p_LnxWrpFmDev);
+
+ DBG(INFO, ("got fm-pcd exception %d", exception));
+
+ /* do nothing */
+ UNUSED(exception);
+}
+
+static void LnxwrpFmPcdDevIndexedExceptionsCb(t_Handle h_App,
+ e_FmPcdExceptions exception,
+ uint16_t index)
+{
+ t_LnxWrpFmDev *p_LnxWrpFmDev = (t_LnxWrpFmDev *) h_App;
+
+ ASSERT_COND(p_LnxWrpFmDev);
+
+ DBG(INFO,
+ ("got fm-pcd-indexed exception %d, indx %d", exception, index));
+
+ /* do nothing */
+ UNUSED(exception);
+ UNUSED(index);
+}
+
+static t_Error InitFmPcdDev(t_LnxWrpFmDev *p_LnxWrpFmDev)
+{
+ spin_lock_init(&lock);
+
+ if (p_LnxWrpFmDev->pcdActive) {
+ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev = &p_LnxWrpFmDev->hcPort;
+ t_FmPcdParams fmPcdParams;
+ t_Error err;
+
+ memset(&fmPcdParams, 0, sizeof(fmPcdParams));
+ fmPcdParams.h_Fm = p_LnxWrpFmDev->h_Dev;
+ fmPcdParams.prsSupport = p_LnxWrpFmDev->prsActive;
+ fmPcdParams.kgSupport = p_LnxWrpFmDev->kgActive;
+ fmPcdParams.plcrSupport = p_LnxWrpFmDev->plcrActive;
+ fmPcdParams.ccSupport = p_LnxWrpFmDev->ccActive;
+ fmPcdParams.numOfSchemes = FM_PCD_KG_NUM_OF_SCHEMES;
+
+#ifndef CONFIG_GUEST_PARTITION
+ fmPcdParams.f_Exception = LnxwrpFmPcdDevExceptionsCb;
+ if (fmPcdParams.kgSupport)
+ fmPcdParams.f_ExceptionId =
+ LnxwrpFmPcdDevIndexedExceptionsCb;
+ fmPcdParams.h_App = p_LnxWrpFmDev;
+#endif /* !CONFIG_GUEST_PARTITION */
+
+#ifdef CONFIG_MULTI_PARTITION_SUPPORT
+ fmPcdParams.numOfSchemes = 0;
+ fmPcdParams.numOfClsPlanEntries = 0;
+ fmPcdParams.partitionId = 0;
+#endif /* CONFIG_MULTI_PARTITION_SUPPORT */
+ fmPcdParams.useHostCommand = TRUE;
+
+ p_LnxWrpFmDev->hc_tx_fq =
+ FqAlloc(p_LnxWrpFmDev,
+ 0,
+ QMAN_FQ_FLAG_TO_DCPORTAL,
+ p_LnxWrpFmPortDev->txCh, 0);
+ if (!p_LnxWrpFmDev->hc_tx_fq)
+ RETURN_ERROR(MAJOR, E_NULL_POINTER,
+ ("Frame queue allocation failed..."));
+
+ p_LnxWrpFmDev->hc_tx_conf_fq =
+ FqAlloc(p_LnxWrpFmDev,
+ 0,
+ QMAN_FQ_FLAG_NO_ENQUEUE,
+ p_LnxWrpFmDev->hcCh, 7);
+ if (!p_LnxWrpFmDev->hc_tx_conf_fq)
+ RETURN_ERROR(MAJOR, E_NULL_POINTER,
+ ("Frame queue allocation failed..."));
+
+ p_LnxWrpFmDev->hc_tx_err_fq =
+ FqAlloc(p_LnxWrpFmDev,
+ 0,
+ QMAN_FQ_FLAG_NO_ENQUEUE,
+ p_LnxWrpFmDev->hcCh, 7);
+ if (!p_LnxWrpFmDev->hc_tx_err_fq)
+ RETURN_ERROR(MAJOR, E_NULL_POINTER,
+ ("Frame queue allocation failed..."));
+
+ fmPcdParams.hc.portBaseAddr = p_LnxWrpFmPortDev->baseAddr;
+ fmPcdParams.hc.portId =
+ p_LnxWrpFmPortDev->settings.param.portId;
+ fmPcdParams.hc.liodnBase =
+ p_LnxWrpFmPortDev->settings.param.liodnBase;
+ fmPcdParams.hc.errFqid =
+ qman_fq_fqid(p_LnxWrpFmDev->hc_tx_err_fq);
+ fmPcdParams.hc.confFqid =
+ qman_fq_fqid(p_LnxWrpFmDev->hc_tx_conf_fq);
+ fmPcdParams.hc.qmChannel = p_LnxWrpFmPortDev->txCh;
+ fmPcdParams.hc.f_QmEnqueue = QmEnqueueCB;
+ fmPcdParams.hc.h_QmArg = (t_Handle) p_LnxWrpFmDev;
+
+ p_LnxWrpFmDev->h_PcdDev = FM_PCD_Config(&fmPcdParams);
+ if (!p_LnxWrpFmDev->h_PcdDev)
+ RETURN_ERROR(MAJOR, E_INVALID_HANDLE, ("FM PCD!"));
+
+ err =
+ FM_PCD_ConfigPlcrNumOfSharedProfiles(p_LnxWrpFmDev->h_PcdDev,
+ LNXWRP_FM_NUM_OF_SHARED_PROFILES);
+ if (err != E_OK)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+
+ err = FM_PCD_Init(p_LnxWrpFmDev->h_PcdDev);
+ if (err != E_OK)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+
+ if (p_LnxWrpFmDev->err_irq == 0) {
+ FM_PCD_SetException(p_LnxWrpFmDev->h_PcdDev,
+ e_FM_PCD_KG_EXCEPTION_DOUBLE_ECC,
+ FALSE);
+ FM_PCD_SetException(p_LnxWrpFmDev->h_PcdDev,
+ e_FM_PCD_KG_EXCEPTION_KEYSIZE_OVERFLOW,
+ FALSE);
+ FM_PCD_SetException(p_LnxWrpFmDev->h_PcdDev,
+ e_FM_PCD_PLCR_EXCEPTION_INIT_ENTRY_ERROR,
+ FALSE);
+ FM_PCD_SetException(p_LnxWrpFmDev->h_PcdDev,
+ e_FM_PCD_PLCR_EXCEPTION_DOUBLE_ECC,
+ FALSE);
+ FM_PCD_SetException(p_LnxWrpFmDev->h_PcdDev,
+ e_FM_PCD_PRS_EXCEPTION_DOUBLE_ECC,
+ FALSE);
+ FM_PCD_SetException(p_LnxWrpFmDev->h_PcdDev,
+ e_FM_PCD_PLCR_EXCEPTION_PRAM_SELF_INIT_COMPLETE,
+ FALSE);
+ FM_PCD_SetException(p_LnxWrpFmDev->h_PcdDev,
+ e_FM_PCD_PLCR_EXCEPTION_ATOMIC_ACTION_COMPLETE,
+ FALSE);
+ FM_PCD_SetException(p_LnxWrpFmDev->h_PcdDev,
+ e_FM_PCD_PRS_EXCEPTION_SINGLE_ECC,
+ FALSE);
+ }
+ }
+
+ return E_OK;
+}
+
+void FreeFmPcdDev(t_LnxWrpFmDev *p_LnxWrpFmDev)
+{
+
+ if (p_LnxWrpFmDev->h_PcdDev)
+ FM_PCD_Free(p_LnxWrpFmDev->h_PcdDev);
+
+ if (p_LnxWrpFmDev->hc_tx_err_fq)
+ FqFree(p_LnxWrpFmDev->hc_tx_err_fq);
+
+ if (p_LnxWrpFmDev->hc_tx_conf_fq)
+ FqFree(p_LnxWrpFmDev->hc_tx_conf_fq);
+
+ if (p_LnxWrpFmDev->hc_tx_fq)
+ FqFree(p_LnxWrpFmDev->hc_tx_fq);
+}
+
+static void FreeFmPortDev(t_LnxWrpFmPortDev *p_LnxWrpFmPortDev)
+{
+ t_LnxWrpFmDev *p_LnxWrpFmDev =
+ (t_LnxWrpFmDev *) p_LnxWrpFmPortDev->h_LnxWrpFmDev;
+
+ if (!p_LnxWrpFmPortDev->active)
+ return;
+
+ if (p_LnxWrpFmPortDev->h_Dev)
+ FM_PORT_Free(p_LnxWrpFmPortDev->h_Dev);
+
+ devm_iounmap(p_LnxWrpFmDev->dev,
+ UINT_TO_PTR(p_LnxWrpFmPortDev->baseAddr));
+ __devm_release_region(p_LnxWrpFmDev->dev, p_LnxWrpFmDev->res,
+ p_LnxWrpFmPortDev->phys_baseAddr,
+ p_LnxWrpFmPortDev->memSize);
+}
+
+static int /*__devinit*/ fm_port_probe(struct platform_device *of_dev)
+{
+ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev;
+ t_LnxWrpFmDev *p_LnxWrpFmDev;
+ struct device *dev;
+
+ dev = &of_dev->dev;
+
+ p_LnxWrpFmPortDev = ReadFmPortDevTreeNode(of_dev);
+ if (p_LnxWrpFmPortDev == NULL)
+ return -EIO;
+ /* Port can be inactive, thus will not be probed:
+ - in performance mode, OH ports are disabled
+ ...
+ */
+ if (!p_LnxWrpFmPortDev->active)
+ return 0;
+
+ if (ConfigureFmPortDev(p_LnxWrpFmPortDev) != E_OK)
+ return -EIO;
+
+ dev_set_drvdata(dev, p_LnxWrpFmPortDev);
+
+ if (p_LnxWrpFmPortDev->settings.param.portType ==
+ e_FM_PORT_TYPE_OH_HOST_COMMAND)
+ InitFmPcdDev((t_LnxWrpFmDev *) p_LnxWrpFmPortDev->h_LnxWrpFmDev);
+
+ p_LnxWrpFmDev = (t_LnxWrpFmDev *) p_LnxWrpFmPortDev->h_LnxWrpFmDev;
+
+ if (p_LnxWrpFmPortDev->settings.param.portType == e_FM_PORT_TYPE_RX) {
+ Sprint(p_LnxWrpFmPortDev->name, "%s-port-rx%d",
+ p_LnxWrpFmDev->name, p_LnxWrpFmPortDev->id);
+ p_LnxWrpFmPortDev->minor =
+ p_LnxWrpFmPortDev->id + DEV_FM_RX_PORTS_MINOR_BASE;
+ } else if (p_LnxWrpFmPortDev->settings.param.portType ==
+ e_FM_PORT_TYPE_RX_10G) {
+ Sprint(p_LnxWrpFmPortDev->name, "%s-port-rx%d",
+ p_LnxWrpFmDev->name,
+ p_LnxWrpFmPortDev->id + FM_MAX_NUM_OF_1G_RX_PORTS);
+ p_LnxWrpFmPortDev->minor =
+ p_LnxWrpFmPortDev->id + FM_MAX_NUM_OF_1G_RX_PORTS +
+ DEV_FM_RX_PORTS_MINOR_BASE;
+ } else if (p_LnxWrpFmPortDev->settings.param.portType ==
+ e_FM_PORT_TYPE_TX) {
+ Sprint(p_LnxWrpFmPortDev->name, "%s-port-tx%d",
+ p_LnxWrpFmDev->name, p_LnxWrpFmPortDev->id);
+ p_LnxWrpFmPortDev->minor =
+ p_LnxWrpFmPortDev->id + DEV_FM_TX_PORTS_MINOR_BASE;
+ } else if (p_LnxWrpFmPortDev->settings.param.portType ==
+ e_FM_PORT_TYPE_TX_10G) {
+ Sprint(p_LnxWrpFmPortDev->name, "%s-port-tx%d",
+ p_LnxWrpFmDev->name,
+ p_LnxWrpFmPortDev->id + FM_MAX_NUM_OF_1G_TX_PORTS);
+ p_LnxWrpFmPortDev->minor =
+ p_LnxWrpFmPortDev->id + FM_MAX_NUM_OF_1G_TX_PORTS +
+ DEV_FM_TX_PORTS_MINOR_BASE;
+ } else if (p_LnxWrpFmPortDev->settings.param.portType ==
+ e_FM_PORT_TYPE_OH_HOST_COMMAND) {
+ Sprint(p_LnxWrpFmPortDev->name, "%s-port-oh%d",
+ p_LnxWrpFmDev->name, p_LnxWrpFmPortDev->id);
+ p_LnxWrpFmPortDev->minor =
+ p_LnxWrpFmPortDev->id + DEV_FM_OH_PORTS_MINOR_BASE;
+ p_LnxWrpFmPortDev->h_Dev = FM_PCD_GetHcDevH(p_LnxWrpFmDev->h_PcdDev);
+ } else if (p_LnxWrpFmPortDev->settings.param.portType ==
+ e_FM_PORT_TYPE_OH_OFFLINE_PARSING) {
+ Sprint(p_LnxWrpFmPortDev->name, "%s-port-oh%d",
+ p_LnxWrpFmDev->name, p_LnxWrpFmPortDev->id + 1);
+ p_LnxWrpFmPortDev->minor =
+ p_LnxWrpFmPortDev->id + 1 +
+ DEV_FM_OH_PORTS_MINOR_BASE;
+ }
+
+ device_create(p_LnxWrpFmDev->fm_class, NULL,
+ MKDEV(p_LnxWrpFmDev->major, p_LnxWrpFmPortDev->minor),
+ NULL, p_LnxWrpFmPortDev->name);
+
+ /* create sysfs entries for stats and regs */
+
+ if (fm_port_sysfs_create(dev) != 0) {
+ FreeFmPortDev(p_LnxWrpFmPortDev);
+ REPORT_ERROR(MAJOR, E_INVALID_STATE,
+ ("Unable to create sys entry - fm port!!!"));
+ return -EIO;
+ }
+
+#ifdef FM_TX_INVALID_ECC_ERRATA_10GMAC_A009
+ FM_DisableRamsEcc(p_LnxWrpFmDev->h_Dev);
+#endif /* FM_TX_INVALID_ECC_ERRATA_10GMAC_A009 */
+
+ DBG(TRACE, ("%s probed", p_LnxWrpFmPortDev->name));
+
+ return 0;
+}
+
+static int fm_port_remove(struct platform_device *of_dev)
+{
+ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev;
+ t_LnxWrpFmDev *p_LnxWrpFmDev;
+ struct device *dev;
+
+ dev = &of_dev->dev;
+ p_LnxWrpFmPortDev = dev_get_drvdata(dev);
+
+ fm_port_sysfs_destroy(dev);
+
+ p_LnxWrpFmDev = (t_LnxWrpFmDev *) p_LnxWrpFmPortDev->h_LnxWrpFmDev;
+ device_destroy(p_LnxWrpFmDev->fm_class,
+ MKDEV(p_LnxWrpFmDev->major, p_LnxWrpFmPortDev->minor));
+
+ FreeFmPortDev(p_LnxWrpFmPortDev);
+
+ dev_set_drvdata(dev, NULL);
+
+ return 0;
+}
+
+static const struct of_device_id fm_port_match[] = {
+ {
+ .compatible = "fsl,fman-port-oh"},
+ {
+ .compatible = "fsl,fman-port-1g-rx"},
+ {
+ .compatible = "fsl,fman-port-10g-rx"},
+ {
+ .compatible = "fsl,fman-port-1g-tx"},
+ {
+ .compatible = "fsl,fman-port-10g-tx"},
+ {}
+};
+
+#ifndef MODULE
+MODULE_DEVICE_TABLE(of, fm_port_match);
+#endif /* !MODULE */
+
+static struct platform_driver fm_port_driver = {
+
+ .driver = {
+ .name = "fsl-fman-port",
+ .of_match_table = fm_port_match,
+ .owner = THIS_MODULE,
+ },
+ .probe = fm_port_probe,
+ .remove = fm_port_remove
+};
+
+
+t_Error LNXWRP_FM_Port_Init(void)
+{
+ /* Register to the DTB for basic FM port API */
+ if (platform_driver_register(&fm_port_driver))
+ return E_NO_DEVICE;
+
+ return E_OK;
+}
+
+void LNXWRP_FM_Port_Free(void)
+{
+ platform_driver_unregister(&fm_port_driver);
+}
+
+static int __init __cold fm_port_load(void)
+{
+ if (LNXWRP_FM_Port_Init() != E_OK) {
+ printk(KERN_CRIT "Failed to init FM Ports wrapper!\n");
+ return -ENODEV;
+ }
+
+ printk(KERN_CRIT "Freescale FM Ports module (" __DATE__ ":" __TIME__
+ ")\n");
+
+ return 0;
+}
+
+static void __exit __cold fm_port_unload(void)
+{
+ LNXWRP_FM_Port_Free();
+}
+
+module_init(fm_port_load);
+module_exit(fm_port_unload);
diff --git a/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_ioctls_fm.c b/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_ioctls_fm.c
new file mode 100644
index 0000000..c958675
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_ioctls_fm.c
@@ -0,0 +1,4423 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * 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 Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * 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 Freescale Semiconductor ``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 Freescale Semiconductor 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.
+ */
+
+/*
+ @File lnxwrp_ioctls_fm.c
+ @Author Shlomi Gridish
+ @Description FM Linux wrapper functions.
+*/
+
+/* Linux Headers ------------------- */
+#include <linux/version.h>
+
+#if defined(CONFIG_MODVERSIONS) && !defined(MODVERSIONS)
+#define MODVERSIONS
+#endif
+#ifdef MODVERSIONS
+#include <config/modversions.h>
+#endif /* MODVERSIONS */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/fs.h>
+#include <linux/cdev.h>
+#include <linux/device.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/of_platform.h>
+#include <asm/uaccess.h>
+#include <asm/errno.h>
+#include <sysdev/fsl_soc.h>
+
+#if defined(CONFIG_COMPAT)
+#include <linux/compat.h>
+#endif
+
+#include "part_ext.h"
+#include "fm_ioctls.h"
+#include "fm_pcd_ioctls.h"
+#include "fm_port_ioctls.h"
+#include "fm_vsp_ext.h"
+
+#if defined(CONFIG_COMPAT)
+#include "lnxwrp_ioctls_fm_compat.h"
+#endif
+
+#include "lnxwrp_fm.h"
+
+#include "dpaa_eth.h"
+
+#define CMP_IOC_DEFINE(def) (IOC_##def != def)
+
+/* fm_pcd_ioctls.h === fm_pcd_ext.h assertions */
+#if CMP_IOC_DEFINE(FM_PCD_MAX_NUM_OF_PRIVATE_HDRS)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+#if CMP_IOC_DEFINE(FM_PCD_PRS_NUM_OF_HDRS)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+#if CMP_IOC_DEFINE(FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+#if CMP_IOC_DEFINE(FM_PCD_MAX_NUM_OF_INTERCHANGEABLE_HDRS)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+#if CMP_IOC_DEFINE(FM_PCD_KG_NUM_OF_GENERIC_REGS)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+#if CMP_IOC_DEFINE(FM_PCD_KG_MAX_NUM_OF_EXTRACTS_PER_KEY)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+#if CMP_IOC_DEFINE(FM_PCD_KG_NUM_OF_EXTRACT_MASKS)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+#if CMP_IOC_DEFINE(FM_PCD_KG_NUM_OF_DEFAULT_GROUPS)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+#if CMP_IOC_DEFINE(FM_PCD_PRS_NUM_OF_LABELS)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+#if CMP_IOC_DEFINE(FM_PCD_SW_PRS_SIZE)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+#if CMP_IOC_DEFINE(FM_PCD_PRS_SW_OFFSET)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+#if CMP_IOC_DEFINE(FM_PCD_PRS_SW_PATCHES_SIZE)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+#if CMP_IOC_DEFINE(FM_PCD_PRS_SW_TAIL_SIZE)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+#if CMP_IOC_DEFINE(FM_SW_PRS_MAX_IMAGE_SIZE)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+#if CMP_IOC_DEFINE(FM_PCD_MAX_MANIP_INSRT_TEMPLATE_SIZE)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+#if DPAA_VERSION >= 11
+#if CMP_IOC_DEFINE(FM_PCD_FRM_REPLIC_MAX_NUM_OF_ENTRIES)
+#error Error: please synchronize IOC_ defines!
+#endif
+#endif
+
+#if CMP_IOC_DEFINE(FM_PCD_MAX_NUM_OF_CC_TREES)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+#if CMP_IOC_DEFINE(FM_PCD_MAX_NUM_OF_CC_GROUPS)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+#if CMP_IOC_DEFINE(FM_PCD_MAX_NUM_OF_CC_UNITS)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+#if CMP_IOC_DEFINE(FM_PCD_MAX_NUM_OF_KEYS)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+#if CMP_IOC_DEFINE(FM_PCD_MAX_SIZE_OF_KEY)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+#if CMP_IOC_DEFINE(FM_PCD_MAX_NUM_OF_CC_ENTRIES_IN_GRP)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+#if CMP_IOC_DEFINE(FM_PCD_LAST_KEY_INDEX)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+/* net_ioctls.h === net_ext.h assertions */
+#if CMP_IOC_DEFINE(NET_HEADER_FIELD_PPP_PID)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+#if CMP_IOC_DEFINE(NET_HEADER_FIELD_PPP_COMPRESSED)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+#if CMP_IOC_DEFINE(NET_HEADER_FIELD_PPP_ALL_FIELDS)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+#if CMP_IOC_DEFINE(NET_HEADER_FIELD_PPPoE_ALL_FIELDS)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+#if CMP_IOC_DEFINE(NET_HEADER_FIELD_PPPMUX_ALL_FIELDS)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+#if CMP_IOC_DEFINE(NET_HEADER_FIELD_PPPMUX_SUBFRAME_ALL_FIELDS)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+#if CMP_IOC_DEFINE(NET_HEADER_FIELD_ETH_ALL_FIELDS)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+#if CMP_IOC_DEFINE(NET_HEADER_FIELD_IPv4_ALL_FIELDS)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+#if CMP_IOC_DEFINE(NET_HEADER_FIELD_IPv6_ALL_FIELDS)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+#if CMP_IOC_DEFINE(NET_HEADER_FIELD_ICMP_ALL_FIELDS)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+#if CMP_IOC_DEFINE(NET_HEADER_FIELD_IGMP_ALL_FIELDS)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+#if CMP_IOC_DEFINE(NET_HEADER_FIELD_TCP_ALL_FIELDS)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+#if CMP_IOC_DEFINE(NET_HEADER_FIELD_SCTP_ALL_FIELDS)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+#if CMP_IOC_DEFINE(NET_HEADER_FIELD_DCCP_ALL_FIELDS)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+#if CMP_IOC_DEFINE(NET_HEADER_FIELD_UDP_ALL_FIELDS)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+#if CMP_IOC_DEFINE(NET_HEADER_FIELD_UDP_ENCAP_ESP_ALL_FIELDS)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+#if CMP_IOC_DEFINE(NET_HEADER_FIELD_IPHC_ALL_FIELDS)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+#if CMP_IOC_DEFINE(NET_HEADER_FIELD_SCTP_CHUNK_DATA_ALL_FIELDS)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+#if CMP_IOC_DEFINE(NET_HEADER_FIELD_L2TPv2_ALL_FIELDS)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+#if CMP_IOC_DEFINE(NET_HEADER_FIELD_L2TPv3_CTRL_ALL_FIELDS)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+#if CMP_IOC_DEFINE(NET_HEADER_FIELD_L2TPv3_SESS_ALL_FIELDS)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+#if CMP_IOC_DEFINE(NET_HEADER_FIELD_VLAN_ALL_FIELDS)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+#if CMP_IOC_DEFINE(NET_HEADER_FIELD_LLC_ALL_FIELDS)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+#if CMP_IOC_DEFINE(NET_HEADER_FIELD_NLPID_ALL_FIELDS)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+#if CMP_IOC_DEFINE(NET_HEADER_FIELD_SNAP_ALL_FIELDS)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+#if CMP_IOC_DEFINE(NET_HEADER_FIELD_LLC_SNAP_ALL_FIELDS)
+#warning Error: please synchronize IOC_ defines!
+#endif
+
+#if CMP_IOC_DEFINE(NET_HEADER_FIELD_ARP_ALL_FIELDS)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+#if CMP_IOC_DEFINE(NET_HEADER_FIELD_RFC2684_ALL_FIELDS)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+#if CMP_IOC_DEFINE(NET_HEADER_FIELD_USER_DEFINED_ALL_FIELDS)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+#if CMP_IOC_DEFINE(NET_HEADER_FIELD_PAYLOAD_ALL_FIELDS)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+#if CMP_IOC_DEFINE(NET_HEADER_FIELD_GRE_ALL_FIELDS)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+#if CMP_IOC_DEFINE(NET_HEADER_FIELD_MINENCAP_ALL_FIELDS)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+#if CMP_IOC_DEFINE(NET_HEADER_FIELD_IPSEC_AH_ALL_FIELDS)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+#if CMP_IOC_DEFINE(NET_HEADER_FIELD_IPSEC_ESP_ALL_FIELDS)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+#if CMP_IOC_DEFINE(NET_HEADER_FIELD_MPLS_LABEL_STACK_ALL_FIELDS)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+#if CMP_IOC_DEFINE(NET_HEADER_FIELD_MACSEC_ALL_FIELDS)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+/* fm_ioctls.h === fm_ext.h assertions */
+#if CMP_IOC_DEFINE(FM_MAX_NUM_OF_VALID_PORTS)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+void LnxWrpPCDIOCTLTypeChecking(void)
+{
+ /* fm_ext.h == fm_ioctls.h */
+ ASSERT_COND(sizeof(ioc_fm_port_bandwidth_params) == sizeof(t_FmPortsBandwidthParams));
+ ASSERT_COND(sizeof(ioc_fm_revision_info_t) == sizeof(t_FmRevisionInfo));
+
+ /* fm_pcd_ext.h == fm_pcd_ioctls.h */
+ /*ioc_fm_pcd_counters_params_t : NOT USED */
+ /*ioc_fm_pcd_exception_params_t : private */
+ ASSERT_COND(sizeof(ioc_fm_pcd_prs_label_params_t) == sizeof(t_FmPcdPrsLabelParams));
+ ASSERT_COND(sizeof(ioc_fm_pcd_prs_sw_params_t) == sizeof(t_FmPcdPrsSwParams));
+ /*ioc_fm_pcd_kg_dflt_value_params_t : private */
+ ASSERT_COND(sizeof(ioc_fm_pcd_hdr_protocol_opt_u) == sizeof(u_FmPcdHdrProtocolOpt));
+ ASSERT_COND(sizeof(ioc_fm_pcd_fields_u) == sizeof(t_FmPcdFields));
+ ASSERT_COND(sizeof(ioc_fm_pcd_from_hdr_t) == sizeof(t_FmPcdFromHdr));
+ ASSERT_COND(sizeof(ioc_fm_pcd_from_field_t) == sizeof(t_FmPcdFromField));
+ ASSERT_COND(sizeof(ioc_fm_pcd_distinction_unit_t) == sizeof(t_FmPcdDistinctionUnit));
+#if !defined(CONFIG_COMPAT)
+ /* different alignment */
+ ASSERT_COND(sizeof(ioc_fm_pcd_net_env_params_t) == sizeof(t_FmPcdNetEnvParams) + sizeof(void *));
+#endif
+ ASSERT_COND(sizeof(ioc_fm_pcd_extract_entry_t) == sizeof(t_FmPcdExtractEntry));
+ ASSERT_COND(sizeof(ioc_fm_pcd_kg_extract_mask_t) == sizeof(t_FmPcdKgExtractMask));
+ ASSERT_COND(sizeof(ioc_fm_pcd_kg_extract_dflt_t) == sizeof(t_FmPcdKgExtractDflt));
+ ASSERT_COND(sizeof(ioc_fm_pcd_kg_key_extract_and_hash_params_t) == sizeof(t_FmPcdKgKeyExtractAndHashParams));
+ ASSERT_COND(sizeof(ioc_fm_pcd_kg_extracted_or_params_t) == sizeof(t_FmPcdKgExtractedOrParams));
+ ASSERT_COND(sizeof(ioc_fm_pcd_kg_scheme_counter_t) == sizeof(t_FmPcdKgSchemeCounter));
+ ASSERT_COND(sizeof(ioc_fm_pcd_kg_plcr_profile_t) == sizeof(t_FmPcdKgPlcrProfile));
+#if (DPAA_VERSION >= 11)
+ ASSERT_COND(sizeof(ioc_fm_pcd_kg_storage_profile_t) == sizeof(t_FmPcdKgStorageProfile));
+#endif
+ ASSERT_COND(sizeof(ioc_fm_pcd_kg_cc_t) == sizeof(t_FmPcdKgCc));
+#if !defined(CONFIG_COMPAT)
+ /* different alignment */
+ ASSERT_COND(sizeof(ioc_fm_pcd_kg_scheme_params_t) == sizeof(t_FmPcdKgSchemeParams) + sizeof(void *));
+#endif
+ ASSERT_COND(sizeof(ioc_fm_pcd_cc_next_cc_params_t) == sizeof(t_FmPcdCcNextCcParams));
+ ASSERT_COND(sizeof(ioc_fm_pcd_cc_next_plcr_params_t) == sizeof(t_FmPcdCcNextPlcrParams));
+ ASSERT_COND(sizeof(ioc_fm_pcd_cc_next_enqueue_params_t) == sizeof(t_FmPcdCcNextEnqueueParams));
+ ASSERT_COND(sizeof(ioc_fm_pcd_cc_next_kg_params_t) == sizeof(t_FmPcdCcNextKgParams));
+ ASSERT_COND(sizeof(ioc_fm_pcd_cc_next_engine_params_t) == sizeof(t_FmPcdCcNextEngineParams));
+ ASSERT_COND(sizeof(ioc_fm_pcd_cc_key_params_t) == sizeof(t_FmPcdCcKeyParams));
+ ASSERT_COND(sizeof(ioc_keys_params_t) == sizeof(t_KeysParams));
+#if !defined(CONFIG_COMPAT)
+ /* different alignment */
+ ASSERT_COND(sizeof(ioc_fm_pcd_cc_node_params_t) == sizeof(t_FmPcdCcNodeParams) + sizeof(void *));
+ ASSERT_COND(sizeof(ioc_fm_pcd_hash_table_params_t) == sizeof(t_FmPcdHashTableParams) + sizeof(void *));
+#endif
+ ASSERT_COND(sizeof(ioc_fm_pcd_cc_grp_params_t) == sizeof(t_FmPcdCcGrpParams));
+#if !defined(CONFIG_COMPAT)
+ /* different alignment */
+ ASSERT_COND(sizeof(ioc_fm_pcd_cc_tree_params_t) == sizeof(t_FmPcdCcTreeParams) + sizeof(void *));
+#endif
+ ASSERT_COND(sizeof(ioc_fm_pcd_plcr_byte_rate_mode_param_t) == sizeof(t_FmPcdPlcrByteRateModeParams));
+ ASSERT_COND(sizeof(ioc_fm_pcd_plcr_non_passthrough_alg_param_t) == sizeof(t_FmPcdPlcrNonPassthroughAlgParams));
+ ASSERT_COND(sizeof(ioc_fm_pcd_plcr_next_engine_params_u) == sizeof(u_FmPcdPlcrNextEngineParams));
+ /*ioc_fm_pcd_port_params_t : private */
+ ASSERT_COND(sizeof(ioc_fm_pcd_plcr_profile_params_t) == sizeof(t_FmPcdPlcrProfileParams) + sizeof(void *));
+ /*ioc_fm_pcd_cc_tree_modify_next_engine_params_t : private */
+
+#ifdef FM_CAPWAP_SUPPORT
+#error TODO: unsupported feature
+/*
+ ASSERT_COND(sizeof(TODO) == sizeof(t_FmPcdManipHdrInsrtByTemplateParams));
+ ASSERT_COND(sizeof(TODO) == sizeof(t_CapwapFragmentationParams));
+ ASSERT_COND(sizeof(TODO) == sizeof(t_CapwapReassemblyParams));
+ ASSERT_COND(sizeof(TODO) == sizeof(t_FmPcdManipFragOrReasmParams));
+ ASSERT_COND(sizeof(TODO) == sizeof(t_FmPcdManipHdrRmvByHdrParams));
+*/
+#endif
+
+ /*ioc_fm_pcd_cc_node_modify_next_engine_params_t : private */
+ /*ioc_fm_pcd_cc_node_remove_key_params_t : private */
+ /*ioc_fm_pcd_cc_node_modify_key_and_next_engine_params_t : private */
+ /*ioc_fm_pcd_cc_node_modify_key_params_t : private */
+ /*ioc_fm_manip_hdr_info_t : private */
+ /*ioc_fm_pcd_hash_table_set_t : private */
+ ASSERT_COND(sizeof(ioc_fm_pcd_manip_frag_ip_params_t) == sizeof(t_FmPcdManipFragIpParams));
+ ASSERT_COND(sizeof(ioc_fm_pcd_manip_reassem_ip_params_t) == sizeof(t_FmPcdManipReassemIpParams));
+ ASSERT_COND(sizeof(ioc_fm_pcd_manip_special_offload_ipsec_params_t) == sizeof(t_FmPcdManipSpecialOffloadIPSecParams));
+ ASSERT_COND(sizeof(ioc_fm_pcd_manip_special_offload_params_t) == sizeof(t_FmPcdManipSpecialOffloadParams));
+ ASSERT_COND(sizeof(ioc_fm_pcd_manip_hdr_rmv_generic_params_t) == sizeof(t_FmPcdManipHdrRmvGenericParams));
+ ASSERT_COND(sizeof(ioc_fm_pcd_manip_hdr_insrt_generic_params_t) == sizeof(t_FmPcdManipHdrInsrtGenericParams));
+ ASSERT_COND(sizeof(ioc_fm_pcd_manip_hdr_insrt_params_t) == sizeof(t_FmPcdManipHdrInsrtParams));
+ ASSERT_COND(sizeof(ioc_fm_pcd_manip_hdr_rmv_params_t) == sizeof(t_FmPcdManipHdrRmvParams));
+ ASSERT_COND(sizeof(ioc_fm_pcd_manip_hdr_params_t) == sizeof(t_FmPcdManipHdrParams));
+ ASSERT_COND(sizeof(ioc_fm_pcd_manip_frag_params_t) == sizeof(t_FmPcdManipFragParams));
+ ASSERT_COND(sizeof(ioc_fm_pcd_manip_reassem_params_t) == sizeof(t_FmPcdManipReassemParams));
+#if !defined(CONFIG_COMPAT)
+ /* different alignment */
+ ASSERT_COND(sizeof(ioc_fm_pcd_manip_params_t) == sizeof(t_FmPcdManipParams) + sizeof(void *));
+#endif
+ ASSERT_COND(sizeof(ioc_fm_pcd_manip_reassem_ip_stats_t) == sizeof(t_FmPcdManipReassemIpStats));
+ ASSERT_COND(sizeof(ioc_fm_pcd_manip_frag_ip_stats_t) == sizeof(t_FmPcdManipFragIpStats));
+ ASSERT_COND(sizeof(ioc_fm_pcd_manip_reassem_stats_t) == sizeof(t_FmPcdManipReassemStats));
+ ASSERT_COND(sizeof(ioc_fm_pcd_manip_frag_stats_t) == sizeof(t_FmPcdManipFragStats));
+ ASSERT_COND(sizeof(ioc_fm_pcd_manip_stats_t) == sizeof(t_FmPcdManipStats));
+#if DPAA_VERSION >= 11
+ ASSERT_COND(sizeof(ioc_fm_pcd_frm_replic_group_params_t) == sizeof(t_FmPcdFrmReplicGroupParams) + sizeof(void *));
+#endif
+
+ /* fm_port_ext.h == fm_port_ioctls.h */
+ ASSERT_COND(sizeof(ioc_fm_port_rate_limit_t) == sizeof(t_FmPortRateLimit));
+ ASSERT_COND(sizeof(ioc_fm_port_pcd_params_t) == sizeof(t_FmPortPcdParams));
+ ASSERT_COND(sizeof(ioc_fm_pcd_kg_scheme_select_t) == sizeof(t_FmPcdKgSchemeSelect));
+ ASSERT_COND(sizeof(ioc_fm_pcd_port_schemes_params_t) == sizeof(t_FmPcdPortSchemesParams));
+ ASSERT_COND(sizeof(ioc_fm_pcd_prs_start_t) == sizeof(t_FmPcdPrsStart));
+
+ return;
+}
+
+#define ASSERT_IOC_NET_ENUM(def) ASSERT_COND((unsigned long)e_IOC_NET_##def == (unsigned long)def)
+
+void LnxWrpPCDIOCTLEnumChecking(void)
+{
+ /* net_ext.h == net_ioctls.h : sampling checks */
+ ASSERT_IOC_NET_ENUM(HEADER_TYPE_MACSEC);
+ ASSERT_IOC_NET_ENUM(HEADER_TYPE_PPP);
+ ASSERT_IOC_NET_ENUM(MAX_HEADER_TYPE_COUNT);
+
+ /* fm_ext.h == fm_ioctls.h */
+ ASSERT_COND((unsigned long)e_IOC_FM_PORT_TYPE_DUMMY == (unsigned long)e_FM_PORT_TYPE_DUMMY);
+ ASSERT_COND((unsigned long)e_IOC_EX_MURAM_ECC == (unsigned long)e_FM_EX_MURAM_ECC);
+ ASSERT_COND((unsigned long)e_IOC_FM_COUNTERS_DEQ_CONFIRM == (unsigned long)e_FM_COUNTERS_DEQ_CONFIRM);
+
+ /* fm_pcd_ext.h == fm_pcd_ioctls.h */
+ ASSERT_COND((unsigned long)e_IOC_FM_PCD_PRS_COUNTERS_FPM_COMMAND_STALL_CYCLES == (unsigned long)e_FM_PCD_PRS_COUNTERS_FPM_COMMAND_STALL_CYCLES);
+ ASSERT_COND((unsigned long)e_IOC_FM_PCD_PRS_EXCEPTION_SINGLE_ECC == (unsigned long)e_FM_PCD_PRS_EXCEPTION_SINGLE_ECC);
+ ASSERT_COND((unsigned long)e_IOC_FM_PCD_PRS == (unsigned long)e_FM_PCD_PRS);
+ ASSERT_COND((unsigned long)e_IOC_FM_PCD_EXTRACT_FULL_FIELD == (unsigned long)e_FM_PCD_EXTRACT_FULL_FIELD);
+ ASSERT_COND((unsigned long)e_IOC_FM_PCD_EXTRACT_FROM_FLOW_ID == (unsigned long)e_FM_PCD_EXTRACT_FROM_FLOW_ID);
+ ASSERT_COND((unsigned long)e_IOC_FM_PCD_KG_EXTRACT_PORT_PRIVATE_INFO == (unsigned long)e_FM_PCD_KG_EXTRACT_PORT_PRIVATE_INFO);
+ ASSERT_COND((unsigned long)e_IOC_FM_PCD_KG_DFLT_ILLEGAL == (unsigned long)e_FM_PCD_KG_DFLT_ILLEGAL);
+ ASSERT_COND((unsigned long)e_IOC_FM_PCD_KG_GENERIC_NOT_FROM_DATA == (unsigned long)e_FM_PCD_KG_GENERIC_NOT_FROM_DATA);
+ ASSERT_COND((unsigned long)e_IOC_FM_PCD_HDR_INDEX_LAST == (unsigned long)e_FM_PCD_HDR_INDEX_LAST);
+ ASSERT_COND((unsigned long)e_IOC_FM_PCD_PLCR_SHARED == (unsigned long)e_FM_PCD_PLCR_SHARED);
+ ASSERT_COND((unsigned long)e_IOC_FM_PCD_PLCR_RFC_4115 == (unsigned long)e_FM_PCD_PLCR_RFC_4115);
+ ASSERT_COND((unsigned long)e_IOC_FM_PCD_PLCR_COLOR_AWARE == (unsigned long)e_FM_PCD_PLCR_COLOR_AWARE);
+ ASSERT_COND((unsigned long)e_IOC_FM_PCD_PLCR_OVERRIDE == (unsigned long)e_FM_PCD_PLCR_OVERRIDE);
+ ASSERT_COND((unsigned long)e_IOC_FM_PCD_PLCR_FULL_FRM_LEN == (unsigned long)e_FM_PCD_PLCR_FULL_FRM_LEN);
+ ASSERT_COND((unsigned long)e_IOC_FM_PCD_PLCR_ROLLBACK_FULL_FRM_LEN == (unsigned long)e_FM_PCD_PLCR_ROLLBACK_FULL_FRM_LEN);
+ ASSERT_COND((unsigned long)e_IOC_FM_PCD_PLCR_PACKET_MODE == (unsigned long)e_FM_PCD_PLCR_PACKET_MODE);
+ ASSERT_COND((unsigned long)e_IOC_FM_PCD_DROP_FRAME == (unsigned long)e_FM_PCD_DROP_FRAME);
+ ASSERT_COND((unsigned long)e_IOC_FM_PCD_PLCR_PROFILE_RECOLOURED_RED_PACKET_TOTAL_COUNTER == (unsigned long)e_FM_PCD_PLCR_PROFILE_RECOLOURED_RED_PACKET_TOTAL_COUNTER);
+ ASSERT_COND((unsigned long)e_IOC_FM_PCD_ACTION_INDEXED_LOOKUP == (unsigned long)e_FM_PCD_ACTION_INDEXED_LOOKUP);
+ ASSERT_COND((unsigned long)e_IOC_FM_PORT_PCD_SUPPORT_PRS_AND_KG_AND_PLCR == (unsigned long)e_FM_PORT_PCD_SUPPORT_PRS_AND_KG_AND_PLCR);
+#if !defined(FM_CAPWAP_SUPPORT)
+ ASSERT_COND((unsigned long)e_IOC_FM_PCD_MANIP_INSRT_GENERIC == (unsigned long)e_FM_PCD_MANIP_INSRT_GENERIC);
+ ASSERT_COND((unsigned long)e_IOC_FM_PCD_MANIP_RMV_GENERIC == (unsigned long)e_FM_PCD_MANIP_RMV_GENERIC);
+#else
+ ASSERT_COND((unsigned long)e_IOC_FM_PCD_MANIP_INSRT_BY_TEMPLATE == (unsigned long)e_FM_PCD_MANIP_INSRT_BY_TEMPLATE);
+ ASSERT_COND((unsigned long)e_IOC_FM_PCD_MANIP_RMV_BY_HDR == (unsigned long)e_FM_PCD_MANIP_RMV_BY_HDR);
+ ASSERT_COND((unsigned long)e_IOC_FM_PCD_MANIP_RMV_BY_HDR_FROM_START == (unsigned long)e_FM_PCD_MANIP_RMV_BY_HDR_FROM_START);
+#endif
+ ASSERT_COND((unsigned long)e_IOC_FM_PCD_MANIP_TIME_OUT_BETWEEN_FRAG == (unsigned long)e_FM_PCD_MANIP_TIME_OUT_BETWEEN_FRAG);
+ ASSERT_COND((unsigned long)e_IOC_FM_PCD_MANIP_EIGHT_WAYS_HASH == (unsigned long)e_FM_PCD_MANIP_EIGHT_WAYS_HASH);
+
+#ifdef FM_CAPWAP_SUPPORT
+ ASSERT_COND((unsigned long)e_IOC_FM_PCD_STATS_PER_FLOWID == (unsigned long)e_FM_PCD_STATS_PER_FLOWID);
+#endif
+ ASSERT_COND((unsigned long)e_IOC_FM_PCD_MANIP_SPECIAL_OFFLOAD == (unsigned long)e_FM_PCD_MANIP_SPECIAL_OFFLOAD);
+ ASSERT_COND((unsigned long)e_IOC_FM_PCD_CC_STATS_MODE_FRAME == (unsigned long)e_FM_PCD_CC_STATS_MODE_FRAME);
+ ASSERT_COND((unsigned long)e_IOC_FM_PCD_MANIP_CONTINUE_WITHOUT_FRAG == (unsigned long)e_FM_PCD_MANIP_CONTINUE_WITHOUT_FRAG);
+ ASSERT_COND((unsigned long)e_IOC_FM_PCD_MANIP_SPECIAL_OFFLOAD_IPSEC == (unsigned long)e_FM_PCD_MANIP_SPECIAL_OFFLOAD_IPSEC);
+
+ /* fm_port_ext.h == fm_port_ioctls.h */
+#if !defined(FM_CAPWAP_SUPPORT)
+ ASSERT_COND((unsigned long)e_IOC_FM_PORT_PCD_SUPPORT_PRS_AND_KG_AND_PLCR == (unsigned long)e_FM_PORT_PCD_SUPPORT_PRS_AND_KG_AND_PLCR);
+#else
+ ASSERT_COND((unsigned long)e_IOC_FM_PORT_PCD_SUPPORT_CC_AND_KG_AND_PLCR == (unsigned long)e_FM_PORT_PCD_SUPPORT_CC_AND_KG_AND_PLCR);
+#endif
+ ASSERT_COND((unsigned long)e_IOC_FM_PORT_COUNTERS_DEQ_CONFIRM == (unsigned long)e_FM_PORT_COUNTERS_DEQ_CONFIRM);
+ ASSERT_COND((unsigned long)e_IOC_FM_PORT_DUAL_RATE_LIMITER_SCALE_DOWN_BY_8 == (unsigned long)e_FM_PORT_DUAL_RATE_LIMITER_SCALE_DOWN_BY_8);
+
+ return;
+}
+
+static t_Error LnxwrpFmPcdIOCTL(t_LnxWrpFmDev *p_LnxWrpFmDev, unsigned int cmd, unsigned long arg, bool compat)
+{
+ t_Error err = E_OK;
+
+/*
+Status: PCD API to fmlib (file: drivers/net/dpa/NetCommSw/inc/Peripherals/fm_pcd_ext.h):
+
+ FM_PCD_PrsLoadSw
+ FM_PCD_SetAdvancedOffloadSupport
+ FM_PCD_Enable
+ FM_PCD_Disable
+ FM_PCD_ForceIntr
+ FM_PCD_SetException
+ FM_PCD_KgSetAdditionalDataAfterParsing
+ FM_PCD_KgSetDfltValue
+ FM_PCD_NetEnvCharacteristicsSet
+ FM_PCD_NetEnvCharacteristicsDelete
+ FM_PCD_KgSchemeSet
+ FM_PCD_KgSchemeDelete
+ FM_PCD_MatchTableSet
+ FM_PCD_MatchTableDelete
+ FM_PCD_CcRootBuild
+ FM_PCD_CcRootDelete
+ FM_PCD_PlcrProfileSet
+ FM_PCD_PlcrProfileDelete
+ FM_PCD_CcRootModifyNextEngine
+ FM_PCD_MatchTableModifyNextEngine
+ FM_PCD_MatchTableModifyMissNextEngine
+ FM_PCD_MatchTableRemoveKey
+ FM_PCD_MatchTableAddKey
+ FM_PCD_MatchTableModifyKeyAndNextEngine
+ FM_PCD_HashTableSet
+ FM_PCD_HashTableDelete
+ FM_PCD_HashTableAddKey
+ FM_PCD_HashTableRemoveKey
+ FM_PCD_MatchTableModifyKey
+ FM_PCD_ManipNodeReplace
+ FM_PCD_ManipNodeSet
+ FM_PCD_ManipNodeDelete
+
+Status: not exported, should be thru sysfs
+ FM_PCD_KgSchemeGetCounter
+ FM_PCD_KgSchemeSetCounter
+ FM_PCD_PlcrProfileGetCounter
+ FM_PCD_PlcrProfileSetCounter
+
+Status: not exported
+ FM_PCD_MatchTableFindNRemoveKey
+ FM_PCD_MatchTableFindNModifyNextEngine
+ FM_PCD_MatchTableFindNModifyKeyAndNextEngine
+ FM_PCD_MatchTableFindNModifyKey
+ FM_PCD_MatchTableGetIndexedHashBucket
+ FM_PCD_MatchTableGetNextEngine
+ FM_PCD_MatchTableGetKeyCounter
+
+Status: not exported, would be nice to have
+ FM_PCD_HashTableModifyNextEngine
+ FM_PCD_HashTableModifyMissNextEngine
+ FM_PCD_HashTableGetMissNextEngine
+ FM_PCD_ManipGetStatistics
+
+Status: not exported
+#if DPAA_VERSION >= 11
+
+ FM_VSP_GetStatistics -- it's not available yet
+#endif
+
+Status: feature not supported
+#ifdef FM_CAPWAP_SUPPORT
+#error unsupported feature
+ FM_PCD_StatisticsSetNode
+#endif
+
+ */
+ _fm_ioctl_dbg("cmd:0x%08x(type:0x%02x, nr:%u).\n",
+ cmd, _IOC_TYPE(cmd), _IOC_NR(cmd) - 20);
+
+ switch (cmd)
+ {
+#if defined(CONFIG_COMPAT)
+ case FM_PCD_IOC_PRS_LOAD_SW_COMPAT:
+#endif
+ case FM_PCD_IOC_PRS_LOAD_SW:
+ {
+ ioc_fm_pcd_prs_sw_params_t *param;
+ uint8_t *p_code;
+
+ param = (ioc_fm_pcd_prs_sw_params_t *) XX_Malloc(sizeof(ioc_fm_pcd_prs_sw_params_t));
+ if (!param)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD"));
+
+ memset(param, 0, sizeof(ioc_fm_pcd_prs_sw_params_t));
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ ioc_compat_fm_pcd_prs_sw_params_t *compat_param;
+
+ compat_param = (ioc_compat_fm_pcd_prs_sw_params_t *) XX_Malloc(
+ sizeof(ioc_compat_fm_pcd_prs_sw_params_t));
+ if (!compat_param)
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD"));
+ }
+
+ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_prs_sw_params_t));
+ if (copy_from_user(compat_param,
+ (ioc_compat_fm_pcd_prs_sw_params_t *) compat_ptr(arg),
+ sizeof(ioc_compat_fm_pcd_prs_sw_params_t)))
+ {
+ XX_Free(compat_param);
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+
+ compat_fm_pcd_prs_sw(compat_param, param, COMPAT_US_TO_K);
+
+ XX_Free(compat_param);
+ }
+ else
+#endif
+ {
+ if (copy_from_user(param, (ioc_fm_pcd_prs_sw_params_t *)arg,
+ sizeof(ioc_fm_pcd_prs_sw_params_t)))
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+ }
+
+ if (!param->p_code || !param->size)
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+
+ p_code = (uint8_t *) XX_Malloc(param->size);
+ if (!p_code)
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD"));
+ }
+
+ memset(p_code, 0, param->size);
+ if (copy_from_user(p_code, param->p_code, param->size))
+ {
+ XX_Free(p_code);
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+
+ param->p_code = p_code;
+
+ err = FM_PCD_PrsLoadSw(p_LnxWrpFmDev->h_PcdDev, (t_FmPcdPrsSwParams*)param);
+
+ XX_Free(p_code);
+ XX_Free(param);
+ break;
+ }
+
+ case FM_PCD_IOC_SET_ADVANCED_OFFLOAD_SUPPORT:
+ err = FM_PCD_SetAdvancedOffloadSupport(p_LnxWrpFmDev->h_PcdDev);
+ break;
+
+ case FM_PCD_IOC_ENABLE:
+ err = FM_PCD_Enable(p_LnxWrpFmDev->h_PcdDev);
+ break;
+
+ case FM_PCD_IOC_DISABLE:
+ err = FM_PCD_Disable(p_LnxWrpFmDev->h_PcdDev);
+ break;
+
+ case FM_PCD_IOC_FORCE_INTR:
+ {
+ int exception;
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ if (get_user(exception, (int *) compat_ptr(arg)))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+ else
+#endif
+ {
+ if (get_user(exception, (int *)arg))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+
+ err = FM_PCD_ForceIntr(p_LnxWrpFmDev->h_PcdDev, (e_FmPcdExceptions)exception);
+ break;
+ }
+
+ case FM_PCD_IOC_SET_EXCEPTION:
+ {
+ ioc_fm_pcd_exception_params_t *param;
+
+ param = (ioc_fm_pcd_exception_params_t *) XX_Malloc(
+ sizeof(ioc_fm_pcd_exception_params_t));
+ if (!param)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD"));
+
+ memset(param, 0, sizeof(ioc_fm_pcd_exception_params_t));
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ if (copy_from_user(param, (ioc_fm_pcd_exception_params_t *)compat_ptr(arg),
+ sizeof(ioc_fm_pcd_exception_params_t)))
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+ }
+ else
+#endif
+ {
+ if (copy_from_user(param, (ioc_fm_pcd_exception_params_t *)arg,
+ sizeof(ioc_fm_pcd_exception_params_t)))
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+ }
+
+ err = FM_PCD_SetException(p_LnxWrpFmDev->h_PcdDev, param->exception, param->enable);
+
+ XX_Free(param);
+ break;
+ }
+
+ case FM_PCD_IOC_KG_SET_ADDITIONAL_DATA_AFTER_PARSING:
+ {
+ uint8_t payloadOffset;
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ if (get_user(payloadOffset, (uint8_t*) compat_ptr(arg)))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+ else
+#endif
+ {
+ if (get_user(payloadOffset, (uint8_t*) arg))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+
+ err = FM_PCD_KgSetAdditionalDataAfterParsing(p_LnxWrpFmDev->h_PcdDev, payloadOffset);
+ break;
+ }
+
+ case FM_PCD_IOC_KG_SET_DFLT_VALUE:
+ {
+ ioc_fm_pcd_kg_dflt_value_params_t *param;
+
+ param = (ioc_fm_pcd_kg_dflt_value_params_t *) XX_Malloc(
+ sizeof(ioc_fm_pcd_kg_dflt_value_params_t));
+ if (!param)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD"));
+
+ memset(param, 0, sizeof(ioc_fm_pcd_kg_dflt_value_params_t));
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ if (copy_from_user(param, (ioc_fm_pcd_kg_dflt_value_params_t *)compat_ptr(arg),
+ sizeof(ioc_fm_pcd_kg_dflt_value_params_t)))
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+ }
+ else
+#endif
+ {
+ if (copy_from_user(param, (ioc_fm_pcd_kg_dflt_value_params_t *)arg,
+ sizeof(ioc_fm_pcd_kg_dflt_value_params_t)))
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+ }
+
+ err = FM_PCD_KgSetDfltValue(p_LnxWrpFmDev->h_PcdDev, param->valueId, param->value);
+
+ XX_Free(param);
+ break;
+ }
+
+#if defined(CONFIG_COMPAT)
+ case FM_PCD_IOC_NET_ENV_CHARACTERISTICS_SET_COMPAT:
+#endif
+ case FM_PCD_IOC_NET_ENV_CHARACTERISTICS_SET:
+ {
+ ioc_fm_pcd_net_env_params_t *param;
+
+ param = (ioc_fm_pcd_net_env_params_t *) XX_Malloc(sizeof(ioc_fm_pcd_net_env_params_t));
+ if (!param)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD"));
+
+ memset(param, 0, sizeof(ioc_fm_pcd_net_env_params_t));
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ ioc_compat_fm_pcd_net_env_params_t *compat_param;
+
+ compat_param = (ioc_compat_fm_pcd_net_env_params_t *) XX_Malloc(
+ sizeof(ioc_compat_fm_pcd_net_env_params_t));
+ if (!compat_param)
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD"));
+ }
+
+ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_net_env_params_t));
+ if (copy_from_user(compat_param, (ioc_compat_fm_pcd_net_env_params_t *) compat_ptr(arg),
+ sizeof(ioc_compat_fm_pcd_net_env_params_t)))
+ {
+ XX_Free(compat_param);
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+
+ compat_copy_fm_pcd_net_env(compat_param, param, COMPAT_US_TO_K);
+ XX_Free(compat_param);
+ }
+ else
+#endif
+ {
+ if (copy_from_user(param, (ioc_fm_pcd_net_env_params_t *) arg,
+ sizeof(ioc_fm_pcd_net_env_params_t)))
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+ }
+
+ param->id = FM_PCD_NetEnvCharacteristicsSet(p_LnxWrpFmDev->h_PcdDev, (t_FmPcdNetEnvParams*)param);
+
+ if (!param->id)
+ {
+ XX_Free(param);
+ err = E_INVALID_VALUE;
+ /* Since the LLD has no errno-style error reporting,
+ we're left here with no other option than to report
+ a generic E_INVALID_VALUE */
+ break;
+ }
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ ioc_compat_fm_pcd_net_env_params_t *compat_param;
+
+ compat_param = (ioc_compat_fm_pcd_net_env_params_t *) XX_Malloc(
+ sizeof(ioc_compat_fm_pcd_net_env_params_t));
+ if (!compat_param)
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD"));
+ }
+
+ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_net_env_params_t));
+ compat_copy_fm_pcd_net_env(compat_param, param, COMPAT_K_TO_US);
+
+ if (copy_to_user((ioc_compat_fm_pcd_net_env_params_t *) compat_ptr(arg),
+ compat_param,
+ sizeof(ioc_compat_fm_pcd_net_env_params_t)))
+ err = E_READ_FAILED;
+
+ XX_Free(compat_param);
+ }
+ else
+#endif
+ {
+ if (copy_to_user((ioc_fm_pcd_net_env_params_t *)arg,
+ param,
+ sizeof(ioc_fm_pcd_net_env_params_t)))
+ err = E_READ_FAILED;
+ }
+
+ XX_Free(param);
+ break;
+ }
+
+#if defined(CONFIG_COMPAT)
+ case FM_PCD_IOC_NET_ENV_CHARACTERISTICS_DELETE_COMPAT:
+#endif
+ case FM_PCD_IOC_NET_ENV_CHARACTERISTICS_DELETE:
+ {
+ ioc_fm_obj_t id;
+
+ memset(&id, 0 , sizeof(ioc_fm_obj_t));
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ ioc_compat_fm_obj_t compat_id;
+
+ if (copy_from_user(&compat_id, (ioc_compat_fm_obj_t *) compat_ptr(arg), sizeof(ioc_compat_fm_obj_t)))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+
+ compat_obj_delete(&compat_id, &id);
+ }
+ else
+#endif
+ {
+ if (copy_from_user(&id, (ioc_fm_obj_t *) arg, sizeof(ioc_fm_obj_t)))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+
+ err = FM_PCD_NetEnvCharacteristicsDelete(id.obj);
+ break;
+ }
+
+#if defined(CONFIG_COMPAT)
+ case FM_PCD_IOC_KG_SCHEME_SET_COMPAT:
+#endif
+ case FM_PCD_IOC_KG_SCHEME_SET:
+ {
+ ioc_fm_pcd_kg_scheme_params_t *param;
+
+ param = (ioc_fm_pcd_kg_scheme_params_t *) XX_Malloc(sizeof(ioc_fm_pcd_kg_scheme_params_t));
+ if (!param)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD"));
+
+ memset(param, 0, sizeof(ioc_fm_pcd_kg_scheme_params_t));
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ ioc_compat_fm_pcd_kg_scheme_params_t *compat_param = NULL;
+
+ compat_param = (ioc_compat_fm_pcd_kg_scheme_params_t *) XX_Malloc(
+ sizeof(ioc_compat_fm_pcd_kg_scheme_params_t));
+ if (!compat_param)
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD"));
+ }
+
+ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_kg_scheme_params_t));
+
+ if (copy_from_user(compat_param, (ioc_compat_fm_pcd_kg_scheme_params_t *) compat_ptr(arg),
+ sizeof(ioc_compat_fm_pcd_kg_scheme_params_t)))
+ {
+ XX_Free(compat_param);
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+
+ compat_copy_fm_pcd_kg_scheme(compat_param, param, COMPAT_US_TO_K);
+
+ XX_Free(compat_param);
+ }
+ else
+#endif
+ {
+ if (copy_from_user(param, (ioc_fm_pcd_kg_scheme_params_t *)arg,
+ sizeof(ioc_fm_pcd_kg_scheme_params_t)))
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+ }
+
+ param->id = FM_PCD_KgSchemeSet(p_LnxWrpFmDev->h_PcdDev, (t_FmPcdKgSchemeParams*)param);
+
+ if (!param->id)
+ {
+ XX_Free(param);
+ err = E_INVALID_VALUE;
+ /* Since the LLD has no errno-style error reporting,
+ we're left here with no other option than to report
+ a generic E_INVALID_VALUE */
+ break;
+ }
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ ioc_compat_fm_pcd_kg_scheme_params_t *compat_param;
+
+ compat_param = (ioc_compat_fm_pcd_kg_scheme_params_t *) XX_Malloc(
+ sizeof(ioc_compat_fm_pcd_kg_scheme_params_t));
+ if (!compat_param)
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD"));
+ }
+
+ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_kg_scheme_params_t));
+ compat_copy_fm_pcd_kg_scheme(compat_param, param, COMPAT_K_TO_US);
+ if (copy_to_user((ioc_compat_fm_pcd_kg_scheme_params_t *)compat_ptr(arg),
+ compat_param,
+ sizeof(ioc_compat_fm_pcd_kg_scheme_params_t)))
+ err = E_READ_FAILED;
+
+ XX_Free(compat_param);
+ }
+ else
+#endif
+ {
+ if (copy_to_user((ioc_fm_pcd_kg_scheme_params_t *)arg,
+ param,
+ sizeof(ioc_fm_pcd_kg_scheme_params_t)))
+ err = E_READ_FAILED;
+ }
+
+ XX_Free(param);
+ break;
+ }
+
+#if defined(CONFIG_COMPAT)
+ case FM_PCD_IOC_KG_SCHEME_DELETE_COMPAT:
+#endif
+ case FM_PCD_IOC_KG_SCHEME_DELETE:
+ {
+ ioc_fm_obj_t id;
+
+ memset(&id, 0 , sizeof(ioc_fm_obj_t));
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ ioc_compat_fm_obj_t compat_id;
+
+ if (copy_from_user(&compat_id, (ioc_compat_fm_obj_t *) compat_ptr(arg), sizeof(ioc_compat_fm_obj_t)))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+
+ compat_obj_delete(&compat_id, &id);
+ }
+ else
+#endif
+ {
+ if (copy_from_user(&id, (ioc_fm_obj_t *) arg, sizeof(ioc_fm_obj_t)))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+
+ err = FM_PCD_KgSchemeDelete(id.obj);
+ break;
+ }
+
+#if defined(CONFIG_COMPAT)
+ case FM_PCD_IOC_MATCH_TABLE_SET_COMPAT:
+#endif
+ case FM_PCD_IOC_MATCH_TABLE_SET:
+ {
+ ioc_fm_pcd_cc_node_params_t *param;
+ uint8_t *keys;
+ uint8_t *masks;
+ int i,k;
+
+ param = (ioc_fm_pcd_cc_node_params_t *) XX_Malloc(
+ sizeof(ioc_fm_pcd_cc_node_params_t) +
+ 2 * IOC_FM_PCD_MAX_NUM_OF_KEYS * IOC_FM_PCD_MAX_SIZE_OF_KEY);
+ if (!param)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD"));
+
+ memset(param, 0, sizeof(ioc_fm_pcd_cc_node_params_t) +
+ 2 * IOC_FM_PCD_MAX_NUM_OF_KEYS * IOC_FM_PCD_MAX_SIZE_OF_KEY);
+
+ keys = (uint8_t *) (param + 1);
+ masks = keys + IOC_FM_PCD_MAX_NUM_OF_KEYS * IOC_FM_PCD_MAX_SIZE_OF_KEY;
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ ioc_compat_fm_pcd_cc_node_params_t *compat_param;
+
+ compat_param = (ioc_compat_fm_pcd_cc_node_params_t *) XX_Malloc(
+ sizeof(ioc_compat_fm_pcd_cc_node_params_t) +
+ 2 * IOC_FM_PCD_MAX_NUM_OF_KEYS * IOC_FM_PCD_MAX_SIZE_OF_KEY);
+ if (!compat_param)
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD"));
+ }
+
+ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_cc_node_params_t) +
+ 2 * IOC_FM_PCD_MAX_NUM_OF_KEYS * IOC_FM_PCD_MAX_SIZE_OF_KEY);
+
+ if (copy_from_user(compat_param,
+ (ioc_compat_fm_pcd_cc_node_params_t *)compat_ptr(arg),
+ sizeof(ioc_compat_fm_pcd_cc_node_params_t)))
+ {
+ XX_Free(compat_param);
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+
+ compat_copy_fm_pcd_cc_node(compat_param, param, COMPAT_US_TO_K);
+
+ XX_Free(compat_param);
+ }
+ else
+#endif
+ {
+ if (copy_from_user(param, (ioc_fm_pcd_cc_node_params_t *)arg, sizeof(ioc_fm_pcd_cc_node_params_t)))
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+ }
+
+ ASSERT_COND(param->keys_params.num_of_keys <= IOC_FM_PCD_MAX_NUM_OF_KEYS);
+ ASSERT_COND(param->keys_params.key_size <= IOC_FM_PCD_MAX_SIZE_OF_KEY);
+
+ /* support for indexed lookup */
+ if( !(param->extract_cc_params.type == e_IOC_FM_PCD_EXTRACT_NON_HDR &&
+ param->extract_cc_params.extract_params.extract_non_hdr.src == e_IOC_FM_PCD_EXTRACT_FROM_HASH &&
+ param->extract_cc_params.extract_params.extract_non_hdr.action == e_IOC_FM_PCD_ACTION_INDEXED_LOOKUP))
+ {
+ for (i=0, k=0;
+ i < param->keys_params.num_of_keys;
+ i++, k += IOC_FM_PCD_MAX_SIZE_OF_KEY)
+ {
+ if (param->keys_params.key_params[i].p_key &&
+ param->keys_params.key_size)
+ {
+ if (copy_from_user(&keys[k],
+ param->keys_params.key_params[i].p_key,
+ param->keys_params.key_size))
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+
+ param->keys_params.key_params[i].p_key = &keys[k];
+ }
+
+ if (param->keys_params.key_params[i].p_mask)
+ {
+ if (copy_from_user(&masks[k],
+ param->keys_params.key_params[i].p_mask,
+ param->keys_params.key_size))
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+
+ param->keys_params.key_params[i].p_mask = &masks[k];
+ }
+ }
+ }
+
+ param->id = FM_PCD_MatchTableSet(p_LnxWrpFmDev->h_PcdDev, (t_FmPcdCcNodeParams*)param);
+
+ if (!param->id) {
+ XX_Free(param);
+ err = E_INVALID_VALUE;
+ /* Since the LLD has no errno-style error reporting,
+ we're left here with no other option than to report
+ a generic E_INVALID_VALUE */
+ break;
+ }
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ ioc_compat_fm_pcd_cc_node_params_t *compat_param;
+ compat_param = (ioc_compat_fm_pcd_cc_node_params_t *) XX_Malloc(
+ sizeof(ioc_compat_fm_pcd_cc_node_params_t) +
+ 2 * IOC_FM_PCD_MAX_NUM_OF_KEYS * IOC_FM_PCD_MAX_SIZE_OF_KEY);
+ if (!compat_param)
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD"));
+ }
+
+ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_cc_node_params_t) +
+ 2 * IOC_FM_PCD_MAX_NUM_OF_KEYS * IOC_FM_PCD_MAX_SIZE_OF_KEY);
+ compat_copy_fm_pcd_cc_node(compat_param, param, COMPAT_K_TO_US);
+
+ if (copy_to_user((ioc_compat_fm_pcd_cc_node_params_t *)compat_ptr(arg),
+ compat_param,
+ sizeof(ioc_compat_fm_pcd_cc_node_params_t)))
+ err = E_READ_FAILED;
+
+ XX_Free(compat_param);
+ }
+ else
+#endif
+ {
+ if (copy_to_user((ioc_fm_pcd_cc_node_params_t *)arg,
+ param,
+ sizeof(ioc_fm_pcd_cc_node_params_t)))
+ err = E_READ_FAILED;
+ }
+
+ XX_Free(param);
+ break;
+ }
+
+#if defined(CONFIG_COMPAT)
+ case FM_PCD_IOC_MATCH_TABLE_DELETE_COMPAT:
+#endif
+ case FM_PCD_IOC_MATCH_TABLE_DELETE:
+ {
+ ioc_fm_obj_t id;
+
+ memset(&id, 0 , sizeof(ioc_fm_obj_t));
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ ioc_compat_fm_obj_t compat_id;
+
+ if (copy_from_user(&compat_id, (ioc_compat_fm_obj_t *) compat_ptr(arg), sizeof(ioc_compat_fm_obj_t)))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+
+ compat_obj_delete(&compat_id, &id);
+ }
+ else
+#endif
+ {
+ if (copy_from_user(&id, (ioc_fm_obj_t *) arg, sizeof(ioc_fm_obj_t)))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+
+ err = FM_PCD_MatchTableDelete(id.obj);
+ break;
+ }
+
+#if defined(CONFIG_COMPAT)
+ case FM_PCD_IOC_CC_ROOT_BUILD_COMPAT:
+#endif
+ case FM_PCD_IOC_CC_ROOT_BUILD:
+ {
+ ioc_fm_pcd_cc_tree_params_t *param;
+
+ param = (ioc_fm_pcd_cc_tree_params_t *) XX_Malloc(sizeof(ioc_fm_pcd_cc_tree_params_t));
+ if (!param)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD"));
+
+ memset(param, 0, sizeof(ioc_fm_pcd_cc_tree_params_t));
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ ioc_compat_fm_pcd_cc_tree_params_t *compat_param;
+
+ compat_param = (ioc_compat_fm_pcd_cc_tree_params_t *) XX_Malloc(
+ sizeof(ioc_compat_fm_pcd_cc_tree_params_t));
+ if (!compat_param)
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD"));
+ }
+
+ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_cc_tree_params_t));
+ if (copy_from_user(compat_param,
+ (ioc_compat_fm_pcd_cc_tree_params_t *)compat_ptr(arg),
+ sizeof(ioc_compat_fm_pcd_cc_tree_params_t)))
+ {
+ XX_Free(compat_param);
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+
+ compat_copy_fm_pcd_cc_tree(compat_param, param, COMPAT_US_TO_K);
+
+ XX_Free(compat_param);
+ }
+ else
+#endif
+ {
+ if (copy_from_user(param, (ioc_fm_pcd_cc_tree_params_t *)arg,
+ sizeof(ioc_fm_pcd_cc_tree_params_t)))
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+ }
+
+ param->id = FM_PCD_CcRootBuild(p_LnxWrpFmDev->h_PcdDev, (t_FmPcdCcTreeParams*)param);
+
+ if (!param->id) {
+ XX_Free(param);
+ err = E_INVALID_VALUE;
+ /* Since the LLD has no errno-style error reporting,
+ we're left here with no other option than to report
+ a generic E_INVALID_VALUE */
+ break;
+ }
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ ioc_compat_fm_pcd_cc_tree_params_t *compat_param;
+
+ compat_param = (ioc_compat_fm_pcd_cc_tree_params_t *) XX_Malloc(sizeof(ioc_compat_fm_pcd_cc_tree_params_t));
+ if (!compat_param)
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD"));
+ }
+
+ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_cc_tree_params_t));
+
+ compat_copy_fm_pcd_cc_tree(compat_param, param, COMPAT_K_TO_US);
+
+ if (copy_to_user((ioc_compat_fm_pcd_cc_tree_params_t *)compat_ptr(arg),
+ compat_param,
+ sizeof(ioc_compat_fm_pcd_cc_tree_params_t)))
+ err = E_READ_FAILED;
+
+ XX_Free(compat_param);
+ }
+ else
+#endif
+ {
+ if (copy_to_user((ioc_fm_pcd_cc_tree_params_t *)arg,
+ param,
+ sizeof(ioc_fm_pcd_cc_tree_params_t)))
+ err = E_READ_FAILED;
+ }
+
+ XX_Free(param);
+ break;
+ }
+
+#if defined(CONFIG_COMPAT)
+ case FM_PCD_IOC_CC_ROOT_DELETE_COMPAT:
+#endif
+ case FM_PCD_IOC_CC_ROOT_DELETE:
+ {
+ ioc_fm_obj_t id;
+
+ memset(&id, 0 , sizeof(ioc_fm_obj_t));
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ ioc_compat_fm_obj_t compat_id;
+
+ if (copy_from_user(&compat_id, (ioc_compat_fm_obj_t *) compat_ptr(arg), sizeof(ioc_compat_fm_obj_t)))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+
+ compat_obj_delete(&compat_id, &id);
+ }
+ else
+#endif
+ {
+ if (copy_from_user(&id, (ioc_fm_obj_t *) arg, sizeof(ioc_fm_obj_t)))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+
+ err = FM_PCD_CcRootDelete(id.obj);
+ break;
+ }
+
+#if defined(CONFIG_COMPAT)
+ case FM_PCD_IOC_PLCR_PROFILE_SET_COMPAT:
+#endif
+ case FM_PCD_IOC_PLCR_PROFILE_SET:
+ {
+ ioc_fm_pcd_plcr_profile_params_t *param;
+
+ param = (ioc_fm_pcd_plcr_profile_params_t *) XX_Malloc(
+ sizeof(ioc_fm_pcd_plcr_profile_params_t));
+ if (!param)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD"));
+
+ memset(param, 0, sizeof(ioc_fm_pcd_plcr_profile_params_t));
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ ioc_compat_fm_pcd_plcr_profile_params_t *compat_param;
+
+ compat_param = (ioc_compat_fm_pcd_plcr_profile_params_t *) XX_Malloc(
+ sizeof(ioc_compat_fm_pcd_plcr_profile_params_t));
+ if (!compat_param)
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD"));
+ }
+
+ memset(compat_param, 0, sizeof(ioc_fm_pcd_plcr_profile_params_t));
+ if (copy_from_user(compat_param, (
+ ioc_compat_fm_pcd_plcr_profile_params_t *)compat_ptr(arg),
+ sizeof(ioc_compat_fm_pcd_plcr_profile_params_t)))
+ {
+ XX_Free(compat_param);
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+
+ compat_copy_fm_pcd_plcr_profile(compat_param, param, COMPAT_US_TO_K);
+
+ XX_Free(compat_param);
+ }
+ else
+#endif
+ {
+ if (copy_from_user(param, (ioc_fm_pcd_plcr_profile_params_t *)arg,
+ sizeof(ioc_fm_pcd_plcr_profile_params_t)))
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+ }
+
+ if (!param->modify &&
+ (((t_FmPcdPlcrProfileParams*)param)->id.newParams.profileType != e_FM_PCD_PLCR_SHARED))
+ {
+ t_Handle h_Port;
+ ioc_fm_pcd_port_params_t *port_params;
+
+ port_params = (ioc_fm_pcd_port_params_t*) XX_Malloc(sizeof(ioc_fm_pcd_port_params_t));
+ if (!port_params)
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD"));
+ }
+
+ memset(port_params, 0, sizeof(ioc_fm_pcd_port_params_t));
+ if (copy_from_user(port_params, (ioc_fm_pcd_port_params_t*)((t_FmPcdPlcrProfileParams*)param)->id.newParams.h_FmPort,
+ sizeof(ioc_fm_pcd_port_params_t)))
+ {
+ XX_Free(port_params);
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+
+ switch(port_params->port_type)
+ {
+ case (e_IOC_FM_PORT_TYPE_RX):
+ if (port_params->port_id < FM_MAX_NUM_OF_1G_RX_PORTS) {
+ h_Port = p_LnxWrpFmDev->rxPorts[port_params->port_id].h_Dev;
+ break;
+ }
+ goto invalid_port_id;
+
+ case (e_IOC_FM_PORT_TYPE_RX_10G):
+ if (port_params->port_id < FM_MAX_NUM_OF_10G_RX_PORTS) {
+ h_Port = p_LnxWrpFmDev->rxPorts[port_params->port_id + FM_MAX_NUM_OF_1G_RX_PORTS].h_Dev;
+ break;
+ }
+ goto invalid_port_id;
+
+ case (e_FM_PORT_TYPE_OH_OFFLINE_PARSING):
+ if (port_params->port_id && port_params->port_id < FM_MAX_NUM_OF_OH_PORTS) {
+ h_Port = p_LnxWrpFmDev->opPorts[port_params->port_id - 1].h_Dev;
+ break;
+ }
+ goto invalid_port_id;
+
+ default:
+invalid_port_id:
+ XX_Free(port_params);
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_INVALID_SELECTION, NO_MSG);
+ }
+
+ ((t_FmPcdPlcrProfileParams*)param)->id.newParams.h_FmPort = h_Port;
+ XX_Free(port_params);
+ }
+
+ param->id = FM_PCD_PlcrProfileSet(p_LnxWrpFmDev->h_PcdDev, (t_FmPcdPlcrProfileParams*)param);
+
+ if (!param->id) {
+ XX_Free(param);
+ err = E_INVALID_VALUE;
+ /* Since the LLD has no errno-style error reporting,
+ we're left here with no other option than to report
+ a generic E_INVALID_VALUE */
+ break;
+ }
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ ioc_compat_fm_pcd_plcr_profile_params_t *compat_param;
+
+ compat_param = (ioc_compat_fm_pcd_plcr_profile_params_t *) XX_Malloc(
+ sizeof(ioc_compat_fm_pcd_plcr_profile_params_t));
+ if (!compat_param)
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD"));
+ }
+
+ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_plcr_profile_params_t));
+ compat_copy_fm_pcd_plcr_profile(compat_param, param, COMPAT_K_TO_US);
+ if (copy_to_user((ioc_compat_fm_pcd_plcr_profile_params_t *) compat_ptr(arg),
+ compat_param,
+ sizeof(ioc_compat_fm_pcd_plcr_profile_params_t)))
+ err = E_READ_FAILED;
+
+ XX_Free(compat_param);
+ }
+ else
+#endif
+ {
+ if (copy_to_user((ioc_fm_pcd_plcr_profile_params_t *)arg,
+ param,
+ sizeof(ioc_fm_pcd_plcr_profile_params_t)))
+ err = E_READ_FAILED;
+ }
+
+ XX_Free(param);
+ break;
+ }
+
+#if defined(CONFIG_COMPAT)
+ case FM_PCD_IOC_PLCR_PROFILE_DELETE_COMPAT:
+#endif
+ case FM_PCD_IOC_PLCR_PROFILE_DELETE:
+ {
+ ioc_fm_obj_t id;
+
+ memset(&id, 0 , sizeof(ioc_fm_obj_t));
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ ioc_compat_fm_obj_t compat_id;
+
+ if (copy_from_user(&compat_id, (ioc_compat_fm_obj_t *) compat_ptr(arg), sizeof(ioc_compat_fm_obj_t)))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+
+ compat_obj_delete(&compat_id, &id);
+ }
+ else
+#endif
+ {
+ if (copy_from_user(&id, (ioc_fm_obj_t *) arg, sizeof(ioc_fm_obj_t)))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+
+ err = FM_PCD_PlcrProfileDelete(id.obj);
+ break;
+ }
+
+#if defined(CONFIG_COMPAT)
+ case FM_PCD_IOC_CC_ROOT_MODIFY_NEXT_ENGINE_COMPAT:
+#endif
+ case FM_PCD_IOC_CC_ROOT_MODIFY_NEXT_ENGINE:
+ {
+ ioc_fm_pcd_cc_tree_modify_next_engine_params_t *param;
+
+ param = (ioc_fm_pcd_cc_tree_modify_next_engine_params_t *) XX_Malloc(
+ sizeof(ioc_fm_pcd_cc_tree_modify_next_engine_params_t));
+ if (!param)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD"));
+
+ memset(param, 0, sizeof(ioc_fm_pcd_cc_tree_modify_next_engine_params_t));
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ ioc_compat_fm_pcd_cc_tree_modify_next_engine_params_t *compat_param;
+
+ compat_param = (ioc_compat_fm_pcd_cc_tree_modify_next_engine_params_t *) XX_Malloc(
+ sizeof(ioc_compat_fm_pcd_cc_tree_modify_next_engine_params_t));
+ if (!compat_param)
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD"));
+ }
+
+ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_cc_tree_modify_next_engine_params_t));
+ if (copy_from_user(compat_param, (ioc_compat_fm_pcd_cc_tree_modify_next_engine_params_t *) compat_ptr(arg),
+ sizeof(ioc_compat_fm_pcd_cc_tree_modify_next_engine_params_t)))
+ {
+ XX_Free(compat_param);
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+
+ compat_fm_pcd_cc_tree_modify_next_engine(compat_param, param, COMPAT_US_TO_K);
+
+ XX_Free(compat_param);
+ }
+ else
+#endif
+ {
+ if (copy_from_user(param, (ioc_fm_pcd_cc_tree_modify_next_engine_params_t *)arg,
+ sizeof(ioc_fm_pcd_cc_tree_modify_next_engine_params_t)))
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+ }
+
+ err = FM_PCD_CcRootModifyNextEngine(param->id,
+ param->grp_indx,
+ param->indx,
+ (t_FmPcdCcNextEngineParams*)(&param->cc_next_engine_params));
+
+ XX_Free(param);
+ break;
+ }
+
+#if defined(CONFIG_COMPAT)
+ case FM_PCD_IOC_MATCH_TABLE_MODIFY_NEXT_ENGINE_COMPAT:
+#endif
+ case FM_PCD_IOC_MATCH_TABLE_MODIFY_NEXT_ENGINE:
+ {
+ ioc_fm_pcd_cc_node_modify_next_engine_params_t *param;
+
+ param = (ioc_fm_pcd_cc_node_modify_next_engine_params_t *) XX_Malloc(
+ sizeof(ioc_fm_pcd_cc_node_modify_next_engine_params_t));
+ if (!param)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD"));
+
+ memset(param, 0, sizeof(ioc_fm_pcd_cc_node_modify_next_engine_params_t));
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ ioc_compat_fm_pcd_cc_node_modify_next_engine_params_t *compat_param;
+
+ compat_param = (ioc_compat_fm_pcd_cc_node_modify_next_engine_params_t *) XX_Malloc(
+ sizeof(ioc_compat_fm_pcd_cc_node_modify_next_engine_params_t));
+ if (!compat_param)
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD"));
+ }
+
+ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_cc_node_modify_next_engine_params_t));
+ if (copy_from_user(compat_param, (ioc_compat_fm_pcd_cc_node_modify_next_engine_params_t *) compat_ptr(arg),
+ sizeof(ioc_compat_fm_pcd_cc_node_modify_next_engine_params_t)))
+ {
+ XX_Free(compat_param);
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+
+ compat_copy_fm_pcd_cc_node_modify_next_engine(compat_param, param, COMPAT_US_TO_K);
+
+ XX_Free(compat_param);
+ }
+ else
+#endif
+ {
+ if (copy_from_user(param, (ioc_fm_pcd_cc_node_modify_next_engine_params_t *)arg,
+ sizeof(ioc_fm_pcd_cc_node_modify_next_engine_params_t)))
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+ }
+
+ err = FM_PCD_MatchTableModifyNextEngine(param->id,
+ param->key_indx,
+ (t_FmPcdCcNextEngineParams*)(&param->cc_next_engine_params));
+
+ XX_Free(param);
+ break;
+ }
+
+#if defined(CONFIG_COMPAT)
+ case FM_PCD_IOC_MATCH_TABLE_MODIFY_MISS_NEXT_ENGINE_COMPAT:
+#endif
+ case FM_PCD_IOC_MATCH_TABLE_MODIFY_MISS_NEXT_ENGINE:
+ {
+ ioc_fm_pcd_cc_node_modify_next_engine_params_t *param;
+
+ param = (ioc_fm_pcd_cc_node_modify_next_engine_params_t *) XX_Malloc(
+ sizeof(ioc_fm_pcd_cc_node_modify_next_engine_params_t));
+ if (!param)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD"));
+
+ memset(param, 0, sizeof(ioc_fm_pcd_cc_node_modify_next_engine_params_t));
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ ioc_compat_fm_pcd_cc_node_modify_next_engine_params_t *compat_param;
+
+ compat_param = (ioc_compat_fm_pcd_cc_node_modify_next_engine_params_t *) XX_Malloc(
+ sizeof(ioc_compat_fm_pcd_cc_node_modify_next_engine_params_t));
+ if (!compat_param)
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD"));
+ }
+
+ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_cc_node_modify_next_engine_params_t));
+ if (copy_from_user(compat_param, (ioc_compat_fm_pcd_cc_node_modify_next_engine_params_t *) compat_ptr(arg),
+ sizeof(ioc_compat_fm_pcd_cc_node_modify_next_engine_params_t)))
+ {
+ XX_Free(compat_param);
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+
+ compat_copy_fm_pcd_cc_node_modify_next_engine(compat_param, param, COMPAT_US_TO_K);
+
+ XX_Free(compat_param);
+ }
+ else
+#endif
+ {
+ if (copy_from_user(param, (ioc_fm_pcd_cc_node_modify_next_engine_params_t *) arg,
+ sizeof(ioc_fm_pcd_cc_node_modify_next_engine_params_t)))
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+ }
+
+ err = FM_PCD_MatchTableModifyMissNextEngine(param->id,
+ (t_FmPcdCcNextEngineParams*)(&param->cc_next_engine_params));
+
+ XX_Free(param);
+ break;
+ }
+
+#if defined(CONFIG_COMPAT)
+ case FM_PCD_IOC_MATCH_TABLE_REMOVE_KEY_COMPAT:
+#endif
+ case FM_PCD_IOC_MATCH_TABLE_REMOVE_KEY:
+ {
+ ioc_fm_pcd_cc_node_remove_key_params_t *param;
+
+ param = (ioc_fm_pcd_cc_node_remove_key_params_t *) XX_Malloc(
+ sizeof(ioc_fm_pcd_cc_node_remove_key_params_t));
+ if (!param)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD"));
+
+ memset(param, 0, sizeof(ioc_fm_pcd_cc_node_remove_key_params_t));
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ ioc_compat_fm_pcd_cc_node_remove_key_params_t *compat_param;
+
+ compat_param = (ioc_compat_fm_pcd_cc_node_remove_key_params_t *) XX_Malloc(
+ sizeof(ioc_compat_fm_pcd_cc_node_remove_key_params_t));
+ if (!compat_param)
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD"));
+ }
+
+ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_cc_node_remove_key_params_t));
+ if (copy_from_user(compat_param,
+ (ioc_compat_fm_pcd_cc_node_remove_key_params_t *)compat_ptr(arg),
+ sizeof(ioc_compat_fm_pcd_cc_node_remove_key_params_t)))
+ {
+ XX_Free(compat_param);
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+
+ param->id = compat_ptr(compat_param->id);
+ param->key_indx = compat_param->key_indx;
+
+ XX_Free(compat_param);
+ }
+ else
+#endif
+ {
+ if (copy_from_user(param, (ioc_fm_pcd_cc_node_remove_key_params_t *) arg,
+ sizeof(ioc_fm_pcd_cc_node_remove_key_params_t)))
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+ }
+
+ err = FM_PCD_MatchTableRemoveKey(param->id, param->key_indx);
+
+ XX_Free(param);
+ break;
+ }
+#if defined(CONFIG_COMPAT)
+ case FM_PCD_IOC_MATCH_TABLE_ADD_KEY_COMPAT:
+#endif
+ case FM_PCD_IOC_MATCH_TABLE_ADD_KEY:
+ {
+ ioc_fm_pcd_cc_node_modify_key_and_next_engine_params_t *param;
+
+ param = (ioc_fm_pcd_cc_node_modify_key_and_next_engine_params_t *) XX_Malloc(
+ sizeof(ioc_fm_pcd_cc_node_modify_key_and_next_engine_params_t));
+ if (!param)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD"));
+
+ memset(param, 0, sizeof(ioc_fm_pcd_cc_node_modify_key_and_next_engine_params_t));
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ ioc_compat_fm_pcd_cc_node_modify_key_and_next_engine_params_t *compat_param;
+
+ compat_param = (ioc_compat_fm_pcd_cc_node_modify_key_and_next_engine_params_t *) XX_Malloc(
+ sizeof(ioc_compat_fm_pcd_cc_node_modify_key_and_next_engine_params_t));
+ if (!compat_param)
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD"));
+ }
+
+ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_cc_node_modify_key_and_next_engine_params_t));
+ if (copy_from_user(compat_param,
+ (ioc_compat_fm_pcd_cc_node_modify_key_and_next_engine_params_t *)compat_ptr(arg),
+ sizeof(ioc_compat_fm_pcd_cc_node_modify_key_and_next_engine_params_t)))
+ {
+ XX_Free(compat_param);
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+
+ compat_copy_fm_pcd_cc_node_modify_key_and_next_engine(compat_param, param, COMPAT_US_TO_K);
+
+ XX_Free(compat_param);
+ }
+ else
+#endif
+ {
+ if (copy_from_user(param, (ioc_fm_pcd_cc_node_modify_key_and_next_engine_params_t *)arg,
+ sizeof(ioc_fm_pcd_cc_node_modify_key_and_next_engine_params_t)))
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+ }
+
+ if (param->key_size)
+ {
+ int size = 0;
+
+ if (param->key_params.p_key) size += param->key_size;
+ if (param->key_params.p_mask) size += param->key_size;
+
+ if (size)
+ {
+ uint8_t *p_tmp;
+
+ p_tmp = (uint8_t*) XX_Malloc(size);
+ if (!p_tmp)
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD key/mask"));
+ }
+
+ if (param->key_params.p_key)
+ {
+ if (copy_from_user(p_tmp, param->key_params.p_key, param->key_size))
+ {
+ XX_Free(p_tmp);
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+
+ param->key_params.p_key = p_tmp;
+ }
+
+ if (param->key_params.p_mask)
+ {
+ p_tmp += param->key_size;
+ if (copy_from_user(p_tmp, param->key_params.p_mask, param->key_size))
+ {
+ XX_Free(p_tmp - param->key_size);
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+
+ param->key_params.p_mask = p_tmp;
+ }
+ }
+ }
+
+ err = FM_PCD_MatchTableAddKey(
+ param->id,
+ param->key_indx,
+ param->key_size,
+ (t_FmPcdCcKeyParams*)&param->key_params);
+
+ if (param->key_params.p_key)
+ XX_Free(param->key_params.p_key);
+ XX_Free(param);
+ break;
+ }
+
+#if defined(CONFIG_COMPAT)
+ case FM_PCD_IOC_MATCH_TABLE_MODIFY_KEY_AND_NEXT_ENGINE_COMPAT:
+#endif
+ case FM_PCD_IOC_MATCH_TABLE_MODIFY_KEY_AND_NEXT_ENGINE:
+ {
+ ioc_fm_pcd_cc_node_modify_key_and_next_engine_params_t *param;
+
+ param = (ioc_fm_pcd_cc_node_modify_key_and_next_engine_params_t *) XX_Malloc(
+ sizeof(ioc_fm_pcd_cc_node_modify_key_and_next_engine_params_t));
+ if (!param)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD"));
+
+ memset(param, 0, sizeof(ioc_fm_pcd_cc_node_modify_key_and_next_engine_params_t));
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ ioc_compat_fm_pcd_cc_node_modify_key_and_next_engine_params_t *compat_param;
+
+ compat_param = (ioc_compat_fm_pcd_cc_node_modify_key_and_next_engine_params_t *) XX_Malloc(
+ sizeof(ioc_compat_fm_pcd_cc_node_modify_key_and_next_engine_params_t));
+ if (!compat_param)
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD"));
+ }
+
+ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_cc_node_modify_key_and_next_engine_params_t));
+ if (copy_from_user(compat_param,
+ (ioc_compat_fm_pcd_cc_node_modify_key_and_next_engine_params_t *)compat_ptr(arg),
+ sizeof(ioc_compat_fm_pcd_cc_node_modify_key_and_next_engine_params_t)))
+ {
+ XX_Free(compat_param);
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+
+ compat_copy_fm_pcd_cc_node_modify_key_and_next_engine(compat_param, param, COMPAT_US_TO_K);
+
+ XX_Free(compat_param);
+ }
+ else
+#endif
+ {
+ if (copy_from_user(param, (ioc_fm_pcd_cc_node_modify_key_and_next_engine_params_t *)arg,
+ sizeof(ioc_fm_pcd_cc_node_modify_key_and_next_engine_params_t)))
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+ }
+
+ err = FM_PCD_MatchTableModifyKeyAndNextEngine(param->id,
+ param->key_indx,
+ param->key_size,
+ (t_FmPcdCcKeyParams*)(&param->key_params));
+
+ XX_Free(param);
+ break;
+ }
+#if defined(CONFIG_COMPAT)
+ case FM_PCD_IOC_HASH_TABLE_SET_COMPAT:
+#endif
+ case FM_PCD_IOC_HASH_TABLE_SET:
+ {
+ ioc_fm_pcd_hash_table_params_t *param;
+
+ param = (ioc_fm_pcd_hash_table_params_t*) XX_Malloc(
+ sizeof(ioc_fm_pcd_hash_table_params_t));
+ if (!param)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD"));
+
+ memset(param, 0, sizeof(ioc_fm_pcd_hash_table_params_t));
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ ioc_compat_fm_pcd_hash_table_params_t *compat_param;
+
+ compat_param = (ioc_compat_fm_pcd_hash_table_params_t*) XX_Malloc(
+ sizeof(ioc_compat_fm_pcd_hash_table_params_t));
+ if (!compat_param)
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD"));
+ }
+
+ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_hash_table_params_t));
+ if (copy_from_user(compat_param,
+ (ioc_compat_fm_pcd_hash_table_params_t*)compat_ptr(arg),
+ sizeof(ioc_compat_fm_pcd_hash_table_params_t)))
+ {
+ XX_Free(compat_param);
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+
+ compat_copy_fm_pcd_hash_table(compat_param, param, COMPAT_US_TO_K);
+
+ XX_Free(compat_param);
+ }
+ else
+#endif
+ {
+ if (copy_from_user(param, (ioc_fm_pcd_hash_table_params_t *)arg,
+ sizeof(ioc_fm_pcd_hash_table_params_t)))
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+ }
+
+ param->id = FM_PCD_HashTableSet(p_LnxWrpFmDev->h_PcdDev, (t_FmPcdHashTableParams *) param);
+
+ if (!param->id)
+ {
+ XX_Free(param);
+ err = E_INVALID_VALUE;
+ /* Since the LLD has no errno-style error reporting,
+ we're left here with no other option than to report
+ a generic E_INVALID_VALUE */
+ break;
+ }
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ ioc_compat_fm_pcd_hash_table_params_t *compat_param;
+
+ compat_param = (ioc_compat_fm_pcd_hash_table_params_t*) XX_Malloc(
+ sizeof(ioc_compat_fm_pcd_hash_table_params_t));
+ if (!compat_param)
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD"));
+ }
+
+ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_hash_table_params_t));
+ compat_copy_fm_pcd_hash_table(compat_param, param, COMPAT_K_TO_US);
+ if (copy_to_user((ioc_compat_fm_pcd_hash_table_params_t*) compat_ptr(arg),
+ compat_param,
+ sizeof(ioc_compat_fm_pcd_hash_table_params_t)))
+ err = E_READ_FAILED;
+
+ XX_Free(compat_param);
+ }
+ else
+#endif
+ {
+ if (copy_to_user((ioc_fm_pcd_hash_table_params_t *)arg,
+ param,
+ sizeof(ioc_fm_pcd_hash_table_params_t)))
+ err = E_READ_FAILED;
+ }
+
+ XX_Free(param);
+ break;
+ }
+
+#if defined(CONFIG_COMPAT)
+ case FM_PCD_IOC_HASH_TABLE_DELETE_COMPAT:
+#endif
+ case FM_PCD_IOC_HASH_TABLE_DELETE:
+ {
+ ioc_fm_obj_t id;
+
+ memset(&id, 0, sizeof(ioc_fm_obj_t));
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ ioc_compat_fm_obj_t compat_id;
+
+ if (copy_from_user(&compat_id, (ioc_compat_fm_obj_t *) compat_ptr(arg), sizeof(ioc_compat_fm_obj_t)))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+
+ id.obj = compat_pcd_id2ptr(compat_id.obj);
+ }
+ else
+#endif
+ {
+ if (copy_from_user(&id, (ioc_fm_obj_t *) arg, sizeof(ioc_fm_obj_t)))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+
+ err = FM_PCD_HashTableDelete(id.obj);
+ break;
+ }
+
+#if defined(CONFIG_COMPAT)
+ case FM_PCD_IOC_HASH_TABLE_ADD_KEY_COMPAT:
+#endif
+ case FM_PCD_IOC_HASH_TABLE_ADD_KEY:
+ {
+ ioc_fm_pcd_hash_table_add_key_params_t *param = NULL;
+
+ param = (ioc_fm_pcd_hash_table_add_key_params_t*) XX_Malloc(
+ sizeof(ioc_fm_pcd_hash_table_add_key_params_t));
+ if (!param)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD"));
+
+ memset(param, 0, sizeof(ioc_fm_pcd_hash_table_add_key_params_t));
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ ioc_compat_fm_pcd_hash_table_add_key_params_t *compat_param;
+
+ compat_param = (ioc_compat_fm_pcd_hash_table_add_key_params_t*) XX_Malloc(
+ sizeof(ioc_compat_fm_pcd_hash_table_add_key_params_t));
+ if (!compat_param)
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD"));
+ }
+
+ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_hash_table_add_key_params_t));
+ if (copy_from_user(compat_param,
+ (ioc_compat_fm_pcd_hash_table_add_key_params_t*) compat_ptr(arg),
+ sizeof(ioc_compat_fm_pcd_hash_table_add_key_params_t)))
+ {
+ XX_Free(compat_param);
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+
+ if (compat_param->key_size)
+ {
+ param->p_hash_tbl = compat_pcd_id2ptr(compat_param->p_hash_tbl);
+ param->key_size = compat_param->key_size;
+
+ compat_copy_fm_pcd_cc_key(&compat_param->key_params, &param->key_params, COMPAT_US_TO_K);
+ }
+ else
+ {
+ XX_Free(compat_param);
+ err = E_INVALID_VALUE;
+ break;
+ }
+
+ XX_Free(compat_param);
+ }
+ else
+#endif
+ {
+ if (copy_from_user(param, (ioc_fm_pcd_hash_table_add_key_params_t*) arg,
+ sizeof(ioc_fm_pcd_hash_table_add_key_params_t)))
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+ }
+
+ if (param->key_size)
+ {
+ int size = 0;
+
+ if (param->key_params.p_key) size += param->key_size;
+ if (param->key_params.p_mask) size += param->key_size;
+
+ if (size)
+ {
+ uint8_t *p_tmp;
+
+ p_tmp = (uint8_t*) XX_Malloc(size);
+ if (!p_tmp)
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD key/mask"));
+ }
+
+ if (param->key_params.p_key)
+ {
+ if (copy_from_user(p_tmp, param->key_params.p_key, param->key_size))
+ {
+ XX_Free(p_tmp);
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+
+ param->key_params.p_key = p_tmp;
+ }
+
+ if (param->key_params.p_mask)
+ {
+ p_tmp += param->key_size;
+ if (copy_from_user(p_tmp, param->key_params.p_mask, param->key_size))
+ {
+ XX_Free(p_tmp - param->key_size);
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+
+ param->key_params.p_mask = p_tmp;
+ }
+ }
+ }
+
+ err = FM_PCD_HashTableAddKey(
+ param->p_hash_tbl,
+ param->key_size,
+ (t_FmPcdCcKeyParams*)&param->key_params);
+
+ if (param->key_params.p_key)
+ XX_Free(param->key_params.p_key);
+ XX_Free(param);
+ break;
+ }
+
+#if defined(CONFIG_COMPAT)
+ case FM_PCD_IOC_HASH_TABLE_REMOVE_KEY_COMPAT:
+#endif
+ case FM_PCD_IOC_HASH_TABLE_REMOVE_KEY:
+ {
+ ioc_fm_pcd_hash_table_remove_key_params_t *param = NULL;
+
+ param = (ioc_fm_pcd_hash_table_remove_key_params_t*) XX_Malloc(
+ sizeof(ioc_fm_pcd_hash_table_remove_key_params_t));
+ if (!param)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD"));
+
+ memset(param, 0, sizeof(ioc_fm_pcd_hash_table_remove_key_params_t));
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ ioc_compat_fm_pcd_hash_table_remove_key_params_t *compat_param;
+
+ compat_param = (ioc_compat_fm_pcd_hash_table_remove_key_params_t*) XX_Malloc(
+ sizeof(ioc_compat_fm_pcd_hash_table_remove_key_params_t));
+ if (!compat_param)
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD"));
+ }
+
+ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_hash_table_remove_key_params_t));
+ if (copy_from_user(compat_param,
+ (ioc_compat_fm_pcd_hash_table_remove_key_params_t*) compat_ptr(arg),
+ sizeof(ioc_compat_fm_pcd_hash_table_remove_key_params_t)))
+ {
+ XX_Free(compat_param);
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+
+ param->p_hash_tbl = compat_pcd_id2ptr(compat_param->p_hash_tbl);
+ param->key_size = compat_param->key_size;
+
+ XX_Free(compat_param);
+ }
+ else
+#endif
+ {
+ if (copy_from_user(param, (ioc_fm_pcd_hash_table_remove_key_params_t*)arg,
+ sizeof(ioc_fm_pcd_hash_table_remove_key_params_t)))
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+ }
+
+ if (param->key_size)
+ {
+ uint8_t *p_key;
+
+ p_key = (uint8_t*) XX_Malloc(param->key_size);
+ if (!p_key)
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD"));
+ }
+
+ if (param->p_key && copy_from_user(p_key, param->p_key, param->key_size))
+ {
+ XX_Free(p_key);
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+ param->p_key = p_key;
+ }
+
+ err = FM_PCD_HashTableRemoveKey(
+ param->p_hash_tbl,
+ param->key_size,
+ param->p_key);
+
+ if (param->p_key)
+ XX_Free(param->p_key);
+ XX_Free(param);
+ break;
+ }
+
+#if defined(CONFIG_COMPAT)
+ case FM_PCD_IOC_MATCH_TABLE_MODIFY_KEY_COMPAT:
+#endif
+ case FM_PCD_IOC_MATCH_TABLE_MODIFY_KEY:
+ {
+ ioc_fm_pcd_cc_node_modify_key_params_t *param;
+
+ param = (ioc_fm_pcd_cc_node_modify_key_params_t *) XX_Malloc(
+ sizeof(ioc_fm_pcd_cc_node_modify_key_params_t));
+ if (!param)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD"));
+
+ memset(param, 0, sizeof(ioc_fm_pcd_cc_node_modify_key_params_t));
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ ioc_compat_fm_pcd_cc_node_modify_key_params_t *compat_param;
+
+ compat_param = (ioc_compat_fm_pcd_cc_node_modify_key_params_t *) XX_Malloc(
+ sizeof(ioc_compat_fm_pcd_cc_node_modify_key_params_t));
+ if (!compat_param)
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD"));
+ }
+
+ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_cc_node_modify_key_params_t));
+ if (copy_from_user(compat_param, (ioc_compat_fm_pcd_cc_node_modify_key_params_t *)compat_ptr(arg),
+ sizeof(ioc_compat_fm_pcd_cc_node_modify_key_params_t)))
+ {
+ XX_Free(compat_param);
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+
+ compat_copy_fm_pcd_cc_node_modify_key(compat_param, param, COMPAT_US_TO_K);
+
+ XX_Free(compat_param);
+ }
+ else
+#endif
+ {
+ if (copy_from_user(param, (ioc_fm_pcd_cc_node_modify_key_params_t *)arg,
+ sizeof(ioc_fm_pcd_cc_node_modify_key_params_t)))
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+ }
+
+ if (param->key_size)
+ {
+ int size = 0;
+
+ if (param->p_key) size += param->key_size;
+ if (param->p_mask) size += param->key_size;
+
+ if (size)
+ {
+ uint8_t *p_tmp;
+
+ p_tmp = (uint8_t*) XX_Malloc(size);
+ if (!p_tmp)
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD key/mask"));
+ }
+
+ if (param->p_key)
+ {
+ if (copy_from_user(p_tmp, param->p_key, param->key_size))
+ {
+ XX_Free(p_tmp);
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+
+ param->p_key = p_tmp;
+ }
+
+ if (param->p_mask)
+ {
+ p_tmp += param->key_size;
+ if (copy_from_user(p_tmp, param->p_mask, param->key_size))
+ {
+ XX_Free(p_tmp - param->key_size);
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+
+ param->p_mask = p_tmp;
+ }
+ }
+ }
+
+ err = FM_PCD_MatchTableModifyKey(param->id,
+ param->key_indx,
+ param->key_size,
+ param->p_key,
+ param->p_mask);
+
+ if (param->p_key)
+ XX_Free(param->p_key);
+ else if (param->p_mask)
+ XX_Free(param->p_mask);
+ XX_Free(param);
+ break;
+ }
+
+#if defined(CONFIG_COMPAT)
+ case FM_PCD_IOC_MANIP_NODE_SET_COMPAT:
+#endif
+ case FM_PCD_IOC_MANIP_NODE_SET:
+ {
+ ioc_fm_pcd_manip_params_t *param;
+ uint8_t *p_data = NULL;
+ uint8_t size;
+
+ param = (ioc_fm_pcd_manip_params_t *) XX_Malloc(
+ sizeof(ioc_fm_pcd_manip_params_t));
+
+ if (!param)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD"));
+
+ memset(param, 0, sizeof(ioc_fm_pcd_manip_params_t));
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ ioc_compat_fm_pcd_manip_params_t *compat_param;
+
+ compat_param = (ioc_compat_fm_pcd_manip_params_t *) XX_Malloc(
+ sizeof(ioc_compat_fm_pcd_manip_params_t));
+ if (!compat_param)
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD"));
+ }
+
+ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_manip_params_t));
+ if (copy_from_user(compat_param,
+ (ioc_compat_fm_pcd_manip_params_t *) compat_ptr(arg),
+ sizeof(ioc_compat_fm_pcd_manip_params_t)))
+ {
+ XX_Free(compat_param);
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+
+ compat_fm_pcd_manip_set_node(compat_param, param, COMPAT_US_TO_K);
+
+ XX_Free(compat_param);
+ }
+ else
+#endif
+ {
+ if (copy_from_user(param, (ioc_fm_pcd_manip_params_t *)arg,
+ sizeof(ioc_fm_pcd_manip_params_t)))
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+ }
+
+ if (param->type == e_IOC_FM_PCD_MANIP_HDR)
+ {
+ size = param->u.hdr.insrt_params.u.generic.size;
+ p_data = (uint8_t *) XX_Malloc(size);
+ if (!p_data )
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_NO_MEMORY, NO_MSG);
+ }
+
+ if (param->u.hdr.insrt_params.u.generic.p_data &&
+ copy_from_user(p_data,
+ param->u.hdr.insrt_params.u.generic.p_data, size))
+ {
+ XX_Free(p_data);
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+
+ param->u.hdr.insrt_params.u.generic.p_data = p_data;
+ }
+
+ if (param->id)
+ {
+ /* Security Hole: the user can pass any piece of garbage
+ in 'param->id', and that will go straight through to the LLD,
+ no checks being done by the wrapper! */
+ err = FM_PCD_ManipNodeReplace(
+ (t_Handle) param->id,
+ (t_FmPcdManipParams*) param);
+ if (err)
+ {
+ if (p_data)
+ XX_Free(p_data);
+ XX_Free(param);
+ break;
+ }
+ }
+ else
+ {
+ param->id = FM_PCD_ManipNodeSet(
+ p_LnxWrpFmDev->h_PcdDev,
+ (t_FmPcdManipParams*) param);
+ if (!param->id)
+ {
+ if (p_data)
+ XX_Free(p_data);
+ XX_Free(param);
+ err = E_INVALID_VALUE;
+ /* Since the LLD has no errno-style error reporting,
+ we're left here with no other option than to report
+ a generic E_INVALID_VALUE */
+ break;
+ }
+ }
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ ioc_compat_fm_pcd_manip_params_t *compat_param;
+
+ compat_param = (ioc_compat_fm_pcd_manip_params_t *) XX_Malloc(
+ sizeof(ioc_compat_fm_pcd_manip_params_t));
+ if (!compat_param)
+ {
+ if (p_data)
+ XX_Free(p_data);
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD"));
+ }
+
+ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_manip_params_t));
+
+ compat_fm_pcd_manip_set_node(compat_param, param, COMPAT_K_TO_US);
+
+ if (copy_to_user((ioc_compat_fm_pcd_manip_params_t *) compat_ptr(arg),
+ compat_param,
+ sizeof(ioc_compat_fm_pcd_manip_params_t)))
+ err = E_READ_FAILED;
+
+ XX_Free(compat_param);
+ }
+ else
+#endif
+ {
+ if (copy_to_user((ioc_fm_pcd_manip_params_t *)arg,
+ param, sizeof(ioc_fm_pcd_manip_params_t)))
+ err = E_READ_FAILED;
+ }
+
+ if (p_data)
+ XX_Free(p_data);
+ XX_Free(param);
+ break;
+ }
+
+#if defined(CONFIG_COMPAT)
+ case FM_PCD_IOC_MANIP_NODE_DELETE_COMPAT:
+#endif
+ case FM_PCD_IOC_MANIP_NODE_DELETE:
+ {
+ ioc_fm_obj_t id;
+
+ memset(&id, 0, sizeof(ioc_fm_obj_t));
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ ioc_compat_fm_obj_t compat_id;
+
+ if (copy_from_user(&compat_id, (ioc_compat_fm_obj_t *) compat_ptr(arg), sizeof(ioc_compat_fm_obj_t)))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+
+ compat_obj_delete(&compat_id, &id);
+ }
+ else
+#endif
+ {
+ if (copy_from_user(&id, (ioc_fm_obj_t *) arg, sizeof(ioc_fm_obj_t)))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+
+ err = FM_PCD_ManipNodeDelete(id.obj);
+ break;
+ }
+
+#if (DPAA_VERSION >= 11)
+#if defined(CONFIG_COMPAT)
+ case FM_PCD_IOC_FRM_REPLIC_GROUP_SET_COMPAT:
+#endif
+ case FM_PCD_IOC_FRM_REPLIC_GROUP_SET:
+ {
+ ioc_fm_pcd_frm_replic_group_params_t *param;
+
+ param = (ioc_fm_pcd_frm_replic_group_params_t *) XX_Malloc(
+ sizeof(ioc_fm_pcd_frm_replic_group_params_t));
+ if (!param)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD"));
+
+ memset(param, 0, sizeof(ioc_fm_pcd_plcr_profile_params_t));
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ ioc_compat_fm_pcd_frm_replic_group_params_t
+ *compat_param;
+
+ compat_param =
+ (ioc_compat_fm_pcd_frm_replic_group_params_t *)
+ XX_Malloc(sizeof(*compat_param));
+ if (!compat_param)
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_NO_MEMORY,
+ ("IOCTL FM PCD"));
+ }
+
+ memset(compat_param, 0, sizeof(*compat_param));
+ if (copy_from_user(compat_param,
+ (ioc_compat_fm_pcd_frm_replic_group_params_t *)
+ compat_ptr(arg),
+ sizeof(*compat_param))) {
+ XX_Free(compat_param);
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_READ_FAILED, NO_MSG);
+ }
+
+ compat_copy_fm_pcd_frm_replic_group_params(compat_param,
+ param, COMPAT_US_TO_K);
+
+ XX_Free(compat_param);
+ }
+ else
+#endif
+ {
+ if (copy_from_user(param,
+ (ioc_fm_pcd_frm_replic_group_params_t *)arg,
+ sizeof(ioc_fm_pcd_frm_replic_group_params_t)))
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_READ_FAILED, NO_MSG);
+ }
+ }
+
+ param->id = FM_PCD_FrmReplicSetGroup(p_LnxWrpFmDev->h_PcdDev,
+ (t_FmPcdFrmReplicGroupParams*)param);
+
+ if (!param->id) {
+ XX_Free(param);
+ err = E_INVALID_VALUE;
+ /*
+ * Since the LLD has no errno-style error reporting,
+ * we're left here with no other option than to report
+ * a generic E_INVALID_VALUE
+ */
+ break;
+ }
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ ioc_compat_fm_pcd_frm_replic_group_params_t
+ *compat_param;
+
+ compat_param =
+ (ioc_compat_fm_pcd_frm_replic_group_params_t *)
+ XX_Malloc(sizeof(*compat_param));
+ if (!compat_param)
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_NO_MEMORY,
+ ("IOCTL FM PCD"));
+ }
+
+ memset(compat_param, 0, sizeof(*compat_param));
+ compat_copy_fm_pcd_frm_replic_group_params(compat_param,
+ param, COMPAT_K_TO_US);
+ if (copy_to_user(
+ (ioc_compat_fm_pcd_frm_replic_group_params_t *)
+ compat_ptr(arg),
+ compat_param,
+ sizeof(*compat_param)))
+ err = E_WRITE_FAILED;
+
+ XX_Free(compat_param);
+ }
+ else
+#endif
+ {
+ if (copy_to_user(
+ (ioc_fm_pcd_frm_replic_group_params_t *)arg,
+ param,
+ sizeof(ioc_fm_pcd_frm_replic_group_params_t)))
+ err = E_WRITE_FAILED;
+ }
+
+ XX_Free(param);
+ break;
+ }
+ break;
+
+#if defined(CONFIG_COMPAT)
+ case FM_PCD_IOC_FRM_REPLIC_GROUP_DELETE_COMPAT:
+#endif
+ case FM_PCD_IOC_FRM_REPLIC_GROUP_DELETE:
+ {
+ ioc_fm_obj_t id;
+
+ memset(&id, 0, sizeof(ioc_fm_obj_t));
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ ioc_compat_fm_obj_t compat_id;
+
+ if (copy_from_user(&compat_id,
+ (ioc_compat_fm_obj_t *) compat_ptr(arg),
+ sizeof(ioc_compat_fm_obj_t)))
+ break;
+ compat_obj_delete(&compat_id, &id);
+ }
+ else
+#endif
+ {
+ if (copy_from_user(&id, (ioc_fm_obj_t *) arg,
+ sizeof(ioc_fm_obj_t)))
+ break;
+ }
+
+ return FM_PCD_FrmReplicDeleteGroup(id.obj);
+ }
+ break;
+
+#if defined(CONFIG_COMPAT)
+ case FM_PCD_IOC_FRM_REPLIC_MEMBER_ADD_COMPAT:
+#endif
+ case FM_PCD_IOC_FRM_REPLIC_MEMBER_ADD:
+ {
+ ioc_fm_pcd_frm_replic_member_params_t param;
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ ioc_compat_fm_pcd_frm_replic_member_params_t compat_param;
+
+ if (copy_from_user(&compat_param, compat_ptr(arg), sizeof(compat_param)))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+
+ compat_copy_fm_pcd_frm_replic_member_params(&compat_param, &param, COMPAT_US_TO_K);
+ }
+ else
+#endif
+ if (copy_from_user(&param, (void *)arg, sizeof(param)))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+
+ return FM_PCD_FrmReplicAddMember(param.member.h_replic_group,
+ param.member.member_index,
+ (t_FmPcdCcNextEngineParams*)&param.next_engine_params);
+ }
+ break;
+
+#if defined(CONFIG_COMPAT)
+ case FM_PCD_IOC_FRM_REPLIC_MEMBER_REMOVE_COMPAT:
+#endif
+ case FM_PCD_IOC_FRM_REPLIC_MEMBER_REMOVE:
+ {
+ ioc_fm_pcd_frm_replic_member_t param;
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ ioc_compat_fm_pcd_frm_replic_member_t compat_param;
+
+ if (copy_from_user(&compat_param, compat_ptr(arg), sizeof(compat_param)))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+
+ compat_copy_fm_pcd_frm_replic_member(&compat_param, &param, COMPAT_US_TO_K);
+ }
+ else
+#endif
+ if (copy_from_user(&param, (void *)arg, sizeof(param)))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+
+ return FM_PCD_FrmReplicRemoveMember(param.h_replic_group, param.member_index);
+ }
+ break;
+
+#if defined(CONFIG_COMPAT)
+ case FM_IOC_VSP_CONFIG_COMPAT:
+#endif
+ case FM_IOC_VSP_CONFIG:
+ {
+ ioc_fm_vsp_params_t param;
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ ioc_compat_fm_vsp_params_t compat_param;
+
+ if (copy_from_user(&compat_param, compat_ptr(arg), sizeof(compat_param)))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+
+ compat_copy_fm_vsp_params(&compat_param, &param, COMPAT_US_TO_K);
+ }
+ else
+#endif
+ if (copy_from_user(&param, (void *)arg, sizeof(param)))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ param.p_fm = p_LnxWrpFmDev->h_Dev;
+ param.id = FM_VSP_Config((t_FmVspParams *)&param);
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ ioc_compat_fm_vsp_params_t compat_param;
+
+ memset(&compat_param, 0, sizeof(compat_param));
+ compat_copy_fm_vsp_params(&compat_param, &param, COMPAT_K_TO_US);
+
+ if (copy_to_user(compat_ptr(arg), &compat_param, sizeof(compat_param)))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+ else
+#endif
+ if (copy_to_user((void *)arg, &param, sizeof(param)))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ break;
+ }
+
+#if defined(CONFIG_COMPAT)
+ case FM_IOC_VSP_INIT_COMPAT:
+#endif
+ case FM_IOC_VSP_INIT:
+ {
+ ioc_fm_obj_t id;
+
+ memset(&id, 0, sizeof(ioc_fm_obj_t));
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ ioc_compat_fm_obj_t compat_id;
+
+ if (copy_from_user(&compat_id,
+ (ioc_compat_fm_obj_t *) compat_ptr(arg),
+ sizeof(ioc_compat_fm_obj_t)))
+ break;
+ id.obj = compat_pcd_id2ptr(compat_id.obj);
+ }
+ else
+#endif
+ {
+ if (copy_from_user(&id, (ioc_fm_obj_t *) arg,
+ sizeof(ioc_fm_obj_t)))
+ break;
+ }
+
+ return FM_VSP_Init(id.obj);
+ }
+
+#if defined(CONFIG_COMPAT)
+ case FM_IOC_VSP_FREE_COMPAT:
+#endif
+ case FM_IOC_VSP_FREE:
+ {
+ ioc_fm_obj_t id;
+
+ memset(&id, 0, sizeof(ioc_fm_obj_t));
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ ioc_compat_fm_obj_t compat_id;
+
+ if (copy_from_user(&compat_id,
+ (ioc_compat_fm_obj_t *) compat_ptr(arg),
+ sizeof(ioc_compat_fm_obj_t)))
+ break;
+ compat_obj_delete(&compat_id, &id);
+ }
+ else
+#endif
+ {
+ if (copy_from_user(&id, (ioc_fm_obj_t *) arg,
+ sizeof(ioc_fm_obj_t)))
+ break;
+ }
+
+ return FM_VSP_Free(id.obj);
+ }
+
+#if defined(CONFIG_COMPAT)
+ case FM_IOC_VSP_CONFIG_POOL_DEPLETION_COMPAT:
+#endif
+ case FM_IOC_VSP_CONFIG_POOL_DEPLETION:
+ {
+ ioc_fm_buf_pool_depletion_params_t param;
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ ioc_compat_fm_buf_pool_depletion_params_t compat_param;
+
+ if (copy_from_user(&compat_param, compat_ptr(arg), sizeof(compat_param)))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+
+ compat_copy_fm_buf_pool_depletion_params(&compat_param, &param, COMPAT_US_TO_K);
+ }
+ else
+#endif
+ if (copy_from_user(&param, (void *)arg, sizeof(param)))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+
+ if (FM_VSP_ConfigPoolDepletion(param.p_fm_vsp,
+ (t_FmBufPoolDepletion *)&param.fm_buf_pool_depletion))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+
+ break;
+ }
+
+
+#if defined(CONFIG_COMPAT)
+ case FM_IOC_VSP_CONFIG_BUFFER_PREFIX_CONTENT_COMPAT:
+#endif
+ case FM_IOC_VSP_CONFIG_BUFFER_PREFIX_CONTENT:
+ {
+ ioc_fm_buffer_prefix_content_params_t param;
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ ioc_compat_fm_buffer_prefix_content_params_t compat_param;
+
+ if (copy_from_user(&compat_param, compat_ptr(arg), sizeof(compat_param)))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+
+ compat_copy_fm_buffer_prefix_content_params(&compat_param, &param, COMPAT_US_TO_K);
+ }
+ else
+#endif
+ if (copy_from_user(&param, (void *)arg, sizeof(param)))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+
+ if (FM_VSP_ConfigBufferPrefixContent(param.p_fm_vsp,
+ (t_FmBufferPrefixContent *)&param.fm_buffer_prefix_content))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+
+ break;
+ }
+
+#if defined(CONFIG_COMPAT)
+ case FM_IOC_VSP_CONFIG_NO_SG_COMPAT:
+#endif
+ case FM_IOC_VSP_CONFIG_NO_SG:
+ {
+ ioc_fm_vsp_config_no_sg_params_t param;
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ ioc_compat_fm_vsp_config_no_sg_params_t compat_param;
+
+ if (copy_from_user(&compat_param, compat_ptr(arg), sizeof(compat_param)))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+
+ compat_copy_fm_vsp_config_no_sg_params(&compat_param, &param, COMPAT_US_TO_K);
+ }
+ else
+#endif
+ if (copy_from_user(&param, (void *)arg, sizeof(param)))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+
+ if (FM_VSP_ConfigNoScatherGather(param.p_fm_vsp, param.no_sg))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+
+ break;
+ }
+
+#if defined(CONFIG_COMPAT)
+ case FM_IOC_VSP_GET_BUFFER_PRS_RESULT_COMPAT:
+#endif
+ case FM_IOC_VSP_GET_BUFFER_PRS_RESULT:
+ {
+ ioc_fm_vsp_prs_result_params_t param;
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ ioc_compat_fm_vsp_prs_result_params_t compat_param;
+
+ if (copy_from_user(&compat_param, compat_ptr(arg), sizeof(compat_param)))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+
+ compat_copy_fm_vsp_prs_result_params(&compat_param, &param, COMPAT_US_TO_K);
+ }
+ else
+#endif
+ if (copy_from_user(&param, (void *)arg, sizeof(param)))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+
+ /* this call just adds the parse results offset to p_data */
+ param.p_data = FM_VSP_GetBufferPrsResult(param.p_fm_vsp, param.p_data);
+
+ if (!param.p_data)
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ ioc_compat_fm_vsp_prs_result_params_t compat_param;
+
+ memset(&compat_param, 0, sizeof(compat_param));
+ compat_copy_fm_vsp_prs_result_params(&compat_param, &param, COMPAT_K_TO_US);
+
+ if (copy_to_user(compat_ptr(arg), &compat_param, sizeof(compat_param)))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+ else
+#endif
+ if (copy_to_user((void *)arg, &param, sizeof(param)))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+
+ break;
+ }
+#endif /* (DPAA_VERSION >= 11) */
+
+#ifdef FM_CAPWAP_SUPPORT
+#warning "feature not supported!"
+#if defined(CONFIG_COMPAT)
+ case FM_PCD_IOC_STATISTICS_SET_NODE_COMPAT:
+#endif
+ case FM_PCD_IOC_STATISTICS_SET_NODE:
+ {
+/* ioc_fm_pcd_stats_params_t param;
+ ...
+ param->id = FM_PCD_StatisticsSetNode(p_LnxWrpFmDev->h_PcdDev,
+ (t_FmPcdStatsParams *)&param);
+*/
+ err = E_NOT_SUPPORTED;
+ break;
+ }
+#endif /* FM_CAPWAP_SUPPORT */
+
+ default:
+ RETURN_ERROR(MINOR, E_INVALID_SELECTION,
+ ("invalid ioctl: cmd:0x%08x(type:0x%02x, nr: %d.\n",
+ cmd, _IOC_TYPE(cmd), _IOC_NR(cmd)));
+ }
+
+ if (err)
+ RETURN_ERROR(MINOR, err, ("IOCTL FM PCD"));
+
+ return E_OK;
+}
+
+void FM_Get_Api_Version(ioc_fm_api_version_t *p_version)
+{
+ p_version->version.major = FMD_API_VERSION_MAJOR;
+ p_version->version.minor = FMD_API_VERSION_MINOR;
+ p_version->version.respin = FMD_API_VERSION_RESPIN;
+ p_version->version.reserved = 0;
+}
+
+t_Error LnxwrpFmIOCTL(t_LnxWrpFmDev *p_LnxWrpFmDev, unsigned int cmd, unsigned long arg, bool compat)
+{
+ t_Error err = E_OK;
+
+ switch (cmd)
+ {
+ case FM_IOC_SET_PORTS_BANDWIDTH:
+ {
+ ioc_fm_port_bandwidth_params *param;
+
+ param = (ioc_fm_port_bandwidth_params*) XX_Malloc(sizeof(ioc_fm_port_bandwidth_params));
+ if (!param)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD"));
+
+ memset(param, 0, sizeof(ioc_fm_port_bandwidth_params));
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ if (copy_from_user(param, (ioc_fm_port_bandwidth_params*)compat_ptr(arg), sizeof(ioc_fm_port_bandwidth_params)))
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+ }
+ else
+#endif
+ {
+ if (copy_from_user(param, (ioc_fm_port_bandwidth_params*)arg, sizeof(ioc_fm_port_bandwidth_params)))
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+ }
+
+ err = FM_SetPortsBandwidth(p_LnxWrpFmDev->h_Dev, (t_FmPortsBandwidthParams*) param);
+
+ XX_Free(param);
+ break;
+ }
+
+ case FM_IOC_GET_REVISION:
+ {
+ ioc_fm_revision_info_t *param;
+
+ param = (ioc_fm_revision_info_t *) XX_Malloc(sizeof(ioc_fm_revision_info_t));
+ if (!param)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD"));
+
+ FM_GetRevision(p_LnxWrpFmDev->h_Dev, (t_FmRevisionInfo*)param);
+ /* This one never returns anything other than E_OK */
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ if (copy_to_user((ioc_fm_revision_info_t *)compat_ptr(arg),
+ param,
+ sizeof(ioc_fm_revision_info_t)))
+ RETURN_ERROR(MINOR, E_READ_FAILED, NO_MSG);
+ }
+ else
+#endif
+ {
+ if (copy_to_user((ioc_fm_revision_info_t *)arg,
+ param,
+ sizeof(ioc_fm_revision_info_t)))
+ RETURN_ERROR(MINOR, E_READ_FAILED, NO_MSG);
+ }
+
+ XX_Free(param);
+ break;
+ }
+
+ case FM_IOC_SET_COUNTER:
+ {
+ ioc_fm_counters_params_t *param;
+
+ param = (ioc_fm_counters_params_t *) XX_Malloc(sizeof(ioc_fm_counters_params_t));
+ if (!param)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD"));
+
+ memset(param, 0, sizeof(ioc_fm_counters_params_t));
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ if (copy_from_user(param, (ioc_fm_counters_params_t *)compat_ptr(arg), sizeof(ioc_fm_counters_params_t)))
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+ }
+ else
+#endif
+ {
+ if (copy_from_user(param, (ioc_fm_counters_params_t *)arg, sizeof(ioc_fm_counters_params_t)))
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+ }
+
+ err = FM_ModifyCounter(p_LnxWrpFmDev->h_Dev, param->cnt, param->val);
+
+ XX_Free(param);
+ break;
+ }
+
+ case FM_IOC_GET_COUNTER:
+ {
+ ioc_fm_counters_params_t *param;
+
+ param = (ioc_fm_counters_params_t *) XX_Malloc(sizeof(ioc_fm_counters_params_t));
+ if (!param)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD"));
+
+ memset(param, 0, sizeof(ioc_fm_counters_params_t));
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ if (copy_from_user(param, (ioc_fm_counters_params_t *)compat_ptr(arg), sizeof(ioc_fm_counters_params_t)))
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+ }
+ else
+#endif
+ {
+ if (copy_from_user(param, (ioc_fm_counters_params_t *)arg, sizeof(ioc_fm_counters_params_t)))
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+ }
+
+ param->val = FM_GetCounter(p_LnxWrpFmDev->h_Dev, param->cnt);
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ if (copy_to_user((ioc_fm_counters_params_t *)compat_ptr(arg), param, sizeof(ioc_fm_counters_params_t)))
+ err = E_READ_FAILED;
+ }
+ else
+#endif
+ {
+ if (copy_to_user((ioc_fm_counters_params_t *)arg, param, sizeof(ioc_fm_counters_params_t)))
+ err = E_READ_FAILED;
+ }
+
+ XX_Free(param);
+ break;
+ }
+
+ case FM_IOC_FORCE_INTR:
+ {
+ ioc_fm_exceptions param;
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ if (get_user(param, (ioc_fm_exceptions*) compat_ptr(arg)))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+ else
+#endif
+ {
+ if (get_user(param, (ioc_fm_exceptions*)arg))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+
+ err = FM_ForceIntr(p_LnxWrpFmDev->h_Dev, (e_FmExceptions)param);
+ break;
+ }
+
+ case FM_IOC_GET_API_VERSION:
+ {
+ ioc_fm_api_version_t version;
+
+ FM_Get_Api_Version(&version);
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ if (copy_to_user(
+ (ioc_fm_api_version_t *)compat_ptr(arg),
+ &version, sizeof(version)))
+ err = E_READ_FAILED;
+ }
+ else
+#endif
+ {
+ if (copy_to_user((ioc_fm_api_version_t *)arg,
+ &version, sizeof(version)))
+ err = E_READ_FAILED;
+ }
+ }
+ break;
+
+ case FM_IOC_CTRL_MON_START:
+ {
+ FM_CtrlMonStart(p_LnxWrpFmDev->h_Dev);
+ }
+ break;
+
+ case FM_IOC_CTRL_MON_STOP:
+ {
+ FM_CtrlMonStop(p_LnxWrpFmDev->h_Dev);
+ }
+ break;
+
+#if defined(CONFIG_COMPAT)
+ case FM_IOC_CTRL_MON_GET_COUNTERS_COMPAT:
+#endif
+ case FM_IOC_CTRL_MON_GET_COUNTERS:
+ {
+ ioc_fm_ctrl_mon_counters_params_t param;
+ t_FmCtrlMon mon;
+
+#if defined(CONFIG_COMPAT)
+ ioc_compat_fm_ctrl_mon_counters_params_t compat_param;
+
+ if (compat)
+ {
+ if (copy_from_user(&compat_param, (void *)compat_ptr(arg),
+ sizeof(compat_param)))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+
+ param.fm_ctrl_index = compat_param.fm_ctrl_index;
+ param.p_mon = (fm_ctrl_mon_t *)compat_ptr(compat_param.p_mon);
+ }
+ else
+#endif
+ {
+ if (copy_from_user(&param, (void *)arg, sizeof(ioc_fm_counters_params_t)))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+
+ if (FM_CtrlMonGetCounters(p_LnxWrpFmDev->h_Dev, param.fm_ctrl_index, &mon))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+
+ if (copy_to_user(param.p_mon, &mon, sizeof(t_FmCtrlMon)))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+ break;
+
+ default:
+ return LnxwrpFmPcdIOCTL(p_LnxWrpFmDev, cmd, arg, compat);
+ }
+
+ if (err)
+ RETURN_ERROR(MINOR, E_INVALID_OPERATION, ("IOCTL FM"));
+
+ return E_OK;
+}
+
+t_Error LnxwrpFmPortIOCTL(t_LnxWrpFmPortDev *p_LnxWrpFmPortDev, unsigned int cmd, unsigned long arg, bool compat)
+{
+ t_Error err = E_OK;
+
+ _fm_ioctl_dbg("cmd:0x%08x(type:0x%02x, nr:%u).\n",
+ cmd, _IOC_TYPE(cmd), _IOC_NR(cmd) - 50);
+
+ switch (cmd)
+ {
+ case FM_PORT_IOC_DISABLE:
+ FM_PORT_Disable(p_LnxWrpFmPortDev->h_Dev);
+ /* deliberately ignoring error codes here */
+ return E_OK;
+
+ case FM_PORT_IOC_ENABLE:
+ FM_PORT_Enable(p_LnxWrpFmPortDev->h_Dev);
+ /* deliberately ignoring error codes here */
+ return E_OK;
+
+ case FM_PORT_IOC_SET_ERRORS_ROUTE:
+ {
+ ioc_fm_port_frame_err_select_t errs;
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ if (get_user(errs, (ioc_fm_port_frame_err_select_t*)compat_ptr(arg)))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+ else
+#endif
+ {
+ if (get_user(errs, (ioc_fm_port_frame_err_select_t*)arg))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+
+ err = FM_PORT_SetErrorsRoute(p_LnxWrpFmPortDev->h_Dev, (fmPortFrameErrSelect_t)errs);
+ break;
+ }
+
+ case FM_PORT_IOC_SET_RATE_LIMIT:
+ {
+ ioc_fm_port_rate_limit_t *param;
+
+ param = (ioc_fm_port_rate_limit_t *) XX_Malloc(sizeof(ioc_fm_port_rate_limit_t));
+ if (!param)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PORT"));
+
+ memset(param, 0, sizeof(ioc_fm_port_rate_limit_t));
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ if (copy_from_user(param, (ioc_fm_port_rate_limit_t *)compat_ptr(arg), sizeof(ioc_fm_port_rate_limit_t)))
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+ }
+ else
+#endif
+ {
+ if (copy_from_user(param, (ioc_fm_port_rate_limit_t *)arg, sizeof(ioc_fm_port_rate_limit_t)))
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+ }
+
+ err = FM_PORT_SetRateLimit(p_LnxWrpFmPortDev->h_Dev, (t_FmPortRateLimit *)param);
+
+ XX_Free(param);
+ break;
+ }
+
+ case FM_PORT_IOC_REMOVE_RATE_LIMIT:
+ FM_PORT_DeleteRateLimit(p_LnxWrpFmPortDev->h_Dev);
+ /* deliberately ignoring error codes here */
+ return E_OK;
+
+ case FM_PORT_IOC_ALLOC_PCD_FQIDS:
+ {
+ ioc_fm_port_pcd_fqids_params_t *param;
+
+ if (!p_LnxWrpFmPortDev->pcd_owner_params.cba)
+ RETURN_ERROR(MINOR, E_INVALID_STATE, ("No one to listen on this PCD!!!"));
+
+ param = (ioc_fm_port_pcd_fqids_params_t *) XX_Malloc(sizeof(ioc_fm_port_pcd_fqids_params_t));
+ if (!param)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PORT"));
+
+ memset(param, 0, sizeof(ioc_fm_port_pcd_fqids_params_t));
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ if (copy_from_user(param, (ioc_fm_port_pcd_fqids_params_t *)compat_ptr(arg),
+ sizeof(ioc_fm_port_pcd_fqids_params_t)))
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+ }
+ else
+#endif
+ {
+ if (copy_from_user(param, (ioc_fm_port_pcd_fqids_params_t *)arg,
+ sizeof(ioc_fm_port_pcd_fqids_params_t)))
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+ }
+
+ if (p_LnxWrpFmPortDev->pcd_owner_params.cba(p_LnxWrpFmPortDev->pcd_owner_params.dev,
+ param->num_fqids,
+ param->alignment,
+ &param->base_fqid))
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_INVALID_STATE, ("can't allocate fqids for PCD!!!"));
+ }
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ if (copy_to_user((ioc_fm_port_pcd_fqids_params_t *)compat_ptr(arg),
+ param, sizeof(ioc_fm_port_pcd_fqids_params_t)))
+ err = E_READ_FAILED;
+ }
+ else
+#endif
+ {
+ if (copy_to_user((ioc_fm_port_pcd_fqids_params_t *)arg,
+ param, sizeof(ioc_fm_port_pcd_fqids_params_t)))
+ err = E_READ_FAILED;
+ }
+
+ XX_Free(param);
+ break;
+ }
+
+ case FM_PORT_IOC_FREE_PCD_FQIDS:
+ {
+ uint32_t base_fqid;
+
+ if (!p_LnxWrpFmPortDev->pcd_owner_params.cbf)
+ RETURN_ERROR(MINOR, E_INVALID_STATE, ("No one to listen on this PCD!!!"));
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ if (get_user(base_fqid, (uint32_t*) compat_ptr(arg)))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+ else
+#endif
+ {
+ if (get_user(base_fqid, (uint32_t*)arg))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+
+ if (p_LnxWrpFmPortDev->pcd_owner_params.cbf(p_LnxWrpFmPortDev->pcd_owner_params.dev, base_fqid))
+ err = E_WRITE_FAILED;
+
+ break;
+ }
+
+#if defined(CONFIG_COMPAT)
+ case FM_PORT_IOC_SET_PCD_COMPAT:
+#endif
+ case FM_PORT_IOC_SET_PCD:
+ {
+ ioc_fm_port_pcd_params_t *port_pcd_params;
+ ioc_fm_port_pcd_prs_params_t *port_pcd_prs_params;
+ ioc_fm_port_pcd_cc_params_t *port_pcd_cc_params;
+ ioc_fm_port_pcd_kg_params_t *port_pcd_kg_params;
+ ioc_fm_port_pcd_plcr_params_t *port_pcd_plcr_params;
+
+ port_pcd_params = (ioc_fm_port_pcd_params_t *) XX_Malloc(
+ sizeof(ioc_fm_port_pcd_params_t) +
+ sizeof(ioc_fm_port_pcd_prs_params_t) +
+ sizeof(ioc_fm_port_pcd_cc_params_t) +
+ sizeof(ioc_fm_port_pcd_kg_params_t) +
+ sizeof(ioc_fm_port_pcd_plcr_params_t));
+ if (!port_pcd_params)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PORT"));
+
+ memset(port_pcd_params, 0,
+ sizeof(ioc_fm_port_pcd_params_t) +
+ sizeof(ioc_fm_port_pcd_prs_params_t) +
+ sizeof(ioc_fm_port_pcd_cc_params_t) +
+ sizeof(ioc_fm_port_pcd_kg_params_t) +
+ sizeof(ioc_fm_port_pcd_plcr_params_t));
+
+ port_pcd_prs_params = (ioc_fm_port_pcd_prs_params_t *) (port_pcd_params + 1);
+ port_pcd_cc_params = (ioc_fm_port_pcd_cc_params_t *) (port_pcd_prs_params + 1);
+ port_pcd_kg_params = (ioc_fm_port_pcd_kg_params_t *) (port_pcd_cc_params + 1);
+ port_pcd_plcr_params = (ioc_fm_port_pcd_plcr_params_t *) (port_pcd_kg_params + 1);
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ ioc_compat_fm_port_pcd_params_t *compat_port_pcd_params;
+ ioc_fm_port_pcd_prs_params_t *same_port_pcd_prs_params;
+ ioc_compat_fm_port_pcd_cc_params_t *compat_port_pcd_cc_params;
+ ioc_compat_fm_port_pcd_kg_params_t *compat_port_pcd_kg_params;
+ ioc_compat_fm_port_pcd_plcr_params_t *compat_port_pcd_plcr_params;
+
+ compat_port_pcd_params = (ioc_compat_fm_port_pcd_params_t *) XX_Malloc(
+ sizeof(ioc_compat_fm_port_pcd_params_t) +
+ sizeof(ioc_fm_port_pcd_prs_params_t) +
+ sizeof(ioc_compat_fm_port_pcd_cc_params_t) +
+ sizeof(ioc_compat_fm_port_pcd_kg_params_t) +
+ sizeof(ioc_compat_fm_port_pcd_plcr_params_t));
+ if (!compat_port_pcd_params)
+ {
+ XX_Free(port_pcd_params);
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PORT"));
+ }
+
+ memset(compat_port_pcd_params, 0,
+ sizeof(ioc_compat_fm_port_pcd_params_t) +
+ sizeof(ioc_fm_port_pcd_prs_params_t) +
+ sizeof(ioc_compat_fm_port_pcd_cc_params_t) +
+ sizeof(ioc_compat_fm_port_pcd_kg_params_t) +
+ sizeof(ioc_compat_fm_port_pcd_plcr_params_t));
+ same_port_pcd_prs_params = (ioc_fm_port_pcd_prs_params_t *) (compat_port_pcd_params + 1);
+ compat_port_pcd_cc_params = (ioc_compat_fm_port_pcd_cc_params_t *) (same_port_pcd_prs_params + 1);
+ compat_port_pcd_kg_params = (ioc_compat_fm_port_pcd_kg_params_t *) (compat_port_pcd_cc_params + 1);
+ compat_port_pcd_plcr_params = (ioc_compat_fm_port_pcd_plcr_params_t *) (compat_port_pcd_kg_params + 1);
+
+ if (copy_from_user(compat_port_pcd_params,
+ (ioc_compat_fm_port_pcd_params_t*) compat_ptr(arg),
+ sizeof(ioc_compat_fm_port_pcd_params_t)))
+ err = E_WRITE_FAILED;
+
+ while (!err) /* pseudo-while */
+ {
+ /* set pointers from where to copy from: */
+ port_pcd_params->p_prs_params = compat_ptr(compat_port_pcd_params->p_prs_params); /* same structure */
+ port_pcd_params->p_cc_params = compat_ptr(compat_port_pcd_params->p_cc_params);
+ port_pcd_params->p_kg_params = compat_ptr(compat_port_pcd_params->p_kg_params);
+ port_pcd_params->p_plcr_params = compat_ptr(compat_port_pcd_params->p_plcr_params);
+ port_pcd_params->p_ip_reassembly_manip = compat_ptr(compat_port_pcd_params->p_ip_reassembly_manip);
+
+ /* the prs member is the same, no compat structure...memcpy only */
+ if (port_pcd_params->p_prs_params)
+ {
+ if (copy_from_user(same_port_pcd_prs_params,
+ port_pcd_params->p_prs_params,
+ sizeof(ioc_fm_port_pcd_prs_params_t)))
+ {
+ err = E_WRITE_FAILED;
+ break; /* from pseudo-while */
+ }
+
+ memcpy(port_pcd_prs_params, same_port_pcd_prs_params, sizeof(ioc_fm_port_pcd_prs_params_t));
+ port_pcd_params->p_prs_params = port_pcd_prs_params;
+ }
+
+ if (port_pcd_params->p_cc_params)
+ {
+ if (copy_from_user(compat_port_pcd_cc_params,
+ port_pcd_params->p_cc_params,
+ sizeof(ioc_compat_fm_port_pcd_cc_params_t)))
+ {
+ err = E_WRITE_FAILED;
+ break; /* from pseudo-while */
+ }
+
+ port_pcd_params->p_cc_params = port_pcd_cc_params;
+ }
+
+ if (port_pcd_params->p_kg_params)
+ {
+ if (copy_from_user(compat_port_pcd_kg_params,
+ port_pcd_params->p_kg_params,
+ sizeof(ioc_compat_fm_port_pcd_kg_params_t)))
+ {
+ err = E_WRITE_FAILED;
+ break; /* from pseudo-while */
+ }
+
+ port_pcd_params->p_kg_params = port_pcd_kg_params;
+ }
+
+ if (port_pcd_params->p_plcr_params)
+ {
+ if (copy_from_user(compat_port_pcd_plcr_params,
+ port_pcd_params->p_plcr_params,
+ sizeof(ioc_compat_fm_port_pcd_plcr_params_t)))
+ {
+ err = E_WRITE_FAILED;
+ break; /* from pseudo-while */
+ }
+
+ port_pcd_params->p_plcr_params = port_pcd_plcr_params;
+ }
+
+ break; /* pseudo-while: always run once! */
+ }
+
+ if (!err)
+ compat_copy_fm_port_pcd(compat_port_pcd_params, port_pcd_params, COMPAT_US_TO_K);
+
+ XX_Free(compat_port_pcd_params);
+ }
+ else
+#endif
+ {
+ if (copy_from_user(port_pcd_params,
+ (ioc_fm_port_pcd_params_t*) arg,
+ sizeof(ioc_fm_port_pcd_params_t)))
+ err = E_WRITE_FAILED;
+
+ while (!err) /* pseudo-while */
+ {
+ if (port_pcd_params->p_prs_params)
+ {
+ if (copy_from_user(port_pcd_prs_params,
+ port_pcd_params->p_prs_params,
+ sizeof(ioc_fm_port_pcd_prs_params_t)))
+ {
+ err = E_WRITE_FAILED;
+ break; /* from pseudo-while */
+ }
+
+ port_pcd_params->p_prs_params = port_pcd_prs_params;
+ }
+
+ if (port_pcd_params->p_cc_params)
+ {
+ if (copy_from_user(port_pcd_cc_params,
+ port_pcd_params->p_cc_params,
+ sizeof(ioc_fm_port_pcd_cc_params_t)))
+ {
+ err = E_WRITE_FAILED;
+ break; /* from pseudo-while */
+ }
+
+ port_pcd_params->p_cc_params = port_pcd_cc_params;
+ }
+
+ if (port_pcd_params->p_kg_params)
+ {
+ if (copy_from_user(port_pcd_kg_params,
+ port_pcd_params->p_kg_params,
+ sizeof(ioc_fm_port_pcd_kg_params_t)))
+ {
+ err = E_WRITE_FAILED;
+ break; /* from pseudo-while */
+ }
+
+ port_pcd_params->p_kg_params = port_pcd_kg_params;
+ }
+
+ if (port_pcd_params->p_plcr_params)
+ {
+ if (copy_from_user(port_pcd_plcr_params,
+ port_pcd_params->p_plcr_params,
+ sizeof(ioc_fm_port_pcd_plcr_params_t)))
+ {
+ err = E_WRITE_FAILED;
+ break; /* from pseudo-while */
+ }
+
+ port_pcd_params->p_plcr_params = port_pcd_plcr_params;
+ }
+
+ break; /* pseudo-while: always run once! */
+ }
+ }
+
+ if (!err)
+ err = FM_PORT_SetPCD(p_LnxWrpFmPortDev->h_Dev, (t_FmPortPcdParams*) port_pcd_params);
+
+ XX_Free(port_pcd_params);
+ break;
+ }
+
+ case FM_PORT_IOC_DELETE_PCD:
+ err = FM_PORT_DeletePCD(p_LnxWrpFmPortDev->h_Dev);
+ break;
+
+#if defined(CONFIG_COMPAT)
+ case FM_PORT_IOC_PCD_KG_MODIFY_INITIAL_SCHEME_COMPAT:
+#endif
+ case FM_PORT_IOC_PCD_KG_MODIFY_INITIAL_SCHEME:
+ {
+ ioc_fm_pcd_kg_scheme_select_t *param;
+
+ param = (ioc_fm_pcd_kg_scheme_select_t *) XX_Malloc(
+ sizeof(ioc_fm_pcd_kg_scheme_select_t));
+ if (!param)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PORT"));
+
+ memset(param, 0, sizeof(ioc_fm_pcd_kg_scheme_select_t));
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ ioc_compat_fm_pcd_kg_scheme_select_t *compat_param;
+
+ compat_param = (ioc_compat_fm_pcd_kg_scheme_select_t *) XX_Malloc(
+ sizeof(ioc_compat_fm_pcd_kg_scheme_select_t));
+ if (!compat_param)
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PORT"));
+ }
+
+ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_kg_scheme_select_t));
+ if (copy_from_user(compat_param,
+ (ioc_compat_fm_pcd_kg_scheme_select_t *) compat_ptr(arg),
+ sizeof(ioc_compat_fm_pcd_kg_scheme_select_t)))
+ {
+ XX_Free(compat_param);
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+
+ compat_copy_fm_pcd_kg_scheme_select(compat_param, param, COMPAT_US_TO_K);
+
+ XX_Free(compat_param);
+ }
+ else
+#endif
+ {
+ if (copy_from_user(param, (ioc_fm_pcd_kg_scheme_select_t *)arg,
+ sizeof(ioc_fm_pcd_kg_scheme_select_t)))
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+ }
+
+ err = FM_PORT_PcdKgModifyInitialScheme(p_LnxWrpFmPortDev->h_Dev, (t_FmPcdKgSchemeSelect *)param);
+
+ XX_Free(param);
+ break;
+ }
+
+#if defined(CONFIG_COMPAT)
+ case FM_PORT_IOC_PCD_PLCR_MODIFY_INITIAL_PROFILE_COMPAT:
+#endif
+ case FM_PORT_IOC_PCD_PLCR_MODIFY_INITIAL_PROFILE:
+ {
+ ioc_fm_obj_t id;
+
+ memset(&id, 0 , sizeof(ioc_fm_obj_t));
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ ioc_compat_fm_obj_t compat_id;
+
+ if (copy_from_user(&compat_id, (ioc_compat_fm_obj_t *) compat_ptr(arg), sizeof(ioc_compat_fm_obj_t)))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+
+ id.obj = compat_ptr(compat_id.obj);
+ }
+ else
+#endif
+ {
+ if (copy_from_user(&id, (ioc_fm_obj_t *) arg, sizeof(ioc_fm_obj_t)))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+
+ err = FM_PORT_PcdPlcrModifyInitialProfile(p_LnxWrpFmPortDev->h_Dev, id.obj);
+ break;
+ }
+
+#if defined(CONFIG_COMPAT)
+ case FM_PORT_IOC_PCD_KG_BIND_SCHEMES_COMPAT:
+#endif
+ case FM_PORT_IOC_PCD_KG_BIND_SCHEMES:
+ {
+ ioc_fm_pcd_port_schemes_params_t *param;
+
+ param = (ioc_fm_pcd_port_schemes_params_t *) XX_Malloc(
+ sizeof(ioc_fm_pcd_port_schemes_params_t));
+ if (!param)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PORT"));
+
+ memset(param, 0 , sizeof(ioc_fm_pcd_port_schemes_params_t));
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ ioc_compat_fm_pcd_port_schemes_params_t compat_param;
+
+ if (copy_from_user(&compat_param,
+ (ioc_compat_fm_pcd_port_schemes_params_t *) compat_ptr(arg),
+ sizeof(ioc_compat_fm_pcd_port_schemes_params_t)))
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+
+ compat_copy_fm_pcd_kg_schemes_params(&compat_param, param, COMPAT_US_TO_K);
+ }
+ else
+#endif
+ {
+ if (copy_from_user(param, (ioc_fm_pcd_port_schemes_params_t *) arg,
+ sizeof(ioc_fm_pcd_port_schemes_params_t)))
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+ }
+
+ err = FM_PORT_PcdKgBindSchemes(p_LnxWrpFmPortDev->h_Dev, (t_FmPcdPortSchemesParams *)param);
+
+ XX_Free(param);
+ break;
+ }
+
+#if defined(CONFIG_COMPAT)
+ case FM_PORT_IOC_PCD_KG_UNBIND_SCHEMES_COMPAT:
+#endif
+ case FM_PORT_IOC_PCD_KG_UNBIND_SCHEMES:
+ {
+ ioc_fm_pcd_port_schemes_params_t *param;
+
+ param = (ioc_fm_pcd_port_schemes_params_t *) XX_Malloc(
+ sizeof(ioc_fm_pcd_port_schemes_params_t));
+ if (!param)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PORT"));
+
+ memset(param, 0 , sizeof(ioc_fm_pcd_port_schemes_params_t));
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ ioc_compat_fm_pcd_port_schemes_params_t compat_param;
+
+ if (copy_from_user(&compat_param,
+ (ioc_compat_fm_pcd_port_schemes_params_t *) compat_ptr(arg),
+ sizeof(ioc_compat_fm_pcd_port_schemes_params_t)))
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+
+ compat_copy_fm_pcd_kg_schemes_params(&compat_param, param, COMPAT_US_TO_K);
+ }
+ else
+#endif
+ {
+ if (copy_from_user(param, (ioc_fm_pcd_port_schemes_params_t *) arg,
+ sizeof(ioc_fm_pcd_port_schemes_params_t)))
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+ }
+
+ err = FM_PORT_PcdKgUnbindSchemes(p_LnxWrpFmPortDev->h_Dev, (t_FmPcdPortSchemesParams *)param);
+
+ XX_Free(param);
+ break;
+ }
+
+ case FM_PORT_IOC_PCD_PRS_MODIFY_START_OFFSET:
+ {
+ ioc_fm_pcd_prs_start_t *param;
+
+ param = (ioc_fm_pcd_prs_start_t *) XX_Malloc(sizeof(ioc_fm_pcd_prs_start_t));
+ if (!param)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PORT"));
+
+ memset(param, 0, sizeof(ioc_fm_pcd_prs_start_t));
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ if (copy_from_user(param, (ioc_fm_pcd_prs_start_t *)compat_ptr(arg),
+ sizeof(ioc_fm_pcd_prs_start_t)))
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+ }
+ else
+#endif
+ {
+ if (copy_from_user(param, (ioc_fm_pcd_prs_start_t *)arg,
+ sizeof(ioc_fm_pcd_prs_start_t)))
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+ }
+
+ err = FM_PORT_PcdPrsModifyStartOffset(p_LnxWrpFmPortDev->h_Dev, (t_FmPcdPrsStart *)param);
+
+ XX_Free(param);
+ break;
+ }
+
+ case FM_PORT_IOC_PCD_PLCR_ALLOC_PROFILES:
+ {
+ uint16_t num;
+ if (get_user(num, (uint16_t*) arg))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+
+ err = FM_PORT_PcdPlcrAllocProfiles(p_LnxWrpFmPortDev->h_Dev, num);
+ break;
+ }
+
+ case FM_PORT_IOC_PCD_PLCR_FREE_PROFILES:
+ err = FM_PORT_PcdPlcrFreeProfiles(p_LnxWrpFmPortDev->h_Dev);
+ break;
+
+ case FM_PORT_IOC_DETACH_PCD:
+ err = FM_PORT_DetachPCD(p_LnxWrpFmPortDev->h_Dev);
+ break;
+
+ case FM_PORT_IOC_ATTACH_PCD:
+ err = FM_PORT_AttachPCD(p_LnxWrpFmPortDev->h_Dev);
+ break;
+
+#if defined(CONFIG_COMPAT)
+ case FM_PORT_IOC_PCD_CC_MODIFY_TREE_COMPAT:
+#endif
+ case FM_PORT_IOC_PCD_CC_MODIFY_TREE:
+ {
+ ioc_fm_obj_t id;
+
+ memset(&id, 0 , sizeof(ioc_fm_obj_t));
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ ioc_compat_fm_obj_t compat_id;
+
+ if (copy_from_user(&compat_id, (ioc_compat_fm_obj_t *) compat_ptr(arg), sizeof(ioc_compat_fm_obj_t)))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+
+ compat_copy_fm_port_pcd_modify_tree(&compat_id, &id, COMPAT_US_TO_K);
+ }
+ else
+#endif
+ {
+ if (copy_from_user(&id, (ioc_fm_obj_t *) arg, sizeof(ioc_fm_obj_t)))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+
+ err = FM_PORT_PcdCcModifyTree(p_LnxWrpFmPortDev->h_Dev, id.obj);
+ break;
+ }
+
+ case FM_PORT_IOC_ADD_CONGESTION_GRPS:
+ case FM_PORT_IOC_REMOVE_CONGESTION_GRPS:
+ {
+ ioc_fm_port_congestion_groups_t *param;
+
+ param = (ioc_fm_port_congestion_groups_t*) XX_Malloc(sizeof(ioc_fm_port_congestion_groups_t));
+ if (!param)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PORT"));
+
+ memset(param, 0, sizeof(ioc_fm_port_congestion_groups_t));
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ if (copy_from_user(param, (t_FmPortCongestionGrps*) compat_ptr(arg),
+ sizeof(t_FmPortCongestionGrps)))
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+ }
+ else
+#endif /* CONFIG_COMPAT */
+ {
+ if (copy_from_user(param, (t_FmPortCongestionGrps*) arg,
+ sizeof(t_FmPortCongestionGrps)))
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+ }
+
+ err = (cmd == FM_PORT_IOC_ADD_CONGESTION_GRPS)
+ ? FM_PORT_AddCongestionGrps(p_LnxWrpFmPortDev->h_Dev, (t_FmPortCongestionGrps*) param)
+ : FM_PORT_RemoveCongestionGrps(p_LnxWrpFmPortDev->h_Dev, (t_FmPortCongestionGrps*) param)
+ ;
+
+ XX_Free(param);
+ break;
+ }
+
+ case FM_PORT_IOC_ADD_RX_HASH_MAC_ADDR:
+ case FM_PORT_IOC_REMOVE_RX_HASH_MAC_ADDR:
+ {
+ ioc_fm_port_mac_addr_params_t *param;
+
+ param = (ioc_fm_port_mac_addr_params_t*) XX_Malloc(
+ sizeof(ioc_fm_port_mac_addr_params_t));
+ if (!param)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PORT"));
+
+ memset(param, 0, sizeof(ioc_fm_port_mac_addr_params_t));
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ if (copy_from_user(param, (ioc_fm_port_mac_addr_params_t*) compat_ptr(arg),
+ sizeof(ioc_fm_port_mac_addr_params_t)))
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+ }
+ else
+#endif /* CONFIG_COMPAT */
+ {
+ if (copy_from_user(param, (ioc_fm_port_mac_addr_params_t*) arg,
+ sizeof(ioc_fm_port_mac_addr_params_t)))
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+ }
+
+ if (p_LnxWrpFmPortDev->pcd_owner_params.dev)
+ {
+ struct net_device *net_dev = dev_get_drvdata(p_LnxWrpFmPortDev->pcd_owner_params.dev);
+
+ if (net_dev)
+ {
+ struct dpa_priv_s *priv = netdev_priv(net_dev);
+
+ if (priv)
+ {
+ struct mac_device *mac_dev = priv->mac_dev;
+
+ if (mac_dev)
+ {
+ void *mac_handle = mac_dev->get_mac_handle(mac_dev);
+
+ err = (cmd == FM_PORT_IOC_ADD_RX_HASH_MAC_ADDR)
+ ? FM_MAC_AddHashMacAddr((t_Handle) mac_handle, (t_EnetAddr*) param)
+ : FM_MAC_RemoveHashMacAddr((t_Handle) mac_handle, (t_EnetAddr*) param)
+ ;
+ }
+ else
+ {
+ err = E_NOT_AVAILABLE;
+ REPORT_ERROR(MINOR, err, ("Attempt to add/remove hash MAC addr. to/from MAC-less port!"));
+ }
+ }
+ else
+ /* Not possible, set err nevertheless: */
+ err = E_NOT_AVAILABLE;
+ }
+ else
+ {
+ err = E_NOT_AVAILABLE;
+ REPORT_ERROR(MINOR, err, ("No net device (and no MAC!) associated to this port!"));
+ }
+ }
+ else
+ {
+ err = E_NOT_AVAILABLE;
+ REPORT_ERROR(MINOR, err, ("Port not initialized or other error!?!?"));
+ }
+
+ XX_Free(param);
+ break;
+ }
+
+ case FM_PORT_IOC_SET_TX_PAUSE_FRAMES:
+ {
+ t_LnxWrpFmDev *p_LnxWrpFmDev =
+ (t_LnxWrpFmDev *)p_LnxWrpFmPortDev->h_LnxWrpFmDev;
+ ioc_fm_port_tx_pause_frames_params_t param;
+ int mac_id = p_LnxWrpFmPortDev->id;
+
+ if(&p_LnxWrpFmDev->txPorts[mac_id] != p_LnxWrpFmPortDev)
+ mac_id += FM_MAX_NUM_OF_1G_MACS; /* 10G port */
+
+ if (copy_from_user(&param, (ioc_fm_port_tx_pause_frames_params_t *)arg,
+ sizeof(ioc_fm_port_tx_pause_frames_params_t)))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+
+ if (p_LnxWrpFmDev && p_LnxWrpFmDev->macs[mac_id].h_Dev)
+ {
+ FM_MAC_SetTxPauseFrames(p_LnxWrpFmDev->macs[mac_id].h_Dev,
+ param.priority,
+ param.pause_time,
+ param.thresh_time);
+ }
+ else
+ {
+ err = E_NOT_AVAILABLE;
+ REPORT_ERROR(MINOR, err, ("Port not initialized or other error!"));
+ }
+
+ break;
+ }
+
+ case FM_PORT_IOC_CONFIG_BUFFER_PREFIX_CONTENT:
+ {
+ ioc_fm_buffer_prefix_content_t *param;
+
+ param = (ioc_fm_buffer_prefix_content_t*) XX_Malloc(sizeof(ioc_fm_buffer_prefix_content_t));
+ if (!param)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PORT"));
+
+ memset(param, 0, sizeof(ioc_fm_buffer_prefix_content_t));
+
+ if (copy_from_user(param, (ioc_fm_buffer_prefix_content_t*) arg,
+ sizeof(ioc_fm_buffer_prefix_content_t)))
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+
+ if (FM_PORT_ConfigBufferPrefixContent(p_LnxWrpFmPortDev->h_Dev,
+ (t_FmBufferPrefixContent *)param))
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+
+ XX_Free(param);
+ break;
+ }
+
+#if (DPAA_VERSION >= 11)
+#if defined(CONFIG_COMPAT)
+ case FM_PORT_IOC_VSP_ALLOC_COMPAT:
+#endif
+ case FM_PORT_IOC_VSP_ALLOC:
+ {
+ ioc_fm_port_vsp_alloc_params_t *param;
+ t_LnxWrpFmDev *p_LnxWrpFmDev;
+ t_LnxWrpFmPortDev *p_LnxWrpFmTxPortDev;
+
+ param = (ioc_fm_port_vsp_alloc_params_t *) XX_Malloc(
+ sizeof(ioc_fm_port_vsp_alloc_params_t));
+ if (!param)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PORT"));
+
+ memset(param, 0, sizeof(ioc_fm_port_vsp_alloc_params_t));
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ ioc_compat_fm_port_vsp_alloc_params_t *compat_param;
+
+ compat_param = (ioc_compat_fm_port_vsp_alloc_params_t *) XX_Malloc(
+ sizeof(ioc_compat_fm_port_vsp_alloc_params_t));
+ if (!compat_param)
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PORT"));
+ }
+
+ memset(compat_param, 0, sizeof(ioc_compat_fm_port_vsp_alloc_params_t));
+ if (copy_from_user(compat_param,
+ (ioc_compat_fm_port_vsp_alloc_params_t *) compat_ptr(arg),
+ sizeof(ioc_compat_fm_port_vsp_alloc_params_t)))
+ {
+ XX_Free(compat_param);
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+
+ compat_copy_fm_port_vsp_alloc_params(compat_param, param, COMPAT_US_TO_K);
+
+ XX_Free(compat_param);
+ }
+ else
+#endif
+ {
+ if (copy_from_user(param, (ioc_fm_port_vsp_alloc_params_t *)arg,
+ sizeof(ioc_fm_port_vsp_alloc_params_t)))
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+ }
+
+ /* Userspace may not have the Tx port t_handle when issuing the IOCTL */
+ if (p_LnxWrpFmPortDev->settings.param.portType == e_FM_PORT_TYPE_RX ||
+ p_LnxWrpFmPortDev->settings.param.portType == e_FM_PORT_TYPE_RX_10G)
+ {
+ /* Determine the Tx port t_Handle from the Rx port id */
+ p_LnxWrpFmDev = p_LnxWrpFmPortDev->h_LnxWrpFmDev;
+ p_LnxWrpFmTxPortDev = &p_LnxWrpFmDev->txPorts[p_LnxWrpFmPortDev->id];
+ param->p_fm_tx_port = p_LnxWrpFmTxPortDev->h_Dev;
+ }
+
+ if (FM_PORT_VSPAlloc(p_LnxWrpFmPortDev->h_Dev, (t_FmPortVSPAllocParams *)param))
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+
+ XX_Free(param);
+ break;
+ }
+#endif /* (DPAA_VERSION >= 11) */
+
+ case FM_PORT_IOC_GET_MAC_STATISTICS:
+ {
+ t_LnxWrpFmDev *p_LnxWrpFmDev =
+ (t_LnxWrpFmDev *)p_LnxWrpFmPortDev->h_LnxWrpFmDev;
+ ioc_fm_port_mac_statistics_t param;
+ int mac_id = p_LnxWrpFmPortDev->id;
+
+ if (!p_LnxWrpFmDev)
+ RETURN_ERROR(MINOR, E_NOT_AVAILABLE, ("Port not initialized or other error!"));
+
+ if (&p_LnxWrpFmDev->txPorts[mac_id] != p_LnxWrpFmPortDev &&
+ &p_LnxWrpFmDev->rxPorts[mac_id] != p_LnxWrpFmPortDev)
+ mac_id += FM_MAX_NUM_OF_1G_MACS; /* 10G port */
+
+ if (!p_LnxWrpFmDev->macs[mac_id].h_Dev)
+ RETURN_ERROR(MINOR, E_NOT_AVAILABLE, ("Port not initialized or other error!"));
+
+ if (FM_MAC_GetStatistics(p_LnxWrpFmDev->macs[mac_id].h_Dev,
+ (t_FmMacStatistics *)&param))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+
+ if (copy_to_user((ioc_fm_port_mac_statistics_t *)arg, &param,
+ sizeof(ioc_fm_port_mac_statistics_t)))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+
+ break;
+ }
+
+ default:
+ RETURN_ERROR(MINOR, E_INVALID_SELECTION,
+ ("invalid ioctl: cmd:0x%08x(type:0x%02x, nr:0x%02x.\n",
+ cmd, _IOC_TYPE(cmd), _IOC_NR(cmd)));
+ }
+
+ if (err)
+ RETURN_ERROR(MINOR, E_INVALID_OPERATION, ("IOCTL FM PORT"));
+
+ return E_OK;
+}
+
+/*****************************************************************************/
+/* API routines for the FM Linux Device */
+/*****************************************************************************/
+
+static int fm_open(struct inode *inode, struct file *file)
+{
+ t_LnxWrpFmDev *p_LnxWrpFmDev = NULL;
+ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev = NULL;
+ unsigned int major = imajor(inode);
+ unsigned int minor = iminor(inode);
+ struct device_node *fm_node;
+ static struct of_device_id fm_node_of_match[] = {
+ { .compatible = "fsl,fman", },
+ { /* end of list */ },
+ };
+
+ DBG(TRACE, ("Opening minor - %d - ", minor));
+
+ if (file->private_data != NULL)
+ return 0;
+
+ /* Get all the FM nodes */
+ for_each_matching_node(fm_node, fm_node_of_match) {
+ struct platform_device *of_dev;
+
+ of_dev = of_find_device_by_node(fm_node);
+ if (unlikely(of_dev == NULL)) {
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("fm id!"));
+ return -ENXIO;
+ }
+
+ p_LnxWrpFmDev = (t_LnxWrpFmDev *)fm_bind(&of_dev->dev);
+ if (p_LnxWrpFmDev->major == major)
+ break;
+ fm_unbind((struct fm *)p_LnxWrpFmDev);
+ p_LnxWrpFmDev = NULL;
+ }
+
+ if (!p_LnxWrpFmDev)
+ return -ENODEV;
+
+ if (minor == DEV_FM_MINOR_BASE)
+ file->private_data = p_LnxWrpFmDev;
+ else if (minor == DEV_FM_PCD_MINOR_BASE)
+ file->private_data = p_LnxWrpFmDev;
+ else {
+ if (minor == DEV_FM_OH_PORTS_MINOR_BASE)
+ p_LnxWrpFmPortDev = &p_LnxWrpFmDev->hcPort;
+ else if ((minor > DEV_FM_OH_PORTS_MINOR_BASE) && (minor < DEV_FM_RX_PORTS_MINOR_BASE))
+ p_LnxWrpFmPortDev = &p_LnxWrpFmDev->opPorts[minor-DEV_FM_OH_PORTS_MINOR_BASE-1];
+ else if ((minor >= DEV_FM_RX_PORTS_MINOR_BASE) && (minor < DEV_FM_TX_PORTS_MINOR_BASE))
+ p_LnxWrpFmPortDev = &p_LnxWrpFmDev->rxPorts[minor-DEV_FM_RX_PORTS_MINOR_BASE];
+ else if ((minor >= DEV_FM_TX_PORTS_MINOR_BASE) && (minor < DEV_FM_MAX_MINORS))
+ p_LnxWrpFmPortDev = &p_LnxWrpFmDev->txPorts[minor-DEV_FM_TX_PORTS_MINOR_BASE];
+ else
+ return -EINVAL;
+
+ /* if trying to open port, check if it initialized */
+ if (!p_LnxWrpFmPortDev->h_Dev)
+ return -ENODEV;
+
+ p_LnxWrpFmPortDev = (t_LnxWrpFmPortDev *)fm_port_bind(p_LnxWrpFmPortDev->dev);
+ file->private_data = p_LnxWrpFmPortDev;
+ fm_unbind((struct fm *)p_LnxWrpFmDev);
+ }
+
+ if (file->private_data == NULL)
+ return -ENXIO;
+
+ return 0;
+}
+
+static int fm_close(struct inode *inode, struct file *file)
+{
+ t_LnxWrpFmDev *p_LnxWrpFmDev;
+ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev;
+ unsigned int minor = iminor(inode);
+ int err = 0;
+
+ DBG(TRACE, ("Closing minor - %d - ", minor));
+
+ if ((minor == DEV_FM_MINOR_BASE) ||
+ (minor == DEV_FM_PCD_MINOR_BASE))
+ {
+ p_LnxWrpFmDev = (t_LnxWrpFmDev*)file->private_data;
+ if (!p_LnxWrpFmDev)
+ return -ENODEV;
+ fm_unbind((struct fm *)p_LnxWrpFmDev);
+ }
+ else if (((minor >= DEV_FM_OH_PORTS_MINOR_BASE) && (minor < DEV_FM_RX_PORTS_MINOR_BASE)) ||
+ ((minor >= DEV_FM_RX_PORTS_MINOR_BASE) && (minor < DEV_FM_TX_PORTS_MINOR_BASE)) ||
+ ((minor >= DEV_FM_TX_PORTS_MINOR_BASE) && (minor < DEV_FM_MAX_MINORS)))
+ {
+ p_LnxWrpFmPortDev = (t_LnxWrpFmPortDev*)file->private_data;
+ if (!p_LnxWrpFmPortDev)
+ return -ENODEV;
+ fm_port_unbind((struct fm_port *)p_LnxWrpFmPortDev);
+ }
+
+ return err;
+}
+
+static int fm_ioctls(unsigned int minor, struct file *file, unsigned int cmd, unsigned long arg, bool compat)
+{
+ DBG(TRACE, ("IOCTL minor - %u, cmd - 0x%08x, arg - 0x%08lx \n", minor, cmd, arg));
+
+ if ((minor == DEV_FM_MINOR_BASE) ||
+ (minor == DEV_FM_PCD_MINOR_BASE))
+ {
+ t_LnxWrpFmDev *p_LnxWrpFmDev = ((t_LnxWrpFmDev*)file->private_data);
+ if (!p_LnxWrpFmDev)
+ return -ENODEV;
+ if (LnxwrpFmIOCTL(p_LnxWrpFmDev, cmd, arg, compat))
+ return -EFAULT;
+ }
+ else if (((minor >= DEV_FM_OH_PORTS_MINOR_BASE) && (minor < DEV_FM_RX_PORTS_MINOR_BASE)) ||
+ ((minor >= DEV_FM_RX_PORTS_MINOR_BASE) && (minor < DEV_FM_TX_PORTS_MINOR_BASE)) ||
+ ((minor >= DEV_FM_TX_PORTS_MINOR_BASE) && (minor < DEV_FM_MAX_MINORS)))
+ {
+ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev = ((t_LnxWrpFmPortDev*)file->private_data);
+ if (!p_LnxWrpFmPortDev)
+ return -ENODEV;
+ if (LnxwrpFmPortIOCTL(p_LnxWrpFmPortDev, cmd, arg, compat))
+ return -EFAULT;
+ }
+ else
+ {
+ REPORT_ERROR(MINOR, E_INVALID_VALUE, ("minor"));
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+#ifdef CONFIG_COMPAT
+static long fm_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ unsigned int minor = iminor(file->f_path.dentry->d_inode);
+ long res;
+
+ fm_mutex_lock();
+ res = fm_ioctls(minor, file, cmd, arg, true);
+ fm_mutex_unlock();
+
+ return res;
+}
+#endif
+
+static long fm_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ unsigned int minor = iminor(file->f_path.dentry->d_inode);
+ long res;
+
+ fm_mutex_lock();
+ res = fm_ioctls(minor, file, cmd, arg, false);
+ fm_mutex_unlock();
+
+ return res;
+}
+
+/* Globals for FM character device */
+struct file_operations fm_fops =
+{
+ .owner = THIS_MODULE,
+ .unlocked_ioctl = fm_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = fm_compat_ioctl,
+#endif
+ .open = fm_open,
+ .release = fm_close,
+};
diff --git a/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_ioctls_fm_compat.c b/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_ioctls_fm_compat.c
new file mode 100644
index 0000000..c307473
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_ioctls_fm_compat.c
@@ -0,0 +1,1223 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * 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 Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * 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 Freescale Semiconductor ``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 Freescale Semiconductor 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.
+ */
+
+/*
+ @File lnxwrp_fm_compat_ioctls.c
+
+ @Description FM PCD compat functions
+
+*/
+
+#if !defined(CONFIG_COMPAT)
+#error "missing COMPAT layer..."
+#endif
+
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/cdev.h>
+#include <linux/device.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <asm/uaccess.h>
+#include <asm/errno.h>
+#include <sysdev/fsl_soc.h>
+
+#include "part_ext.h"
+#include "fm_ioctls.h"
+#include "fm_pcd_ioctls.h"
+#include "fm_port_ioctls.h"
+#include "lnxwrp_ioctls_fm_compat.h"
+
+#if defined(FM_COMPAT_DBG)
+static void hex_dump(void * p_addr, unsigned int size)
+{
+ int i;
+
+ for(i=0; i<size; i+=16)
+ {
+ printk("%p: 0x%08x 0x%08x 0x%08x 0x%08x\n", p_addr + i,
+ *(unsigned int *)(p_addr + i),
+ *(unsigned int *)(p_addr + i + 4),
+ *(unsigned int *)(p_addr + i + 8),
+ *(unsigned int *)(p_addr + i +12)
+ );
+ }
+}
+#endif
+
+/* maping kernel pointers w/ UserSpace id's { */
+struct map_node {
+ void *ptr;
+ u8 node_type;
+};
+
+static struct map_node compat_ptr2id_array[COMPAT_PTR2ID_ARRAY_MAX] = {{NULL},{FM_MAP_TYPE_UNSPEC}};
+
+void compat_del_ptr2id(void *p, enum fm_map_node_type node_type)
+{
+ compat_uptr_t k;
+
+ _fm_cpt_dbg(COMPAT_GENERIC, "delete (%p)\n", p);
+
+ for(k=1; k < COMPAT_PTR2ID_ARRAY_MAX; k++)
+ if(compat_ptr2id_array[k].ptr == p){
+ compat_ptr2id_array[k].ptr = NULL;
+ compat_ptr2id_array[k].node_type = FM_MAP_TYPE_UNSPEC;
+ }
+}
+EXPORT_SYMBOL(compat_del_ptr2id);
+
+compat_uptr_t compat_add_ptr2id(void *p, enum fm_map_node_type node_type)
+{
+ compat_uptr_t k;
+
+ _fm_cpt_dbg(COMPAT_GENERIC, " (%p) do ->\n", p);
+
+ if(!p)
+ return 0;
+
+ for(k=1; k < COMPAT_PTR2ID_ARRAY_MAX; k++)
+ if(compat_ptr2id_array[k].ptr == NULL)
+ {
+ compat_ptr2id_array[k].ptr = p;
+ compat_ptr2id_array[k].node_type = node_type;
+ _fm_cpt_dbg(COMPAT_GENERIC, "0x%08x \n", k | COMPAT_PTR2ID_WATERMARK);
+ return k | COMPAT_PTR2ID_WATERMARK;
+ }
+
+ printk(KERN_WARNING "FMan map list full! No more PCD space on kernel!\n");
+ return 0;
+}
+EXPORT_SYMBOL(compat_add_ptr2id);
+
+compat_uptr_t compat_get_ptr2id(void *p, enum fm_map_node_type node_type)
+{
+ compat_uptr_t k;
+
+ _fm_cpt_dbg(COMPAT_GENERIC, " (%p) get -> \n", p);
+
+ for(k=1; k < COMPAT_PTR2ID_ARRAY_MAX; k++)
+ if(compat_ptr2id_array[k].ptr == p &&
+ compat_ptr2id_array[k].node_type == node_type) {
+
+ _fm_cpt_dbg(COMPAT_GENERIC, "0x%08x\n", k | COMPAT_PTR2ID_WATERMARK);
+ return k | COMPAT_PTR2ID_WATERMARK;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(compat_get_ptr2id);
+
+void *compat_get_id2ptr(compat_uptr_t comp, enum fm_map_node_type node_type)
+{
+
+ _fm_cpt_dbg(COMPAT_GENERIC, " (0x%08x) get -> \n", comp);
+
+ if((COMPAT_PTR2ID_WM_MASK & comp) != COMPAT_PTR2ID_WATERMARK) {
+ _fm_cpt_dbg(COMPAT_GENERIC, "Error, invalid watermark (0x%08x)!\n\n", comp);
+ dump_stack();
+ return compat_ptr(comp);
+ }
+
+ comp &= ~COMPAT_PTR2ID_WM_MASK;
+
+ if(((0 < comp) && (comp < COMPAT_PTR2ID_ARRAY_MAX) && (compat_ptr2id_array[comp].ptr != NULL)
+ && compat_ptr2id_array[comp].node_type == node_type)) {
+ _fm_cpt_dbg(COMPAT_GENERIC, "%p\n", compat_ptr2id_array[comp].ptr);
+ return compat_ptr2id_array[comp].ptr;
+ }
+ return NULL;
+}
+EXPORT_SYMBOL(compat_get_id2ptr);
+/* } maping kernel pointers w/ UserSpace id's */
+
+void compat_obj_delete(
+ ioc_compat_fm_obj_t *compat_id,
+ ioc_fm_obj_t *id)
+{
+ id->obj = compat_pcd_id2ptr(compat_id->obj);
+ compat_del_ptr2id(id->obj, FM_MAP_TYPE_PCD_NODE);
+}
+
+static inline void compat_copy_fm_pcd_plcr_next_engine(
+ ioc_compat_fm_pcd_plcr_next_engine_params_u *compat_param,
+ ioc_fm_pcd_plcr_next_engine_params_u *param,
+ ioc_fm_pcd_engine next_engine,
+ uint8_t compat)
+{
+ _fm_cpt_dbg (compat, " {->...\n");
+
+ switch (next_engine)
+ {
+ case e_IOC_FM_PCD_PLCR:
+ if (compat == COMPAT_US_TO_K)
+ param->p_profile = compat_pcd_id2ptr(compat_param->p_profile);
+ else
+ compat_param->p_profile = compat_pcd_ptr2id(param->p_profile);
+ break;
+ case e_IOC_FM_PCD_KG:
+ if (compat == COMPAT_US_TO_K)
+ param->p_direct_scheme = compat_pcd_id2ptr(compat_param->p_direct_scheme);
+ else
+ compat_param->p_direct_scheme = compat_pcd_ptr2id(param->p_direct_scheme);
+ break;
+ default:
+ if (compat == COMPAT_US_TO_K)
+ param->action = compat_param->action;
+ else
+ compat_param->action = param->action;
+ break;
+ }
+
+ _fm_cpt_dbg (compat, " ...->}\n");
+}
+
+void compat_copy_fm_pcd_plcr_profile(
+ ioc_compat_fm_pcd_plcr_profile_params_t *compat_param,
+ ioc_fm_pcd_plcr_profile_params_t *param,
+ uint8_t compat)
+{
+ _fm_cpt_dbg (compat, " {->...\n");
+
+ if (compat == COMPAT_US_TO_K)
+ {
+ param->modify = compat_param->modify;
+
+ /* profile_select */
+ if (!compat_param->modify)
+ {
+ param->profile_select.new_params.profile_type =
+ compat_param->profile_select.new_params.profile_type;
+ param->profile_select.new_params.p_fm_port =
+ compat_ptr(compat_param->profile_select.new_params.p_fm_port);
+ param->profile_select.new_params.relative_profile_id =
+ compat_param->profile_select.new_params.relative_profile_id;
+ }
+ else
+ param->profile_select.p_profile =
+ compat_pcd_id2ptr(compat_param->profile_select.p_profile);
+
+ param->alg_selection = compat_param->alg_selection;
+ param->color_mode = compat_param->color_mode;
+
+ /* both parameters in the union has the same size, so memcpy works */
+ memcpy(&param->color, &compat_param->color, sizeof(param->color));
+
+ memcpy(&param->non_passthrough_alg_param,
+ &compat_param->non_passthrough_alg_param,
+ sizeof(ioc_fm_pcd_plcr_non_passthrough_alg_param_t));
+
+ param->next_engine_on_green = compat_param->next_engine_on_green;
+ param->next_engine_on_yellow = compat_param->next_engine_on_yellow;
+ param->next_engine_on_red = compat_param->next_engine_on_red;
+
+ param->trap_profile_on_flow_A = compat_param->trap_profile_on_flow_A;
+ param->trap_profile_on_flow_B = compat_param->trap_profile_on_flow_B;
+ param->trap_profile_on_flow_C = compat_param->trap_profile_on_flow_C;
+ }
+ else
+ {
+ compat_param->modify = param->modify;
+
+ /* profile_select */
+ if (!param->modify)
+ {
+ compat_param->profile_select.new_params.profile_type =
+ param->profile_select.new_params.profile_type;
+ compat_param->profile_select.new_params.p_fm_port =
+ ptr_to_compat(param->profile_select.new_params.p_fm_port);
+ compat_param->profile_select.new_params.relative_profile_id =
+ param->profile_select.new_params.relative_profile_id;
+ }
+ else
+ compat_param->profile_select.p_profile =
+ compat_pcd_ptr2id(param->profile_select.p_profile);
+
+ compat_param->alg_selection = param->alg_selection;
+ compat_param->color_mode = param->color_mode;
+
+ /* both parameters in the union has the same size, so memcpy works */
+ memcpy(&compat_param->color, &param->color, sizeof(compat_param->color));
+
+ memcpy(&compat_param->non_passthrough_alg_param,
+ &param->non_passthrough_alg_param,
+ sizeof(ioc_fm_pcd_plcr_non_passthrough_alg_param_t));
+
+ compat_param->next_engine_on_green = param->next_engine_on_green;
+ compat_param->next_engine_on_yellow = param->next_engine_on_yellow;
+ compat_param->next_engine_on_red = param->next_engine_on_red;
+
+ compat_param->trap_profile_on_flow_A = param->trap_profile_on_flow_A;
+ compat_param->trap_profile_on_flow_B = param->trap_profile_on_flow_B;
+ compat_param->trap_profile_on_flow_C = param->trap_profile_on_flow_C;
+
+ compat_param->id = compat_add_ptr2id(param->id, FM_MAP_TYPE_PCD_NODE);
+ }
+
+ compat_copy_fm_pcd_plcr_next_engine(&compat_param->params_on_green,
+ &param->params_on_green, param->next_engine_on_green, compat);
+
+ compat_copy_fm_pcd_plcr_next_engine(&compat_param->params_on_yellow,
+ &param->params_on_yellow, param->next_engine_on_yellow, compat);
+
+ compat_copy_fm_pcd_plcr_next_engine(&compat_param->params_on_red,
+ &param->params_on_red, param->next_engine_on_red, compat);
+
+ _fm_cpt_dbg (compat, " ...->}\n");
+}
+
+static inline void compat_copy_fm_pcd_cc_next_kg(
+ ioc_compat_fm_pcd_cc_next_kg_params_t *compat_param,
+ ioc_fm_pcd_cc_next_kg_params_t *param,
+ uint8_t compat)
+{
+ _fm_cpt_dbg (compat, " {->...\n");
+
+ if (compat == COMPAT_US_TO_K)
+ {
+ param->new_fqid = compat_param->new_fqid;
+ param->override_fqid = compat_param->override_fqid;
+ param->p_direct_scheme = compat_pcd_id2ptr(compat_param->p_direct_scheme);
+ }
+ else
+ {
+ compat_param->new_fqid = param->new_fqid;
+ compat_param->override_fqid = param->override_fqid;
+ compat_param->p_direct_scheme = compat_pcd_ptr2id(param->p_direct_scheme);
+ }
+
+ _fm_cpt_dbg (compat, " ...->}\n");
+}
+
+static inline void compat_copy_fm_pcd_cc_next_cc(
+ ioc_compat_fm_pcd_cc_next_cc_params_t *compat_param,
+ ioc_fm_pcd_cc_next_cc_params_t *param,
+ uint8_t compat)
+{
+ _fm_cpt_dbg (compat, " {->...\n");
+
+ if (compat == COMPAT_US_TO_K)
+ param->cc_node_id = compat_pcd_id2ptr(compat_param->cc_node_id);
+ else
+ compat_param->cc_node_id = compat_pcd_ptr2id(param->cc_node_id);
+
+ _fm_cpt_dbg (compat, " ...->}\n");
+}
+
+static inline void compat_copy_fm_pcd_cc_next_engine(
+ ioc_compat_fm_pcd_cc_next_engine_params_t *compat_param,
+ ioc_fm_pcd_cc_next_engine_params_t *param,
+ uint8_t compat)
+{
+ _fm_cpt_dbg (compat, " {->...\n");
+
+ if (compat == COMPAT_US_TO_K)
+ {
+ param->next_engine = compat_param->next_engine;
+ if (param->next_engine != e_IOC_FM_PCD_INVALID )
+ _fm_cpt_dbg(compat, " param->next_engine = %i \n", param->next_engine);
+
+ switch (param->next_engine)
+ {
+#if DPAA_VERSION >= 11
+ case e_IOC_FM_PCD_FR:
+ param->params.fr_params.frm_replic_id = compat_pcd_id2ptr(compat_param->params.fr_params.frm_replic_id);
+ break;
+#endif /* DPAA_VERSION >= 11 */
+ case e_IOC_FM_PCD_CC:
+ compat_copy_fm_pcd_cc_next_cc(&compat_param->params.cc_params, &param->params.cc_params, compat);
+ break;
+ case e_IOC_FM_PCD_KG:
+ param->manip_id = compat_pcd_id2ptr(compat_param->manip_id);
+ compat_copy_fm_pcd_cc_next_kg(&compat_param->params.kg_params, &param->params.kg_params, compat);
+ break;
+ case e_IOC_FM_PCD_DONE:
+ case e_IOC_FM_PCD_PLCR:
+ param->manip_id = compat_pcd_id2ptr(compat_param->manip_id);
+ default:
+ memcpy(&param->params, &compat_param->params, sizeof(param->params));
+ }
+ param->statistics_en = compat_param->statistics_en;
+ }
+ else
+ {
+ compat_param->next_engine = param->next_engine;
+
+ switch (compat_param->next_engine)
+ {
+#if DPAA_VERSION >= 11
+ case e_IOC_FM_PCD_FR:
+ compat_param->params.fr_params.frm_replic_id = compat_pcd_ptr2id(param->params.fr_params.frm_replic_id);
+ break;
+#endif /* DPAA_VERSION >= 11 */
+ case e_IOC_FM_PCD_CC:
+ compat_copy_fm_pcd_cc_next_cc(&compat_param->params.cc_params, &param->params.cc_params, compat);
+ break;
+ case e_IOC_FM_PCD_KG:
+ compat_param->manip_id = compat_pcd_ptr2id(param->manip_id);
+ compat_copy_fm_pcd_cc_next_kg(&compat_param->params.kg_params, &param->params.kg_params, compat);
+ break;
+ case e_IOC_FM_PCD_DONE:
+ case e_IOC_FM_PCD_PLCR:
+ compat_param->manip_id = compat_pcd_ptr2id(param->manip_id);
+ default:
+ memcpy(&compat_param->params, &param->params, sizeof(compat_param->params));
+ }
+ compat_param->statistics_en = param->statistics_en;
+ }
+
+ _fm_cpt_dbg (compat, " ...->}\n");
+}
+
+void compat_copy_fm_pcd_cc_key(
+ ioc_compat_fm_pcd_cc_key_params_t *compat_param,
+ ioc_fm_pcd_cc_key_params_t *param,
+ uint8_t compat)
+{
+ if (compat == COMPAT_US_TO_K)
+ {
+ param->p_key = compat_ptr(compat_param->p_key);
+ param->p_mask = compat_ptr(compat_param->p_mask);
+ }
+ else
+ {
+ compat_param->p_key = ptr_to_compat(param->p_key);
+ compat_param->p_mask = ptr_to_compat(param->p_mask);
+ }
+
+ compat_copy_fm_pcd_cc_next_engine(
+ &compat_param->cc_next_engine_params,
+ &param->cc_next_engine_params,
+ compat);
+}
+
+void compat_copy_fm_pcd_cc_node_modify_key_and_next_engine(
+ ioc_compat_fm_pcd_cc_node_modify_key_and_next_engine_params_t *compat_param,
+ ioc_fm_pcd_cc_node_modify_key_and_next_engine_params_t *param,
+ uint8_t compat)
+{
+ if (compat == COMPAT_US_TO_K)
+ {
+ param->id = compat_pcd_id2ptr(compat_param->id);
+ param->key_indx = compat_param->key_indx;
+ param->key_size = compat_param->key_size;
+ compat_copy_fm_pcd_cc_key(
+ &compat_param->key_params,
+ &param->key_params,
+ compat);
+ }
+ else
+ {
+ compat_param->id = compat_pcd_ptr2id(param->id);
+ compat_param->key_indx = param->key_indx;
+ compat_param->key_size = param->key_size;
+ compat_copy_fm_pcd_cc_key(
+ &compat_param->key_params,
+ &param->key_params,
+ compat);
+ }
+}
+
+void compat_copy_fm_pcd_cc_node_modify_next_engine(
+ ioc_compat_fm_pcd_cc_node_modify_next_engine_params_t *compat_param,
+ ioc_fm_pcd_cc_node_modify_next_engine_params_t *param,
+ uint8_t compat)
+{
+ if (compat == COMPAT_US_TO_K)
+ {
+ param->id = compat_pcd_id2ptr(compat_param->id);
+ param->key_indx = compat_param->key_indx;
+ param->key_size = compat_param->key_size;
+ }
+ else
+ {
+ compat_param->id = compat_pcd_ptr2id(param->id);
+ compat_param->key_indx = param->key_indx;
+ compat_param->key_size = param->key_size;
+ }
+
+ compat_copy_fm_pcd_cc_next_engine(
+ &compat_param->cc_next_engine_params,
+ &param->cc_next_engine_params,
+ compat);
+}
+
+void compat_fm_pcd_cc_tree_modify_next_engine(
+ ioc_compat_fm_pcd_cc_tree_modify_next_engine_params_t *compat_param,
+ ioc_fm_pcd_cc_tree_modify_next_engine_params_t *param,
+ uint8_t compat)
+{
+ if (compat == COMPAT_US_TO_K)
+ {
+ param->id = compat_pcd_id2ptr(compat_param->id);
+ param->grp_indx = compat_param->grp_indx;
+ param->indx = compat_param->indx;
+ }
+ else
+ {
+ compat_param->id = compat_pcd_ptr2id(param->id);
+ compat_param->grp_indx = param->grp_indx;
+ compat_param->indx = param->indx;
+ }
+
+ compat_copy_fm_pcd_cc_next_engine(
+ &compat_param->cc_next_engine_params,
+ &param->cc_next_engine_params,
+ compat);
+}
+
+void compat_copy_fm_pcd_hash_table(
+ ioc_compat_fm_pcd_hash_table_params_t *compat_param,
+ ioc_fm_pcd_hash_table_params_t *param,
+ uint8_t compat)
+{
+ if (compat == COMPAT_US_TO_K)
+ {
+ param-> max_num_of_keys = compat_param->max_num_of_keys;
+ param->statistics_mode = compat_param->statistics_mode;
+ param->hash_res_mask = compat_param->hash_res_mask;
+ param->hash_shift = compat_param->hash_shift;
+ param->match_key_size = compat_param->match_key_size;
+ param->id = compat_pcd_id2ptr(compat_param->id);
+ }
+ else
+ {
+ compat_param-> max_num_of_keys = param->max_num_of_keys;
+ compat_param->statistics_mode = param->statistics_mode;
+ compat_param->hash_res_mask = param->hash_res_mask;
+ compat_param->hash_shift = param->hash_shift;
+ compat_param->match_key_size = param->match_key_size;
+
+ compat_param->id = compat_add_ptr2id(param->id, FM_MAP_TYPE_PCD_NODE);
+ }
+
+ compat_copy_fm_pcd_cc_next_engine(
+ &compat_param->cc_next_engine_params_for_miss,
+ &param->cc_next_engine_params_for_miss,
+ compat);
+}
+
+void compat_copy_fm_pcd_cc_grp(
+ ioc_compat_fm_pcd_cc_grp_params_t *compat_param,
+ ioc_fm_pcd_cc_grp_params_t *param,
+ uint8_t compat)
+{
+ int k;
+
+ _fm_cpt_dbg (compat, " {->...\n");
+
+ if (compat == COMPAT_US_TO_K)
+ {
+ param->num_of_distinction_units = compat_param->num_of_distinction_units;
+ memcpy(param->unit_ids, compat_param->unit_ids, IOC_FM_PCD_MAX_NUM_OF_CC_UNITS);
+ }
+ else
+ {
+ compat_param->num_of_distinction_units = param->num_of_distinction_units;
+ memcpy(compat_param->unit_ids, param->unit_ids, IOC_FM_PCD_MAX_NUM_OF_CC_UNITS);
+ }
+
+ for (k=0; k < IOC_FM_PCD_MAX_NUM_OF_CC_ENTRIES_IN_GRP; k++)
+ compat_copy_fm_pcd_cc_next_engine(
+ &compat_param->next_engine_per_entries_in_grp[k],
+ &param->next_engine_per_entries_in_grp[k],
+ compat);
+
+ _fm_cpt_dbg (compat, " ...->}\n");
+}
+
+void compat_copy_fm_pcd_cc_tree(
+ ioc_compat_fm_pcd_cc_tree_params_t *compat_param,
+ ioc_fm_pcd_cc_tree_params_t *param,
+ uint8_t compat)
+{
+ int k;
+ _fm_cpt_dbg (compat, " {->...\n");
+
+ if (compat == COMPAT_US_TO_K)
+ {
+ param->net_env_id = compat_pcd_id2ptr(compat_param->net_env_id);
+ param->num_of_groups = compat_param->num_of_groups;
+ }
+ else
+ {
+ compat_param->net_env_id = compat_pcd_ptr2id(param->net_env_id);
+ compat_param->num_of_groups = param->num_of_groups;
+
+ compat_param->id = compat_add_ptr2id(param->id, FM_MAP_TYPE_PCD_NODE);
+ }
+
+ for (k=0; k < IOC_FM_PCD_MAX_NUM_OF_CC_GROUPS; k++)
+ compat_copy_fm_pcd_cc_grp(
+ &compat_param->fm_pcd_cc_group_params[k],
+ &param->fm_pcd_cc_group_params[k],
+ compat);
+
+ _fm_cpt_dbg (compat, " ...->}\n");
+}
+
+void compat_fm_pcd_prs_sw(
+ ioc_compat_fm_pcd_prs_sw_params_t *compat_param,
+ ioc_fm_pcd_prs_sw_params_t *param,
+ uint8_t compat)
+{
+ if (compat == COMPAT_US_TO_K)
+ {
+ param->override = compat_param->override;
+ param->size = compat_param->size;
+ param->base = compat_param->base;
+ param->p_code = compat_ptr(compat_param->p_code);
+ memcpy(param->sw_prs_data_params,compat_param->sw_prs_data_params,IOC_FM_PCD_PRS_NUM_OF_HDRS*sizeof(uint32_t));
+ param->num_of_labels = compat_param->num_of_labels;
+ memcpy(param->labels_table,compat_param->labels_table,IOC_FM_PCD_PRS_NUM_OF_LABELS*sizeof(ioc_fm_pcd_prs_label_params_t));
+ }
+}
+
+void compat_copy_fm_pcd_kg_scheme(
+ ioc_compat_fm_pcd_kg_scheme_params_t *compat_param,
+ ioc_fm_pcd_kg_scheme_params_t *param,
+ uint8_t compat)
+{
+ _fm_cpt_dbg(compat," {->...\n");
+
+ if (compat == COMPAT_US_TO_K)
+ {
+ param->modify = compat_param->modify;
+
+ /* scm_id */
+ if (compat_param->modify)
+ {
+ param->scm_id.scheme_id = compat_pcd_id2ptr(compat_param->scm_id.scheme_id);
+ _fm_cpt_dbg(compat," param->scm_id.scheme_id = %p \n", param->scm_id.scheme_id);
+ }
+ else
+ param->scm_id.relative_scheme_id = compat_param->scm_id.relative_scheme_id;
+
+ param->always_direct = compat_param->always_direct;
+ /* net_env_params */
+ param->net_env_params.net_env_id = compat_pcd_id2ptr(compat_param->net_env_params.net_env_id);
+ param->net_env_params.num_of_distinction_units = compat_param->net_env_params.num_of_distinction_units;
+ memcpy(param->net_env_params.unit_ids,
+ compat_param->net_env_params.unit_ids,
+ IOC_FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS);
+
+ param->use_hash = compat_param->use_hash;
+ memcpy(&param->key_extract_and_hash_params,
+ &compat_param->key_extract_and_hash_params,
+ sizeof(ioc_fm_pcd_kg_key_extract_and_hash_params_t));
+ param->bypass_fqid_generation = compat_param->bypass_fqid_generation;
+ param->base_fqid = compat_param->base_fqid;
+#if DPAA_VERSION >= 11
+ param->override_storage_profile =
+ compat_param->override_storage_profile;
+ param->storage_profile = compat_param->storage_profile;
+#endif /* DPAA_VERSION >= 11 */
+ param->num_of_used_extracted_ors = compat_param->num_of_used_extracted_ors;
+ memcpy(param->extracted_ors,
+ compat_param->extracted_ors,
+ IOC_FM_PCD_KG_NUM_OF_GENERIC_REGS * sizeof(ioc_fm_pcd_kg_extracted_or_params_t));
+ param->next_engine = compat_param->next_engine;
+
+ /* kg_next_engine_params */
+ if (param->next_engine == e_IOC_FM_PCD_CC)
+ {
+ param->kg_next_engine_params.cc.tree_id = compat_pcd_id2ptr(compat_param->kg_next_engine_params.cc.tree_id);
+ param->kg_next_engine_params.cc.grp_id = compat_param->kg_next_engine_params.cc.grp_id;
+ param->kg_next_engine_params.cc.plcr_next = compat_param->kg_next_engine_params.cc.plcr_next;
+ param->kg_next_engine_params.cc.bypass_plcr_profile_generation
+ = compat_param->kg_next_engine_params.cc.bypass_plcr_profile_generation;
+ memcpy(&param->kg_next_engine_params.cc.plcr_profile,
+ &compat_param->kg_next_engine_params.cc.plcr_profile,
+ sizeof(ioc_fm_pcd_kg_plcr_profile_t));
+ }
+ else
+ memcpy(&param->kg_next_engine_params,
+ &compat_param->kg_next_engine_params,
+ sizeof(param->kg_next_engine_params));
+
+ memcpy(&param->scheme_counter,
+ &compat_param->scheme_counter,
+ sizeof(ioc_fm_pcd_kg_scheme_counter_t));
+ }
+ else
+ {
+ compat_param->modify = param->modify;
+
+ /* scm_id */
+ if (param->modify)
+ compat_param->scm_id.scheme_id = compat_pcd_ptr2id(param->scm_id.scheme_id);
+ else
+ compat_param->scm_id.relative_scheme_id = param->scm_id.relative_scheme_id;
+
+ compat_param->always_direct = param->always_direct;
+
+ /* net_env_params */
+ compat_param->net_env_params.net_env_id = compat_pcd_ptr2id(param->net_env_params.net_env_id);
+ compat_param->net_env_params.num_of_distinction_units = param->net_env_params.num_of_distinction_units;
+ memcpy(compat_param->net_env_params.unit_ids, param->net_env_params.unit_ids, IOC_FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS);
+
+ compat_param->use_hash = param->use_hash;
+ memcpy(&compat_param->key_extract_and_hash_params, &param->key_extract_and_hash_params, sizeof(ioc_fm_pcd_kg_key_extract_and_hash_params_t));
+ compat_param->bypass_fqid_generation = param->bypass_fqid_generation;
+ compat_param->base_fqid = param->base_fqid;
+#if DPAA_VERSION >= 11
+ compat_param->override_storage_profile =
+ param->override_storage_profile;
+ compat_param->storage_profile = param->storage_profile;
+#endif /* DPAA_VERSION >= 11 */
+ compat_param->num_of_used_extracted_ors = param->num_of_used_extracted_ors;
+ memcpy(compat_param->extracted_ors, param->extracted_ors, IOC_FM_PCD_KG_NUM_OF_GENERIC_REGS * sizeof(ioc_fm_pcd_kg_extracted_or_params_t));
+ compat_param->next_engine = param->next_engine;
+
+ /* kg_next_engine_params */
+ if (compat_param->next_engine == e_IOC_FM_PCD_CC)
+ {
+ compat_param->kg_next_engine_params.cc.tree_id = compat_pcd_ptr2id(param->kg_next_engine_params.cc.tree_id);
+ compat_param->kg_next_engine_params.cc.grp_id = param->kg_next_engine_params.cc.grp_id;
+ compat_param->kg_next_engine_params.cc.plcr_next = param->kg_next_engine_params.cc.plcr_next;
+ compat_param->kg_next_engine_params.cc.bypass_plcr_profile_generation
+ = param->kg_next_engine_params.cc.bypass_plcr_profile_generation;
+ memcpy(&compat_param->kg_next_engine_params.cc.plcr_profile,
+ &param->kg_next_engine_params.cc.plcr_profile,
+ sizeof(ioc_fm_pcd_kg_plcr_profile_t));
+ }
+ else
+ memcpy(&param->kg_next_engine_params, &compat_param->kg_next_engine_params, sizeof(compat_param->kg_next_engine_params));
+
+ memcpy(&compat_param->scheme_counter, &param->scheme_counter, sizeof(ioc_fm_pcd_kg_scheme_counter_t));
+
+ compat_param->id = compat_add_ptr2id(param->id, FM_MAP_TYPE_PCD_NODE);
+ }
+
+ _fm_cpt_dbg(compat," ...->}\n");
+}
+
+void compat_copy_fm_pcd_kg_scheme_select(
+ ioc_compat_fm_pcd_kg_scheme_select_t *compat_param,
+ ioc_fm_pcd_kg_scheme_select_t *param,
+ uint8_t compat)
+{
+ if (compat == COMPAT_US_TO_K)
+ {
+ param->direct = compat_param->direct;
+ if (param->direct)
+ param->scheme_id = compat_pcd_id2ptr(compat_param->scheme_id);
+ }
+}
+
+void compat_copy_fm_pcd_kg_schemes_params(
+ ioc_compat_fm_pcd_port_schemes_params_t *compat_param,
+ ioc_fm_pcd_port_schemes_params_t *param,
+ uint8_t compat)
+{
+ int k;
+
+ if (compat == COMPAT_US_TO_K) {
+ param->num_of_schemes = compat_param->num_of_schemes;
+ for(k=0; k < compat_param->num_of_schemes; k++)
+ param->scheme_ids[k] = compat_pcd_id2ptr(compat_param->scheme_ids[k]);
+ }
+}
+
+void compat_copy_fm_port_pcd_cc(
+ ioc_compat_fm_port_pcd_cc_params_t *compat_cc_params ,
+ ioc_fm_port_pcd_cc_params_t *p_cc_params,
+ uint8_t compat)
+{
+ if (compat == COMPAT_US_TO_K){
+ p_cc_params->cc_tree_id = compat_pcd_id2ptr(compat_cc_params->cc_tree_id);
+ }
+}
+
+void compat_copy_fm_port_pcd_kg(
+ ioc_compat_fm_port_pcd_kg_params_t *compat_param,
+ ioc_fm_port_pcd_kg_params_t *param,
+ uint8_t compat)
+{
+ if (compat == COMPAT_US_TO_K){
+ uint8_t k;
+
+ param->num_of_schemes = compat_param->num_of_schemes;
+ for(k=0; k<compat_param->num_of_schemes; k++)
+ param->scheme_ids[k] = compat_pcd_id2ptr(compat_param->scheme_ids[k]);
+
+ param->direct_scheme = compat_param->direct_scheme;
+ if (param->direct_scheme)
+ param->direct_scheme_id = compat_pcd_id2ptr(compat_param->direct_scheme_id);
+ }
+}
+
+void compat_copy_fm_port_pcd(
+ ioc_compat_fm_port_pcd_params_t *compat_param,
+ ioc_fm_port_pcd_params_t *param,
+ uint8_t compat)
+{
+ if (compat == COMPAT_US_TO_K)
+ {
+ ioc_fm_port_pcd_prs_params_t *same_port_pcd_prs_params;
+ ioc_compat_fm_port_pcd_cc_params_t *compat_port_pcd_cc_params;
+ ioc_compat_fm_port_pcd_kg_params_t *compat_port_pcd_kg_params;
+ ioc_compat_fm_port_pcd_plcr_params_t *compat_port_pcd_plcr_params;
+
+ same_port_pcd_prs_params = (ioc_fm_port_pcd_prs_params_t *) (compat_param + 1);
+ compat_port_pcd_cc_params = (ioc_compat_fm_port_pcd_cc_params_t *) (same_port_pcd_prs_params + 1);
+ compat_port_pcd_kg_params = (ioc_compat_fm_port_pcd_kg_params_t *) (compat_port_pcd_cc_params + 1);
+ compat_port_pcd_plcr_params = (ioc_compat_fm_port_pcd_plcr_params_t *) (compat_port_pcd_kg_params + 1);
+
+ _fm_cpt_dbg(compat,"\n param->p_prs_params=%p \n", param->p_prs_params);
+ _fm_cpt_dbg(compat," param->p_cc_params=%p \n", param->p_cc_params);
+ _fm_cpt_dbg(compat," param->p_kg_params=%p \n", param->p_kg_params);
+ _fm_cpt_dbg(compat," param->p_plcr_params=%p \n", param->p_plcr_params);
+ _fm_cpt_dbg(compat," param->p_ip_reassembly_manip=%p \n", param->p_ip_reassembly_manip);
+
+ param->pcd_support = compat_param->pcd_support;
+ param->net_env_id = compat_pcd_id2ptr(compat_param->net_env_id);
+
+ if (param->p_cc_params)
+ compat_copy_fm_port_pcd_cc(compat_port_pcd_cc_params, param->p_cc_params, COMPAT_US_TO_K);
+ if (param->p_kg_params)
+ compat_copy_fm_port_pcd_kg(compat_port_pcd_kg_params, param->p_kg_params, COMPAT_US_TO_K);
+ if (param->p_plcr_params)
+ param->p_plcr_params->plcr_profile_id = compat_pcd_id2ptr(compat_port_pcd_plcr_params->plcr_profile_id);
+ param->p_ip_reassembly_manip = compat_pcd_id2ptr(compat_param->p_ip_reassembly_manip);
+ }
+}
+
+void compat_copy_fm_port_pcd_modify_tree(
+ ioc_compat_fm_obj_t *compat_id,
+ ioc_fm_obj_t *id,
+ uint8_t compat)
+{
+ if (compat == COMPAT_US_TO_K)
+ id->obj = compat_pcd_id2ptr(compat_id->obj);
+}
+
+#if (DPAA_VERSION >= 11)
+void compat_copy_fm_port_vsp_alloc_params(
+ ioc_compat_fm_port_vsp_alloc_params_t *compat_param,
+ ioc_fm_port_vsp_alloc_params_t *param,
+ uint8_t compat)
+{
+ if (compat == COMPAT_US_TO_K)
+ {
+ _fm_cpt_dbg(compat," param->p_fm_tx_port=%p \n", param->p_fm_tx_port);
+
+ param->dflt_relative_id = compat_param->dflt_relative_id;
+ param->num_of_profiles = compat_param->num_of_profiles;
+ param->p_fm_tx_port = compat_pcd_id2ptr(compat_param->p_fm_tx_port);
+ }
+}
+#endif /* (DPAA_VERSION >= 11) */
+
+void compat_copy_fm_pcd_net_env(
+ ioc_compat_fm_pcd_net_env_params_t *compat_param,
+ ioc_fm_pcd_net_env_params_t *param,
+ uint8_t compat)
+{
+ if (compat == COMPAT_US_TO_K)
+ {
+ param->num_of_distinction_units = compat_param->num_of_distinction_units;
+ memcpy(param->units, compat_param->units, sizeof(ioc_fm_pcd_distinction_unit_t)*IOC_FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS);
+ param->id = NULL; /* to avoid passing garbage to the kernel */
+ }
+ else
+ {
+ compat_param->num_of_distinction_units = param->num_of_distinction_units;
+ memcpy(compat_param->units, param->units, sizeof(ioc_fm_pcd_distinction_unit_t)*IOC_FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS);
+
+ compat_param->id = compat_add_ptr2id(param->id, FM_MAP_TYPE_PCD_NODE);
+ }
+}
+
+void compat_copy_fm_pcd_cc_node_modify_key(
+ ioc_compat_fm_pcd_cc_node_modify_key_params_t *compat_param,
+ ioc_fm_pcd_cc_node_modify_key_params_t *param,
+ uint8_t compat)
+{
+ if (compat == COMPAT_US_TO_K)
+ {
+ param->key_indx = compat_param->key_indx;
+ param->key_size = compat_param->key_size;
+ param->p_key = (uint8_t *)compat_ptr(compat_param->p_key);
+ _fm_cpt_dbg(compat," param->p_key = %p \n", param->p_key);
+ param->p_mask = (uint8_t *)compat_ptr(compat_param->p_mask);
+ _fm_cpt_dbg(compat," param->p_mask = %p\n", param->p_mask);
+ param->id = compat_pcd_id2ptr(compat_param->id);
+ _fm_cpt_dbg(compat," param->id = %p \n", param->id);
+ }
+ else
+ {
+ compat_param->key_indx = param->key_indx;
+ compat_param->key_size = param->key_size;
+ compat_param->p_key = ptr_to_compat((void *)param->p_key);
+ compat_param->p_mask = ptr_to_compat((void *)param->p_mask);
+
+ compat_param->id = compat_add_ptr2id(param->id, FM_MAP_TYPE_PCD_NODE);
+ }
+}
+
+void compat_copy_keys(
+ ioc_compat_keys_params_t *compat_param,
+ ioc_keys_params_t *param,
+ uint8_t compat)
+{
+ int k = 0;
+
+ _fm_cpt_dbg(compat," {->...\n");
+
+ if (compat == COMPAT_US_TO_K) {
+ param->max_num_of_keys = compat_param->max_num_of_keys;
+ param->mask_support = compat_param->mask_support;
+ param->statistics_mode = compat_param->statistics_mode;
+ param->num_of_keys = compat_param->num_of_keys;
+ param->key_size = compat_param->key_size;
+#if (DPAA_VERSION >= 11)
+ memcpy(&param->frame_length_ranges,
+ &compat_param->frame_length_ranges,
+ sizeof(param->frame_length_ranges[0] *
+ IOC_FM_PCD_CC_STATS_MAX_NUM_OF_FLR));
+#endif /* (DPAA_VERSION >= 11) */
+ }
+ else {
+ compat_param->max_num_of_keys = param->max_num_of_keys;
+ compat_param->mask_support = param->mask_support;
+ compat_param->statistics_mode = param->statistics_mode;
+ compat_param->num_of_keys = param->num_of_keys;
+ compat_param->key_size = param->key_size;
+#if (DPAA_VERSION >= 11)
+ memcpy(&compat_param->frame_length_ranges,
+ &param->frame_length_ranges,
+ sizeof(compat_param->frame_length_ranges[0] *
+ IOC_FM_PCD_CC_STATS_MAX_NUM_OF_FLR));
+#endif /* (DPAA_VERSION >= 11) */
+ }
+
+ for (k=0; k < IOC_FM_PCD_MAX_NUM_OF_KEYS; k++)
+ compat_copy_fm_pcd_cc_key(
+ &compat_param->key_params[k],
+ &param->key_params[k],
+ compat);
+
+ compat_copy_fm_pcd_cc_next_engine(
+ &compat_param->cc_next_engine_params_for_miss,
+ &param->cc_next_engine_params_for_miss,
+ compat);
+
+ _fm_cpt_dbg(compat," ...->}\n");
+}
+
+void compat_copy_fm_pcd_cc_node(
+ ioc_compat_fm_pcd_cc_node_params_t *compat_param,
+ ioc_fm_pcd_cc_node_params_t *param,
+ uint8_t compat)
+{
+ _fm_cpt_dbg(compat," {->...\n");
+
+ if (compat == COMPAT_US_TO_K)
+ memcpy(&param->extract_cc_params, &compat_param->extract_cc_params, sizeof(ioc_fm_pcd_extract_entry_t));
+
+ else
+ {
+ compat_copy_keys(&compat_param->keys_params, &param->keys_params, compat);
+
+ compat_param->id = compat_add_ptr2id(param->id, FM_MAP_TYPE_PCD_NODE);
+ _fm_cpt_dbg(compat," param->id = %p \n", param->id);
+ }
+
+ compat_copy_keys(&compat_param->keys_params, &param->keys_params, compat);
+
+ _fm_cpt_dbg(compat," ...->}\n");
+}
+
+void compat_fm_pcd_manip_set_node(
+ ioc_compat_fm_pcd_manip_params_t *compat_param,
+ ioc_fm_pcd_manip_params_t *param,
+ uint8_t compat)
+{
+ if (compat == COMPAT_US_TO_K) {
+ param->type = compat_param->type;
+ switch (param->type) {
+ case e_IOC_FM_PCD_MANIP_HDR:
+ param->u.hdr.rmv = compat_param->u.hdr.rmv;
+ memcpy(&param->u.hdr.rmv_params,
+ &compat_param->u.hdr.rmv_params,
+ sizeof(param->u.hdr.rmv_params));
+
+ param->u.hdr.insrt = compat_param->u.hdr.insrt;
+ param->u.hdr.insrt_params.type =
+ compat_param->u.hdr.insrt_params.type;
+ switch (compat_param->u.hdr.insrt_params.type)
+ {
+ case e_IOC_FM_PCD_MANIP_INSRT_GENERIC:
+ param->u.hdr.insrt_params.u.generic.offset =
+ compat_param->u.hdr.insrt_params.u.generic.offset;
+ param->u.hdr.insrt_params.u.generic.size =
+ compat_param->u.hdr.insrt_params.u.generic.size;
+ param->u.hdr.insrt_params.u.generic.replace =
+ compat_param->u.hdr.insrt_params.u.generic.replace;
+ param->u.hdr.insrt_params.u.generic.p_data =
+ compat_ptr(compat_param->u.hdr.insrt_params.u.generic.p_data);
+ break;
+ case e_IOC_FM_PCD_MANIP_INSRT_BY_HDR:
+ param->u.hdr.insrt_params.u.by_hdr.type =
+ compat_param->u.hdr.insrt_params.u.by_hdr.type;
+ param->u.hdr.insrt_params.u.by_hdr.u.specific_l2_params.specific_l2 =
+ compat_param->u.hdr.insrt_params.u.by_hdr.u.specific_l2_params.specific_l2;
+ param->u.hdr.insrt_params.u.by_hdr.u.specific_l2_params.update =
+ compat_param->u.hdr.insrt_params.u.by_hdr.u.specific_l2_params.update;
+ param->u.hdr.insrt_params.u.by_hdr.u.specific_l2_params.size =
+ compat_param->u.hdr.insrt_params.u.by_hdr.u.specific_l2_params.size;
+ param->u.hdr.insrt_params.u.by_hdr.u.specific_l2_params.p_data =
+ compat_ptr(compat_param->u.hdr.insrt_params.u.by_hdr.u.specific_l2_params.p_data);
+ break;
+ default:
+ _fm_cpt_err("Unsupported type: %d", compat_param->u.hdr.insrt_params.type);
+ }
+
+ param->u.hdr.field_update = compat_param->u.hdr.field_update;
+ memcpy(&param->u.hdr.field_update_params,
+ &compat_param->u.hdr.field_update_params,
+ sizeof(param->u.hdr.field_update_params));
+
+ param->u.hdr.custom = compat_param->u.hdr.custom;
+ memcpy(&param->u.hdr.custom_params,
+ &compat_param->u.hdr.custom_params,
+ sizeof(param->u.hdr.custom_params));
+
+ param->u.hdr.dont_parse_after_manip =
+ compat_param->u.hdr.dont_parse_after_manip;
+ break;
+ case e_IOC_FM_PCD_MANIP_REASSEM:
+ memcpy(&param->u.reassem, &compat_param->u.reassem, sizeof(param->u.reassem));
+ break;
+ case e_IOC_FM_PCD_MANIP_FRAG:
+ memcpy(&param->u.frag, &compat_param->u.frag, sizeof(param->u.frag));
+ break;
+ case e_IOC_FM_PCD_MANIP_SPECIAL_OFFLOAD:
+ param->u.special_offload = compat_param->u.special_offload;
+ break;
+ }
+
+ param->p_next_manip = compat_pcd_id2ptr(compat_param->p_next_manip);
+ param->id = compat_pcd_id2ptr(compat_param->id);
+ }
+ else {
+ compat_param->type = param->type;
+ memcpy(&compat_param->u, &param->u, sizeof(compat_param->u));
+
+ if (param->type == e_IOC_FM_PCD_MANIP_HDR &&
+ param->u.hdr.insrt_params.type == e_IOC_FM_PCD_MANIP_INSRT_GENERIC)
+ compat_param->u.hdr.insrt_params.u.generic.p_data =
+ ptr_to_compat(param->u.hdr.insrt_params.u.generic.p_data);
+
+ compat_param->p_next_manip = compat_pcd_ptr2id(param->id);
+ /* ... should be one that was added previously by the very call to
+ compat_add_ptr2id() below: */
+ compat_param->id = compat_add_ptr2id(param->id, FM_MAP_TYPE_PCD_NODE);
+ }
+}
+
+#if (DPAA_VERSION >= 11)
+void compat_copy_fm_pcd_frm_replic_group_params(
+ ioc_compat_fm_pcd_frm_replic_group_params_t *compat_param,
+ ioc_fm_pcd_frm_replic_group_params_t *param,
+ uint8_t compat)
+{
+ int k;
+
+ _fm_cpt_dbg (compat, " {->...\n");
+
+ if (compat == COMPAT_US_TO_K)
+ {
+ param->max_num_of_entries = compat_param->max_num_of_entries;
+ param->num_of_entries = compat_param->num_of_entries;
+ param->id = compat_pcd_id2ptr(compat_param->id);
+ }
+ else
+ {
+ compat_param->max_num_of_entries = param->max_num_of_entries;
+ compat_param->num_of_entries = param->num_of_entries;
+ compat_param->id = compat_add_ptr2id(param->id,
+ FM_MAP_TYPE_PCD_NODE);
+ }
+
+ for (k=0; k < IOC_FM_PCD_FRM_REPLIC_MAX_NUM_OF_ENTRIES; k++)
+ compat_copy_fm_pcd_cc_next_engine(
+ &compat_param->next_engine_params[k],
+ &param->next_engine_params[k],
+ compat);
+
+ _fm_cpt_dbg (compat, " ...->}\n");
+}
+
+void compat_copy_fm_pcd_frm_replic_member(
+ ioc_compat_fm_pcd_frm_replic_member_t *compat_param,
+ ioc_fm_pcd_frm_replic_member_t *param,
+ uint8_t compat)
+{
+ _fm_cpt_dbg (compat, " {->...\n");
+
+ if (compat == COMPAT_US_TO_K)
+ {
+ param->h_replic_group = compat_pcd_id2ptr(compat_param->h_replic_group);
+ param->member_index = compat_param->member_index;
+ }
+
+ _fm_cpt_dbg (compat, " ...->}\n");
+}
+
+void compat_copy_fm_pcd_frm_replic_member_params(
+ ioc_compat_fm_pcd_frm_replic_member_params_t *compat_param,
+ ioc_fm_pcd_frm_replic_member_params_t *param,
+ uint8_t compat)
+{
+ _fm_cpt_dbg (compat, " {->...\n");
+
+ compat_copy_fm_pcd_frm_replic_member(&compat_param->member,
+ &param->member, compat);
+
+ compat_copy_fm_pcd_cc_next_engine(&compat_param->next_engine_params,
+ &param->next_engine_params, compat);
+
+ _fm_cpt_dbg (compat, " ...->}\n");
+}
+
+void compat_copy_fm_vsp_params(
+ ioc_compat_fm_vsp_params_t *compat_param,
+ ioc_fm_vsp_params_t *param,
+ uint8_t compat)
+{
+ _fm_cpt_dbg (compat, " {->...\n");
+
+ if (compat == COMPAT_US_TO_K)
+ {
+ param->p_fm = compat_pcd_id2ptr(compat_param->p_fm);
+ memcpy(&param->ext_buf_pools, &compat_param->ext_buf_pools, sizeof(ioc_fm_ext_pools));
+ param->liodn_offset = compat_param->liodn_offset;
+ param->portParams.port_id = compat_param->portParams.port_id;
+ param->portParams.port_type = compat_param->portParams.port_type;
+ param->relative_profile_id = compat_param->relative_profile_id;
+ param->id = compat_pcd_id2ptr(compat_param->id);
+ }
+ else
+ {
+ compat_param->p_fm = compat_pcd_ptr2id(param->p_fm);
+ memcpy(&compat_param->ext_buf_pools, &param->ext_buf_pools, sizeof(ioc_fm_ext_pools));
+ compat_param->liodn_offset = param->liodn_offset;
+ compat_param->portParams.port_id = param->portParams.port_id;
+ compat_param->portParams.port_type = param->portParams.port_type;
+ compat_param->relative_profile_id = param->relative_profile_id;
+ compat_param->id = compat_add_ptr2id(param->id, FM_MAP_TYPE_PCD_NODE);
+ }
+
+ _fm_cpt_dbg (compat, " ...->}\n");
+}
+
+void compat_copy_fm_buf_pool_depletion_params(
+ ioc_compat_fm_buf_pool_depletion_params_t *compat_param,
+ ioc_fm_buf_pool_depletion_params_t *param,
+ uint8_t compat)
+{
+ _fm_cpt_dbg (compat, " {->...\n");
+
+ if (compat == COMPAT_US_TO_K)
+ {
+ param->p_fm_vsp = compat_pcd_id2ptr(compat_param->p_fm_vsp);
+ memcpy(&param->fm_buf_pool_depletion,
+ &compat_param->fm_buf_pool_depletion,
+ sizeof(ioc_fm_buf_pool_depletion_t));
+ }
+
+ _fm_cpt_dbg (compat, " ...->}\n");
+}
+
+void compat_copy_fm_buffer_prefix_content_params(
+ ioc_compat_fm_buffer_prefix_content_params_t *compat_param,
+ ioc_fm_buffer_prefix_content_params_t *param,
+ uint8_t compat)
+{
+ _fm_cpt_dbg (compat, " {->...\n");
+
+ if (compat == COMPAT_US_TO_K)
+ {
+ param->p_fm_vsp = compat_pcd_id2ptr(compat_param->p_fm_vsp);
+ memcpy(&param->fm_buffer_prefix_content,
+ &compat_param->fm_buffer_prefix_content,
+ sizeof(ioc_fm_buffer_prefix_content_t));
+ }
+
+ _fm_cpt_dbg (compat, " ...->}\n");
+}
+
+void compat_copy_fm_vsp_config_no_sg_params(
+ ioc_compat_fm_vsp_config_no_sg_params_t *compat_param,
+ ioc_fm_vsp_config_no_sg_params_t *param,
+ uint8_t compat)
+{
+ _fm_cpt_dbg (compat, " {->...\n");
+
+ if (compat == COMPAT_US_TO_K)
+ {
+ param->p_fm_vsp = compat_pcd_id2ptr(compat_param->p_fm_vsp);
+ param->no_sg = compat_param->no_sg;
+ }
+
+ _fm_cpt_dbg (compat, " ...->}\n");
+}
+
+void compat_copy_fm_vsp_prs_result_params(
+ ioc_compat_fm_vsp_prs_result_params_t *compat_param,
+ ioc_fm_vsp_prs_result_params_t *param,
+ uint8_t compat)
+{
+ _fm_cpt_dbg (compat, " {->...\n");
+
+ if (compat == COMPAT_US_TO_K)
+ {
+ param->p_fm_vsp = compat_pcd_id2ptr(compat_param->p_fm_vsp);
+ /* p_data is an user-space pointer that needs to remain unmodified */
+ param->p_data = (void *)(unsigned long long)compat_param->p_data;
+ }
+ else
+ {
+ compat_param->p_fm_vsp = compat_pcd_ptr2id(param->p_fm_vsp);
+ /* p_data is an user-space pointer that needs to remain unmodified */
+ compat_param->p_data = (compat_uptr_t)((unsigned long long)param->p_data & 0xFFFFFFFF);
+ }
+
+ _fm_cpt_dbg (compat, " ...->}\n");
+}
+#endif /* (DPAA_VERSION >= 11) */
diff --git a/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_ioctls_fm_compat.h b/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_ioctls_fm_compat.h
new file mode 100644
index 0000000..e8e6677
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_ioctls_fm_compat.h
@@ -0,0 +1,679 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * 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 Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * 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 Freescale Semiconductor ``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 Freescale Semiconductor 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.
+ */
+
+/*
+ @File lnxwrp_ioctls_fm_compat.h
+
+ @Description FM PCD compat structures definition.
+
+*/
+
+#ifndef __FM_COMPAT_IOCTLS_H
+#define __FM_COMPAT_IOCTLS_H
+
+#include <linux/compat.h>
+
+#define COMPAT_K_TO_US 0 /* copy from Kernel to User */
+#define COMPAT_US_TO_K 1 /* copy from User to Kernel */
+#define COMPAT_GENERIC 2
+
+#define COMPAT_COPY_K2US(dest, src, type) compat_copy_##type(src, dest, 0)
+#define COMPAT_COPY_US2K(dest, src, type) compat_copy_##type(dest, src, 1)
+
+/* mapping kernel pointers w/ UserSpace id's { */
+/* Because compat_ptr(ptr_to_compat(X)) != X, this way we cannot exchange pointers
+ back and forth (US - KS). compat_ptr is a cast and pointers are broken. */
+#define COMPAT_PTR2ID_ARRAY_MAX (256+1) /* first location is not used */
+#define COMPAT_PTR2ID_WATERMARK 0xface0000
+#define COMPAT_PTR2ID_WM_MASK 0xffff0000
+
+/* define it for debug trace */
+/*#define FM_COMPAT_DBG*/
+
+#define _fm_cpt_prk(stage, format, arg...) \
+ printk(stage "fm_cpt (cpu:%u): " format, raw_smp_processor_id(), ##arg)
+
+#define _fm_cpt_inf(format, arg...) _fm_cpt_prk(KERN_INFO, format, ##arg)
+#define _fm_cpt_wrn(format, arg...) _fm_cpt_prk(KERN_WARNING, format, ##arg)
+#define _fm_cpt_err(format, arg...) _fm_cpt_prk(KERN_ERR, format, ##arg)
+
+/* used for compat IOCTL debugging */
+#if defined(FM_COMPAT_DBG)
+ #define _fm_cpt_dbg(from, format, arg...) \
+ do{ \
+ if (from == COMPAT_US_TO_K) \
+ printk("fm_cpt to KS [%s:%u](cpu:%u) - " format, \
+ __func__, __LINE__, raw_smp_processor_id(), ##arg); \
+ else if (from == COMPAT_K_TO_US) \
+ printk("fm_cpt to US [%s:%u](cpu:%u) - " format, \
+ __func__, __LINE__, raw_smp_processor_id(), ##arg); \
+ else \
+ printk("fm_cpt [%s:%u](cpu:%u) - " format, \
+ __func__, __LINE__, raw_smp_processor_id(), ##arg); \
+ }while(0)
+#else
+# define _fm_cpt_dbg(arg...)
+#endif
+
+/*TODO: per FMan module:
+ *
+ * Parser: FM_MAP_TYPE_PARSER_NODE,
+ * Kg: FM_MAP_TYPE_KG_NODE,
+ * Policer: FM_MAP_TYPE_POLICER_NODE
+ * Manip: FM_MAP_TYPE_MANIP_NODE
+ **/
+enum fm_map_node_type {
+ FM_MAP_TYPE_UNSPEC = 0,
+ FM_MAP_TYPE_PCD_NODE,
+
+ /* add types here, update the policy */
+
+ __FM_MAP_TYPE_AFTER_LAST,
+ FM_MAP_TYPE_MAX = __FM_MAP_TYPE_AFTER_LAST - 1
+};
+
+void compat_del_ptr2id(void *p, enum fm_map_node_type);
+compat_uptr_t compat_add_ptr2id(void *p, enum fm_map_node_type);
+compat_uptr_t compat_get_ptr2id(void *p, enum fm_map_node_type);
+void *compat_get_id2ptr(compat_uptr_t comp, enum fm_map_node_type);
+
+static inline compat_uptr_t compat_pcd_ptr2id(void *ptr) {
+ return (ptr)? compat_get_ptr2id(ptr, FM_MAP_TYPE_PCD_NODE)
+ : (compat_uptr_t) 0;
+}
+
+static inline void *compat_pcd_id2ptr(compat_uptr_t id) {
+ return (id) ? compat_get_id2ptr(id, FM_MAP_TYPE_PCD_NODE)
+ : NULL;
+}
+
+/* other similar inlines may be added as new nodes are added
+ to enum fm_map_node_type above... */
+/* } mapping kernel pointers w/ UserSpace id's */
+
+/* pcd compat structures { */
+typedef struct ioc_compat_fm_pcd_cc_node_remove_key_params_t {
+ compat_uptr_t id;
+ uint16_t key_indx;
+} ioc_compat_fm_pcd_cc_node_remove_key_params_t;
+
+typedef union ioc_compat_fm_pcd_plcr_next_engine_params_u {
+ ioc_fm_pcd_done_action action;
+ compat_uptr_t p_profile;
+ compat_uptr_t p_direct_scheme;
+} ioc_compat_fm_pcd_plcr_next_engine_params_u;
+
+typedef struct ioc_compat_fm_pcd_plcr_profile_params_t {
+ bool modify;
+ union {
+ struct {
+ ioc_fm_pcd_profile_type_selection profile_type;
+ compat_uptr_t p_fm_port;
+ uint16_t relative_profile_id;
+ } new_params;
+ compat_uptr_t p_profile;
+ } profile_select;
+ ioc_fm_pcd_plcr_algorithm_selection alg_selection;
+ ioc_fm_pcd_plcr_color_mode color_mode;
+
+ union {
+ ioc_fm_pcd_plcr_color dflt_color;
+ ioc_fm_pcd_plcr_color override;
+ } color;
+
+ ioc_fm_pcd_plcr_non_passthrough_alg_param_t non_passthrough_alg_param;
+
+ ioc_fm_pcd_engine next_engine_on_green;
+ ioc_compat_fm_pcd_plcr_next_engine_params_u params_on_green;
+
+ ioc_fm_pcd_engine next_engine_on_yellow;
+ ioc_compat_fm_pcd_plcr_next_engine_params_u params_on_yellow;
+
+ ioc_fm_pcd_engine next_engine_on_red;
+ ioc_compat_fm_pcd_plcr_next_engine_params_u params_on_red;
+
+ bool trap_profile_on_flow_A;
+ bool trap_profile_on_flow_B;
+ bool trap_profile_on_flow_C;
+ compat_uptr_t id;
+} ioc_compat_fm_pcd_plcr_profile_params_t;
+
+typedef struct ioc_compat_fm_obj_t {
+ compat_uptr_t obj;
+} ioc_compat_fm_obj_t;
+
+typedef struct ioc_compat_fm_pcd_kg_scheme_select_t {
+ bool direct;
+ compat_uptr_t scheme_id;
+} ioc_compat_fm_pcd_kg_scheme_select_t;
+
+typedef struct ioc_compat_fm_pcd_port_schemes_params_t {
+ uint8_t num_of_schemes;
+ compat_uptr_t scheme_ids[FM_PCD_KG_NUM_OF_SCHEMES];
+} ioc_compat_fm_pcd_port_schemes_params_t;
+
+#if (DPAA_VERSION >= 11)
+typedef struct ioc_compat_fm_port_vsp_alloc_params_t {
+ uint8_t num_of_profiles; /**< Number of Virtual Storage Profiles */
+ uint8_t dflt_relative_id; /**< The default Virtual-Storage-Profile-id dedicated to Rx/OP port
+ The same default Virtual-Storage-Profile-id will be for coupled Tx port
+ if relevant function called for Rx port */
+ compat_uptr_t p_fm_tx_port; /**< Handle to coupled Tx Port; not relevant for OP port. */
+}ioc_compat_fm_port_vsp_alloc_params_t;
+#endif /* (DPAA_VERSION >= 11) */
+
+typedef struct ioc_compat_fm_pcd_net_env_params_t {
+ uint8_t num_of_distinction_units;
+ ioc_fm_pcd_distinction_unit_t units[IOC_FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS]; /* same structure*/
+ compat_uptr_t id;
+} ioc_compat_fm_pcd_net_env_params_t;
+
+typedef struct ioc_compat_fm_pcd_prs_sw_params_t {
+ bool override;
+ uint32_t size;
+ uint16_t base;
+ compat_uptr_t p_code;
+ uint32_t sw_prs_data_params[IOC_FM_PCD_PRS_NUM_OF_HDRS];
+ uint8_t num_of_labels;
+ ioc_fm_pcd_prs_label_params_t labels_table[IOC_FM_PCD_PRS_NUM_OF_LABELS];
+} ioc_compat_fm_pcd_prs_sw_params_t;
+
+typedef struct ioc_compat_fm_pcd_cc_next_kg_params_t {
+ bool override_fqid;
+ uint32_t new_fqid;
+#if DPAA_VERSION >= 11
+ uint8_t new_relative_storage_profile_id;
+#endif
+ compat_uptr_t p_direct_scheme;
+} ioc_compat_fm_pcd_cc_next_kg_params_t;
+
+typedef struct ioc_compat_fm_pcd_cc_next_cc_params_t {
+ compat_uptr_t cc_node_id;
+} ioc_compat_fm_pcd_cc_next_cc_params_t;
+
+#if DPAA_VERSION >= 11
+typedef struct ioc_compat_fm_pcd_cc_next_fr_params_t {
+ compat_uptr_t frm_replic_id;
+} ioc_compat_fm_pcd_cc_next_fr_params_t;
+#endif /* DPAA_VERSION >= 11 */
+
+typedef struct ioc_compat_fm_pcd_cc_next_engine_params_t {
+ ioc_fm_pcd_engine next_engine;
+ union {
+ ioc_compat_fm_pcd_cc_next_cc_params_t cc_params; /**< compat structure*/
+ ioc_fm_pcd_cc_next_plcr_params_t plcr_params; /**< same structure*/
+ ioc_fm_pcd_cc_next_enqueue_params_t enqueue_params; /**< same structure*/
+ ioc_compat_fm_pcd_cc_next_kg_params_t kg_params; /**< compat structure*/
+#if DPAA_VERSION >= 11
+ ioc_compat_fm_pcd_cc_next_fr_params_t fr_params; /**< compat structure*/
+#endif /* DPAA_VERSION >= 11 */
+ } params;
+ compat_uptr_t manip_id;
+ bool statistics_en;
+} ioc_compat_fm_pcd_cc_next_engine_params_t;
+
+typedef struct ioc_compat_fm_pcd_cc_grp_params_t {
+ uint8_t num_of_distinction_units;
+ uint8_t unit_ids [IOC_FM_PCD_MAX_NUM_OF_CC_UNITS];
+ ioc_compat_fm_pcd_cc_next_engine_params_t next_engine_per_entries_in_grp[IOC_FM_PCD_MAX_NUM_OF_CC_ENTRIES_IN_GRP];
+} ioc_compat_fm_pcd_cc_grp_params_t;
+
+typedef struct ioc_compat_fm_pcd_cc_tree_params_t {
+ compat_uptr_t net_env_id;
+ uint8_t num_of_groups;
+ ioc_compat_fm_pcd_cc_grp_params_t fm_pcd_cc_group_params [IOC_FM_PCD_MAX_NUM_OF_CC_GROUPS];
+ compat_uptr_t id;
+} ioc_compat_fm_pcd_cc_tree_params_t;
+
+typedef struct ioc_compat_fm_pcd_cc_tree_modify_next_engine_params_t {
+ compat_uptr_t id;
+ uint8_t grp_indx;
+ uint8_t indx;
+ ioc_compat_fm_pcd_cc_next_engine_params_t cc_next_engine_params;
+} ioc_compat_fm_pcd_cc_tree_modify_next_engine_params_t;
+
+typedef struct ioc_compat_fm_pcd_cc_key_params_t {
+ compat_uptr_t p_key;
+ compat_uptr_t p_mask;
+ ioc_compat_fm_pcd_cc_next_engine_params_t cc_next_engine_params; /**< compat structure*/
+} ioc_compat_fm_pcd_cc_key_params_t;
+
+typedef struct ioc_compat_keys_params_t {
+ uint16_t max_num_of_keys;
+ bool mask_support;
+ ioc_fm_pcd_cc_stats_mode statistics_mode;
+#if (DPAA_VERSION >= 11)
+ uint16_t frame_length_ranges[IOC_FM_PCD_CC_STATS_MAX_NUM_OF_FLR];
+#endif /* (DPAA_VERSION >= 11) */
+ uint16_t num_of_keys;
+ uint8_t key_size;
+ ioc_compat_fm_pcd_cc_key_params_t key_params[IOC_FM_PCD_MAX_NUM_OF_KEYS]; /**< compat structure*/
+ ioc_compat_fm_pcd_cc_next_engine_params_t cc_next_engine_params_for_miss; /**< compat structure*/
+} ioc_compat_keys_params_t;
+
+typedef struct ioc_compat_fm_pcd_cc_node_params_t {
+ ioc_fm_pcd_extract_entry_t extract_cc_params; /**< same structure*/
+ ioc_compat_keys_params_t keys_params; /**< compat structure*/
+ compat_uptr_t id;
+} ioc_compat_fm_pcd_cc_node_params_t;
+
+/**************************************************************************//**
+ @Description Parameters for defining a hash table
+*//***************************************************************************/
+typedef struct ioc_compat_fm_pcd_hash_table_params_t {
+ uint16_t max_num_of_keys;
+ ioc_fm_pcd_cc_stats_mode statistics_mode;
+ uint16_t hash_res_mask;
+ uint8_t hash_shift;
+ uint8_t match_key_size;
+ ioc_compat_fm_pcd_cc_next_engine_params_t cc_next_engine_params_for_miss;
+ compat_uptr_t id;
+} ioc_compat_fm_pcd_hash_table_params_t;
+
+typedef struct ioc_compat_fm_pcd_hash_table_add_key_params_t {
+ compat_uptr_t p_hash_tbl;
+ uint8_t key_size;
+ ioc_compat_fm_pcd_cc_key_params_t key_params;
+} ioc_compat_fm_pcd_hash_table_add_key_params_t;
+
+typedef struct ioc_compat_fm_pcd_cc_node_modify_key_params_t {
+ compat_uptr_t id;
+ uint16_t key_indx;
+ uint8_t key_size;
+ compat_uptr_t p_key;
+ compat_uptr_t p_mask;
+} ioc_compat_fm_pcd_cc_node_modify_key_params_t;
+
+typedef struct ioc_compat_fm_pcd_hash_table_remove_key_params_t {
+ compat_uptr_t p_hash_tbl;
+ uint8_t key_size;
+ compat_uptr_t p_key;
+} ioc_compat_fm_pcd_hash_table_remove_key_params_t;
+
+typedef struct ioc_compat_fm_pcd_cc_node_modify_key_and_next_engine_params_t {
+ compat_uptr_t id;
+ uint16_t key_indx;
+ uint8_t key_size;
+ ioc_compat_fm_pcd_cc_key_params_t key_params;
+} ioc_compat_fm_pcd_cc_node_modify_key_and_next_engine_params_t;
+
+typedef struct ioc_compat_fm_port_pcd_plcr_params_t {
+ compat_uptr_t plcr_profile_id;
+} ioc_compat_fm_port_pcd_plcr_params_t;
+
+typedef struct ioc_compat_fm_port_pcd_cc_params_t {
+ compat_uptr_t cc_tree_id;
+} ioc_compat_fm_port_pcd_cc_params_t;
+
+typedef struct ioc_compat_fm_port_pcd_kg_params_t {
+ uint8_t num_of_schemes;
+ compat_uptr_t scheme_ids[FM_PCD_KG_NUM_OF_SCHEMES];
+ bool direct_scheme;
+ compat_uptr_t direct_scheme_id;
+} ioc_compat_fm_port_pcd_kg_params_t;
+
+typedef struct ioc_compat_fm_port_pcd_params_t {
+ ioc_fm_port_pcd_support pcd_support;
+ compat_uptr_t net_env_id;
+ compat_uptr_t p_prs_params;
+ compat_uptr_t p_cc_params;
+ compat_uptr_t p_kg_params;
+ compat_uptr_t p_plcr_params;
+ compat_uptr_t p_ip_reassembly_manip;
+} ioc_compat_fm_port_pcd_params_t;
+
+typedef struct ioc_compat_fm_pcd_kg_cc_t {
+ compat_uptr_t tree_id;
+ uint8_t grp_id;
+ bool plcr_next;
+ bool bypass_plcr_profile_generation;
+ ioc_fm_pcd_kg_plcr_profile_t plcr_profile;
+} ioc_compat_fm_pcd_kg_cc_t;
+
+typedef struct ioc_compat_fm_pcd_kg_scheme_params_t {
+ bool modify;
+ union {
+ uint8_t relative_scheme_id;
+ compat_uptr_t scheme_id;
+ } scm_id;
+ bool always_direct;
+ struct {
+ compat_uptr_t net_env_id;
+ uint8_t num_of_distinction_units;
+ uint8_t unit_ids[IOC_FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS];
+ } net_env_params;
+ bool use_hash;
+ ioc_fm_pcd_kg_key_extract_and_hash_params_t key_extract_and_hash_params;
+ bool bypass_fqid_generation;
+ uint32_t base_fqid;
+ uint8_t num_of_used_extracted_ors;
+ ioc_fm_pcd_kg_extracted_or_params_t extracted_ors[IOC_FM_PCD_KG_NUM_OF_GENERIC_REGS];
+#if DPAA_VERSION >= 11
+ bool override_storage_profile;
+ ioc_fm_pcd_kg_storage_profile_t storage_profile;
+#endif /* DPAA_VERSION >= 11 */
+ ioc_fm_pcd_engine next_engine;
+ union{
+ ioc_fm_pcd_done_action done_action;
+ ioc_fm_pcd_kg_plcr_profile_t plcr_profile;
+ ioc_compat_fm_pcd_kg_cc_t cc;
+ } kg_next_engine_params;
+ ioc_fm_pcd_kg_scheme_counter_t scheme_counter;
+ compat_uptr_t id;
+} ioc_compat_fm_pcd_kg_scheme_params_t;
+
+typedef struct ioc_compat_fm_pcd_cc_node_modify_next_engine_params_t {
+ compat_uptr_t id;
+ uint16_t key_indx;
+ uint8_t key_size;
+ ioc_compat_fm_pcd_cc_next_engine_params_t cc_next_engine_params;
+} ioc_compat_fm_pcd_cc_node_modify_next_engine_params_t;
+
+typedef struct ioc_compat_fm_pcd_manip_hdr_insrt_generic_params_t {
+ uint8_t offset;
+ uint8_t size;
+ bool replace;
+ compat_uptr_t p_data;
+} ioc_compat_fm_pcd_manip_hdr_insrt_generic_params_t;
+
+typedef struct ioc_compat_fm_pcd_manip_hdr_insrt_specific_l2_params_t {
+ ioc_fm_pcd_manip_hdr_insrt_specific_l2 specific_l2;
+ bool update;
+ uint8_t size;
+ compat_uptr_t p_data;
+} ioc_compat_fm_pcd_manip_hdr_insrt_specific_l2_params_t;
+
+typedef struct ioc_compat_fm_pcd_manip_hdr_insrt_by_hdr_params_t {
+ ioc_fm_pcd_manip_hdr_insrt_by_hdr_type type;
+ union {
+ ioc_compat_fm_pcd_manip_hdr_insrt_specific_l2_params_t specific_l2_params;
+ } u;
+} ioc_compat_fm_pcd_manip_hdr_insrt_by_hdr_params_t;
+
+typedef struct ioc_compat_fm_pcd_manip_hdr_insrt_params_t {
+ ioc_fm_pcd_manip_hdr_insrt_type type;
+ union {
+ ioc_compat_fm_pcd_manip_hdr_insrt_by_hdr_params_t by_hdr;
+ ioc_compat_fm_pcd_manip_hdr_insrt_generic_params_t generic;
+#ifdef FM_CAPWAP_SUPPORT
+#error CAPWAP not supported!
+ ioc_fm_pcd_manip_hdr_insrt_by_template_params_t by_template;
+#endif /* FM_CAPWAP_SUPPORT */
+ } u;
+} ioc_compat_fm_pcd_manip_hdr_insrt_params_t;
+
+typedef struct ioc_compat_fm_pcd_manip_hdr_params_t {
+ bool rmv;
+ ioc_fm_pcd_manip_hdr_rmv_params_t rmv_params;
+ bool insrt;
+ ioc_compat_fm_pcd_manip_hdr_insrt_params_t insrt_params;
+ bool field_update;
+ ioc_fm_pcd_manip_hdr_field_update_params_t field_update_params;
+ bool custom;
+ ioc_fm_pcd_manip_hdr_custom_params_t custom_params;
+ bool dont_parse_after_manip;
+} ioc_compat_fm_pcd_manip_hdr_params_t;
+
+typedef struct ioc_compat_fm_pcd_manip_params_t {
+ ioc_fm_pcd_manip_type type;
+ union {
+ ioc_compat_fm_pcd_manip_hdr_params_t hdr;
+ ioc_fm_pcd_manip_reassem_params_t reassem;
+ ioc_fm_pcd_manip_frag_params_t frag;
+ ioc_fm_pcd_manip_special_offload_params_t special_offload;
+ } u;
+ compat_uptr_t p_next_manip;
+#ifdef FM_CAPWAP_SUPPORT
+#error "FM_CAPWAP_SUPPORT feature not supported!"
+ bool frag_or_reasm;
+ ioc_fm_pcd_manip_frag_or_reasm_params_t frag_or_reasm_params;
+#endif /* FM_CAPWAP_SUPPORT */
+ compat_uptr_t id;
+} ioc_compat_fm_pcd_manip_params_t;
+
+#if (DPAA_VERSION >= 11)
+typedef struct ioc_compat_fm_pcd_frm_replic_group_params_t {
+ uint8_t max_num_of_entries;
+ uint8_t num_of_entries;
+ ioc_compat_fm_pcd_cc_next_engine_params_t
+ next_engine_params[IOC_FM_PCD_FRM_REPLIC_MAX_NUM_OF_ENTRIES];
+ compat_uptr_t id;
+} ioc_compat_fm_pcd_frm_replic_group_params_t;
+
+typedef struct ioc_compat_fm_pcd_frm_replic_member_t {
+ compat_uptr_t h_replic_group;
+ uint16_t member_index;
+} ioc_compat_fm_pcd_frm_replic_member_t;
+
+typedef struct ioc_compat_fm_pcd_frm_replic_member_params_t {
+ ioc_compat_fm_pcd_frm_replic_member_t member;
+ ioc_compat_fm_pcd_cc_next_engine_params_t next_engine_params;
+} ioc_compat_fm_pcd_frm_replic_member_params_t;
+
+typedef struct ioc_compat_fm_vsp_params_t {
+ compat_uptr_t p_fm; /**< A handle to the FM object this VSP related to */
+ ioc_fm_ext_pools ext_buf_pools; /**< Which external buffer pools are used
+ (up to FM_PORT_MAX_NUM_OF_EXT_POOLS), and their sizes.
+ parameter associated with Rx / OP port */
+ uint16_t liodn_offset; /**< VSP's LIODN offset */
+ struct {
+ ioc_fm_port_type port_type; /**< Port type */
+ uint8_t port_id; /**< Port Id - relative to type */
+ } portParams;
+ uint8_t relative_profile_id; /**< VSP Id - relative to VSP's range
+ defined in relevant FM object */
+ compat_uptr_t id; /**< return value */
+} ioc_compat_fm_vsp_params_t;
+
+typedef struct ioc_compat_fm_buf_pool_depletion_params_t {
+ compat_uptr_t p_fm_vsp;
+ ioc_fm_buf_pool_depletion_t fm_buf_pool_depletion;
+} ioc_compat_fm_buf_pool_depletion_params_t;
+
+typedef struct ioc_compat_fm_buffer_prefix_content_params_t {
+ compat_uptr_t p_fm_vsp;
+ ioc_fm_buffer_prefix_content_t fm_buffer_prefix_content;
+} ioc_compat_fm_buffer_prefix_content_params_t;
+
+typedef struct ioc_compat_fm_vsp_config_no_sg_params_t {
+ compat_uptr_t p_fm_vsp;
+ bool no_sg;
+} ioc_compat_fm_vsp_config_no_sg_params_t;
+
+typedef struct ioc_compat_fm_vsp_prs_result_params_t {
+ compat_uptr_t p_fm_vsp;
+ compat_uptr_t p_data;
+} ioc_compat_fm_vsp_prs_result_params_t;
+#endif /* (DPAA_VERSION >= 11) */
+
+typedef struct ioc_compat_fm_ctrl_mon_counters_params_t {
+ uint8_t fm_ctrl_index;
+ compat_uptr_t p_mon;
+} ioc_compat_fm_ctrl_mon_counters_params_t;
+
+/* } pcd compat structures */
+
+void compat_obj_delete(
+ ioc_compat_fm_obj_t *compat_id,
+ ioc_fm_obj_t *id);
+
+/* pcd compat functions { */
+void compat_copy_fm_pcd_plcr_profile(
+ ioc_compat_fm_pcd_plcr_profile_params_t *compat_param,
+ ioc_fm_pcd_plcr_profile_params_t *param,
+ uint8_t compat);
+
+void compat_copy_fm_pcd_cc_key(
+ ioc_compat_fm_pcd_cc_key_params_t *compat_param,
+ ioc_fm_pcd_cc_key_params_t *param,
+ uint8_t compat);
+
+void compat_copy_fm_pcd_cc_node_modify_key_and_next_engine(
+ ioc_compat_fm_pcd_cc_node_modify_key_and_next_engine_params_t *compat_param,
+ ioc_fm_pcd_cc_node_modify_key_and_next_engine_params_t *param,
+ uint8_t compat);
+
+void compat_copy_fm_pcd_cc_node_modify_next_engine(
+ ioc_compat_fm_pcd_cc_node_modify_next_engine_params_t *compat_param,
+ ioc_fm_pcd_cc_node_modify_next_engine_params_t *param,
+ uint8_t compat);
+
+void compat_fm_pcd_cc_tree_modify_next_engine(
+ ioc_compat_fm_pcd_cc_tree_modify_next_engine_params_t *compat_param,
+ ioc_fm_pcd_cc_tree_modify_next_engine_params_t *param,
+ uint8_t compat);
+
+void compat_copy_fm_pcd_hash_table(
+ ioc_compat_fm_pcd_hash_table_params_t *compat_param,
+ ioc_fm_pcd_hash_table_params_t *param,
+ uint8_t compat);
+
+void compat_copy_fm_pcd_cc_grp(
+ ioc_compat_fm_pcd_cc_grp_params_t *compat_param,
+ ioc_fm_pcd_cc_grp_params_t *param,
+ uint8_t compat);
+
+void compat_copy_fm_pcd_cc_tree(
+ ioc_compat_fm_pcd_cc_tree_params_t *compat_param,
+ ioc_fm_pcd_cc_tree_params_t *param,
+ uint8_t compat);
+
+void compat_fm_pcd_prs_sw(
+ ioc_compat_fm_pcd_prs_sw_params_t *compat_param,
+ ioc_fm_pcd_prs_sw_params_t *param,
+ uint8_t compat);
+
+void compat_copy_fm_pcd_kg_scheme(
+ ioc_compat_fm_pcd_kg_scheme_params_t *compat_param,
+ ioc_fm_pcd_kg_scheme_params_t *param,
+ uint8_t compat);
+
+void compat_copy_fm_pcd_kg_scheme_select(
+ ioc_compat_fm_pcd_kg_scheme_select_t *compat_param,
+ ioc_fm_pcd_kg_scheme_select_t *param,
+ uint8_t compat);
+
+void compat_copy_fm_pcd_kg_schemes_params(
+ ioc_compat_fm_pcd_port_schemes_params_t *compat_param,
+ ioc_fm_pcd_port_schemes_params_t *param,
+ uint8_t compat);
+
+void compat_copy_fm_port_pcd_kg(
+ ioc_compat_fm_port_pcd_kg_params_t *compat_param,
+ ioc_fm_port_pcd_kg_params_t *param,
+ uint8_t compat);
+
+void compat_copy_fm_port_pcd(
+ ioc_compat_fm_port_pcd_params_t *compat_param,
+ ioc_fm_port_pcd_params_t *param,
+ uint8_t compat);
+
+#if (DPAA_VERSION >= 11)
+void compat_copy_fm_port_vsp_alloc_params(
+ ioc_compat_fm_port_vsp_alloc_params_t *compat_param,
+ ioc_fm_port_vsp_alloc_params_t *param,
+ uint8_t compat);
+#endif /* (DPAA_VERSION >= 11) */
+
+void compat_copy_fm_pcd_net_env(
+ ioc_compat_fm_pcd_net_env_params_t *compat_param,
+ ioc_fm_pcd_net_env_params_t *param,
+ uint8_t compat);
+
+void compat_copy_fm_pcd_cc_node_modify_key(
+ ioc_compat_fm_pcd_cc_node_modify_key_params_t *compat_param,
+ ioc_fm_pcd_cc_node_modify_key_params_t *param,
+ uint8_t compat);
+
+void compat_copy_keys(
+ ioc_compat_keys_params_t *compat_param,
+ ioc_keys_params_t *param,
+ uint8_t compat);
+
+void compat_copy_fm_pcd_cc_node(
+ ioc_compat_fm_pcd_cc_node_params_t *compat_param,
+ ioc_fm_pcd_cc_node_params_t *param,
+ uint8_t compat);
+
+void compat_fm_pcd_manip_set_node(
+ ioc_compat_fm_pcd_manip_params_t *compat_param,
+ ioc_fm_pcd_manip_params_t *param,
+ uint8_t compat);
+
+void compat_copy_fm_port_pcd_modify_tree(
+ ioc_compat_fm_obj_t *compat_id,
+ ioc_fm_obj_t *id,
+ uint8_t compat);
+
+#if (DPAA_VERSION >= 11)
+void compat_copy_fm_pcd_frm_replic_group_params(
+ ioc_compat_fm_pcd_frm_replic_group_params_t *compat_param,
+ ioc_fm_pcd_frm_replic_group_params_t *param,
+ uint8_t compat);
+
+void compat_copy_fm_pcd_frm_replic_member(
+ ioc_compat_fm_pcd_frm_replic_member_t *compat_param,
+ ioc_fm_pcd_frm_replic_member_t *param,
+ uint8_t compat);
+
+void compat_copy_fm_pcd_frm_replic_member_params(
+ ioc_compat_fm_pcd_frm_replic_member_params_t *compat_param,
+ ioc_fm_pcd_frm_replic_member_params_t *param,
+ uint8_t compat);
+
+void compat_copy_fm_vsp_params(
+ ioc_compat_fm_vsp_params_t *compat_param,
+ ioc_fm_vsp_params_t *param,
+ uint8_t compat);
+
+void compat_copy_fm_buf_pool_depletion_params(
+ ioc_compat_fm_buf_pool_depletion_params_t *compat_param,
+ ioc_fm_buf_pool_depletion_params_t *param,
+ uint8_t compat);
+
+void compat_copy_fm_buffer_prefix_content_params(
+ ioc_compat_fm_buffer_prefix_content_params_t *compat_param,
+ ioc_fm_buffer_prefix_content_params_t *param,
+ uint8_t compat);
+
+void compat_copy_fm_vsp_config_no_sg_params(
+ ioc_compat_fm_vsp_config_no_sg_params_t *compat_param,
+ ioc_fm_vsp_config_no_sg_params_t *param,
+ uint8_t compat);
+
+void compat_copy_fm_vsp_prs_result_params(
+ ioc_compat_fm_vsp_prs_result_params_t *compat_param,
+ ioc_fm_vsp_prs_result_params_t *param,
+ uint8_t compat);
+#endif /* (DPAA_VERSION >= 11) */
+/* } pcd compat functions */
+#endif
diff --git a/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_resources.c b/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_resources.c
new file mode 100644
index 0000000..2686aa2
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_resources.c
@@ -0,0 +1,1196 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * 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 Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * 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 Freescale Semiconductor ``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 Freescale Semiconductor 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.
+ */
+
+/*
+ @File lnxwrp_resources.c
+
+ @Description FMD wrapper resource allocation functions.
+
+*/
+#if !defined(FMAN_RESOURCES_UNIT_TEST)
+
+#include <linux/version.h>
+#if defined(CONFIG_MODVERSIONS) && !defined(MODVERSIONS)
+#define MODVERSIONS
+#endif
+#ifdef MODVERSIONS
+#include <config/modversions.h>
+#endif /* MODVERSIONS */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/skbuff.h>
+
+#endif /*#if !defined(FMAN_RESOURCES_UNIT_TEST)*/
+
+#include "lnxwrp_resources.h"
+
+#if !defined(FMAN_RESOURCES_UNIT_TEST)
+static struct device_node *match_mac_to_dpaa_port(struct device_node
+ *enet_mac_node)
+{
+ struct device_node *dpaa_node = NULL;
+ struct device_node *dpaa_itf = NULL;
+
+ /* find DPAA node starting from root */
+ dpaa_node = of_find_compatible_node(NULL, NULL, "fsl,dpaa");
+ if (dpaa_node) {
+ /* for all dpaa ports check which one refers this mac node. */
+ for_each_child_of_node(dpaa_node, dpaa_itf) {
+ struct device_node *by_handle_enet_mac_node = NULL;
+ const phandle *phandle_prop = NULL;
+ int lenp = 0;
+
+ phandle_prop =
+ (typeof(phandle_prop))
+ of_get_property(dpaa_itf, "fsl,fman-mac",
+ &lenp);
+ if (phandle_prop == NULL)
+ continue;
+
+ if (WARN_ON(lenp != sizeof(phandle)))
+ return NULL;
+
+ by_handle_enet_mac_node =
+ of_find_node_by_phandle(*phandle_prop);
+ if (unlikely(by_handle_enet_mac_node == NULL))
+ return NULL;
+
+ /* check */
+ if (by_handle_enet_mac_node == enet_mac_node) {
+ of_node_put(by_handle_enet_mac_node);
+ return dpaa_itf;
+ }
+
+ of_node_put(by_handle_enet_mac_node);
+ }
+ of_node_put(dpaa_node);
+ }
+
+ return NULL;
+}
+
+static struct device_node *match_fman_port_to_mac(struct device_node *fm_node,
+ struct device_node
+ *fm_port_node)
+{
+ struct device_node *fm_node_idx = NULL;
+
+ /* for all enet nodes (macs) check which one refers this FMan port. */
+ for_each_child_of_node(fm_node, fm_node_idx) {
+ if (of_device_is_compatible(fm_node_idx, "fsl,fman-1g-mac") ||
+ of_device_is_compatible(fm_node_idx, "fsl,fman-10g-mac") ||
+ of_device_is_compatible(fm_node_idx, "fsl,fman-memac")) {
+ struct device_node *fman_port_node_rx = NULL;
+ struct device_node *fman_port_node_tx = NULL;
+ /* RX is first */
+ fman_port_node_rx = of_parse_phandle(fm_node_idx,
+ "fsl,port-handles", 0);
+ if (unlikely(fman_port_node_rx == NULL))
+ continue;
+ /* TX is second */
+ fman_port_node_tx = of_parse_phandle(fm_node_idx,
+ "fsl,port-handles", 1);
+ if (unlikely(fman_port_node_tx == NULL)) {
+ of_node_put(fman_port_node_rx);
+ continue;
+ }
+
+ /* check */
+ if (fman_port_node_rx == fm_port_node
+ || fman_port_node_tx == fm_port_node) {
+ of_node_put(fman_port_node_rx);
+ of_node_put(fman_port_node_tx);
+ return fm_node_idx;
+ }
+
+ of_node_put(fman_port_node_rx);
+ of_node_put(fman_port_node_tx);
+ }
+ }
+
+ return NULL;
+}
+
+static bool is_fman_port_active(struct device_node *fm_node,
+ struct device_node *fm_port_node)
+{
+ struct device_node *enet_mac_node = NULL;
+ struct device_node *itf_node = NULL;
+
+ /* Which MAC node refers to this FMan port. */
+ enet_mac_node = match_fman_port_to_mac(fm_node, fm_port_node);
+
+ if (unlikely(enet_mac_node == NULL))
+ return false;
+
+ /* Which dpaa port node refers this MAC node. */
+ itf_node = match_mac_to_dpaa_port(enet_mac_node);
+ of_node_put(enet_mac_node);
+
+ if (unlikely(!itf_node))
+ return false;
+
+ /* check if itf (DPAA ports) is available.
+ * if available, means that the FMan port is
+ * also available - return true
+ */
+ if (!of_device_is_available(itf_node)) {
+ of_node_put(itf_node);
+ return false;
+ }
+ of_node_put(itf_node);
+
+ return true;
+}
+
+int fm_set_active_fman_ports(struct platform_device *of_dev,
+ t_LnxWrpFmDev *p_LnxWrpFmDev)
+{
+ struct device_node *fm_node = NULL;
+ struct device_node *fm_port_node = NULL;
+
+ memset(&p_LnxWrpFmDev->fm_active_ports_info, 0,
+ sizeof(struct fm_active_ports));
+
+ /* get FMan node */
+ fm_node = of_dev->dev.of_node;
+
+ /* for all ports which belong to this FMan, check if they are active.
+ * If active, set their parameters. */
+ for_each_child_of_node(fm_node, fm_port_node) {
+
+ if (!of_device_is_available(fm_port_node))
+ continue;
+
+ /* OH FMan ports */
+ if (of_device_is_compatible(fm_port_node,
+ "fsl,fman-port-oh")) {
+ p_LnxWrpFmDev->fm_active_ports_info.num_oh_ports++;
+ continue;
+ }
+
+ if (!is_fman_port_active(fm_node, fm_port_node))
+ continue;
+
+ /* 10g TX FMan ports */
+ if (of_device_is_compatible(fm_port_node,
+ "fsl,fman-port-10g-tx"))
+ p_LnxWrpFmDev->fm_active_ports_info.num_tx10_ports++;
+
+ /* 10g RX FMan ports */
+ else if (of_device_is_compatible(fm_port_node,
+ "fsl,fman-port-10g-rx"))
+ p_LnxWrpFmDev->fm_active_ports_info.num_rx10_ports++;
+
+ /* 1G TX FMan ports */
+ else if (of_device_is_compatible(fm_port_node,
+ "fsl,fman-port-1g-tx"))
+ p_LnxWrpFmDev->fm_active_ports_info.num_tx_ports++;
+
+ /* 1G RX FMan ports */
+ else if (of_device_is_compatible(fm_port_node,
+ "fsl,fman-port-1g-rx"))
+ p_LnxWrpFmDev->fm_active_ports_info.num_rx_ports++;
+ }
+
+ /* If performance is needed no oh port is probed
+ * except the one used for host command. */
+#if defined(CONFIG_FMAN_DISABLE_OH_TO_REUSE_RESOURCES)
+ if (p_LnxWrpFmDev->fm_active_ports_info.num_oh_ports)
+ p_LnxWrpFmDev->fm_active_ports_info.num_oh_ports = 1;
+
+ printk(KERN_WARNING "FMAN(%u)-Performance mode - no OH support...\n",
+ p_LnxWrpFmDev->id);
+#endif
+
+ return 0;
+}
+#endif /*!defined(FMAN_RESOURCES_UNIT_TEST)*/
+
+/* BPOOL size is constant and equal w/ DPA_BP_SIZE */
+static uint32_t get_largest_buf_size(uint32_t max_rx_frame_size, uint32_t buf_size)
+{
+ uint32_t priv_data_size = 16; /* DPA_PRIV_DATA_SIZE */
+ uint32_t hash_results_size = 16; /* DPA_HASH_RESULTS_SIZE */
+ uint32_t parse_results_size =
+ sizeof(t_FmPrsResult); /* DPA_PARSE_RESULTS_SIZE */
+ uint32_t bp_head = priv_data_size + hash_results_size +
+ parse_results_size +
+ fm_get_rx_extra_headroom(); /* DPA_BP_HEAD */
+ uint32_t bp_size = bp_head + max_rx_frame_size
+ + NET_IP_ALIGN; /* DPA_BP_SIZE */
+
+#ifndef CONFIG_DPAA_ETH_SG_SUPPORT
+ return CEIL_DIV(bp_size, buf_size);
+#else
+ bp_size = CEIL_DIV(bp_size, 16); /* frame split in 16 frags */
+
+ return max((uint32_t)16, CEIL_DIV(bp_size, buf_size));
+#endif /* CONFIG_DPAA_ETH_SG_SUPPORT */
+}
+
+/* Calculate the fifosize based on MURAM allocation, number of ports, dpde
+ value and s/g software support (! Kernel does not suport s/g).
+
+ Algorithm summary:
+ - Calculate the the minimum fifosize required for every type of port
+ (TX,RX for 1G, 2.5G and 10G).
+ - Set TX the minimum fifosize required.
+ - Distribute the remaining buffers (after all TX were set) to RX ports
+ based on:
+ 1G RX = Remaining_buffers * 1/(1+2.5+10)
+ 2.5G RX = Remaining_buffers * 2.5/(1+2.5+10)
+ 10G RX = Remaining_buffers * 10/(1+2.5+10)
+ - if the RX is smaller than the minimum required, then set the minimum
+ required
+ - In the end distribuite the leftovers if there are any (due to
+ unprecise calculus) or if over allocation cat some buffers from all RX
+ ports w/o pass over minimum required treshold, but if there must be
+ pass the treshold in order to cat the over allocation ,then this
+ configuration can not be set - KERN_ALERT.
+*/
+int fm_precalculate_fifosizes(t_LnxWrpFmDev *p_LnxWrpFmDev, int muram_fifo_size)
+{
+
+ /* input parameters */
+ struct fm_active_ports *fm_active_ports_info = NULL;
+ int num_1g_ports = 0;
+ int num_2g5_ports = 0;
+ int num_10g_ports = 0;
+ int num_oh_ports = 0;
+
+ /* output parameters */
+ struct fm_resource_settings *fm_resource_settings_info = NULL;
+ int oh_buff = 0;
+ int tx_1g_bufs = 0, rx_1g_bufs = 0;
+ int tx_2g5_bufs = 0, rx_2g5_bufs = 0;
+ int tx_10g_bufs = 0, rx_10g_bufs = 0;
+ int err = 0;
+
+ /* throughput parameters: divide it by 10 when used */
+ int gb1g = 10, gb2g5 = 25, gb10g = 100, gb_sum = 0;
+
+ /* buffers parameters */
+ int buf_size = 0x100; /* Buffer unit size */
+ int total_no_buffers = 0; /* Calculus based on MURAM size for
+ fifos and buf. unit size */
+
+ int shared_ext_buff = 0; /* External buffers allocated - LLD
+ boundaries:DEFAULT_PORT_extraSizeOfFifo */
+
+ int min_tx_1g_2g5_bufs = 0; /* minimum TX1g buffers required
+ (see refman.) */
+ int min_tx_10g_bufs = 0; /* minimum TX10g buffers required
+ (see refman.) */
+ int min_rx_bufs = 0; /* minimum RX buffers required (see refman.) */
+
+ /* Buffer sizes calculus */
+ int max_frame_size = fm_get_max_frm();
+ int remaining_bufs = 0;
+ int rx_1g_bufs_ceil = 0, rx_2g5_bufs_ceil = 0, rx_10g_bufs_ceil = 0;
+ int rx_2g5_max_bufs = 0, rx_10g_max_bufs = 0;
+ int rx_1g_used = 0, rx_1g_2g5_used = 0, rx_1g_10g_used =0,
+ rx_2g5_used = 0, rx_2g5_10g_used = 0, rx_1g_2g5_10g_used = 0;
+
+ /* overflow checking */
+ int tot_rx_buffs, tot_tx_buffs, tot_oh_buffs, tot_used_buffs,
+ leftovers = 0;
+ int overflow = 0;
+ bool loop = false;
+
+ /* check input parameters correctness */
+ ASSERT_COND(p_LnxWrpFmDev != NULL);
+ fm_active_ports_info = &p_LnxWrpFmDev->fm_active_ports_info;
+ fm_resource_settings_info = &p_LnxWrpFmDev->fm_resource_settings_info;
+ ASSERT_COND(fm_active_ports_info != NULL);
+ ASSERT_COND(fm_resource_settings_info != NULL);
+ ASSERT_COND(fm_active_ports_info->num_tx_ports ==
+ fm_active_ports_info->num_rx_ports);
+ ASSERT_COND(fm_active_ports_info->num_tx25_ports ==
+ fm_active_ports_info->num_tx25_ports);
+ ASSERT_COND(fm_active_ports_info->num_tx10_ports ==
+ fm_active_ports_info->num_tx10_ports);
+ ASSERT_COND(max_frame_size != 0);
+ ASSERT_COND(muram_fifo_size != 0);
+
+ /* set input parameters */
+ num_1g_ports = fm_active_ports_info->num_tx_ports;
+ num_2g5_ports = fm_active_ports_info->num_tx25_ports;
+ num_10g_ports = fm_active_ports_info->num_tx10_ports;
+ num_oh_ports = fm_active_ports_info->num_oh_ports;
+
+ /* throughput calculus */
+ gb_sum = gb1g * num_1g_ports + gb2g5 * num_2g5_ports
+ + gb10g * num_10g_ports; /* divide it by 10 */
+
+ /* Base buffer calculus */
+ oh_buff = 8;
+ total_no_buffers = muram_fifo_size / buf_size;
+
+ min_tx_1g_2g5_bufs = CEIL_DIV(max_frame_size, buf_size)
+ + DPDE_1G + 3 + 1; /* +1 to handle Jumbo Frames */
+ min_tx_10g_bufs = CEIL_DIV(max_frame_size, buf_size)
+ + DPDE_10G + 3 + 1; /* +1 to handle Jumbo Frames */
+
+ {
+/*
+ * On P1023RDS FM_FIFO_ALLOCATION_ALG is enabled allowing a smaller Rx FIFO
+ * on hardware major rev 4. If the Rx FIFO is smaller than the size of the
+ * buffer in the buffer pool SG frames will be received
+ */
+#if defined(FM_FIFO_ALLOCATION_ALG) && \
+ !defined(FMAN_RESOURCES_UNIT_TEST) && \
+ defined(CONFIG_DPAA_ETH_SG_SUPPORT)
+ uint8_t fm_rev_major = 0;
+ fm_rev_major = (uint8_t) ((*
+ ((volatile uint32_t *)
+ UINT_TO_PTR(p_LnxWrpFmDev->fmBaseAddr +
+ 0x000c30c4)) & 0xff00) >> 8);
+
+ if (fm_rev_major == 4)
+ min_rx_bufs = 8;
+ else
+#endif
+ min_rx_bufs = get_largest_buf_size(max_frame_size,
+ buf_size) + 7;
+ }
+
+#ifdef CONFIG_FMAN_P1023
+ shared_ext_buff = 0;
+#else
+ /* changing these might reduce performance */
+ shared_ext_buff = num_10g_ports ? 32 : 16; /* LLD boundaries:
+ DEFAULT_PORT_extraNumOfFifoBufs */
+#endif
+
+ /* TX ports will have minimum required buffers
+ Calculus of the remaining buffers for all RX ports */
+ tx_1g_bufs = num_1g_ports ? min_tx_1g_2g5_bufs : 0;
+ tx_2g5_bufs = num_2g5_ports ? min_tx_1g_2g5_bufs : 0;
+ tx_10g_bufs = num_10g_ports ? min_tx_10g_bufs : 0;
+
+ remaining_bufs = total_no_buffers -
+ oh_buff * num_oh_ports -
+ num_1g_ports * min_tx_1g_2g5_bufs -
+ num_2g5_ports * min_tx_1g_2g5_bufs -
+ num_10g_ports * min_tx_10g_bufs - shared_ext_buff;
+
+ if (remaining_bufs < 0) {
+ printk(KERN_ALERT
+ "\nThis configuration will not work due to low number of"
+ " buffers (%u buffers)...\n",
+ total_no_buffers);
+ err = -1;
+ goto precalculated_fifosize_out;
+ }
+
+ /* Per port buffer size calculus
+ . for TX ports give always minimum required
+ . for RX ports give whatever left scaled per port type */
+ /* ------------------------------------------------------- */
+ if (num_1g_ports) {
+ rx_1g_bufs_ceil =
+ (gb_sum /
+ 10) ? CEIL_DIV(((remaining_bufs * gb1g) / 10),
+ (gb_sum / 10)) : 0;
+ rx_1g_bufs = MAX(min_rx_bufs, rx_1g_bufs_ceil);
+ rx_1g_used = rx_1g_bufs - rx_1g_bufs_ceil; /* always >= 0 */
+ /* distribute to 2.5g and 10g ports */
+ rx_1g_2g5_used =
+ (num_2g5_ports +
+ num_10g_ports) ? CEIL_DIV(rx_1g_used * num_1g_ports *
+ num_2g5_ports,
+ num_2g5_ports +
+ num_10g_ports) : 0;
+ rx_1g_10g_used =
+ (num_2g5_ports +
+ num_10g_ports) ? CEIL_DIV(rx_1g_used * num_1g_ports *
+ num_10g_ports,
+ num_2g5_ports +
+ num_10g_ports) : 0;
+ }
+
+ if (num_2g5_ports) {
+ rx_2g5_bufs_ceil =
+ (gb_sum /
+ 10) ? CEIL_DIV(((remaining_bufs * gb2g5) / 10),
+ (gb_sum / 10)) : 0;
+ rx_2g5_max_bufs = MAX(min_rx_bufs, rx_2g5_bufs_ceil);
+ rx_2g5_bufs =
+ MAX(min_rx_bufs, rx_2g5_max_bufs - rx_1g_2g5_used);
+ rx_2g5_used = rx_2g5_bufs - rx_2g5_bufs_ceil; /* always >= 0 */
+ /* distribute to 10g ports */
+ rx_2g5_10g_used =
+ num_10g_ports ? CEIL_DIV(rx_2g5_used * num_2g5_ports,
+ num_10g_ports) : 0;
+ }
+
+ if (num_10g_ports) {
+ rx_10g_bufs_ceil =
+ (gb_sum /
+ 10) ? CEIL_DIV(((remaining_bufs * gb10g) / 10),
+ (gb_sum / 10)) : 0;
+ rx_10g_max_bufs = MAX(min_rx_bufs, rx_10g_bufs_ceil);
+ /* keep count of all distribution */
+ rx_1g_2g5_10g_used = rx_1g_10g_used + rx_2g5_10g_used;
+ rx_10g_bufs =
+ MAX(min_rx_bufs,
+ rx_10g_max_bufs - rx_1g_2g5_10g_used);
+ }
+
+ /* overflow-leftover calculus */
+ tot_rx_buffs = rx_1g_bufs * num_1g_ports +
+ rx_2g5_bufs * num_2g5_ports + rx_10g_bufs * num_10g_ports;
+ tot_tx_buffs = tx_1g_bufs * num_1g_ports +
+ tx_2g5_bufs * num_2g5_ports + tx_10g_bufs * num_10g_ports;
+ tot_oh_buffs = oh_buff * num_oh_ports;
+ tot_used_buffs =
+ tot_oh_buffs + tot_tx_buffs + tot_rx_buffs + shared_ext_buff;
+
+ overflow = tot_used_buffs - total_no_buffers;
+ /* used more than available */
+ if (overflow > 0) {
+ loop = true;
+ while (overflow > 0 && loop) {
+ loop = false;
+ if (overflow && num_10g_ports
+ && rx_10g_bufs > min_rx_bufs) {
+ rx_10g_bufs--;
+ overflow -= num_10g_ports;
+ loop = true;
+ }
+ if (overflow && num_2g5_ports
+ && rx_2g5_bufs > min_rx_bufs) {
+ rx_2g5_bufs--;
+ overflow -= num_2g5_ports;
+ loop = true;
+ }
+ if (overflow && num_1g_ports
+ && rx_1g_bufs > min_rx_bufs) {
+ rx_1g_bufs--;
+ overflow -= num_1g_ports;
+ loop = true;
+ }
+ }
+
+ if (overflow > 0) {
+ printk(KERN_ALERT
+ "This configuration will not work due to over"
+ " buffer allocation (%d buffers)...\n",
+ overflow);
+ err = -1;
+ goto precalculated_fifosize_out;
+ }
+ }
+ /* left a few buffers */
+ else if (overflow < 0) {
+ leftovers = total_no_buffers - tot_used_buffs;
+ loop = true;
+ while (leftovers > 0 && loop) {
+ loop = false;
+ if (leftovers && num_1g_ports) {
+ rx_1g_bufs++;
+ leftovers -= num_1g_ports;
+ loop = true;
+ }
+
+ if (leftovers && num_2g5_ports) {
+ rx_2g5_bufs++;
+ leftovers -= num_2g5_ports;
+ loop = true;
+ }
+
+ if (leftovers && num_10g_ports) {
+ rx_10g_bufs++;
+ leftovers -= num_10g_ports;
+ loop = true;
+ }
+ }
+ }
+
+ /* set fifosizes for this FMan ports */
+ fm_resource_settings_info->tx1g_num_buffers = tx_1g_bufs;
+ fm_resource_settings_info->rx1g_num_buffers = rx_1g_bufs;
+ fm_resource_settings_info->tx2g5_num_buffers = tx_2g5_bufs;
+ fm_resource_settings_info->rx2g5_num_buffers = rx_2g5_bufs;
+ fm_resource_settings_info->tx10g_num_buffers = tx_10g_bufs;
+ fm_resource_settings_info->rx10g_num_buffers = rx_10g_bufs;
+ fm_resource_settings_info->oh_num_buffers = oh_buff;
+ fm_resource_settings_info->shared_ext_buffers = shared_ext_buff;
+
+precalculated_fifosize_out:
+ printk(KERN_INFO " FMAN(%u) Fifo size settings:\n",
+ p_LnxWrpFmDev->id);
+ printk(KERN_INFO " - Total buffers available(%u - 256B/buffer)\n",
+ total_no_buffers);
+ printk(KERN_INFO " - Total throughput(%uGbps)\n", (gb_sum / 10));
+ printk(KERN_INFO " - Max frame size(%uB)\n", max_frame_size);
+ if (num_1g_ports) {
+ printk(KERN_INFO
+ " - 1G ports TX %u(%u bufs set (min: %u))\n",
+ num_1g_ports, tx_1g_bufs, min_tx_1g_2g5_bufs);
+ printk(KERN_INFO
+ " - 1G ports RX %u(%u bufs set (min: %u))\n",
+ num_1g_ports, rx_1g_bufs, min_rx_bufs);
+ }
+ if (num_2g5_ports) {
+ printk(KERN_INFO
+ " - 2.5G ports TX %u(%u bufs set (min: %u))\n",
+ num_2g5_ports, tx_2g5_bufs, min_tx_1g_2g5_bufs);
+ printk(KERN_INFO
+ " - 2.5G ports RX %u(%u bufs set (min: %u))\n",
+ num_2g5_ports, rx_2g5_bufs, min_rx_bufs);
+ }
+ if (num_10g_ports) {
+ printk(KERN_INFO
+ " - 10G ports TX %u(%u bufs set (min: %u))\n",
+ num_10g_ports, tx_10g_bufs, min_tx_10g_bufs);
+ printk(KERN_INFO
+ " - 10G ports RX %u(%u bufs set (min: %u))\n",
+ num_10g_ports, rx_10g_bufs, min_rx_bufs);
+ }
+ if (num_oh_ports)
+ printk(KERN_INFO " - OH-HC ports %u(%u)\n", num_oh_ports,
+ oh_buff);
+ printk(KERN_INFO " - Shared extra buffers(%u)\n", shared_ext_buff);
+
+ return err;
+}
+
+#if !defined(FMAN_RESOURCES_UNIT_TEST)
+int fm_config_precalculate_fifosize(t_LnxWrpFmPortDev *p_LnxWrpFmPortDev)
+{
+ t_LnxWrpFmDev *p_LnxWrpFmDev =
+ (t_LnxWrpFmDev *) p_LnxWrpFmPortDev->h_LnxWrpFmDev;
+ struct fm_resource_settings *fm_resource_settings_info = NULL;
+ struct fm_active_ports *fm_active_ports_info = NULL;
+ t_FmPortRsrc portRsrc;
+ t_Error errCode;
+ uint32_t buf_size = 0x100;
+
+ ASSERT_COND(p_LnxWrpFmDev != NULL);
+ fm_resource_settings_info = &p_LnxWrpFmDev->fm_resource_settings_info;
+ fm_active_ports_info = &p_LnxWrpFmDev->fm_active_ports_info;
+
+ memset(&portRsrc, 0, sizeof(t_FmPortRsrc));
+
+/* IF 1G PORT */
+ if (p_LnxWrpFmPortDev->settings.param.portType == e_FM_PORT_TYPE_TX) {
+ portRsrc.num =
+ fm_resource_settings_info->tx1g_num_buffers * buf_size;
+ portRsrc.extra = 0;
+ } else if (p_LnxWrpFmPortDev->settings.param.portType ==
+ e_FM_PORT_TYPE_RX) {
+ portRsrc.num =
+ fm_resource_settings_info->rx1g_num_buffers * buf_size;
+ portRsrc.extra =
+ fm_resource_settings_info->shared_ext_buffers *
+ buf_size;
+ }
+/* IF 2.5G PORT */
+ /* TODO: Not supported by LLD yet. */
+
+/* IF 10G PORT */
+ else if (p_LnxWrpFmPortDev->settings.param.portType ==
+ e_FM_PORT_TYPE_TX_10G) {
+ portRsrc.num =
+ fm_resource_settings_info->tx10g_num_buffers *
+ buf_size;
+ portRsrc.extra = 0;
+ } else if (p_LnxWrpFmPortDev->settings.param.portType ==
+ e_FM_PORT_TYPE_RX_10G) {
+ portRsrc.num =
+ fm_resource_settings_info->rx10g_num_buffers *
+ buf_size;
+ portRsrc.extra =
+ fm_resource_settings_info->shared_ext_buffers *
+ buf_size;
+ } else { /* IF OH PORT */
+ portRsrc.num =
+ fm_resource_settings_info->oh_num_buffers * buf_size;
+ portRsrc.extra = 0;
+ }
+
+ errCode = FM_PORT_ConfigSizeOfFifo(p_LnxWrpFmPortDev->h_Dev, &portRsrc);
+ if (errCode != E_OK) {
+ printk(KERN_WARNING
+ "FM_PORT_SetSizeOfFifo failed (errCode:0x%2x)",
+ errCode);
+ return -EIO;
+ }
+
+ return 0;
+}
+#endif /*if !defined(FMAN_RESOURCES_UNIT_TEST)*/
+
+/* Compute FMan open DMA based on total number of open DMAs and
+ * number of available FMan ports.
+ *
+ * By default 10g ports are set to input parameters. The other ports
+ * tries to keep the proportion rx=2tx open DMAs or thresholds.
+ *
+ * If leftovers, then those will be set as shared.
+ *
+ * If after computing overflow appears, then it decrements open DMA
+ * for all ports w/o cross the thresholds. If the thresholds are meet
+ * and is still overflow, then it returns error.
+ */
+int fm_precalculate_open_dma(t_LnxWrpFmDev *p_LnxWrpFmDev,
+ int max_fm_open_dma,
+ int default_tx_10g_dmas,
+ int default_rx_10g_dmas,
+ int min_tx_10g_treshold, int min_rx_10g_treshold)
+{
+ /* input parameters */
+ struct fm_active_ports *fm_active_ports_info = NULL;
+ int num_1g_ports = 0;
+ int num_2g5_ports = 0;
+ int num_10g_ports = 0;
+ int num_oh_ports = 0;
+
+ /* output parameters */
+ struct fm_resource_settings *fm_resource_settings_info = NULL;
+ int tx_1g_dmas = 0, rx_1g_dmas = 0;
+ int tx_2g5_dmas = 0, rx_2g5_dmas = 0;
+ int tx_10g_dmas = 0, rx_10g_dmas = 0;
+ int oh_dmas = 0;
+ int shared_ext_open_dma = 0;
+ int err = 0;
+
+ /* open dma calculus */
+ int remaing_dmas = 0;
+ int rx_tx_raport =
+ FM_OPENDMA_RX_TX_RAPORT; /* RX = FM_OPENDMA_RX_TX_RAPORT *TX */
+ int min_tx_1_2g5_treshold = 1;
+ int min_rx_1_2g5_treshold = 1;
+ int max_open_dma_treshold = 16; /* LLD: MAX_NUM_OF_DMAS */
+ int max_ext_open_dma_treshold = 8; /* LLD: MAX_NUM_OF_EXTRA_DMAS */
+
+ int open_dmas_computed = 0;
+ int weighted_remaining_ports = 0;
+ int overflow = 0;
+ bool re_loop = false;
+
+ /* check input parameters correctness */
+ ASSERT_COND(p_LnxWrpFmDev != NULL);
+ fm_active_ports_info = &p_LnxWrpFmDev->fm_active_ports_info;
+ fm_resource_settings_info = &p_LnxWrpFmDev->fm_resource_settings_info;
+ ASSERT_COND(fm_active_ports_info != NULL);
+ ASSERT_COND(fm_resource_settings_info != NULL);
+ ASSERT_COND(fm_active_ports_info->num_tx_ports ==
+ fm_active_ports_info->num_rx_ports);
+ ASSERT_COND(fm_active_ports_info->num_tx25_ports ==
+ fm_active_ports_info->num_tx25_ports);
+ ASSERT_COND(fm_active_ports_info->num_tx10_ports ==
+ fm_active_ports_info->num_tx10_ports);
+ ASSERT_COND(min_tx_10g_treshold <= max_open_dma_treshold);
+ ASSERT_COND(min_tx_10g_treshold <= max_open_dma_treshold);
+
+ /* set input parameters */
+ num_1g_ports = fm_active_ports_info->num_tx_ports;
+ num_2g5_ports = fm_active_ports_info->num_tx25_ports;
+ num_10g_ports = fm_active_ports_info->num_tx10_ports;
+ num_oh_ports = fm_active_ports_info->num_oh_ports;
+
+ /* compute open DMAs per port */
+ /* ------------------------------------------------------- */
+ if (num_10g_ports) {
+ tx_10g_dmas = default_tx_10g_dmas; /* per 10G TX port */
+ rx_10g_dmas = default_rx_10g_dmas; /* per 10G RX port */
+ }
+ if (num_oh_ports)
+ oh_dmas = 1; /* per OH port */
+
+ /* should this be null? or LLD:
+ DEFAULT_PORT_extraNumOfOpenDmas:10g-8,else 1 */
+ shared_ext_open_dma = 0;
+
+ /* based on total number of ports set open DMAs for all other ports */
+ remaing_dmas = max_fm_open_dma -
+ (oh_dmas * num_oh_ports) -
+ (tx_10g_dmas * num_10g_ports + rx_10g_dmas * num_10g_ports) -
+ shared_ext_open_dma;
+
+ if (remaing_dmas < 0) {
+ printk(KERN_ALERT
+ "This configuration will not work due to low number"
+ " of open dmas (%u open dmas)...\n",
+ max_fm_open_dma);
+ err = -1;
+ goto precalculated_open_dma_out;
+ }
+
+ weighted_remaining_ports =
+ /*tx */ num_1g_ports * rx_tx_raport + /*rx */ num_1g_ports +
+ /*tx */ num_2g5_ports * rx_tx_raport + /*rx */ num_2g5_ports;
+
+ /* compute the other ports */
+ if (num_1g_ports) {
+ tx_1g_dmas =
+ MAX(MIN
+ (ROUND_DIV
+ (remaing_dmas, weighted_remaining_ports),
+ max_open_dma_treshold), min_tx_1_2g5_treshold);
+ rx_1g_dmas =
+ MAX(MIN
+ (ROUND_DIV
+ ((remaing_dmas * rx_tx_raport),
+ weighted_remaining_ports),
+ max_open_dma_treshold), min_rx_1_2g5_treshold);
+ }
+ if (num_2g5_ports) {
+ tx_2g5_dmas =
+ MAX(MIN
+ (CEIL_DIV(remaing_dmas, weighted_remaining_ports),
+ max_open_dma_treshold), min_tx_1_2g5_treshold);
+ rx_2g5_dmas =
+ MAX(MIN
+ (CEIL_DIV
+ ((remaing_dmas * rx_tx_raport),
+ weighted_remaining_ports),
+ max_open_dma_treshold), min_rx_1_2g5_treshold);
+
+ }
+
+ /* Check if these settings is not exceding treshold */
+ open_dmas_computed = num_1g_ports * tx_1g_dmas +
+ num_1g_ports * rx_1g_dmas +
+ num_2g5_ports * tx_2g5_dmas +
+ num_2g5_ports * rx_2g5_dmas +
+ num_10g_ports * tx_10g_dmas +
+ num_10g_ports * rx_10g_dmas +
+ num_oh_ports * oh_dmas + shared_ext_open_dma;
+
+ /* overflow-leftover calculus */
+ overflow = open_dmas_computed - max_fm_open_dma;
+ re_loop = true;
+ while (overflow > 0 && re_loop == true) {
+ re_loop = false;
+ if (num_1g_ports && overflow
+ && rx_1g_dmas > min_rx_1_2g5_treshold) {
+ rx_1g_dmas--;
+ overflow -= num_1g_ports;
+ re_loop = true;
+ }
+ if (num_2g5_ports && overflow
+ && rx_2g5_dmas > min_rx_1_2g5_treshold) {
+ rx_2g5_dmas--;
+ overflow -= num_2g5_ports;
+ re_loop = true;
+ }
+ if (num_10g_ports && overflow
+ && rx_10g_dmas > min_rx_10g_treshold) {
+ rx_10g_dmas--;
+ overflow -= num_10g_ports;
+ re_loop = true;
+ }
+
+ if (num_1g_ports && overflow
+ && tx_1g_dmas > min_tx_1_2g5_treshold) {
+ tx_1g_dmas--;
+ overflow -= num_1g_ports;
+ re_loop = true;
+ }
+ if (num_2g5_ports && overflow
+ && tx_2g5_dmas > min_tx_1_2g5_treshold) {
+ tx_2g5_dmas--;
+ overflow -= num_2g5_ports;
+ re_loop = true;
+ }
+ if (num_10g_ports && overflow
+ && tx_10g_dmas > min_tx_10g_treshold) {
+ tx_10g_dmas--;
+ overflow -= num_10g_ports;
+ re_loop = true;
+ }
+ }
+
+ if (overflow > 0) {
+ printk(KERN_ALERT
+ "This configuration will not work due to over open dma"
+ " allocation (%d open dmas)...\n",
+ overflow);
+ err = -1;
+ goto precalculated_open_dma_out;
+ }
+
+ /* could remain leftovers... e.g. overflow=1,
+ 2ports => leftover=1 => shared=1 */
+ open_dmas_computed = num_1g_ports * tx_1g_dmas +
+ num_1g_ports * rx_1g_dmas +
+ num_2g5_ports * tx_2g5_dmas +
+ num_2g5_ports * rx_2g5_dmas +
+ num_10g_ports * tx_10g_dmas +
+ num_10g_ports * rx_10g_dmas +
+ num_oh_ports * oh_dmas + shared_ext_open_dma;
+
+ if (max_fm_open_dma - open_dmas_computed > 0)
+ shared_ext_open_dma =
+ MIN(shared_ext_open_dma + max_fm_open_dma -
+ open_dmas_computed, max_ext_open_dma_treshold);
+
+ /* set open dmas */
+ fm_resource_settings_info->tx_1g_dmas = tx_1g_dmas;
+ fm_resource_settings_info->rx_1g_dmas = rx_1g_dmas;
+ fm_resource_settings_info->tx_2g5_dmas = tx_2g5_dmas;
+ fm_resource_settings_info->rx_2g5_dmas = rx_2g5_dmas;
+ fm_resource_settings_info->tx_10g_dmas = tx_10g_dmas;
+ fm_resource_settings_info->rx_10g_dmas = rx_10g_dmas;
+ fm_resource_settings_info->oh_dmas = oh_dmas;
+ fm_resource_settings_info->shared_ext_open_dma = shared_ext_open_dma;
+
+precalculated_open_dma_out:
+ printk(KERN_INFO " FMAN(%u) open dma settings:\n",
+ p_LnxWrpFmDev->id);
+ printk(KERN_INFO " - Total open dma available(%u)\n",
+ max_fm_open_dma);
+ if (num_1g_ports) {
+ printk(KERN_INFO " - 1G ports TX %u(%u)\n", num_1g_ports,
+ tx_1g_dmas);
+ printk(KERN_INFO " - 1G ports RX %u(%u)\n", num_1g_ports,
+ rx_1g_dmas);
+ }
+ if (num_2g5_ports) {
+ printk(KERN_INFO " - 2.5G ports TX %u(%u)\n", num_2g5_ports,
+ tx_2g5_dmas);
+ printk(KERN_INFO " - 2.5G ports RX %u(%u)\n", num_2g5_ports,
+ tx_2g5_dmas);
+ }
+ if (num_10g_ports) {
+ printk(KERN_INFO " - 10G ports TX %u(%u)\n", num_10g_ports,
+ tx_10g_dmas);
+ printk(KERN_INFO " - 10G ports RX %u(%u)\n", num_10g_ports,
+ rx_10g_dmas);
+ }
+ if (num_oh_ports)
+ printk(KERN_INFO " - OH-HC ports %u(%u)\n", num_oh_ports,
+ oh_dmas);
+ printk(KERN_INFO " - Shared extra open dma(%u)\n",
+ shared_ext_open_dma ? shared_ext_open_dma : 0);
+
+ return err;
+}
+
+#if !defined(FMAN_RESOURCES_UNIT_TEST)
+int fm_config_precalculate_open_dma(t_LnxWrpFmPortDev *p_LnxWrpFmPortDev)
+{
+ t_LnxWrpFmDev *p_LnxWrpFmDev =
+ (t_LnxWrpFmDev *) p_LnxWrpFmPortDev->h_LnxWrpFmDev;
+ struct fm_resource_settings *fm_resource_settings_info = NULL;
+ t_FmPortRsrc numOfOpenDmas;
+ t_Error errCode;
+
+ ASSERT_COND(p_LnxWrpFmDev != NULL);
+ fm_resource_settings_info = &p_LnxWrpFmDev->fm_resource_settings_info;
+
+ memset(&numOfOpenDmas, 0, sizeof(t_FmPortRsrc));
+
+/* IF 1G PORT */
+ if (p_LnxWrpFmPortDev->settings.param.portType == e_FM_PORT_TYPE_TX)
+ numOfOpenDmas.num = fm_resource_settings_info->tx_1g_dmas;
+ else if (p_LnxWrpFmPortDev->settings.param.portType ==
+ e_FM_PORT_TYPE_RX)
+ numOfOpenDmas.num = fm_resource_settings_info->rx_1g_dmas;
+/* IF 2.5G PORT*/
+ /* TODO: Not supported by LLD yet. */
+
+/* IF 10G PORT */
+ else if (p_LnxWrpFmPortDev->settings.param.portType ==
+ e_FM_PORT_TYPE_TX_10G)
+ numOfOpenDmas.num = fm_resource_settings_info->tx_10g_dmas;
+ else if (p_LnxWrpFmPortDev->settings.param.portType ==
+ e_FM_PORT_TYPE_RX_10G)
+ numOfOpenDmas.num = fm_resource_settings_info->rx_10g_dmas;
+/* IF OH PORT */
+ else
+ numOfOpenDmas.num = fm_resource_settings_info->oh_dmas;
+
+ numOfOpenDmas.extra = fm_resource_settings_info->shared_ext_open_dma;
+
+ errCode = FM_PORT_ConfigNumOfOpenDmas(p_LnxWrpFmPortDev->h_Dev,
+ &numOfOpenDmas);
+ if (errCode != E_OK) {
+ printk(KERN_WARNING
+ "FM_PORT_SetNumOfOpenDmas failed (errCode:0x%2x)",
+ errCode);
+ return -EIO;
+ }
+
+ return 0;
+}
+#endif /*if !defined(FMAN_RESOURCES_UNIT_TEST)*/
+
+/* Compute FMan tnums based on available tnums and number of ports.
+ Set defaults (minim tresholds) and then distribute leftovers.*/
+int fm_precalculate_tnums(t_LnxWrpFmDev *p_LnxWrpFmDev, int max_fm_tnums)
+{
+ /* input parameters */
+ struct fm_active_ports *fm_active_ports_info = NULL;
+ int num_1g_ports = 0;
+ int num_2g5_ports = 0;
+ int num_10g_ports = 0;
+ int num_oh_ports = 0;
+
+ /* output parameters */
+ struct fm_resource_settings *fm_resource_settings_info = NULL;
+ int tx_1g_tnums = 0, rx_1g_tnums = 0;
+ int tx_2g5_tnums = 0, rx_2g5_tnums = 0;
+ int tx_10g_tnums = 0, rx_10g_tnums = 0;
+ int oh_tnums = 0;
+ int shared_ext_tnums = 0;
+ int err = 0;
+
+ /* open dma calculus */
+ int default_and_treshold_rx_tx_10g_tnums = 16; /* DPDE_10g */
+ int default_and_treshold_rx_tx_1g_2g5_tnums = 4; /* DPDE_1g */
+ int default_and_treshold_oh_tnums = 2; /* Hell knows why */
+ int max_tnums_treshold = 64; /* LLD: MAX_NUM_OF_TASKS */
+ int max_ext_tnums_treshold = 8; /* LLD: MAX_NUM_OF_EXTRA_TASKS */
+ int remaing_tnums = 0;
+ int tnums_computed = 0;
+ int leftovers = 0;
+ bool re_loop = true;
+
+ /* check input parameters correctness */
+ ASSERT_COND(p_LnxWrpFmDev != NULL);
+ fm_active_ports_info = &p_LnxWrpFmDev->fm_active_ports_info;
+ fm_resource_settings_info = &p_LnxWrpFmDev->fm_resource_settings_info;
+ ASSERT_COND(fm_active_ports_info != NULL);
+ ASSERT_COND(fm_resource_settings_info != NULL);
+ ASSERT_COND(fm_active_ports_info->num_tx_ports ==
+ fm_active_ports_info->num_rx_ports);
+ ASSERT_COND(fm_active_ports_info->num_tx25_ports ==
+ fm_active_ports_info->num_tx25_ports);
+ ASSERT_COND(fm_active_ports_info->num_tx10_ports ==
+ fm_active_ports_info->num_tx10_ports);
+
+ /* set input parameters */
+ num_1g_ports = fm_active_ports_info->num_tx_ports;
+ num_2g5_ports = fm_active_ports_info->num_tx25_ports;
+ num_10g_ports = fm_active_ports_info->num_tx10_ports;
+ num_oh_ports = fm_active_ports_info->num_oh_ports;
+
+ /* compute FMan TNUMs per port */
+ /* ------------------------------------------------------- */
+ if (num_1g_ports) {
+ tx_1g_tnums = default_and_treshold_rx_tx_1g_2g5_tnums;
+ rx_1g_tnums = default_and_treshold_rx_tx_1g_2g5_tnums;
+ }
+ if (num_2g5_ports) {
+ tx_2g5_tnums = default_and_treshold_rx_tx_1g_2g5_tnums;
+ rx_2g5_tnums = default_and_treshold_rx_tx_1g_2g5_tnums;
+ }
+ if (num_10g_ports) {
+ tx_10g_tnums = default_and_treshold_rx_tx_10g_tnums;
+ rx_10g_tnums = default_and_treshold_rx_tx_10g_tnums;
+ }
+ if (num_oh_ports)
+ oh_tnums = default_and_treshold_oh_tnums;
+
+ shared_ext_tnums = num_10g_ports ?
+ max_ext_tnums_treshold : 2; /* DEFAULT_PORT_extraNumOfTasks */
+
+ /* based on total number of ports set open DMAs for all other ports */
+ remaing_tnums = max_fm_tnums -
+ (oh_tnums * num_oh_ports) -
+ (tx_1g_tnums * num_1g_ports + rx_1g_tnums * num_1g_ports) -
+ (tx_2g5_tnums * num_2g5_ports + rx_2g5_tnums * num_2g5_ports) -
+ (tx_10g_tnums * num_10g_ports + rx_10g_tnums * num_10g_ports) -
+ shared_ext_tnums;
+
+ if (remaing_tnums < 0) {
+ printk(KERN_ALERT
+ "This configuration will not work due to low number"
+ " of tnums (%u tnums) and number of total ports"
+ " available...\n",
+ max_fm_tnums);
+ err = -1;
+ goto precalculated_tnums_out;
+ }
+
+ leftovers = remaing_tnums;
+ re_loop = true;
+ while (leftovers > 0 && re_loop == true) {
+ re_loop = false;
+ if (num_10g_ports && (leftovers - (int) num_10g_ports) >= 0
+ && (rx_10g_tnums < max_tnums_treshold)) {
+ rx_10g_tnums++;
+ leftovers -= num_10g_ports;
+ re_loop = true;
+ }
+
+ if (num_10g_ports && (leftovers - (int) num_10g_ports) >= 0
+ && (tx_10g_tnums < max_tnums_treshold)) {
+ tx_10g_tnums++;
+ leftovers -= num_10g_ports;
+ re_loop = true;
+ }
+
+ if (num_2g5_ports && (leftovers - (int) num_2g5_ports) >= 0
+ && (rx_2g5_tnums < max_tnums_treshold)) {
+ rx_2g5_tnums++;
+ leftovers -= num_2g5_ports;
+ re_loop = true;
+ }
+
+ if (num_2g5_ports && (leftovers - (int) num_2g5_ports) >= 0
+ && (tx_2g5_tnums < max_tnums_treshold)) {
+ tx_2g5_tnums++;
+ leftovers -= num_2g5_ports;
+ re_loop = true;
+ }
+
+ if (num_1g_ports && (leftovers - (int) num_1g_ports) >= 0
+ && (rx_1g_tnums < max_tnums_treshold)) {
+ rx_1g_tnums++;
+ leftovers -= num_1g_ports;
+ re_loop = true;
+ }
+
+ if (num_1g_ports && (leftovers - (int) num_1g_ports) >= 0
+ && (tx_1g_tnums < max_tnums_treshold)) {
+ tx_1g_tnums++;
+ leftovers -= num_1g_ports;
+ re_loop = true;
+ }
+ }
+
+ tnums_computed =
+ num_1g_ports * tx_1g_tnums +
+ num_1g_ports * rx_1g_tnums +
+ num_2g5_ports * tx_2g5_tnums +
+ num_2g5_ports * rx_2g5_tnums +
+ num_10g_ports * tx_10g_tnums +
+ num_10g_ports * rx_10g_tnums +
+ num_oh_ports * oh_tnums +
+ shared_ext_tnums;
+
+ if (leftovers > 0)
+ shared_ext_tnums =
+ MIN(shared_ext_tnums + max_fm_tnums - tnums_computed,
+ max_ext_tnums_treshold);
+
+ ASSERT_COND((oh_tnums * num_oh_ports) +
+ (tx_1g_tnums * num_1g_ports + rx_1g_tnums * num_1g_ports) +
+ (tx_2g5_tnums * num_2g5_ports +
+ rx_2g5_tnums * num_2g5_ports) +
+ (tx_10g_tnums * num_10g_ports +
+ rx_10g_tnums * num_10g_ports) + shared_ext_tnums <=
+ max_fm_tnums);
+
+ /* set computed tnums */
+ fm_resource_settings_info->tx_1g_tnums = tx_1g_tnums;
+ fm_resource_settings_info->rx_1g_tnums = rx_1g_tnums;
+ fm_resource_settings_info->tx_2g5_tnums = tx_2g5_tnums;
+ fm_resource_settings_info->rx_2g5_tnums = rx_2g5_tnums;
+ fm_resource_settings_info->tx_10g_tnums = tx_10g_tnums;
+ fm_resource_settings_info->rx_10g_tnums = rx_10g_tnums;
+ fm_resource_settings_info->oh_tnums = oh_tnums;
+ fm_resource_settings_info->shared_ext_tnums = shared_ext_tnums;
+
+precalculated_tnums_out:
+ printk(KERN_INFO " FMAN(%u) Tnums settings:\n", p_LnxWrpFmDev->id);
+ printk(KERN_INFO " - Total Tnums available(%u)\n", max_fm_tnums);
+ if (num_1g_ports) {
+ printk(KERN_INFO " - 1G ports TX %u(%u)\n", num_1g_ports,
+ tx_1g_tnums);
+ printk(KERN_INFO " - 1G ports RX %u(%u)\n", num_1g_ports,
+ rx_1g_tnums);
+ }
+ if (num_2g5_ports) {
+ printk(KERN_INFO " - 2.5G ports TX %u(%u)\n", num_2g5_ports,
+ tx_2g5_tnums);
+ printk(KERN_INFO " - 2.5G ports RX %u(%u)\n", num_2g5_ports,
+ rx_2g5_tnums);
+ }
+ if (num_10g_ports) {
+ printk(KERN_INFO " - 10G ports TX %u(%u)\n", num_10g_ports,
+ tx_10g_tnums);
+ printk(KERN_INFO " - 10G ports RX %u(%u)\n", num_10g_ports,
+ rx_10g_tnums);
+ }
+ if (num_oh_ports)
+ printk(KERN_INFO " - OH-HC ports %u(%u)\n", num_oh_ports,
+ oh_tnums);
+ printk(KERN_INFO " - Shared extra tnums(%u)\n", shared_ext_tnums);
+
+ return err;
+}
+
+#if !defined(FMAN_RESOURCES_UNIT_TEST)
+int fm_config_precalculate_tnums(t_LnxWrpFmPortDev *p_LnxWrpFmPortDev)
+{
+ t_LnxWrpFmDev *p_LnxWrpFmDev =
+ (t_LnxWrpFmDev *) p_LnxWrpFmPortDev->h_LnxWrpFmDev;
+ struct fm_resource_settings *fm_resource_settings_info = NULL;
+ t_FmPortRsrc numOfTask;
+ t_Error errCode;
+
+ ASSERT_COND(p_LnxWrpFmDev != NULL);
+ fm_resource_settings_info = &p_LnxWrpFmDev->fm_resource_settings_info;
+
+ memset(&numOfTask, 0, sizeof(t_FmPortRsrc));
+
+/* IF 1G PORT */
+ if (p_LnxWrpFmPortDev->settings.param.portType == e_FM_PORT_TYPE_TX)
+ numOfTask.num = fm_resource_settings_info->tx_1g_tnums;
+ else if (p_LnxWrpFmPortDev->settings.param.portType ==
+ e_FM_PORT_TYPE_RX)
+ numOfTask.num = fm_resource_settings_info->rx_1g_tnums;
+/* IF 2.5G PORT*/
+ /* TODO: Not supported by LLD yet. */
+
+/* IF 10G PORT */
+ else if (p_LnxWrpFmPortDev->settings.param.portType ==
+ e_FM_PORT_TYPE_TX_10G)
+ numOfTask.num = fm_resource_settings_info->tx_10g_tnums;
+ else if (p_LnxWrpFmPortDev->settings.param.portType ==
+ e_FM_PORT_TYPE_RX_10G)
+ numOfTask.num = fm_resource_settings_info->rx_10g_tnums;
+/* IF OH PORT */
+ else
+ numOfTask.num = fm_resource_settings_info->oh_dmas;
+
+ numOfTask.extra = fm_resource_settings_info->shared_ext_tnums;
+
+ errCode = FM_PORT_ConfigNumOfTasks(p_LnxWrpFmPortDev->h_Dev, &numOfTask);
+ if (errCode != E_OK) {
+ printk(KERN_WARNING
+ "FM_PORT_SetNumOfTasks failed (errCode:0x%2x)",
+ errCode);
+ return -EIO;
+ }
+
+ return 0;
+}
+#endif /*if !defined(FMAN_RESOURCES_UNIT_TEST)*/
diff --git a/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_resources.h b/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_resources.h
new file mode 100644
index 0000000..1b72e1d
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_resources.h
@@ -0,0 +1,121 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * 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 Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * 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 Freescale Semiconductor ``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 Freescale Semiconductor 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.
+ */
+
+/*
+ @File lnxwrp_resources.h
+
+ @Description FMD wrapper resource allocation functions.
+
+*/
+
+#ifndef LNXWRP_RESOURCES_H_
+#define LNXWRP_RESOURCES_H_
+
+#if !defined(FMAN_RESOURCES_UNIT_TEST)
+#include "lnxwrp_fm.h"
+#else
+#include "lnxwrp_resources_ut.h"
+#endif
+
+#define ROUND(X) ((2*(X)+1)/2)
+#define CEIL(X) ((X)+1)
+/* #define ROUND_DIV(X, Y) (((X)+(Y)/2)/(Y)) */
+#define ROUND_DIV(X, Y) ((2*(X)+(Y))/(2*(Y)))
+#define CEIL_DIV(X, Y) (((X)+(Y)-1)/(Y))
+
+/* used for resource calculus */
+#define DPDE_1G 2 /* DQDP 1g - from LLD:
+ DEFAULT_PORT_txFifoDeqPipelineDepth_1G */
+#define DPDE_10G 8 /* DQDP 10g - from LLD:
+ DEFAULT_PORT_txFifoDeqPipelineDepth_10G */
+
+int fm_set_active_fman_ports(struct platform_device *of_dev,
+ t_LnxWrpFmDev *p_LnxWrpFmDev);
+
+/* Calculate the fifosize based on MURAM allocation, number of ports, dpde
+ * value and s/g software support (! Kernel does not suport s/g).
+ *
+ * Algorithm summary:
+ * - Calculate the the minimum fifosize required for every type of port
+ * (TX,RX for 1G, 2.5G and 10G).
+ * - Set TX the minimum fifosize required.
+ * - Distribute the remaining buffers (after all TX were set) to RX ports
+ * based on:
+ * 1G RX = Remaining_buffers * 1/(1+2.5+10)
+ * 2.5G RX = Remaining_buffers * 2.5/(1+2.5+10)
+ * 10G RX = Remaining_buffers * 10/(1+2.5+10)
+ * - if the RX is smaller than the minimum required, then set the minimum
+ * required
+ * - In the end distribuite the leftovers if there are any (due to
+ * unprecise calculus) or if over allocation cat some buffers from all RX
+ * ports w/o pass over minimum required treshold, but if there must be
+ * pass the treshold in order to cat the over allocation ,then this
+ * configuration can not be set - KERN_ALERT.
+*/
+int fm_precalculate_fifosizes(t_LnxWrpFmDev *p_LnxWrpFmDev,
+ int muram_fifo_size);
+
+#if !defined(FMAN_RESOURCES_UNIT_TEST)
+int fm_config_precalculate_fifosize(t_LnxWrpFmPortDev *p_LnxWrpFmPortDev);
+#endif
+
+/* Compute FMan open DMA based on total number of open DMAs and
+ * number of available fman ports.
+ *
+ * By default 10g ports are set to input parameters. The other ports
+ * tries to keep the proportion rx=2tx open dmas or tresholds.
+ *
+ * If leftovers, then those will be set as shared.
+ *
+ * If after computing overflow appears, then it decrements open dma
+ * for all ports w/o cross the tresholds. If the tresholds are meet
+ * and is still overflow, then it returns error.
+*/
+int fm_precalculate_open_dma(t_LnxWrpFmDev *p_LnxWrpFmDev,
+ int max_fm_open_dma,
+ int default_tx_10g_dmas,
+ int default_rx_10g_dmas,
+ int min_tx_10g_treshold, int min_rx_10g_treshold);
+
+#if !defined(FMAN_RESOURCES_UNIT_TEST)
+int fm_config_precalculate_open_dma(t_LnxWrpFmPortDev *p_LnxWrpFmPortDev);
+#endif
+
+/* Compute FMan tnums based on available tnums and number of ports.
+ * Set defaults (minim tresholds) and then distribute leftovers.*/
+int fm_precalculate_tnums(t_LnxWrpFmDev *p_LnxWrpFmDev, int max_fm_tnums);
+
+#if !defined(FMAN_RESOURCES_UNIT_TEST)
+int fm_config_precalculate_tnums(t_LnxWrpFmPortDev *p_LnxWrpFmPortDev);
+#endif
+
+#endif /* LNXWRP_RESOURCES_H_ */
diff --git a/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_resources_ut.c b/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_resources_ut.c
new file mode 100644
index 0000000..6c06a5a
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_resources_ut.c
@@ -0,0 +1,191 @@
+/* Copyright (c) 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 Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * 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 Freescale Semiconductor ``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 Freescale Semiconductor 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 "lnxwrp_resources.h"
+#include "lnxwrp_resources_ut.h"
+
+#define KILOBYTE 0x400 /* 1024 */
+
+typedef enum e_board_type {
+ e_p3041,
+ e_p4080,
+ e_p5020,
+ e_p1023
+} e_board_type;
+
+uint8_t board_type;
+uint32_t muram_size = 0;
+uint32_t dmas_num = 0;
+uint32_t task_num = 0;
+uint32_t frame_size = 0;
+uint32_t oh_num = 0;
+uint32_t num_ports_1g = 0;
+uint32_t num_ports_10g = 0;
+uint32_t num_ports_2g5 = 0;
+uint32_t fsl_fman_phy_maxfrm = 0;
+uint32_t dpa_rx_extra_headroom = 0;
+
+void show_help(void){
+ printf(" help: \n");
+ printf(" -b <board_type> -f <max_fram_size(mtu)> -o <num_oh_ports> -g1"
+ " <num_1g_ports> -g10 <num_10g_ports> -g25 <num_2g5_ports>\n");
+ printf(" Maxim num of DMAS availbale: P3/P4/P5:32 , P1023:16 \n");
+ printf(" Maxim num of TNUMs availbale: P3/P4/P5:128, P1023:32 \n");
+ printf(" Muram size: P3/P4/P5:160K, P1023:64K \n");
+ printf(" Number of ports:\n");
+ printf(" P3/P5: 5p 1g, 1p 10g, 7p oh \n");
+ printf(" P4 : 4p 1g, 1p 10g, 7p oh \n");
+ printf(" P1 : 2p 1g, 0p 10g, 4p oh \n");
+ printf(" MTU: Default:1522, Jumbo:9600 \n");
+}
+
+int fm_set_param(t_LnxWrpFmDev *p_LnxWrpFmDev) {
+ struct fm_active_ports *fm_active_ports_info = NULL;
+ fm_active_ports_info = &p_LnxWrpFmDev->fm_active_ports_info;
+
+ switch(board_type){
+ case e_p3041:
+ case e_p5020:
+ muram_size = 160*KILOBYTE;
+ dmas_num = 32;
+ task_num = 128;
+ if ((num_ports_1g+num_ports_2g5) > 5 || num_ports_10g > 1 || oh_num > 7)
+ goto err_fm_set_param;
+ break;
+ case e_p4080:
+ muram_size = 160*KILOBYTE;
+ dmas_num = 32;
+ task_num = 128;
+ if ((num_ports_1g+num_ports_2g5) > 4 || num_ports_10g > 1 || oh_num > 7)
+ goto err_fm_set_param;
+ break;
+ case e_p1023:
+ muram_size = 64*KILOBYTE;
+ dmas_num = 16;
+ task_num = 128;
+ if ((num_ports_1g+num_ports_2g5) > 2 || oh_num > 4)
+ goto err_fm_set_param;
+ break;
+ default:
+ goto err_fm_set_param;
+ break;
+ }
+
+ p_LnxWrpFmDev->id = 0;
+ fsl_fman_phy_maxfrm = frame_size;
+ dpa_rx_extra_headroom = 0; /* ATTENTION: can be != 0 */
+ fm_active_ports_info->num_oh_ports = oh_num;
+ fm_active_ports_info->num_tx_ports = num_ports_1g;
+ fm_active_ports_info->num_rx_ports = num_ports_1g;
+ fm_active_ports_info->num_tx25_ports = num_ports_2g5;
+ fm_active_ports_info->num_rx25_ports = num_ports_2g5;
+ fm_active_ports_info->num_tx10_ports = num_ports_10g;
+ fm_active_ports_info->num_rx10_ports = num_ports_10g;
+
+ return 0;
+
+err_fm_set_param:
+ printf(" ERR: To many ports!!! \n");
+ return -1;
+}
+
+int main (int argc, char *argv[]){
+ t_LnxWrpFmDev LnxWrpFmDev;
+ t_LnxWrpFmDev *p_LnxWrpFmDev = &LnxWrpFmDev;
+ int tokens_cnt = 1;
+
+ char *token = NULL;
+
+ while(tokens_cnt < argc)
+ {
+ token = argv[tokens_cnt++];
+ if (strcmp(token, "-b") == 0){
+ if(strcmp(argv[tokens_cnt],"p3") == 0)
+ board_type = e_p3041;
+ else if(strcmp(argv[tokens_cnt],"p4") == 0)
+ board_type = e_p4080;
+ else if(strcmp(argv[tokens_cnt],"p5") == 0)
+ board_type = e_p5020;
+ else if(strcmp(argv[tokens_cnt],"p1") == 0)
+ board_type = e_p1023;
+ else
+ show_help();
+ tokens_cnt++;
+ }
+ else if(strcmp(token, "-d") == 0){
+ dmas_num = atoi(argv[tokens_cnt++]);
+ }
+ else if(strcmp(token, "-t") == 0)
+ task_num = atoi(argv[tokens_cnt++]);
+ else if(strcmp(token, "-f") == 0)
+ frame_size = atoi(argv[tokens_cnt++]);
+ else if(strcmp(token, "-o") == 0)
+ oh_num = atoi(argv[tokens_cnt++]);
+ else if(strcmp(token, "-g1") == 0)
+ num_ports_1g = atoi(argv[tokens_cnt++]);
+ else if(strcmp(token, "-g10") == 0)
+ num_ports_10g = atoi(argv[tokens_cnt++]);
+ else if(strcmp(token, "-g25") == 0)
+ num_ports_2g5 = atoi(argv[tokens_cnt++]);
+ else {
+ show_help();
+ return -1;
+ }
+ }
+
+ if(fm_set_param(p_LnxWrpFmDev) < 0){
+ show_help();
+ return -1;
+ }
+
+ if(fm_precalculate_fifosizes(
+ p_LnxWrpFmDev,
+ 128*KILOBYTE)
+ != 0)
+ return -1;
+ if(fm_precalculate_open_dma(
+ p_LnxWrpFmDev,
+ dmas_num, /* max open dmas:dpaa_integration_ext.h */
+ FM_DEFAULT_TX10G_OPENDMA, /* default TX 10g open dmas */
+ FM_DEFAULT_RX10G_OPENDMA, /* default RX 10g open dmas */
+ FM_10G_OPENDMA_MIN_TRESHOLD,/* TX 10g minimum treshold */
+ FM_10G_OPENDMA_MIN_TRESHOLD)/* RX 10g minimum treshold */
+ != 0)
+ return -1;
+ if(fm_precalculate_tnums(
+ p_LnxWrpFmDev,
+ task_num) /* max TNUMS: dpa integration file. */
+ != 0)
+ return -1;
+
+ return 0;
+}
diff --git a/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_resources_ut.h b/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_resources_ut.h
new file mode 100644
index 0000000..063946e
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_resources_ut.h
@@ -0,0 +1,144 @@
+/* Copyright (c) 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 Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * 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 Freescale Semiconductor ``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 Freescale Semiconductor 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 FM_RESS_TEST_H_
+#define FM_RESS_TEST_H_
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <assert.h>
+#include <string.h>
+#include <stdlib.h>
+
+#define _Packed
+#define _PackedType __attribute__ ((packed))
+#define MAX(x, y) (((x) > (y)) ? (x) : (y))
+#define MIN(x, y) (((x) < (y)) ? (x) : (y))
+#define KERN_ALERT ""
+#define KERN_INFO ""
+#define ASSERT_COND assert
+#define printk printf
+#define NET_IP_ALIGN 0
+#define FM_FIFO_ALLOCATION_OLD_ALG
+
+#if defined(CONFIG_FMAN_DISABLE_OH_AND_DISTRIBUTE_RESOURCES)
+#define FM_10G_OPENDMA_MIN_TRESHOLD 8 /* 10g minimum treshold if only HC is enabled and no OH port enabled */
+#define FM_OPENDMA_RX_TX_RAPORT 2 /* RX = 2*TX */
+#else
+#define FM_10G_OPENDMA_MIN_TRESHOLD 7 /* 10g minimum treshold if 7 OH ports are enabled */
+#define FM_OPENDMA_RX_TX_RAPORT 1 /* RX = TX */
+#endif
+#define FM_DEFAULT_TX10G_OPENDMA 8 /* default TX 10g open dmas */
+#define FM_DEFAULT_RX10G_OPENDMA 8 /* default RX 10g open dmas */
+
+/* information about all active ports for an FMan.
+ * !Some ports may be disabled by u-boot, thus will not be available */
+struct fm_active_ports {
+ uint32_t num_oh_ports;
+ uint32_t num_tx_ports;
+ uint32_t num_rx_ports;
+ uint32_t num_tx25_ports;
+ uint32_t num_rx25_ports;
+ uint32_t num_tx10_ports;
+ uint32_t num_rx10_ports;
+};
+
+/* FMan resources precalculated at fm probe based
+ * on available FMan port. */
+struct fm_resource_settings {
+ /* buffers - fifo sizes */
+ uint32_t tx1g_num_buffers;
+ uint32_t rx1g_num_buffers;
+ uint32_t tx2g5_num_buffers; /* Not supported yet by LLD */
+ uint32_t rx2g5_num_buffers; /* Not supported yet by LLD */
+ uint32_t tx10g_num_buffers;
+ uint32_t rx10g_num_buffers;
+ uint32_t oh_num_buffers;
+ uint32_t shared_ext_buffers;
+
+
+ /* open DMAs */
+ uint32_t tx_1g_dmas;
+ uint32_t rx_1g_dmas;
+ uint32_t tx_2g5_dmas; /* Not supported yet by LLD */
+ uint32_t rx_2g5_dmas; /* Not supported yet by LLD */
+ uint32_t tx_10g_dmas;
+ uint32_t rx_10g_dmas;
+ uint32_t oh_dmas;
+ uint32_t shared_ext_open_dma;
+
+ /* Tnums */
+ uint32_t tx_1g_tnums;
+ uint32_t rx_1g_tnums;
+ uint32_t tx_2g5_tnums; /* Not supported yet by LLD */
+ uint32_t rx_2g5_tnums; /* Not supported yet by LLD */
+ uint32_t tx_10g_tnums;
+ uint32_t rx_10g_tnums;
+ uint32_t oh_tnums;
+ uint32_t shared_ext_tnums;
+};
+
+typedef struct {
+ uint8_t id;
+ struct fm_active_ports fm_active_ports_info;
+ struct fm_resource_settings fm_resource_settings_info;
+} t_LnxWrpFmDev;
+
+typedef struct {
+ uint8_t id;
+} t_LnxWrpFmPortDev;
+
+typedef _Packed struct t_FmPrsResult {
+ volatile uint8_t lpid; /**< Logical port id */
+ volatile uint8_t shimr; /**< Shim header result */
+ volatile uint16_t l2r; /**< Layer 2 result */
+ volatile uint16_t l3r; /**< Layer 3 result */
+ volatile uint8_t l4r; /**< Layer 4 result */
+ volatile uint8_t cplan; /**< Classification plan id */
+ volatile uint16_t nxthdr; /**< Next Header */
+ volatile uint16_t cksum; /**< Checksum */
+ volatile uint32_t lcv; /**< LCV */
+ volatile uint8_t shim_off[3]; /**< Shim offset */
+ volatile uint8_t eth_off; /**< ETH offset */
+ volatile uint8_t llc_snap_off; /**< LLC_SNAP offset */
+ volatile uint8_t vlan_off[2]; /**< VLAN offset */
+ volatile uint8_t etype_off; /**< ETYPE offset */
+ volatile uint8_t pppoe_off; /**< PPP offset */
+ volatile uint8_t mpls_off[2]; /**< MPLS offset */
+ volatile uint8_t ip_off[2]; /**< IP offset */
+ volatile uint8_t gre_off; /**< GRE offset */
+ volatile uint8_t l4_off; /**< Layer 4 offset */
+ volatile uint8_t nxthdr_off; /**< Parser end point */
+} _PackedType t_FmPrsResult;
+
+#endif
diff --git a/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_resources_ut.make b/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_resources_ut.make
new file mode 100644
index 0000000..58009cd
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_resources_ut.make
@@ -0,0 +1,28 @@
+CC=gcc
+
+LNXWRP_RESS_UT=lnxwrp_resources_ut
+OBJ=lnxwrp_resources
+
+INC_PATH=
+LIB_PATH=
+
+INC=$(addprefix -I,$(INC_PATH))
+LIB=$(addprefix -L,$(LIB_PATH))
+
+CFLAGS= -gdwarf-2 -g -O0 -Wall
+XFLAGS= -DFMAN_RESOURCES_UNIT_TEST
+
+all: $(LNXWRP_RESS_UT)
+
+$(LNXWRP_RESS_UT):$(addsuffix .o,$(OBJ)) $(LNXWRP_RESS_UT).o
+ $(CC) -o $(LNXWRP_RESS_UT) $(LNXWRP_RESS_UT).o $(addsuffix .o,$(OBJ))
+
+%.o: %.c
+ @(echo " (CC) $@")
+ @($(CC) $(INC) $(CFLAGS) $(XFLAGS) -o $(@) -c $<)
+
+.PHONY: clean
+
+clean:
+ rm -f *.o
+ rm -f $(LNXWRP_RESS_UT)
diff --git a/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_sysfs.c b/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_sysfs.c
new file mode 100644
index 0000000..3f122b5
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_sysfs.c
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * 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 Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * 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 Freescale Semiconductor ``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 Freescale Semiconductor 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.
+ */
+
+/*
+ @File lnxwrp_sysfs.c
+
+ @Description FM wrapper sysfs related functions.
+
+*/
+
+#include <linux/types.h>
+#include "lnxwrp_sysfs.h"
+
+uint8_t fm_find_statistic_counter_by_name(const char *attr_name,
+ const struct SysfsStats_t *sysfs_stats,
+ uint8_t *offset)
+{
+ int i = 0;
+
+ while (sysfs_stats[i].statisticName != NULL) {
+ if (strcmp(sysfs_stats[i].statisticName, attr_name) == 0) {
+ if (offset != NULL)
+ *offset = i;
+ return sysfs_stats[i].statisticCounter;
+ }
+
+ i++;
+ }
+ WARN(1, "FMD: Should never get here!");
+ return 0;
+}
diff --git a/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_sysfs.h b/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_sysfs.h
new file mode 100644
index 0000000..67cb2b0
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_sysfs.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * 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 Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * 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 Freescale Semiconductor ``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 Freescale Semiconductor 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.
+ */
+
+/*
+ @File lnxwrp_sysfs.h
+
+ @Description FM sysfs functions.
+
+*/
+
+#ifndef LNXWRP_SYSFS_H_
+#define LNXWRP_SYSFS_H_
+
+/* Linux Headers ------------------- */
+#include <linux/version.h>
+
+#if defined(CONFIG_MODVERSIONS) && !defined(MODVERSIONS)
+#define MODVERSIONS
+#endif
+#ifdef MODVERSIONS
+#include <config/modversions.h>
+#endif /* MODVERSIONS */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/sysfs.h>
+
+struct SysfsStats_t {
+ const char *statisticName;
+ uint8_t statisticCounter;
+};
+
+uint8_t fm_find_statistic_counter_by_name(const char *attr_name,
+ const struct SysfsStats_t *sysfs_stats,
+ uint8_t *offset);
+
+#endif /* LNXWRP_SYSFS_H_ */
diff --git a/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_sysfs_fm.c b/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_sysfs_fm.c
new file mode 100644
index 0000000..2cfc0b9
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_sysfs_fm.c
@@ -0,0 +1,573 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * 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 Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * 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 Freescale Semiconductor ``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 Freescale Semiconductor 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.
+ */
+
+/*
+ @File lnxwrp_sysfs_fm.c
+
+ @Description FM sysfs related functions.
+
+*/
+
+#include "lnxwrp_sysfs.h"
+#include "lnxwrp_fm.h"
+
+enum e_FmDmaMatchStatistics {
+ e_FM_DMA_COUNTERS_CMQ_NOT_EMPTY,
+ e_FM_DMA_COUNTERS_BUS_ERROR,
+ e_FM_DMA_COUNTERS_READ_BUF_ECC_ERROR,
+ e_FM_DMA_COUNTERS_WRITE_BUF_ECC_SYS_ERROR,
+ e_FM_DMA_COUNTERS_WRITE_BUF_ECC_FM_ERROR
+};
+
+static const struct SysfsStats_t fmSysfsStats[] = {
+ /* FM statistics */
+ {
+ .statisticName = "enq_total_frame",
+ .statisticCounter = e_FM_COUNTERS_ENQ_TOTAL_FRAME,
+ },
+ {
+ .statisticName = "deq_total_frame",
+ .statisticCounter = e_FM_COUNTERS_DEQ_TOTAL_FRAME,
+ },
+ {
+ .statisticName = "deq_0",
+ .statisticCounter = e_FM_COUNTERS_DEQ_0,
+ },
+ {
+ .statisticName = "deq_1",
+ .statisticCounter = e_FM_COUNTERS_DEQ_1,
+ },
+ {
+ .statisticName = "deq_2",
+ .statisticCounter = e_FM_COUNTERS_DEQ_2,
+ },
+ {
+ .statisticName = "deq_3",
+ .statisticCounter = e_FM_COUNTERS_DEQ_3,
+ },
+ {
+ .statisticName = "deq_from_default",
+ .statisticCounter = e_FM_COUNTERS_DEQ_FROM_DEFAULT,
+ },
+ {
+ .statisticName = "deq_from_context",
+ .statisticCounter = e_FM_COUNTERS_DEQ_FROM_CONTEXT,
+ },
+ {
+ .statisticName = "deq_from_fd",
+ .statisticCounter = e_FM_COUNTERS_DEQ_FROM_FD,
+ },
+ {
+ .statisticName = "deq_confirm",
+ .statisticCounter = e_FM_COUNTERS_DEQ_CONFIRM,
+ },
+ /* FM:DMA statistics */
+ {
+ .statisticName = "cmq_not_empty",
+ .statisticCounter = e_FM_DMA_COUNTERS_CMQ_NOT_EMPTY,
+ },
+ {
+ .statisticName = "bus_error",
+ .statisticCounter = e_FM_DMA_COUNTERS_BUS_ERROR,
+ },
+ {
+ .statisticName = "read_buf_ecc_error",
+ .statisticCounter = e_FM_DMA_COUNTERS_READ_BUF_ECC_ERROR,
+ },
+ {
+ .statisticName = "write_buf_ecc_sys_error",
+ .statisticCounter = e_FM_DMA_COUNTERS_WRITE_BUF_ECC_SYS_ERROR,
+ },
+ {
+ .statisticName = "write_buf_ecc_fm_error",
+ .statisticCounter = e_FM_DMA_COUNTERS_WRITE_BUF_ECC_FM_ERROR,
+ },
+ /* FM:PCD statistics */
+ {
+ .statisticName = "pcd_kg_total",
+ .statisticCounter = e_FM_PCD_KG_COUNTERS_TOTAL,
+ },
+ {
+ .statisticName = "pcd_plcr_yellow",
+ .statisticCounter = e_FM_PCD_PLCR_COUNTERS_YELLOW,
+ },
+ {
+ .statisticName = "pcd_plcr_red",
+ .statisticCounter = e_FM_PCD_PLCR_COUNTERS_RED,
+ },
+ {
+ .statisticName = "pcd_plcr_recolored_to_red",
+ .statisticCounter = e_FM_PCD_PLCR_COUNTERS_RECOLORED_TO_RED,
+ },
+ {
+ .statisticName = "pcd_plcr_recolored_to_yellow",
+ .statisticCounter = e_FM_PCD_PLCR_COUNTERS_RECOLORED_TO_YELLOW,
+ },
+ {
+ .statisticName = "pcd_plcr_total",
+ .statisticCounter = e_FM_PCD_PLCR_COUNTERS_TOTAL,
+ },
+ {
+ .statisticName = "pcd_plcr_length_mismatch",
+ .statisticCounter = e_FM_PCD_PLCR_COUNTERS_LENGTH_MISMATCH,
+ },
+ {
+ .statisticName = "pcd_prs_parse_dispatch",
+ .statisticCounter = e_FM_PCD_PRS_COUNTERS_PARSE_DISPATCH,
+ },
+ {
+ .statisticName = "pcd_prs_l2_parse_result_returned",
+ .statisticCounter = e_FM_PCD_PRS_COUNTERS_L2_PARSE_RESULT_RETURNED,
+ },
+ {
+ .statisticName = "pcd_prs_l3_parse_result_returned",
+ .statisticCounter = e_FM_PCD_PRS_COUNTERS_L3_PARSE_RESULT_RETURNED,
+ },
+ {
+ .statisticName = "pcd_prs_l4_parse_result_returned",
+ .statisticCounter = e_FM_PCD_PRS_COUNTERS_L4_PARSE_RESULT_RETURNED,
+ },
+ {
+ .statisticName = "pcd_prs_shim_parse_result_returned",
+ .statisticCounter = e_FM_PCD_PRS_COUNTERS_SHIM_PARSE_RESULT_RETURNED,
+ },
+ {
+ .statisticName = "pcd_prs_l2_parse_result_returned_with_err",
+ .statisticCounter =
+ e_FM_PCD_PRS_COUNTERS_L2_PARSE_RESULT_RETURNED_WITH_ERR,
+ },
+ {
+ .statisticName = "pcd_prs_l3_parse_result_returned_with_err",
+ .statisticCounter =
+ e_FM_PCD_PRS_COUNTERS_L3_PARSE_RESULT_RETURNED_WITH_ERR,
+ },
+ {
+ .statisticName = "pcd_prs_l4_parse_result_returned_with_err",
+ .statisticCounter =
+ e_FM_PCD_PRS_COUNTERS_L4_PARSE_RESULT_RETURNED_WITH_ERR,
+ },
+ {
+ .statisticName = "pcd_prs_shim_parse_result_returned_with_err",
+ .statisticCounter =
+ e_FM_PCD_PRS_COUNTERS_SHIM_PARSE_RESULT_RETURNED_WITH_ERR,
+ },
+ {
+ .statisticName = "pcd_prs_soft_prs_cycles",
+ .statisticCounter = e_FM_PCD_PRS_COUNTERS_SOFT_PRS_CYCLES,
+ },
+ {
+ .statisticName = "pcd_prs_soft_prs_stall_cycles",
+ .statisticCounter = e_FM_PCD_PRS_COUNTERS_SOFT_PRS_STALL_CYCLES,
+ },
+ {
+ .statisticName = "pcd_prs_hard_prs_cycle_incl_stall_cycles",
+ .statisticCounter =
+ e_FM_PCD_PRS_COUNTERS_HARD_PRS_CYCLE_INCL_STALL_CYCLES,
+ },
+ {
+ .statisticName = "pcd_prs_muram_read_cycles",
+ .statisticCounter = e_FM_PCD_PRS_COUNTERS_MURAM_READ_CYCLES,
+ },
+ {
+ .statisticName = "pcd_prs_muram_read_stall_cycles",
+ .statisticCounter = e_FM_PCD_PRS_COUNTERS_MURAM_READ_STALL_CYCLES,
+ },
+ {
+ .statisticName = "pcd_prs_muram_write_cycles",
+ .statisticCounter = e_FM_PCD_PRS_COUNTERS_MURAM_WRITE_CYCLES,
+ },
+ {
+ .statisticName = "pcd_prs_muram_write_stall_cycles",
+ .statisticCounter = e_FM_PCD_PRS_COUNTERS_MURAM_WRITE_STALL_CYCLES,
+ },
+ {
+ .statisticName = "pcd_prs_fpm_command_stall_cycles",
+ .statisticCounter = e_FM_PCD_PRS_COUNTERS_FPM_COMMAND_STALL_CYCLES,
+ },
+ {}
+};
+
+/* Fm stats and regs dumps via sysfs */
+static ssize_t show_fm_dma_stats(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ t_LnxWrpFmDev *p_LnxWrpFmDev = NULL;
+ t_FmDmaStatus fmDmaStatus;
+ unsigned long flags = 0;
+ unsigned n = 0;
+ uint8_t counter_value = 0, counter = 0;
+
+ if (attr == NULL || buf == NULL || dev == NULL)
+ return -EINVAL;
+
+ p_LnxWrpFmDev = (t_LnxWrpFmDev *) dev_get_drvdata(dev);
+ if (WARN_ON(p_LnxWrpFmDev == NULL))
+ return -EINVAL;
+
+ if (!p_LnxWrpFmDev->active || !p_LnxWrpFmDev->h_Dev)
+ return -EIO;
+
+ counter = fm_find_statistic_counter_by_name(
+ attr->attr.name,
+ fmSysfsStats, NULL);
+
+ local_irq_save(flags);
+
+ memset(&fmDmaStatus, 0, sizeof(fmDmaStatus));
+ FM_GetDmaStatus(p_LnxWrpFmDev->h_Dev, &fmDmaStatus);
+
+ switch (counter) {
+ case e_FM_DMA_COUNTERS_CMQ_NOT_EMPTY:
+ counter_value = fmDmaStatus.cmqNotEmpty;
+ break;
+ case e_FM_DMA_COUNTERS_BUS_ERROR:
+ counter_value = fmDmaStatus.busError;
+ break;
+ case e_FM_DMA_COUNTERS_READ_BUF_ECC_ERROR:
+ counter_value = fmDmaStatus.readBufEccError;
+ break;
+ case e_FM_DMA_COUNTERS_WRITE_BUF_ECC_SYS_ERROR:
+ counter_value = fmDmaStatus.writeBufEccSysError;
+ break;
+ case e_FM_DMA_COUNTERS_WRITE_BUF_ECC_FM_ERROR:
+ counter_value = fmDmaStatus.writeBufEccFmError;
+ break;
+ default:
+ WARN(1, "FMD: failure at %s:%d/%s()!\n", __FILE__, __LINE__,
+ __func__);
+ break;
+ };
+
+ n = snprintf(buf, PAGE_SIZE, "\tFM %u counter: %c\n",
+ p_LnxWrpFmDev->id, counter_value ? 'T' : 'F');
+
+ local_irq_restore(flags);
+
+ return n;
+}
+
+static ssize_t show_fm_stats(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ t_LnxWrpFmDev *p_LnxWrpFmDev = NULL;
+ unsigned long flags = 0;
+ unsigned n = 0, counter = 0;
+
+ if (attr == NULL || buf == NULL || dev == NULL)
+ return -EINVAL;
+
+ p_LnxWrpFmDev = (t_LnxWrpFmDev *) dev_get_drvdata(dev);
+ if (WARN_ON(p_LnxWrpFmDev == NULL))
+ return -EINVAL;
+
+ if (!p_LnxWrpFmDev->active || !p_LnxWrpFmDev->h_Dev)
+ return -EIO;
+
+ counter = fm_find_statistic_counter_by_name(
+ attr->attr.name,
+ fmSysfsStats, NULL);
+
+ local_irq_save(flags);
+
+ n = snprintf(buf, PAGE_SIZE, "\tFM %d counter: %d\n",
+ p_LnxWrpFmDev->id,
+ FM_GetCounter(p_LnxWrpFmDev->h_Dev,
+ (e_FmCounters) counter));
+
+ local_irq_restore(flags);
+
+ return n;
+}
+
+static ssize_t show_fm_pcd_stats(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ t_LnxWrpFmDev *p_LnxWrpFmDev = NULL;
+ unsigned long flags = 0;
+ unsigned n = 0, counter = 0;
+
+ if (attr == NULL || buf == NULL || dev == NULL)
+ return -EINVAL;
+
+ p_LnxWrpFmDev = (t_LnxWrpFmDev *) dev_get_drvdata(dev);
+ if (WARN_ON(p_LnxWrpFmDev == NULL))
+ return -EINVAL;
+
+ if (!p_LnxWrpFmDev->active || !p_LnxWrpFmDev->h_Dev ||
+ !p_LnxWrpFmDev->h_PcdDev)
+ return -EIO;
+
+ counter = fm_find_statistic_counter_by_name(
+ attr->attr.name,
+ fmSysfsStats, NULL);
+
+ local_irq_save(flags);
+
+ n = snprintf(buf, PAGE_SIZE, "\tFM %d counter: %d\n",
+ p_LnxWrpFmDev->id,
+ FM_PCD_GetCounter(p_LnxWrpFmDev->h_PcdDev,
+ (e_FmPcdCounters) counter));
+
+ local_irq_restore(flags);
+
+ return n;
+}
+
+/* FM */
+static DEVICE_ATTR(enq_total_frame, S_IRUGO, show_fm_stats, NULL);
+static DEVICE_ATTR(deq_total_frame, S_IRUGO, show_fm_stats, NULL);
+static DEVICE_ATTR(deq_0, S_IRUGO, show_fm_stats, NULL);
+static DEVICE_ATTR(deq_1, S_IRUGO, show_fm_stats, NULL);
+static DEVICE_ATTR(deq_2, S_IRUGO, show_fm_stats, NULL);
+static DEVICE_ATTR(deq_3, S_IRUGO, show_fm_stats, NULL);
+static DEVICE_ATTR(deq_from_default, S_IRUGO, show_fm_stats, NULL);
+static DEVICE_ATTR(deq_from_context, S_IRUGO, show_fm_stats, NULL);
+static DEVICE_ATTR(deq_from_fd, S_IRUGO, show_fm_stats, NULL);
+static DEVICE_ATTR(deq_confirm, S_IRUGO, show_fm_stats, NULL);
+/* FM:DMA */
+static DEVICE_ATTR(cmq_not_empty, S_IRUGO, show_fm_dma_stats, NULL);
+static DEVICE_ATTR(bus_error, S_IRUGO, show_fm_dma_stats, NULL);
+static DEVICE_ATTR(read_buf_ecc_error, S_IRUGO, show_fm_dma_stats, NULL);
+static DEVICE_ATTR(write_buf_ecc_sys_error, S_IRUGO, show_fm_dma_stats, NULL);
+static DEVICE_ATTR(write_buf_ecc_fm_error, S_IRUGO, show_fm_dma_stats, NULL);
+/* FM:PCD */
+static DEVICE_ATTR(pcd_kg_total, S_IRUGO, show_fm_pcd_stats, NULL);
+static DEVICE_ATTR(pcd_plcr_yellow, S_IRUGO, show_fm_pcd_stats, NULL);
+static DEVICE_ATTR(pcd_plcr_red, S_IRUGO, show_fm_pcd_stats, NULL);
+static DEVICE_ATTR(pcd_plcr_recolored_to_red, S_IRUGO, show_fm_pcd_stats,
+ NULL);
+static DEVICE_ATTR(pcd_plcr_recolored_to_yellow, S_IRUGO, show_fm_pcd_stats,
+ NULL);
+static DEVICE_ATTR(pcd_plcr_total, S_IRUGO, show_fm_pcd_stats, NULL);
+static DEVICE_ATTR(pcd_plcr_length_mismatch, S_IRUGO, show_fm_pcd_stats,
+ NULL);
+static DEVICE_ATTR(pcd_prs_parse_dispatch, S_IRUGO, show_fm_pcd_stats, NULL);
+static DEVICE_ATTR(pcd_prs_l2_parse_result_returned, S_IRUGO,
+ show_fm_pcd_stats, NULL);
+static DEVICE_ATTR(pcd_prs_l3_parse_result_returned, S_IRUGO,
+ show_fm_pcd_stats, NULL);
+static DEVICE_ATTR(pcd_prs_l4_parse_result_returned, S_IRUGO,
+ show_fm_pcd_stats, NULL);
+static DEVICE_ATTR(pcd_prs_shim_parse_result_returned, S_IRUGO,
+ show_fm_pcd_stats, NULL);
+static DEVICE_ATTR(pcd_prs_l2_parse_result_returned_with_err, S_IRUGO,
+ show_fm_pcd_stats, NULL);
+static DEVICE_ATTR(pcd_prs_l3_parse_result_returned_with_err, S_IRUGO,
+ show_fm_pcd_stats, NULL);
+static DEVICE_ATTR(pcd_prs_l4_parse_result_returned_with_err, S_IRUGO,
+ show_fm_pcd_stats, NULL);
+static DEVICE_ATTR(pcd_prs_shim_parse_result_returned_with_err, S_IRUGO,
+ show_fm_pcd_stats, NULL);
+static DEVICE_ATTR(pcd_prs_soft_prs_cycles, S_IRUGO, show_fm_pcd_stats, NULL);
+static DEVICE_ATTR(pcd_prs_soft_prs_stall_cycles, S_IRUGO, show_fm_pcd_stats,
+ NULL);
+static DEVICE_ATTR(pcd_prs_hard_prs_cycle_incl_stall_cycles, S_IRUGO,
+ show_fm_pcd_stats, NULL);
+static DEVICE_ATTR(pcd_prs_muram_read_cycles, S_IRUGO, show_fm_pcd_stats,
+ NULL);
+static DEVICE_ATTR(pcd_prs_muram_read_stall_cycles, S_IRUGO,
+ show_fm_pcd_stats, NULL);
+static DEVICE_ATTR(pcd_prs_muram_write_cycles, S_IRUGO, show_fm_pcd_stats,
+ NULL);
+static DEVICE_ATTR(pcd_prs_muram_write_stall_cycles, S_IRUGO,
+ show_fm_pcd_stats, NULL);
+static DEVICE_ATTR(pcd_prs_fpm_command_stall_cycles, S_IRUGO,
+ show_fm_pcd_stats, NULL);
+
+static struct attribute *fm_dev_stats_attributes[] = {
+ &dev_attr_enq_total_frame.attr,
+ &dev_attr_deq_total_frame.attr,
+ &dev_attr_deq_0.attr,
+ &dev_attr_deq_1.attr,
+ &dev_attr_deq_2.attr,
+ &dev_attr_deq_3.attr,
+ &dev_attr_deq_from_default.attr,
+ &dev_attr_deq_from_context.attr,
+ &dev_attr_deq_from_fd.attr,
+ &dev_attr_deq_confirm.attr,
+ &dev_attr_cmq_not_empty.attr,
+ &dev_attr_bus_error.attr,
+ &dev_attr_read_buf_ecc_error.attr,
+ &dev_attr_write_buf_ecc_sys_error.attr,
+ &dev_attr_write_buf_ecc_fm_error.attr,
+ &dev_attr_pcd_kg_total.attr,
+ &dev_attr_pcd_plcr_yellow.attr,
+ &dev_attr_pcd_plcr_red.attr,
+ &dev_attr_pcd_plcr_recolored_to_red.attr,
+ &dev_attr_pcd_plcr_recolored_to_yellow.attr,
+ &dev_attr_pcd_plcr_total.attr,
+ &dev_attr_pcd_plcr_length_mismatch.attr,
+ &dev_attr_pcd_prs_parse_dispatch.attr,
+ &dev_attr_pcd_prs_l2_parse_result_returned.attr,
+ &dev_attr_pcd_prs_l3_parse_result_returned.attr,
+ &dev_attr_pcd_prs_l4_parse_result_returned.attr,
+ &dev_attr_pcd_prs_shim_parse_result_returned.attr,
+ &dev_attr_pcd_prs_l2_parse_result_returned_with_err.attr,
+ &dev_attr_pcd_prs_l3_parse_result_returned_with_err.attr,
+ &dev_attr_pcd_prs_l4_parse_result_returned_with_err.attr,
+ &dev_attr_pcd_prs_shim_parse_result_returned_with_err.attr,
+ &dev_attr_pcd_prs_soft_prs_cycles.attr,
+ &dev_attr_pcd_prs_soft_prs_stall_cycles.attr,
+ &dev_attr_pcd_prs_hard_prs_cycle_incl_stall_cycles.attr,
+ &dev_attr_pcd_prs_muram_read_cycles.attr,
+ &dev_attr_pcd_prs_muram_read_stall_cycles.attr,
+ &dev_attr_pcd_prs_muram_write_cycles.attr,
+ &dev_attr_pcd_prs_muram_write_stall_cycles.attr,
+ &dev_attr_pcd_prs_fpm_command_stall_cycles.attr,
+ NULL
+};
+
+static const struct attribute_group fm_dev_stats_attr_grp = {
+ .name = "statistics",
+ .attrs = fm_dev_stats_attributes
+};
+
+static ssize_t show_fm_regs(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ unsigned long flags;
+ unsigned n = 0;
+#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0))
+ t_LnxWrpFmDev *p_LnxWrpFmDev = NULL;
+#endif
+
+ if (attr == NULL || buf == NULL || dev == NULL)
+ return -EINVAL;
+
+#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0))
+
+ p_LnxWrpFmDev = (t_LnxWrpFmDev *) dev_get_drvdata(dev);
+ if (WARN_ON(p_LnxWrpFmDev == NULL))
+ return -EINVAL;
+
+ local_irq_save(flags);
+
+ n = snprintf(buf, PAGE_SIZE, "FM driver registers dump.\n");
+
+ if (!p_LnxWrpFmDev->active || !p_LnxWrpFmDev->h_Dev)
+ return -EIO;
+ else
+ FM_DumpRegs(p_LnxWrpFmDev->h_Dev);
+
+ local_irq_restore(flags);
+#else
+
+ local_irq_save(flags);
+ n = snprintf(buf, PAGE_SIZE,
+ "Debug level is too low to dump registers!!!\n");
+ local_irq_restore(flags);
+#endif /* (defined(DEBUG_ERRORS) && ... */
+
+ return n;
+}
+
+static ssize_t show_pcd_regs(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned long flags;
+ unsigned n = 0;
+#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0))
+ t_LnxWrpFmDev *p_LnxWrpFmDev = NULL;
+#endif
+
+ if (attr == NULL || buf == NULL || dev == NULL)
+ return -EINVAL;
+
+#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0))
+ p_LnxWrpFmDev = (t_LnxWrpFmDev *) dev_get_drvdata(dev);
+ if (WARN_ON(p_LnxWrpFmDev == NULL))
+ return -EINVAL;
+
+ local_irq_save(flags);
+ n = snprintf(buf, PAGE_SIZE, "FM driver registers dump.\n");
+
+ if (!p_LnxWrpFmDev->active || !p_LnxWrpFmDev->h_PcdDev)
+ return -EIO;
+ else
+ FM_PCD_DumpRegs(p_LnxWrpFmDev->h_PcdDev);
+
+ local_irq_restore(flags);
+#else
+
+ local_irq_save(flags);
+ n = snprintf(buf, PAGE_SIZE,
+ "Debug level is too low to dump registers!!!\n");
+ local_irq_restore(flags);
+
+#endif /* (defined(DEBUG_ERRORS) && ... */
+
+ return n;
+}
+
+static DEVICE_ATTR(fm_regs, S_IRUGO, show_fm_regs, NULL);
+static DEVICE_ATTR(fm_pcd_regs, S_IRUGO, show_pcd_regs, NULL);
+
+int fm_sysfs_create(struct device *dev)
+{
+ t_LnxWrpFmDev *p_LnxWrpFmDev = NULL;
+
+ if (dev == NULL)
+ return -EIO;
+
+ p_LnxWrpFmDev = (t_LnxWrpFmDev *) dev_get_drvdata(dev);
+
+ /* store to remove them when module is disabled */
+ p_LnxWrpFmDev->dev_attr_regs = &dev_attr_fm_regs;
+ p_LnxWrpFmDev->dev_pcd_attr_regs = &dev_attr_fm_pcd_regs;
+
+ /* Create sysfs statistics group for FM module */
+ if (sysfs_create_group(&dev->kobj, &fm_dev_stats_attr_grp) != 0)
+ return -EIO;
+
+ /* Registers dump entry - in future will be moved to debugfs */
+ if (device_create_file(dev, &dev_attr_fm_regs) != 0 ||
+ device_create_file(dev, &dev_attr_fm_pcd_regs) != 0)
+ return -EIO;
+
+ return 0;
+}
+
+void fm_sysfs_destroy(struct device *dev)
+{
+ t_LnxWrpFmDev *p_LnxWrpFmDev = NULL;
+
+ if (WARN_ON(dev == NULL))
+ return;
+
+ p_LnxWrpFmDev = (t_LnxWrpFmDev *) dev_get_drvdata(dev);
+ if (WARN_ON(p_LnxWrpFmDev == NULL))
+ return;
+
+ sysfs_remove_group(&dev->kobj, &fm_dev_stats_attr_grp);
+ device_remove_file(dev, p_LnxWrpFmDev->dev_attr_regs);
+ device_remove_file(dev, p_LnxWrpFmDev->dev_pcd_attr_regs);
+}
diff --git a/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_sysfs_fm.h b/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_sysfs_fm.h
new file mode 100644
index 0000000..8aff850
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_sysfs_fm.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * 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 Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * 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 Freescale Semiconductor ``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 Freescale Semiconductor 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.
+ */
+
+/*
+ @File lnxwrp_sysfs_fm.h
+
+ @Description FM sysfs functions.
+
+*/
+
+#ifndef LNXWRP_SYSFS_FM_H_
+#define LNXWRP_SYSFS_FM_H_
+
+#include "lnxwrp_sysfs.h"
+
+int fm_sysfs_create(struct device *dev);
+void fm_sysfs_destroy(struct device *dev);
+
+#endif /* LNXWRP_SYSFS_FM_H_ */
diff --git a/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_sysfs_fm_port.c b/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_sysfs_fm_port.c
new file mode 100644
index 0000000..97dacb7
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_sysfs_fm_port.c
@@ -0,0 +1,365 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * 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 Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * 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 Freescale Semiconductor ``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 Freescale Semiconductor 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.
+ */
+
+/*
+ @File lnxwrp_sysfs_fm_port.c
+
+ @Description FM port sysfs related functions.
+
+*/
+
+#include "lnxwrp_sysfs.h"
+#include "lnxwrp_fm.h"
+
+static const struct SysfsStats_t portSysfsStats[] = {
+ /* RX/TX/OH common statistics */
+ {
+ .statisticName = "port_frame",
+ .statisticCounter = e_FM_PORT_COUNTERS_FRAME,
+ },
+ {
+ .statisticName = "port_discard_frame",
+ .statisticCounter = e_FM_PORT_COUNTERS_DISCARD_FRAME,
+ },
+ {
+ .statisticName = "port_dealloc_buf",
+ .statisticCounter = e_FM_PORT_COUNTERS_DEALLOC_BUF,
+ },
+ {
+ .statisticName = "port_enq_total",
+ .statisticCounter = e_FM_PORT_COUNTERS_ENQ_TOTAL,
+ },
+ /* TX/OH */
+ {
+ .statisticName = "port_length_err",
+ .statisticCounter = e_FM_PORT_COUNTERS_LENGTH_ERR,
+ },
+ {
+ .statisticName = "port_unsupprted_format",
+ .statisticCounter = e_FM_PORT_COUNTERS_UNSUPPRTED_FORMAT,
+ },
+ {
+ .statisticName = "port_deq_total",
+ .statisticCounter = e_FM_PORT_COUNTERS_DEQ_TOTAL,
+ },
+ {
+ .statisticName = "port_deq_from_default",
+ .statisticCounter = e_FM_PORT_COUNTERS_DEQ_FROM_DEFAULT,
+ },
+ {
+ .statisticName = "port_deq_confirm",
+ .statisticCounter = e_FM_PORT_COUNTERS_DEQ_CONFIRM,
+ },
+ /* RX/OH */
+ {
+ .statisticName = "port_rx_bad_frame",
+ .statisticCounter = e_FM_PORT_COUNTERS_RX_BAD_FRAME,
+ },
+ {
+ .statisticName = "port_rx_large_frame",
+ .statisticCounter = e_FM_PORT_COUNTERS_RX_LARGE_FRAME,
+ },
+ {
+ .statisticName = "port_rx_out_of_buffers_discard",
+ .statisticCounter = e_FM_PORT_COUNTERS_RX_OUT_OF_BUFFERS_DISCARD,
+ },
+ {
+ .statisticName = "port_rx_filter_frame",
+ .statisticCounter = e_FM_PORT_COUNTERS_RX_FILTER_FRAME,
+ },
+ /* TODO: Particular statistics for OH ports */
+ {}
+};
+
+static ssize_t show_fm_port_stats(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev;
+ t_LnxWrpFmDev *p_LnxWrpFmDev;
+ unsigned long flags;
+ int n = 0;
+ uint8_t counter = 0;
+
+ if (attr == NULL || buf == NULL || dev == NULL)
+ return -EINVAL;
+
+ p_LnxWrpFmPortDev = (t_LnxWrpFmPortDev *) dev_get_drvdata(dev);
+ if (WARN_ON(p_LnxWrpFmPortDev == NULL))
+ return -EINVAL;
+
+ p_LnxWrpFmDev = (t_LnxWrpFmDev *) p_LnxWrpFmPortDev->h_LnxWrpFmDev;
+ if (WARN_ON(p_LnxWrpFmDev == NULL))
+ return -EINVAL;
+
+ if (!p_LnxWrpFmDev->active || !p_LnxWrpFmDev->h_Dev)
+ return -EIO;
+
+ if (!p_LnxWrpFmPortDev->h_Dev) {
+ n = snprintf(buf, PAGE_SIZE, "\tFM Port not configured...\n");
+ return n;
+ }
+
+ counter = fm_find_statistic_counter_by_name(
+ attr->attr.name,
+ portSysfsStats, NULL);
+
+ if (counter == e_FM_PORT_COUNTERS_RX_LIST_DMA_ERR) {
+ uint32_t fmRev = 0;
+ fmRev = 0xffff & ioread32(UINT_TO_PTR(p_LnxWrpFmDev->fmBaseAddr
+ + 0x000c30c4));
+
+ if (fmRev == 0x0100) {
+ local_irq_save(flags);
+ n = snprintf(buf, PAGE_SIZE,
+ "counter not available for revision 1\n");
+ local_irq_restore(flags);
+ }
+ return n;
+ }
+
+ local_irq_save(flags);
+ n = snprintf(buf, PAGE_SIZE, "\tFM %d Port %d counter: %d\n",
+ p_LnxWrpFmDev->id,
+ p_LnxWrpFmPortDev->id,
+ FM_PORT_GetCounter(p_LnxWrpFmPortDev->h_Dev,
+ (e_FmPortCounters) counter));
+ local_irq_restore(flags);
+
+ return n;
+}
+
+/* FM PORT RX/TX/OH statistics */
+static DEVICE_ATTR(port_frame, S_IRUGO, show_fm_port_stats, NULL);
+static DEVICE_ATTR(port_discard_frame, S_IRUGO, show_fm_port_stats, NULL);
+static DEVICE_ATTR(port_dealloc_buf, S_IRUGO, show_fm_port_stats, NULL);
+static DEVICE_ATTR(port_enq_total, S_IRUGO, show_fm_port_stats, NULL);
+/* FM PORT TX/OH statistics */
+static DEVICE_ATTR(port_length_err, S_IRUGO, show_fm_port_stats, NULL);
+static DEVICE_ATTR(port_unsupprted_format, S_IRUGO, show_fm_port_stats, NULL);
+static DEVICE_ATTR(port_deq_total, S_IRUGO, show_fm_port_stats, NULL);
+static DEVICE_ATTR(port_deq_from_default, S_IRUGO, show_fm_port_stats, NULL);
+static DEVICE_ATTR(port_deq_confirm, S_IRUGO, show_fm_port_stats, NULL);
+/* FM PORT RX/OH statistics */
+static DEVICE_ATTR(port_rx_bad_frame, S_IRUGO, show_fm_port_stats, NULL);
+static DEVICE_ATTR(port_rx_large_frame, S_IRUGO, show_fm_port_stats, NULL);
+static DEVICE_ATTR(port_rx_out_of_buffers_discard, S_IRUGO,
+ show_fm_port_stats, NULL);
+static DEVICE_ATTR(port_rx_filter_frame, S_IRUGO, show_fm_port_stats, NULL);
+
+/* FM PORT TX statistics */
+static struct attribute *fm_tx_port_dev_stats_attributes[] = {
+ &dev_attr_port_frame.attr,
+ &dev_attr_port_discard_frame.attr,
+ &dev_attr_port_dealloc_buf.attr,
+ &dev_attr_port_enq_total.attr,
+ &dev_attr_port_length_err.attr,
+ &dev_attr_port_unsupprted_format.attr,
+ &dev_attr_port_deq_total.attr,
+ &dev_attr_port_deq_from_default.attr,
+ &dev_attr_port_deq_confirm.attr,
+ NULL
+};
+
+static const struct attribute_group fm_tx_port_dev_stats_attr_grp = {
+ .name = "statistics",
+ .attrs = fm_tx_port_dev_stats_attributes
+};
+
+/* FM PORT RX statistics */
+static struct attribute *fm_rx_port_dev_stats_attributes[] = {
+ &dev_attr_port_frame.attr,
+ &dev_attr_port_discard_frame.attr,
+ &dev_attr_port_dealloc_buf.attr,
+ &dev_attr_port_enq_total.attr,
+ &dev_attr_port_rx_bad_frame.attr,
+ &dev_attr_port_rx_large_frame.attr,
+ &dev_attr_port_rx_out_of_buffers_discard.attr,
+ &dev_attr_port_rx_filter_frame.attr,
+ NULL
+};
+
+static const struct attribute_group fm_rx_port_dev_stats_attr_grp = {
+ .name = "statistics",
+ .attrs = fm_rx_port_dev_stats_attributes
+};
+
+/* TODO: add particular OH ports statistics */
+static struct attribute *fm_oh_port_dev_stats_attributes[] = {
+ &dev_attr_port_frame.attr,
+ &dev_attr_port_discard_frame.attr,
+ &dev_attr_port_dealloc_buf.attr,
+ &dev_attr_port_enq_total.attr,
+ /*TX*/ &dev_attr_port_length_err.attr,
+ &dev_attr_port_unsupprted_format.attr,
+ &dev_attr_port_deq_total.attr,
+ &dev_attr_port_deq_from_default.attr,
+ &dev_attr_port_deq_confirm.attr,
+ /*RX*/ &dev_attr_port_rx_bad_frame.attr,
+ &dev_attr_port_rx_large_frame.attr,
+ &dev_attr_port_rx_out_of_buffers_discard.attr,
+ /*&dev_attr_port_rx_filter_frame.attr, */
+ NULL
+};
+
+static const struct attribute_group fm_oh_port_dev_stats_attr_grp = {
+ .name = "statistics",
+ .attrs = fm_oh_port_dev_stats_attributes
+};
+
+static ssize_t show_fm_port_regs(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned long flags;
+ unsigned n = 0;
+#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0))
+ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev =
+ (t_LnxWrpFmPortDev *) dev_get_drvdata(dev);
+#endif
+
+ if (attr == NULL || buf == NULL || dev == NULL)
+ return -EINVAL;
+
+#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0))
+ local_irq_save(flags);
+
+ if (!p_LnxWrpFmPortDev->h_Dev) {
+ n = snprintf(buf, PAGE_SIZE, "\tFM Port not configured...\n");
+ return n;
+ } else {
+ n = snprintf(buf, PAGE_SIZE,
+ "FM port driver registers dump.\n");
+ FM_PORT_DumpRegs(p_LnxWrpFmPortDev->h_Dev);
+ }
+
+ local_irq_restore(flags);
+
+ return n;
+#else
+
+ local_irq_save(flags);
+ n = snprintf(buf, PAGE_SIZE,
+ "Debug level is too low to dump registers!!!\n");
+ local_irq_restore(flags);
+
+ return n;
+#endif
+}
+
+static DEVICE_ATTR(fm_port_regs, 0x644, show_fm_port_regs, NULL);
+
+int fm_port_sysfs_create(struct device *dev)
+{
+ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev;
+
+ if (dev == NULL)
+ return -EINVAL;
+
+ p_LnxWrpFmPortDev = (t_LnxWrpFmPortDev *) dev_get_drvdata(dev);
+ if (WARN_ON(p_LnxWrpFmPortDev == NULL))
+ return -EINVAL;
+
+ /* store to remove them when module is disabled */
+ p_LnxWrpFmPortDev->dev_attr_regs = &dev_attr_fm_port_regs;
+
+ /* Registers dump entry - in future will be moved to debugfs */
+ if (device_create_file(dev, &dev_attr_fm_port_regs) != 0)
+ return -EIO;
+
+ /* FM Ports statistics */
+ switch (p_LnxWrpFmPortDev->settings.param.portType) {
+ case e_FM_PORT_TYPE_TX:
+ case e_FM_PORT_TYPE_TX_10G:
+ if (sysfs_create_group
+ (&dev->kobj, &fm_tx_port_dev_stats_attr_grp) != 0)
+ return -EIO;
+ break;
+ case e_FM_PORT_TYPE_RX:
+ case e_FM_PORT_TYPE_RX_10G:
+ if (sysfs_create_group
+ (&dev->kobj, &fm_rx_port_dev_stats_attr_grp) != 0)
+ return -EIO;
+ break;
+ /* TODO:FMD16 e_FM_PORT_TYPE_DUMMY is accutally a HC port.
+ * NetCommSw defined this way... no idea why!!! */
+ case e_FM_PORT_TYPE_DUMMY:
+ case e_FM_PORT_TYPE_OH_OFFLINE_PARSING:
+ if (sysfs_create_group
+ (&dev->kobj, &fm_oh_port_dev_stats_attr_grp) != 0)
+ return -EIO;
+ break;
+ default:
+ WARN(1, "FMD: failure at %s:%d/%s()!\n", __FILE__, __LINE__,
+ __func__);
+ return -EINVAL;
+ break;
+ };
+
+ return 0;
+}
+
+void fm_port_sysfs_destroy(struct device *dev)
+{
+ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev = NULL;
+
+ /* this function has never been tested !!! */
+
+ if (WARN_ON(dev == NULL))
+ return;
+
+ p_LnxWrpFmPortDev = (t_LnxWrpFmPortDev *) dev_get_drvdata(dev);
+ if (WARN_ON(p_LnxWrpFmPortDev == NULL))
+ return;
+
+ /* The name attribute will be freed also by these 2 functions? */
+ switch (p_LnxWrpFmPortDev->settings.param.portType) {
+ case e_FM_PORT_TYPE_TX:
+ case e_FM_PORT_TYPE_TX_10G:
+ sysfs_remove_group(&dev->kobj, &fm_tx_port_dev_stats_attr_grp);
+ break;
+ case e_FM_PORT_TYPE_RX:
+ case e_FM_PORT_TYPE_RX_10G:
+ sysfs_remove_group(&dev->kobj, &fm_rx_port_dev_stats_attr_grp);
+ break;
+ /* TODO:FMD16 e_FM_PORT_TYPE_DUMMY is accutally a HC port.
+ * NetCommSw defined this way... no idea why!!! */
+ case e_FM_PORT_TYPE_DUMMY:
+ case e_FM_PORT_TYPE_OH_OFFLINE_PARSING:
+ sysfs_remove_group(&dev->kobj, &fm_oh_port_dev_stats_attr_grp);
+ break;
+ default:
+ WARN(1, "FMD: failure at %s:%d/%s()!\n", __FILE__, __LINE__,
+ __func__);
+ break;
+ };
+
+ device_remove_file(dev, p_LnxWrpFmPortDev->dev_attr_regs);
+}
diff --git a/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_sysfs_fm_port.h b/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_sysfs_fm_port.h
new file mode 100644
index 0000000..03b3a03
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_sysfs_fm_port.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * 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 Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * 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 Freescale Semiconductor ``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 Freescale Semiconductor 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.
+ */
+
+/*
+ @File lnxwrp_sysfs_fm_port.h
+
+ @Description FM port sysfs functions.
+
+*/
+
+#ifndef LNXWRP_SYSFS_FM_PORT_H_
+#define LNXWRP_SYSFS_FM_PORT_H_
+
+#include "lnxwrp_sysfs.h"
+
+int fm_port_sysfs_create(struct device *dev);
+void fm_port_sysfs_destroy(struct device *dev);
+
+#endif /* LNXWRP_SYSFS_FM_PORT_H_ */
diff --git a/drivers/net/ethernet/freescale/fman/src/xx/Makefile b/drivers/net/ethernet/freescale/fman/src/xx/Makefile
new file mode 100644
index 0000000..1e0db57
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/src/xx/Makefile
@@ -0,0 +1,12 @@
+#
+# Makefile for the Freescale Ethernet controllers
+#
+EXTRA_CFLAGS += -DVERSION=\"\"
+#
+#Include netcomm SW specific definitions
+include $(srctree)/drivers/net/ethernet/freescale/fman/ncsw_config.mk
+
+obj-y += fsl-ncsw-xx.o
+
+fsl-ncsw-xx-objs := xx_linux.o udivdi3.o stdlib.o \
+ module_strings.o
diff --git a/drivers/net/ethernet/freescale/fman/src/xx/module_strings.c b/drivers/net/ethernet/freescale/fman/src/xx/module_strings.c
new file mode 100644
index 0000000..98c64fb
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/src/xx/module_strings.c
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2012 Freescale Semiconductor Inc.
+ *
+ * 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 Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * 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 Freescale Semiconductor ``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 Freescale Semiconductor 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.
+ */
+
+/* Module names for debug messages */
+const char *moduleStrings[] =
+{
+ "", /* MODULE_UNKNOWN */
+ "FM", /* MODULE_FM */
+ "FM-MURAM", /* MODULE_FM_MURAM */
+ "FM-PCD", /* MODULE_FM_PCD */
+ "FM-RTC", /* MODULE_FM_RTC */
+ "FM-MAC", /* MODULE_FM_MAC */
+ "FM-Port", /* MODULE_FM_PORT */
+ "MM", /* MODULE_MM */
+ "FM-SP" /* MODULE_FM_SP */
+};
diff --git a/drivers/net/ethernet/freescale/fman/src/xx/stdlib.c b/drivers/net/ethernet/freescale/fman/src/xx/stdlib.c
new file mode 100644
index 0000000..851bcf1
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/src/xx/stdlib.c
@@ -0,0 +1,264 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * 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 Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * 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 Freescale Semiconductor ``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 Freescale Semiconductor 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.
+ */
+
+/*------------------------------------------------------*/
+/* */
+/* File: stdlib.c */
+/* */
+/* Description: */
+/* Standard library routines (externals) */
+/* */
+/* Modifications: */
+/* ============== */
+/* */
+/*------------------------------------------------------*/
+#include "stdlib_ext.h"
+#include "stdarg_ext.h"
+#include "ctype_ext.h"
+#include "string_ext.h"
+#include "std_ext.h"
+#include "xx_ext.h"
+
+
+#ifdef MODULE
+/**
+ * strtoul - convert a string to an uint32_t
+ * @cp: The start of the string
+ * @endp: A pointer to the end of the parsed string will be placed here
+ * @base: The number base to use
+ */
+uint32_t strtoul(const char *cp,char **endp,uint32_t base)
+{
+ uint32_t result = 0,value;
+
+ if (!base) {
+ base = 10;
+ if (*cp == '0') {
+ base = 8;
+ cp++;
+ if ((*cp == 'x') && isxdigit(cp[1])) {
+ cp++;
+ base = 16;
+ }
+ }
+ }
+ while (isxdigit(*cp) &&
+ (value = (uint32_t)(isdigit(*cp) ? *cp-'0' : toupper((uint8_t)(*cp))-'A'+10)) < base) {
+ result = result*base + value;
+ cp++;
+ }
+ if (endp)
+ *endp = (char *)cp;
+ return result;
+}
+
+/**
+ * strtol - convert a string to a int32_t
+ * @cp: The start of the string
+ * @endp: A pointer to the end of the parsed string will be placed here
+ * @base: The number base to use
+ */
+long strtol(const char *cp,char **endp,uint32_t base)
+{
+ if(*cp=='-')
+ return (long)(-strtoul(cp+1,endp,base));
+ return (long)strtoul(cp,endp,base);
+}
+
+/**
+ * strtoull - convert a string to an uint64_t
+ * @cp: The start of the string
+ * @endp: A pointer to the end of the parsed string will be placed here
+ * @base: The number base to use
+ */
+uint64_t strtoull(const char *cp,char **endp,uint32_t base)
+{
+ uint64_t result = 0,value;
+
+ if (!base) {
+ base = 10;
+ if (*cp == '0') {
+ base = 8;
+ cp++;
+ if ((*cp == 'x') && isxdigit(cp[1])) {
+ cp++;
+ base = 16;
+ }
+ }
+ }
+ while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp-'0' : (islower(*cp)
+ ? toupper((uint8_t)(*cp)) : *cp)-'A'+10) < base) {
+ result = result*base + value;
+ cp++;
+ }
+ if (endp)
+ *endp = (char *)cp;
+ return result;
+}
+
+/**
+ * strtoll - convert a string to a int64
+ * @cp: The start of the string
+ * @endp: A pointer to the end of the parsed string will be placed here
+ * @base: The number base to use
+ */
+long long strtoll(const char *cp,char **endp,uint32_t base)
+{
+ if(*cp=='-')
+ return (long long)(-strtoull(cp+1,endp,base));
+ return (long long)(strtoull(cp,endp,base));
+}
+
+/**
+ * atoi - convert a string to a int
+ * @s: The start of the string
+ */
+int atoi(const char *s)
+{
+ int i=0;
+ const char **tmp_s = &s;
+
+ while (isdigit(**tmp_s))
+ i = i*10 + *((*tmp_s)++) - '0';
+ return i;
+}
+
+/**
+ * strlen - Find the length of a string
+ * @s: The string to be sized
+ */
+size_t strlen(const char * s)
+{
+ const char *sc;
+
+ for (sc = s; *sc != '\0'; ++sc)
+ /* nothing */;
+
+ return sc - s;
+}
+
+/**
+ * strnlen - Find the length of a length-limited string
+ * @s: The string to be sized
+ * @count: The maximum number of bytes to search
+ */
+size_t strnlen(const char * s, size_t count)
+{
+ const char *sc;
+
+ for (sc = s; count-- && *sc != '\0'; ++sc)
+ /* nothing */;
+
+ return sc - s;
+}
+
+/**
+ * strcpy - Copy a %NUL terminated string
+ * @dest: Where to copy the string to
+ * @src: Where to copy the string from
+ */
+char * strcpy(char * dest,const char *src)
+{
+ char *tmp = dest;
+
+ while ((*dest++ = *src++) != '\0')
+ /* nothing */;
+
+ return tmp;
+}
+#endif /* MODULE */
+
+/**
+ * strtok - Split a string into tokens
+ * @s: The string to be searched
+ * @ct: The characters to search for
+ *
+ * WARNING: strtok is deprecated, use strsep instead.
+ */
+char *___strtok;
+
+char * strtok(char * s,const char * ct)
+{
+ char *sbegin, *send;
+
+ sbegin = s ? s : ___strtok;
+ if (!sbegin) {
+ return NULL;
+ }
+ sbegin += strspn(sbegin,ct);
+ if (*sbegin == '\0') {
+ ___strtok = NULL;
+ return( NULL );
+ }
+ send = strpbrk( sbegin, ct);
+ if (send && *send != '\0')
+ *send++ = '\0';
+ ___strtok = send;
+ return (sbegin);
+}
+
+
+#ifdef MODULE
+/**
+ * strncpy - Copy a length-limited, %NUL-terminated string
+ * @dest: Where to copy the string to
+ * @src: Where to copy the string from
+ * @count: The maximum number of bytes to copy
+ *
+ * Note that unlike userspace strncpy, this does not %NUL-pad the buffer.
+ * However, the result is not %NUL-terminated if the source exceeds
+ * @count bytes.
+ */
+char * strncpy(char * dest,const char *src,size_t count)
+{
+ char *tmp = dest;
+
+ while (count-- && (*dest++ = *src++) != '\0')
+ /* nothing */;
+
+ return tmp;
+}
+
+/**
+ * vsprintf - Format a string and place it in a buffer
+ * @buf: The buffer to place the result into
+ * @fmt: The format string to use
+ * @args: Arguments for the format string
+ *
+ * Call this function if you are already dealing with a va_list.
+ * You probably want sprintf instead.
+ */
+int vsprintf(char *buf, const char *fmt, va_list args)
+{
+ return vsnprintf(buf, INT32_MAX, fmt, args);
+}
+#endif /* MODULE */
diff --git a/drivers/net/ethernet/freescale/fman/src/xx/udivdi3.c b/drivers/net/ethernet/freescale/fman/src/xx/udivdi3.c
new file mode 100644
index 0000000..419e27e
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/src/xx/udivdi3.c
@@ -0,0 +1,132 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * 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 Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * 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 Freescale Semiconductor ``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 Freescale Semiconductor 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 <linux/version.h>
+
+#if defined(CONFIG_MODVERSIONS) && !defined(MODVERSIONS)
+#define MODVERSIONS
+#endif
+#ifdef MODVERSIONS
+#include <config/modversions.h>
+#endif /* MODVERSIONS */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <asm/div64.h>
+
+
+#define BITS_PER_UNIT 8
+#define SI_TYPE_SIZE (sizeof (SItype) * BITS_PER_UNIT)
+
+
+typedef unsigned int UQItype __attribute__ ((mode (QI)));
+typedef int SItype __attribute__ ((mode (SI)));
+typedef unsigned int USItype __attribute__ ((mode (SI)));
+typedef int DItype __attribute__ ((mode (DI)));
+typedef int word_type __attribute__ ((mode (__word__)));
+typedef unsigned int UDItype __attribute__ ((mode (DI)));
+
+struct DIstruct {SItype low, high;};
+
+typedef union
+{
+ struct DIstruct s;
+ DItype ll;
+} DIunion;
+
+
+/* bit divisor, dividend and result. dynamic precision */
+static __inline__ uint64_t _div64_64(uint64_t dividend, uint64_t divisor)
+{
+ uint32_t d = divisor;
+
+ if (divisor > 0xffffffffULL)
+ {
+ unsigned int shift = fls(divisor >> 32);
+
+ d = divisor >> shift;
+ dividend >>= shift;
+ }
+
+ /* avoid 64 bit division if possible */
+ if (dividend >> 32)
+ do_div(dividend, d);
+ else
+ dividend = (uint32_t) dividend / d;
+
+ return dividend;
+}
+
+UDItype __udivdi3 (UDItype n, UDItype d)
+{
+ return _div64_64(n, d);
+}
+
+DItype __divdi3 (DItype n, DItype d)
+{
+ DItype sign = 1;
+ if (n<0)
+ {
+ sign *= -1;
+ n *= -1;
+ }
+ if (d<0)
+ {
+ sign *= -1;
+ d *= -1;
+ }
+ return sign*_div64_64((UDItype)n, (UDItype)d);
+}
+
+UDItype __umoddi3 (UDItype n, UDItype d)
+{
+ return n-(_div64_64(n, d)*d);
+}
+
+#ifdef MODULE
+word_type __ucmpdi2 (DItype a, DItype b)
+{
+ DIunion au, bu;
+
+ au.ll = a, bu.ll = b;
+
+ if ((USItype) au.s.high < (USItype) bu.s.high)
+ return 0;
+ else if ((USItype) au.s.high > (USItype) bu.s.high)
+ return 2;
+ if ((USItype) au.s.low < (USItype) bu.s.low)
+ return 0;
+ else if ((USItype) au.s.low > (USItype) bu.s.low)
+ return 2;
+ return 1;
+}
+#endif /* MODULE */
diff --git a/drivers/net/ethernet/freescale/fman/src/xx/xx_linux.c b/drivers/net/ethernet/freescale/fman/src/xx/xx_linux.c
new file mode 100644
index 0000000..4b5c7863
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/src/xx/xx_linux.c
@@ -0,0 +1,901 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * 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 Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * 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 Freescale Semiconductor ``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 Freescale Semiconductor 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.
+ */
+
+/**************************************************************************//**
+ @File xx_linux.c
+
+ @Description XX routines implementation for Linux.
+*//***************************************************************************/
+#include <linux/version.h>
+
+#if defined(CONFIG_MODVERSIONS) && !defined(MODVERSIONS)
+#define MODVERSIONS
+#endif
+#ifdef MODVERSIONS
+#include <config/modversions.h>
+#endif /* MODVERSIONS */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/ptrace.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/fs.h>
+#include <linux/vmalloc.h>
+#include <linux/init.h>
+#include <linux/timer.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <linux/proc_fs.h>
+#include <linux/smp.h>
+#include <linux/of.h>
+
+#include <linux/workqueue.h>
+
+#ifdef BIGPHYSAREA_ENABLE
+#include <linux/bigphysarea.h>
+#endif /* BIGPHYSAREA_ENABLE */
+
+#include <sysdev/fsl_soc.h>
+#include <asm/pgtable.h>
+#include <asm/irq.h>
+#include <asm/bitops.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <asm/atomic.h>
+#include <asm/string.h>
+#include <asm/byteorder.h>
+#include <asm/page.h>
+
+#include "error_ext.h"
+#include "std_ext.h"
+#include "list_ext.h"
+#include "mm_ext.h"
+#include "sys_io_ext.h"
+#include "xx.h"
+
+
+#define __ERR_MODULE__ MODULE_UNKNOWN
+
+#ifdef BIGPHYSAREA_ENABLE
+#define MAX_ALLOCATION_SIZE 128 * 1024 /* Maximum size allocated with kmalloc is 128K */
+
+
+/* TODO: large allocations => use big phys area */
+/******************************************************************************
+ * routine: get_nr_pages
+ *
+ * description:
+ * calculates the number of memory pages for a given size (in bytes)
+ *
+ * arguments:
+ * size - the number of bytes
+ *
+ * return code:
+ * The number of pages
+ *
+ *****************************************************************************/
+static __inline__ uint32_t get_nr_pages (uint32_t size)
+{
+ return (uint32_t)((size >> PAGE_SHIFT) + (size & PAGE_SHIFT ? 1 : 0));
+}
+
+static bool in_big_phys_area (uint32_t addr)
+{
+ uint32_t base, size;
+
+ bigphysarea_get_details (&base, &size);
+ return ((addr >= base) && (addr < base + size));
+}
+#endif /* BIGPHYSAREA_ENABLE */
+
+void * xx_Malloc(uint32_t n)
+{
+ void *a;
+ uint32_t flags;
+
+ flags = XX_DisableAllIntr();
+#ifdef BIGPHYSAREA_ENABLE
+ if (n >= MAX_ALLOCATION_SIZE)
+ a = (void*)bigphysarea_alloc_pages(get_nr_pages(n), 0, GFP_ATOMIC);
+ else
+#endif /* BIGPHYSAREA_ENABLE */
+ a = (void *)kmalloc((uint32_t)n, GFP_ATOMIC);
+ if (!a)
+ XX_Print("No memory for XX_Malloc\n");
+ XX_RestoreAllIntr(flags);
+
+ return a;
+}
+
+void xx_Free(void *p)
+{
+#ifdef BIGPHYSAREA_ENABLE
+ if (in_big_phys_area ((uint32_t)p))
+ bigphysarea_free_pages(p);
+ else
+#endif /* BIGPHYSAREA_ENABLE */
+ kfree(p);
+}
+
+void XX_Exit(int status)
+{
+ WARN(1, "\n\nFMD: fatal error, driver can't go on!!!\n\n");
+}
+
+#define BUF_SIZE 512
+void XX_Print(char *str, ...)
+{
+ va_list args;
+#ifdef CONFIG_SMP
+ char buf[BUF_SIZE];
+#endif /* CONFIG_SMP */
+
+ va_start(args, str);
+#ifdef CONFIG_SMP
+ if (vsnprintf (buf, BUF_SIZE, str, args) >= BUF_SIZE)
+ printk(KERN_WARNING "Illegal string to print!\n more than %d characters.\n\tString was not printed completelly.\n", BUF_SIZE);
+ printk (KERN_CRIT "cpu%d: %s",raw_smp_processor_id(), buf);
+#else
+ vprintk(str, args);
+#endif /* CONFIG_SMP */
+ va_end(args);
+}
+
+void XX_Fprint(void *file, char *str, ...)
+{
+ va_list args;
+#ifdef CONFIG_SMP
+ char buf[BUF_SIZE];
+#endif /* CONFIG_SMP */
+
+ va_start(args, str);
+#ifdef CONFIG_SMP
+ if (vsnprintf (buf, BUF_SIZE, str, args) >= BUF_SIZE)
+ printk(KERN_WARNING "Illegal string to print!\n more than %d characters.\n\tString was not printed completelly.\n", BUF_SIZE);
+ printk (KERN_CRIT "cpu%d: %s", raw_smp_processor_id(), buf);
+#else
+ vprintk(str, args);
+#endif /* CONFIG_SMP */
+ va_end(args);
+}
+
+#ifdef DEBUG_XX_MALLOC
+typedef void (*t_ffn)(void *);
+typedef struct {
+ t_ffn f_free;
+ void *mem;
+ char *fname;
+ int fline;
+ uint32_t size;
+ t_List node;
+} t_MemDebug;
+#define MEMDBG_OBJECT(p_List) LIST_OBJECT(p_List, t_MemDebug, node)
+
+LIST(memDbgLst);
+
+
+void * XX_MallocDebug(uint32_t size, char *fname, int line)
+{
+ void *mem;
+ t_MemDebug *p_MemDbg;
+
+ p_MemDbg = (t_MemDebug *)xx_Malloc(sizeof(t_MemDebug));
+ if (p_MemDbg == NULL)
+ return NULL;
+
+ mem = xx_Malloc(size);
+ if (mem == NULL)
+ {
+ XX_Free(p_MemDbg);
+ return NULL;
+ }
+
+ INIT_LIST(&p_MemDbg->node);
+ p_MemDbg->f_free = xx_Free;
+ p_MemDbg->mem = mem;
+ p_MemDbg->fname = fname;
+ p_MemDbg->fline = line;
+ p_MemDbg->size = size+sizeof(t_MemDebug);
+ LIST_AddToTail(&p_MemDbg->node, &memDbgLst);
+
+ return mem;
+}
+
+void * XX_MallocSmartDebug(uint32_t size,
+ int memPartitionId,
+ uint32_t align,
+ char *fname,
+ int line)
+{
+ void *mem;
+ t_MemDebug *p_MemDbg;
+
+ p_MemDbg = (t_MemDebug *)XX_Malloc(sizeof(t_MemDebug));
+ if (p_MemDbg == NULL)
+ return NULL;
+
+ mem = xx_MallocSmart((uint32_t)size, memPartitionId, align);
+ if (mem == NULL)
+ {
+ XX_Free(p_MemDbg);
+ return NULL;
+ }
+
+ INIT_LIST(&p_MemDbg->node);
+ p_MemDbg->f_free = xx_FreeSmart;
+ p_MemDbg->mem = mem;
+ p_MemDbg->fname = fname;
+ p_MemDbg->fline = line;
+ p_MemDbg->size = size+sizeof(t_MemDebug);
+ LIST_AddToTail(&p_MemDbg->node, &memDbgLst);
+
+ return mem;
+}
+
+static void debug_free(void *mem)
+{
+ t_List *p_MemDbgLh = NULL;
+ t_MemDebug *p_MemDbg;
+ bool found = FALSE;
+
+ if (LIST_IsEmpty(&memDbgLst))
+ {
+ REPORT_ERROR(MAJOR, E_ALREADY_FREE, ("Unbalanced free (0x%08x)", mem));
+ return;
+ }
+
+ LIST_FOR_EACH(p_MemDbgLh, &memDbgLst)
+ {
+ p_MemDbg = MEMDBG_OBJECT(p_MemDbgLh);
+ if (p_MemDbg->mem == mem)
+ {
+ found = TRUE;
+ break;
+ }
+ }
+
+ if (!found)
+ {
+ REPORT_ERROR(MAJOR, E_NOT_FOUND,
+ ("Attempt to free unallocated address (0x%08x)",mem));
+ dump_stack();
+ return;
+ }
+
+ LIST_Del(p_MemDbgLh);
+ p_MemDbg->f_free(mem);
+ p_MemDbg->f_free(p_MemDbg);
+}
+
+void XX_FreeSmart(void *p)
+{
+ debug_free(p);
+}
+
+
+void XX_Free(void *p)
+{
+ debug_free(p);
+}
+
+#else /* not DEBUG_XX_MALLOC */
+void * XX_Malloc(uint32_t size)
+{
+ return xx_Malloc(size);
+}
+
+void * XX_MallocSmart(uint32_t size, int memPartitionId, uint32_t alignment)
+{
+ return xx_MallocSmart(size,memPartitionId, alignment);
+}
+
+void XX_FreeSmart(void *p)
+{
+ xx_FreeSmart(p);
+}
+
+
+void XX_Free(void *p)
+{
+ xx_Free(p);
+}
+#endif /* not DEBUG_XX_MALLOC */
+
+
+#if (defined(REPORT_EVENTS) && (REPORT_EVENTS > 0))
+void XX_EventById(uint32_t event, t_Handle appId, uint16_t flags, char *msg)
+{
+ e_Event eventCode = (e_Event)event;
+
+ UNUSED(eventCode);
+ UNUSED(appId);
+ UNUSED(flags);
+ UNUSED(msg);
+}
+#endif /* (defined(REPORT_EVENTS) && ... */
+
+
+uint32_t XX_DisableAllIntr(void)
+{
+ unsigned long flags;
+
+ local_irq_save(flags);
+
+ return (uint32_t)flags;
+}
+
+void XX_RestoreAllIntr(uint32_t flags)
+{
+ local_irq_restore((unsigned long)flags);
+}
+
+t_Error XX_Call( uint32_t qid, t_Error (* f)(t_Handle), t_Handle id, t_Handle appId, uint16_t flags )
+{
+ UNUSED(qid);
+ UNUSED(appId);
+ UNUSED(flags);
+
+ return f(id);
+}
+
+int XX_IsICacheEnable(void)
+{
+ return TRUE;
+}
+
+int XX_IsDCacheEnable(void)
+{
+ return TRUE;
+}
+
+
+typedef struct {
+ t_Isr *f_Isr;
+ t_Handle handle;
+} t_InterruptHandler;
+
+
+t_Handle interruptHandlers[0x00010000];
+
+static irqreturn_t LinuxInterruptHandler (int irq, void *dev_id)
+{
+ t_InterruptHandler *p_IntrHndl = (t_InterruptHandler *)dev_id;
+ p_IntrHndl->f_Isr(p_IntrHndl->handle);
+ return IRQ_HANDLED;
+}
+
+t_Error XX_SetIntr(int irq, t_Isr *f_Isr, t_Handle handle)
+{
+ const char *device;
+ t_InterruptHandler *p_IntrHndl;
+
+ device = GetDeviceName(irq);
+ if (device == NULL)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Interrupt source - %d", irq));
+
+ p_IntrHndl = (t_InterruptHandler *)XX_Malloc(sizeof(t_InterruptHandler));
+ if (p_IntrHndl == NULL)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, NO_MSG);
+ p_IntrHndl->f_Isr = f_Isr;
+ p_IntrHndl->handle = handle;
+ interruptHandlers[irq] = p_IntrHndl;
+
+ if (request_irq(GetDeviceIrqNum(irq), LinuxInterruptHandler, 0, device, p_IntrHndl) < 0)
+ RETURN_ERROR(MAJOR, E_BUSY, ("Can't get IRQ %s\n", device));
+ disable_irq(GetDeviceIrqNum(irq));
+
+ return E_OK;
+}
+
+t_Error XX_FreeIntr(int irq)
+{
+ t_InterruptHandler *p_IntrHndl = interruptHandlers[irq];
+ free_irq(GetDeviceIrqNum(irq), p_IntrHndl);
+ XX_Free(p_IntrHndl);
+ interruptHandlers[irq] = 0;
+ return E_OK;
+}
+
+t_Error XX_EnableIntr(int irq)
+{
+ enable_irq(GetDeviceIrqNum(irq));
+ return E_OK;
+}
+
+t_Error XX_DisableIntr(int irq)
+{
+ disable_irq(GetDeviceIrqNum(irq));
+ return E_OK;
+}
+
+
+/*****************************************************************************/
+/* Tasklet Service Routines */
+/*****************************************************************************/
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
+typedef struct
+{
+ t_Handle h_Data;
+ void (*f_Callback) (void *);
+ struct delayed_work dwork;
+} t_Tasklet;
+
+static void GenericTaskletCallback(struct work_struct *p_Work)
+{
+ t_Tasklet *p_Task = container_of(p_Work, t_Tasklet, dwork.work);
+
+ p_Task->f_Callback(p_Task->h_Data);
+}
+#endif /* LINUX_VERSION_CODE */
+
+
+t_TaskletHandle XX_InitTasklet (void (*routine)(void *), void *data)
+{
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
+ struct work_struct *p_Task;
+ p_Task = (struct work_struct *)XX_Malloc(sizeof(struct work_struct));
+ INIT_WORK(p_Task, routine, data);
+#else
+ t_Tasklet *p_Task = (t_Tasklet *)XX_Malloc(sizeof(t_Tasklet));
+ p_Task->h_Data = data;
+ p_Task->f_Callback = routine;
+ INIT_DELAYED_WORK(&p_Task->dwork, GenericTaskletCallback);
+#endif /* LINUX_VERSION_CODE */
+
+ return (t_TaskletHandle)p_Task;
+}
+
+
+void XX_FreeTasklet (t_TaskletHandle h_Tasklet)
+{
+ if (h_Tasklet)
+ XX_Free(h_Tasklet);
+}
+
+int XX_ScheduleTask(t_TaskletHandle h_Tasklet, int immediate)
+{
+ int ans;
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
+ if (immediate)
+ ans = schedule_work(h_Tasklet);
+ else
+ ans = schedule_delayed_work(h_Tasklet, 1);
+#else
+ if (immediate)
+ ans = schedule_delayed_work(&((t_Tasklet *)h_Tasklet)->dwork, 0);
+ else
+ ans = schedule_delayed_work(&((t_Tasklet *)h_Tasklet)->dwork, HZ);
+#endif /* LINUX_VERSION_CODE */
+
+ return ans;
+}
+
+void XX_FlushScheduledTasks(void)
+{
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+ flush_scheduled_tasks();
+#else
+ flush_scheduled_work();
+#endif /* LINUX_VERSION_CODE */
+}
+
+int XX_TaskletIsQueued(t_TaskletHandle h_Tasklet)
+{
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
+ return (int)(((struct work_struct *)h_Tasklet)->pending);
+#else
+ return (int)delayed_work_pending(&((t_Tasklet *)h_Tasklet)->dwork);
+#endif /* LINUX_VERSION_CODE */
+}
+
+void XX_SetTaskletData(t_TaskletHandle h_Tasklet, t_Handle data)
+{
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+ ((struct tq_struct *)h_Tasklet)->data = data;
+#elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
+ ((struct work_struct *)h_Tasklet)->data = data;
+#else
+ ((t_Tasklet *)h_Tasklet)->h_Data = data;
+#endif /* LINUX_VERSION_CODE */
+}
+
+t_Handle XX_GetTaskletData(t_TaskletHandle h_Tasklet)
+{
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
+ return (t_Handle)(((struct work_struct *)h_Tasklet)->data);
+#else
+ return ((t_Tasklet *)h_Tasklet)->h_Data;
+#endif /* LINUX_VERSION_CODE */
+}
+
+
+/*****************************************************************************/
+/* Spinlock Service Routines */
+/*****************************************************************************/
+
+t_Handle XX_InitSpinlock(void)
+{
+ spinlock_t *p_Spinlock = (spinlock_t *)XX_Malloc(sizeof(spinlock_t));
+ if (!p_Spinlock)
+ return NULL;
+
+ spin_lock_init(p_Spinlock);
+
+ return (t_Handle)p_Spinlock;
+}
+
+void XX_FreeSpinlock(t_Handle h_Spinlock)
+{
+ if (h_Spinlock)
+ XX_Free(h_Spinlock);
+}
+
+void XX_LockSpinlock(t_Handle h_Spinlock)
+{
+ spin_lock((spinlock_t *)h_Spinlock);
+}
+
+void XX_UnlockSpinlock(t_Handle h_Spinlock)
+{
+ spin_unlock((spinlock_t *)h_Spinlock);
+}
+
+uint32_t XX_LockIntrSpinlock(t_Handle h_Spinlock)
+{
+ unsigned long intrFlags;
+ spin_lock_irqsave((spinlock_t *)h_Spinlock, intrFlags);
+ return intrFlags;
+}
+
+void XX_UnlockIntrSpinlock(t_Handle h_Spinlock, uint32_t intrFlags)
+{
+ spin_unlock_irqrestore((spinlock_t *)h_Spinlock, (unsigned long)intrFlags);
+}
+
+
+/*****************************************************************************/
+/* Timers Service Routines */
+/*****************************************************************************/
+/* The time now is in mili sec. resolution */
+uint32_t XX_CurrentTime(void)
+{
+ return (jiffies*1000)/HZ;
+}
+
+
+t_Handle XX_CreateTimer(void)
+{
+ struct timer_list *p_Timer = (struct timer_list *)XX_Malloc(sizeof(struct timer_list));
+ if (p_Timer)
+ {
+ memset(p_Timer, 0, sizeof(struct timer_list));
+ init_timer(p_Timer);
+ }
+ return (t_Handle)p_Timer;
+}
+
+void XX_FreeTimer(t_Handle h_Timer)
+{
+ if (h_Timer)
+ XX_Free(h_Timer);
+}
+
+void XX_StartTimer(t_Handle h_Timer,
+ uint32_t msecs,
+ bool periodic,
+ void (*f_TimerExpired)(t_Handle),
+ t_Handle h_Arg)
+{
+ int tmp_jiffies = (msecs*HZ)/1000;
+ struct timer_list *p_Timer = (struct timer_list *)h_Timer;
+
+ SANITY_CHECK_RETURN((periodic == FALSE), E_NOT_SUPPORTED);
+
+ p_Timer->function = (void (*)(unsigned long))f_TimerExpired;
+ p_Timer->data = (unsigned long)h_Arg;
+ if ((msecs*HZ)%1000)
+ tmp_jiffies++;
+ p_Timer->expires = (jiffies + tmp_jiffies);
+
+ add_timer((struct timer_list *)h_Timer);
+}
+
+void XX_SetTimerData(t_Handle h_Timer, t_Handle data)
+{
+ struct timer_list *p_Timer = (struct timer_list *)h_Timer;
+
+ p_Timer->data = (unsigned long)data;
+}
+
+t_Handle XX_GetTimerData(t_Handle h_Timer)
+{
+ struct timer_list *p_Timer = (struct timer_list *)h_Timer;
+
+ return (t_Handle)p_Timer->data;
+}
+
+uint32_t XX_GetExpirationTime(t_Handle h_Timer)
+{
+ struct timer_list *p_Timer = (struct timer_list *)h_Timer;
+
+ return (uint32_t)p_Timer->expires;
+}
+
+void XX_StopTimer(t_Handle h_Timer)
+{
+ del_timer((struct timer_list *)h_Timer);
+}
+
+void XX_ModTimer(t_Handle h_Timer, uint32_t msecs)
+{
+ int tmp_jiffies = (msecs*HZ)/1000;
+
+ if ((msecs*HZ)%1000)
+ tmp_jiffies++;
+ mod_timer((struct timer_list *)h_Timer, jiffies + tmp_jiffies);
+}
+
+int XX_TimerIsActive(t_Handle h_Timer)
+{
+ return timer_pending((struct timer_list *)h_Timer);
+}
+
+uint32_t XX_Sleep(uint32_t msecs)
+{
+ int tmp_jiffies = (msecs*HZ)/1000;
+
+ if ((msecs*HZ)%1000)
+ tmp_jiffies++;
+ return schedule_timeout(tmp_jiffies);
+}
+
+/*BEWARE!!!!! UDelay routine is BUSY WAITTING!!!!!*/
+void XX_UDelay(uint32_t usecs)
+{
+ udelay(usecs);
+}
+
+/* TODO: verify that these are correct */
+#define MSG_BODY_SIZE 512
+typedef t_Error (t_MsgHandler) (t_Handle h_Mod, uint32_t msgId, uint8_t msgBody[MSG_BODY_SIZE]);
+typedef void (t_MsgCompletionCB) (t_Handle h_Arg, uint8_t msgBody[MSG_BODY_SIZE]);
+t_Error XX_SendMessage(char *p_DestAddr,
+ uint32_t msgId,
+ uint8_t msgBody[MSG_BODY_SIZE],
+ t_MsgCompletionCB *f_CompletionCB,
+ t_Handle h_CBArg);
+
+typedef struct {
+ char *p_Addr;
+ t_MsgHandler *f_MsgHandlerCB;
+ t_Handle h_Mod;
+ t_List node;
+} t_MsgHndlr;
+#define MSG_HNDLR_OBJECT(ptr) LIST_OBJECT(ptr, t_MsgHndlr, node)
+
+LIST(msgHndlrList);
+
+static void EnqueueMsgHndlr(t_MsgHndlr *p_MsgHndlr)
+{
+ uint32_t intFlags;
+
+ intFlags = XX_DisableAllIntr();
+ LIST_AddToTail(&p_MsgHndlr->node, &msgHndlrList);
+ XX_RestoreAllIntr(intFlags);
+}
+/* TODO: add this for multi-platform support
+static t_MsgHndlr * DequeueMsgHndlr(void)
+{
+ t_MsgHndlr *p_MsgHndlr = NULL;
+ uint32_t intFlags;
+
+ intFlags = XX_DisableAllIntr();
+ if (!LIST_IsEmpty(&msgHndlrList))
+ {
+ p_MsgHndlr = MSG_HNDLR_OBJECT(msgHndlrList.p_Next);
+ LIST_DelAndInit(&p_MsgHndlr->node);
+ }
+ XX_RestoreAllIntr(intFlags);
+
+ return p_MsgHndlr;
+}
+*/
+static t_MsgHndlr * FindMsgHndlr(char *p_Addr)
+{
+ t_MsgHndlr *p_MsgHndlr;
+ t_List *p_Pos;
+
+ LIST_FOR_EACH(p_Pos, &msgHndlrList)
+ {
+ p_MsgHndlr = MSG_HNDLR_OBJECT(p_Pos);
+ if (strstr(p_MsgHndlr->p_Addr, p_Addr))
+ return p_MsgHndlr;
+ }
+
+ return NULL;
+}
+
+t_Error XX_RegisterMessageHandler (char *p_Addr, t_MsgHandler *f_MsgHandlerCB, t_Handle h_Mod)
+{
+ t_MsgHndlr *p_MsgHndlr;
+ uint32_t len;
+
+ p_MsgHndlr = (t_MsgHndlr*)XX_Malloc(sizeof(t_MsgHndlr));
+ if (!p_MsgHndlr)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("message handler object!!!"));
+ memset(p_MsgHndlr, 0, sizeof(t_MsgHndlr));
+
+ len = strlen(p_Addr);
+ p_MsgHndlr->p_Addr = (char*)XX_Malloc(len+1);
+ strncpy(p_MsgHndlr->p_Addr,p_Addr, (uint32_t)(len+1));
+
+ p_MsgHndlr->f_MsgHandlerCB = f_MsgHandlerCB;
+ p_MsgHndlr->h_Mod = h_Mod;
+ INIT_LIST(&p_MsgHndlr->node);
+ EnqueueMsgHndlr(p_MsgHndlr);
+
+ return E_OK;
+}
+
+t_Error XX_UnregisterMessageHandler (char *p_Addr)
+{
+ t_MsgHndlr *p_MsgHndlr = FindMsgHndlr(p_Addr);
+ if (!p_MsgHndlr)
+ RETURN_ERROR(MINOR, E_NO_DEVICE, ("message handler not found in list!!!"));
+
+ LIST_Del(&p_MsgHndlr->node);
+ XX_Free(p_MsgHndlr->p_Addr);
+ XX_Free(p_MsgHndlr);
+
+ return E_OK;
+}
+
+t_Error XX_SendMessage(char *p_DestAddr,
+ uint32_t msgId,
+ uint8_t msgBody[MSG_BODY_SIZE],
+ t_MsgCompletionCB *f_CompletionCB,
+ t_Handle h_CBArg)
+{
+ t_Error ans;
+ t_MsgHndlr *p_MsgHndlr = FindMsgHndlr(p_DestAddr);
+ if (!p_MsgHndlr)
+ RETURN_ERROR(MINOR, E_NO_DEVICE, ("message handler not found in list!!!"));
+
+ ans = p_MsgHndlr->f_MsgHandlerCB(p_MsgHndlr->h_Mod, msgId, msgBody);
+
+ if (f_CompletionCB)
+ f_CompletionCB(h_CBArg, msgBody);
+
+ return ans;
+}
+
+t_Error XX_IpcRegisterMsgHandler(char addr[XX_IPC_MAX_ADDR_NAME_LENGTH],
+ t_IpcMsgHandler *f_MsgHandler,
+ t_Handle h_Module,
+ uint32_t replyLength)
+{
+ UNUSED(addr);UNUSED(f_MsgHandler);UNUSED(h_Module);UNUSED(replyLength);
+ return E_OK;
+}
+
+t_Error XX_IpcUnregisterMsgHandler(char addr[XX_IPC_MAX_ADDR_NAME_LENGTH])
+{
+ UNUSED(addr);
+ return E_OK;
+}
+
+
+t_Error XX_IpcSendMessage(t_Handle h_Session,
+ uint8_t *p_Msg,
+ uint32_t msgLength,
+ uint8_t *p_Reply,
+ uint32_t *p_ReplyLength,
+ t_IpcMsgCompletion *f_Completion,
+ t_Handle h_Arg)
+{
+ UNUSED(h_Session); UNUSED(p_Msg); UNUSED(msgLength); UNUSED(p_Reply);
+ UNUSED(p_ReplyLength); UNUSED(f_Completion); UNUSED(h_Arg);
+ return E_OK;
+}
+
+t_Handle XX_IpcInitSession(char destAddr[XX_IPC_MAX_ADDR_NAME_LENGTH],
+ char srcAddr[XX_IPC_MAX_ADDR_NAME_LENGTH])
+{
+ UNUSED(destAddr); UNUSED(srcAddr);
+ return E_OK;
+}
+
+/*Forced to introduce due to PRINT_FMT_PARAMS define*/
+uint32_t E500_GetId(void)
+{
+ return raw_smp_processor_id();
+}
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
+int GetDeviceIrqNum(int irq)
+{
+ struct device_node *iPar;
+ struct irq_host *irqHost;
+ uint32_t hwIrq;
+
+ /* Get the interrupt controller */
+ iPar = of_find_node_by_name(NULL, "mpic");
+ hwIrq = 0;
+
+ ASSERT_COND(iPar != NULL);
+ /* Get the irq host */
+ irqHost = irq_find_host(iPar);
+ of_node_put(iPar);
+
+ /* Create irq mapping */
+ return irq_create_mapping(irqHost, hwIrq);
+}
+#else
+#error "kernel not supported!!!"
+#endif /* LINUX_VERSION_CODE */
+
+void * XX_PhysToVirt(physAddress_t addr)
+{
+ return UINT_TO_PTR(SYS_PhysToVirt((uint64_t)addr));
+}
+
+physAddress_t XX_VirtToPhys(void * addr)
+{
+ return (physAddress_t)SYS_VirtToPhys(PTR_TO_UINT(addr));
+}
+
+void * xx_MallocSmart(uint32_t size, int memPartitionId, uint32_t alignment)
+{
+ uintptr_t *returnCode, tmp;
+
+ if (alignment < sizeof(uintptr_t))
+ alignment = sizeof(uintptr_t);
+ size += alignment + sizeof(returnCode);
+ tmp = (uintptr_t)xx_Malloc(size);
+ if (tmp == 0)
+ return NULL;
+ returnCode = (uintptr_t*)((tmp + alignment + sizeof(returnCode)) & ~((uintptr_t)alignment - 1));
+ *(returnCode - 1) = tmp;
+
+ return (void*)returnCode;
+}
+
+void xx_FreeSmart(void *p)
+{
+ xx_Free((void*)(*((uintptr_t *)(p) - 1)));
+}