layerscape: add ls1088ardb device support
[openwrt/staging/yousong.git] / target / linux / layerscape / patches-4.4 / 7220-dpaa2-ethsw-Ethernet-Switch-driver.patch
diff --git a/target/linux/layerscape/patches-4.4/7220-dpaa2-ethsw-Ethernet-Switch-driver.patch b/target/linux/layerscape/patches-4.4/7220-dpaa2-ethsw-Ethernet-Switch-driver.patch
new file mode 100644 (file)
index 0000000..067eb59
--- /dev/null
@@ -0,0 +1,6605 @@
+From 8df017d70c54ceafc99b7904785603c678a2e5c1 Mon Sep 17 00:00:00 2001
+From: Razvan Stefanescu <razvan.stefanescu@freescale.com>
+Date: Tue, 22 Sep 2015 11:36:34 +0300
+Subject: [PATCH 220/226] dpaa2-ethsw: Ethernet Switch driver
+
+This is a commit of the cummulative, squashed dpaa2-l2switch patches.
+All the commit logs are preserved below.
+
+Signed-off-by: Stuart Yoder <stuart.yoder@nxp.com>
+
+---------------------------------------------------------------------
+
+dpaa2-ethsw: Ethernet Switch driver
+
+Initial support for DPAA2 L2 switch.  The switch and all ports are
+presented as network interfaces in linux (swX and swXpY).  I/O
+functionality is not available on these interfaces, they are exclusively
+for management.
+
+Configuration is done using bridge tool.  Supported commands are:
+- fdb operations with unicast/multicast addresses
+- vlan configuration
+- setting STP state of ports
+- flooding, learning control
+
+Offers support for retrieving port statistics via ethtool (or similar
+applications).
+
+This patch contains the following patches squashed together:
+staging: fsl-dpaa2: ethsw: ethernet switch driver
+dpaa2-ethsw: Include by default in configuration
+staging: fsl-dpaa2: ethsw: Rebasing onto kernel 4.0
+staging: fsl-mc: migrated remaining flibs for MC fw 8.0.0
+dpaa2-ethsw: Prefix driver name with dpaa2-
+dpaa2-ethsw: Set carrier state on probe
+dpaa2-ethsw: Add support for link state update
+
+These patches were initally submitted by:
+Alex Marginean <alexandru.marginean@freescale.com>
+J. German Rivera <German.Rivera@freescale.com>
+Razvan Stefanescu <razvan.stefanescu@freescale.com>
+
+and reviewed by Stuart Yoder <stuart.yoder@freescale.com>
+
+Ported to linux-v4.1 by updating iflink usage and ndo_bridge_getlink()
+parameters list update.
+
+Signed-off-by: Razvan Stefanescu <razvan.stefanescu@freescale.com>
+[Stuart: resolved minor merge conflicts]
+Signed-off-by: Stuart Yoder <stuart.yoder@nxp.com>
+
+dpaa2-ethsw: Update dpsw binary interface to 7.0
+
+This corresponds to MC release 0.8.0.
+
+Signed-off-by: Razvan Stefanescu <razvan.stefanescu@freescale.com>
+
+dpaa2-ethsw: Add object version check
+
+Abort probing if DPSW object version is smaller than required.
+
+Signed-off-by: Razvan Stefanescu <razvan.stefanescu@freescale.com>
+
+dpaa2-ethsw: Fix interrupt handling
+
+Mask only the events handled by the driver - DPSW_IRQ_EVENT_LINK_CHANGED.
+
+Use clear-on-read mechanism for the interrupt status and avoid calling
+dpsw_clear_irq_status(). Status contains the events handled (only link
+state change for the moment) and masks the first 16-bits, as they are used
+to store the interface ID that generated the event.
+
+Signed-off-by: Razvan Stefanescu <razvan.stefanescu@freescale.com>
+
+dpaa2-ethsw: resolve compile issues on uprev to 4.5
+
+-irq_number field no longer exists in fsl-mc interrupt
+ struct
+-netdev_master_upper_dev_link() has 2 new parameters, which
+ are set to NULL for now
+
+Signed-off-by: Stuart Yoder <stuart.yoder@nxp.com>
+---
+ MAINTAINERS                                |    6 +
+ drivers/staging/fsl-dpaa2/Kconfig          |    1 +
+ drivers/staging/fsl-dpaa2/Makefile         |    1 +
+ drivers/staging/fsl-dpaa2/ethsw/Kconfig    |    7 +
+ drivers/staging/fsl-dpaa2/ethsw/Makefile   |   10 +
+ drivers/staging/fsl-dpaa2/ethsw/dpsw-cmd.h |  916 ++++++++++++
+ drivers/staging/fsl-dpaa2/ethsw/dpsw.c     | 1639 +++++++++++++++++++++
+ drivers/staging/fsl-dpaa2/ethsw/dpsw.h     | 2164 ++++++++++++++++++++++++++++
+ drivers/staging/fsl-dpaa2/ethsw/switch.c   | 1711 ++++++++++++++++++++++
+ drivers/staging/fsl-mc/include/net.h       |    1 -
+ 10 files changed, 6455 insertions(+), 1 deletion(-)
+ create mode 100644 drivers/staging/fsl-dpaa2/ethsw/Kconfig
+ create mode 100644 drivers/staging/fsl-dpaa2/ethsw/Makefile
+ create mode 100644 drivers/staging/fsl-dpaa2/ethsw/dpsw-cmd.h
+ create mode 100644 drivers/staging/fsl-dpaa2/ethsw/dpsw.c
+ create mode 100644 drivers/staging/fsl-dpaa2/ethsw/dpsw.h
+ create mode 100644 drivers/staging/fsl-dpaa2/ethsw/switch.c
+
+--- a/MAINTAINERS
++++ b/MAINTAINERS
+@@ -4554,6 +4554,12 @@ S:      Maintained
+ F:    drivers/staging/fsl-mc/bus/mc-ioctl.h
+ F:    drivers/staging/fsl-mc/bus/mc-restool.c
++FREESCALE DPAA2 ETHERNET SWITCH DRIVER
++M:    Alex Marginean <Alexandru.Marginean@freescale.com>
++L:    linux-kernel@vger.kernel.org
++S:    Maintained
++F:    drivers/staging/fsl-dpaa2/ethsw/
++
+ FREESCALE DPAA2 MAC/PHY INTERFACE DRIVER
+ M:    Alex Marginean <Alexandru.Marginean@freescale.com>
+ L:    linux-kernel@vger.kernel.org
+--- a/drivers/staging/fsl-dpaa2/Kconfig
++++ b/drivers/staging/fsl-dpaa2/Kconfig
+@@ -11,3 +11,4 @@ config FSL_DPAA2
+ source "drivers/staging/fsl-dpaa2/ethernet/Kconfig"
+ source "drivers/staging/fsl-dpaa2/mac/Kconfig"
+ source "drivers/staging/fsl-dpaa2/evb/Kconfig"
++source "drivers/staging/fsl-dpaa2/ethsw/Kconfig"
+--- a/drivers/staging/fsl-dpaa2/Makefile
++++ b/drivers/staging/fsl-dpaa2/Makefile
+@@ -5,3 +5,4 @@
+ obj-$(CONFIG_FSL_DPAA2_ETH)   += ethernet/
+ obj-$(CONFIG_FSL_DPAA2_MAC)   += mac/
+ obj-$(CONFIG_FSL_DPAA2_EVB)   += evb/
++obj-$(CONFIG_FSL_DPAA2_ETHSW) += ethsw/
+--- /dev/null
++++ b/drivers/staging/fsl-dpaa2/ethsw/Kconfig
+@@ -0,0 +1,7 @@
++config FSL_DPAA2_ETHSW
++      tristate "DPAA2 Ethernet Switch"
++      depends on FSL_MC_BUS && FSL_DPAA2 && FSL_DPAA2_ETH
++      select FSL_DPAA2_MAC
++      default y
++      ---help---
++      Prototype driver for DPAA2 Ethernet Switch.
+--- /dev/null
++++ b/drivers/staging/fsl-dpaa2/ethsw/Makefile
+@@ -0,0 +1,10 @@
++
++obj-$(CONFIG_FSL_DPAA2_ETHSW) += dpaa2-ethsw.o
++
++dpaa2-ethsw-objs := switch.o dpsw.o
++
++all:
++      make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
++
++clean:
++      make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
+--- /dev/null
++++ b/drivers/staging/fsl-dpaa2/ethsw/dpsw-cmd.h
+@@ -0,0 +1,916 @@
++/* Copyright 2013-2015 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 the above-listed copyright holders nor the
++ * names of any contributors may be used to endorse or promote products
++ * derived from this software without specific prior written permission.
++ *
++ *
++ * ALTERNATIVELY, this software may be distributed under the terms of the
++ * GNU General Public License ("GPL") as published by the Free Software
++ * Foundation, either version 2 of that License or (at your option) any
++ * later version.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
++ * POSSIBILITY OF SUCH DAMAGE.
++ */
++#ifndef __FSL_DPSW_CMD_H
++#define __FSL_DPSW_CMD_H
++
++/* DPSW Version */
++#define DPSW_VER_MAJOR                                7
++#define DPSW_VER_MINOR                                0
++
++/* Command IDs */
++#define DPSW_CMDID_CLOSE                      0x800
++#define DPSW_CMDID_OPEN                               0x802
++#define DPSW_CMDID_CREATE                     0x902
++#define DPSW_CMDID_DESTROY                    0x900
++
++#define DPSW_CMDID_ENABLE                     0x002
++#define DPSW_CMDID_DISABLE                    0x003
++#define DPSW_CMDID_GET_ATTR                   0x004
++#define DPSW_CMDID_RESET                      0x005
++#define DPSW_CMDID_IS_ENABLED                 0x006
++
++#define DPSW_CMDID_SET_IRQ                    0x010
++#define DPSW_CMDID_GET_IRQ                    0x011
++#define DPSW_CMDID_SET_IRQ_ENABLE             0x012
++#define DPSW_CMDID_GET_IRQ_ENABLE             0x013
++#define DPSW_CMDID_SET_IRQ_MASK                       0x014
++#define DPSW_CMDID_GET_IRQ_MASK                       0x015
++#define DPSW_CMDID_GET_IRQ_STATUS             0x016
++#define DPSW_CMDID_CLEAR_IRQ_STATUS           0x017
++
++#define DPSW_CMDID_SET_REFLECTION_IF          0x022
++
++#define DPSW_CMDID_ADD_CUSTOM_TPID            0x024
++
++#define DPSW_CMDID_REMOVE_CUSTOM_TPID         0x026
++
++#define DPSW_CMDID_IF_SET_TCI                 0x030
++#define DPSW_CMDID_IF_SET_STP                 0x031
++#define DPSW_CMDID_IF_SET_ACCEPTED_FRAMES     0x032
++#define DPSW_CMDID_SET_IF_ACCEPT_ALL_VLAN     0x033
++#define DPSW_CMDID_IF_GET_COUNTER             0x034
++#define DPSW_CMDID_IF_SET_COUNTER             0x035
++#define DPSW_CMDID_IF_SET_TX_SELECTION                0x036
++#define DPSW_CMDID_IF_ADD_REFLECTION          0x037
++#define DPSW_CMDID_IF_REMOVE_REFLECTION               0x038
++#define DPSW_CMDID_IF_SET_FLOODING_METERING   0x039
++#define DPSW_CMDID_IF_SET_METERING            0x03A
++#define DPSW_CMDID_IF_SET_EARLY_DROP          0x03B
++
++#define DPSW_CMDID_IF_ENABLE                  0x03D
++#define DPSW_CMDID_IF_DISABLE                 0x03E
++
++#define DPSW_CMDID_IF_GET_ATTR                        0x042
++
++#define DPSW_CMDID_IF_SET_MAX_FRAME_LENGTH    0x044
++#define DPSW_CMDID_IF_GET_MAX_FRAME_LENGTH    0x045
++#define DPSW_CMDID_IF_GET_LINK_STATE          0x046
++#define DPSW_CMDID_IF_SET_FLOODING            0x047
++#define DPSW_CMDID_IF_SET_BROADCAST           0x048
++#define DPSW_CMDID_IF_SET_MULTICAST           0x049
++#define DPSW_CMDID_IF_GET_TCI                 0x04A
++
++#define DPSW_CMDID_IF_SET_LINK_CFG            0x04C
++
++#define DPSW_CMDID_VLAN_ADD                   0x060
++#define DPSW_CMDID_VLAN_ADD_IF                        0x061
++#define DPSW_CMDID_VLAN_ADD_IF_UNTAGGED               0x062
++#define DPSW_CMDID_VLAN_ADD_IF_FLOODING               0x063
++#define DPSW_CMDID_VLAN_REMOVE_IF             0x064
++#define DPSW_CMDID_VLAN_REMOVE_IF_UNTAGGED    0x065
++#define DPSW_CMDID_VLAN_REMOVE_IF_FLOODING    0x066
++#define DPSW_CMDID_VLAN_REMOVE                        0x067
++#define DPSW_CMDID_VLAN_GET_IF                        0x068
++#define DPSW_CMDID_VLAN_GET_IF_FLOODING               0x069
++#define DPSW_CMDID_VLAN_GET_IF_UNTAGGED               0x06A
++#define DPSW_CMDID_VLAN_GET_ATTRIBUTES                0x06B
++
++#define DPSW_CMDID_FDB_GET_MULTICAST          0x080
++#define DPSW_CMDID_FDB_GET_UNICAST            0x081
++#define DPSW_CMDID_FDB_ADD                    0x082
++#define DPSW_CMDID_FDB_REMOVE                 0x083
++#define DPSW_CMDID_FDB_ADD_UNICAST            0x084
++#define DPSW_CMDID_FDB_REMOVE_UNICAST         0x085
++#define DPSW_CMDID_FDB_ADD_MULTICAST          0x086
++#define DPSW_CMDID_FDB_REMOVE_MULTICAST               0x087
++#define DPSW_CMDID_FDB_SET_LEARNING_MODE      0x088
++#define DPSW_CMDID_FDB_GET_ATTR                       0x089
++
++#define DPSW_CMDID_ACL_ADD                    0x090
++#define DPSW_CMDID_ACL_REMOVE                 0x091
++#define DPSW_CMDID_ACL_ADD_ENTRY              0x092
++#define DPSW_CMDID_ACL_REMOVE_ENTRY           0x093
++#define DPSW_CMDID_ACL_ADD_IF                 0x094
++#define DPSW_CMDID_ACL_REMOVE_IF              0x095
++#define DPSW_CMDID_ACL_GET_ATTR                       0x096
++
++#define DPSW_CMDID_CTRL_IF_GET_ATTR           0x0A0
++#define DPSW_CMDID_CTRL_IF_SET_POOLS          0x0A1
++#define DPSW_CMDID_CTRL_IF_ENABLE             0x0A2
++#define DPSW_CMDID_CTRL_IF_DISABLE            0x0A3
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPSW_CMD_OPEN(cmd, dpsw_id) \
++      MC_CMD_OP(cmd, 0, 0,  32, int,   dpsw_id)
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPSW_CMD_CREATE(cmd, cfg) \
++do { \
++      MC_CMD_OP(cmd, 0, 0,  16, uint16_t, cfg->num_ifs);\
++      MC_CMD_OP(cmd, 0, 16,  8, uint8_t,  cfg->adv.max_fdbs);\
++      MC_CMD_OP(cmd, 0, 24,  8, uint8_t,  cfg->adv.max_meters_per_if);\
++      MC_CMD_OP(cmd, 0, 32,  4, enum dpsw_component_type,  \
++                      cfg->adv.component_type);\
++      MC_CMD_OP(cmd, 1, 0,  16, uint16_t, cfg->adv.max_vlans);\
++      MC_CMD_OP(cmd, 1, 16, 16, uint16_t, cfg->adv.max_fdb_entries);\
++      MC_CMD_OP(cmd, 1, 32, 16, uint16_t, cfg->adv.fdb_aging_time);\
++      MC_CMD_OP(cmd, 1, 48, 16, uint16_t, cfg->adv.max_fdb_mc_groups);\
++      MC_CMD_OP(cmd, 2, 0,  64, uint64_t, cfg->adv.options);\
++} while (0)
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPSW_RSP_IS_ENABLED(cmd, en) \
++      MC_RSP_OP(cmd, 0, 0,  1,  int,      en)
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPSW_CMD_SET_IRQ(cmd, irq_index, irq_cfg) \
++do { \
++      MC_CMD_OP(cmd, 0, 0,  8,  uint8_t,  irq_index);\
++      MC_CMD_OP(cmd, 0, 32, 32, uint32_t, irq_cfg->val);\
++      MC_CMD_OP(cmd, 1, 0,  64, uint64_t, irq_cfg->addr);\
++      MC_CMD_OP(cmd, 2, 0,  32, int,      irq_cfg->irq_num); \
++} while (0)
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPSW_CMD_GET_IRQ(cmd, irq_index) \
++      MC_CMD_OP(cmd, 0, 32, 8,  uint8_t,  irq_index)
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPSW_RSP_GET_IRQ(cmd, type, irq_cfg) \
++do { \
++      MC_RSP_OP(cmd, 0, 0,  32, uint32_t, irq_cfg->val); \
++      MC_RSP_OP(cmd, 1, 0,  64, uint64_t, irq_cfg->addr);\
++      MC_RSP_OP(cmd, 2, 0,  32, int,      irq_cfg->irq_num); \
++      MC_RSP_OP(cmd, 2, 32, 32, int,      type); \
++} while (0)
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPSW_CMD_SET_IRQ_ENABLE(cmd, irq_index, enable_state) \
++do { \
++      MC_CMD_OP(cmd, 0, 0,  8, uint8_t, enable_state); \
++      MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\
++} while (0)
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPSW_CMD_GET_IRQ_ENABLE(cmd, irq_index) \
++      MC_CMD_OP(cmd, 0, 32, 8,  uint8_t,  irq_index)
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPSW_RSP_GET_IRQ_ENABLE(cmd, enable_state) \
++      MC_RSP_OP(cmd, 0, 0,  8,  uint8_t,  enable_state)
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPSW_CMD_SET_IRQ_MASK(cmd, irq_index, mask) \
++do { \
++      MC_CMD_OP(cmd, 0, 0,  32, uint32_t, mask); \
++      MC_CMD_OP(cmd, 0, 32, 8,  uint8_t,  irq_index);\
++} while (0)
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPSW_CMD_GET_IRQ_MASK(cmd, irq_index) \
++      MC_CMD_OP(cmd, 0, 32, 8,  uint8_t,  irq_index)
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPSW_RSP_GET_IRQ_MASK(cmd, mask) \
++      MC_RSP_OP(cmd, 0, 0,  32, uint32_t, mask)
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPSW_CMD_GET_IRQ_STATUS(cmd, irq_index, status) \
++do { \
++      MC_CMD_OP(cmd, 0, 0,  32, uint32_t, status);\
++      MC_CMD_OP(cmd, 0, 32, 8,  uint8_t,  irq_index);\
++} while (0)
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPSW_RSP_GET_IRQ_STATUS(cmd, status) \
++      MC_RSP_OP(cmd, 0, 0,  32, uint32_t, status)
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPSW_CMD_CLEAR_IRQ_STATUS(cmd, irq_index, status) \
++do { \
++      MC_CMD_OP(cmd, 0, 0,  32, uint32_t, status); \
++      MC_CMD_OP(cmd, 0, 32, 8,  uint8_t,  irq_index);\
++} while (0)
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPSW_RSP_GET_ATTR(cmd, attr) \
++do { \
++      MC_RSP_OP(cmd, 0, 0,  16, uint16_t, attr->num_ifs);\
++      MC_RSP_OP(cmd, 0, 16, 8,  uint8_t,  attr->max_fdbs);\
++      MC_RSP_OP(cmd, 0, 24, 8,  uint8_t,  attr->num_fdbs);\
++      MC_RSP_OP(cmd, 0, 32, 16, uint16_t, attr->max_vlans);\
++      MC_RSP_OP(cmd, 0, 48, 16, uint16_t, attr->num_vlans);\
++      MC_RSP_OP(cmd, 1, 0,  16, uint16_t, attr->version.major);\
++      MC_RSP_OP(cmd, 1, 16, 16, uint16_t, attr->version.minor);\
++      MC_RSP_OP(cmd, 1, 32, 16, uint16_t, attr->max_fdb_entries);\
++      MC_RSP_OP(cmd, 1, 48, 16, uint16_t, attr->fdb_aging_time);\
++      MC_RSP_OP(cmd, 2, 0,  32, int,   attr->id);\
++      MC_RSP_OP(cmd, 2, 32, 16, uint16_t, attr->mem_size);\
++      MC_RSP_OP(cmd, 2, 48, 16, uint16_t, attr->max_fdb_mc_groups);\
++      MC_RSP_OP(cmd, 3, 0,  64, uint64_t, attr->options);\
++      MC_RSP_OP(cmd, 4, 0,  8,  uint8_t, attr->max_meters_per_if);\
++      MC_RSP_OP(cmd, 4, 8,  4,  enum dpsw_component_type, \
++                      attr->component_type);\
++} while (0)
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPSW_CMD_SET_REFLECTION_IF(cmd, if_id) \
++      MC_CMD_OP(cmd, 0, 0,  16, uint16_t, if_id)
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPSW_CMD_IF_SET_FLOODING(cmd, if_id, en) \
++do { \
++      MC_CMD_OP(cmd, 0, 0,  16, uint16_t, if_id);\
++      MC_CMD_OP(cmd, 0, 16, 1,  int,   en);\
++} while (0)
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPSW_CMD_IF_SET_BROADCAST(cmd, if_id, en) \
++do { \
++      MC_CMD_OP(cmd, 0, 0,  16, uint16_t, if_id);\
++      MC_CMD_OP(cmd, 0, 16, 1,  int,   en);\
++} while (0)
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPSW_CMD_IF_SET_MULTICAST(cmd, if_id, en) \
++do { \
++      MC_CMD_OP(cmd, 0, 0,  16, uint16_t, if_id);\
++      MC_CMD_OP(cmd, 0, 16, 1,  int,   en);\
++} while (0)
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPSW_CMD_IF_SET_TCI(cmd, if_id, cfg) \
++do { \
++      MC_CMD_OP(cmd, 0, 0,  16, uint16_t, if_id);\
++      MC_CMD_OP(cmd, 0, 16, 12, uint16_t, cfg->vlan_id);\
++      MC_CMD_OP(cmd, 0, 28, 1,  uint8_t,  cfg->dei);\
++      MC_CMD_OP(cmd, 0, 29, 3,  uint8_t,  cfg->pcp);\
++} while (0)
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPSW_CMD_IF_GET_TCI(cmd, if_id) \
++      MC_CMD_OP(cmd, 0, 0,  16, uint16_t, if_id)
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPSW_RSP_IF_GET_TCI(cmd, cfg) \
++do { \
++      MC_RSP_OP(cmd, 0, 16, 16, uint16_t, cfg->vlan_id);\
++      MC_RSP_OP(cmd, 0, 32, 8,  uint8_t,  cfg->dei);\
++      MC_RSP_OP(cmd, 0, 40, 8,  uint8_t,  cfg->pcp);\
++} while (0)
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPSW_CMD_IF_SET_STP(cmd, if_id, cfg) \
++do { \
++      MC_CMD_OP(cmd, 0, 0,  16, uint16_t, if_id);\
++      MC_CMD_OP(cmd, 0, 16, 16, uint16_t, cfg->vlan_id);\
++      MC_CMD_OP(cmd, 0, 32, 4,  enum dpsw_stp_state, cfg->state);\
++} while (0)
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPSW_CMD_IF_SET_ACCEPTED_FRAMES(cmd, if_id, cfg) \
++do { \
++      MC_CMD_OP(cmd, 0, 0,  16, uint16_t, if_id);\
++      MC_CMD_OP(cmd, 0, 16, 4,  enum dpsw_accepted_frames, cfg->type);\
++      MC_CMD_OP(cmd, 0, 20, 4,  enum dpsw_action, cfg->unaccept_act);\
++} while (0)
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPSW_CMD_IF_SET_ACCEPT_ALL_VLAN(cmd, if_id, accept_all) \
++do { \
++      MC_CMD_OP(cmd, 0, 0,  16, uint16_t, if_id);\
++      MC_CMD_OP(cmd, 0, 16, 1,  int,   accept_all);\
++} while (0)
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPSW_CMD_IF_GET_COUNTER(cmd, if_id, type) \
++do { \
++      MC_CMD_OP(cmd, 0, 0,  16, uint16_t, if_id);\
++      MC_CMD_OP(cmd, 0, 16, 5,  enum dpsw_counter, type);\
++} while (0)
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPSW_RSP_IF_GET_COUNTER(cmd, counter) \
++      MC_RSP_OP(cmd, 1, 0, 64, uint64_t, counter)
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPSW_CMD_IF_SET_COUNTER(cmd, if_id, type, counter) \
++do { \
++      MC_CMD_OP(cmd, 0, 0,  16, uint16_t,       if_id);\
++      MC_CMD_OP(cmd, 0, 16, 5,  enum dpsw_counter, type);\
++      MC_CMD_OP(cmd, 1, 0,  64, uint64_t,       counter);\
++} while (0)
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPSW_CMD_IF_SET_TX_SELECTION(cmd, if_id, cfg) \
++do { \
++      MC_CMD_OP(cmd, 0, 0,  16, uint16_t, if_id);\
++      MC_CMD_OP(cmd, 0, 16, 3,  enum dpsw_priority_selector, \
++                                                cfg->priority_selector);\
++      MC_CMD_OP(cmd, 1, 0,  8,  uint8_t,  cfg->tc_id[0]);\
++      MC_CMD_OP(cmd, 1, 8,  8,  uint8_t,  cfg->tc_id[1]);\
++      MC_CMD_OP(cmd, 1, 16, 8,  uint8_t,  cfg->tc_id[2]);\
++      MC_CMD_OP(cmd, 1, 24, 8,  uint8_t,  cfg->tc_id[3]);\
++      MC_CMD_OP(cmd, 1, 32, 8,  uint8_t,  cfg->tc_id[4]);\
++      MC_CMD_OP(cmd, 1, 40, 8,  uint8_t,  cfg->tc_id[5]);\
++      MC_CMD_OP(cmd, 1, 48, 8,  uint8_t,  cfg->tc_id[6]);\
++      MC_CMD_OP(cmd, 1, 56, 8,  uint8_t,  cfg->tc_id[7]);\
++      MC_CMD_OP(cmd, 2, 0,  16, uint16_t, cfg->tc_sched[0].delta_bandwidth);\
++      MC_CMD_OP(cmd, 2, 16, 4,  enum dpsw_schedule_mode,  \
++                                          cfg->tc_sched[0].mode);\
++      MC_CMD_OP(cmd, 2, 32, 16, uint16_t, cfg->tc_sched[1].delta_bandwidth);\
++      MC_CMD_OP(cmd, 2, 48, 4,  enum dpsw_schedule_mode, \
++                                          cfg->tc_sched[1].mode);\
++      MC_CMD_OP(cmd, 3, 0,  16, uint16_t, cfg->tc_sched[2].delta_bandwidth);\
++      MC_CMD_OP(cmd, 3, 16, 4,  enum dpsw_schedule_mode,  \
++                                          cfg->tc_sched[2].mode);\
++      MC_CMD_OP(cmd, 3, 32, 16, uint16_t, cfg->tc_sched[3].delta_bandwidth);\
++      MC_CMD_OP(cmd, 3, 48, 4,  enum dpsw_schedule_mode, \
++                                          cfg->tc_sched[3].mode);\
++      MC_CMD_OP(cmd, 4, 0,  16, uint16_t, cfg->tc_sched[4].delta_bandwidth);\
++      MC_CMD_OP(cmd, 4, 16,  4,  enum dpsw_schedule_mode,  \
++                                          cfg->tc_sched[4].mode);\
++      MC_CMD_OP(cmd, 4, 32, 16, uint16_t, cfg->tc_sched[5].delta_bandwidth);\
++      MC_CMD_OP(cmd, 4, 48, 4,  enum dpsw_schedule_mode,  \
++                                          cfg->tc_sched[5].mode);\
++      MC_CMD_OP(cmd, 5, 0,  16, uint16_t, cfg->tc_sched[6].delta_bandwidth);\
++      MC_CMD_OP(cmd, 5, 16, 4,  enum dpsw_schedule_mode,  \
++                                          cfg->tc_sched[6].mode);\
++      MC_CMD_OP(cmd, 5, 32, 16, uint16_t, cfg->tc_sched[7].delta_bandwidth);\
++      MC_CMD_OP(cmd, 5, 48, 4,  enum dpsw_schedule_mode,  \
++                                          cfg->tc_sched[7].mode);\
++} while (0)
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPSW_CMD_IF_ADD_REFLECTION(cmd, if_id, cfg) \
++do { \
++      MC_CMD_OP(cmd, 0, 0,  16, uint16_t, if_id);\
++      MC_CMD_OP(cmd, 0, 16, 16, uint16_t, cfg->vlan_id);\
++      MC_CMD_OP(cmd, 0, 32, 2,  enum dpsw_reflection_filter, cfg->filter);\
++} while (0)
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPSW_CMD_IF_REMOVE_REFLECTION(cmd, if_id, cfg) \
++do { \
++      MC_CMD_OP(cmd, 0, 0,  16, uint16_t, if_id);\
++      MC_CMD_OP(cmd, 0, 16, 16, uint16_t, cfg->vlan_id);\
++      MC_CMD_OP(cmd, 0, 32, 2,  enum dpsw_reflection_filter, cfg->filter);\
++} while (0)
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPSW_CMD_IF_SET_FLOODING_METERING(cmd, if_id, cfg) \
++do { \
++      MC_CMD_OP(cmd, 0, 0,  16, uint16_t, if_id);\
++      MC_CMD_OP(cmd, 0, 24, 4,  enum dpsw_metering_mode, cfg->mode);\
++      MC_CMD_OP(cmd, 0, 28, 4,  enum dpsw_metering_unit, cfg->units);\
++      MC_CMD_OP(cmd, 0, 32, 32, uint32_t, cfg->cir);\
++      MC_CMD_OP(cmd, 1, 0,  32, uint32_t, cfg->eir);\
++      MC_CMD_OP(cmd, 1, 32, 32, uint32_t, cfg->cbs);\
++      MC_CMD_OP(cmd, 2, 0,  32, uint32_t, cfg->ebs);\
++} while (0)
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPSW_CMD_IF_SET_METERING(cmd, if_id, tc_id, cfg) \
++do { \
++      MC_CMD_OP(cmd, 0, 0,  16, uint16_t, if_id);\
++      MC_CMD_OP(cmd, 0, 16, 8,  uint8_t,  tc_id);\
++      MC_CMD_OP(cmd, 0, 24, 4,  enum dpsw_metering_mode, cfg->mode);\
++      MC_CMD_OP(cmd, 0, 28, 4,  enum dpsw_metering_unit, cfg->units);\
++      MC_CMD_OP(cmd, 0, 32, 32, uint32_t, cfg->cir);\
++      MC_CMD_OP(cmd, 1, 0,  32, uint32_t, cfg->eir);\
++      MC_CMD_OP(cmd, 1, 32, 32, uint32_t, cfg->cbs);\
++      MC_CMD_OP(cmd, 2, 0,  32, uint32_t, cfg->ebs);\
++} while (0)
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPSW_PREP_EARLY_DROP(ext, cfg) \
++do { \
++      MC_PREP_OP(ext, 0, 0,  2, enum dpsw_early_drop_mode, cfg->drop_mode); \
++      MC_PREP_OP(ext, 0, 2,  2, \
++                enum dpsw_early_drop_unit, cfg->units); \
++      MC_PREP_OP(ext, 0, 32, 32, uint32_t, cfg->tail_drop_threshold); \
++      MC_PREP_OP(ext, 1, 0,  8,  uint8_t,  cfg->green.drop_probability); \
++      MC_PREP_OP(ext, 2, 0,  64, uint64_t, cfg->green.max_threshold); \
++      MC_PREP_OP(ext, 3, 0,  64, uint64_t, cfg->green.min_threshold); \
++      MC_PREP_OP(ext, 5, 0,  8,  uint8_t,  cfg->yellow.drop_probability);\
++      MC_PREP_OP(ext, 6, 0,  64, uint64_t, cfg->yellow.max_threshold); \
++      MC_PREP_OP(ext, 7, 0,  64, uint64_t, cfg->yellow.min_threshold); \
++} while (0)
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPSW_EXT_EARLY_DROP(ext, cfg) \
++do { \
++      MC_EXT_OP(ext, 0, 0,  2, enum dpsw_early_drop_mode, cfg->drop_mode); \
++      MC_EXT_OP(ext, 0, 2,  2, \
++                enum dpsw_early_drop_unit, cfg->units); \
++      MC_EXT_OP(ext, 0, 32, 32, uint32_t, cfg->tail_drop_threshold); \
++      MC_EXT_OP(ext, 1, 0,  8,  uint8_t,  cfg->green.drop_probability); \
++      MC_EXT_OP(ext, 2, 0,  64, uint64_t, cfg->green.max_threshold); \
++      MC_EXT_OP(ext, 3, 0,  64, uint64_t, cfg->green.min_threshold); \
++      MC_EXT_OP(ext, 5, 0,  8,  uint8_t,  cfg->yellow.drop_probability);\
++      MC_EXT_OP(ext, 6, 0,  64, uint64_t, cfg->yellow.max_threshold); \
++      MC_EXT_OP(ext, 7, 0,  64, uint64_t, cfg->yellow.min_threshold); \
++} while (0)
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPSW_CMD_IF_SET_EARLY_DROP(cmd, if_id, tc_id, early_drop_iova) \
++do { \
++      MC_CMD_OP(cmd, 0, 8,  8,  uint8_t,  tc_id); \
++      MC_CMD_OP(cmd, 0, 16, 16, uint16_t, if_id); \
++      MC_CMD_OP(cmd, 1, 0,  64, uint64_t, early_drop_iova); \
++} while (0)
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPSW_CMD_ADD_CUSTOM_TPID(cmd, cfg) \
++      MC_CMD_OP(cmd, 0, 16, 16, uint16_t, cfg->tpid)
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPSW_CMD_REMOVE_CUSTOM_TPID(cmd, cfg) \
++      MC_CMD_OP(cmd, 0, 16, 16, uint16_t, cfg->tpid)
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPSW_CMD_IF_ENABLE(cmd, if_id) \
++      MC_CMD_OP(cmd, 0, 0,  16, uint16_t, if_id)
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPSW_CMD_IF_DISABLE(cmd, if_id) \
++      MC_CMD_OP(cmd, 0, 0,  16, uint16_t, if_id)
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPSW_CMD_IF_GET_ATTR(cmd, if_id) \
++      MC_CMD_OP(cmd, 0, 0,  16, uint16_t, if_id)
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPSW_RSP_IF_GET_ATTR(cmd, attr) \
++do { \
++      MC_RSP_OP(cmd, 0, 0,  4,  enum dpsw_accepted_frames, \
++                                                      attr->admit_untagged);\
++      MC_RSP_OP(cmd, 0, 5,  1,  int,      attr->enabled);\
++      MC_RSP_OP(cmd, 0, 6,  1,  int,      attr->accept_all_vlan);\
++      MC_RSP_OP(cmd, 0, 16, 8,  uint8_t,  attr->num_tcs);\
++      MC_RSP_OP(cmd, 0, 32, 16, uint16_t,     attr->qdid);\
++      MC_RSP_OP(cmd, 1, 0,  32, uint32_t, attr->options);\
++      MC_RSP_OP(cmd, 2, 0,  32, uint32_t, attr->rate);\
++} while (0)
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPSW_CMD_IF_SET_MAX_FRAME_LENGTH(cmd, if_id, frame_length) \
++do { \
++      MC_CMD_OP(cmd, 0, 0,  16, uint16_t, if_id);\
++      MC_CMD_OP(cmd, 0, 16, 16, uint16_t, frame_length);\
++} while (0)
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPSW_CMD_IF_GET_MAX_FRAME_LENGTH(cmd, if_id) \
++      MC_CMD_OP(cmd, 0, 0,  16, uint16_t, if_id)
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPSW_RSP_IF_GET_MAX_FRAME_LENGTH(cmd, frame_length) \
++      MC_RSP_OP(cmd, 0, 16, 16, uint16_t, frame_length)
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPSW_CMD_IF_SET_LINK_CFG(cmd, if_id, cfg) \
++do { \
++      MC_CMD_OP(cmd, 0, 0,  16, uint16_t, if_id);\
++      MC_CMD_OP(cmd, 1, 0,  32, uint32_t, cfg->rate);\
++      MC_CMD_OP(cmd, 2, 0,  64, uint64_t, cfg->options);\
++} while (0)
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPSW_CMD_IF_GET_LINK_STATE(cmd, if_id) \
++      MC_CMD_OP(cmd, 0, 0,  16, uint16_t, if_id)
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPSW_RSP_IF_GET_LINK_STATE(cmd, state) \
++do { \
++      MC_RSP_OP(cmd, 0, 32, 1,  int,      state->up);\
++      MC_RSP_OP(cmd, 1, 0,  32, uint32_t, state->rate);\
++      MC_RSP_OP(cmd, 2, 0,  64, uint64_t, state->options);\
++} while (0)
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPSW_CMD_VLAN_ADD(cmd, vlan_id, cfg) \
++do { \
++      MC_CMD_OP(cmd, 0, 0,  16, uint16_t, cfg->fdb_id);\
++      MC_CMD_OP(cmd, 0, 16, 16, uint16_t, vlan_id);\
++} while (0)
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPSW_CMD_VLAN_ADD_IF(cmd, vlan_id) \
++      MC_CMD_OP(cmd, 0, 16, 16, uint16_t, vlan_id)
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPSW_CMD_VLAN_ADD_IF_UNTAGGED(cmd, vlan_id) \
++      MC_CMD_OP(cmd, 0, 16, 16, uint16_t, vlan_id)
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPSW_CMD_VLAN_ADD_IF_FLOODING(cmd, vlan_id) \
++      MC_CMD_OP(cmd, 0, 16, 16, uint16_t, vlan_id)
++
++#define DPSW_CMD_VLAN_REMOVE_IF(cmd, vlan_id) \
++      MC_CMD_OP(cmd, 0, 16, 16, uint16_t, vlan_id)
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPSW_CMD_VLAN_REMOVE_IF_UNTAGGED(cmd, vlan_id) \
++      MC_CMD_OP(cmd, 0, 16, 16, uint16_t, vlan_id)
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPSW_CMD_VLAN_REMOVE_IF_FLOODING(cmd, vlan_id) \
++      MC_CMD_OP(cmd, 0, 16, 16, uint16_t, vlan_id)
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPSW_CMD_VLAN_REMOVE(cmd, vlan_id) \
++      MC_CMD_OP(cmd, 0, 16, 16, uint16_t, vlan_id)
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPSW_CMD_VLAN_GET_ATTR(cmd, vlan_id) \
++      MC_CMD_OP(cmd, 0, 0,  16, uint16_t, vlan_id)
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPSW_RSP_VLAN_GET_ATTR(cmd, attr) \
++do { \
++      MC_RSP_OP(cmd, 1, 0,  16, uint16_t, attr->fdb_id); \
++      MC_RSP_OP(cmd, 1, 16, 16, uint16_t, attr->num_ifs); \
++      MC_RSP_OP(cmd, 1, 32, 16, uint16_t, attr->num_untagged_ifs); \
++      MC_RSP_OP(cmd, 1, 48, 16, uint16_t, attr->num_flooding_ifs); \
++} while (0)
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPSW_CMD_VLAN_GET_IF(cmd, vlan_id) \
++      MC_CMD_OP(cmd, 0, 0,  16, uint16_t, vlan_id)
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPSW_RSP_VLAN_GET_IF(cmd, cfg) \
++      MC_RSP_OP(cmd, 0, 16, 16, uint16_t, cfg->num_ifs)
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPSW_CMD_VLAN_GET_IF_FLOODING(cmd, vlan_id) \
++      MC_CMD_OP(cmd, 0, 0,  16, uint16_t, vlan_id)
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPSW_RSP_VLAN_GET_IF_FLOODING(cmd, cfg) \
++      MC_RSP_OP(cmd, 0, 16, 16, uint16_t, cfg->num_ifs)
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPSW_CMD_VLAN_GET_IF_UNTAGGED(cmd, vlan_id) \
++      MC_CMD_OP(cmd, 0, 0,  16, uint16_t, vlan_id)
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPSW_RSP_VLAN_GET_IF_UNTAGGED(cmd, cfg) \
++      MC_RSP_OP(cmd, 0, 16, 16, uint16_t, cfg->num_ifs)
++
++/*    param, offset, width,   type,           arg_name */
++#define DPSW_CMD_FDB_ADD(cmd, cfg) \
++do { \
++      MC_CMD_OP(cmd, 0, 32, 16, uint16_t, cfg->fdb_aging_time);\
++      MC_CMD_OP(cmd, 0, 48, 16, uint16_t, cfg->num_fdb_entries);\
++} while (0)
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPSW_RSP_FDB_ADD(cmd, fdb_id) \
++      MC_RSP_OP(cmd, 0, 0,  16, uint16_t, fdb_id)
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPSW_CMD_FDB_REMOVE(cmd, fdb_id) \
++      MC_CMD_OP(cmd, 0, 0,  16, uint16_t, fdb_id)
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPSW_CMD_FDB_ADD_UNICAST(cmd, fdb_id, cfg) \
++do { \
++      MC_CMD_OP(cmd, 0, 0,  16, uint16_t, fdb_id);\
++      MC_CMD_OP(cmd, 0, 16, 8,  uint8_t,  cfg->mac_addr[5]);\
++      MC_CMD_OP(cmd, 0, 24, 8,  uint8_t,  cfg->mac_addr[4]);\
++      MC_CMD_OP(cmd, 0, 32, 8,  uint8_t,  cfg->mac_addr[3]);\
++      MC_CMD_OP(cmd, 0, 40, 8,  uint8_t,  cfg->mac_addr[2]);\
++      MC_CMD_OP(cmd, 0, 48, 8,  uint8_t,  cfg->mac_addr[1]);\
++      MC_CMD_OP(cmd, 0, 56, 8,  uint8_t,  cfg->mac_addr[0]);\
++      MC_CMD_OP(cmd, 1, 0,  8,  uint16_t, cfg->if_egress);\
++      MC_CMD_OP(cmd, 1, 16, 4,  enum dpsw_fdb_entry_type, cfg->type);\
++} while (0)
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPSW_CMD_FDB_GET_UNICAST(cmd, fdb_id) \
++do { \
++      MC_CMD_OP(cmd, 0, 0,  16, uint16_t, fdb_id);\
++      MC_CMD_OP(cmd, 0, 16, 8,  uint8_t,  cfg->mac_addr[5]);\
++      MC_CMD_OP(cmd, 0, 24, 8,  uint8_t,  cfg->mac_addr[4]);\
++      MC_CMD_OP(cmd, 0, 32, 8,  uint8_t,  cfg->mac_addr[3]);\
++      MC_CMD_OP(cmd, 0, 40, 8,  uint8_t,  cfg->mac_addr[2]);\
++      MC_CMD_OP(cmd, 0, 48, 8,  uint8_t,  cfg->mac_addr[1]);\
++      MC_CMD_OP(cmd, 0, 56, 8,  uint8_t,  cfg->mac_addr[0]);\
++} while (0)
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPSW_RSP_FDB_GET_UNICAST(cmd, cfg) \
++do { \
++      MC_RSP_OP(cmd, 1, 0,  16, uint16_t, cfg->if_egress);\
++      MC_RSP_OP(cmd, 1, 16, 4,  enum dpsw_fdb_entry_type, cfg->type);\
++} while (0)
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPSW_CMD_FDB_REMOVE_UNICAST(cmd, fdb_id, cfg) \
++do { \
++      MC_CMD_OP(cmd, 0, 0,  16, uint16_t, fdb_id);\
++      MC_CMD_OP(cmd, 0, 16, 8,  uint8_t,  cfg->mac_addr[5]);\
++      MC_CMD_OP(cmd, 0, 24, 8,  uint8_t,  cfg->mac_addr[4]);\
++      MC_CMD_OP(cmd, 0, 32, 8,  uint8_t,  cfg->mac_addr[3]);\
++      MC_CMD_OP(cmd, 0, 40, 8,  uint8_t,  cfg->mac_addr[2]);\
++      MC_CMD_OP(cmd, 0, 48, 8,  uint8_t,  cfg->mac_addr[1]);\
++      MC_CMD_OP(cmd, 0, 56, 8,  uint8_t,  cfg->mac_addr[0]);\
++      MC_CMD_OP(cmd, 1, 0,  16, uint16_t, cfg->if_egress);\
++      MC_CMD_OP(cmd, 1, 16, 4,  enum dpsw_fdb_entry_type, cfg->type);\
++} while (0)
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPSW_CMD_FDB_ADD_MULTICAST(cmd, fdb_id, cfg) \
++do { \
++      MC_CMD_OP(cmd, 0, 0,  16, uint16_t, fdb_id);\
++      MC_CMD_OP(cmd, 0, 16, 16, uint16_t, cfg->num_ifs);\
++      MC_CMD_OP(cmd, 0, 32, 4,  enum dpsw_fdb_entry_type, cfg->type);\
++      MC_CMD_OP(cmd, 1, 0,  8,  uint8_t,  cfg->mac_addr[5]);\
++      MC_CMD_OP(cmd, 1, 8,  8,  uint8_t,  cfg->mac_addr[4]);\
++      MC_CMD_OP(cmd, 1, 16, 8,  uint8_t,  cfg->mac_addr[3]);\
++      MC_CMD_OP(cmd, 1, 24, 8,  uint8_t,  cfg->mac_addr[2]);\
++      MC_CMD_OP(cmd, 1, 32, 8,  uint8_t,  cfg->mac_addr[1]);\
++      MC_CMD_OP(cmd, 1, 40, 8,  uint8_t,  cfg->mac_addr[0]);\
++} while (0)
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPSW_CMD_FDB_GET_MULTICAST(cmd, fdb_id) \
++do { \
++      MC_CMD_OP(cmd, 0, 0,  16, uint16_t, fdb_id);\
++      MC_CMD_OP(cmd, 0, 16, 8,  uint8_t,  cfg->mac_addr[5]);\
++      MC_CMD_OP(cmd, 0, 24, 8,  uint8_t,  cfg->mac_addr[4]);\
++      MC_CMD_OP(cmd, 0, 32, 8,  uint8_t,  cfg->mac_addr[3]);\
++      MC_CMD_OP(cmd, 0, 40, 8,  uint8_t,  cfg->mac_addr[2]);\
++      MC_CMD_OP(cmd, 0, 48, 8,  uint8_t,  cfg->mac_addr[1]);\
++      MC_CMD_OP(cmd, 0, 56, 8,  uint8_t,  cfg->mac_addr[0]);\
++} while (0)
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPSW_RSP_FDB_GET_MULTICAST(cmd, cfg) \
++do { \
++      MC_RSP_OP(cmd, 1, 0,  16, uint16_t, cfg->num_ifs);\
++      MC_RSP_OP(cmd, 1, 16, 4,  enum dpsw_fdb_entry_type, cfg->type);\
++} while (0)
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPSW_CMD_FDB_REMOVE_MULTICAST(cmd, fdb_id, cfg) \
++do { \
++      MC_CMD_OP(cmd, 0, 0,  16, uint16_t, fdb_id);\
++      MC_CMD_OP(cmd, 0, 16, 16, uint16_t, cfg->num_ifs);\
++      MC_CMD_OP(cmd, 0, 32, 4,  enum dpsw_fdb_entry_type, cfg->type);\
++      MC_CMD_OP(cmd, 1, 0,  8,  uint8_t,  cfg->mac_addr[5]);\
++      MC_CMD_OP(cmd, 1, 8,  8,  uint8_t,  cfg->mac_addr[4]);\
++      MC_CMD_OP(cmd, 1, 16, 8,  uint8_t,  cfg->mac_addr[3]);\
++      MC_CMD_OP(cmd, 1, 24, 8,  uint8_t,  cfg->mac_addr[2]);\
++      MC_CMD_OP(cmd, 1, 32, 8,  uint8_t,  cfg->mac_addr[1]);\
++      MC_CMD_OP(cmd, 1, 40, 8,  uint8_t,  cfg->mac_addr[0]);\
++} while (0)
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPSW_CMD_FDB_SET_LEARNING_MODE(cmd, fdb_id, mode) \
++do { \
++      MC_CMD_OP(cmd, 0, 0,  16, uint16_t, fdb_id);\
++      MC_CMD_OP(cmd, 0, 16, 4,  enum dpsw_fdb_learning_mode, mode);\
++} while (0)
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPSW_CMD_FDB_GET_ATTR(cmd, fdb_id) \
++      MC_CMD_OP(cmd, 0, 0,  16, uint16_t, fdb_id)
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPSW_RSP_FDB_GET_ATTR(cmd, attr) \
++do { \
++      MC_RSP_OP(cmd, 0, 16, 16, uint16_t, attr->max_fdb_entries);\
++      MC_RSP_OP(cmd, 0, 32, 16, uint16_t, attr->fdb_aging_time);\
++      MC_RSP_OP(cmd, 0, 48, 16, uint16_t, attr->num_fdb_mc_groups);\
++      MC_RSP_OP(cmd, 1, 0,  16, uint16_t, attr->max_fdb_mc_groups);\
++      MC_RSP_OP(cmd, 1, 16, 4,  enum dpsw_fdb_learning_mode, \
++                                                        attr->learning_mode);\
++} while (0)
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPSW_CMD_ACL_ADD(cmd, cfg) \
++      MC_CMD_OP(cmd, 0, 16, 16, uint16_t, cfg->max_entries)
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPSW_RSP_ACL_ADD(cmd, acl_id) \
++      MC_RSP_OP(cmd, 0, 0,  16, uint16_t, acl_id)
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPSW_CMD_ACL_REMOVE(cmd, acl_id) \
++      MC_CMD_OP(cmd, 0, 0,  16, uint16_t, acl_id)
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPSW_PREP_ACL_ENTRY(ext, key) \
++do { \
++      MC_PREP_OP(ext, 0, 0,  8,  uint8_t,  key->match.l2_dest_mac[5]);\
++      MC_PREP_OP(ext, 0, 8,  8,  uint8_t,  key->match.l2_dest_mac[4]);\
++      MC_PREP_OP(ext, 0, 16, 8,  uint8_t,  key->match.l2_dest_mac[3]);\
++      MC_PREP_OP(ext, 0, 24, 8,  uint8_t,  key->match.l2_dest_mac[2]);\
++      MC_PREP_OP(ext, 0, 32, 8,  uint8_t,  key->match.l2_dest_mac[1]);\
++      MC_PREP_OP(ext, 0, 40, 8,  uint8_t,  key->match.l2_dest_mac[0]);\
++      MC_PREP_OP(ext, 0, 48, 16, uint16_t, key->match.l2_tpid);\
++      MC_PREP_OP(ext, 1, 0,  8,  uint8_t,  key->match.l2_source_mac[5]);\
++      MC_PREP_OP(ext, 1, 8,  8,  uint8_t,  key->match.l2_source_mac[4]);\
++      MC_PREP_OP(ext, 1, 16, 8,  uint8_t,  key->match.l2_source_mac[3]);\
++      MC_PREP_OP(ext, 1, 24, 8,  uint8_t,  key->match.l2_source_mac[2]);\
++      MC_PREP_OP(ext, 1, 32, 8,  uint8_t,  key->match.l2_source_mac[1]);\
++      MC_PREP_OP(ext, 1, 40, 8,  uint8_t,  key->match.l2_source_mac[0]);\
++      MC_PREP_OP(ext, 1, 48, 16, uint16_t, key->match.l2_vlan_id);\
++      MC_PREP_OP(ext, 2, 0,  32, uint32_t, key->match.l3_dest_ip);\
++      MC_PREP_OP(ext, 2, 32, 32, uint32_t, key->match.l3_source_ip);\
++      MC_PREP_OP(ext, 3, 0,  16, uint16_t, key->match.l4_dest_port);\
++      MC_PREP_OP(ext, 3, 16, 16, uint16_t, key->match.l4_source_port);\
++      MC_PREP_OP(ext, 3, 32, 16, uint16_t, key->match.l2_ether_type);\
++      MC_PREP_OP(ext, 3, 48, 8,  uint8_t,  key->match.l2_pcp_dei);\
++      MC_PREP_OP(ext, 3, 56, 8,  uint8_t,  key->match.l3_dscp);\
++      MC_PREP_OP(ext, 4, 0,  8,  uint8_t,  key->mask.l2_dest_mac[5]);\
++      MC_PREP_OP(ext, 4, 8,  8,  uint8_t,  key->mask.l2_dest_mac[4]);\
++      MC_PREP_OP(ext, 4, 16, 8,  uint8_t,  key->mask.l2_dest_mac[3]);\
++      MC_PREP_OP(ext, 4, 24, 8,  uint8_t,  key->mask.l2_dest_mac[2]);\
++      MC_PREP_OP(ext, 4, 32, 8,  uint8_t,  key->mask.l2_dest_mac[1]);\
++      MC_PREP_OP(ext, 4, 40, 8,  uint8_t,  key->mask.l2_dest_mac[0]);\
++      MC_PREP_OP(ext, 4, 48, 16, uint16_t, key->mask.l2_tpid);\
++      MC_PREP_OP(ext, 5, 0,  8,  uint8_t,  key->mask.l2_source_mac[5]);\
++      MC_PREP_OP(ext, 5, 8,  8,  uint8_t,  key->mask.l2_source_mac[4]);\
++      MC_PREP_OP(ext, 5, 16, 8,  uint8_t,  key->mask.l2_source_mac[3]);\
++      MC_PREP_OP(ext, 5, 24, 8,  uint8_t,  key->mask.l2_source_mac[2]);\
++      MC_PREP_OP(ext, 5, 32, 8,  uint8_t,  key->mask.l2_source_mac[1]);\
++      MC_PREP_OP(ext, 5, 40, 8,  uint8_t,  key->mask.l2_source_mac[0]);\
++      MC_PREP_OP(ext, 5, 48, 16, uint16_t, key->mask.l2_vlan_id);\
++      MC_PREP_OP(ext, 6, 0,  32, uint32_t, key->mask.l3_dest_ip);\
++      MC_PREP_OP(ext, 6, 32, 32, uint32_t, key->mask.l3_source_ip);\
++      MC_PREP_OP(ext, 7, 0,  16, uint16_t, key->mask.l4_dest_port);\
++      MC_PREP_OP(ext, 7, 16, 16, uint16_t, key->mask.l4_source_port);\
++      MC_PREP_OP(ext, 7, 32, 16, uint16_t, key->mask.l2_ether_type);\
++      MC_PREP_OP(ext, 7, 48, 8,  uint8_t,  key->mask.l2_pcp_dei);\
++      MC_PREP_OP(ext, 7, 56, 8,  uint8_t,  key->mask.l3_dscp);\
++      MC_PREP_OP(ext, 8, 0,  8,  uint8_t,  key->match.l3_protocol);\
++      MC_PREP_OP(ext, 8, 8,  8,  uint8_t,  key->mask.l3_protocol);\
++} while (0)
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPSW_EXT_ACL_ENTRY(ext, key) \
++do { \
++      MC_EXT_OP(ext, 0, 0,  8,  uint8_t,  key->match.l2_dest_mac[5]);\
++      MC_EXT_OP(ext, 0, 8,  8,  uint8_t,  key->match.l2_dest_mac[4]);\
++      MC_EXT_OP(ext, 0, 16, 8,  uint8_t,  key->match.l2_dest_mac[3]);\
++      MC_EXT_OP(ext, 0, 24, 8,  uint8_t,  key->match.l2_dest_mac[2]);\
++      MC_EXT_OP(ext, 0, 32, 8,  uint8_t,  key->match.l2_dest_mac[1]);\
++      MC_EXT_OP(ext, 0, 40, 8,  uint8_t,  key->match.l2_dest_mac[0]);\
++      MC_EXT_OP(ext, 0, 48, 16, uint16_t, key->match.l2_tpid);\
++      MC_EXT_OP(ext, 1, 0,  8,  uint8_t,  key->match.l2_source_mac[5]);\
++      MC_EXT_OP(ext, 1, 8,  8,  uint8_t,  key->match.l2_source_mac[4]);\
++      MC_EXT_OP(ext, 1, 16, 8,  uint8_t,  key->match.l2_source_mac[3]);\
++      MC_EXT_OP(ext, 1, 24, 8,  uint8_t,  key->match.l2_source_mac[2]);\
++      MC_EXT_OP(ext, 1, 32, 8,  uint8_t,  key->match.l2_source_mac[1]);\
++      MC_EXT_OP(ext, 1, 40, 8,  uint8_t,  key->match.l2_source_mac[0]);\
++      MC_EXT_OP(ext, 1, 48, 16, uint16_t, key->match.l2_vlan_id);\
++      MC_EXT_OP(ext, 2, 0,  32, uint32_t, key->match.l3_dest_ip);\
++      MC_EXT_OP(ext, 2, 32, 32, uint32_t, key->match.l3_source_ip);\
++      MC_EXT_OP(ext, 3, 0,  16, uint16_t, key->match.l4_dest_port);\
++      MC_EXT_OP(ext, 3, 16, 16, uint16_t, key->match.l4_source_port);\
++      MC_EXT_OP(ext, 3, 32, 16, uint16_t, key->match.l2_ether_type);\
++      MC_EXT_OP(ext, 3, 48, 8,  uint8_t,  key->match.l2_pcp_dei);\
++      MC_EXT_OP(ext, 3, 56, 8,  uint8_t,  key->match.l3_dscp);\
++      MC_EXT_OP(ext, 4, 0,  8,  uint8_t,  key->mask.l2_dest_mac[5]);\
++      MC_EXT_OP(ext, 4, 8,  8,  uint8_t,  key->mask.l2_dest_mac[4]);\
++      MC_EXT_OP(ext, 4, 16, 8,  uint8_t,  key->mask.l2_dest_mac[3]);\
++      MC_EXT_OP(ext, 4, 24, 8,  uint8_t,  key->mask.l2_dest_mac[2]);\
++      MC_EXT_OP(ext, 4, 32, 8,  uint8_t,  key->mask.l2_dest_mac[1]);\
++      MC_EXT_OP(ext, 4, 40, 8,  uint8_t,  key->mask.l2_dest_mac[0]);\
++      MC_EXT_OP(ext, 4, 48, 16, uint16_t, key->mask.l2_tpid);\
++      MC_EXT_OP(ext, 5, 0,  8,  uint8_t,  key->mask.l2_source_mac[5]);\
++      MC_EXT_OP(ext, 5, 8,  8,  uint8_t,  key->mask.l2_source_mac[4]);\
++      MC_EXT_OP(ext, 5, 16, 8,  uint8_t,  key->mask.l2_source_mac[3]);\
++      MC_EXT_OP(ext, 5, 24, 8,  uint8_t,  key->mask.l2_source_mac[2]);\
++      MC_EXT_OP(ext, 5, 32, 8,  uint8_t,  key->mask.l2_source_mac[1]);\
++      MC_EXT_OP(ext, 5, 40, 8,  uint8_t,  key->mask.l2_source_mac[0]);\
++      MC_EXT_OP(ext, 5, 48, 16, uint16_t, key->mask.l2_vlan_id);\
++      MC_EXT_OP(ext, 6, 0,  32, uint32_t, key->mask.l3_dest_ip);\
++      MC_EXT_OP(ext, 6, 32, 32, uint32_t, key->mask.l3_source_ip);\
++      MC_EXT_OP(ext, 7, 0,  16, uint16_t, key->mask.l4_dest_port);\
++      MC_EXT_OP(ext, 7, 16, 16, uint16_t, key->mask.l4_source_port);\
++      MC_EXT_OP(ext, 7, 32, 16, uint16_t, key->mask.l2_ether_type);\
++      MC_EXT_OP(ext, 7, 48, 8,  uint8_t,  key->mask.l2_pcp_dei);\
++      MC_EXT_OP(ext, 7, 56, 8,  uint8_t,  key->mask.l3_dscp);\
++      MC_EXT_OP(ext, 8, 0,  8,  uint8_t,  key->match.l3_protocol);\
++      MC_EXT_OP(ext, 8, 8,  8,  uint8_t,  key->mask.l3_protocol);\
++} while (0)
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPSW_CMD_ACL_ADD_ENTRY(cmd, acl_id, cfg) \
++do { \
++      MC_CMD_OP(cmd, 0, 0,  16, uint16_t, acl_id);\
++      MC_CMD_OP(cmd, 0, 16, 16, uint16_t, cfg->result.if_id);\
++      MC_CMD_OP(cmd, 0, 32, 32, int,      cfg->precedence);\
++      MC_CMD_OP(cmd, 1, 0,  4,  enum dpsw_acl_action, cfg->result.action);\
++      MC_CMD_OP(cmd, 6, 0,  64, uint64_t, cfg->key_iova); \
++} while (0)
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPSW_CMD_ACL_REMOVE_ENTRY(cmd, acl_id, cfg) \
++do { \
++      MC_CMD_OP(cmd, 0, 0,  16, uint16_t, acl_id);\
++      MC_CMD_OP(cmd, 0, 16, 16, uint16_t, cfg->result.if_id);\
++      MC_CMD_OP(cmd, 0, 32, 32, int,      cfg->precedence);\
++      MC_CMD_OP(cmd, 1, 0,  4,  enum dpsw_acl_action, cfg->result.action);\
++      MC_CMD_OP(cmd, 6, 0,  64, uint64_t, cfg->key_iova); \
++} while (0)
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPSW_CMD_ACL_ADD_IF(cmd, acl_id, cfg) \
++do { \
++      MC_CMD_OP(cmd, 0, 0,  16, uint16_t, acl_id);\
++      MC_CMD_OP(cmd, 0, 16, 16, uint16_t, cfg->num_ifs); \
++} while (0)
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPSW_CMD_ACL_REMOVE_IF(cmd, acl_id, cfg) \
++do { \
++      MC_CMD_OP(cmd, 0, 0,  16, uint16_t, acl_id);\
++      MC_CMD_OP(cmd, 0, 16, 16, uint16_t, cfg->num_ifs); \
++} while (0)
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPSW_CMD_ACL_GET_ATTR(cmd, acl_id) \
++      MC_CMD_OP(cmd, 0, 0,  16, uint16_t, acl_id)
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPSW_RSP_ACL_GET_ATTR(cmd, attr) \
++do { \
++      MC_RSP_OP(cmd, 1, 0,  16, uint16_t, attr->max_entries);\
++      MC_RSP_OP(cmd, 1, 16, 16, uint16_t, attr->num_entries);\
++      MC_RSP_OP(cmd, 1, 32, 16, uint16_t, attr->num_ifs);\
++} while (0)
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPSW_RSP_CTRL_IF_GET_ATTR(cmd, attr) \
++do { \
++      MC_RSP_OP(cmd, 1, 0,  32, uint32_t, attr->rx_fqid);\
++      MC_RSP_OP(cmd, 1, 32, 32, uint32_t, attr->rx_err_fqid);\
++      MC_RSP_OP(cmd, 2, 0,  32, uint32_t, attr->tx_err_conf_fqid);\
++} while (0)
++
++/*                cmd, param, offset, width, type, arg_name */
++#define DPSW_CMD_CTRL_IF_SET_POOLS(cmd, cfg) \
++do { \
++      MC_CMD_OP(cmd, 0, 0,  8,  uint8_t,  cfg->num_dpbp); \
++      MC_CMD_OP(cmd, 0, 8,  1,  int,      cfg->pools[0].backup_pool); \
++      MC_CMD_OP(cmd, 0, 9,  1,  int,      cfg->pools[1].backup_pool); \
++      MC_CMD_OP(cmd, 0, 10, 1,  int,      cfg->pools[2].backup_pool); \
++      MC_CMD_OP(cmd, 0, 11, 1,  int,      cfg->pools[3].backup_pool); \
++      MC_CMD_OP(cmd, 0, 12, 1,  int,      cfg->pools[4].backup_pool); \
++      MC_CMD_OP(cmd, 0, 13, 1,  int,      cfg->pools[5].backup_pool); \
++      MC_CMD_OP(cmd, 0, 14, 1,  int,      cfg->pools[6].backup_pool); \
++      MC_CMD_OP(cmd, 0, 15, 1,  int,      cfg->pools[7].backup_pool); \
++      MC_CMD_OP(cmd, 0, 32, 32, int,      cfg->pools[0].dpbp_id); \
++      MC_CMD_OP(cmd, 4, 32, 16, uint16_t, cfg->pools[0].buffer_size);\
++      MC_CMD_OP(cmd, 1, 0,  32, int,      cfg->pools[1].dpbp_id); \
++      MC_CMD_OP(cmd, 4, 48, 16, uint16_t, cfg->pools[1].buffer_size);\
++      MC_CMD_OP(cmd, 1, 32, 32, int,      cfg->pools[2].dpbp_id); \
++      MC_CMD_OP(cmd, 5, 0,  16, uint16_t, cfg->pools[2].buffer_size);\
++      MC_CMD_OP(cmd, 2, 0,  32, int,      cfg->pools[3].dpbp_id); \
++      MC_CMD_OP(cmd, 5, 16, 16, uint16_t, cfg->pools[3].buffer_size);\
++      MC_CMD_OP(cmd, 2, 32, 32, int,      cfg->pools[4].dpbp_id); \
++      MC_CMD_OP(cmd, 5, 32, 16, uint16_t, cfg->pools[4].buffer_size);\
++      MC_CMD_OP(cmd, 3, 0,  32, int,      cfg->pools[5].dpbp_id); \
++      MC_CMD_OP(cmd, 5, 48, 16, uint16_t, cfg->pools[5].buffer_size);\
++      MC_CMD_OP(cmd, 3, 32, 32, int,      cfg->pools[6].dpbp_id); \
++      MC_CMD_OP(cmd, 6, 0,  16, uint16_t, cfg->pools[6].buffer_size);\
++      MC_CMD_OP(cmd, 4, 0,  32, int,      cfg->pools[7].dpbp_id); \
++      MC_CMD_OP(cmd, 6, 16, 16, uint16_t, cfg->pools[7].buffer_size);\
++} while (0)
++
++#endif /* __FSL_DPSW_CMD_H */
+--- /dev/null
++++ b/drivers/staging/fsl-dpaa2/ethsw/dpsw.c
+@@ -0,0 +1,1639 @@
++/* Copyright 2013-2015 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 the above-listed copyright holders nor the
++ * names of any contributors may be used to endorse or promote products
++ * derived from this software without specific prior written permission.
++ *
++ *
++ * ALTERNATIVELY, this software may be distributed under the terms of the
++ * GNU General Public License ("GPL") as published by the Free Software
++ * Foundation, either version 2 of that License or (at your option) any
++ * later version.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
++ * POSSIBILITY OF SUCH DAMAGE.
++ */
++#include "../../fsl-mc/include/mc-sys.h"
++#include "../../fsl-mc/include/mc-cmd.h"
++#include "dpsw.h"
++#include "dpsw-cmd.h"
++
++/* internal functions */
++static void build_if_id_bitmap(const uint16_t *if_id,
++                             const uint16_t num_ifs,
++                             struct mc_command *cmd,
++                             int start_param)
++{
++      int i;
++
++      for (i = 0; (i < num_ifs) && (i < DPSW_MAX_IF); i++)
++              cmd->params[start_param + (if_id[i] / 64)] |= mc_enc(
++                      (if_id[i] % 64), 1, 1);
++}
++
++static int read_if_id_bitmap(uint16_t *if_id,
++                           uint16_t *num_ifs,
++                           struct mc_command *cmd,
++                           int start_param)
++{
++      int bitmap[DPSW_MAX_IF] = { 0 };
++      int i, j = 0;
++      int count = 0;
++
++      for (i = 0; i < DPSW_MAX_IF; i++) {
++              bitmap[i] = (int)mc_dec(cmd->params[start_param + i / 64],
++                                       i % 64, 1);
++              count += bitmap[i];
++      }
++
++      *num_ifs = (uint16_t)count;
++
++      for (i = 0; (i < DPSW_MAX_IF) && (j < count); i++) {
++              if (bitmap[i]) {
++                      if_id[j] = (uint16_t)i;
++                      j++;
++              }
++      }
++
++      return 0;
++}
++
++/* DPSW APIs */
++int dpsw_open(struct fsl_mc_io *mc_io,
++            uint32_t cmd_flags,
++            int dpsw_id,
++            uint16_t *token)
++{
++      struct mc_command cmd = { 0 };
++      int err;
++
++      /* prepare command */
++      cmd.header = mc_encode_cmd_header(DPSW_CMDID_OPEN,
++                                        cmd_flags,
++                                        0);
++      DPSW_CMD_OPEN(cmd, dpsw_id);
++
++      /* send command to mc*/
++      err = mc_send_command(mc_io, &cmd);
++      if (err)
++              return err;
++
++      /* retrieve response parameters */
++      *token = MC_CMD_HDR_READ_TOKEN(cmd.header);
++
++      return 0;
++}
++
++int dpsw_close(struct fsl_mc_io *mc_io,
++             uint32_t cmd_flags,
++      uint16_t token)
++{
++      struct mc_command cmd = { 0 };
++
++      /* prepare command */
++      cmd.header = mc_encode_cmd_header(DPSW_CMDID_CLOSE,
++                                        cmd_flags,
++                                        token);
++
++      /* send command to mc*/
++      return mc_send_command(mc_io, &cmd);
++}
++
++int dpsw_create(struct fsl_mc_io *mc_io,
++              uint32_t cmd_flags,
++              const struct dpsw_cfg *cfg,
++              uint16_t *token)
++{
++      struct mc_command cmd = { 0 };
++      int err;
++
++      /* prepare command */
++      cmd.header = mc_encode_cmd_header(DPSW_CMDID_CREATE,
++                                        cmd_flags,
++                                        0);
++      DPSW_CMD_CREATE(cmd, cfg);
++
++      /* send command to mc*/
++      err = mc_send_command(mc_io, &cmd);
++      if (err)
++              return err;
++
++      /* retrieve response parameters */
++      *token = MC_CMD_HDR_READ_TOKEN(cmd.header);
++
++      return 0;
++}
++
++int dpsw_destroy(struct fsl_mc_io *mc_io,
++               uint32_t cmd_flags,
++               uint16_t token)
++{
++      struct mc_command cmd = { 0 };
++
++      /* prepare command */
++      cmd.header = mc_encode_cmd_header(DPSW_CMDID_DESTROY,
++                                        cmd_flags,
++                                        token);
++
++      /* send command to mc*/
++      return mc_send_command(mc_io, &cmd);
++}
++
++int dpsw_enable(struct fsl_mc_io *mc_io,
++              uint32_t cmd_flags,
++              uint16_t token)
++{
++      struct mc_command cmd = { 0 };
++
++      /* prepare command */
++      cmd.header = mc_encode_cmd_header(DPSW_CMDID_ENABLE,
++                                        cmd_flags,
++                                        token);
++
++      /* send command to mc*/
++      return mc_send_command(mc_io, &cmd);
++}
++
++int dpsw_disable(struct fsl_mc_io *mc_io,
++               uint32_t cmd_flags,
++               uint16_t token)
++{
++      struct mc_command cmd = { 0 };
++
++      /* prepare command */
++      cmd.header = mc_encode_cmd_header(DPSW_CMDID_DISABLE,
++                                        cmd_flags,
++                                        token);
++
++      /* send command to mc*/
++      return mc_send_command(mc_io, &cmd);
++}
++
++int dpsw_is_enabled(struct fsl_mc_io *mc_io,
++                  uint32_t cmd_flags,
++                  uint16_t token,
++                  int *en)
++{
++      struct mc_command cmd = { 0 };
++      int err;
++
++      /* prepare command */
++      cmd.header = mc_encode_cmd_header(DPSW_CMDID_IS_ENABLED, cmd_flags,
++                                        token);
++
++      /* send command to mc*/
++      err = mc_send_command(mc_io, &cmd);
++      if (err)
++              return err;
++
++      /* retrieve response parameters */
++      DPSW_RSP_IS_ENABLED(cmd, *en);
++
++      return 0;
++}
++
++int dpsw_reset(struct fsl_mc_io *mc_io,
++             uint32_t cmd_flags,
++             uint16_t token)
++{
++      struct mc_command cmd = { 0 };
++
++      /* prepare command */
++      cmd.header = mc_encode_cmd_header(DPSW_CMDID_RESET,
++                                        cmd_flags,
++                                        token);
++
++      /* send command to mc*/
++      return mc_send_command(mc_io, &cmd);
++}
++
++int dpsw_set_irq(struct fsl_mc_io *mc_io,
++               uint32_t cmd_flags,
++               uint16_t token,
++               uint8_t irq_index,
++               struct dpsw_irq_cfg *irq_cfg)
++{
++      struct mc_command cmd = { 0 };
++
++      /* prepare command */
++      cmd.header = mc_encode_cmd_header(DPSW_CMDID_SET_IRQ,
++                                        cmd_flags,
++                                        token);
++      DPSW_CMD_SET_IRQ(cmd, irq_index, irq_cfg);
++
++      /* send command to mc*/
++      return mc_send_command(mc_io, &cmd);
++}
++
++int dpsw_get_irq(struct fsl_mc_io *mc_io,
++               uint32_t cmd_flags,
++               uint16_t token,
++               uint8_t irq_index,
++               int *type,
++               struct dpsw_irq_cfg *irq_cfg)
++{
++      struct mc_command cmd = { 0 };
++      int err;
++
++      /* prepare command */
++      cmd.header = mc_encode_cmd_header(DPSW_CMDID_GET_IRQ,
++                                        cmd_flags,
++                                        token);
++      DPSW_CMD_GET_IRQ(cmd, irq_index);
++
++      /* send command to mc*/
++      err = mc_send_command(mc_io, &cmd);
++      if (err)
++              return err;
++
++      /* retrieve response parameters */
++      DPSW_RSP_GET_IRQ(cmd, *type, irq_cfg);
++
++      return 0;
++}
++
++int dpsw_set_irq_enable(struct fsl_mc_io *mc_io,
++                      uint32_t cmd_flags,
++                      uint16_t token,
++                      uint8_t irq_index,
++                      uint8_t en)
++{
++      struct mc_command cmd = { 0 };
++
++      /* prepare command */
++      cmd.header = mc_encode_cmd_header(DPSW_CMDID_SET_IRQ_ENABLE,
++                                        cmd_flags,
++                                        token);
++      DPSW_CMD_SET_IRQ_ENABLE(cmd, irq_index, en);
++
++      /* send command to mc*/
++      return mc_send_command(mc_io, &cmd);
++}
++
++int dpsw_get_irq_enable(struct fsl_mc_io *mc_io,
++                      uint32_t cmd_flags,
++                      uint16_t token,
++                      uint8_t irq_index,
++                      uint8_t *en)
++{
++      struct mc_command cmd = { 0 };
++      int err;
++
++      /* prepare command */
++      cmd.header = mc_encode_cmd_header(DPSW_CMDID_GET_IRQ_ENABLE,
++                                        cmd_flags,
++                                        token);
++      DPSW_CMD_GET_IRQ_ENABLE(cmd, irq_index);
++
++      /* send command to mc*/
++      err = mc_send_command(mc_io, &cmd);
++      if (err)
++              return err;
++
++      /* retrieve response parameters */
++      DPSW_RSP_GET_IRQ_ENABLE(cmd, *en);
++
++      return 0;
++}
++
++int dpsw_set_irq_mask(struct fsl_mc_io *mc_io,
++                    uint32_t cmd_flags,
++                    uint16_t token,
++                    uint8_t irq_index,
++                    uint32_t mask)
++{
++      struct mc_command cmd = { 0 };
++
++      /* prepare command */
++      cmd.header = mc_encode_cmd_header(DPSW_CMDID_SET_IRQ_MASK,
++                                        cmd_flags,
++                                        token);
++      DPSW_CMD_SET_IRQ_MASK(cmd, irq_index, mask);
++
++      /* send command to mc*/
++      return mc_send_command(mc_io, &cmd);
++}
++
++int dpsw_get_irq_mask(struct fsl_mc_io *mc_io,
++                    uint32_t cmd_flags,
++                    uint16_t token,
++                    uint8_t irq_index,
++                    uint32_t *mask)
++{
++      struct mc_command cmd = { 0 };
++      int err;
++
++      /* prepare command */
++      cmd.header = mc_encode_cmd_header(DPSW_CMDID_GET_IRQ_MASK,
++                                        cmd_flags,
++                                        token);
++      DPSW_CMD_GET_IRQ_MASK(cmd, irq_index);
++
++      /* send command to mc*/
++      err = mc_send_command(mc_io, &cmd);
++      if (err)
++              return err;
++
++      /* retrieve response parameters */
++      DPSW_RSP_GET_IRQ_MASK(cmd, *mask);
++
++      return 0;
++}
++
++int dpsw_get_irq_status(struct fsl_mc_io *mc_io,
++                      uint32_t cmd_flags,
++                      uint16_t token,
++                      uint8_t irq_index,
++                      uint32_t *status)
++{
++      struct mc_command cmd = { 0 };
++      int err;
++
++      /* prepare command */
++      cmd.header = mc_encode_cmd_header(DPSW_CMDID_GET_IRQ_STATUS,
++                                        cmd_flags,
++                                        token);
++      DPSW_CMD_GET_IRQ_STATUS(cmd, irq_index, *status);
++
++      /* send command to mc*/
++      err = mc_send_command(mc_io, &cmd);
++      if (err)
++              return err;
++
++      /* retrieve response parameters */
++      DPSW_RSP_GET_IRQ_STATUS(cmd, *status);
++
++      return 0;
++}
++
++int dpsw_clear_irq_status(struct fsl_mc_io *mc_io,
++                        uint32_t cmd_flags,
++                        uint16_t token,
++                        uint8_t irq_index,
++                        uint32_t status)
++{
++      struct mc_command cmd = { 0 };
++
++      /* prepare command */
++      cmd.header = mc_encode_cmd_header(DPSW_CMDID_CLEAR_IRQ_STATUS,
++                                        cmd_flags,
++                                        token);
++      DPSW_CMD_CLEAR_IRQ_STATUS(cmd, irq_index, status);
++
++      /* send command to mc*/
++      return mc_send_command(mc_io, &cmd);
++}
++
++int dpsw_get_attributes(struct fsl_mc_io *mc_io,
++                      uint32_t cmd_flags,
++                      uint16_t token,
++                      struct dpsw_attr *attr)
++{
++      struct mc_command cmd = { 0 };
++      int err;
++
++      /* prepare command */
++      cmd.header = mc_encode_cmd_header(DPSW_CMDID_GET_ATTR,
++                                        cmd_flags,
++                                        token);
++
++      /* send command to mc*/
++      err = mc_send_command(mc_io, &cmd);
++      if (err)
++              return err;
++
++      /* retrieve response parameters */
++      DPSW_RSP_GET_ATTR(cmd, attr);
++
++      return 0;
++}
++
++int dpsw_set_reflection_if(struct fsl_mc_io *mc_io,
++                         uint32_t cmd_flags,
++                         uint16_t token,
++                         uint16_t if_id)
++{
++      struct mc_command cmd = { 0 };
++
++      /* prepare command */
++      cmd.header = mc_encode_cmd_header(DPSW_CMDID_SET_REFLECTION_IF,
++                                        cmd_flags,
++                                        token);
++      DPSW_CMD_SET_REFLECTION_IF(cmd, if_id);
++
++      /* send command to mc*/
++      return mc_send_command(mc_io, &cmd);
++}
++
++int dpsw_if_set_link_cfg(struct fsl_mc_io *mc_io,
++                       uint32_t cmd_flags,
++                       uint16_t token,
++                       uint16_t if_id,
++                       struct dpsw_link_cfg *cfg)
++{
++      struct mc_command cmd = { 0 };
++
++      /* prepare command */
++      cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_SET_LINK_CFG,
++                                        cmd_flags,
++                                        token);
++      DPSW_CMD_IF_SET_LINK_CFG(cmd, if_id, cfg);
++
++      /* send command to mc*/
++      return mc_send_command(mc_io, &cmd);
++}
++
++int dpsw_if_get_link_state(struct fsl_mc_io *mc_io,
++                         uint32_t cmd_flags,
++                         uint16_t token,
++                         uint16_t if_id,
++                         struct dpsw_link_state *state)
++{
++      struct mc_command cmd = { 0 };
++      int err;
++
++      /* prepare command */
++      cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_GET_LINK_STATE,
++                                        cmd_flags,
++                                        token);
++      DPSW_CMD_IF_GET_LINK_STATE(cmd, if_id);
++
++      /* send command to mc*/
++      err = mc_send_command(mc_io, &cmd);
++      if (err)
++              return err;
++
++      /* retrieve response parameters */
++      DPSW_RSP_IF_GET_LINK_STATE(cmd, state);
++
++      return 0;
++}
++
++int dpsw_if_set_flooding(struct fsl_mc_io *mc_io,
++                       uint32_t cmd_flags,
++                       uint16_t token,
++                       uint16_t if_id,
++                       int en)
++{
++      struct mc_command cmd = { 0 };
++
++      /* prepare command */
++      cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_SET_FLOODING,
++                                        cmd_flags,
++                                        token);
++      DPSW_CMD_IF_SET_FLOODING(cmd, if_id, en);
++
++      /* send command to mc*/
++      return mc_send_command(mc_io, &cmd);
++}
++
++int dpsw_if_set_broadcast(struct fsl_mc_io *mc_io,
++                        uint32_t cmd_flags,
++                        uint16_t token,
++                        uint16_t if_id,
++                        int en)
++{
++      struct mc_command cmd = { 0 };
++
++      /* prepare command */
++      cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_SET_BROADCAST,
++                                        cmd_flags,
++                                        token);
++      DPSW_CMD_IF_SET_FLOODING(cmd, if_id, en);
++
++      /* send command to mc*/
++      return mc_send_command(mc_io, &cmd);
++}
++
++int dpsw_if_set_multicast(struct fsl_mc_io *mc_io,
++                        uint32_t cmd_flags,
++                        uint16_t token,
++                        uint16_t if_id,
++                        int en)
++{
++      struct mc_command cmd = { 0 };
++
++      /* prepare command */
++      cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_SET_MULTICAST,
++                                        cmd_flags,
++                                        token);
++      DPSW_CMD_IF_SET_FLOODING(cmd, if_id, en);
++
++      /* send command to mc*/
++      return mc_send_command(mc_io, &cmd);
++}
++
++int dpsw_if_set_tci(struct fsl_mc_io *mc_io,
++                  uint32_t cmd_flags,
++                  uint16_t token,
++                  uint16_t if_id,
++                  const struct dpsw_tci_cfg *cfg)
++{
++      struct mc_command cmd = { 0 };
++
++      /* prepare command */
++      cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_SET_TCI,
++                                        cmd_flags,
++                                        token);
++      DPSW_CMD_IF_SET_TCI(cmd, if_id, cfg);
++
++      /* send command to mc*/
++      return mc_send_command(mc_io, &cmd);
++}
++
++int dpsw_if_get_tci(struct fsl_mc_io *mc_io,
++                  uint32_t cmd_flags,
++                  uint16_t token,
++                  uint16_t if_id,
++                  struct dpsw_tci_cfg *cfg)
++{
++      struct mc_command cmd = { 0 };
++      int err = 0;
++
++      /* prepare command */
++      cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_GET_TCI,
++                                        cmd_flags,
++                                        token);
++      DPSW_CMD_IF_GET_TCI(cmd, if_id);
++
++      /* send command to mc*/
++      err = mc_send_command(mc_io, &cmd);
++      if (err)
++              return err;
++
++      /* retrieve response parameters */
++      DPSW_RSP_IF_GET_TCI(cmd, cfg);
++
++      return 0;
++}
++
++int dpsw_if_set_stp(struct fsl_mc_io *mc_io,
++                  uint32_t cmd_flags,
++                  uint16_t token,
++                  uint16_t if_id,
++                  const struct dpsw_stp_cfg *cfg)
++{
++      struct mc_command cmd = { 0 };
++
++      /* prepare command */
++      cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_SET_STP,
++                                        cmd_flags,
++                                        token);
++      DPSW_CMD_IF_SET_STP(cmd, if_id, cfg);
++
++      /* send command to mc*/
++      return mc_send_command(mc_io, &cmd);
++}
++
++int dpsw_if_set_accepted_frames(struct fsl_mc_io *mc_io,
++                              uint32_t cmd_flags,
++                              uint16_t token,
++                              uint16_t if_id,
++                              const struct dpsw_accepted_frames_cfg *cfg)
++{
++      struct mc_command cmd = { 0 };
++
++      /* prepare command */
++      cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_SET_ACCEPTED_FRAMES,
++                                        cmd_flags,
++                                        token);
++      DPSW_CMD_IF_SET_ACCEPTED_FRAMES(cmd, if_id, cfg);
++
++      /* send command to mc*/
++      return mc_send_command(mc_io, &cmd);
++}
++
++int dpsw_if_set_accept_all_vlan(struct fsl_mc_io *mc_io,
++                              uint32_t cmd_flags,
++                              uint16_t token,
++                              uint16_t if_id,
++                              int accept_all)
++{
++      struct mc_command cmd = { 0 };
++
++      /* prepare command */
++      cmd.header = mc_encode_cmd_header(DPSW_CMDID_SET_IF_ACCEPT_ALL_VLAN,
++                                        cmd_flags,
++                                        token);
++      DPSW_CMD_IF_SET_ACCEPT_ALL_VLAN(cmd, if_id, accept_all);
++
++      /* send command to mc*/
++      return mc_send_command(mc_io, &cmd);
++}
++
++int dpsw_if_get_counter(struct fsl_mc_io *mc_io,
++                      uint32_t cmd_flags,
++                      uint16_t token,
++                      uint16_t if_id,
++                      enum dpsw_counter type,
++                      uint64_t *counter)
++{
++      struct mc_command cmd = { 0 };
++      int err;
++
++      /* prepare command */
++      cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_GET_COUNTER,
++                                        cmd_flags,
++                                        token);
++      DPSW_CMD_IF_GET_COUNTER(cmd, if_id, type);
++
++      /* send command to mc*/
++      err = mc_send_command(mc_io, &cmd);
++      if (err)
++              return err;
++
++      /* retrieve response parameters */
++      DPSW_RSP_IF_GET_COUNTER(cmd, *counter);
++
++      return 0;
++}
++
++int dpsw_if_set_counter(struct fsl_mc_io *mc_io,
++                      uint32_t cmd_flags,
++                      uint16_t token,
++                      uint16_t if_id,
++                      enum dpsw_counter type,
++                      uint64_t counter)
++{
++      struct mc_command cmd = { 0 };
++
++      /* prepare command */
++      cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_SET_COUNTER,
++                                        cmd_flags,
++                                        token);
++      DPSW_CMD_IF_SET_COUNTER(cmd, if_id, type, counter);
++
++      /* send command to mc*/
++      return mc_send_command(mc_io, &cmd);
++}
++
++int dpsw_if_set_tx_selection(struct fsl_mc_io *mc_io,
++                           uint32_t cmd_flags,
++                           uint16_t token,
++                           uint16_t if_id,
++                           const struct dpsw_tx_selection_cfg *cfg)
++{
++      struct mc_command cmd = { 0 };
++
++      /* prepare command */
++      cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_SET_TX_SELECTION,
++                                        cmd_flags,
++                                        token);
++      DPSW_CMD_IF_SET_TX_SELECTION(cmd, if_id, cfg);
++
++      /* send command to mc*/
++      return mc_send_command(mc_io, &cmd);
++}
++
++int dpsw_if_add_reflection(struct fsl_mc_io *mc_io,
++                         uint32_t cmd_flags,
++                         uint16_t token,
++                         uint16_t if_id,
++                         const struct dpsw_reflection_cfg *cfg)
++{
++      struct mc_command cmd = { 0 };
++
++      /* prepare command */
++      cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_ADD_REFLECTION,
++                                        cmd_flags,
++                                        token);
++      DPSW_CMD_IF_ADD_REFLECTION(cmd, if_id, cfg);
++
++      /* send command to mc*/
++      return mc_send_command(mc_io, &cmd);
++}
++
++int dpsw_if_remove_reflection(struct fsl_mc_io *mc_io,
++                            uint32_t cmd_flags,
++                            uint16_t token,
++                            uint16_t if_id,
++                            const struct dpsw_reflection_cfg *cfg)
++{
++      struct mc_command cmd = { 0 };
++
++      /* prepare command */
++      cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_REMOVE_REFLECTION,
++                                        cmd_flags,
++                                        token);
++      DPSW_CMD_IF_REMOVE_REFLECTION(cmd, if_id, cfg);
++
++      /* send command to mc*/
++      return mc_send_command(mc_io, &cmd);
++}
++
++int dpsw_if_set_flooding_metering(struct fsl_mc_io *mc_io,
++                                uint32_t cmd_flags,
++                                uint16_t token,
++                                uint16_t if_id,
++                                const struct dpsw_metering_cfg *cfg)
++{
++      struct mc_command cmd = { 0 };
++
++      /* prepare command */
++      cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_SET_FLOODING_METERING,
++                                        cmd_flags,
++                                        token);
++      DPSW_CMD_IF_SET_FLOODING_METERING(cmd, if_id, cfg);
++
++      /* send command to mc*/
++      return mc_send_command(mc_io, &cmd);
++}
++
++int dpsw_if_set_metering(struct fsl_mc_io *mc_io,
++                       uint32_t cmd_flags,
++                       uint16_t token,
++                       uint16_t if_id,
++                       uint8_t tc_id,
++                       const struct dpsw_metering_cfg *cfg)
++{
++      struct mc_command cmd = { 0 };
++
++      /* prepare command */
++      cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_SET_METERING,
++                                        cmd_flags,
++                                        token);
++      DPSW_CMD_IF_SET_METERING(cmd, if_id, tc_id, cfg);
++
++      /* send command to mc*/
++      return mc_send_command(mc_io, &cmd);
++}
++
++void dpsw_prepare_early_drop(const struct dpsw_early_drop_cfg *cfg,
++                           uint8_t *early_drop_buf)
++{
++      uint64_t *ext_params = (uint64_t *)early_drop_buf;
++
++      DPSW_PREP_EARLY_DROP(ext_params, cfg);
++}
++
++int dpsw_if_set_early_drop(struct fsl_mc_io   *mc_io,
++                         uint32_t             cmd_flags,
++                         uint16_t             token,
++                         uint16_t             if_id,
++                         uint8_t              tc_id,
++                         uint64_t             early_drop_iova)
++{
++      struct mc_command cmd = { 0 };
++
++      /* prepare command */
++      cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_SET_EARLY_DROP,
++                                        cmd_flags,
++                                        token);
++      DPSW_CMD_IF_SET_EARLY_DROP(cmd, if_id, tc_id, early_drop_iova);
++
++      /* send command to mc*/
++      return mc_send_command(mc_io, &cmd);
++}
++
++int dpsw_add_custom_tpid(struct fsl_mc_io *mc_io,
++                       uint32_t cmd_flags,
++                       uint16_t token,
++                       const struct dpsw_custom_tpid_cfg *cfg)
++{
++      struct mc_command cmd = { 0 };
++
++      /* prepare command */
++      cmd.header = mc_encode_cmd_header(DPSW_CMDID_ADD_CUSTOM_TPID,
++                                        cmd_flags,
++                                        token);
++      DPSW_CMD_ADD_CUSTOM_TPID(cmd, cfg);
++
++      /* send command to mc*/
++      return mc_send_command(mc_io, &cmd);
++}
++
++int dpsw_remove_custom_tpid(struct fsl_mc_io *mc_io,
++                          uint32_t cmd_flags,
++                          uint16_t token,
++                          const struct dpsw_custom_tpid_cfg *cfg)
++{
++      struct mc_command cmd = { 0 };
++
++      /* prepare command */
++      cmd.header = mc_encode_cmd_header(DPSW_CMDID_REMOVE_CUSTOM_TPID,
++                                        cmd_flags,
++                                        token);
++      DPSW_CMD_REMOVE_CUSTOM_TPID(cmd, cfg);
++
++      /* send command to mc*/
++      return mc_send_command(mc_io, &cmd);
++}
++
++int dpsw_if_enable(struct fsl_mc_io *mc_io,
++                 uint32_t cmd_flags,
++                 uint16_t token,
++                 uint16_t if_id)
++{
++      struct mc_command cmd = { 0 };
++
++      /* prepare command */
++      cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_ENABLE,
++                                        cmd_flags,
++                                        token);
++      DPSW_CMD_IF_ENABLE(cmd, if_id);
++
++      /* send command to mc*/
++      return mc_send_command(mc_io, &cmd);
++}
++
++int dpsw_if_disable(struct fsl_mc_io *mc_io,
++                  uint32_t cmd_flags,
++                  uint16_t token,
++                  uint16_t if_id)
++{
++      struct mc_command cmd = { 0 };
++
++      /* prepare command */
++      cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_DISABLE,
++                                        cmd_flags,
++                                        token);
++      DPSW_CMD_IF_DISABLE(cmd, if_id);
++
++      /* send command to mc*/
++      return mc_send_command(mc_io, &cmd);
++}
++
++int dpsw_if_get_attributes(struct fsl_mc_io *mc_io,
++                         uint32_t cmd_flags,
++                         uint16_t token,
++                         uint16_t if_id,
++                         struct dpsw_if_attr *attr)
++{
++      struct mc_command cmd = { 0 };
++      int err;
++
++      /* prepare command */
++      cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_GET_ATTR,
++                                        cmd_flags,
++                                        token);
++      DPSW_CMD_IF_GET_ATTR(cmd, if_id);
++
++      /* send command to mc*/
++      err = mc_send_command(mc_io, &cmd);
++      if (err)
++              return err;
++
++      /* retrieve response parameters */
++      DPSW_RSP_IF_GET_ATTR(cmd, attr);
++
++      return 0;
++}
++
++int dpsw_if_set_max_frame_length(struct fsl_mc_io *mc_io,
++                               uint32_t cmd_flags,
++                               uint16_t token,
++                               uint16_t if_id,
++                               uint16_t frame_length)
++{
++      struct mc_command cmd = { 0 };
++
++      /* prepare command */
++      cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_SET_MAX_FRAME_LENGTH,
++                                        cmd_flags,
++                                        token);
++      DPSW_CMD_IF_SET_MAX_FRAME_LENGTH(cmd, if_id, frame_length);
++
++      /* send command to mc*/
++      return mc_send_command(mc_io, &cmd);
++}
++
++int dpsw_if_get_max_frame_length(struct fsl_mc_io *mc_io,
++                               uint32_t cmd_flags,
++                               uint16_t token,
++                               uint16_t if_id,
++                               uint16_t *frame_length)
++{
++      struct mc_command cmd = { 0 };
++      int err;
++
++      /* prepare command */
++      cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_GET_MAX_FRAME_LENGTH,
++                                        cmd_flags,
++                                        token);
++      DPSW_CMD_IF_GET_MAX_FRAME_LENGTH(cmd, if_id);
++
++      /* send command to mc*/
++      err = mc_send_command(mc_io, &cmd);
++      if (err)
++              return err;
++
++      DPSW_RSP_IF_GET_MAX_FRAME_LENGTH(cmd, *frame_length);
++
++      return 0;
++}
++
++int dpsw_vlan_add(struct fsl_mc_io *mc_io,
++                uint32_t cmd_flags,
++                uint16_t token,
++                uint16_t vlan_id,
++                const struct dpsw_vlan_cfg *cfg)
++{
++      struct mc_command cmd = { 0 };
++
++      /* prepare command */
++      cmd.header = mc_encode_cmd_header(DPSW_CMDID_VLAN_ADD,
++                                        cmd_flags,
++                                        token);
++      DPSW_CMD_VLAN_ADD(cmd, vlan_id, cfg);
++
++      /* send command to mc*/
++      return mc_send_command(mc_io, &cmd);
++}
++
++int dpsw_vlan_add_if(struct fsl_mc_io *mc_io,
++                   uint32_t cmd_flags,
++                   uint16_t token,
++                   uint16_t vlan_id,
++                   const struct dpsw_vlan_if_cfg *cfg)
++{
++      struct mc_command cmd = { 0 };
++
++      /* prepare command */
++      build_if_id_bitmap(cfg->if_id, cfg->num_ifs, &cmd, 1);
++      cmd.header = mc_encode_cmd_header(DPSW_CMDID_VLAN_ADD_IF,
++                                        cmd_flags,
++                                        token);
++      DPSW_CMD_VLAN_ADD_IF(cmd, vlan_id);
++
++      /* send command to mc*/
++      return mc_send_command(mc_io, &cmd);
++}
++
++int dpsw_vlan_add_if_untagged(struct fsl_mc_io *mc_io,
++                            uint32_t cmd_flags,
++                            uint16_t token,
++                            uint16_t vlan_id,
++                            const struct dpsw_vlan_if_cfg *cfg)
++{
++      struct mc_command cmd = { 0 };
++
++      /* prepare command */
++      build_if_id_bitmap(cfg->if_id, cfg->num_ifs, &cmd, 1);
++      cmd.header = mc_encode_cmd_header(DPSW_CMDID_VLAN_ADD_IF_UNTAGGED,
++                                        cmd_flags,
++                                        token);
++      DPSW_CMD_VLAN_ADD_IF_UNTAGGED(cmd, vlan_id);
++
++      /* send command to mc*/
++      return mc_send_command(mc_io, &cmd);
++}
++
++int dpsw_vlan_add_if_flooding(struct fsl_mc_io *mc_io,
++                            uint32_t cmd_flags,
++                            uint16_t token,
++                            uint16_t vlan_id,
++                            const struct dpsw_vlan_if_cfg *cfg)
++{
++      struct mc_command cmd = { 0 };
++
++      /* prepare command */
++      build_if_id_bitmap(cfg->if_id, cfg->num_ifs, &cmd, 1);
++      cmd.header = mc_encode_cmd_header(DPSW_CMDID_VLAN_ADD_IF_FLOODING,
++                                        cmd_flags,
++                                        token);
++      DPSW_CMD_VLAN_ADD_IF_FLOODING(cmd, vlan_id);
++
++      /* send command to mc*/
++      return mc_send_command(mc_io, &cmd);
++}
++
++int dpsw_vlan_remove_if(struct fsl_mc_io *mc_io,
++                      uint32_t cmd_flags,
++                      uint16_t token,
++                      uint16_t vlan_id,
++                      const struct dpsw_vlan_if_cfg *cfg)
++{
++      struct mc_command cmd = { 0 };
++
++      /* prepare command */
++      build_if_id_bitmap(cfg->if_id, cfg->num_ifs, &cmd, 1);
++      cmd.header = mc_encode_cmd_header(DPSW_CMDID_VLAN_REMOVE_IF,
++                                        cmd_flags,
++                                        token);
++      DPSW_CMD_VLAN_REMOVE_IF(cmd, vlan_id);
++
++      /* send command to mc*/
++      return mc_send_command(mc_io, &cmd);
++}
++
++int dpsw_vlan_remove_if_untagged(struct fsl_mc_io *mc_io,
++                               uint32_t cmd_flags,
++                               uint16_t token,
++                               uint16_t vlan_id,
++                               const struct dpsw_vlan_if_cfg *cfg)
++{
++      struct mc_command cmd = { 0 };
++
++      /* prepare command */
++      build_if_id_bitmap(cfg->if_id, cfg->num_ifs, &cmd, 1);
++      cmd.header = mc_encode_cmd_header(DPSW_CMDID_VLAN_REMOVE_IF_UNTAGGED,
++                                        cmd_flags,
++                                        token);
++      DPSW_CMD_VLAN_REMOVE_IF_UNTAGGED(cmd, vlan_id);
++
++      /* send command to mc*/
++      return mc_send_command(mc_io, &cmd);
++}
++
++int dpsw_vlan_remove_if_flooding(struct fsl_mc_io *mc_io,
++                               uint32_t cmd_flags,
++                               uint16_t token,
++                               uint16_t vlan_id,
++                               const struct dpsw_vlan_if_cfg *cfg)
++{
++      struct mc_command cmd = { 0 };
++
++      /* prepare command */
++      build_if_id_bitmap(cfg->if_id, cfg->num_ifs, &cmd, 1);
++      cmd.header = mc_encode_cmd_header(DPSW_CMDID_VLAN_REMOVE_IF_FLOODING,
++                                        cmd_flags,
++                                        token);
++      DPSW_CMD_VLAN_REMOVE_IF_FLOODING(cmd, vlan_id);
++
++      /* send command to mc*/
++      return mc_send_command(mc_io, &cmd);
++}
++
++int dpsw_vlan_remove(struct fsl_mc_io *mc_io,
++                   uint32_t cmd_flags,
++                   uint16_t token,
++                   uint16_t vlan_id)
++{
++      struct mc_command cmd = { 0 };
++
++      /* prepare command */
++      cmd.header = mc_encode_cmd_header(DPSW_CMDID_VLAN_REMOVE,
++                                        cmd_flags,
++                                        token);
++      DPSW_CMD_VLAN_REMOVE(cmd, vlan_id);
++
++      /* send command to mc*/
++      return mc_send_command(mc_io, &cmd);
++}
++
++int dpsw_vlan_get_attributes(struct fsl_mc_io *mc_io,
++                           uint32_t cmd_flags,
++                           uint16_t token,
++                           uint16_t vlan_id,
++                           struct dpsw_vlan_attr *attr)
++{
++      struct mc_command cmd = { 0 };
++      int err;
++
++      /* prepare command */
++      cmd.header = mc_encode_cmd_header(DPSW_CMDID_VLAN_GET_ATTRIBUTES,
++                                        cmd_flags,
++                                        token);
++      DPSW_CMD_VLAN_GET_ATTR(cmd, vlan_id);
++
++      /* send command to mc*/
++      err = mc_send_command(mc_io, &cmd);
++      if (err)
++              return err;
++
++      /* retrieve response parameters */
++      DPSW_RSP_VLAN_GET_ATTR(cmd, attr);
++
++      return 0;
++}
++
++int dpsw_vlan_get_if(struct fsl_mc_io *mc_io,
++                   uint32_t cmd_flags,
++                   uint16_t token,
++                   uint16_t vlan_id,
++                   struct dpsw_vlan_if_cfg *cfg)
++{
++      struct mc_command cmd = { 0 };
++      int err;
++
++      /* prepare command */
++      cmd.header = mc_encode_cmd_header(DPSW_CMDID_VLAN_GET_IF,
++                                        cmd_flags,
++                                        token);
++      DPSW_CMD_VLAN_GET_IF(cmd, vlan_id);
++
++      /* send command to mc*/
++      err = mc_send_command(mc_io, &cmd);
++      if (err)
++              return err;
++
++      /* retrieve response parameters */
++      DPSW_RSP_VLAN_GET_IF(cmd, cfg);
++      read_if_id_bitmap(cfg->if_id, &cfg->num_ifs, &cmd, 1);
++
++      return 0;
++}
++
++int dpsw_vlan_get_if_flooding(struct fsl_mc_io *mc_io,
++                            uint32_t cmd_flags,
++                            uint16_t token,
++                            uint16_t vlan_id,
++                            struct dpsw_vlan_if_cfg *cfg)
++{
++      struct mc_command cmd = { 0 };
++      int err;
++
++      /* prepare command */
++      cmd.header = mc_encode_cmd_header(DPSW_CMDID_VLAN_GET_IF_FLOODING,
++                                        cmd_flags,
++                                        token);
++      DPSW_CMD_VLAN_GET_IF_FLOODING(cmd, vlan_id);
++
++      /* send command to mc*/
++      err = mc_send_command(mc_io, &cmd);
++      if (err)
++              return err;
++
++      /* retrieve response parameters */
++      DPSW_RSP_VLAN_GET_IF_FLOODING(cmd, cfg);
++      read_if_id_bitmap(cfg->if_id, &cfg->num_ifs, &cmd, 1);
++
++      return 0;
++}
++
++int dpsw_vlan_get_if_untagged(struct fsl_mc_io *mc_io,
++                            uint32_t cmd_flags,
++                            uint16_t token,
++                            uint16_t vlan_id,
++                            struct dpsw_vlan_if_cfg *cfg)
++{
++      struct mc_command cmd = { 0 };
++      int err;
++
++      /* prepare command */
++      cmd.header = mc_encode_cmd_header(DPSW_CMDID_VLAN_GET_IF_UNTAGGED,
++                                        cmd_flags,
++                                        token);
++      DPSW_CMD_VLAN_GET_IF_UNTAGGED(cmd, vlan_id);
++
++      /* send command to mc*/
++      err = mc_send_command(mc_io, &cmd);
++      if (err)
++              return err;
++
++      /* retrieve response parameters */
++      DPSW_RSP_VLAN_GET_IF(cmd, cfg);
++      read_if_id_bitmap(cfg->if_id, &cfg->num_ifs, &cmd, 1);
++
++      return 0;
++}
++
++int dpsw_fdb_add(struct fsl_mc_io *mc_io,
++               uint32_t cmd_flags,
++               uint16_t token,
++               uint16_t *fdb_id,
++               const struct dpsw_fdb_cfg *cfg)
++{
++      struct mc_command cmd = { 0 };
++      int err;
++
++      /* prepare command */
++      cmd.header = mc_encode_cmd_header(DPSW_CMDID_FDB_ADD,
++                                        cmd_flags,
++                                        token);
++      DPSW_CMD_FDB_ADD(cmd, cfg);
++
++      /* send command to mc*/
++      err = mc_send_command(mc_io, &cmd);
++      if (err)
++              return err;
++
++      /* retrieve response parameters */
++      DPSW_RSP_FDB_ADD(cmd, *fdb_id);
++
++      return 0;
++}
++
++int dpsw_fdb_remove(struct fsl_mc_io *mc_io,
++                  uint32_t cmd_flags,
++                  uint16_t token,
++                  uint16_t fdb_id)
++{
++      struct mc_command cmd = { 0 };
++
++      /* prepare command */
++      cmd.header = mc_encode_cmd_header(DPSW_CMDID_FDB_REMOVE,
++                                        cmd_flags,
++                                        token);
++      DPSW_CMD_FDB_REMOVE(cmd, fdb_id);
++
++      /* send command to mc*/
++      return mc_send_command(mc_io, &cmd);
++}
++
++int dpsw_fdb_add_unicast(struct fsl_mc_io *mc_io,
++                       uint32_t cmd_flags,
++                       uint16_t token,
++                       uint16_t fdb_id,
++                       const struct dpsw_fdb_unicast_cfg *cfg)
++{
++      struct mc_command cmd = { 0 };
++
++      /* prepare command */
++      cmd.header = mc_encode_cmd_header(DPSW_CMDID_FDB_ADD_UNICAST,
++                                        cmd_flags,
++                                        token);
++      DPSW_CMD_FDB_ADD_UNICAST(cmd, fdb_id, cfg);
++
++      /* send command to mc*/
++      return mc_send_command(mc_io, &cmd);
++}
++
++int dpsw_fdb_get_unicast(struct fsl_mc_io *mc_io,
++                       uint32_t cmd_flags,
++                       uint16_t token,
++                       uint16_t fdb_id,
++                       struct dpsw_fdb_unicast_cfg *cfg)
++{
++      struct mc_command cmd = { 0 };
++      int err;
++
++      /* prepare command */
++      cmd.header = mc_encode_cmd_header(DPSW_CMDID_FDB_GET_UNICAST,
++                                        cmd_flags,
++                                        token);
++      DPSW_CMD_FDB_GET_UNICAST(cmd, fdb_id);
++
++      /* send command to mc*/
++      err = mc_send_command(mc_io, &cmd);
++      if (err)
++              return err;
++
++      /* retrieve response parameters */
++      DPSW_RSP_FDB_GET_UNICAST(cmd, cfg);
++
++      return 0;
++}
++
++int dpsw_fdb_remove_unicast(struct fsl_mc_io *mc_io,
++                          uint32_t cmd_flags,
++                          uint16_t token,
++                          uint16_t fdb_id,
++                          const struct dpsw_fdb_unicast_cfg *cfg)
++{
++      struct mc_command cmd = { 0 };
++
++      /* prepare command */
++      cmd.header = mc_encode_cmd_header(DPSW_CMDID_FDB_REMOVE_UNICAST,
++                                        cmd_flags,
++                                        token);
++      DPSW_CMD_FDB_REMOVE_UNICAST(cmd, fdb_id, cfg);
++
++      /* send command to mc*/
++      return mc_send_command(mc_io, &cmd);
++}
++
++int dpsw_fdb_add_multicast(struct fsl_mc_io *mc_io,
++                         uint32_t cmd_flags,
++                         uint16_t token,
++                         uint16_t fdb_id,
++                         const struct dpsw_fdb_multicast_cfg *cfg)
++{
++      struct mc_command cmd = { 0 };
++
++      /* prepare command */
++      build_if_id_bitmap(cfg->if_id, cfg->num_ifs, &cmd, 2);
++      cmd.header = mc_encode_cmd_header(DPSW_CMDID_FDB_ADD_MULTICAST,
++                                        cmd_flags,
++                                        token);
++      DPSW_CMD_FDB_ADD_MULTICAST(cmd, fdb_id, cfg);
++
++      /* send command to mc*/
++      return mc_send_command(mc_io, &cmd);
++}
++
++int dpsw_fdb_get_multicast(struct fsl_mc_io *mc_io,
++                         uint32_t cmd_flags,
++                         uint16_t token,
++                         uint16_t fdb_id,
++                         struct dpsw_fdb_multicast_cfg *cfg)
++{
++      struct mc_command cmd = { 0 };
++      int err;
++
++      /* prepare command */
++      cmd.header = mc_encode_cmd_header(DPSW_CMDID_FDB_GET_MULTICAST,
++                                        cmd_flags,
++                                        token);
++      DPSW_CMD_FDB_GET_MULTICAST(cmd, fdb_id);
++
++      /* send command to mc*/
++      err = mc_send_command(mc_io, &cmd);
++      if (err)
++              return err;
++
++      /* retrieve response parameters */
++      DPSW_RSP_FDB_GET_MULTICAST(cmd, cfg);
++      read_if_id_bitmap(cfg->if_id, &cfg->num_ifs, &cmd, 2);
++
++      return 0;
++}
++
++int dpsw_fdb_remove_multicast(struct fsl_mc_io *mc_io,
++                            uint32_t cmd_flags,
++                            uint16_t token,
++                            uint16_t fdb_id,
++                            const struct dpsw_fdb_multicast_cfg *cfg)
++{
++      struct mc_command cmd = { 0 };
++
++      /* prepare command */
++      build_if_id_bitmap(cfg->if_id, cfg->num_ifs, &cmd, 2);
++      cmd.header = mc_encode_cmd_header(DPSW_CMDID_FDB_REMOVE_MULTICAST,
++                                        cmd_flags,
++                                        token);
++      DPSW_CMD_FDB_REMOVE_MULTICAST(cmd, fdb_id, cfg);
++
++      /* send command to mc*/
++      return mc_send_command(mc_io, &cmd);
++}
++
++int dpsw_fdb_set_learning_mode(struct fsl_mc_io *mc_io,
++                             uint32_t cmd_flags,
++                             uint16_t token,
++                             uint16_t fdb_id,
++                             enum dpsw_fdb_learning_mode mode)
++{
++      struct mc_command cmd = { 0 };
++
++      /* prepare command */
++      cmd.header = mc_encode_cmd_header(DPSW_CMDID_FDB_SET_LEARNING_MODE,
++                                        cmd_flags,
++                                        token);
++      DPSW_CMD_FDB_SET_LEARNING_MODE(cmd, fdb_id, mode);
++
++      /* send command to mc*/
++      return mc_send_command(mc_io, &cmd);
++}
++
++int dpsw_fdb_get_attributes(struct fsl_mc_io *mc_io,
++                          uint32_t cmd_flags,
++                          uint16_t token,
++                          uint16_t fdb_id,
++                          struct dpsw_fdb_attr *attr)
++{
++      struct mc_command cmd = { 0 };
++      int err;
++
++      /* prepare command */
++      cmd.header = mc_encode_cmd_header(DPSW_CMDID_FDB_GET_ATTR,
++                                        cmd_flags,
++                                        token);
++      DPSW_CMD_FDB_GET_ATTR(cmd, fdb_id);
++
++      /* send command to mc*/
++      err = mc_send_command(mc_io, &cmd);
++      if (err)
++              return err;
++
++      /* retrieve response parameters */
++      DPSW_RSP_FDB_GET_ATTR(cmd, attr);
++
++      return 0;
++}
++
++int dpsw_acl_add(struct fsl_mc_io *mc_io,
++               uint32_t cmd_flags,
++               uint16_t token,
++               uint16_t *acl_id,
++               const struct dpsw_acl_cfg  *cfg)
++{
++      struct mc_command cmd = { 0 };
++      int err;
++
++      /* prepare command */
++      cmd.header = mc_encode_cmd_header(DPSW_CMDID_ACL_ADD,
++                                        cmd_flags,
++                                        token);
++      DPSW_CMD_ACL_ADD(cmd, cfg);
++
++      /* send command to mc*/
++      err = mc_send_command(mc_io, &cmd);
++      if (err)
++              return err;
++
++      /* retrieve response parameters */
++      DPSW_RSP_ACL_ADD(cmd, *acl_id);
++
++      return 0;
++}
++
++int dpsw_acl_remove(struct fsl_mc_io *mc_io,
++                  uint32_t cmd_flags,
++                  uint16_t token,
++                  uint16_t acl_id)
++{
++      struct mc_command cmd = { 0 };
++
++      /* prepare command */
++      cmd.header = mc_encode_cmd_header(DPSW_CMDID_ACL_REMOVE,
++                                        cmd_flags,
++                                        token);
++      DPSW_CMD_ACL_REMOVE(cmd, acl_id);
++
++      /* send command to mc*/
++      return mc_send_command(mc_io, &cmd);
++}
++
++void dpsw_acl_prepare_entry_cfg(const struct dpsw_acl_key *key,
++                              uint8_t *entry_cfg_buf)
++{
++      uint64_t *ext_params = (uint64_t *)entry_cfg_buf;
++
++      DPSW_PREP_ACL_ENTRY(ext_params, key);
++}
++
++int dpsw_acl_add_entry(struct fsl_mc_io *mc_io,
++                     uint32_t cmd_flags,
++                     uint16_t token,
++                     uint16_t acl_id,
++                     const struct dpsw_acl_entry_cfg *cfg)
++{
++      struct mc_command cmd = { 0 };
++
++      /* prepare command */
++      cmd.header = mc_encode_cmd_header(DPSW_CMDID_ACL_ADD_ENTRY,
++                                        cmd_flags,
++                                        token);
++      DPSW_CMD_ACL_ADD_ENTRY(cmd, acl_id, cfg);
++
++      /* send command to mc*/
++      return mc_send_command(mc_io, &cmd);
++}
++
++int dpsw_acl_remove_entry(struct fsl_mc_io *mc_io,
++                        uint32_t cmd_flags,
++                        uint16_t token,
++                        uint16_t acl_id,
++                        const struct dpsw_acl_entry_cfg *cfg)
++{
++      struct mc_command cmd = { 0 };
++
++      /* prepare command */
++      cmd.header = mc_encode_cmd_header(DPSW_CMDID_ACL_REMOVE_ENTRY,
++                                        cmd_flags,
++                                        token);
++      DPSW_CMD_ACL_REMOVE_ENTRY(cmd, acl_id, cfg);
++
++      /* send command to mc*/
++      return mc_send_command(mc_io, &cmd);
++}
++
++int dpsw_acl_add_if(struct fsl_mc_io *mc_io,
++                  uint32_t cmd_flags,
++                  uint16_t token,
++                  uint16_t acl_id,
++                  const struct dpsw_acl_if_cfg *cfg)
++{
++      struct mc_command cmd = { 0 };
++
++      /* prepare command */
++      build_if_id_bitmap(cfg->if_id, cfg->num_ifs, &cmd, 1);
++      cmd.header = mc_encode_cmd_header(DPSW_CMDID_ACL_ADD_IF,
++                                        cmd_flags,
++                                        token);
++      DPSW_CMD_ACL_ADD_IF(cmd, acl_id, cfg);
++
++      /* send command to mc*/
++      return mc_send_command(mc_io, &cmd);
++}
++
++int dpsw_acl_remove_if(struct fsl_mc_io *mc_io,
++                     uint32_t cmd_flags,
++                     uint16_t token,
++                     uint16_t acl_id,
++                     const struct dpsw_acl_if_cfg *cfg)
++{
++      struct mc_command cmd = { 0 };
++
++      /* prepare command */
++      build_if_id_bitmap(cfg->if_id, cfg->num_ifs, &cmd, 1);
++      cmd.header = mc_encode_cmd_header(DPSW_CMDID_ACL_REMOVE_IF,
++                                        cmd_flags,
++                                        token);
++      DPSW_CMD_ACL_REMOVE_IF(cmd, acl_id, cfg);
++
++      /* send command to mc*/
++      return mc_send_command(mc_io, &cmd);
++}
++
++int dpsw_acl_get_attributes(struct fsl_mc_io          *mc_io,
++                          uint32_t                    cmd_flags,
++                          uint16_t                    token,
++                          uint16_t                    acl_id,
++                          struct dpsw_acl_attr        *attr)
++{
++      struct mc_command cmd = { 0 };
++      int err;
++
++      /* prepare command */
++      cmd.header = mc_encode_cmd_header(DPSW_CMDID_ACL_GET_ATTR,
++                                        cmd_flags,
++                                        token);
++      DPSW_CMD_ACL_GET_ATTR(cmd, acl_id);
++
++      /* send command to mc*/
++      err = mc_send_command(mc_io, &cmd);
++      if (err)
++              return err;
++
++      /* retrieve response parameters */
++      DPSW_RSP_ACL_GET_ATTR(cmd, attr);
++
++      return 0;
++}
++
++int dpsw_ctrl_if_get_attributes(struct fsl_mc_io              *mc_io,
++                              uint32_t                        cmd_flags,
++                              uint16_t                        token,
++                              struct dpsw_ctrl_if_attr        *attr)
++{
++      struct mc_command cmd = { 0 };
++      int err;
++
++      /* prepare command */
++      cmd.header = mc_encode_cmd_header(DPSW_CMDID_CTRL_IF_GET_ATTR,
++                                        cmd_flags,
++                                        token);
++
++      /* send command to mc*/
++      err = mc_send_command(mc_io, &cmd);
++      if (err)
++              return err;
++
++      /* retrieve response parameters */
++      DPSW_RSP_CTRL_IF_GET_ATTR(cmd, attr);
++
++      return 0;
++}
++
++int dpsw_ctrl_if_set_pools(struct fsl_mc_io                   *mc_io,
++                         uint32_t                             cmd_flags,
++                         uint16_t                             token,
++                         const struct dpsw_ctrl_if_pools_cfg *pools)
++{
++      struct mc_command cmd = { 0 };
++
++      /* prepare command */
++      cmd.header = mc_encode_cmd_header(DPSW_CMDID_CTRL_IF_SET_POOLS,
++                                        cmd_flags,
++                                        token);
++      DPSW_CMD_CTRL_IF_SET_POOLS(cmd, pools);
++
++      /* send command to mc*/
++      return mc_send_command(mc_io, &cmd);
++}
++
++int dpsw_ctrl_if_enable(struct fsl_mc_io      *mc_io,
++                      uint32_t                cmd_flags,
++                      uint16_t                token)
++{
++      struct mc_command cmd = { 0 };
++
++      /* prepare command */
++      cmd.header = mc_encode_cmd_header(DPSW_CMDID_CTRL_IF_ENABLE,
++                                        cmd_flags,
++                                        token);
++
++      /* send command to mc*/
++      return mc_send_command(mc_io, &cmd);
++}
++
++/**
++* @brief    Function disables control interface
++* @mc_io:     Pointer to MC portal's I/O object
++* @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
++* @token:     Token of DPSW object
++*
++* Return:     '0' on Success; Error code otherwise.
++*/
++int dpsw_ctrl_if_disable(struct fsl_mc_io     *mc_io,
++                       uint32_t               cmd_flags,
++                       uint16_t               token)
++{
++      struct mc_command cmd = { 0 };
++
++      /* prepare command */
++      cmd.header = mc_encode_cmd_header(DPSW_CMDID_CTRL_IF_DISABLE,
++                                        cmd_flags,
++                                        token);
++
++      /* send command to mc*/
++      return mc_send_command(mc_io, &cmd);
++}
+--- /dev/null
++++ b/drivers/staging/fsl-dpaa2/ethsw/dpsw.h
+@@ -0,0 +1,2164 @@
++/* Copyright 2013-2015 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 the above-listed copyright holders nor the
++ * names of any contributors may be used to endorse or promote products
++ * derived from this software without specific prior written permission.
++ *
++ *
++ * ALTERNATIVELY, this software may be distributed under the terms of the
++ * GNU General Public License ("GPL") as published by the Free Software
++ * Foundation, either version 2 of that License or (at your option) any
++ * later version.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
++ * POSSIBILITY OF SUCH DAMAGE.
++ */
++#ifndef __FSL_DPSW_H
++#define __FSL_DPSW_H
++
++#include "../../fsl-mc/include/net.h"
++
++/* Data Path L2-Switch API
++ * Contains API for handling DPSW topology and functionality
++ */
++
++struct fsl_mc_io;
++
++/**
++ * DPSW general definitions
++ */
++
++/**
++ * Maximum number of traffic class priorities
++ */
++#define DPSW_MAX_PRIORITIES   8
++/**
++ * Maximum number of interfaces
++ */
++#define DPSW_MAX_IF           64
++
++/**
++ * dpsw_open() - Open a control session for the specified object
++ * @mc_io:    Pointer to MC portal's I/O object
++ * @cmd_flags:        Command flags; one or more of 'MC_CMD_FLAG_'
++ * @dpsw_id:  DPSW unique ID
++ * @token:    Returned token; use in subsequent API calls
++ *
++ * This function can be used to open a control session for an
++ * already created object; an object may have been declared in
++ * the DPL or by calling the dpsw_create() function.
++ * This function returns a unique authentication token,
++ * associated with the specific object ID and the specific MC
++ * portal; this token must be used in all subsequent commands for
++ * this specific object
++ *
++ * Return:    '0' on Success; Error code otherwise.
++ */
++int dpsw_open(struct fsl_mc_io        *mc_io,
++            uint32_t          cmd_flags,
++            int               dpsw_id,
++            uint16_t          *token);
++
++/**
++ * dpsw_close() - Close the control session of the object
++ * @mc_io:    Pointer to MC portal's I/O object
++ * @cmd_flags:        Command flags; one or more of 'MC_CMD_FLAG_'
++ * @token:    Token of DPSW object
++ *
++ * After this function is called, no further operations are
++ * allowed on the object without opening a new control session.
++ *
++ * Return:    '0' on Success; Error code otherwise.
++ */
++int dpsw_close(struct fsl_mc_io *mc_io,
++             uint32_t cmd_flags,
++             uint16_t token);
++
++/**
++ * DPSW options
++ */
++
++/**
++ * Disable flooding
++ */
++#define DPSW_OPT_FLOODING_DIS         0x0000000000000001ULL
++/**
++ * Disable Multicast
++ */
++#define DPSW_OPT_MULTICAST_DIS                0x0000000000000004ULL
++/**
++ * Support control interface
++ */
++#define DPSW_OPT_CTRL_IF_DIS          0x0000000000000010ULL
++/**
++ * Disable flooding metering
++ */
++#define DPSW_OPT_FLOODING_METERING_DIS  0x0000000000000020ULL
++/**
++ * Enable metering
++ */
++#define DPSW_OPT_METERING_EN            0x0000000000000040ULL
++
++/**
++ * enum dpsw_component_type - component type of a bridge
++ * @DPSW_COMPONENT_TYPE_C_VLAN: A C-VLAN component of an
++ *   enterprise VLAN bridge or of a Provider Bridge used
++ *   to process C-tagged frames
++ * @DPSW_COMPONENT_TYPE_S_VLAN: An S-VLAN component of a
++ *   Provider Bridge
++ *
++ */
++enum dpsw_component_type {
++      DPSW_COMPONENT_TYPE_C_VLAN = 0,
++      DPSW_COMPONENT_TYPE_S_VLAN
++};
++
++/**
++ * struct dpsw_cfg - DPSW configuration
++ * @num_ifs: Number of external and internal interfaces
++ * @adv: Advanced parameters; default is all zeros;
++ *             use this structure to change default settings
++ */
++struct dpsw_cfg {
++      uint16_t                num_ifs;
++      /**
++       * struct adv - Advanced parameters
++       * @options: Enable/Disable DPSW features (bitmap)
++       * @max_vlans: Maximum Number of VLAN's; 0 - indicates default 16
++       * @max_meters_per_if: Number of meters per interface
++       * @max_fdbs: Maximum Number of FDB's; 0 - indicates default 16
++       * @max_fdb_entries: Number of FDB entries for default FDB table;
++       *                      0 - indicates default 1024 entries.
++       * @fdb_aging_time: Default FDB aging time for default FDB table;
++       *                      0 - indicates default 300 seconds
++       * @max_fdb_mc_groups: Number of multicast groups in each FDB table;
++       *                      0 - indicates default 32
++       * @component_type: Indicates the component type of this bridge
++       */
++      struct {
++              uint64_t        options;
++              uint16_t        max_vlans;
++              uint8_t max_meters_per_if;
++              uint8_t max_fdbs;
++              uint16_t        max_fdb_entries;
++              uint16_t        fdb_aging_time;
++              uint16_t        max_fdb_mc_groups;
++              enum dpsw_component_type component_type;
++      } adv;
++};
++
++/**
++ * dpsw_create() - Create the DPSW object.
++ * @mc_io:    Pointer to MC portal's I/O object
++ * @cmd_flags:        Command flags; one or more of 'MC_CMD_FLAG_'
++ * @cfg:      Configuration structure
++ * @token:    Returned token; use in subsequent API calls
++ *
++ * Create the DPSW object, allocate required resources and
++ * perform required initialization.
++ *
++ * The object can be created either by declaring it in the
++ * DPL file, or by calling this function.
++ *
++ * This function returns a unique authentication token,
++ * associated with the specific object ID and the specific MC
++ * portal; this token must be used in all subsequent calls to
++ * this specific object. For objects that are created using the
++ * DPL file, call dpsw_open() function to get an authentication
++ * token first
++ *
++ * Return:    '0' on Success; Error code otherwise.
++ */
++int dpsw_create(struct fsl_mc_io      *mc_io,
++              uint32_t                cmd_flags,
++              const struct dpsw_cfg   *cfg,
++              uint16_t                *token);
++
++/**
++ * dpsw_destroy() - Destroy the DPSW object and release all its resources.
++ * @mc_io:    Pointer to MC portal's I/O object
++ * @cmd_flags:        Command flags; one or more of 'MC_CMD_FLAG_'
++ * @token:    Token of DPSW object
++ *
++ * Return:    '0' on Success; error code otherwise.
++ */
++int dpsw_destroy(struct fsl_mc_io     *mc_io,
++               uint32_t               cmd_flags,
++               uint16_t               token);
++
++/**
++ * dpsw_enable() - Enable DPSW functionality
++ * @mc_io:    Pointer to MC portal's I/O object
++ * @cmd_flags:        Command flags; one or more of 'MC_CMD_FLAG_'
++ * @token:            Token of DPSW object
++ *
++ * Return:    Completion status. '0' on Success; Error code otherwise.
++ */
++int dpsw_enable(struct fsl_mc_io      *mc_io,
++              uint32_t                cmd_flags,
++              uint16_t                token);
++
++/**
++ * dpsw_disable() - Disable DPSW functionality
++ * @mc_io:    Pointer to MC portal's I/O object
++ * @cmd_flags:        Command flags; one or more of 'MC_CMD_FLAG_'
++ * @token:            Token of DPSW object
++ *
++ * Return:    Completion status. '0' on Success; Error code otherwise.
++ */
++int dpsw_disable(struct fsl_mc_io     *mc_io,
++               uint32_t               cmd_flags,
++               uint16_t               token);
++
++/**
++ * dpsw_is_enabled() - Check if the DPSW is enabled
++ *
++ * @mc_io:    Pointer to MC portal's I/O object
++ * @cmd_flags:        Command flags; one or more of 'MC_CMD_FLAG_'
++ * @token:    Token of DPSW object
++ * @en:               Returns '1' if object is enabled; '0' otherwise
++ *
++ * Return:    '0' on Success; Error code otherwise
++ */
++int dpsw_is_enabled(struct fsl_mc_io  *mc_io,
++                  uint32_t            cmd_flags,
++                  uint16_t            token,
++                  int         *en);
++
++/**
++ * dpsw_reset() - Reset the DPSW, returns the object to initial state.
++ * @mc_io:    Pointer to MC portal's I/O object
++ * @cmd_flags:        Command flags; one or more of 'MC_CMD_FLAG_'
++ * @token:    Token of DPSW object
++ *
++ * Return:    '0' on Success; Error code otherwise.
++ */
++int dpsw_reset(struct fsl_mc_io *mc_io,
++             uint32_t cmd_flags,
++             uint16_t token);
++
++/**
++ * DPSW IRQ Index and Events
++ */
++
++#define DPSW_IRQ_INDEX_IF             0x0000
++#define DPSW_IRQ_INDEX_L2SW           0x0001
++
++/**
++ * IRQ event - Indicates that the link state changed
++ */
++#define DPSW_IRQ_EVENT_LINK_CHANGED   0x0001
++
++/**
++ * struct dpsw_irq_cfg - IRQ configuration
++ * @addr:     Address that must be written to signal a message-based interrupt
++ * @val:      Value to write into irq_addr address
++ * @irq_num: A user defined number associated with this IRQ
++ */
++struct dpsw_irq_cfg {
++           uint64_t           addr;
++           uint32_t           val;
++           int                irq_num;
++};
++
++/**
++ * dpsw_set_irq() - Set IRQ information for the DPSW to trigger an interrupt.
++ * @mc_io:    Pointer to MC portal's I/O object
++ * @cmd_flags:        Command flags; one or more of 'MC_CMD_FLAG_'
++ * @token:    Token of DPSW object
++ * @irq_index:        Identifies the interrupt index to configure
++ * @irq_cfg:  IRQ configuration
++ *
++ * Return:    '0' on Success; Error code otherwise.
++ */
++int dpsw_set_irq(struct fsl_mc_io     *mc_io,
++               uint32_t               cmd_flags,
++               uint16_t               token,
++               uint8_t                irq_index,
++               struct dpsw_irq_cfg    *irq_cfg);
++
++/**
++ * dpsw_get_irq() - Get IRQ information from the DPSW
++ *
++ * @mc_io:    Pointer to MC portal's I/O object
++ * @cmd_flags:        Command flags; one or more of 'MC_CMD_FLAG_'
++ * @token:    Token of DPSW object
++ * @irq_index:        The interrupt index to configure
++ * @type:     Interrupt type: 0 represents message interrupt
++ *            type (both irq_addr and irq_val are valid)
++ * @irq_cfg:  IRQ attributes
++ *
++ * Return:    '0' on Success; Error code otherwise.
++ */
++int dpsw_get_irq(struct fsl_mc_io     *mc_io,
++               uint32_t               cmd_flags,
++               uint16_t               token,
++               uint8_t                irq_index,
++               int                    *type,
++               struct dpsw_irq_cfg    *irq_cfg);
++
++/**
++ * dpsw_set_irq_enable() - Set overall interrupt state.
++ * @mc_io:    Pointer to MC portal's I/O object
++ * @cmd_flags:        Command flags; one or more of 'MC_CMD_FLAG_'
++ * @token:            Token of DPCI object
++ * @irq_index:        The interrupt index to configure
++ * @en:                       Interrupt state - enable = 1, disable = 0
++ *
++ * Allows GPP software to control when interrupts are generated.
++ * Each interrupt can have up to 32 causes.  The enable/disable control's the
++ * overall interrupt state. if the interrupt is disabled no causes will cause
++ * an interrupt
++ *
++ * Return:    '0' on Success; Error code otherwise.
++ */
++int dpsw_set_irq_enable(struct fsl_mc_io      *mc_io,
++                      uint32_t                cmd_flags,
++                      uint16_t                token,
++                      uint8_t         irq_index,
++                      uint8_t         en);
++
++/**
++ * dpsw_get_irq_enable() - Get overall interrupt state
++ * @mc_io:    Pointer to MC portal's I/O object
++ * @cmd_flags:        Command flags; one or more of 'MC_CMD_FLAG_'
++ * @token:            Token of DPSW object
++ * @irq_index:        The interrupt index to configure
++ * @en:                       Returned Interrupt state - enable = 1, disable = 0
++ *
++ * Return:    '0' on Success; Error code otherwise.
++ */
++int dpsw_get_irq_enable(struct fsl_mc_io      *mc_io,
++                      uint32_t                cmd_flags,
++                      uint16_t                token,
++                      uint8_t         irq_index,
++                      uint8_t         *en);
++
++/**
++ * dpsw_set_irq_mask() - Set interrupt mask.
++ * @mc_io:    Pointer to MC portal's I/O object
++ * @cmd_flags:        Command flags; one or more of 'MC_CMD_FLAG_'
++ * @token:            Token of DPCI object
++ * @irq_index:        The interrupt index to configure
++ * @mask:             event mask to trigger interrupt;
++ *                            each bit:
++ *                                    0 = ignore event
++ *                                    1 = consider event for asserting IRQ
++ *
++ * Every interrupt can have up to 32 causes and the interrupt model supports
++ * masking/unmasking each cause independently
++ *
++ * Return:    '0' on Success; Error code otherwise.
++ */
++int dpsw_set_irq_mask(struct fsl_mc_io        *mc_io,
++                    uint32_t          cmd_flags,
++                    uint16_t          token,
++                    uint8_t           irq_index,
++                    uint32_t          mask);
++
++/**
++ * dpsw_get_irq_mask() - Get interrupt mask.
++ * @mc_io:    Pointer to MC portal's I/O object
++ * @cmd_flags:        Command flags; one or more of 'MC_CMD_FLAG_'
++ * @token:            Token of DPSW object
++ * @irq_index:        The interrupt index to configure
++ * @mask:             Returned event mask to trigger interrupt
++ *
++ * Every interrupt can have up to 32 causes and the interrupt model supports
++ * masking/unmasking each cause independently
++ *
++ * Return:    '0' on Success; Error code otherwise.
++ */
++int dpsw_get_irq_mask(struct fsl_mc_io        *mc_io,
++                    uint32_t          cmd_flags,
++                    uint16_t          token,
++                    uint8_t           irq_index,
++                    uint32_t          *mask);
++
++/**
++ * dpsw_get_irq_status() - Get the current status of any pending interrupts
++ * @mc_io:    Pointer to MC portal's I/O object
++ * @cmd_flags:        Command flags; one or more of 'MC_CMD_FLAG_'
++ * @token:            Token of DPSW object
++ * @irq_index:        The interrupt index to configure
++ * @status:           Returned interrupts status - one bit per cause:
++ *                                    0 = no interrupt pending
++ *                                    1 = interrupt pending
++ *
++ * Return:    '0' on Success; Error code otherwise.
++ */
++int dpsw_get_irq_status(struct fsl_mc_io      *mc_io,
++                      uint32_t                cmd_flags,
++                      uint16_t                token,
++                      uint8_t         irq_index,
++                      uint32_t                *status);
++
++/**
++ * dpsw_clear_irq_status() - Clear a pending interrupt's status
++ * @mc_io:    Pointer to MC portal's I/O object
++ * @cmd_flags:        Command flags; one or more of 'MC_CMD_FLAG_'
++ * @token:            Token of DPCI object
++ * @irq_index:        The interrupt index to configure
++ * @status:           bits to clear (W1C) - one bit per cause:
++ *                                    0 = don't change
++ *                                    1 = clear status bit
++ *
++ * Return:    '0' on Success; Error code otherwise.
++ */
++int dpsw_clear_irq_status(struct fsl_mc_io    *mc_io,
++                        uint32_t              cmd_flags,
++                        uint16_t              token,
++                        uint8_t               irq_index,
++                        uint32_t              status);
++/**
++ * struct dpsw_attr - Structure representing DPSW attributes
++ * @id: DPSW object ID
++ * @version: DPSW version
++ * @options: Enable/Disable DPSW features
++ * @max_vlans: Maximum Number of VLANs
++ * @max_meters_per_if:  Number of meters per interface
++ * @max_fdbs: Maximum Number of FDBs
++ * @max_fdb_entries: Number of FDB entries for default FDB table;
++ *                    0 - indicates default 1024 entries.
++ * @fdb_aging_time: Default FDB aging time for default FDB table;
++ *                    0 - indicates default 300 seconds
++ * @max_fdb_mc_groups: Number of multicast groups in each FDB table;
++ *                    0 - indicates default 32
++ * @mem_size: DPSW frame storage memory size
++ * @num_ifs: Number of interfaces
++ * @num_vlans: Current number of VLANs
++ * @num_fdbs: Current number of FDBs
++ * @component_type: Component type of this bridge
++ */
++struct dpsw_attr {
++      int             id;
++      /**
++       * struct version - DPSW version
++       * @major: DPSW major version
++       * @minor: DPSW minor version
++       */
++      struct {
++              uint16_t major;
++              uint16_t minor;
++      } version;
++      uint64_t        options;
++      uint16_t        max_vlans;
++      uint8_t max_meters_per_if;
++      uint8_t max_fdbs;
++      uint16_t        max_fdb_entries;
++      uint16_t        fdb_aging_time;
++      uint16_t        max_fdb_mc_groups;
++      uint16_t        num_ifs;
++      uint16_t        mem_size;
++      uint16_t        num_vlans;
++      uint8_t         num_fdbs;
++      enum dpsw_component_type component_type;
++};
++
++/**
++ * dpsw_get_attributes() - Retrieve DPSW attributes
++ * @mc_io:    Pointer to MC portal's I/O object
++ * @cmd_flags:        Command flags; one or more of 'MC_CMD_FLAG_'
++ * @token:            Token of DPSW object
++ * @attr:             Returned DPSW attributes
++ *
++ * Return:    Completion status. '0' on Success; Error code otherwise.
++ */
++int dpsw_get_attributes(struct fsl_mc_io      *mc_io,
++                      uint32_t                cmd_flags,
++                      uint16_t                token,
++                      struct dpsw_attr        *attr);
++
++/**
++ * dpsw_set_reflection_if() - Set target interface for reflected interfaces.
++ * @mc_io:    Pointer to MC portal's I/O object
++ * @cmd_flags:        Command flags; one or more of 'MC_CMD_FLAG_'
++ * @token:            Token of DPSW object
++ * @if_id:            Interface Id
++ *
++ *    Only one reflection receive interface is allowed per switch
++ *
++ * Return:    Completion status. '0' on Success; Error code otherwise.
++ */
++int dpsw_set_reflection_if(struct fsl_mc_io   *mc_io,
++                         uint32_t             cmd_flags,
++                         uint16_t             token,
++                         uint16_t             if_id);
++
++/**
++ * enum dpsw_action - Action selection for special/control frames
++ * @DPSW_ACTION_DROP: Drop frame
++ * @DPSW_ACTION_REDIRECT: Redirect frame to control port
++ */
++enum dpsw_action {
++      DPSW_ACTION_DROP = 0,
++      DPSW_ACTION_REDIRECT = 1
++};
++
++/**
++ * Enable auto-negotiation
++ */
++#define DPSW_LINK_OPT_AUTONEG         0x0000000000000001ULL
++/**
++ * Enable half-duplex mode
++ */
++#define DPSW_LINK_OPT_HALF_DUPLEX     0x0000000000000002ULL
++/**
++ * Enable pause frames
++ */
++#define DPSW_LINK_OPT_PAUSE           0x0000000000000004ULL
++/**
++ * Enable a-symmetric pause frames
++ */
++#define DPSW_LINK_OPT_ASYM_PAUSE      0x0000000000000008ULL
++
++/**
++ * struct dpsw_link_cfg - Structure representing DPSW link configuration
++ * @rate: Rate
++ * @options: Mask of available options; use 'DPSW_LINK_OPT_<X>' values
++ */
++struct dpsw_link_cfg {
++      uint32_t rate;
++      uint64_t options;
++};
++
++/**
++ * dpsw_if_set_link_cfg() - set the link configuration.
++ * @mc_io:    Pointer to MC portal's I/O object
++ * @cmd_flags:        Command flags; one or more of 'MC_CMD_FLAG_'
++ * @token: Token of DPSW object
++ * @if_id: interface id
++ * @cfg: Link configuration
++ *
++ * Return:    '0' on Success; Error code otherwise.
++ */
++int dpsw_if_set_link_cfg(struct fsl_mc_io     *mc_io,
++                       uint32_t               cmd_flags,
++                       uint16_t               token,
++                       uint16_t               if_id,
++                       struct dpsw_link_cfg   *cfg);
++/**
++ * struct dpsw_link_state - Structure representing DPSW link state
++ * @rate: Rate
++ * @options: Mask of available options; use 'DPSW_LINK_OPT_<X>' values
++ * @up: 0 - covers two cases: down and disconnected, 1 - up
++ */
++struct dpsw_link_state {
++      uint32_t rate;
++      uint64_t options;
++      int      up;
++};
++
++/**
++ * dpsw_if_get_link_state - Return the link state
++ * @mc_io:    Pointer to MC portal's I/O object
++ * @cmd_flags:        Command flags; one or more of 'MC_CMD_FLAG_'
++ * @token: Token of DPSW object
++ * @if_id: interface id
++ * @state: link state 1 - linkup, 0 - link down or disconnected
++ *
++ * @returns   '0' on Success; Error code otherwise.
++ */
++int dpsw_if_get_link_state(struct fsl_mc_io           *mc_io,
++                         uint32_t                     cmd_flags,
++                         uint16_t                     token,
++                         uint16_t                     if_id,
++                         struct dpsw_link_state       *state);
++
++/**
++ * dpsw_if_set_flooding() - Enable Disable flooding for particular interface
++ * @mc_io:    Pointer to MC portal's I/O object
++ * @cmd_flags:        Command flags; one or more of 'MC_CMD_FLAG_'
++ * @token:            Token of DPSW object
++ * @if_id:            Interface Identifier
++ * @en:                       1 - enable, 0 - disable
++ *
++ * Return:    Completion status. '0' on Success; Error code otherwise.
++ */
++int dpsw_if_set_flooding(struct fsl_mc_io     *mc_io,
++                       uint32_t               cmd_flags,
++                       uint16_t               token,
++                       uint16_t               if_id,
++                       int                    en);
++
++/**
++ * dpsw_if_set_broadcast() - Enable/disable broadcast for particular interface
++ * @mc_io:    Pointer to MC portal's I/O object
++ * @cmd_flags:        Command flags; one or more of 'MC_CMD_FLAG_'
++ * @token:            Token of DPSW object
++ * @if_id:            Interface Identifier
++ * @en:                       1 - enable, 0 - disable
++ *
++ * Return:    Completion status. '0' on Success; Error code otherwise.
++ */
++int dpsw_if_set_broadcast(struct fsl_mc_io    *mc_io,
++                        uint32_t              cmd_flags,
++                        uint16_t              token,
++                        uint16_t              if_id,
++                        int                   en);
++
++/**
++ * dpsw_if_set_multicast() - Enable/disable multicast for particular interface
++ * @mc_io:    Pointer to MC portal's I/O object
++ * @cmd_flags:        Command flags; one or more of 'MC_CMD_FLAG_'
++ * @token:            Token of DPSW object
++ * @if_id:            Interface Identifier
++ * @en:                       1 - enable, 0 - disable
++ *
++ * Return:    Completion status. '0' on Success; Error code otherwise.
++ */
++int dpsw_if_set_multicast(struct fsl_mc_io    *mc_io,
++                        uint32_t              cmd_flags,
++                        uint16_t              token,
++                        uint16_t              if_id,
++                        int                   en);
++
++/**
++ * struct dpsw_tci_cfg - Tag Contorl Information (TCI) configuration
++ * @pcp: Priority Code Point (PCP): a 3-bit field which refers
++ *             to the IEEE 802.1p priority
++ * @dei: Drop Eligible Indicator (DEI): a 1-bit field. May be used
++ *             separately or in conjunction with PCP to indicate frames
++ *             eligible to be dropped in the presence of congestion
++ * @vlan_id: VLAN Identifier (VID): a 12-bit field specifying the VLAN
++ *                    to which the frame belongs. The hexadecimal values
++ *                    of 0x000 and 0xFFF are reserved;
++ *                    all other values may be used as VLAN identifiers,
++ *                    allowing up to 4,094 VLANs
++ */
++struct dpsw_tci_cfg {
++      uint8_t pcp;
++      uint8_t dei;
++      uint16_t        vlan_id;
++};
++
++/**
++ * dpsw_if_set_tci() - Set default VLAN Tag Control Information (TCI)
++ * @mc_io:    Pointer to MC portal's I/O object
++ * @cmd_flags:        Command flags; one or more of 'MC_CMD_FLAG_'
++ * @token:            Token of DPSW object
++ * @if_id:            Interface Identifier
++ * @cfg:              Tag Control Information Configuration
++ *
++ * Return:    Completion status. '0' on Success; Error code otherwise.
++ */
++int dpsw_if_set_tci(struct fsl_mc_io          *mc_io,
++                  uint32_t                    cmd_flags,
++                  uint16_t                    token,
++                  uint16_t                    if_id,
++                  const struct dpsw_tci_cfg   *cfg);
++
++/**
++ * dpsw_if_get_tci() - Get default VLAN Tag Control Information (TCI)
++ * @mc_io:    Pointer to MC portal's I/O object
++ * @cmd_flags:        Command flags; one or more of 'MC_CMD_FLAG_'
++ * @token:            Token of DPSW object
++ * @if_id:            Interface Identifier
++ * @cfg:              Tag Control Information Configuration
++ *
++ * Return:    Completion status. '0' on Success; Error code otherwise.
++ */
++int dpsw_if_get_tci(struct fsl_mc_io  *mc_io,
++                  uint32_t            cmd_flags,
++                  uint16_t            token,
++                  uint16_t            if_id,
++                  struct dpsw_tci_cfg *cfg);
++
++/**
++ * enum dpsw_stp_state - Spanning Tree Protocol (STP) states
++ * @DPSW_STP_STATE_BLOCKING: Blocking state
++ * @DPSW_STP_STATE_LISTENING: Listening state
++ * @DPSW_STP_STATE_LEARNING: Learning state
++ * @DPSW_STP_STATE_FORWARDING: Forwarding state
++ *
++ */
++enum dpsw_stp_state {
++      DPSW_STP_STATE_BLOCKING = 0,
++      DPSW_STP_STATE_LISTENING = 1,
++      DPSW_STP_STATE_LEARNING = 2,
++      DPSW_STP_STATE_FORWARDING = 3
++};
++
++/**
++ * struct dpsw_stp_cfg - Spanning Tree Protocol (STP) Configuration
++ * @vlan_id: VLAN ID STP state
++ * @state: STP state
++ */
++struct dpsw_stp_cfg {
++      uint16_t                vlan_id;
++      enum dpsw_stp_state     state;
++};
++
++/**
++ * dpsw_if_set_stp() - Function sets Spanning Tree Protocol (STP) state.
++ * @mc_io:    Pointer to MC portal's I/O object
++ * @cmd_flags:        Command flags; one or more of 'MC_CMD_FLAG_'
++ * @token:            Token of DPSW object
++ * @if_id:            Interface Identifier
++ * @cfg:              STP State configuration parameters
++ *
++ * The following STP states are supported -
++ * blocking, listening, learning, forwarding and disabled.
++ *
++ * Return:    Completion status. '0' on Success; Error code otherwise.
++ */
++int dpsw_if_set_stp(struct fsl_mc_io          *mc_io,
++                  uint32_t                    cmd_flags,
++                  uint16_t                    token,
++                  uint16_t                    if_id,
++                  const struct dpsw_stp_cfg   *cfg);
++
++/**
++ * enum dpsw_accepted_frames - Types of frames to accept
++ * @DPSW_ADMIT_ALL: The device accepts VLAN tagged, untagged and
++ *                    priority tagged frames
++ * @DPSW_ADMIT_ONLY_VLAN_TAGGED: The device discards untagged frames or
++ *                    Priority-Tagged frames received on this interface.
++ *
++ */
++enum dpsw_accepted_frames {
++      DPSW_ADMIT_ALL = 1,
++      DPSW_ADMIT_ONLY_VLAN_TAGGED = 3
++};
++
++/**
++ * struct dpsw_accepted_frames_cfg - Types of frames to accept configuration
++ * @type: Defines ingress accepted frames
++ * @unaccept_act: When a frame is not accepted, it may be discarded or
++ *                    redirected to control interface depending on this mode
++ */
++struct dpsw_accepted_frames_cfg {
++      enum dpsw_accepted_frames       type;
++      enum dpsw_action                unaccept_act;
++};
++
++/**
++ * dpsw_if_set_accepted_frames()
++ * @mc_io:    Pointer to MC portal's I/O object
++ * @cmd_flags:        Command flags; one or more of 'MC_CMD_FLAG_'
++ * @token:            Token of DPSW object
++ * @if_id:            Interface Identifier
++ * @cfg:              Frame types configuration
++ *
++ * When is admit_only_vlan_tagged- the device will discard untagged
++ * frames or Priority-Tagged frames received on this interface.
++ * When admit_only_untagged- untagged frames or Priority-Tagged
++ * frames received on this interface will be accepted and assigned
++ * to a VID based on the PVID and VID Set for this interface.
++ * When admit_all - the device will accept VLAN tagged, untagged
++ * and priority tagged frames.
++ * The default is admit_all
++ *
++ * Return:    Completion status. '0' on Success; Error code otherwise.
++ */
++int dpsw_if_set_accepted_frames(struct fsl_mc_io              *mc_io,
++                              uint32_t                        cmd_flags,
++                              uint16_t                        token,
++                              uint16_t                        if_id,
++                              const struct dpsw_accepted_frames_cfg *cfg);
++
++/**
++ * dpsw_if_set_accept_all_vlan()
++ * @mc_io:    Pointer to MC portal's I/O object
++ * @cmd_flags:        Command flags; one or more of 'MC_CMD_FLAG_'
++ * @token:            Token of DPSW object
++ * @if_id:            Interface Identifier
++ * @accept_all:       Accept or drop frames having different VLAN
++ *
++ * When this is accept (FALSE), the device will discard incoming
++ * frames for VLANs that do not include this interface in its
++ * Member set. When accept (TRUE), the interface will accept all incoming frames
++ *
++ * Return:    Completion status. '0' on Success; Error code otherwise.
++ */
++int dpsw_if_set_accept_all_vlan(struct fsl_mc_io      *mc_io,
++                              uint32_t                cmd_flags,
++                              uint16_t                token,
++                              uint16_t                if_id,
++                              int                     accept_all);
++
++/**
++ * enum dpsw_counter  - Counters types
++ * @DPSW_CNT_ING_FRAME: Counts ingress frames
++ * @DPSW_CNT_ING_BYTE: Counts ingress bytes
++ * @DPSW_CNT_ING_FLTR_FRAME: Counts filtered ingress frames
++ * @DPSW_CNT_ING_FRAME_DISCARD: Counts discarded ingress frame
++ * @DPSW_CNT_ING_MCAST_FRAME: Counts ingress multicast frames
++ * @DPSW_CNT_ING_MCAST_BYTE: Counts ingress multicast bytes
++ * @DPSW_CNT_ING_BCAST_FRAME: Counts ingress broadcast frames
++ * @DPSW_CNT_ING_BCAST_BYTES: Counts ingress broadcast bytes
++ * @DPSW_CNT_EGR_FRAME: Counts egress frames
++ * @DPSW_CNT_EGR_BYTE: Counts eEgress bytes
++ * @DPSW_CNT_EGR_FRAME_DISCARD: Counts discarded egress frames
++ * @DPSW_CNT_EGR_STP_FRAME_DISCARD: Counts egress STP discarded frames
++ */
++enum dpsw_counter {
++      DPSW_CNT_ING_FRAME = 0x0,
++      DPSW_CNT_ING_BYTE = 0x1,
++      DPSW_CNT_ING_FLTR_FRAME = 0x2,
++      DPSW_CNT_ING_FRAME_DISCARD = 0x3,
++      DPSW_CNT_ING_MCAST_FRAME = 0x4,
++      DPSW_CNT_ING_MCAST_BYTE = 0x5,
++      DPSW_CNT_ING_BCAST_FRAME = 0x6,
++      DPSW_CNT_ING_BCAST_BYTES = 0x7,
++      DPSW_CNT_EGR_FRAME = 0x8,
++      DPSW_CNT_EGR_BYTE = 0x9,
++      DPSW_CNT_EGR_FRAME_DISCARD = 0xa,
++      DPSW_CNT_EGR_STP_FRAME_DISCARD = 0xb
++};
++
++/**
++ * dpsw_if_get_counter() - Get specific counter of particular interface
++ * @mc_io:    Pointer to MC portal's I/O object
++ * @cmd_flags:        Command flags; one or more of 'MC_CMD_FLAG_'
++ * @token:            Token of DPSW object
++ * @if_id:            Interface Identifier
++ * @type:             Counter type
++ * @counter:  return value
++ *
++ * Return:    Completion status. '0' on Success; Error code otherwise.
++ */
++int dpsw_if_get_counter(struct fsl_mc_io      *mc_io,
++                      uint32_t                cmd_flags,
++                      uint16_t                token,
++                      uint16_t                if_id,
++                      enum dpsw_counter       type,
++                      uint64_t                *counter);
++
++/**
++ * dpsw_if_set_counter() - Set specific counter of particular interface
++ * @mc_io:    Pointer to MC portal's I/O object
++ * @cmd_flags:        Command flags; one or more of 'MC_CMD_FLAG_'
++ * @token:            Token of DPSW object
++ * @if_id:            Interface Identifier
++ * @type:             Counter type
++ * @counter:  New counter value
++ *
++ * Return:    Completion status. '0' on Success; Error code otherwise.
++ */
++int dpsw_if_set_counter(struct fsl_mc_io      *mc_io,
++                      uint32_t                cmd_flags,
++                      uint16_t                token,
++                      uint16_t                if_id,
++                      enum dpsw_counter       type,
++                      uint64_t                counter);
++
++/**
++ * Maximum number of TC
++ */
++#define DPSW_MAX_TC             8
++
++/**
++ * enum dpsw_priority_selector - User priority
++ * @DPSW_UP_PCP: Priority Code Point (PCP): a 3-bit field which
++ *                             refers to the IEEE 802.1p priority.
++ * @DPSW_UP_DSCP: Differentiated services Code Point (DSCP): 6 bit
++ *                            field from IP header
++ *
++ */
++enum dpsw_priority_selector {
++      DPSW_UP_PCP = 0,
++      DPSW_UP_DSCP = 1
++};
++
++/**
++ * enum dpsw_schedule_mode - Traffic classes scheduling
++ * @DPSW_SCHED_STRICT_PRIORITY: schedule strict priority
++ * @DPSW_SCHED_WEIGHTED: schedule based on token bucket created algorithm
++ */
++enum dpsw_schedule_mode {
++      DPSW_SCHED_STRICT_PRIORITY,
++      DPSW_SCHED_WEIGHTED
++};
++
++/**
++ * struct dpsw_tx_schedule_cfg - traffic class configuration
++ * @mode: Strict or weight-based scheduling
++ * @delta_bandwidth: weighted Bandwidth in range from 100 to 10000
++ */
++struct dpsw_tx_schedule_cfg {
++      enum dpsw_schedule_mode mode;
++      uint16_t                delta_bandwidth;
++};
++
++/**
++ * struct dpsw_tx_selection_cfg - Mapping user priority into traffic
++ *                                    class configuration
++ * @priority_selector: Source for user priority regeneration
++ * @tc_id: The Regenerated User priority that the incoming
++ *                            User Priority is mapped to for this interface
++ * @tc_sched: Traffic classes configuration
++ */
++struct dpsw_tx_selection_cfg {
++      enum dpsw_priority_selector     priority_selector;
++      uint8_t                 tc_id[DPSW_MAX_PRIORITIES];
++      struct dpsw_tx_schedule_cfg     tc_sched[DPSW_MAX_TC];
++};
++
++/**
++ * dpsw_if_set_tx_selection() - Function is used for mapping variety
++ *                            of frame fields
++ * @mc_io:    Pointer to MC portal's I/O object
++ * @cmd_flags:        Command flags; one or more of 'MC_CMD_FLAG_'
++ * @token:            Token of DPSW object
++ * @if_id:            Interface Identifier
++ * @cfg:              Traffic class mapping configuration
++ *
++ * Function is used for mapping variety of frame fields (DSCP, PCP)
++ * to Traffic Class. Traffic class is a number
++ * in the range from 0 to 7
++ *
++ * Return:    Completion status. '0' on Success; Error code otherwise.
++ */
++int dpsw_if_set_tx_selection(struct fsl_mc_io                 *mc_io,
++                           uint32_t                           cmd_flags,
++                           uint16_t                           token,
++                           uint16_t                           if_id,
++                           const struct dpsw_tx_selection_cfg *cfg);
++
++/**
++ * enum dpsw_reflection_filter - Filter type for frames to reflect
++ * @DPSW_REFLECTION_FILTER_INGRESS_ALL: Reflect all frames
++ * @DPSW_REFLECTION_FILTER_INGRESS_VLAN: Reflect only frames belong to
++ *                    particular VLAN defined by vid parameter
++ *
++ */
++enum dpsw_reflection_filter {
++      DPSW_REFLECTION_FILTER_INGRESS_ALL = 0,
++      DPSW_REFLECTION_FILTER_INGRESS_VLAN = 1
++};
++
++/**
++ * struct dpsw_reflection_cfg - Structure representing reflection information
++ * @filter: Filter type for frames to reflect
++ * @vlan_id: Vlan Id to reflect; valid only when filter type is
++ *            DPSW_INGRESS_VLAN
++ */
++struct dpsw_reflection_cfg {
++      enum dpsw_reflection_filter     filter;
++      uint16_t                        vlan_id;
++};
++
++/**
++ * dpsw_if_add_reflection() - Identify interface to be reflected or mirrored
++ * @mc_io:    Pointer to MC portal's I/O object
++ * @cmd_flags:        Command flags; one or more of 'MC_CMD_FLAG_'
++ * @token:            Token of DPSW object
++ * @if_id:            Interface Identifier
++ * @cfg:              Reflection configuration
++ *
++ * Return:    Completion status. '0' on Success; Error code otherwise.
++ */
++int dpsw_if_add_reflection(struct fsl_mc_io                   *mc_io,
++                         uint32_t                             cmd_flags,
++                         uint16_t                             token,
++                         uint16_t                             if_id,
++                         const struct dpsw_reflection_cfg     *cfg);
++
++/**
++ * dpsw_if_remove_reflection() - Remove interface to be reflected or mirrored
++ * @mc_io:    Pointer to MC portal's I/O object
++ * @cmd_flags:        Command flags; one or more of 'MC_CMD_FLAG_'
++ * @token:            Token of DPSW object
++ * @if_id:            Interface Identifier
++ * @cfg:              Reflection configuration
++ *
++ * Return:    Completion status. '0' on Success; Error code otherwise.
++ */
++int dpsw_if_remove_reflection(struct fsl_mc_io                        *mc_io,
++                            uint32_t                          cmd_flags,
++                            uint16_t                          token,
++                            uint16_t                          if_id,
++                            const struct dpsw_reflection_cfg  *cfg);
++
++/**
++ * enum dpsw_metering_mode - Metering modes
++ * @DPSW_METERING_MODE_NONE: metering disabled
++ * @DPSW_METERING_MODE_RFC2698: RFC 2698
++ * @DPSW_METERING_MODE_RFC4115: RFC 4115
++ */
++enum dpsw_metering_mode {
++      DPSW_METERING_MODE_NONE = 0,
++      DPSW_METERING_MODE_RFC2698,
++      DPSW_METERING_MODE_RFC4115
++};
++
++/**
++ * enum dpsw_metering_unit - Metering count
++ * @DPSW_METERING_UNIT_BYTES: count bytes
++ * @DPSW_METERING_UNIT_FRAMES: count frames
++ */
++enum dpsw_metering_unit {
++      DPSW_METERING_UNIT_BYTES = 0,
++      DPSW_METERING_UNIT_FRAMES
++};
++
++/**
++ * struct dpsw_metering_cfg - Metering configuration
++ * @mode: metering modes
++ * @units: Bytes or frame units
++ * @cir: Committed information rate (CIR) in Kbits/s
++ * @eir: Peak information rate (PIR) Kbit/s  rfc2698
++ *     Excess information rate (EIR) Kbit/s rfc4115
++ * @cbs: Committed burst size (CBS) in bytes
++ * @ebs: Peak burst size (PBS) in bytes for rfc2698
++ *       Excess bust size (EBS) in bytes rfc4115
++ *
++ */
++struct dpsw_metering_cfg {
++      enum dpsw_metering_mode mode;
++      enum dpsw_metering_unit units;
++      uint32_t                cir;
++      uint32_t                eir;
++      uint32_t                cbs;
++      uint32_t                ebs;
++};
++
++/**
++ * dpsw_if_set_flooding_metering() - Set flooding metering
++ * @mc_io:    Pointer to MC portal's I/O object
++ * @cmd_flags:        Command flags; one or more of 'MC_CMD_FLAG_'
++ * @token:    Token of DPSW object
++ * @if_id:    Interface Identifier
++ * @cfg:      Metering parameters
++ *
++ * Return:    Completion status. '0' on Success; Error code otherwise.
++ */
++int dpsw_if_set_flooding_metering(struct fsl_mc_io            *mc_io,
++                                uint32_t                      cmd_flags,
++                                uint16_t                      token,
++                                uint16_t                      if_id,
++                                const struct dpsw_metering_cfg *cfg);
++
++/**
++ * dpsw_if_set_metering() - Set interface metering for flooding
++ * @mc_io:    Pointer to MC portal's I/O object
++ * @cmd_flags:        Command flags; one or more of 'MC_CMD_FLAG_'
++ * @token:    Token of DPSW object
++ * @if_id:    Interface Identifier
++ * @tc_id:    Traffic class ID
++ * @cfg:      Metering parameters
++ *
++ * Return:    Completion status. '0' on Success; Error code otherwise.
++ */
++int dpsw_if_set_metering(struct fsl_mc_io                     *mc_io,
++                       uint32_t                               cmd_flags,
++                       uint16_t                               token,
++                       uint16_t                               if_id,
++                       uint8_t                                tc_id,
++                       const struct dpsw_metering_cfg *cfg);
++
++/**
++ * enum dpsw_early_drop_unit - DPSW early drop unit
++ * @DPSW_EARLY_DROP_UNIT_BYTE: count bytes
++ * @DPSW_EARLY_DROP_UNIT_FRAMES: count frames
++ */
++enum dpsw_early_drop_unit {
++      DPSW_EARLY_DROP_UNIT_BYTE = 0,
++      DPSW_EARLY_DROP_UNIT_FRAMES
++};
++
++/**
++ * enum dpsw_early_drop_mode - DPSW early drop mode
++ * @DPSW_EARLY_DROP_MODE_NONE: early drop is disabled
++ * @DPSW_EARLY_DROP_MODE_TAIL: early drop in taildrop mode
++ * @DPSW_EARLY_DROP_MODE_WRED: early drop in WRED mode
++ */
++enum dpsw_early_drop_mode {
++      DPSW_EARLY_DROP_MODE_NONE = 0,
++      DPSW_EARLY_DROP_MODE_TAIL,
++      DPSW_EARLY_DROP_MODE_WRED
++};
++
++/**
++ * struct dpsw_wred_cfg - WRED configuration
++ * @max_threshold: maximum threshold that packets may be discarded. Above this
++ *      threshold all packets are discarded; must be less than 2^39;
++ *      approximated to be expressed as (x+256)*2^(y-1) due to HW
++ *        implementation.
++ * @min_threshold: minimum threshold that packets may be discarded at
++ * @drop_probability: probability that a packet will be discarded (1-100,
++ *    associated with the maximum threshold)
++ */
++struct dpsw_wred_cfg {
++      uint64_t                min_threshold;
++      uint64_t                max_threshold;
++      uint8_t                 drop_probability;
++};
++
++/**
++ * struct dpsw_early_drop_cfg - early-drop configuration
++ * @drop_mode: drop mode
++ * @units: count units
++ * @yellow: WRED - 'yellow' configuration
++ * @green: WRED - 'green' configuration
++ * @tail_drop_threshold: tail drop threshold
++ */
++struct dpsw_early_drop_cfg {
++      enum dpsw_early_drop_mode       drop_mode;
++      enum dpsw_early_drop_unit       units;
++      struct dpsw_wred_cfg            yellow;
++      struct dpsw_wred_cfg            green;
++      uint32_t                        tail_drop_threshold;
++};
++
++/**
++ * dpsw_prepare_early_drop() - Prepare an early drop for setting in to interface
++ * @cfg:      Early-drop configuration
++ * @early_drop_buf: Zeroed 256 bytes of memory before mapping it to DMA
++ *
++ * This function has to be called before dpsw_if_tc_set_early_drop
++ *
++ */
++void dpsw_prepare_early_drop(const struct dpsw_early_drop_cfg *cfg,
++                           uint8_t                    *early_drop_buf);
++
++/**
++ * dpsw_if_set_early_drop() - Set interface traffic class early-drop
++ *                            configuration
++ * @mc_io:    Pointer to MC portal's I/O object
++ * @cmd_flags:        Command flags; one or more of 'MC_CMD_FLAG_'
++ * @token:    Token of DPSW object
++ * @if_id:            Interface Identifier
++ * @tc_id:    Traffic class selection (0-7)
++ * @early_drop_iova:  I/O virtual address of 64 bytes;
++ * Must be cacheline-aligned and DMA-able memory
++ *
++ * warning: Before calling this function, call dpsw_prepare_if_tc_early_drop()
++ *            to prepare the early_drop_iova parameter
++ *
++ * Return:    '0' on Success; error code otherwise.
++ */
++int dpsw_if_set_early_drop(struct fsl_mc_io   *mc_io,
++                         uint32_t             cmd_flags,
++                         uint16_t             token,
++                         uint16_t             if_id,
++                         uint8_t              tc_id,
++                         uint64_t             early_drop_iova);
++
++/**
++ * struct dpsw_custom_tpid_cfg - Structure representing tag Protocol identifier
++ * @tpid: An additional tag protocol identifier
++ */
++struct dpsw_custom_tpid_cfg {
++      uint16_t tpid;
++};
++
++/**
++ * dpsw_add_custom_tpid() - API Configures a distinct Ethernet type value
++ * @mc_io:    Pointer to MC portal's I/O object
++ * @cmd_flags:        Command flags; one or more of 'MC_CMD_FLAG_'
++ * @token:            Token of DPSW object
++ * @cfg:              Tag Protocol identifier
++ *
++ * API Configures a distinct Ethernet type value (or TPID value)
++ * to indicate a VLAN tag in addition to the common
++ * TPID values 0x8100 and 0x88A8.
++ * Two additional TPID's are supported
++ *
++ * Return:    Completion status. '0' on Success; Error code otherwise.
++ */
++int dpsw_add_custom_tpid(struct fsl_mc_io                     *mc_io,
++                       uint32_t                               cmd_flags,
++                       uint16_t                               token,
++                       const struct dpsw_custom_tpid_cfg      *cfg);
++
++/**
++ * dpsw_remove_custom_tpid - API removes a distinct Ethernet type value
++ * @mc_io:    Pointer to MC portal's I/O object
++ * @cmd_flags:        Command flags; one or more of 'MC_CMD_FLAG_'
++ * @token:            Token of DPSW object
++ * @cfg:              Tag Protocol identifier
++ *
++ * Return:    Completion status. '0' on Success; Error code otherwise.
++ */
++int dpsw_remove_custom_tpid(struct fsl_mc_io                  *mc_io,
++                          uint32_t                            cmd_flags,
++                          uint16_t                            token,
++                          const struct dpsw_custom_tpid_cfg   *cfg);
++
++/**
++ * dpsw_if_enable() - Enable Interface
++ * @mc_io:    Pointer to MC portal's I/O object
++ * @cmd_flags:        Command flags; one or more of 'MC_CMD_FLAG_'
++ * @token:            Token of DPSW object
++ * @if_id:            Interface Identifier
++ *
++ * Return:    Completion status. '0' on Success; Error code otherwise.
++ */
++int dpsw_if_enable(struct fsl_mc_io   *mc_io,
++                 uint32_t             cmd_flags,
++                 uint16_t             token,
++                 uint16_t             if_id);
++
++/**
++ * dpsw_if_disable() - Disable Interface
++ * @mc_io:    Pointer to MC portal's I/O object
++ * @cmd_flags:        Command flags; one or more of 'MC_CMD_FLAG_'
++ * @token:            Token of DPSW object
++ * @if_id:            Interface Identifier
++ *
++ * Return:    Completion status. '0' on Success; Error code otherwise.
++ */
++int dpsw_if_disable(struct fsl_mc_io  *mc_io,
++                  uint32_t            cmd_flags,
++                  uint16_t            token,
++                  uint16_t            if_id);
++
++/**
++ * struct dpsw_if_attr - Structure representing DPSW interface attributes
++ * @num_tcs: Number of traffic classes
++ * @rate: Transmit rate in bits per second
++ * @options: Interface configuration options (bitmap)
++ * @enabled: Indicates if interface is enabled
++ * @accept_all_vlan: The device discards/accepts incoming frames
++ *            for VLANs that do not include this interface
++ * @admit_untagged: When set to 'DPSW_ADMIT_ONLY_VLAN_TAGGED', the device
++ *            discards untagged frames or priority-tagged frames received on
++ *            this interface;
++ *            When set to 'DPSW_ADMIT_ALL', untagged frames or priority-
++ *            tagged frames received on this interface are accepted
++ * @qdid: control frames transmit qdid
++ */
++struct dpsw_if_attr {
++      uint8_t                         num_tcs;
++      uint32_t                        rate;
++      uint32_t                        options;
++      int                             enabled;
++      int                             accept_all_vlan;
++      enum dpsw_accepted_frames       admit_untagged;
++      uint16_t                        qdid;
++};
++
++/**
++ * dpsw_if_get_attributes() - Function obtains attributes of interface
++ * @mc_io:    Pointer to MC portal's I/O object
++ * @cmd_flags:        Command flags; one or more of 'MC_CMD_FLAG_'
++ * @token:    Token of DPSW object
++ * @if_id:    Interface Identifier
++ * @attr:     Returned interface attributes
++ *
++ * Return:    Completion status. '0' on Success; Error code otherwise.
++ */
++int dpsw_if_get_attributes(struct fsl_mc_io   *mc_io,
++                         uint32_t             cmd_flags,
++                         uint16_t             token,
++                         uint16_t             if_id,
++                         struct dpsw_if_attr  *attr);
++
++/**
++ * dpsw_if_set_max_frame_length() - Set Maximum Receive frame length.
++ * @mc_io:    Pointer to MC portal's I/O object
++ * @cmd_flags:        Command flags; one or more of 'MC_CMD_FLAG_'
++ * @token:    Token of DPSW object
++ * @if_id:    Interface Identifier
++ * @frame_length: Maximum Frame Length
++ *
++ * Return:    Completion status. '0' on Success; Error code otherwise.
++ */
++int dpsw_if_set_max_frame_length(struct fsl_mc_io     *mc_io,
++                               uint32_t               cmd_flags,
++                               uint16_t               token,
++                               uint16_t               if_id,
++                               uint16_t               frame_length);
++
++/**
++ * dpsw_if_get_max_frame_length() - Get Maximum Receive frame length.
++ * @mc_io:    Pointer to MC portal's I/O object
++ * @cmd_flags:        Command flags; one or more of 'MC_CMD_FLAG_'
++ * @token:    Token of DPSW object
++ * @if_id:    Interface Identifier
++ * @frame_length: Returned maximum Frame Length
++ *
++ * Return:    Completion status. '0' on Success; Error code otherwise.
++ */
++int dpsw_if_get_max_frame_length(struct fsl_mc_io     *mc_io,
++                               uint32_t               cmd_flags,
++                               uint16_t               token,
++                               uint16_t               if_id,
++                               uint16_t               *frame_length);
++
++/**
++ * struct dpsw_vlan_cfg - VLAN Configuration
++ * @fdb_id: Forwarding Data Base
++ */
++struct dpsw_vlan_cfg {
++      uint16_t fdb_id;
++};
++
++/**
++ * dpsw_vlan_add() - Adding new VLAN to DPSW.
++ * @mc_io:    Pointer to MC portal's I/O object
++ * @cmd_flags:        Command flags; one or more of 'MC_CMD_FLAG_'
++ * @token:    Token of DPSW object
++ * @vlan_id:  VLAN Identifier
++ * @cfg:      VLAN configuration
++ *
++ * Only VLAN ID and FDB ID are required parameters here.
++ * 12 bit VLAN ID is defined in IEEE802.1Q.
++ * Adding a duplicate VLAN ID is not allowed.
++ * FDB ID can be shared across multiple VLANs. Shared learning
++ * is obtained by calling dpsw_vlan_add for multiple VLAN IDs
++ * with same fdb_id
++ *
++ * Return:    Completion status. '0' on Success; Error code otherwise.
++ */
++int dpsw_vlan_add(struct fsl_mc_io            *mc_io,
++                uint32_t                      cmd_flags,
++                uint16_t                      token,
++                uint16_t                      vlan_id,
++                const struct dpsw_vlan_cfg    *cfg);
++
++/**
++ * struct dpsw_vlan_if_cfg - Set of VLAN Interfaces
++ * @num_ifs: The number of interfaces that are assigned to the egress
++ *            list for this VLAN
++ * @if_id: The set of interfaces that are
++ *            assigned to the egress list for this VLAN
++ */
++struct dpsw_vlan_if_cfg {
++      uint16_t num_ifs;
++      uint16_t if_id[DPSW_MAX_IF];
++};
++
++/**
++ * dpsw_vlan_add_if() - Adding a set of interfaces to an existing VLAN.
++ * @mc_io:    Pointer to MC portal's I/O object
++ * @cmd_flags:        Command flags; one or more of 'MC_CMD_FLAG_'
++ * @token:    Token of DPSW object
++ * @vlan_id:  VLAN Identifier
++ * @cfg:      Set of interfaces to add
++ *
++ * It adds only interfaces not belonging to this VLAN yet,
++ * otherwise an error is generated and an entire command is
++ * ignored. This function can be called numerous times always
++ * providing required interfaces delta.
++ *
++ * Return:    Completion status. '0' on Success; Error code otherwise.
++ */
++int dpsw_vlan_add_if(struct fsl_mc_io                 *mc_io,
++                   uint32_t                           cmd_flags,
++                   uint16_t                           token,
++                   uint16_t                           vlan_id,
++                   const struct dpsw_vlan_if_cfg      *cfg);
++
++/**
++ * dpsw_vlan_add_if_untagged() - Defining a set of interfaces that should be
++ *                            transmitted as untagged.
++ * @mc_io:    Pointer to MC portal's I/O object
++ * @cmd_flags:        Command flags; one or more of 'MC_CMD_FLAG_'
++ * @token:    Token of DPSW object
++ * @vlan_id:  VLAN Identifier
++ * @cfg:      set of interfaces that should be transmitted as untagged
++ *
++ * These interfaces should already belong to this VLAN.
++ * By default all interfaces are transmitted as tagged.
++ * Providing un-existing interface or untagged interface that is
++ * configured untagged already generates an error and the entire
++ * command is ignored.
++ *
++ * Return:    Completion status. '0' on Success; Error code otherwise.
++ */
++int dpsw_vlan_add_if_untagged(struct fsl_mc_io                        *mc_io,
++                            uint32_t                          cmd_flags,
++                            uint16_t                          token,
++                            uint16_t                          vlan_id,
++                            const struct dpsw_vlan_if_cfg     *cfg);
++
++/**
++ * dpsw_vlan_add_if_flooding() - Define a set of interfaces that should be
++ *                    included in flooding when frame with unknown destination
++ *                    unicast MAC arrived.
++ * @mc_io:    Pointer to MC portal's I/O object
++ * @cmd_flags:        Command flags; one or more of 'MC_CMD_FLAG_'
++ * @token:    Token of DPSW object
++ * @vlan_id:  VLAN Identifier
++ * @cfg:      Set of interfaces that should be used for flooding
++ *
++ * These interfaces should belong to this VLAN. By default all
++ * interfaces are included into flooding list. Providing
++ * un-existing interface or an interface that already in the
++ * flooding list generates an error and the entire command is
++ * ignored.
++ *
++ * Return:    Completion status. '0' on Success; Error code otherwise.
++ */
++int dpsw_vlan_add_if_flooding(struct fsl_mc_io                        *mc_io,
++                            uint32_t                          cmd_flags,
++                            uint16_t                          token,
++                            uint16_t                          vlan_id,
++                            const struct dpsw_vlan_if_cfg     *cfg);
++
++/**
++ * dpsw_vlan_remove_if() - Remove interfaces from an existing VLAN.
++ * @mc_io:    Pointer to MC portal's I/O object
++ * @cmd_flags:        Command flags; one or more of 'MC_CMD_FLAG_'
++ * @token:    Token of DPSW object
++ * @vlan_id:  VLAN Identifier
++ * @cfg:      Set of interfaces that should be removed
++ *
++ * Interfaces must belong to this VLAN, otherwise an error
++ * is returned and an the command is ignored
++ *
++ * Return:    Completion status. '0' on Success; Error code otherwise.
++ */
++int dpsw_vlan_remove_if(struct fsl_mc_io              *mc_io,
++                      uint32_t                        cmd_flags,
++                      uint16_t                        token,
++                      uint16_t                        vlan_id,
++                      const struct dpsw_vlan_if_cfg   *cfg);
++
++/**
++ * dpsw_vlan_remove_if_untagged() - Define a set of interfaces that should be
++ *            converted from transmitted as untagged to transmit as tagged.
++ * @mc_io:    Pointer to MC portal's I/O object
++ * @cmd_flags:        Command flags; one or more of 'MC_CMD_FLAG_'
++ * @token:    Token of DPSW object
++ * @vlan_id:  VLAN Identifier
++ * @cfg:      set of interfaces that should be removed
++ *
++ * Interfaces provided by API have to belong to this VLAN and
++ * configured untagged, otherwise an error is returned and the
++ * command is ignored
++ *
++ * Return:    Completion status. '0' on Success; Error code otherwise.
++ */
++int dpsw_vlan_remove_if_untagged(struct fsl_mc_io             *mc_io,
++                               uint32_t                       cmd_flags,
++                               uint16_t                       token,
++                               uint16_t                       vlan_id,
++                               const struct dpsw_vlan_if_cfg  *cfg);
++
++/**
++ * dpsw_vlan_remove_if_flooding() - Define a set of interfaces that should be
++ *                    removed from the flooding list.
++ * @mc_io:    Pointer to MC portal's I/O object
++ * @cmd_flags:        Command flags; one or more of 'MC_CMD_FLAG_'
++ * @token:    Token of DPSW object
++ * @vlan_id:  VLAN Identifier
++ * @cfg:      set of interfaces used for flooding
++ *
++ * Return:    Completion status. '0' on Success; Error code otherwise.
++ */
++int dpsw_vlan_remove_if_flooding(struct fsl_mc_io             *mc_io,
++                               uint32_t                       cmd_flags,
++                               uint16_t                       token,
++                               uint16_t                       vlan_id,
++                               const struct dpsw_vlan_if_cfg  *cfg);
++
++/**
++ * dpsw_vlan_remove() - Remove an entire VLAN
++ * @mc_io:    Pointer to MC portal's I/O object
++ * @cmd_flags:        Command flags; one or more of 'MC_CMD_FLAG_'
++ * @token:    Token of DPSW object
++ * @vlan_id:  VLAN Identifier
++ *
++ * Return:    Completion status. '0' on Success; Error code otherwise.
++ */
++int dpsw_vlan_remove(struct fsl_mc_io *mc_io,
++                   uint32_t           cmd_flags,
++                   uint16_t           token,
++                   uint16_t           vlan_id);
++
++/**
++ * struct dpsw_vlan_attr - VLAN attributes
++ * @fdb_id: Associated FDB ID
++ * @num_ifs: Number of interfaces
++ * @num_untagged_ifs: Number of untagged interfaces
++ * @num_flooding_ifs: Number of flooding interfaces
++ */
++struct dpsw_vlan_attr {
++      uint16_t fdb_id;
++      uint16_t num_ifs;
++      uint16_t num_untagged_ifs;
++      uint16_t num_flooding_ifs;
++};
++
++/**
++ * dpsw_vlan_get_attributes() - Get VLAN attributes
++ * @mc_io:    Pointer to MC portal's I/O object
++ * @cmd_flags:        Command flags; one or more of 'MC_CMD_FLAG_'
++ * @token:    Token of DPSW object
++ * @vlan_id:  VLAN Identifier
++ * @attr:     Returned DPSW attributes
++ *
++ * Return:    Completion status. '0' on Success; Error code otherwise.
++ */
++int dpsw_vlan_get_attributes(struct fsl_mc_io         *mc_io,
++                           uint32_t                   cmd_flags,
++                           uint16_t                   token,
++                           uint16_t                   vlan_id,
++                           struct dpsw_vlan_attr      *attr);
++
++/**
++ * dpsw_vlan_get_if() - Get interfaces belong to this VLAN
++ * @mc_io:    Pointer to MC portal's I/O object
++ * @cmd_flags:        Command flags; one or more of 'MC_CMD_FLAG_'
++ * @token:    Token of DPSW object
++ * @vlan_id:  VLAN Identifier
++ * @cfg:      Returned set of interfaces belong to this VLAN
++ *
++ * Return:    Completion status. '0' on Success; Error code otherwise.
++ */
++int dpsw_vlan_get_if(struct fsl_mc_io         *mc_io,
++                   uint32_t                   cmd_flags,
++                   uint16_t                   token,
++                   uint16_t                   vlan_id,
++                   struct dpsw_vlan_if_cfg    *cfg);
++
++/**
++ * dpsw_vlan_get_if_flooding() - Get interfaces used in flooding for this VLAN
++ * @mc_io:    Pointer to MC portal's I/O object
++ * @cmd_flags:        Command flags; one or more of 'MC_CMD_FLAG_'
++ * @token:    Token of DPSW object
++ * @vlan_id:  VLAN Identifier
++ * @cfg:      Returned set of flooding interfaces
++ *
++ * Return:    Completion status. '0' on Success; Error code otherwise.
++ */
++int dpsw_vlan_get_if_flooding(struct fsl_mc_io                *mc_io,
++                            uint32_t                  cmd_flags,
++                            uint16_t                  token,
++                            uint16_t                  vlan_id,
++                            struct dpsw_vlan_if_cfg   *cfg);
++
++/**
++ * dpsw_vlan_get_if_untagged() - Get interfaces that should be transmitted as
++ *                            untagged
++ * @mc_io:    Pointer to MC portal's I/O object
++ * @cmd_flags:        Command flags; one or more of 'MC_CMD_FLAG_'
++ * @token:    Token of DPSW object
++ * @vlan_id:  VLAN Identifier
++ * @cfg:      Returned set of untagged interfaces
++ *
++ * Return:    Completion status. '0' on Success; Error code otherwise.
++ */
++int dpsw_vlan_get_if_untagged(struct fsl_mc_io                *mc_io,
++                            uint32_t                  cmd_flags,
++                            uint16_t                  token,
++                            uint16_t                  vlan_id,
++                            struct dpsw_vlan_if_cfg   *cfg);
++
++/**
++ * struct dpsw_fdb_cfg  - FDB Configuration
++ * @num_fdb_entries: Number of FDB entries
++ * @fdb_aging_time: Aging time in seconds
++ */
++struct dpsw_fdb_cfg {
++      uint16_t num_fdb_entries;
++      uint16_t fdb_aging_time;
++};
++
++/**
++ * dpsw_fdb_add() - Add FDB to switch and Returns handle to FDB table for
++ *            the reference
++ * @mc_io:    Pointer to MC portal's I/O object
++ * @cmd_flags:        Command flags; one or more of 'MC_CMD_FLAG_'
++ * @token:    Token of DPSW object
++ * @fdb_id:   Returned Forwarding Database Identifier
++ * @cfg:      FDB Configuration
++ *
++ * Return:    Completion status. '0' on Success; Error code otherwise.
++ */
++int dpsw_fdb_add(struct fsl_mc_io             *mc_io,
++               uint32_t                       cmd_flags,
++               uint16_t                       token,
++               uint16_t                       *fdb_id,
++               const struct dpsw_fdb_cfg      *cfg);
++
++/**
++ * dpsw_fdb_remove() - Remove FDB from switch
++ * @mc_io:    Pointer to MC portal's I/O object
++ * @cmd_flags:        Command flags; one or more of 'MC_CMD_FLAG_'
++ * @token:    Token of DPSW object
++ * @fdb_id:   Forwarding Database Identifier
++ *
++ * Return:    Completion status. '0' on Success; Error code otherwise.
++ */
++int dpsw_fdb_remove(struct fsl_mc_io  *mc_io,
++                  uint32_t            cmd_flags,
++                  uint16_t            token,
++                  uint16_t            fdb_id);
++
++/**
++ * enum dpsw_fdb_entry_type - FDB Entry type - Static/Dynamic
++ * @DPSW_FDB_ENTRY_STATIC: Static entry
++ * @DPSW_FDB_ENTRY_DINAMIC: Dynamic entry
++ */
++enum dpsw_fdb_entry_type {
++      DPSW_FDB_ENTRY_STATIC = 0,
++      DPSW_FDB_ENTRY_DINAMIC = 1
++};
++
++/**
++ * struct dpsw_fdb_unicast_cfg - Unicast entry configuration
++ * @type: Select static or dynamic entry
++ * @mac_addr: MAC address
++ * @if_egress: Egress interface ID
++ */
++struct dpsw_fdb_unicast_cfg {
++      enum dpsw_fdb_entry_type        type;
++      uint8_t                 mac_addr[6];
++      uint16_t                        if_egress;
++};
++
++/**
++ * dpsw_fdb_add_unicast() - Function adds an unicast entry into MAC lookup table
++ * @mc_io:    Pointer to MC portal's I/O object
++ * @cmd_flags:        Command flags; one or more of 'MC_CMD_FLAG_'
++ * @token:    Token of DPSW object
++ * @fdb_id:   Forwarding Database Identifier
++ * @cfg:      Unicast entry configuration
++ *
++ * Return:    Completion status. '0' on Success; Error code otherwise.
++ */
++int dpsw_fdb_add_unicast(struct fsl_mc_io                     *mc_io,
++                       uint32_t                               cmd_flags,
++                       uint16_t                               token,
++                       uint16_t                               fdb_id,
++                       const struct dpsw_fdb_unicast_cfg      *cfg);
++
++/**
++ * dpsw_fdb_get_unicast() - Get unicast entry from MAC lookup table by
++ *            unicast Ethernet address
++ * @mc_io:    Pointer to MC portal's I/O object
++ * @cmd_flags:        Command flags; one or more of 'MC_CMD_FLAG_'
++ * @token:    Token of DPSW object
++ * @fdb_id:   Forwarding Database Identifier
++ * @cfg:      Returned unicast entry configuration
++ *
++ * Return:    Completion status. '0' on Success; Error code otherwise.
++ */
++int dpsw_fdb_get_unicast(struct fsl_mc_io             *mc_io,
++                       uint32_t                       cmd_flags,
++                       uint16_t                       token,
++                       uint16_t                       fdb_id,
++                       struct dpsw_fdb_unicast_cfg    *cfg);
++
++/**
++ * dpsw_fdb_remove_unicast() - removes an entry from MAC lookup table
++ * @mc_io:    Pointer to MC portal's I/O object
++ * @cmd_flags:        Command flags; one or more of 'MC_CMD_FLAG_'
++ * @token:    Token of DPSW object
++ * @fdb_id:   Forwarding Database Identifier
++ * @cfg:      Unicast entry configuration
++ *
++ * Return:    Completion status. '0' on Success; Error code otherwise.
++ */
++int dpsw_fdb_remove_unicast(struct fsl_mc_io                  *mc_io,
++                          uint32_t                            cmd_flags,
++                          uint16_t                            token,
++                          uint16_t                            fdb_id,
++                          const struct dpsw_fdb_unicast_cfg   *cfg);
++
++/**
++ * struct dpsw_fdb_multicast_cfg - Multi-cast entry configuration
++ * @type: Select static or dynamic entry
++ * @mac_addr: MAC address
++ * @num_ifs: Number of external and internal interfaces
++ * @if_id: Egress interface IDs
++ */
++struct dpsw_fdb_multicast_cfg {
++      enum dpsw_fdb_entry_type        type;
++      uint8_t                 mac_addr[6];
++      uint16_t                        num_ifs;
++      uint16_t                        if_id[DPSW_MAX_IF];
++};
++
++/**
++ * dpsw_fdb_add_multicast() - Add a set of egress interfaces to multi-cast group
++ * @mc_io:    Pointer to MC portal's I/O object
++ * @cmd_flags:        Command flags; one or more of 'MC_CMD_FLAG_'
++ * @token:    Token of DPSW object
++ * @fdb_id:   Forwarding Database Identifier
++ * @cfg:      Multicast entry configuration
++ *
++ * If group doesn't exist, it will be created.
++ * It adds only interfaces not belonging to this multicast group
++ * yet, otherwise error will be generated and the command is
++ * ignored.
++ * This function may be called numerous times always providing
++ * required interfaces delta.
++ *
++ * Return:    Completion status. '0' on Success; Error code otherwise.
++ */
++int dpsw_fdb_add_multicast(struct fsl_mc_io                   *mc_io,
++                         uint32_t                             cmd_flags,
++                         uint16_t                             token,
++                         uint16_t                             fdb_id,
++                         const struct dpsw_fdb_multicast_cfg  *cfg);
++
++/**
++ * dpsw_fdb_get_multicast() - Reading multi-cast group by multi-cast Ethernet
++ *                            address.
++ * @mc_io:    Pointer to MC portal's I/O object
++ * @cmd_flags:        Command flags; one or more of 'MC_CMD_FLAG_'
++ * @token:    Token of DPSW object
++ * @fdb_id:   Forwarding Database Identifier
++ * @cfg:      Returned multicast entry configuration
++ *
++ * Return:    Completion status. '0' on Success; Error code otherwise.
++ */
++int dpsw_fdb_get_multicast(struct fsl_mc_io                   *mc_io,
++                         uint32_t                             cmd_flags,
++                         uint16_t                             token,
++                         uint16_t                             fdb_id,
++                         struct dpsw_fdb_multicast_cfg        *cfg);
++
++/**
++ * dpsw_fdb_remove_multicast() - Removing interfaces from an existing multicast
++ *                            group.
++ * @mc_io:    Pointer to MC portal's I/O object
++ * @cmd_flags:        Command flags; one or more of 'MC_CMD_FLAG_'
++ * @token:    Token of DPSW object
++ * @fdb_id:   Forwarding Database Identifier
++ * @cfg:      Multicast entry configuration
++ *
++ * Interfaces provided by this API have to exist in the group,
++ * otherwise an error will be returned and an entire command
++ * ignored. If there is no interface left in the group,
++ * an entire group is deleted
++ *
++ * Return:    Completion status. '0' on Success; Error code otherwise.
++ */
++int dpsw_fdb_remove_multicast(struct fsl_mc_io                        *mc_io,
++                            uint32_t                          cmd_flags,
++                            uint16_t                          token,
++                            uint16_t                          fdb_id,
++                            const struct dpsw_fdb_multicast_cfg *cfg);
++
++/**
++ * enum dpsw_fdb_learning_mode - Auto-learning modes
++ * @DPSW_FDB_LEARNING_MODE_DIS: Disable Auto-learning
++ * @DPSW_FDB_LEARNING_MODE_HW: Enable HW auto-Learning
++ * @DPSW_FDB_LEARNING_MODE_NON_SECURE: Enable None secure learning by CPU
++ * @DPSW_FDB_LEARNING_MODE_SECURE: Enable secure learning by CPU
++ *
++ *    NONE - SECURE LEARNING
++ *    SMAC found      DMAC found      CTLU Action
++ *    v               v       Forward frame to
++ *                                            1.  DMAC destination
++ *    -               v       Forward frame to
++ *                                            1.  DMAC destination
++ *                                            2.  Control interface
++ *    v               -       Forward frame to
++ *                                            1.  Flooding list of interfaces
++ *    -               -       Forward frame to
++ *                                            1.  Flooding list of interfaces
++ *                                            2.  Control interface
++ *    SECURE LEARING
++ *    SMAC found      DMAC found      CTLU Action
++ *    v               v               Forward frame to
++ *                                            1.  DMAC destination
++ *    -               v               Forward frame to
++ *                                            1.  Control interface
++ *    v               -               Forward frame to
++ *                                            1.  Flooding list of interfaces
++ *    -               -               Forward frame to
++ *                                            1.  Control interface
++ */
++enum dpsw_fdb_learning_mode {
++      DPSW_FDB_LEARNING_MODE_DIS = 0,
++      DPSW_FDB_LEARNING_MODE_HW = 1,
++      DPSW_FDB_LEARNING_MODE_NON_SECURE = 2,
++      DPSW_FDB_LEARNING_MODE_SECURE = 3
++};
++
++/**
++ * dpsw_fdb_set_learning_mode() - Define FDB learning mode
++ * @mc_io:    Pointer to MC portal's I/O object
++ * @cmd_flags:        Command flags; one or more of 'MC_CMD_FLAG_'
++ * @token:    Token of DPSW object
++ * @fdb_id:   Forwarding Database Identifier
++ * @mode:     learning mode
++ *
++ * Return:    Completion status. '0' on Success; Error code otherwise.
++ */
++int dpsw_fdb_set_learning_mode(struct fsl_mc_io               *mc_io,
++                             uint32_t                 cmd_flags,
++                             uint16_t                 token,
++                             uint16_t                 fdb_id,
++                             enum dpsw_fdb_learning_mode      mode);
++
++/**
++ * struct dpsw_fdb_attr - FDB Attributes
++ * @max_fdb_entries: Number of FDB entries
++ * @fdb_aging_time: Aging time in seconds
++ * @learning_mode: Learning mode
++ * @num_fdb_mc_groups: Current number of multicast groups
++ * @max_fdb_mc_groups: Maximum number of multicast groups
++ */
++struct dpsw_fdb_attr {
++      uint16_t                        max_fdb_entries;
++      uint16_t                        fdb_aging_time;
++      enum dpsw_fdb_learning_mode     learning_mode;
++      uint16_t                        num_fdb_mc_groups;
++      uint16_t                        max_fdb_mc_groups;
++};
++
++/**
++ * dpsw_fdb_get_attributes() - Get FDB attributes
++ * @mc_io:    Pointer to MC portal's I/O object
++ * @cmd_flags:        Command flags; one or more of 'MC_CMD_FLAG_'
++ * @token:    Token of DPSW object
++ * @fdb_id:   Forwarding Database Identifier
++ * @attr:     Returned FDB attributes
++ *
++ * Return:    Completion status. '0' on Success; Error code otherwise.
++ */
++int dpsw_fdb_get_attributes(struct fsl_mc_io          *mc_io,
++                          uint32_t                    cmd_flags,
++                          uint16_t                    token,
++                          uint16_t                    fdb_id,
++                          struct dpsw_fdb_attr        *attr);
++
++/**
++ * struct dpsw_acl_cfg - ACL Configuration
++ * @max_entries: Number of FDB entries
++ */
++struct dpsw_acl_cfg {
++      uint16_t        max_entries;
++};
++
++/**
++ * struct dpsw_acl_fields - ACL fields.
++ * @l2_dest_mac: Destination MAC address: BPDU, Multicast, Broadcast, Unicast,
++ *                    slow protocols, MVRP, STP
++ * @l2_source_mac: Source MAC address
++ * @l2_tpid: Layer 2 (Ethernet) protocol type, used to identify the following
++ *            protocols: MPLS, PTP, PFC, ARP, Jumbo frames, LLDP, IEEE802.1ae,
++ *            Q-in-Q, IPv4, IPv6, PPPoE
++ * @l2_pcp_dei: indicate which protocol is encapsulated in the payload
++ * @l2_vlan_id: layer 2 VLAN ID
++ * @l2_ether_type: layer 2 Ethernet type
++ * @l3_dscp: Layer 3 differentiated services code point
++ * @l3_protocol: Tells the Network layer at the destination host, to which
++ *            Protocol this packet belongs to. The following protocol are
++ *            supported: ICMP, IGMP, IPv4 (encapsulation), TCP, IPv6
++ *            (encapsulation), GRE, PTP
++ * @l3_source_ip: Source IPv4 IP
++ * @l3_dest_ip: Destination IPv4 IP
++ * @l4_source_port: Source TCP/UDP Port
++ * @l4_dest_port: Destination TCP/UDP Port
++ */
++struct dpsw_acl_fields {
++      uint8_t         l2_dest_mac[6];
++      uint8_t         l2_source_mac[6];
++      uint16_t        l2_tpid;
++      uint8_t         l2_pcp_dei;
++      uint16_t        l2_vlan_id;
++      uint16_t        l2_ether_type;
++      uint8_t         l3_dscp;
++      uint8_t         l3_protocol;
++      uint32_t        l3_source_ip;
++      uint32_t        l3_dest_ip;
++      uint16_t        l4_source_port;
++      uint16_t        l4_dest_port;
++};
++
++/**
++ * struct dpsw_acl_key - ACL key
++ * @match: Match fields
++ * @mask: Mask: b'1 - valid, b'0 don't care
++ */
++struct dpsw_acl_key {
++      struct dpsw_acl_fields  match;
++      struct dpsw_acl_fields  mask;
++};
++
++/**
++ * enum dpsw_acl_action
++ * @DPSW_ACL_ACTION_DROP: Drop frame
++ * @DPSW_ACL_ACTION_REDIRECT: Redirect to certain port
++ * @DPSW_ACL_ACTION_ACCEPT: Accept frame
++ * @DPSW_ACL_ACTION_REDIRECT_TO_CTRL_IF: Redirect to control interface
++ */
++enum dpsw_acl_action {
++      DPSW_ACL_ACTION_DROP,
++      DPSW_ACL_ACTION_REDIRECT,
++      DPSW_ACL_ACTION_ACCEPT,
++      DPSW_ACL_ACTION_REDIRECT_TO_CTRL_IF
++};
++
++/**
++ * struct dpsw_acl_result - ACL action
++ * @action: Action should be taken when       ACL entry hit
++ * @if_id:  Interface IDs to redirect frame. Valid only if redirect selected for
++ *             action
++ */
++struct dpsw_acl_result {
++      enum dpsw_acl_action    action;
++      uint16_t                if_id;
++};
++
++/**
++ * struct dpsw_acl_entry_cfg - ACL entry
++ * @key_iova: I/O virtual address of DMA-able memory filled with key after call
++ *                            to dpsw_acl_prepare_entry_cfg()
++ * @result: Required action when entry hit occurs
++ * @precedence: Precedence inside ACL 0 is lowest; This priority can not change
++ *            during the lifetime of a Policy. It is user responsibility to
++ *            space the priorities according to consequent rule additions.
++ */
++struct dpsw_acl_entry_cfg {
++      uint64_t                key_iova;
++      struct dpsw_acl_result  result;
++      int                     precedence;
++};
++
++/**
++ * dpsw_acl_add() - Adds ACL to L2 switch.
++ * @mc_io:    Pointer to MC portal's I/O object
++ * @cmd_flags:        Command flags; one or more of 'MC_CMD_FLAG_'
++ * @token:    Token of DPSW object
++ * @acl_id:   Returned ACL ID, for the future reference
++ * @cfg:      ACL configuration
++ *
++ * Create Access Control List. Multiple ACLs can be created and
++ * co-exist in L2 switch
++ *
++ * Return:    '0' on Success; Error code otherwise.
++ */
++int dpsw_acl_add(struct fsl_mc_io             *mc_io,
++               uint32_t                       cmd_flags,
++               uint16_t                       token,
++               uint16_t                       *acl_id,
++               const struct dpsw_acl_cfg      *cfg);
++
++/**
++ * dpsw_acl_remove() - Removes ACL from L2 switch.
++ * @mc_io:    Pointer to MC portal's I/O object
++ * @cmd_flags:        Command flags; one or more of 'MC_CMD_FLAG_'
++ * @token:    Token of DPSW object
++ * @acl_id:   ACL ID
++ *
++ * Return:    '0' on Success; Error code otherwise.
++ */
++int dpsw_acl_remove(struct fsl_mc_io  *mc_io,
++                  uint32_t            cmd_flags,
++                  uint16_t            token,
++                  uint16_t            acl_id);
++
++/**
++ * dpsw_acl_prepare_entry_cfg() - Set an entry to ACL.
++ * @key:      key
++ * @entry_cfg_buf: Zeroed 256 bytes of memory before mapping it to DMA
++ *
++ * This function has to be called before adding or removing acl_entry
++ *
++ */
++void dpsw_acl_prepare_entry_cfg(const struct dpsw_acl_key     *key,
++                              uint8_t                 *entry_cfg_buf);
++
++/**
++ * dpsw_acl_add_entry() - Adds an entry to ACL.
++ * @mc_io:    Pointer to MC portal's I/O object
++ * @cmd_flags:        Command flags; one or more of 'MC_CMD_FLAG_'
++ * @token:    Token of DPSW object
++ * @acl_id:   ACL ID
++ * @cfg:      entry configuration
++ *
++ * warning: This function has to be called after dpsw_acl_set_entry_cfg()
++ *
++ * Return:    '0' on Success; Error code otherwise.
++ */
++int dpsw_acl_add_entry(struct fsl_mc_io               *mc_io,
++                     uint32_t                 cmd_flags,
++                     uint16_t                 token,
++                     uint16_t                 acl_id,
++                     const struct dpsw_acl_entry_cfg  *cfg);
++
++/**
++ * dpsw_acl_remove_entry() - Removes an entry from ACL.
++ * @mc_io:    Pointer to MC portal's I/O object
++ * @cmd_flags:        Command flags; one or more of 'MC_CMD_FLAG_'
++ * @token:    Token of DPSW object
++ * @acl_id:   ACL ID
++ * @cfg:      entry configuration
++ *
++ * warning: This function has to be called after dpsw_acl_set_entry_cfg()
++ *
++ * Return:    '0' on Success; Error code otherwise.
++ */
++int dpsw_acl_remove_entry(struct fsl_mc_io                    *mc_io,
++                        uint32_t                              cmd_flags,
++                        uint16_t                              token,
++                        uint16_t                              acl_id,
++                        const struct dpsw_acl_entry_cfg       *cfg);
++
++/**
++ * struct dpsw_acl_if_cfg - List of interfaces to Associate with ACL
++ * @num_ifs: Number of interfaces
++ * @if_id: List of interfaces
++ */
++struct dpsw_acl_if_cfg {
++      uint16_t        num_ifs;
++      uint16_t        if_id[DPSW_MAX_IF];
++};
++
++/**
++ * dpsw_acl_add_if() - Associate interface/interfaces with ACL.
++ * @mc_io:    Pointer to MC portal's I/O object
++ * @cmd_flags:        Command flags; one or more of 'MC_CMD_FLAG_'
++ * @token:    Token of DPSW object
++ * @acl_id:   ACL ID
++ * @cfg:      interfaces list
++ *
++ * Return:    '0' on Success; Error code otherwise.
++ */
++int dpsw_acl_add_if(struct fsl_mc_io                  *mc_io,
++                  uint32_t                            cmd_flags,
++                  uint16_t                            token,
++                  uint16_t                            acl_id,
++                  const struct dpsw_acl_if_cfg        *cfg);
++
++/**
++ * dpsw_acl_remove_if() - De-associate interface/interfaces from ACL.
++ * @mc_io:    Pointer to MC portal's I/O object
++ * @cmd_flags:        Command flags; one or more of 'MC_CMD_FLAG_'
++ * @token:    Token of DPSW object
++ * @acl_id:   ACL ID
++ * @cfg:      interfaces list
++ *
++ * Return:    '0' on Success; Error code otherwise.
++ */
++int dpsw_acl_remove_if(struct fsl_mc_io               *mc_io,
++                     uint32_t                 cmd_flags,
++                     uint16_t                 token,
++                     uint16_t                 acl_id,
++                     const struct dpsw_acl_if_cfg     *cfg);
++
++/**
++ * struct dpsw_acl_attr -  ACL Attributes
++ * @max_entries: Max number of ACL entries
++ * @num_entries: Number of used ACL entries
++ * @num_ifs: Number of interfaces associated with ACL
++ */
++struct dpsw_acl_attr {
++      uint16_t max_entries;
++      uint16_t num_entries;
++      uint16_t num_ifs;
++};
++
++/**
++* dpsw_acl_get_attributes() - Get specific counter of particular interface
++* @mc_io:     Pointer to MC portal's I/O object
++* @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
++* @token:     Token of DPSW object
++* @acl_id:      ACL Identifier
++* @attr:        Returned ACL attributes
++*
++* Return:     '0' on Success; Error code otherwise.
++*/
++int dpsw_acl_get_attributes(struct fsl_mc_io          *mc_io,
++                          uint32_t                    cmd_flags,
++                          uint16_t                    token,
++                          uint16_t                    acl_id,
++                          struct dpsw_acl_attr        *attr);
++/**
++* struct dpsw_ctrl_if_attr - Control interface attributes
++* @rx_fqid:           Receive FQID
++* @rx_err_fqid:               Receive error FQID
++* @tx_err_conf_fqid:  Transmit error and confirmation FQID
++*/
++struct dpsw_ctrl_if_attr {
++      uint32_t        rx_fqid;
++      uint32_t        rx_err_fqid;
++      uint32_t        tx_err_conf_fqid;
++};
++
++/**
++* dpsw_ctrl_if_get_attributes() - Obtain control interface attributes
++* @mc_io:     Pointer to MC portal's I/O object
++* @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
++* @token:     Token of DPSW object
++* @attr:        Returned control interface attributes
++*
++* Return:     '0' on Success; Error code otherwise.
++*/
++int dpsw_ctrl_if_get_attributes(struct fsl_mc_io              *mc_io,
++                              uint32_t                        cmd_flags,
++                              uint16_t                        token,
++                              struct dpsw_ctrl_if_attr        *attr);
++
++/**
++ * Maximum number of DPBP
++ */
++#define DPSW_MAX_DPBP     8
++
++/**
++ * struct dpsw_ctrl_if_pools_cfg - Control interface buffer pools configuration
++ * @num_dpbp: Number of DPBPs
++ * @pools: Array of buffer pools parameters; The number of valid entries
++ *    must match 'num_dpbp' value
++ */
++struct dpsw_ctrl_if_pools_cfg {
++      uint8_t num_dpbp;
++      /**
++      * struct pools - Buffer pools parameters
++      * @dpbp_id: DPBP object ID
++      * @buffer_size: Buffer size
++      * @backup_pool: Backup pool
++      */
++      struct {
++              int dpbp_id;
++              uint16_t buffer_size;
++              int backup_pool;
++      } pools[DPSW_MAX_DPBP];
++};
++
++/**
++* dpsw_ctrl_if_set_pools() - Set control interface buffer pools
++* @mc_io:     Pointer to MC portal's I/O object
++* @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
++* @token:     Token of DPSW object
++* @cfg:         buffer pools configuration
++*
++* Return:     '0' on Success; Error code otherwise.
++*/
++int dpsw_ctrl_if_set_pools(struct fsl_mc_io                   *mc_io,
++                         uint32_t                             cmd_flags,
++                         uint16_t                             token,
++                         const struct dpsw_ctrl_if_pools_cfg *cfg);
++
++/**
++* dpsw_ctrl_if_enable() - Enable control interface
++* @mc_io:     Pointer to MC portal's I/O object
++* @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
++* @token:     Token of DPSW object
++*
++* Return:     '0' on Success; Error code otherwise.
++*/
++int dpsw_ctrl_if_enable(struct fsl_mc_io      *mc_io,
++                      uint32_t                cmd_flags,
++                      uint16_t                token);
++
++/**
++* dpsw_ctrl_if_disable() - Function disables control interface
++* @mc_io:     Pointer to MC portal's I/O object
++* @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
++* @token:     Token of DPSW object
++*
++* Return:     '0' on Success; Error code otherwise.
++*/
++int dpsw_ctrl_if_disable(struct fsl_mc_io     *mc_io,
++                       uint32_t               cmd_flags,
++                       uint16_t               token);
++
++#endif /* __FSL_DPSW_H */
+--- /dev/null
++++ b/drivers/staging/fsl-dpaa2/ethsw/switch.c
+@@ -0,0 +1,1711 @@
++/* Copyright 2014-2015 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/module.h>
++
++#include <linux/netdevice.h>
++#include <linux/etherdevice.h>
++#include <linux/rtnetlink.h>
++#include <linux/if_vlan.h>
++#include <linux/interrupt.h>
++#include <linux/msi.h>
++
++#include <uapi/linux/if_bridge.h>
++#include <net/netlink.h>
++
++#include "../../fsl-mc/include/mc.h"
++#include "dpsw.h"
++#include "dpsw-cmd.h"
++
++/* Minimal supported DPSE version */
++#define DPSW_MIN_VER_MAJOR    7
++#define DPSW_MIN_VER_MINOR    0
++
++/* IRQ index */
++#define DPSW_MAX_IRQ_NUM              2
++
++#define ETHSW_VLAN_MEMBER     1
++#define ETHSW_VLAN_UNTAGGED   2
++#define ETHSW_VLAN_PVID               4
++#define ETHSW_VLAN_GLOBAL     8
++
++struct ethsw_port_priv {
++      struct net_device       *netdev;
++      struct list_head        list;
++      u16                     port_index;
++      struct ethsw_dev_priv   *ethsw_priv;
++      u8                      stp_state;
++
++      char                    vlans[VLAN_VID_MASK+1];
++
++};
++
++struct ethsw_dev_priv {
++      struct net_device               *netdev;
++      struct fsl_mc_io                *mc_io;
++      uint16_t                        dpsw_handle;
++      struct dpsw_attr                sw_attr;
++      int                             dev_id;
++      /*TODO: redundant, we can use the slave dev list */
++      struct list_head                port_list;
++
++      bool                            flood;
++      bool                            learning;
++
++      char                            vlans[VLAN_VID_MASK+1];
++};
++
++static int ethsw_port_stop(struct net_device *netdev);
++static int ethsw_port_open(struct net_device *netdev);
++
++static inline void __get_priv(struct net_device *netdev,
++                            struct ethsw_dev_priv **priv,
++                            struct ethsw_port_priv **port_priv)
++{
++      struct ethsw_dev_priv *_priv = NULL;
++      struct ethsw_port_priv *_port_priv = NULL;
++
++      if (netdev->flags & IFF_MASTER) {
++              _priv = netdev_priv(netdev);
++      } else {
++              _port_priv = netdev_priv(netdev);
++              _priv = _port_priv->ethsw_priv;
++      }
++
++      if (priv)
++              *priv = _priv;
++      if (port_priv)
++              *port_priv = _port_priv;
++}
++
++/* -------------------------------------------------------------------------- */
++/* ethsw netdevice ops */
++
++static netdev_tx_t ethsw_dropframe(struct sk_buff *skb, struct net_device *dev)
++{
++      /* we don't support I/O for now, drop the frame */
++      dev_kfree_skb_any(skb);
++      return NETDEV_TX_OK;
++}
++
++static int ethsw_open(struct net_device *netdev)
++{
++      struct ethsw_dev_priv   *priv = netdev_priv(netdev);
++      struct list_head        *pos;
++      struct ethsw_port_priv  *port_priv = NULL;
++      int                     err;
++
++      err = dpsw_enable(priv->mc_io, 0, priv->dpsw_handle);
++      if (err) {
++              netdev_err(netdev, "dpsw_enable err %d\n", err);
++              return err;
++      }
++
++      list_for_each(pos, &priv->port_list) {
++              port_priv = list_entry(pos, struct ethsw_port_priv, list);
++              err = dev_open(port_priv->netdev);
++              if (err)
++                      netdev_err(port_priv->netdev, "dev_open err %d\n", err);
++      }
++
++      return 0;
++}
++
++static int ethsw_stop(struct net_device *netdev)
++{
++      struct ethsw_dev_priv   *priv = netdev_priv(netdev);
++      struct list_head        *pos;
++      struct ethsw_port_priv  *port_priv = NULL;
++      int                     err;
++
++      err = dpsw_disable(priv->mc_io, 0, priv->dpsw_handle);
++      if (err) {
++              netdev_err(netdev, "dpsw_disable err %d\n", err);
++              return err;
++      }
++
++      list_for_each(pos, &priv->port_list) {
++              port_priv = list_entry(pos, struct ethsw_port_priv, list);
++              err = dev_close(port_priv->netdev);
++              if (err)
++                      netdev_err(port_priv->netdev,
++                                 "dev_close err %d\n", err);
++      }
++
++      return 0;
++}
++
++static int ethsw_add_vlan(struct net_device *netdev, u16 vid)
++{
++      struct ethsw_dev_priv   *priv = netdev_priv(netdev);
++      int                     err;
++
++      struct dpsw_vlan_cfg    vcfg = {
++              /* TODO: add support for VLAN private FDBs */
++              .fdb_id = 0,
++      };
++      if (priv->vlans[vid]) {
++              netdev_err(netdev, "VLAN already configured\n");
++              return -EEXIST;
++      }
++
++      err = dpsw_vlan_add(priv->mc_io, 0, priv->dpsw_handle, vid, &vcfg);
++      if (err) {
++              netdev_err(netdev, "dpsw_vlan_add err %d\n", err);
++              return err;
++      }
++      priv->vlans[vid] = ETHSW_VLAN_MEMBER;
++
++      return 0;
++}
++
++static int ethsw_port_add_vlan(struct net_device *netdev, u16 vid, u16 flags)
++{
++      struct ethsw_port_priv  *port_priv = netdev_priv(netdev);
++      struct ethsw_dev_priv   *priv = port_priv->ethsw_priv;
++      int                     err;
++
++      struct dpsw_vlan_if_cfg vcfg = {
++              .num_ifs = 1,
++              .if_id[0] = port_priv->port_index,
++      };
++
++      if (port_priv->vlans[vid]) {
++              netdev_err(netdev, "VLAN already configured\n");
++              return -EEXIST;
++      }
++
++      if (flags & BRIDGE_VLAN_INFO_PVID && netif_oper_up(netdev)) {
++              netdev_err(netdev, "interface must be down to change PVID!\n");
++              return -EBUSY;
++      }
++
++      err = dpsw_vlan_add_if(priv->mc_io, 0, priv->dpsw_handle, vid, &vcfg);
++      if (err) {
++              netdev_err(netdev, "dpsw_vlan_add_if err %d\n", err);
++              return err;
++      }
++      port_priv->vlans[vid] = ETHSW_VLAN_MEMBER;
++
++      if (flags & BRIDGE_VLAN_INFO_UNTAGGED) {
++              err = dpsw_vlan_add_if_untagged(priv->mc_io, 0,
++                                              priv->dpsw_handle, vid, &vcfg);
++              if (err) {
++                      netdev_err(netdev, "dpsw_vlan_add_if_untagged err %d\n",
++                                 err);
++                      return err;
++              }
++              port_priv->vlans[vid] |= ETHSW_VLAN_UNTAGGED;
++      }
++
++      if (flags & BRIDGE_VLAN_INFO_PVID) {
++              struct dpsw_tci_cfg tci_cfg = {
++                      /* TODO: at least add better defaults if these cannot
++                       * be configured
++                       */
++                      .pcp = 0,
++                      .dei = 0,
++                      .vlan_id = vid,
++              };
++
++              err = dpsw_if_set_tci(priv->mc_io, 0, priv->dpsw_handle,
++                                    port_priv->port_index, &tci_cfg);
++              if (err) {
++                      netdev_err(netdev, "dpsw_if_set_tci err %d\n", err);
++                      return err;
++              }
++              port_priv->vlans[vid] |= ETHSW_VLAN_PVID;
++      }
++
++      return 0;
++}
++
++static const struct nla_policy ifla_br_policy[IFLA_MAX+1] = {
++      [IFLA_BRIDGE_FLAGS]     = { .type = NLA_U16 },
++      [IFLA_BRIDGE_MODE]      = { .type = NLA_U16 },
++      [IFLA_BRIDGE_VLAN_INFO] = { .type = NLA_BINARY,
++                              .len = sizeof(struct bridge_vlan_info), },
++};
++
++static int ethsw_setlink_af_spec(struct net_device *netdev,
++                               struct nlattr **tb)
++{
++      struct bridge_vlan_info *vinfo;
++      struct ethsw_dev_priv   *priv = NULL;
++      struct ethsw_port_priv  *port_priv = NULL;
++      int                     err = 0;
++
++      if (!tb[IFLA_BRIDGE_VLAN_INFO]) {
++              netdev_err(netdev, "no VLAN INFO in nlmsg\n");
++              return -EOPNOTSUPP;
++      }
++
++      vinfo = nla_data(tb[IFLA_BRIDGE_VLAN_INFO]);
++
++      if (!vinfo->vid || vinfo->vid > VLAN_VID_MASK)
++              return -EINVAL;
++
++      __get_priv(netdev, &priv, &port_priv);
++
++      if (!port_priv || !priv->vlans[vinfo->vid]) {
++              /* command targets switch device or this is a new VLAN */
++              err = ethsw_add_vlan(priv->netdev, vinfo->vid);
++              if (err)
++                      return err;
++
++              /* command targets switch device; mark it*/
++              if (!port_priv)
++                      priv->vlans[vinfo->vid] |= ETHSW_VLAN_GLOBAL;
++      }
++
++      if (port_priv) {
++              /* command targets switch port */
++              err = ethsw_port_add_vlan(netdev, vinfo->vid, vinfo->flags);
++              if (err)
++                      return err;
++      }
++
++      return 0;
++}
++
++static const struct nla_policy ifla_brport_policy[IFLA_BRPORT_MAX + 1] = {
++      [IFLA_BRPORT_STATE]     = { .type = NLA_U8 },
++      [IFLA_BRPORT_COST]      = { .type = NLA_U32 },
++      [IFLA_BRPORT_PRIORITY]  = { .type = NLA_U16 },
++      [IFLA_BRPORT_MODE]      = { .type = NLA_U8 },
++      [IFLA_BRPORT_GUARD]     = { .type = NLA_U8 },
++      [IFLA_BRPORT_PROTECT]   = { .type = NLA_U8 },
++      [IFLA_BRPORT_LEARNING]  = { .type = NLA_U8 },
++      [IFLA_BRPORT_UNICAST_FLOOD] = { .type = NLA_U8 },
++};
++
++static int ethsw_set_learning(struct net_device *netdev, u8 flag)
++{
++      struct ethsw_dev_priv           *priv = netdev_priv(netdev);
++      enum dpsw_fdb_learning_mode     learn_mode;
++      int                             err;
++
++      if (flag)
++              learn_mode = DPSW_FDB_LEARNING_MODE_HW;
++      else
++              learn_mode = DPSW_FDB_LEARNING_MODE_DIS;
++
++      err = dpsw_fdb_set_learning_mode(priv->mc_io, 0, priv->dpsw_handle,
++                                       0, learn_mode);
++      if (err) {
++              netdev_err(netdev, "dpsw_fdb_set_learning_mode err %d\n", err);
++              return err;
++      }
++      priv->learning = !!flag;
++
++      return 0;
++}
++
++static int ethsw_port_set_flood(struct net_device *netdev, u8 flag)
++{
++      struct ethsw_port_priv  *port_priv = netdev_priv(netdev);
++      struct ethsw_dev_priv   *priv = port_priv->ethsw_priv;
++      int                     err;
++
++      err = dpsw_if_set_flooding(priv->mc_io, 0, priv->dpsw_handle,
++                                 port_priv->port_index, (int)flag);
++      if (err) {
++              netdev_err(netdev, "dpsw_fdb_set_learning_mode err %d\n", err);
++              return err;
++      }
++      priv->flood = !!flag;
++
++      return 0;
++}
++
++static int ethsw_port_set_state(struct net_device *netdev, u8 state)
++{
++      struct ethsw_port_priv  *port_priv = netdev_priv(netdev);
++      struct ethsw_dev_priv   *priv = port_priv->ethsw_priv;
++      u8                      old_state = port_priv->stp_state;
++      int                     err;
++
++      struct dpsw_stp_cfg stp_cfg = {
++              .vlan_id = 1,
++              .state = state,
++      };
++      /* TODO: check port state, interface may be down */
++
++      if (state > BR_STATE_BLOCKING)
++              return -EINVAL;
++
++      if (state == port_priv->stp_state)
++              return 0;
++
++      if (state == BR_STATE_DISABLED) {
++              port_priv->stp_state = state;
++
++              err = ethsw_port_stop(netdev);
++              if (err)
++                      goto error;
++      } else {
++              err = dpsw_if_set_stp(priv->mc_io, 0, priv->dpsw_handle,
++                                    port_priv->port_index, &stp_cfg);
++              if (err) {
++                      netdev_err(netdev, "dpsw_if_set_stp err %d\n", err);
++                      return err;
++              }
++
++              port_priv->stp_state = state;
++
++              if (old_state == BR_STATE_DISABLED) {
++                      err = ethsw_port_open(netdev);
++                      if (err)
++                              goto error;
++              }
++      }
++
++      return 0;
++error:
++      port_priv->stp_state = old_state;
++      return err;
++}
++
++static int ethsw_setlink_protinfo(struct net_device *netdev,
++                                struct nlattr **tb)
++{
++      struct ethsw_dev_priv   *priv;
++      struct ethsw_port_priv  *port_priv = NULL;
++      int                     err = 0;
++
++      __get_priv(netdev, &priv, &port_priv);
++
++      if (tb[IFLA_BRPORT_LEARNING]) {
++              u8 flag = nla_get_u8(tb[IFLA_BRPORT_LEARNING]);
++
++              if (port_priv)
++                      netdev_warn(netdev,
++                                  "learning set on whole switch dev\n");
++
++              err = ethsw_set_learning(priv->netdev, flag);
++              if (err)
++                      return err;
++
++      } else if (tb[IFLA_BRPORT_UNICAST_FLOOD] && port_priv) {
++              u8 flag = nla_get_u8(tb[IFLA_BRPORT_UNICAST_FLOOD]);
++
++              err = ethsw_port_set_flood(port_priv->netdev, flag);
++              if (err)
++                      return err;
++
++      } else if (tb[IFLA_BRPORT_STATE] && port_priv) {
++              u8 state = nla_get_u8(tb[IFLA_BRPORT_STATE]);
++
++              err = ethsw_port_set_state(port_priv->netdev, state);
++              if (err)
++                      return err;
++
++      } else {
++              return -EOPNOTSUPP;
++      }
++
++      return 0;
++}
++
++static int ethsw_setlink(struct net_device *netdev,
++                       struct nlmsghdr *nlh,
++                       u16 flags)
++{
++      struct nlattr   *attr;
++      struct nlattr   *tb[(IFLA_BRIDGE_MAX > IFLA_BRPORT_MAX) ?
++                              IFLA_BRIDGE_MAX : IFLA_BRPORT_MAX+1];
++      int err = 0;
++
++      attr = nlmsg_find_attr(nlh, sizeof(struct ifinfomsg), IFLA_AF_SPEC);
++      if (attr) {
++              err = nla_parse_nested(tb, IFLA_BRIDGE_MAX, attr,
++                                     ifla_br_policy);
++              if (err) {
++                      netdev_err(netdev,
++                                 "nla_parse_nested for br_policy err %d\n",
++                                 err);
++                      return err;
++              }
++
++              err = ethsw_setlink_af_spec(netdev, tb);
++              return err;
++      }
++
++      attr = nlmsg_find_attr(nlh, sizeof(struct ifinfomsg), IFLA_PROTINFO);
++      if (attr) {
++              err = nla_parse_nested(tb, IFLA_BRPORT_MAX, attr,
++                                     ifla_brport_policy);
++              if (err) {
++                      netdev_err(netdev,
++                                 "nla_parse_nested for brport_policy err %d\n",
++                                 err);
++                      return err;
++              }
++
++              err = ethsw_setlink_protinfo(netdev, tb);
++              return err;
++      }
++
++      netdev_err(netdev, "nlmsg_find_attr found no AF_SPEC/PROTINFO\n");
++      return -EOPNOTSUPP;
++}
++
++static int __nla_put_netdev(struct sk_buff *skb, struct net_device *netdev,
++                          struct ethsw_dev_priv *priv)
++{
++      u8 operstate = netif_running(netdev) ? netdev->operstate : IF_OPER_DOWN;
++      int iflink;
++      int err;
++
++      err = nla_put_string(skb, IFLA_IFNAME, netdev->name);
++      if (err)
++              goto nla_put_err;
++      err = nla_put_u32(skb, IFLA_MASTER, priv->netdev->ifindex);
++      if (err)
++              goto nla_put_err;
++      err = nla_put_u32(skb, IFLA_MTU, netdev->mtu);
++      if (err)
++              goto nla_put_err;
++      err = nla_put_u8(skb, IFLA_OPERSTATE, operstate);
++      if (err)
++              goto nla_put_err;
++      if (netdev->addr_len) {
++              err = nla_put(skb, IFLA_ADDRESS, netdev->addr_len,
++                            netdev->dev_addr);
++              if (err)
++                      goto nla_put_err;
++      }
++
++      iflink = dev_get_iflink(netdev);
++      if (netdev->ifindex != iflink) {
++              err = nla_put_u32(skb, IFLA_LINK, iflink);
++              if (err)
++                      goto nla_put_err;
++      }
++
++      return 0;
++
++nla_put_err:
++      netdev_err(netdev, "nla_put_ err %d\n", err);
++      return err;
++}
++
++static int __nla_put_port(struct sk_buff *skb, struct net_device *netdev,
++                        struct ethsw_port_priv *port_priv)
++{
++      struct nlattr *nest;
++      int err;
++
++      u8 stp_state = port_priv->stp_state;
++
++      if (port_priv->stp_state == DPSW_STP_STATE_BLOCKING)
++              stp_state = BR_STATE_BLOCKING;
++
++      nest = nla_nest_start(skb, IFLA_PROTINFO | NLA_F_NESTED);
++      if (!nest) {
++              netdev_err(netdev, "nla_nest_start failed\n");
++              return -ENOMEM;
++      }
++
++      err = nla_put_u8(skb, IFLA_BRPORT_STATE, stp_state);
++      if (err)
++              goto nla_put_err;
++      err = nla_put_u16(skb, IFLA_BRPORT_PRIORITY, 0);
++      if (err)
++              goto nla_put_err;
++      err = nla_put_u32(skb, IFLA_BRPORT_COST, 0);
++      if (err)
++              goto nla_put_err;
++      err = nla_put_u8(skb, IFLA_BRPORT_MODE, 0);
++      if (err)
++              goto nla_put_err;
++      err = nla_put_u8(skb, IFLA_BRPORT_GUARD, 0);
++      if (err)
++              goto nla_put_err;
++      err = nla_put_u8(skb, IFLA_BRPORT_PROTECT, 0);
++      if (err)
++              goto nla_put_err;
++      err = nla_put_u8(skb, IFLA_BRPORT_FAST_LEAVE, 0);
++      if (err)
++              goto nla_put_err;
++      err = nla_put_u8(skb, IFLA_BRPORT_LEARNING,
++                       port_priv->ethsw_priv->learning);
++      if (err)
++              goto nla_put_err;
++      err = nla_put_u8(skb, IFLA_BRPORT_UNICAST_FLOOD,
++                       port_priv->ethsw_priv->flood);
++      if (err)
++              goto nla_put_err;
++      nla_nest_end(skb, nest);
++
++      return 0;
++
++nla_put_err:
++      netdev_err(netdev, "nla_put_ err %d\n", err);
++      nla_nest_cancel(skb, nest);
++      return err;
++}
++
++static int __nla_put_vlan(struct sk_buff *skb,  struct net_device *netdev,
++                        struct ethsw_dev_priv *priv,
++                        struct ethsw_port_priv *port_priv)
++{
++      struct nlattr *nest;
++      struct bridge_vlan_info vinfo;
++      const char *vlans;
++      u16 i;
++      int err;
++
++      nest = nla_nest_start(skb, IFLA_AF_SPEC);
++      if (!nest) {
++              netdev_err(netdev, "nla_nest_start failed");
++              return -ENOMEM;
++      }
++
++      if (port_priv)
++              vlans = port_priv->vlans;
++      else
++              vlans = priv->vlans;
++
++      for (i = 0; i < VLAN_VID_MASK+1; i++) {
++              vinfo.flags = 0;
++              vinfo.vid = i;
++
++              if (vlans[i] & ETHSW_VLAN_UNTAGGED)
++                      vinfo.flags |= BRIDGE_VLAN_INFO_UNTAGGED;
++
++              if (vlans[i] & ETHSW_VLAN_PVID)
++                      vinfo.flags |= BRIDGE_VLAN_INFO_PVID;
++
++              if (vlans[i] & ETHSW_VLAN_MEMBER) {
++                      err = nla_put(skb, IFLA_BRIDGE_VLAN_INFO,
++                                    sizeof(vinfo), &vinfo);
++                      if (err)
++                              goto nla_put_err;
++              }
++      }
++
++      nla_nest_end(skb, nest);
++
++      return 0;
++nla_put_err:
++      netdev_err(netdev, "nla_put_ err %d\n", err);
++      nla_nest_cancel(skb, nest);
++      return err;
++}
++
++static int ethsw_getlink(struct sk_buff *skb, u32 pid, u32 seq,
++                       struct net_device *netdev, u32 filter_mask,
++                       int nlflags)
++{
++      struct ethsw_dev_priv   *priv;
++      struct ethsw_port_priv  *port_priv = NULL;
++      struct ifinfomsg *hdr;
++      struct nlmsghdr *nlh;
++      int err;
++
++      __get_priv(netdev, &priv, &port_priv);
++
++      nlh = nlmsg_put(skb, pid, seq, RTM_NEWLINK, sizeof(*hdr), NLM_F_MULTI);
++      if (!nlh)
++              return -EMSGSIZE;
++
++      hdr = nlmsg_data(nlh);
++      memset(hdr, 0, sizeof(*hdr));
++      hdr->ifi_family = AF_BRIDGE;
++      hdr->ifi_type = netdev->type;
++      hdr->ifi_index = netdev->ifindex;
++      hdr->ifi_flags = dev_get_flags(netdev);
++
++      err = __nla_put_netdev(skb, netdev, priv);
++      if (err)
++              goto nla_put_err;
++
++      if (port_priv) {
++              err = __nla_put_port(skb, netdev, port_priv);
++              if (err)
++                      goto nla_put_err;
++      }
++
++      /* Check if  the VID information is requested */
++      if (filter_mask & RTEXT_FILTER_BRVLAN) {
++              err = __nla_put_vlan(skb, netdev, priv, port_priv);
++              if (err)
++                      goto nla_put_err;
++      }
++
++      nlmsg_end(skb, nlh);
++      return skb->len;
++
++nla_put_err:
++      nlmsg_cancel(skb, nlh);
++      return -EMSGSIZE;
++}
++
++static int ethsw_dellink_switch(struct ethsw_dev_priv *priv, u16 vid)
++{
++      struct list_head        *pos;
++      struct ethsw_port_priv  *ppriv_local = NULL;
++      int                     err = 0;
++
++      if (!priv->vlans[vid])
++              return -ENOENT;
++
++      err = dpsw_vlan_remove(priv->mc_io, 0, priv->dpsw_handle, vid);
++      if (err) {
++              netdev_err(priv->netdev, "dpsw_vlan_remove err %d\n", err);
++              return err;
++      }
++      priv->vlans[vid] = 0;
++
++      list_for_each(pos, &priv->port_list) {
++              ppriv_local = list_entry(pos, struct ethsw_port_priv,
++                                       list);
++              ppriv_local->vlans[vid] = 0;
++      }
++
++      return 0;
++}
++
++static int ethsw_dellink_port(struct ethsw_dev_priv *priv,
++                            struct ethsw_port_priv *port_priv,
++                            u16 vid)
++{
++      struct list_head        *pos;
++      struct ethsw_port_priv  *ppriv_local = NULL;
++      struct dpsw_vlan_if_cfg vcfg = {
++              .num_ifs = 1,
++              .if_id[0] = port_priv->port_index,
++      };
++      unsigned int            count = 0;
++      int                     err = 0;
++
++      if (!port_priv->vlans[vid])
++              return -ENOENT;
++
++      /* VLAN will be deleted from switch if global flag is not set
++       * and is configured on only one port
++       */
++      if (!(priv->vlans[vid] & ETHSW_VLAN_GLOBAL)) {
++              list_for_each(pos, &priv->port_list) {
++                      ppriv_local = list_entry(pos, struct ethsw_port_priv,
++                                               list);
++                      if (ppriv_local->vlans[vid] & ETHSW_VLAN_MEMBER)
++                              count++;
++              }
++
++              if (count == 1)
++                      return ethsw_dellink_switch(priv, vid);
++      }
++
++      err = dpsw_vlan_remove_if(priv->mc_io, 0, priv->dpsw_handle,
++                                vid, &vcfg);
++      if (err) {
++              netdev_err(priv->netdev, "dpsw_vlan_remove_if err %d\n", err);
++              return err;
++      }
++      port_priv->vlans[vid] = 0;
++      return 0;
++}
++
++static int ethsw_dellink(struct net_device *netdev,
++                       struct nlmsghdr *nlh,
++                       u16 flags)
++{
++      struct nlattr           *tb[IFLA_BRIDGE_MAX+1];
++      struct nlattr           *spec;
++      struct bridge_vlan_info *vinfo;
++      struct ethsw_dev_priv   *priv;
++      struct ethsw_port_priv  *port_priv = NULL;
++      int                     err = 0;
++
++      spec = nlmsg_find_attr(nlh, sizeof(struct ifinfomsg), IFLA_AF_SPEC);
++      if (!spec)
++              return 0;
++
++      err = nla_parse_nested(tb, IFLA_BRIDGE_MAX, spec, ifla_br_policy);
++      if (err)
++              return err;
++
++      if (!tb[IFLA_BRIDGE_VLAN_INFO])
++              return -EOPNOTSUPP;
++
++      vinfo = nla_data(tb[IFLA_BRIDGE_VLAN_INFO]);
++
++      if (!vinfo->vid || vinfo->vid > VLAN_VID_MASK)
++              return -EINVAL;
++
++      __get_priv(netdev, &priv, &port_priv);
++
++      /* decide if command targets switch device or port */
++      if (!port_priv)
++              err = ethsw_dellink_switch(priv, vinfo->vid);
++      else
++              err = ethsw_dellink_port(priv, port_priv, vinfo->vid);
++
++      return err;
++}
++
++static const struct net_device_ops ethsw_ops = {
++      .ndo_open               = &ethsw_open,
++      .ndo_stop               = &ethsw_stop,
++
++      .ndo_bridge_setlink     = &ethsw_setlink,
++      .ndo_bridge_getlink     = &ethsw_getlink,
++      .ndo_bridge_dellink     = &ethsw_dellink,
++
++      .ndo_start_xmit         = &ethsw_dropframe,
++};
++
++/*--------------------------------------------------------------------------- */
++/* switch port netdevice ops */
++
++static int _ethsw_port_carrier_state_sync(struct net_device *netdev)
++{
++      struct ethsw_port_priv  *port_priv = netdev_priv(netdev);
++      struct dpsw_link_state  state;
++      int                     err;
++
++      err = dpsw_if_get_link_state(port_priv->ethsw_priv->mc_io, 0,
++                                   port_priv->ethsw_priv->dpsw_handle,
++                                   port_priv->port_index, &state);
++      if (unlikely(err)) {
++              netdev_err(netdev, "dpsw_if_get_link_state() err %d\n", err);
++              return err;
++      }
++
++      WARN_ONCE(state.up > 1, "Garbage read into link_state");
++
++      if (state.up)
++              netif_carrier_on(port_priv->netdev);
++      else
++              netif_carrier_off(port_priv->netdev);
++
++      return 0;
++}
++
++static int ethsw_port_open(struct net_device *netdev)
++{
++      struct ethsw_port_priv  *port_priv = netdev_priv(netdev);
++      int                     err;
++
++      if (!netif_oper_up(netdev) ||
++          port_priv->stp_state == BR_STATE_DISABLED)
++              return 0;
++
++      err = dpsw_if_enable(port_priv->ethsw_priv->mc_io, 0,
++                           port_priv->ethsw_priv->dpsw_handle,
++                           port_priv->port_index);
++      if (err) {
++              netdev_err(netdev, "dpsw_if_enable err %d\n", err);
++              return err;
++      }
++
++      return 0;
++}
++
++static int ethsw_port_stop(struct net_device *netdev)
++{
++      struct ethsw_port_priv  *port_priv = netdev_priv(netdev);
++      int                     err;
++
++      err = dpsw_if_disable(port_priv->ethsw_priv->mc_io, 0,
++                            port_priv->ethsw_priv->dpsw_handle,
++                            port_priv->port_index);
++      if (err) {
++              netdev_err(netdev, "dpsw_if_disable err %d\n", err);
++              return err;
++      }
++
++      return 0;
++}
++
++static int ethsw_port_fdb_add_uc(struct net_device *netdev,
++                               const unsigned char *addr)
++{
++      struct ethsw_port_priv          *port_priv = netdev_priv(netdev);
++      struct dpsw_fdb_unicast_cfg     entry = {0};
++      int err;
++
++      entry.if_egress = port_priv->port_index;
++      entry.type = DPSW_FDB_ENTRY_STATIC;
++      ether_addr_copy(entry.mac_addr, addr);
++
++      err = dpsw_fdb_add_unicast(port_priv->ethsw_priv->mc_io, 0,
++                                 port_priv->ethsw_priv->dpsw_handle,
++                                 0, &entry);
++      if (err)
++              netdev_err(netdev, "dpsw_fdb_add_unicast err %d\n", err);
++      return err;
++}
++
++static int ethsw_port_fdb_del_uc(struct net_device *netdev,
++                               const unsigned char *addr)
++{
++      struct ethsw_port_priv          *port_priv = netdev_priv(netdev);
++      struct dpsw_fdb_unicast_cfg     entry = {0};
++      int err;
++
++      entry.if_egress = port_priv->port_index;
++      entry.type = DPSW_FDB_ENTRY_STATIC;
++      ether_addr_copy(entry.mac_addr, addr);
++
++      err = dpsw_fdb_remove_unicast(port_priv->ethsw_priv->mc_io, 0,
++                                    port_priv->ethsw_priv->dpsw_handle,
++                                    0, &entry);
++      if (err)
++              netdev_err(netdev, "dpsw_fdb_remove_unicast err %d\n", err);
++      return err;
++}
++
++static int ethsw_port_fdb_add_mc(struct net_device *netdev,
++                               const unsigned char *addr)
++{
++      struct ethsw_port_priv          *port_priv = netdev_priv(netdev);
++      struct dpsw_fdb_multicast_cfg   entry = {0};
++      int err;
++
++      ether_addr_copy(entry.mac_addr, addr);
++      entry.type = DPSW_FDB_ENTRY_STATIC;
++      entry.num_ifs = 1;
++      entry.if_id[0] = port_priv->port_index;
++
++      err = dpsw_fdb_add_multicast(port_priv->ethsw_priv->mc_io, 0,
++                                   port_priv->ethsw_priv->dpsw_handle,
++                                   0, &entry);
++      if (err)
++              netdev_err(netdev, "dpsw_fdb_add_multicast err %d\n", err);
++      return err;
++}
++
++static int ethsw_port_fdb_del_mc(struct net_device *netdev,
++                               const unsigned char *addr)
++{
++      struct ethsw_port_priv          *port_priv = netdev_priv(netdev);
++      struct dpsw_fdb_multicast_cfg   entry = {0};
++      int err;
++
++      ether_addr_copy(entry.mac_addr, addr);
++      entry.type = DPSW_FDB_ENTRY_STATIC;
++      entry.num_ifs = 1;
++      entry.if_id[0] = port_priv->port_index;
++
++      err = dpsw_fdb_remove_multicast(port_priv->ethsw_priv->mc_io, 0,
++                                      port_priv->ethsw_priv->dpsw_handle,
++                                      0, &entry);
++      if (err)
++              netdev_err(netdev, "dpsw_fdb_remove_multicast err %d\n", err);
++      return err;
++}
++
++static int _lookup_address(struct net_device *netdev, int is_uc,
++                         const unsigned char *addr)
++{
++      struct netdev_hw_addr *ha;
++      struct netdev_hw_addr_list *list = (is_uc) ? &netdev->uc : &netdev->mc;
++
++      netif_addr_lock_bh(netdev);
++      list_for_each_entry(ha, &list->list, list) {
++              if (ether_addr_equal(ha->addr, addr)) {
++                      netif_addr_unlock_bh(netdev);
++                      return 1;
++              }
++      }
++      netif_addr_unlock_bh(netdev);
++      return 0;
++}
++
++static int ethsw_port_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
++                            struct net_device *netdev,
++                            const unsigned char *addr, u16 vid,
++                            u16 flags)
++{
++      struct list_head        *pos;
++      struct ethsw_port_priv  *port_priv = netdev_priv(netdev);
++      struct ethsw_dev_priv   *priv = port_priv->ethsw_priv;
++      int err;
++
++      /* TODO: add replace support when added to iproute bridge */
++      if (!(flags & NLM_F_REQUEST)) {
++              netdev_err(netdev,
++                         "ethsw_port_fdb_add unexpected flags value %08x\n",
++                         flags);
++              return -EINVAL;
++      }
++
++      if (is_unicast_ether_addr(addr)) {
++              /* if entry cannot be replaced, return error if exists */
++              if (flags & NLM_F_EXCL || flags & NLM_F_APPEND) {
++                      list_for_each(pos, &priv->port_list) {
++                              port_priv = list_entry(pos,
++                                                     struct ethsw_port_priv,
++                                                     list);
++                              if (_lookup_address(port_priv->netdev,
++                                                  1, addr))
++                                      return -EEXIST;
++                      }
++              }
++
++              err = ethsw_port_fdb_add_uc(netdev, addr);
++              if (err) {
++                      netdev_err(netdev, "ethsw_port_fdb_add_uc err %d\n",
++                                 err);
++                      return err;
++              }
++
++              /* we might have replaced an existing entry for a different
++               * switch port, make sure the address doesn't linger in any
++               * port address list
++               */
++              list_for_each(pos, &priv->port_list) {
++                      port_priv = list_entry(pos, struct ethsw_port_priv,
++                                             list);
++                      dev_uc_del(port_priv->netdev, addr);
++              }
++
++              err = dev_uc_add(netdev, addr);
++              if (err) {
++                      netdev_err(netdev, "dev_uc_add err %d\n", err);
++                      return err;
++              }
++      } else {
++              struct dpsw_fdb_multicast_cfg entry = {
++                      .type = DPSW_FDB_ENTRY_STATIC,
++                      .num_ifs = 0,
++              };
++
++              /* check if address is already set on this port */
++              if (_lookup_address(netdev, 0, addr))
++                      return -EEXIST;
++
++              /* check if the address exists on other port */
++              ether_addr_copy(entry.mac_addr, addr);
++              err = dpsw_fdb_get_multicast(priv->mc_io, 0, priv->dpsw_handle,
++                                           0, &entry);
++              if (!err) {
++                      /* entry exists, can we replace it? */
++                      if (flags & NLM_F_EXCL)
++                              return -EEXIST;
++              } else if (err != -ENAVAIL) {
++                      netdev_err(netdev, "dpsw_fdb_get_unicast err %d\n",
++                                 err);
++                      return err;
++              }
++
++              err = ethsw_port_fdb_add_mc(netdev, addr);
++              if (err) {
++                      netdev_err(netdev, "ethsw_port_fdb_add_mc err %d\n",
++                                 err);
++                      return err;
++              }
++
++              err = dev_mc_add(netdev, addr);
++              if (err) {
++                      netdev_err(netdev, "dev_mc_add err %d\n", err);
++                      return err;
++              }
++      }
++
++      return 0;
++}
++
++static int ethsw_port_fdb_del(struct ndmsg *ndm, struct nlattr *tb[],
++                            struct net_device *netdev,
++                            const unsigned char *addr, u16 vid)
++{
++      int err;
++
++      if (is_unicast_ether_addr(addr)) {
++              err = ethsw_port_fdb_del_uc(netdev, addr);
++              if (err) {
++                      netdev_err(netdev, "ethsw_port_fdb_del_uc err %d\n",
++                                 err);
++                      return err;
++              }
++
++              /* also delete if configured on port */
++              err = dev_uc_del(netdev, addr);
++              if (err && err != -ENOENT) {
++                      netdev_err(netdev, "dev_uc_del err %d\n", err);
++                      return err;
++              }
++      } else {
++              if (!_lookup_address(netdev, 0, addr))
++                      return -ENOENT;
++
++              err = dev_mc_del(netdev, addr);
++              if (err) {
++                      netdev_err(netdev, "dev_mc_del err %d\n", err);
++                      return err;
++              }
++
++              err = ethsw_port_fdb_del_mc(netdev, addr);
++              if (err) {
++                      netdev_err(netdev, "ethsw_port_fdb_del_mc err %d\n",
++                                 err);
++                      return err;
++              }
++      }
++
++      return 0;
++}
++
++static struct rtnl_link_stats64 *
++ethsw_port_get_stats(struct net_device *netdev,
++                   struct rtnl_link_stats64 *storage)
++{
++      struct ethsw_port_priv  *port_priv = netdev_priv(netdev);
++      u64                     tmp;
++      int                     err;
++
++      err = dpsw_if_get_counter(port_priv->ethsw_priv->mc_io, 0,
++                                port_priv->ethsw_priv->dpsw_handle,
++                                port_priv->port_index,
++                                DPSW_CNT_ING_FRAME, &storage->rx_packets);
++      if (err)
++              goto error;
++
++      err = dpsw_if_get_counter(port_priv->ethsw_priv->mc_io, 0,
++                                port_priv->ethsw_priv->dpsw_handle,
++                                port_priv->port_index,
++                                DPSW_CNT_EGR_FRAME, &storage->tx_packets);
++      if (err)
++              goto error;
++
++      err = dpsw_if_get_counter(port_priv->ethsw_priv->mc_io, 0,
++                                port_priv->ethsw_priv->dpsw_handle,
++                                port_priv->port_index,
++                                DPSW_CNT_ING_BYTE, &storage->rx_bytes);
++      if (err)
++              goto error;
++
++      err = dpsw_if_get_counter(port_priv->ethsw_priv->mc_io, 0,
++                                port_priv->ethsw_priv->dpsw_handle,
++                                port_priv->port_index,
++                                DPSW_CNT_EGR_BYTE, &storage->tx_bytes);
++      if (err)
++              goto error;
++
++      err = dpsw_if_get_counter(port_priv->ethsw_priv->mc_io, 0,
++                                port_priv->ethsw_priv->dpsw_handle,
++                                port_priv->port_index,
++                                DPSW_CNT_ING_FRAME_DISCARD,
++                                &storage->rx_dropped);
++      if (err)
++              goto error;
++
++      err = dpsw_if_get_counter(port_priv->ethsw_priv->mc_io, 0,
++                                port_priv->ethsw_priv->dpsw_handle,
++                                port_priv->port_index,
++                                DPSW_CNT_ING_FLTR_FRAME,
++                                &tmp);
++      if (err)
++              goto error;
++      storage->rx_dropped += tmp;
++
++      err = dpsw_if_get_counter(port_priv->ethsw_priv->mc_io, 0,
++                                port_priv->ethsw_priv->dpsw_handle,
++                                port_priv->port_index,
++                                DPSW_CNT_EGR_FRAME_DISCARD,
++                                &storage->tx_dropped);
++      if (err)
++              goto error;
++
++      return storage;
++
++error:
++      netdev_err(netdev, "dpsw_if_get_counter err %d\n", err);
++      return storage;
++}
++
++static const struct net_device_ops ethsw_port_ops = {
++      .ndo_open               = &ethsw_port_open,
++      .ndo_stop               = &ethsw_port_stop,
++
++      .ndo_fdb_add            = &ethsw_port_fdb_add,
++      .ndo_fdb_del            = &ethsw_port_fdb_del,
++      .ndo_fdb_dump           = &ndo_dflt_fdb_dump,
++
++      .ndo_get_stats64        = &ethsw_port_get_stats,
++
++      .ndo_start_xmit         = &ethsw_dropframe,
++};
++
++static struct {
++      enum dpsw_counter id;
++      char name[ETH_GSTRING_LEN];
++} ethsw_ethtool_counters[] =  {
++      {DPSW_CNT_ING_FRAME,            "rx frames"},
++      {DPSW_CNT_ING_BYTE,             "rx bytes"},
++      {DPSW_CNT_ING_FLTR_FRAME,       "rx filtered frames"},
++      {DPSW_CNT_ING_FRAME_DISCARD,    "rx discarded frames"},
++      {DPSW_CNT_ING_BCAST_FRAME,      "rx b-cast frames"},
++      {DPSW_CNT_ING_BCAST_BYTES,      "rx b-cast bytes"},
++      {DPSW_CNT_ING_MCAST_FRAME,      "rx m-cast frames"},
++      {DPSW_CNT_ING_MCAST_BYTE,       "rx m-cast bytes"},
++      {DPSW_CNT_EGR_FRAME,            "tx frames"},
++      {DPSW_CNT_EGR_BYTE,             "tx bytes"},
++      {DPSW_CNT_EGR_FRAME_DISCARD,    "tx discarded frames"},
++
++};
++
++static int ethsw_ethtool_get_sset_count(struct net_device *dev, int sset)
++{
++      switch (sset) {
++      case ETH_SS_STATS:
++              return ARRAY_SIZE(ethsw_ethtool_counters);
++      default:
++              return -EOPNOTSUPP;
++      }
++}
++
++static void ethsw_ethtool_get_strings(struct net_device *netdev,
++                                    u32 stringset, u8 *data)
++{
++      int i;
++
++      switch (stringset) {
++      case ETH_SS_STATS:
++              for (i = 0; i < ARRAY_SIZE(ethsw_ethtool_counters); i++)
++                      memcpy(data + i * ETH_GSTRING_LEN,
++                             ethsw_ethtool_counters[i].name, ETH_GSTRING_LEN);
++              break;
++      }
++}
++
++static void ethsw_ethtool_get_stats(struct net_device *netdev,
++                                  struct ethtool_stats *stats,
++                                  u64 *data)
++{
++      struct ethsw_port_priv  *port_priv = netdev_priv(netdev);
++      int                     i;
++      int                     err;
++
++      for (i = 0; i < ARRAY_SIZE(ethsw_ethtool_counters); i++) {
++              err = dpsw_if_get_counter(port_priv->ethsw_priv->mc_io, 0,
++                                        port_priv->ethsw_priv->dpsw_handle,
++                                        port_priv->port_index,
++                                        ethsw_ethtool_counters[i].id,
++                                        &data[i]);
++              if (err)
++                      netdev_err(netdev, "dpsw_if_get_counter[%s] err %d\n",
++                                 ethsw_ethtool_counters[i].name, err);
++      }
++}
++
++static const struct ethtool_ops ethsw_port_ethtool_ops = {
++      .get_strings            = &ethsw_ethtool_get_strings,
++      .get_ethtool_stats      = &ethsw_ethtool_get_stats,
++      .get_sset_count         = &ethsw_ethtool_get_sset_count,
++};
++
++/* -------------------------------------------------------------------------- */
++/* ethsw driver functions */
++
++static int ethsw_links_state_update(struct ethsw_dev_priv *priv)
++{
++      struct list_head        *pos;
++      struct ethsw_port_priv  *port_priv;
++      int err;
++
++      list_for_each(pos, &priv->port_list) {
++              port_priv = list_entry(pos, struct ethsw_port_priv,
++                                     list);
++
++              err = _ethsw_port_carrier_state_sync(port_priv->netdev);
++              if (err)
++                      netdev_err(port_priv->netdev,
++                                 "_ethsw_port_carrier_state_sync err %d\n",
++                                 err);
++      }
++
++      return 0;
++}
++
++static irqreturn_t ethsw_irq0_handler(int irq_num, void *arg)
++{
++      return IRQ_WAKE_THREAD;
++}
++
++static irqreturn_t _ethsw_irq0_handler_thread(int irq_num, void *arg)
++{
++      struct device           *dev = (struct device *)arg;
++      struct fsl_mc_device    *sw_dev = to_fsl_mc_device(dev);
++      struct net_device       *netdev = dev_get_drvdata(dev);
++      struct ethsw_dev_priv   *priv = netdev_priv(netdev);
++
++      struct fsl_mc_io *io = priv->mc_io;
++      uint16_t token = priv->dpsw_handle;
++      int irq_index = DPSW_IRQ_INDEX_IF;
++
++      /* Mask the events and the if_id reserved bits to be cleared on read */
++      uint32_t status = DPSW_IRQ_EVENT_LINK_CHANGED | 0xFFFF0000;
++      int err;
++
++      /* Sanity check */
++      if (WARN_ON(!sw_dev || !sw_dev->irqs || !sw_dev->irqs[irq_index]))
++              goto out;
++      if (WARN_ON(sw_dev->irqs[irq_index]->msi_desc->irq != irq_num))
++              goto out;
++
++      err = dpsw_get_irq_status(io, 0, token, irq_index, &status);
++      if (unlikely(err)) {
++              netdev_err(netdev, "Can't get irq status (err %d)", err);
++
++              err = dpsw_clear_irq_status(io, 0, token, irq_index,
++                                          0xFFFFFFFF);
++              if (unlikely(err))
++                      netdev_err(netdev, "Can't clear irq status (err %d)",
++                                 err);
++              goto out;
++      }
++
++      if (status & DPSW_IRQ_EVENT_LINK_CHANGED) {
++              err = ethsw_links_state_update(priv);
++              if (unlikely(err))
++                      goto out;
++      }
++
++out:
++      return IRQ_HANDLED;
++}
++
++static int ethsw_setup_irqs(struct fsl_mc_device *sw_dev)
++{
++      struct device           *dev = &sw_dev->dev;
++      struct net_device       *netdev = dev_get_drvdata(dev);
++      struct ethsw_dev_priv   *priv = netdev_priv(netdev);
++      int err = 0;
++      struct fsl_mc_device_irq *irq;
++      const int irq_index = DPSW_IRQ_INDEX_IF;
++      uint32_t mask = DPSW_IRQ_EVENT_LINK_CHANGED;
++
++      err = fsl_mc_allocate_irqs(sw_dev);
++      if (unlikely(err)) {
++              dev_err(dev, "MC irqs allocation failed\n");
++              return err;
++      }
++
++      if (WARN_ON(sw_dev->obj_desc.irq_count != DPSW_MAX_IRQ_NUM)) {
++              err = -EINVAL;
++              goto free_irq;
++      }
++
++      err = dpsw_set_irq_enable(priv->mc_io, 0, priv->dpsw_handle,
++                                irq_index, 0);
++      if (unlikely(err)) {
++              dev_err(dev, "dpsw_set_irq_enable err %d\n", err);
++              goto free_irq;
++      }
++
++      irq = sw_dev->irqs[irq_index];
++
++      err = devm_request_threaded_irq(dev, irq->msi_desc->irq,
++                                      ethsw_irq0_handler,
++                                      _ethsw_irq0_handler_thread,
++                                      IRQF_NO_SUSPEND | IRQF_ONESHOT,
++                                      dev_name(dev), dev);
++      if (unlikely(err)) {
++              dev_err(dev, "devm_request_threaded_irq(): %d", err);
++              goto free_irq;
++      }
++
++      err = dpsw_set_irq_mask(priv->mc_io, 0, priv->dpsw_handle,
++                              irq_index, mask);
++      if (unlikely(err)) {
++              dev_err(dev, "dpsw_set_irq_mask(): %d", err);
++              goto free_devm_irq;
++      }
++
++      err = dpsw_set_irq_enable(priv->mc_io, 0, priv->dpsw_handle,
++                                irq_index, 1);
++      if (unlikely(err)) {
++              dev_err(dev, "dpsw_set_irq_enable(): %d", err);
++              goto free_devm_irq;
++      }
++
++      return 0;
++
++free_devm_irq:
++      devm_free_irq(dev, irq->msi_desc->irq, dev);
++free_irq:
++      fsl_mc_free_irqs(sw_dev);
++      return err;
++}
++
++static void ethsw_teardown_irqs(struct fsl_mc_device *sw_dev)
++{
++      struct device           *dev = &sw_dev->dev;
++      struct net_device       *netdev = dev_get_drvdata(dev);
++      struct ethsw_dev_priv   *priv = netdev_priv(netdev);
++
++      dpsw_set_irq_enable(priv->mc_io, 0, priv->dpsw_handle,
++                            DPSW_IRQ_INDEX_IF, 0);
++      devm_free_irq(dev,
++                    sw_dev->irqs[DPSW_IRQ_INDEX_IF]->msi_desc->irq,
++                    dev);
++      fsl_mc_free_irqs(sw_dev);
++}
++
++static int __cold
++ethsw_init(struct fsl_mc_device *sw_dev)
++{
++      struct device           *dev = &sw_dev->dev;
++      struct ethsw_dev_priv   *priv;
++      struct net_device       *netdev;
++      int                     err = 0;
++      u16                     i;
++      const struct dpsw_stp_cfg stp_cfg = {
++              .vlan_id = 1,
++              .state = DPSW_STP_STATE_FORWARDING,
++      };
++
++      netdev = dev_get_drvdata(dev);
++      priv = netdev_priv(netdev);
++
++      priv->dev_id = sw_dev->obj_desc.id;
++
++      err = dpsw_open(priv->mc_io, 0, priv->dev_id, &priv->dpsw_handle);
++      if (err) {
++              dev_err(dev, "dpsw_open err %d\n", err);
++              goto err_exit;
++      }
++      if (!priv->dpsw_handle) {
++              dev_err(dev, "dpsw_open returned null handle but no error\n");
++              err = -EFAULT;
++              goto err_exit;
++      }
++
++      err = dpsw_get_attributes(priv->mc_io, 0, priv->dpsw_handle,
++                                &priv->sw_attr);
++      if (err) {
++              dev_err(dev, "dpsw_get_attributes err %d\n", err);
++              goto err_close;
++      }
++
++      /* Minimum supported DPSW version check */
++      if (priv->sw_attr.version.major < DPSW_MIN_VER_MAJOR ||
++          (priv->sw_attr.version.major == DPSW_MIN_VER_MAJOR &&
++           priv->sw_attr.version.minor < DPSW_MIN_VER_MINOR)) {
++              dev_err(dev, "DPSW version %d:%d not supported. Use %d.%d or greater.\n",
++                      priv->sw_attr.version.major,
++                      priv->sw_attr.version.minor,
++                      DPSW_MIN_VER_MAJOR, DPSW_MIN_VER_MINOR);
++              err = -ENOTSUPP;
++              goto err_close;
++      }
++
++      err = dpsw_reset(priv->mc_io, 0, priv->dpsw_handle);
++      if (err) {
++              dev_err(dev, "dpsw_reset err %d\n", err);
++              goto err_close;
++      }
++
++      err = dpsw_fdb_set_learning_mode(priv->mc_io, 0, priv->dpsw_handle, 0,
++                                       DPSW_FDB_LEARNING_MODE_HW);
++      if (err) {
++              dev_err(dev, "dpsw_fdb_set_learning_mode err %d\n", err);
++              goto err_close;
++      }
++
++      for (i = 0; i < priv->sw_attr.num_ifs; i++) {
++              err = dpsw_if_set_stp(priv->mc_io, 0, priv->dpsw_handle, i,
++                                    &stp_cfg);
++              if (err) {
++                      dev_err(dev, "dpsw_if_set_stp err %d for port %d\n",
++                              err, i);
++                      goto err_close;
++              }
++
++              err = dpsw_if_set_broadcast(priv->mc_io, 0,
++                                          priv->dpsw_handle, i, 1);
++              if (err) {
++                      dev_err(dev,
++                              "dpsw_if_set_broadcast err %d for port %d\n",
++                              err, i);
++                      goto err_close;
++              }
++      }
++
++      return 0;
++
++err_close:
++      dpsw_close(priv->mc_io, 0, priv->dpsw_handle);
++err_exit:
++      return err;
++}
++
++static int __cold
++ethsw_takedown(struct fsl_mc_device *sw_dev)
++{
++      struct device           *dev = &sw_dev->dev;
++      struct net_device       *netdev;
++      struct ethsw_dev_priv   *priv;
++      int                     err;
++
++      netdev = dev_get_drvdata(dev);
++      priv = netdev_priv(netdev);
++
++      err = dpsw_close(priv->mc_io, 0, priv->dpsw_handle);
++      if (err)
++              dev_warn(dev, "dpsw_close err %d\n", err);
++
++      return 0;
++}
++
++static int __cold
++ethsw_remove(struct fsl_mc_device *sw_dev)
++{
++      struct device           *dev;
++      struct net_device       *netdev;
++      struct ethsw_dev_priv   *priv;
++      struct ethsw_port_priv  *port_priv;
++      struct list_head        *pos;
++
++      dev = &sw_dev->dev;
++      netdev = dev_get_drvdata(dev);
++      priv = netdev_priv(netdev);
++
++      list_for_each(pos, &priv->port_list) {
++              port_priv = list_entry(pos, struct ethsw_port_priv, list);
++
++              rtnl_lock();
++              netdev_upper_dev_unlink(port_priv->netdev, netdev);
++              rtnl_unlock();
++
++              unregister_netdev(port_priv->netdev);
++              free_netdev(port_priv->netdev);
++      }
++
++      ethsw_teardown_irqs(sw_dev);
++
++      unregister_netdev(netdev);
++
++      ethsw_takedown(sw_dev);
++      fsl_mc_portal_free(priv->mc_io);
++
++      dev_set_drvdata(dev, NULL);
++      free_netdev(netdev);
++
++      return 0;
++}
++
++static int __cold
++ethsw_probe(struct fsl_mc_device *sw_dev)
++{
++      struct device           *dev;
++      struct net_device       *netdev = NULL;
++      struct ethsw_dev_priv   *priv = NULL;
++      int                     err = 0;
++      u16                     i;
++      const char              def_mcast[ETH_ALEN] = {
++              0x01, 0x00, 0x5e, 0x00, 0x00, 0x01,
++      };
++      char                    port_name[IFNAMSIZ];
++
++      dev = &sw_dev->dev;
++
++      /* register switch device, it's for management only - no I/O */
++      netdev = alloc_etherdev(sizeof(*priv));
++      if (!netdev) {
++              dev_err(dev, "alloc_etherdev error\n");
++              return -ENOMEM;
++      }
++      netdev->netdev_ops = &ethsw_ops;
++
++      SET_NETDEV_DEV(netdev, dev);
++      dev_set_drvdata(dev, netdev);
++
++      priv = netdev_priv(netdev);
++      priv->netdev = netdev;
++
++      err = fsl_mc_portal_allocate(sw_dev, 0, &priv->mc_io);
++      if (err) {
++              dev_err(dev, "fsl_mc_portal_allocate err %d\n", err);
++              goto err_free_netdev;
++      }
++      if (!priv->mc_io) {
++              dev_err(dev, "fsl_mc_portal_allocate returned null handle but no error\n");
++              err = -EFAULT;
++              goto err_free_netdev;
++      }
++
++      err = ethsw_init(sw_dev);
++      if (err) {
++              dev_err(dev, "switch init err %d\n", err);
++              goto err_free_cmdport;
++      }
++
++      netdev->flags = netdev->flags | IFF_PROMISC | IFF_MASTER;
++
++      /* TODO: should we hold rtnl_lock here?  We can't register_netdev under
++       * lock
++       */
++      dev_alloc_name(netdev, "sw%d");
++      err = register_netdev(netdev);
++      if (err < 0) {
++              dev_err(dev, "register_netdev error %d\n", err);
++              goto err_takedown;
++      }
++      if (err)
++              dev_info(dev, "register_netdev res %d\n", err);
++
++      /* VLAN 1 is implicitly configured on the switch */
++      priv->vlans[1] = ETHSW_VLAN_MEMBER;
++      /* Flooding, learning are implicitly enabled */
++      priv->learning = true;
++      priv->flood = true;
++
++      /* register switch ports */
++      snprintf(port_name, IFNAMSIZ, "%sp%%d", netdev->name);
++
++      INIT_LIST_HEAD(&priv->port_list);
++      for (i = 0; i < priv->sw_attr.num_ifs; i++) {
++              struct net_device *port_netdev;
++              struct ethsw_port_priv *port_priv;
++
++              port_netdev = alloc_etherdev(sizeof(struct ethsw_port_priv));
++              if (!port_netdev) {
++                      dev_err(dev, "alloc_etherdev error\n");
++                      goto err_takedown;
++              }
++
++              port_priv = netdev_priv(port_netdev);
++              port_priv->netdev = port_netdev;
++              port_priv->ethsw_priv = priv;
++
++              port_priv->port_index = i;
++              port_priv->stp_state = BR_STATE_FORWARDING;
++              /* VLAN 1 is configured by default on all switch ports */
++              port_priv->vlans[1] = ETHSW_VLAN_MEMBER | ETHSW_VLAN_UNTAGGED |
++                                    ETHSW_VLAN_PVID;
++
++              SET_NETDEV_DEV(port_netdev, dev);
++              port_netdev->netdev_ops = &ethsw_port_ops;
++              port_netdev->ethtool_ops = &ethsw_port_ethtool_ops;
++
++              port_netdev->flags = port_netdev->flags |
++                              IFF_PROMISC | IFF_SLAVE;
++
++              dev_alloc_name(port_netdev, port_name);
++              err = register_netdev(port_netdev);
++              if (err < 0) {
++                      dev_err(dev, "register_netdev error %d\n", err);
++                      free_netdev(port_netdev);
++                      goto err_takedown;
++              }
++
++              rtnl_lock();
++
++              err = netdev_master_upper_dev_link(port_netdev, netdev, NULL, NULL);
++              if (err) {
++                      dev_err(dev, "netdev_master_upper_dev_link error %d\n",
++                              err);
++                      unregister_netdev(port_netdev);
++                      free_netdev(port_netdev);
++                      rtnl_unlock();
++                      goto err_takedown;
++              }
++
++              rtmsg_ifinfo(RTM_NEWLINK, port_netdev, IFF_SLAVE, GFP_KERNEL);
++
++              rtnl_unlock();
++
++              list_add(&port_priv->list, &priv->port_list);
++
++              /* TODO: implmenet set_rm_mode instead of this */
++              err = ethsw_port_fdb_add_mc(port_netdev, def_mcast);
++              if (err)
++                      dev_warn(&netdev->dev,
++                               "ethsw_port_fdb_add_mc err %d\n", err);
++
++
++              /* sync carrier state */
++              err = _ethsw_port_carrier_state_sync(port_netdev);
++              if (err)
++                      netdev_err(netdev,
++                                 "_ethsw_port_carrier_state_sync err %d\n",
++                                 err);
++      }
++
++      /* the switch starts up enabled */
++      rtnl_lock();
++      err = dev_open(netdev);
++      rtnl_unlock();
++      if (err)
++              dev_warn(dev, "dev_open err %d\n", err);
++
++      /* setup irqs */
++      err = ethsw_setup_irqs(sw_dev);
++      if (unlikely(err)) {
++              dev_warn(dev, "ethsw_setup_irqs err %d\n", err);
++              goto err_takedown;
++      }
++
++      dev_info(&netdev->dev,
++               "probed %d port switch\n", priv->sw_attr.num_ifs);
++      return 0;
++
++err_takedown:
++      ethsw_remove(sw_dev);
++err_free_cmdport:
++      fsl_mc_portal_free(priv->mc_io);
++err_free_netdev:
++      dev_set_drvdata(dev, NULL);
++      free_netdev(netdev);
++
++      return err;
++}
++
++static const struct fsl_mc_device_match_id ethsw_match_id_table[] = {
++      {
++              .vendor = FSL_MC_VENDOR_FREESCALE,
++              .obj_type = "dpsw",
++              .ver_major = DPSW_VER_MAJOR,
++              .ver_minor = DPSW_VER_MINOR,
++      },
++      {}
++};
++
++static struct fsl_mc_driver eth_sw_drv = {
++      .driver = {
++              .name           = KBUILD_MODNAME,
++              .owner          = THIS_MODULE,
++      },
++      .probe          = ethsw_probe,
++      .remove         = ethsw_remove,
++      .match_id_table = ethsw_match_id_table,
++};
++
++module_fsl_mc_driver(eth_sw_drv);
++
++MODULE_LICENSE("GPL");
++MODULE_DESCRIPTION("DPAA2 Ethernet Switch Driver (prototype)");
+--- a/drivers/staging/fsl-mc/include/net.h
++++ b/drivers/staging/fsl-mc/include/net.h
+@@ -367,7 +367,6 @@
+ /***************************  GTP fields  ************************************/
+ #define NH_FLD_GTP_TEID                       (1)
+-
+ /* Protocol options */
+ /* Ethernet options */