diff options
Diffstat (limited to 'drivers/staging')
-rw-r--r-- | drivers/staging/Kconfig | 2 | ||||
-rw-r--r-- | drivers/staging/Makefile | 1 | ||||
-rw-r--r-- | drivers/staging/fsl-dpaa2/Kconfig | 19 | ||||
-rw-r--r-- | drivers/staging/fsl-dpaa2/Makefile | 6 | ||||
-rw-r--r-- | drivers/staging/fsl-dpaa2/ethsw/Makefile | 10 | ||||
-rw-r--r-- | drivers/staging/fsl-dpaa2/ethsw/README | 106 | ||||
-rw-r--r-- | drivers/staging/fsl-dpaa2/ethsw/TODO | 13 | ||||
-rw-r--r-- | drivers/staging/fsl-dpaa2/ethsw/dpsw-cmd.h | 390 | ||||
-rw-r--r-- | drivers/staging/fsl-dpaa2/ethsw/dpsw.c | 1322 | ||||
-rw-r--r-- | drivers/staging/fsl-dpaa2/ethsw/dpsw.h | 594 | ||||
-rw-r--r-- | drivers/staging/fsl-dpaa2/ethsw/ethsw-ethtool.c | 189 | ||||
-rw-r--r-- | drivers/staging/fsl-dpaa2/ethsw/ethsw.c | 1839 | ||||
-rw-r--r-- | drivers/staging/fsl-dpaa2/ethsw/ethsw.h | 80 | ||||
-rw-r--r-- | drivers/staging/octeon/ethernet.c | 10 | ||||
-rw-r--r-- | drivers/staging/wfx/main.c | 7 |
15 files changed, 6 insertions, 4582 deletions
diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index 808e78d6cd98..b7ae5bdc4eb5 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -76,8 +76,6 @@ source "drivers/staging/clocking-wizard/Kconfig" source "drivers/staging/fbtft/Kconfig" -source "drivers/staging/fsl-dpaa2/Kconfig" - source "drivers/staging/most/Kconfig" source "drivers/staging/ks7010/Kconfig" diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index 5a871f0ff2f4..075c979bfe7c 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -28,7 +28,6 @@ obj-$(CONFIG_GS_FPGABOOT) += gs_fpgaboot/ obj-$(CONFIG_UNISYSSPAR) += unisys/ obj-$(CONFIG_COMMON_CLK_XLNX_CLKWZRD) += clocking-wizard/ obj-$(CONFIG_FB_TFT) += fbtft/ -obj-$(CONFIG_FSL_DPAA2) += fsl-dpaa2/ obj-$(CONFIG_MOST) += most/ obj-$(CONFIG_KS7010) += ks7010/ obj-$(CONFIG_GREYBUS) += greybus/ diff --git a/drivers/staging/fsl-dpaa2/Kconfig b/drivers/staging/fsl-dpaa2/Kconfig deleted file mode 100644 index 244237bb068a..000000000000 --- a/drivers/staging/fsl-dpaa2/Kconfig +++ /dev/null @@ -1,19 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -# -# Freescale DataPath Acceleration Architecture Gen2 (DPAA2) drivers -# - -config FSL_DPAA2 - bool "Freescale DPAA2 devices" - depends on FSL_MC_BUS - help - Build drivers for Freescale DataPath Acceleration - Architecture (DPAA2) family of SoCs. - -config FSL_DPAA2_ETHSW - tristate "Freescale DPAA2 Ethernet Switch" - depends on FSL_DPAA2 - depends on NET_SWITCHDEV - help - Driver for Freescale DPAA2 Ethernet Switch. Select - BRIDGE to have support for bridge tools. diff --git a/drivers/staging/fsl-dpaa2/Makefile b/drivers/staging/fsl-dpaa2/Makefile deleted file mode 100644 index 9645db7689c9..000000000000 --- a/drivers/staging/fsl-dpaa2/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -# -# Freescale DataPath Acceleration Architecture Gen2 (DPAA2) drivers -# - -obj-$(CONFIG_FSL_DPAA2_ETHSW) += ethsw/ diff --git a/drivers/staging/fsl-dpaa2/ethsw/Makefile b/drivers/staging/fsl-dpaa2/ethsw/Makefile deleted file mode 100644 index f6f2cf798faf..000000000000 --- a/drivers/staging/fsl-dpaa2/ethsw/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -# -# Makefile for the Freescale DPAA2 Ethernet Switch -# -# Copyright 2014-2017 Freescale Semiconductor Inc. -# Copyright 2017-2018 NXP - -obj-$(CONFIG_FSL_DPAA2_ETHSW) += dpaa2-ethsw.o - -dpaa2-ethsw-objs := ethsw.o ethsw-ethtool.o dpsw.o diff --git a/drivers/staging/fsl-dpaa2/ethsw/README b/drivers/staging/fsl-dpaa2/ethsw/README deleted file mode 100644 index b48dcbf7c5fb..000000000000 --- a/drivers/staging/fsl-dpaa2/ethsw/README +++ /dev/null @@ -1,106 +0,0 @@ -DPAA2 Ethernet Switch driver -============================ - -This file provides documentation for the DPAA2 Ethernet Switch driver - - -Contents -======== - Supported Platforms - Architecture Overview - Creating an Ethernet Switch - Features - - - Supported Platforms -=================== -This driver provides networking support for Freescale LS2085A, LS2088A -DPAA2 SoCs. - - -Architecture Overview -===================== -The Ethernet Switch in the DPAA2 architecture consists of several hardware -resources that provide the functionality. These are allocated and -configured via the Management Complex (MC) portals. MC abstracts most of -these resources as DPAA2 objects and exposes ABIs through which they can -be configured and controlled. - -For a more detailed description of the DPAA2 architecture and its object -abstractions see: - drivers/staging/fsl-mc/README.txt - -The Ethernet Switch is built on top of a Datapath Switch (DPSW) object. - -Configuration interface: - - --------------------- - | DPAA2 Switch driver | - --------------------- - . - . - ---------- - | DPSW API | - ---------- - . software - ================= . ============== - . hardware - --------------------- - | MC hardware portals | - --------------------- - . - . - ------ - | DPSW | - ------ - -Driver uses the switch device driver model and exposes each switch port as -a network interface, which can be included in a bridge. Traffic switched -between ports is offloaded into the hardware. Exposed network interfaces -are not used for I/O, they are used just for configuration. This -limitation is going to be addressed in the future. - -The DPSW can have ports connected to DPNIs or to PHYs via DPMACs. - - - [ethA] [ethB] [ethC] [ethD] [ethE] [ethF] - : : : : : : - : : : : : : -[eth drv] [eth drv] [ ethsw drv ] - : : : : : : kernel -======================================================================== - : : : : : : hardware - [DPNI] [DPNI] [============= DPSW =================] - | | | | | | - | ---------- | [DPMAC] [DPMAC] - ------------------------------- | | - | | - [PHY] [PHY] - -For a more detailed description of the Ethernet switch device driver model -see: - Documentation/networking/switchdev.rst - -Creating an Ethernet Switch -=========================== -A device is created for the switch objects probed on the MC bus. Each DPSW -has a number of properties which determine the configuration options and -associated hardware resources. - -A DPSW object (and the other DPAA2 objects needed for a DPAA2 switch) can -be added to a container on the MC bus in one of two ways: statically, -through a Datapath Layout Binary file (DPL) that is parsed by MC at boot -time; or created dynamically at runtime, via the DPAA2 objects APIs. - -Features -======== -Driver configures DPSW to perform hardware switching offload of -unicast/multicast/broadcast (VLAN tagged or untagged) traffic between its -ports. - -It allows configuration of hardware learning, flooding, multicast groups, -port VLAN configuration and STP state. - -Static entries can be added/removed from the FDB. - -Hardware statistics for each port are provided through ethtool -S option. diff --git a/drivers/staging/fsl-dpaa2/ethsw/TODO b/drivers/staging/fsl-dpaa2/ethsw/TODO deleted file mode 100644 index 4d46857b0b2b..000000000000 --- a/drivers/staging/fsl-dpaa2/ethsw/TODO +++ /dev/null @@ -1,13 +0,0 @@ -* Add I/O capabilities on switch port netdevices. This will allow control -traffic to reach the CPU. -* Add ACL to redirect control traffic to CPU. -* Add support for multiple FDBs and switch port partitioning -* MC firmware uprev; the DPAA2 objects used by the Ethernet Switch driver -need to be kept in sync with binary interface changes in MC -* refine README file -* cleanup - -NOTE: At least first three of the above are required before getting the -DPAA2 Ethernet Switch driver out of staging. Another requirement is that -dpio driver is moved to drivers/soc (this is required for I/O). - diff --git a/drivers/staging/fsl-dpaa2/ethsw/dpsw-cmd.h b/drivers/staging/fsl-dpaa2/ethsw/dpsw-cmd.h deleted file mode 100644 index 450841cc6ca8..000000000000 --- a/drivers/staging/fsl-dpaa2/ethsw/dpsw-cmd.h +++ /dev/null @@ -1,390 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Copyright 2014-2016 Freescale Semiconductor Inc. - * Copyright 2017-2020 NXP - * - */ - -#ifndef __FSL_DPSW_CMD_H -#define __FSL_DPSW_CMD_H - -/* DPSW Version */ -#define DPSW_VER_MAJOR 8 -#define DPSW_VER_MINOR 5 - -#define DPSW_CMD_BASE_VERSION 1 -#define DPSW_CMD_VERSION_2 2 -#define DPSW_CMD_ID_OFFSET 4 - -#define DPSW_CMD_ID(id) (((id) << DPSW_CMD_ID_OFFSET) | DPSW_CMD_BASE_VERSION) -#define DPSW_CMD_V2(id) (((id) << DPSW_CMD_ID_OFFSET) | DPSW_CMD_VERSION_2) - -/* Command IDs */ -#define DPSW_CMDID_CLOSE DPSW_CMD_ID(0x800) -#define DPSW_CMDID_OPEN DPSW_CMD_ID(0x802) - -#define DPSW_CMDID_GET_API_VERSION DPSW_CMD_ID(0xa02) - -#define DPSW_CMDID_ENABLE DPSW_CMD_ID(0x002) -#define DPSW_CMDID_DISABLE DPSW_CMD_ID(0x003) -#define DPSW_CMDID_GET_ATTR DPSW_CMD_ID(0x004) -#define DPSW_CMDID_RESET DPSW_CMD_ID(0x005) - -#define DPSW_CMDID_SET_IRQ_ENABLE DPSW_CMD_ID(0x012) - -#define DPSW_CMDID_SET_IRQ_MASK DPSW_CMD_ID(0x014) - -#define DPSW_CMDID_GET_IRQ_STATUS DPSW_CMD_ID(0x016) -#define DPSW_CMDID_CLEAR_IRQ_STATUS DPSW_CMD_ID(0x017) - -#define DPSW_CMDID_IF_SET_TCI DPSW_CMD_ID(0x030) -#define DPSW_CMDID_IF_SET_STP DPSW_CMD_ID(0x031) - -#define DPSW_CMDID_IF_GET_COUNTER DPSW_CMD_V2(0x034) - -#define DPSW_CMDID_IF_ENABLE DPSW_CMD_ID(0x03D) -#define DPSW_CMDID_IF_DISABLE DPSW_CMD_ID(0x03E) - -#define DPSW_CMDID_IF_SET_MAX_FRAME_LENGTH DPSW_CMD_ID(0x044) - -#define DPSW_CMDID_IF_GET_LINK_STATE DPSW_CMD_ID(0x046) -#define DPSW_CMDID_IF_SET_FLOODING DPSW_CMD_ID(0x047) -#define DPSW_CMDID_IF_SET_BROADCAST DPSW_CMD_ID(0x048) - -#define DPSW_CMDID_IF_GET_TCI DPSW_CMD_ID(0x04A) - -#define DPSW_CMDID_IF_SET_LINK_CFG DPSW_CMD_ID(0x04C) - -#define DPSW_CMDID_VLAN_ADD DPSW_CMD_ID(0x060) -#define DPSW_CMDID_VLAN_ADD_IF DPSW_CMD_ID(0x061) -#define DPSW_CMDID_VLAN_ADD_IF_UNTAGGED DPSW_CMD_ID(0x062) - -#define DPSW_CMDID_VLAN_REMOVE_IF DPSW_CMD_ID(0x064) -#define DPSW_CMDID_VLAN_REMOVE_IF_UNTAGGED DPSW_CMD_ID(0x065) -#define DPSW_CMDID_VLAN_REMOVE_IF_FLOODING DPSW_CMD_ID(0x066) -#define DPSW_CMDID_VLAN_REMOVE DPSW_CMD_ID(0x067) - -#define DPSW_CMDID_FDB_ADD_UNICAST DPSW_CMD_ID(0x084) -#define DPSW_CMDID_FDB_REMOVE_UNICAST DPSW_CMD_ID(0x085) -#define DPSW_CMDID_FDB_ADD_MULTICAST DPSW_CMD_ID(0x086) -#define DPSW_CMDID_FDB_REMOVE_MULTICAST DPSW_CMD_ID(0x087) -#define DPSW_CMDID_FDB_SET_LEARNING_MODE DPSW_CMD_ID(0x088) -#define DPSW_CMDID_FDB_DUMP DPSW_CMD_ID(0x08A) - -#define DPSW_CMDID_IF_GET_PORT_MAC_ADDR DPSW_CMD_ID(0x0A7) -#define DPSW_CMDID_IF_GET_PRIMARY_MAC_ADDR DPSW_CMD_ID(0x0A8) -#define DPSW_CMDID_IF_SET_PRIMARY_MAC_ADDR DPSW_CMD_ID(0x0A9) - -/* Macros for accessing command fields smaller than 1byte */ -#define DPSW_MASK(field) \ - GENMASK(DPSW_##field##_SHIFT + DPSW_##field##_SIZE - 1, \ - DPSW_##field##_SHIFT) -#define dpsw_set_field(var, field, val) \ - ((var) |= (((val) << DPSW_##field##_SHIFT) & DPSW_MASK(field))) -#define dpsw_get_field(var, field) \ - (((var) & DPSW_MASK(field)) >> DPSW_##field##_SHIFT) -#define dpsw_get_bit(var, bit) \ - (((var) >> (bit)) & GENMASK(0, 0)) - -#pragma pack(push, 1) -struct dpsw_cmd_open { - __le32 dpsw_id; -}; - -#define DPSW_COMPONENT_TYPE_SHIFT 0 -#define DPSW_COMPONENT_TYPE_SIZE 4 - -struct dpsw_cmd_create { - /* cmd word 0 */ - __le16 num_ifs; - u8 max_fdbs; - u8 max_meters_per_if; - /* from LSB: only the first 4 bits */ - u8 component_type; - u8 pad[3]; - /* cmd word 1 */ - __le16 max_vlans; - __le16 max_fdb_entries; - __le16 fdb_aging_time; - __le16 max_fdb_mc_groups; - /* cmd word 2 */ - __le64 options; -}; - -struct dpsw_cmd_destroy { - __le32 dpsw_id; -}; - -#define DPSW_ENABLE_SHIFT 0 -#define DPSW_ENABLE_SIZE 1 - -struct dpsw_rsp_is_enabled { - /* from LSB: enable:1 */ - u8 enabled; -}; - -struct dpsw_cmd_set_irq_enable { - u8 enable_state; - u8 pad[3]; - u8 irq_index; -}; - -struct dpsw_cmd_get_irq_enable { - __le32 pad; - u8 irq_index; -}; - -struct dpsw_rsp_get_irq_enable { - u8 enable_state; -}; - -struct dpsw_cmd_set_irq_mask { - __le32 mask; - u8 irq_index; -}; - -struct dpsw_cmd_get_irq_mask { - __le32 pad; - u8 irq_index; -}; - -struct dpsw_rsp_get_irq_mask { - __le32 mask; -}; - -struct dpsw_cmd_get_irq_status { - __le32 status; - u8 irq_index; -}; - -struct dpsw_rsp_get_irq_status { - __le32 status; -}; - -struct dpsw_cmd_clear_irq_status { - __le32 status; - u8 irq_index; -}; - -#define DPSW_COMPONENT_TYPE_SHIFT 0 -#define DPSW_COMPONENT_TYPE_SIZE 4 - -struct dpsw_rsp_get_attr { - /* cmd word 0 */ - __le16 num_ifs; - u8 max_fdbs; - u8 num_fdbs; - __le16 max_vlans; - __le16 num_vlans; - /* cmd word 1 */ - __le16 max_fdb_entries; - __le16 fdb_aging_time; - __le32 dpsw_id; - /* cmd word 2 */ - __le16 mem_size; - __le16 max_fdb_mc_groups; - u8 max_meters_per_if; - /* from LSB only the first 4 bits */ - u8 component_type; - __le16 pad; - /* cmd word 3 */ - __le64 options; -}; - -struct dpsw_cmd_if_set_flooding { - __le16 if_id; - /* from LSB: enable:1 */ - u8 enable; -}; - -struct dpsw_cmd_if_set_broadcast { - __le16 if_id; - /* from LSB: enable:1 */ - u8 enable; -}; - -#define DPSW_VLAN_ID_SHIFT 0 -#define DPSW_VLAN_ID_SIZE 12 -#define DPSW_DEI_SHIFT 12 -#define DPSW_DEI_SIZE 1 -#define DPSW_PCP_SHIFT 13 -#define DPSW_PCP_SIZE 3 - -struct dpsw_cmd_if_set_tci { - __le16 if_id; - /* from LSB: VLAN_ID:12 DEI:1 PCP:3 */ - __le16 conf; -}; - -struct dpsw_cmd_if_get_tci { - __le16 if_id; -}; - -struct dpsw_rsp_if_get_tci { - __le16 pad; - __le16 vlan_id; - u8 dei; - u8 pcp; -}; - -#define DPSW_STATE_SHIFT 0 -#define DPSW_STATE_SIZE 4 - -struct dpsw_cmd_if_set_stp { - __le16 if_id; - __le16 vlan_id; - /* only the first LSB 4 bits */ - u8 state; -}; - -#define DPSW_COUNTER_TYPE_SHIFT 0 -#define DPSW_COUNTER_TYPE_SIZE 5 - -struct dpsw_cmd_if_get_counter { - __le16 if_id; - /* from LSB: type:5 */ - u8 type; -}; - -struct dpsw_rsp_if_get_counter { - __le64 pad; - __le64 counter; -}; - -struct dpsw_cmd_if { - __le16 if_id; -}; - -struct dpsw_cmd_if_set_max_frame_length { - __le16 if_id; - __le16 frame_length; -}; - -struct dpsw_cmd_if_set_link_cfg { - /* cmd word 0 */ - __le16 if_id; - u8 pad[6]; - /* cmd word 1 */ - __le32 rate; - __le32 pad1; - /* cmd word 2 */ - __le64 options; -}; - -struct dpsw_cmd_if_get_link_state { - __le16 if_id; -}; - -#define DPSW_UP_SHIFT 0 -#define DPSW_UP_SIZE 1 - -struct dpsw_rsp_if_get_link_state { - /* cmd word 0 */ - __le32 pad0; - u8 up; - u8 pad1[3]; - /* cmd word 1 */ - __le32 rate; - __le32 pad2; - /* cmd word 2 */ - __le64 options; -}; - -struct dpsw_vlan_add { - __le16 fdb_id; - __le16 vlan_id; -}; - -struct dpsw_cmd_vlan_manage_if { - /* cmd word 0 */ - __le16 pad0; - __le16 vlan_id; - __le32 pad1; - /* cmd word 1-4 */ - __le64 if_id[4]; -}; - -struct dpsw_cmd_vlan_remove { - __le16 pad; - __le16 vlan_id; -}; - -struct dpsw_cmd_fdb_add { - __le32 pad; - __le16 fdb_aging_time; - __le16 num_fdb_entries; -}; - -struct dpsw_rsp_fdb_add { - __le16 fdb_id; -}; - -struct dpsw_cmd_fdb_remove { - __le16 fdb_id; -}; - -#define DPSW_ENTRY_TYPE_SHIFT 0 -#define DPSW_ENTRY_TYPE_SIZE 4 - -struct dpsw_cmd_fdb_unicast_op { - /* cmd word 0 */ - __le16 fdb_id; - u8 mac_addr[6]; - /* cmd word 1 */ - __le16 if_egress; - /* only the first 4 bits from LSB */ - u8 type; -}; - -struct dpsw_cmd_fdb_multicast_op { - /* cmd word 0 */ - __le16 fdb_id; - __le16 num_ifs; - /* only the first 4 bits from LSB */ - u8 type; - u8 pad[3]; - /* cmd word 1 */ - u8 mac_addr[6]; - __le16 pad2; - /* cmd word 2-5 */ - __le64 if_id[4]; -}; - -#define DPSW_LEARNING_MODE_SHIFT 0 -#define DPSW_LEARNING_MODE_SIZE 4 - -struct dpsw_cmd_fdb_set_learning_mode { - __le16 fdb_id; - /* only the first 4 bits from LSB */ - u8 mode; -}; - -struct dpsw_cmd_fdb_dump { - __le16 fdb_id; - __le16 pad0; - __le32 pad1; - __le64 iova_addr; - __le32 iova_size; -}; - -struct dpsw_rsp_fdb_dump { - __le16 num_entries; -}; - -struct dpsw_rsp_get_api_version { - __le16 version_major; - __le16 version_minor; -}; - -struct dpsw_rsp_if_get_mac_addr { - __le16 pad; - u8 mac_addr[6]; -}; - -struct dpsw_cmd_if_set_mac_addr { - __le16 if_id; - u8 mac_addr[6]; -}; - -#pragma pack(pop) -#endif /* __FSL_DPSW_CMD_H */ diff --git a/drivers/staging/fsl-dpaa2/ethsw/dpsw.c b/drivers/staging/fsl-dpaa2/ethsw/dpsw.c deleted file mode 100644 index f8bfe779bd30..000000000000 --- a/drivers/staging/fsl-dpaa2/ethsw/dpsw.c +++ /dev/null @@ -1,1322 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright 2014-2016 Freescale Semiconductor Inc. - * Copyright 2017-2018 NXP - * - */ - -#include <linux/fsl/mc.h> -#include "dpsw.h" -#include "dpsw-cmd.h" - -static void build_if_id_bitmap(__le64 *bmap, - const u16 *id, - const u16 num_ifs) -{ - int i; - - for (i = 0; (i < num_ifs) && (i < DPSW_MAX_IF); i++) { - if (id[i] < DPSW_MAX_IF) - bmap[id[i] / 64] |= cpu_to_le64(BIT_MASK(id[i] % 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, - u32 cmd_flags, - int dpsw_id, - u16 *token) -{ - struct fsl_mc_command cmd = { 0 }; - struct dpsw_cmd_open *cmd_params; - int err; - - /* prepare command */ - cmd.header = mc_encode_cmd_header(DPSW_CMDID_OPEN, - cmd_flags, - 0); - cmd_params = (struct dpsw_cmd_open *)cmd.params; - cmd_params->dpsw_id = cpu_to_le32(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); - - return 0; -} - -/** - * 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, - u32 cmd_flags, - u16 token) -{ - struct fsl_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); -} - -/** - * 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, - u32 cmd_flags, - u16 token) -{ - struct fsl_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); -} - -/** - * 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, - u32 cmd_flags, - u16 token) -{ - struct fsl_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); -} - -/** - * 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, - u32 cmd_flags, - u16 token) -{ - struct fsl_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); -} - -/** - * 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, - u32 cmd_flags, - u16 token, - u8 irq_index, - u8 en) -{ - struct fsl_mc_command cmd = { 0 }; - struct dpsw_cmd_set_irq_enable *cmd_params; - - /* prepare command */ - cmd.header = mc_encode_cmd_header(DPSW_CMDID_SET_IRQ_ENABLE, - cmd_flags, - token); - cmd_params = (struct dpsw_cmd_set_irq_enable *)cmd.params; - dpsw_set_field(cmd_params->enable_state, ENABLE, en); - cmd_params->irq_index = irq_index; - - /* send command to mc*/ - return mc_send_command(mc_io, &cmd); -} - -/** - * 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, - u32 cmd_flags, - u16 token, - u8 irq_index, - u32 mask) -{ - struct fsl_mc_command cmd = { 0 }; - struct dpsw_cmd_set_irq_mask *cmd_params; - - /* prepare command */ - cmd.header = mc_encode_cmd_header(DPSW_CMDID_SET_IRQ_MASK, - cmd_flags, - token); - cmd_params = (struct dpsw_cmd_set_irq_mask *)cmd.params; - cmd_params->mask = cpu_to_le32(mask); - cmd_params->irq_index = irq_index; - - /* send command to mc*/ - return mc_send_command(mc_io, &cmd); -} - -/** - * 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, - u32 cmd_flags, - u16 token, - u8 irq_index, - u32 *status) -{ - struct fsl_mc_command cmd = { 0 }; - struct dpsw_cmd_get_irq_status *cmd_params; - struct dpsw_rsp_get_irq_status *rsp_params; - int err; - - /* prepare command */ - cmd.header = mc_encode_cmd_header(DPSW_CMDID_GET_IRQ_STATUS, - cmd_flags, - token); - cmd_params = (struct dpsw_cmd_get_irq_status *)cmd.params; - cmd_params->status = cpu_to_le32(*status); - cmd_params->irq_index = irq_index; - - /* send command to mc*/ - err = mc_send_command(mc_io, &cmd); - if (err) - return err; - - /* retrieve response parameters */ - rsp_params = (struct dpsw_rsp_get_irq_status *)cmd.params; - *status = le32_to_cpu(rsp_params->status); - - return 0; -} - -/** - * 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, - u32 cmd_flags, - u16 token, - u8 irq_index, - u32 status) -{ - struct fsl_mc_command cmd = { 0 }; - struct dpsw_cmd_clear_irq_status *cmd_params; - - /* prepare command */ - cmd.header = mc_encode_cmd_header(DPSW_CMDID_CLEAR_IRQ_STATUS, - cmd_flags, - token); - cmd_params = (struct dpsw_cmd_clear_irq_status *)cmd.params; - cmd_params->status = cpu_to_le32(status); - cmd_params->irq_index = irq_index; - - /* send command to mc*/ - return mc_send_command(mc_io, &cmd); -} - -/** - * 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, - u32 cmd_flags, - u16 token, - struct dpsw_attr *attr) -{ - struct fsl_mc_command cmd = { 0 }; - struct dpsw_rsp_get_attr *rsp_params; - 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 */ - rsp_params = (struct dpsw_rsp_get_attr *)cmd.params; - attr->num_ifs = le16_to_cpu(rsp_params->num_ifs); - attr->max_fdbs = rsp_params->max_fdbs; - attr->num_fdbs = rsp_params->num_fdbs; - attr->max_vlans = le16_to_cpu(rsp_params->max_vlans); - attr->num_vlans = le16_to_cpu(rsp_params->num_vlans); - attr->max_fdb_entries = le16_to_cpu(rsp_params->max_fdb_entries); - attr->fdb_aging_time = le16_to_cpu(rsp_params->fdb_aging_time); - attr->id = le32_to_cpu(rsp_params->dpsw_id); - attr->mem_size = le16_to_cpu(rsp_params->mem_size); - attr->max_fdb_mc_groups = le16_to_cpu(rsp_params->max_fdb_mc_groups); - attr->max_meters_per_if = rsp_params->max_meters_per_if; - attr->options = le64_to_cpu(rsp_params->options); - attr->component_type = dpsw_get_field(rsp_params->component_type, - COMPONENT_TYPE); - - return 0; -} - -/** - * 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, - u32 cmd_flags, - u16 token, - u16 if_id, - struct dpsw_link_cfg *cfg) -{ - struct fsl_mc_command cmd = { 0 }; - struct dpsw_cmd_if_set_link_cfg *cmd_params; - - /* prepare command */ - cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_SET_LINK_CFG, - cmd_flags, - token); - cmd_params = (struct dpsw_cmd_if_set_link_cfg *)cmd.params; - cmd_params->if_id = cpu_to_le16(if_id); - cmd_params->rate = cpu_to_le32(cfg->rate); - cmd_params->options = cpu_to_le64(cfg->options); - - /* send command to mc*/ - return mc_send_command(mc_io, &cmd); -} - -/** - * 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 - * - * @Return '0' on Success; Error code otherwise. - */ -int dpsw_if_get_link_state(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token, - u16 if_id, - struct dpsw_link_state *state) -{ - struct fsl_mc_command cmd = { 0 }; - struct dpsw_cmd_if_get_link_state *cmd_params; - struct dpsw_rsp_if_get_link_state *rsp_params; - int err; - - /* prepare command */ - cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_GET_LINK_STATE, - cmd_flags, - token); - cmd_params = (struct dpsw_cmd_if_get_link_state *)cmd.params; - cmd_params->if_id = cpu_to_le16(if_id); - - /* send command to mc*/ - err = mc_send_command(mc_io, &cmd); - if (err) - return err; - - /* retrieve response parameters */ - rsp_params = (struct dpsw_rsp_if_get_link_state *)cmd.params; - state->rate = le32_to_cpu(rsp_params->rate); - state->options = le64_to_cpu(rsp_params->options); - state->up = dpsw_get_field(rsp_params->up, UP); - - return 0; -} - -/** - * 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, - u32 cmd_flags, - u16 token, - u16 if_id, - u8 en) -{ - struct fsl_mc_command cmd = { 0 }; - struct dpsw_cmd_if_set_flooding *cmd_params; - - /* prepare command */ - cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_SET_FLOODING, - cmd_flags, - token); - cmd_params = (struct dpsw_cmd_if_set_flooding *)cmd.params; - cmd_params->if_id = cpu_to_le16(if_id); - dpsw_set_field(cmd_params->enable, ENABLE, en); - - /* send command to mc*/ - return mc_send_command(mc_io, &cmd); -} - -/** - * 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, - u32 cmd_flags, - u16 token, - u16 if_id, - u8 en) -{ - struct fsl_mc_command cmd = { 0 }; - struct dpsw_cmd_if_set_broadcast *cmd_params; - - /* prepare command */ - cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_SET_BROADCAST, - cmd_flags, - token); - cmd_params = (struct dpsw_cmd_if_set_broadcast *)cmd.params; - cmd_params->if_id = cpu_to_le16(if_id); - dpsw_set_field(cmd_params->enable, ENABLE, en); - - /* send command to mc*/ - return mc_send_command(mc_io, &cmd); -} - -/** - * 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, - u32 cmd_flags, - u16 token, - u16 if_id, - const struct dpsw_tci_cfg *cfg) -{ - struct fsl_mc_command cmd = { 0 }; - struct dpsw_cmd_if_set_tci *cmd_params; - u16 tmp_conf = 0; - - /* prepare command */ - cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_SET_TCI, - cmd_flags, - token); - cmd_params = (struct dpsw_cmd_if_set_tci *)cmd.params; - cmd_params->if_id = cpu_to_le16(if_id); - dpsw_set_field(tmp_conf, VLAN_ID, cfg->vlan_id); - dpsw_set_field(tmp_conf, DEI, cfg->dei); - dpsw_set_field(tmp_conf, PCP, cfg->pcp); - cmd_params->conf = cpu_to_le16(tmp_conf); - - /* send command to mc*/ - return mc_send_command(mc_io, &cmd); -} - -/** - * 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, - u32 cmd_flags, - u16 token, - u16 if_id, - struct dpsw_tci_cfg *cfg) -{ - struct fsl_mc_command cmd = { 0 }; - struct dpsw_cmd_if_get_tci *cmd_params; - struct dpsw_rsp_if_get_tci *rsp_params; - int err; - - /* prepare command */ - cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_GET_TCI, - cmd_flags, - token); - cmd_params = (struct dpsw_cmd_if_get_tci *)cmd.params; - cmd_params->if_id = cpu_to_le16(if_id); - - /* send command to mc*/ - err = mc_send_command(mc_io, &cmd); - if (err) - return err; - - /* retrieve response parameters */ - rsp_params = (struct dpsw_rsp_if_get_tci *)cmd.params; - cfg->pcp = rsp_params->pcp; - cfg->dei = rsp_params->dei; - cfg->vlan_id = le16_to_cpu(rsp_params->vlan_id); - - return 0; -} - -/** - * 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, - u32 cmd_flags, - u16 token, - u16 if_id, - const struct dpsw_stp_cfg *cfg) -{ - struct fsl_mc_command cmd = { 0 }; - struct dpsw_cmd_if_set_stp *cmd_params; - - /* prepare command */ - cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_SET_STP, - cmd_flags, - token); - cmd_params = (struct dpsw_cmd_if_set_stp *)cmd.params; - cmd_params->if_id = cpu_to_le16(if_id); - cmd_params->vlan_id = cpu_to_le16(cfg->vlan_id); - dpsw_set_field(cmd_params->state, STATE, cfg->state); - - /* send command to mc*/ - return mc_send_command(mc_io, &cmd); -} - -/** - * 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, - u32 cmd_flags, - u16 token, - u16 if_id, - enum dpsw_counter type, - u64 *counter) -{ - struct fsl_mc_command cmd = { 0 }; - struct dpsw_cmd_if_get_counter *cmd_params; - struct dpsw_rsp_if_get_counter *rsp_params; - int err; - - /* prepare command */ - cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_GET_COUNTER, - cmd_flags, - token); - cmd_params = (struct dpsw_cmd_if_get_counter *)cmd.params; - cmd_params->if_id = cpu_to_le16(if_id); - dpsw_set_field(cmd_params->type, COUNTER_TYPE, type); - - /* send command to mc*/ - err = mc_send_command(mc_io, &cmd); - if (err) - return err; - - /* retrieve response parameters */ - rsp_params = (struct dpsw_rsp_if_get_counter *)cmd.params; - *counter = le64_to_cpu(rsp_params->counter); - - return 0; -} - -/** - * 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, - u32 cmd_flags, - u16 token, - u16 if_id) -{ - struct fsl_mc_command cmd = { 0 }; - struct dpsw_cmd_if *cmd_params; - - /* prepare command */ - cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_ENABLE, - cmd_flags, - token); - cmd_params = (struct dpsw_cmd_if *)cmd.params; - cmd_params->if_id = cpu_to_le16(if_id); - - /* send command to mc*/ - return mc_send_command(mc_io, &cmd); -} - -/** - * 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, - u32 cmd_flags, - u16 token, - u16 if_id) -{ - struct fsl_mc_command cmd = { 0 }; - struct dpsw_cmd_if *cmd_params; - - /* prepare command */ - cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_DISABLE, - cmd_flags, - token); - cmd_params = (struct dpsw_cmd_if *)cmd.params; - cmd_params->if_id = cpu_to_le16(if_id); - - /* send command to mc*/ - return mc_send_command(mc_io, &cmd); -} - -/** - * 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, - u32 cmd_flags, - u16 token, - u16 if_id, - u16 frame_length) -{ - struct fsl_mc_command cmd = { 0 }; - struct dpsw_cmd_if_set_max_frame_length *cmd_params; - - /* prepare command */ - cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_SET_MAX_FRAME_LENGTH, - cmd_flags, - token); - cmd_params = (struct dpsw_cmd_if_set_max_frame_length *)cmd.params; - cmd_params->if_id = cpu_to_le16(if_id); - cmd_params->frame_length = cpu_to_le16(frame_length); - - /* send command to mc*/ - return mc_send_command(mc_io, &cmd); -} - -/** - * 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, - u32 cmd_flags, - u16 token, - u16 vlan_id, - const struct dpsw_vlan_cfg *cfg) -{ - struct fsl_mc_command cmd = { 0 }; - struct dpsw_vlan_add *cmd_params; - - /* prepare command */ - cmd.header = mc_encode_cmd_header(DPSW_CMDID_VLAN_ADD, - cmd_flags, - token); - cmd_params = (struct dpsw_vlan_add *)cmd.params; - cmd_params->fdb_id = cpu_to_le16(cfg->fdb_id); - cmd_params->vlan_id = cpu_to_le16(vlan_id); - - /* send command to mc*/ - return mc_send_command(mc_io, &cmd); -} - -/** - * 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, - u32 cmd_flags, - u16 token, - u16 vlan_id, - const struct dpsw_vlan_if_cfg *cfg) -{ - struct fsl_mc_command cmd = { 0 }; - struct dpsw_cmd_vlan_manage_if *cmd_params; - - /* prepare command */ - cmd.header = mc_encode_cmd_header(DPSW_CMDID_VLAN_ADD_IF, - cmd_flags, - token); - cmd_params = (struct dpsw_cmd_vlan_manage_if *)cmd.params; - cmd_params->vlan_id = cpu_to_le16(vlan_id); - build_if_id_bitmap(cmd_params->if_id, cfg->if_id, cfg->num_ifs); - - /* send command to mc*/ - return mc_send_command(mc_io, &cmd); -} - -/** - * 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, - u32 cmd_flags, - u16 token, - u16 vlan_id, - const struct dpsw_vlan_if_cfg *cfg) -{ - struct fsl_mc_command cmd = { 0 }; - struct dpsw_cmd_vlan_manage_if *cmd_params; - - /* prepare command */ - cmd.header = mc_encode_cmd_header(DPSW_CMDID_VLAN_ADD_IF_UNTAGGED, - cmd_flags, - token); - cmd_params = (struct dpsw_cmd_vlan_manage_if *)cmd.params; - cmd_params->vlan_id = cpu_to_le16(vlan_id); - build_if_id_bitmap(cmd_params->if_id, cfg->if_id, cfg->num_ifs); - - /* send command to mc*/ - return mc_send_command(mc_io, &cmd); -} - -/** - * 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, - u32 cmd_flags, - u16 token, - u16 vlan_id, - const struct dpsw_vlan_if_cfg *cfg) -{ - struct fsl_mc_command cmd = { 0 }; - struct dpsw_cmd_vlan_manage_if *cmd_params; - - /* prepare command */ - cmd.header = mc_encode_cmd_header(DPSW_CMDID_VLAN_REMOVE_IF, - cmd_flags, - token); - cmd_params = (struct dpsw_cmd_vlan_manage_if *)cmd.params; - cmd_params->vlan_id = cpu_to_le16(vlan_id); - build_if_id_bitmap(cmd_params->if_id, cfg->if_id, cfg->num_ifs); - - /* send command to mc*/ - return mc_send_command(mc_io, &cmd); -} - -/** - * 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, - u32 cmd_flags, - u16 token, - u16 vlan_id, - const struct dpsw_vlan_if_cfg *cfg) -{ - struct fsl_mc_command cmd = { 0 }; - struct dpsw_cmd_vlan_manage_if *cmd_params; - - /* prepare command */ - cmd.header = mc_encode_cmd_header(DPSW_CMDID_VLAN_REMOVE_IF_UNTAGGED, - cmd_flags, - token); - cmd_params = (struct dpsw_cmd_vlan_manage_if *)cmd.params; - cmd_params->vlan_id = cpu_to_le16(vlan_id); - build_if_id_bitmap(cmd_params->if_id, cfg->if_id, cfg->num_ifs); - - /* send command to mc*/ - return mc_send_command(mc_io, &cmd); -} - -/** - * 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, - u32 cmd_flags, - u16 token, - u16 vlan_id) -{ - struct fsl_mc_command cmd = { 0 }; - struct dpsw_cmd_vlan_remove *cmd_params; - - /* prepare command */ - cmd.header = mc_encode_cmd_header(DPSW_CMDID_VLAN_REMOVE, - cmd_flags, - token); - cmd_params = (struct dpsw_cmd_vlan_remove *)cmd.params; - cmd_params->vlan_id = cpu_to_le16(vlan_id); - - /* send command to mc*/ - return mc_send_command(mc_io, &cmd); -} - -/** - * 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, - u32 cmd_flags, - u16 token, - u16 fdb_id, - const struct dpsw_fdb_unicast_cfg *cfg) -{ - struct fsl_mc_command cmd = { 0 }; - struct dpsw_cmd_fdb_unicast_op *cmd_params; - int i; - - /* prepare command */ - cmd.header = mc_encode_cmd_header(DPSW_CMDID_FDB_ADD_UNICAST, - cmd_flags, - token); - cmd_params = (struct dpsw_cmd_fdb_unicast_op *)cmd.params; - cmd_params->fdb_id = cpu_to_le16(fdb_id); - cmd_params->if_egress = cpu_to_le16(cfg->if_egress); - for (i = 0; i < 6; i++) - cmd_params->mac_addr[i] = cfg->mac_addr[5 - i]; - dpsw_set_field(cmd_params->type, ENTRY_TYPE, cfg->type); - - /* send command to mc*/ - return mc_send_command(mc_io, &cmd); -} - -/** - * dpsw_fdb_dump() - Dump the content of FDB table into memory. - * @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 - * @iova_addr: Data will be stored here as an array of struct fdb_dump_entry - * @iova_size: Memory size allocated at iova_addr - * @num_entries:Number of entries written at iova_addr - * - * Return: Completion status. '0' on Success; Error code otherwise. - * - * The memory allocated at iova_addr must be initialized with zero before - * command execution. If the FDB table does not fit into memory MC will stop - * after the memory is filled up. - * The struct fdb_dump_entry array must be parsed until the end of memory - * area or until an entry with mac_addr set to zero is found. - */ -int dpsw_fdb_dump(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token, - u16 fdb_id, - u64 iova_addr, - u32 iova_size, - u16 *num_entries) -{ - struct dpsw_cmd_fdb_dump *cmd_params; - struct dpsw_rsp_fdb_dump *rsp_params; - struct fsl_mc_command cmd = { 0 }; - int err; - - /* prepare command */ - cmd.header = mc_encode_cmd_header(DPSW_CMDID_FDB_DUMP, - cmd_flags, - token); - cmd_params = (struct dpsw_cmd_fdb_dump *)cmd.params; - cmd_params->fdb_id = cpu_to_le16(fdb_id); - cmd_params->iova_addr = cpu_to_le64(iova_addr); - cmd_params->iova_size = cpu_to_le32(iova_size); - - /* send command to mc */ - err = mc_send_command(mc_io, &cmd); - if (err) - return err; - - rsp_params = (struct dpsw_rsp_fdb_dump *)cmd.params; - *num_entries = le16_to_cpu(rsp_params->num_entries); - - return 0; -} - -/** - * 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, - u32 cmd_flags, - u16 token, - u16 fdb_id, - const struct dpsw_fdb_unicast_cfg *cfg) -{ - struct fsl_mc_command cmd = { 0 }; - struct dpsw_cmd_fdb_unicast_op *cmd_params; - int i; - - /* prepare command */ - cmd.header = mc_encode_cmd_header(DPSW_CMDID_FDB_REMOVE_UNICAST, - cmd_flags, - token); - cmd_params = (struct dpsw_cmd_fdb_unicast_op *)cmd.params; - cmd_params->fdb_id = cpu_to_le16(fdb_id); - for (i = 0; i < 6; i++) - cmd_params->mac_addr[i] = cfg->mac_addr[5 - i]; - cmd_params->if_egress = cpu_to_le16(cfg->if_egress); - dpsw_set_field(cmd_params->type, ENTRY_TYPE, cfg->type); - - /* send command to mc*/ - return mc_send_command(mc_io, &cmd); -} - -/** - * 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, - u32 cmd_flags, - u16 token, - u16 fdb_id, - const struct dpsw_fdb_multicast_cfg *cfg) -{ - struct fsl_mc_command cmd = { 0 }; - struct dpsw_cmd_fdb_multicast_op *cmd_params; - int i; - - /* prepare command */ - cmd.header = mc_encode_cmd_header(DPSW_CMDID_FDB_ADD_MULTICAST, - cmd_flags, - token); - cmd_params = (struct dpsw_cmd_fdb_multicast_op *)cmd.params; - cmd_params->fdb_id = cpu_to_le16(fdb_id); - cmd_params->num_ifs = cpu_to_le16(cfg->num_ifs); - dpsw_set_field(cmd_params->type, ENTRY_TYPE, cfg->type); - build_if_id_bitmap(cmd_params->if_id, cfg->if_id, cfg->num_ifs); - for (i = 0; i < 6; i++) - cmd_params->mac_addr[i] = cfg->mac_addr[5 - i]; - - /* send command to mc*/ - return mc_send_command(mc_io, &cmd); -} - -/** - * 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, - u32 cmd_flags, - u16 token, - u16 fdb_id, - const struct dpsw_fdb_multicast_cfg *cfg) -{ - struct fsl_mc_command cmd = { 0 }; - struct dpsw_cmd_fdb_multicast_op *cmd_params; - int i; - - /* prepare command */ - cmd.header = mc_encode_cmd_header(DPSW_CMDID_FDB_REMOVE_MULTICAST, - cmd_flags, - token); - cmd_params = (struct dpsw_cmd_fdb_multicast_op *)cmd.params; - cmd_params->fdb_id = cpu_to_le16(fdb_id); - cmd_params->num_ifs = cpu_to_le16(cfg->num_ifs); - dpsw_set_field(cmd_params->type, ENTRY_TYPE, cfg->type); - build_if_id_bitmap(cmd_params->if_id, cfg->if_id, cfg->num_ifs); - for (i = 0; i < 6; i++) - cmd_params->mac_addr[i] = cfg->mac_addr[5 - i]; - - /* send command to mc*/ - return mc_send_command(mc_io, &cmd); -} - -/** - * 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, - u32 cmd_flags, - u16 token, - u16 fdb_id, - enum dpsw_fdb_learning_mode mode) -{ - struct fsl_mc_command cmd = { 0 }; - struct dpsw_cmd_fdb_set_learning_mode *cmd_params; - - /* prepare command */ - cmd.header = mc_encode_cmd_header(DPSW_CMDID_FDB_SET_LEARNING_MODE, - cmd_flags, - token); - cmd_params = (struct dpsw_cmd_fdb_set_learning_mode *)cmd.params; - cmd_params->fdb_id = cpu_to_le16(fdb_id); - dpsw_set_field(cmd_params->mode, LEARNING_MODE, mode); - - /* send command to mc*/ - return mc_send_command(mc_io, &cmd); -} - -/** - * dpsw_get_api_version() - Get Data Path Switch API version - * @mc_io: Pointer to MC portal's I/O object - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' - * @major_ver: Major version of data path switch API - * @minor_ver: Minor version of data path switch API - * - * Return: '0' on Success; Error code otherwise. - */ -int dpsw_get_api_version(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 *major_ver, - u16 *minor_ver) -{ - struct fsl_mc_command cmd = { 0 }; - struct dpsw_rsp_get_api_version *rsp_params; - int err; - - cmd.header = mc_encode_cmd_header(DPSW_CMDID_GET_API_VERSION, - cmd_flags, - 0); - - err = mc_send_command(mc_io, &cmd); - if (err) - return err; - - rsp_params = (struct dpsw_rsp_get_api_version *)cmd.params; - *major_ver = le16_to_cpu(rsp_params->version_major); - *minor_ver = le16_to_cpu(rsp_params->version_minor); - - return 0; -} - -/** - * dpsw_if_get_port_mac_addr() - * @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 - * @mac_addr: MAC address of the physical port, if any, otherwise 0 - * - * Return: Completion status. '0' on Success; Error code otherwise. - */ -int dpsw_if_get_port_mac_addr(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token, - u16 if_id, u8 mac_addr[6]) -{ - struct dpsw_rsp_if_get_mac_addr *rsp_params; - struct fsl_mc_command cmd = { 0 }; - struct dpsw_cmd_if *cmd_params; - int err, i; - - /* prepare command */ - cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_GET_PORT_MAC_ADDR, - cmd_flags, - token); - cmd_params = (struct dpsw_cmd_if *)cmd.params; - cmd_params->if_id = cpu_to_le16(if_id); - - /* send command to mc*/ - err = mc_send_command(mc_io, &cmd); - if (err) - return err; - - /* retrieve response parameters */ - rsp_params = (struct dpsw_rsp_if_get_mac_addr *)cmd.params; - for (i = 0; i < 6; i++) - mac_addr[5 - i] = rsp_params->mac_addr[i]; - - return 0; -} - -/** - * dpsw_if_get_primary_mac_addr() - * @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 - * @mac_addr: MAC address of the physical port, if any, otherwise 0 - * - * Return: Completion status. '0' on Success; Error code otherwise. - */ -int dpsw_if_get_primary_mac_addr(struct fsl_mc_io *mc_io, u32 cmd_flags, - u16 token, u16 if_id, u8 mac_addr[6]) -{ - struct dpsw_rsp_if_get_mac_addr *rsp_params; - struct fsl_mc_command cmd = { 0 }; - struct dpsw_cmd_if *cmd_params; - int err, i; - - /* prepare command */ - cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_SET_PRIMARY_MAC_ADDR, - cmd_flags, - token); - cmd_params = (struct dpsw_cmd_if *)cmd.params; - cmd_params->if_id = cpu_to_le16(if_id); - - /* send command to mc*/ - err = mc_send_command(mc_io, &cmd); - if (err) - return err; - - /* retrieve response parameters */ - rsp_params = (struct dpsw_rsp_if_get_mac_addr *)cmd.params; - for (i = 0; i < 6; i++) - mac_addr[5 - i] = rsp_params->mac_addr[i]; - - return 0; -} - -/** - * dpsw_if_set_primary_mac_addr() - * @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 - * @mac_addr: MAC address of the physical port, if any, otherwise 0 - * - * Return: Completion status. '0' on Success; Error code otherwise. - */ -int dpsw_if_set_primary_mac_addr(struct fsl_mc_io *mc_io, u32 cmd_flags, - u16 token, u16 if_id, u8 mac_addr[6]) -{ - struct dpsw_cmd_if_set_mac_addr *cmd_params; - struct fsl_mc_command cmd = { 0 }; - int i; - - /* prepare command */ - cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_SET_PRIMARY_MAC_ADDR, - cmd_flags, - token); - cmd_params = (struct dpsw_cmd_if_set_mac_addr *)cmd.params; - cmd_params->if_id = cpu_to_le16(if_id); - for (i = 0; i < 6; i++) - cmd_params->mac_addr[i] = mac_addr[5 - i]; - - /* send command to mc*/ - return mc_send_command(mc_io, &cmd); -} diff --git a/drivers/staging/fsl-dpaa2/ethsw/dpsw.h b/drivers/staging/fsl-dpaa2/ethsw/dpsw.h deleted file mode 100644 index 9cfd8a8e0197..000000000000 --- a/drivers/staging/fsl-dpaa2/ethsw/dpsw.h +++ /dev/null @@ -1,594 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Copyright 2014-2016 Freescale Semiconductor Inc. - * Copyright 2017-2018 NXP - * - */ - -#ifndef __FSL_DPSW_H -#define __FSL_DPSW_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 - -int dpsw_open(struct fsl_mc_io *mc_io, - u32 cmd_flags, - int dpsw_id, - u16 *token); - -int dpsw_close(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 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 -}; - -int dpsw_enable(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token); - -int dpsw_disable(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token); - -int dpsw_reset(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 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 { - u64 addr; - u32 val; - int irq_num; -}; - -int dpsw_set_irq_enable(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token, - u8 irq_index, - u8 en); - -int dpsw_set_irq_mask(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token, - u8 irq_index, - u32 mask); - -int dpsw_get_irq_status(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token, - u8 irq_index, - u32 *status); - -int dpsw_clear_irq_status(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token, - u8 irq_index, - u32 status); - -/** - * struct dpsw_attr - Structure representing DPSW attributes - * @id: DPSW object ID - * @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; - u64 options; - u16 max_vlans; - u8 max_meters_per_if; - u8 max_fdbs; - u16 max_fdb_entries; - u16 fdb_aging_time; - u16 max_fdb_mc_groups; - u16 num_ifs; - u16 mem_size; - u16 num_vlans; - u8 num_fdbs; - enum dpsw_component_type component_type; -}; - -int dpsw_get_attributes(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token, - struct dpsw_attr *attr); - -/** - * 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 { - u32 rate; - u64 options; -}; - -int dpsw_if_set_link_cfg(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token, - u16 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 { - u32 rate; - u64 options; - u8 up; -}; - -int dpsw_if_get_link_state(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token, - u16 if_id, - struct dpsw_link_state *state); - -int dpsw_if_set_flooding(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token, - u16 if_id, - u8 en); - -int dpsw_if_set_broadcast(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token, - u16 if_id, - u8 en); - -/** - * struct dpsw_tci_cfg - Tag Control 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 { - u8 pcp; - u8 dei; - u16 vlan_id; -}; - -int dpsw_if_set_tci(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token, - u16 if_id, - const struct dpsw_tci_cfg *cfg); - -int dpsw_if_get_tci(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token, - u16 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_DISABLED = 0, - DPSW_STP_STATE_LISTENING = 1, - DPSW_STP_STATE_LEARNING = 2, - DPSW_STP_STATE_FORWARDING = 3, - DPSW_STP_STATE_BLOCKING = 0 -}; - -/** - * struct dpsw_stp_cfg - Spanning Tree Protocol (STP) Configuration - * @vlan_id: VLAN ID STP state - * @state: STP state - */ -struct dpsw_stp_cfg { - u16 vlan_id; - enum dpsw_stp_state state; -}; - -int dpsw_if_set_stp(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token, - u16 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 -}; - -/** - * 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 egress bytes - * @DPSW_CNT_EGR_FRAME_DISCARD: Counts discarded egress frames - * @DPSW_CNT_EGR_STP_FRAME_DISCARD: Counts egress STP discarded frames - * @DPSW_CNT_ING_NO_BUFF_DISCARD: Counts ingress no buffer 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_CNT_ING_NO_BUFF_DISCARD = 0xc, -}; - -int dpsw_if_get_counter(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token, - u16 if_id, - enum dpsw_counter type, - u64 *counter); - -int dpsw_if_enable(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token, - u16 if_id); - -int dpsw_if_disable(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token, - u16 if_id); - -int dpsw_if_set_max_frame_length(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token, - u16 if_id, - u16 frame_length); - -/** - * struct dpsw_vlan_cfg - VLAN Configuration - * @fdb_id: Forwarding Data Base - */ -struct dpsw_vlan_cfg { - u16 fdb_id; -}; - -int dpsw_vlan_add(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token, - u16 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 { - u16 num_ifs; - u16 if_id[DPSW_MAX_IF]; -}; - -int dpsw_vlan_add_if(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token, - u16 vlan_id, - const struct dpsw_vlan_if_cfg *cfg); - -int dpsw_vlan_add_if_untagged(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token, - u16 vlan_id, - const struct dpsw_vlan_if_cfg *cfg); - -int dpsw_vlan_remove_if(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token, - u16 vlan_id, - const struct dpsw_vlan_if_cfg *cfg); - -int dpsw_vlan_remove_if_untagged(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token, - u16 vlan_id, - const struct dpsw_vlan_if_cfg *cfg); - -int dpsw_vlan_remove(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token, - u16 vlan_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; - u8 mac_addr[6]; - u16 if_egress; -}; - -int dpsw_fdb_add_unicast(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token, - u16 fdb_id, - const struct dpsw_fdb_unicast_cfg *cfg); - -int dpsw_fdb_remove_unicast(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token, - u16 fdb_id, - const struct dpsw_fdb_unicast_cfg *cfg); - -#define DPSW_FDB_ENTRY_TYPE_DYNAMIC BIT(0) -#define DPSW_FDB_ENTRY_TYPE_UNICAST BIT(1) - -/** - * struct fdb_dump_entry - fdb snapshot entry - * @mac_addr: MAC address - * @type: bit0 - DINAMIC(1)/STATIC(0), bit1 - UNICAST(1)/MULTICAST(0) - * @if_info: unicast - egress interface, multicast - number of egress interfaces - * @if_mask: multicast - egress interface mask - */ -struct fdb_dump_entry { - u8 mac_addr[6]; - u8 type; - u8 if_info; - u8 if_mask[8]; -}; - -int dpsw_fdb_dump(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token, - u16 fdb_id, - u64 iova_addr, - u32 iova_size, - u16 *num_entries); - -/** - * 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; - u8 mac_addr[6]; - u16 num_ifs; - u16 if_id[DPSW_MAX_IF]; -}; - -int dpsw_fdb_add_multicast(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token, - u16 fdb_id, - const struct dpsw_fdb_multicast_cfg *cfg); - -int dpsw_fdb_remove_multicast(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token, - u16 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 -}; - -int dpsw_fdb_set_learning_mode(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token, - u16 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 { - u16 max_fdb_entries; - u16 fdb_aging_time; - enum dpsw_fdb_learning_mode learning_mode; - u16 num_fdb_mc_groups; - u16 max_fdb_mc_groups; -}; - -int dpsw_get_api_version(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 *major_ver, - u16 *minor_ver); - -int dpsw_if_get_port_mac_addr(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token, - u16 if_id, u8 mac_addr[6]); - -int dpsw_if_get_primary_mac_addr(struct fsl_mc_io *mc_io, u32 cmd_flags, - u16 token, u16 if_id, u8 mac_addr[6]); - -int dpsw_if_set_primary_mac_addr(struct fsl_mc_io *mc_io, u32 cmd_flags, - u16 token, u16 if_id, u8 mac_addr[6]); - -#endif /* __FSL_DPSW_H */ diff --git a/drivers/staging/fsl-dpaa2/ethsw/ethsw-ethtool.c b/drivers/staging/fsl-dpaa2/ethsw/ethsw-ethtool.c deleted file mode 100644 index 0af2e9914ec4..000000000000 --- a/drivers/staging/fsl-dpaa2/ethsw/ethsw-ethtool.c +++ /dev/null @@ -1,189 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * DPAA2 Ethernet Switch ethtool support - * - * Copyright 2014-2016 Freescale Semiconductor Inc. - * Copyright 2017-2018 NXP - * - */ - -#include <linux/ethtool.h> - -#include "ethsw.h" - -static struct { - enum dpsw_counter id; - char name[ETH_GSTRING_LEN]; -} dpaa2_switch_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"}, - {DPSW_CNT_ING_NO_BUFF_DISCARD, "rx discarded no buffer frames"}, -}; - -#define DPAA2_SWITCH_NUM_COUNTERS ARRAY_SIZE(dpaa2_switch_ethtool_counters) - -static void dpaa2_switch_get_drvinfo(struct net_device *netdev, - struct ethtool_drvinfo *drvinfo) -{ - struct ethsw_port_priv *port_priv = netdev_priv(netdev); - u16 version_major, version_minor; - int err; - - strscpy(drvinfo->driver, KBUILD_MODNAME, sizeof(drvinfo->driver)); - - err = dpsw_get_api_version(port_priv->ethsw_data->mc_io, 0, - &version_major, - &version_minor); - if (err) - strscpy(drvinfo->fw_version, "N/A", - sizeof(drvinfo->fw_version)); - else - snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version), - "%u.%u", version_major, version_minor); - - strscpy(drvinfo->bus_info, dev_name(netdev->dev.parent->parent), - sizeof(drvinfo->bus_info)); -} - -static int -dpaa2_switch_get_link_ksettings(struct net_device *netdev, - struct ethtool_link_ksettings *link_ksettings) -{ - struct ethsw_port_priv *port_priv = netdev_priv(netdev); - struct dpsw_link_state state = {0}; - int err = 0; - - err = dpsw_if_get_link_state(port_priv->ethsw_data->mc_io, 0, - port_priv->ethsw_data->dpsw_handle, - port_priv->idx, - &state); - if (err) { - netdev_err(netdev, "ERROR %d getting link state\n", err); - goto out; - } - - /* At the moment, we have no way of interrogating the DPMAC - * from the DPSW side or there may not exist a DPMAC at all. - * Report only autoneg state, duplexity and speed. - */ - if (state.options & DPSW_LINK_OPT_AUTONEG) - link_ksettings->base.autoneg = AUTONEG_ENABLE; - if (!(state.options & DPSW_LINK_OPT_HALF_DUPLEX)) - link_ksettings->base.duplex = DUPLEX_FULL; - link_ksettings->base.speed = state.rate; - -out: - return err; -} - -static int -dpaa2_switch_set_link_ksettings(struct net_device *netdev, - const struct ethtool_link_ksettings *link_ksettings) -{ - struct ethsw_port_priv *port_priv = netdev_priv(netdev); - struct ethsw_core *ethsw = port_priv->ethsw_data; - struct dpsw_link_cfg cfg = {0}; - bool if_running; - int err = 0, ret; - - /* Interface needs to be down to change link settings */ - if_running = netif_running(netdev); - if (if_running) { - err = dpsw_if_disable(ethsw->mc_io, 0, - ethsw->dpsw_handle, - port_priv->idx); - if (err) { - netdev_err(netdev, "dpsw_if_disable err %d\n", err); - return err; - } - } - - cfg.rate = link_ksettings->base.speed; - if (link_ksettings->base.autoneg == AUTONEG_ENABLE) - cfg.options |= DPSW_LINK_OPT_AUTONEG; - else - cfg.options &= ~DPSW_LINK_OPT_AUTONEG; - if (link_ksettings->base.duplex == DUPLEX_HALF) - cfg.options |= DPSW_LINK_OPT_HALF_DUPLEX; - else - cfg.options &= ~DPSW_LINK_OPT_HALF_DUPLEX; - - err = dpsw_if_set_link_cfg(port_priv->ethsw_data->mc_io, 0, - port_priv->ethsw_data->dpsw_handle, - port_priv->idx, - &cfg); - - if (if_running) { - ret = dpsw_if_enable(ethsw->mc_io, 0, - ethsw->dpsw_handle, - port_priv->idx); - if (ret) { - netdev_err(netdev, "dpsw_if_enable err %d\n", ret); - return ret; - } - } - return err; -} - -static int dpaa2_switch_ethtool_get_sset_count(struct net_device *dev, int sset) -{ - switch (sset) { - case ETH_SS_STATS: - return DPAA2_SWITCH_NUM_COUNTERS; - default: - return -EOPNOTSUPP; - } -} - -static void dpaa2_switch_ethtool_get_strings(struct net_device *netdev, - u32 stringset, u8 *data) -{ - int i; - - switch (stringset) { - case ETH_SS_STATS: - for (i = 0; i < DPAA2_SWITCH_NUM_COUNTERS; i++) - memcpy(data + i * ETH_GSTRING_LEN, - dpaa2_switch_ethtool_counters[i].name, - ETH_GSTRING_LEN); - break; - } -} - -static void dpaa2_switch_ethtool_get_stats(struct net_device *netdev, - struct ethtool_stats *stats, - u64 *data) -{ - struct ethsw_port_priv *port_priv = netdev_priv(netdev); - int i, err; - - for (i = 0; i < DPAA2_SWITCH_NUM_COUNTERS; i++) { - err = dpsw_if_get_counter(port_priv->ethsw_data->mc_io, 0, - port_priv->ethsw_data->dpsw_handle, - port_priv->idx, - dpaa2_switch_ethtool_counters[i].id, - &data[i]); - if (err) - netdev_err(netdev, "dpsw_if_get_counter[%s] err %d\n", - dpaa2_switch_ethtool_counters[i].name, err); - } -} - -const struct ethtool_ops dpaa2_switch_port_ethtool_ops = { - .get_drvinfo = dpaa2_switch_get_drvinfo, - .get_link = ethtool_op_get_link, - .get_link_ksettings = dpaa2_switch_get_link_ksettings, - .set_link_ksettings = dpaa2_switch_set_link_ksettings, - .get_strings = dpaa2_switch_ethtool_get_strings, - .get_ethtool_stats = dpaa2_switch_ethtool_get_stats, - .get_sset_count = dpaa2_switch_ethtool_get_sset_count, -}; diff --git a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c deleted file mode 100644 index 703055e063ff..000000000000 --- a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c +++ /dev/null @@ -1,1839 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * DPAA2 Ethernet Switch driver - * - * Copyright 2014-2016 Freescale Semiconductor Inc. - * Copyright 2017-2018 NXP - * - */ - -#include <linux/module.h> - -#include <linux/interrupt.h> -#include <linux/msi.h> -#include <linux/kthread.h> -#include <linux/workqueue.h> - -#include <linux/fsl/mc.h> - -#include "ethsw.h" - -/* Minimal supported DPSW version */ -#define DPSW_MIN_VER_MAJOR 8 -#define DPSW_MIN_VER_MINOR 1 - -#define DEFAULT_VLAN_ID 1 - -static int dpaa2_switch_add_vlan(struct ethsw_core *ethsw, u16 vid) -{ - int err; - - struct dpsw_vlan_cfg vcfg = { - .fdb_id = 0, - }; - - err = dpsw_vlan_add(ethsw->mc_io, 0, - ethsw->dpsw_handle, vid, &vcfg); - if (err) { - dev_err(ethsw->dev, "dpsw_vlan_add err %d\n", err); - return err; - } - ethsw->vlans[vid] = ETHSW_VLAN_MEMBER; - - return 0; -} - -static bool dpaa2_switch_port_is_up(struct ethsw_port_priv *port_priv) -{ - struct net_device *netdev = port_priv->netdev; - struct dpsw_link_state state; - int err; - - err = dpsw_if_get_link_state(port_priv->ethsw_data->mc_io, 0, - port_priv->ethsw_data->dpsw_handle, - port_priv->idx, &state); - if (err) { - netdev_err(netdev, "dpsw_if_get_link_state() err %d\n", err); - return true; - } - - WARN_ONCE(state.up > 1, "Garbage read into link_state"); - - return state.up ? true : false; -} - -static int dpaa2_switch_port_set_pvid(struct ethsw_port_priv *port_priv, u16 pvid) -{ - struct ethsw_core *ethsw = port_priv->ethsw_data; - struct net_device *netdev = port_priv->netdev; - struct dpsw_tci_cfg tci_cfg = { 0 }; - bool up; - int err, ret; - - err = dpsw_if_get_tci(ethsw->mc_io, 0, ethsw->dpsw_handle, - port_priv->idx, &tci_cfg); - if (err) { - netdev_err(netdev, "dpsw_if_get_tci err %d\n", err); - return err; - } - - tci_cfg.vlan_id = pvid; - - /* Interface needs to be down to change PVID */ - up = dpaa2_switch_port_is_up(port_priv); - if (up) { - err = dpsw_if_disable(ethsw->mc_io, 0, - ethsw->dpsw_handle, - port_priv->idx); - if (err) { - netdev_err(netdev, "dpsw_if_disable err %d\n", err); - return err; - } - } - - err = dpsw_if_set_tci(ethsw->mc_io, 0, ethsw->dpsw_handle, - port_priv->idx, &tci_cfg); - if (err) { - netdev_err(netdev, "dpsw_if_set_tci err %d\n", err); - goto set_tci_error; - } - - /* Delete previous PVID info and mark the new one */ - port_priv->vlans[port_priv->pvid] &= ~ETHSW_VLAN_PVID; - port_priv->vlans[pvid] |= ETHSW_VLAN_PVID; - port_priv->pvid = pvid; - -set_tci_error: - if (up) { - ret = dpsw_if_enable(ethsw->mc_io, 0, - ethsw->dpsw_handle, - port_priv->idx); - if (ret) { - netdev_err(netdev, "dpsw_if_enable err %d\n", ret); - return ret; - } - } - - return err; -} - -static int dpaa2_switch_port_add_vlan(struct ethsw_port_priv *port_priv, - u16 vid, u16 flags) -{ - struct ethsw_core *ethsw = port_priv->ethsw_data; - struct net_device *netdev = port_priv->netdev; - struct dpsw_vlan_if_cfg vcfg; - int err; - - if (port_priv->vlans[vid]) { - netdev_warn(netdev, "VLAN %d already configured\n", vid); - return -EEXIST; - } - - vcfg.num_ifs = 1; - vcfg.if_id[0] = port_priv->idx; - err = dpsw_vlan_add_if(ethsw->mc_io, 0, ethsw->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(ethsw->mc_io, 0, - ethsw->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) { - err = dpaa2_switch_port_set_pvid(port_priv, vid); - if (err) - return err; - } - - return 0; -} - -static int dpaa2_switch_set_learning(struct ethsw_core *ethsw, bool enable) -{ - enum dpsw_fdb_learning_mode learn_mode; - int err; - - if (enable) - learn_mode = DPSW_FDB_LEARNING_MODE_HW; - else - learn_mode = DPSW_FDB_LEARNING_MODE_DIS; - - err = dpsw_fdb_set_learning_mode(ethsw->mc_io, 0, ethsw->dpsw_handle, 0, - learn_mode); - if (err) { - dev_err(ethsw->dev, "dpsw_fdb_set_learning_mode err %d\n", err); - return err; - } - ethsw->learning = enable; - - return 0; -} - -static int dpaa2_switch_port_set_flood(struct ethsw_port_priv *port_priv, bool enable) -{ - int err; - - err = dpsw_if_set_flooding(port_priv->ethsw_data->mc_io, 0, - port_priv->ethsw_data->dpsw_handle, - port_priv->idx, enable); - if (err) { - netdev_err(port_priv->netdev, - "dpsw_if_set_flooding err %d\n", err); - return err; - } - port_priv->flood = enable; - - return 0; -} - -static int dpaa2_switch_port_set_stp_state(struct ethsw_port_priv *port_priv, u8 state) -{ - struct dpsw_stp_cfg stp_cfg = { - .state = state, - }; - int err; - u16 vid; - - if (!netif_running(port_priv->netdev) || state == port_priv->stp_state) - return 0; /* Nothing to do */ - - for (vid = 0; vid <= VLAN_VID_MASK; vid++) { - if (port_priv->vlans[vid] & ETHSW_VLAN_MEMBER) { - stp_cfg.vlan_id = vid; - err = dpsw_if_set_stp(port_priv->ethsw_data->mc_io, 0, - port_priv->ethsw_data->dpsw_handle, - port_priv->idx, &stp_cfg); - if (err) { - netdev_err(port_priv->netdev, - "dpsw_if_set_stp err %d\n", err); - return err; - } - } - } - - port_priv->stp_state = state; - - return 0; -} - -static int dpaa2_switch_dellink(struct ethsw_core *ethsw, u16 vid) -{ - struct ethsw_port_priv *ppriv_local = NULL; - int i, err; - - if (!ethsw->vlans[vid]) - return -ENOENT; - - err = dpsw_vlan_remove(ethsw->mc_io, 0, ethsw->dpsw_handle, vid); - if (err) { - dev_err(ethsw->dev, "dpsw_vlan_remove err %d\n", err); - return err; - } - ethsw->vlans[vid] = 0; - - for (i = 0; i < ethsw->sw_attr.num_ifs; i++) { - ppriv_local = ethsw->ports[i]; - ppriv_local->vlans[vid] = 0; - } - - return 0; -} - -static int dpaa2_switch_port_fdb_add_uc(struct ethsw_port_priv *port_priv, - const unsigned char *addr) -{ - struct dpsw_fdb_unicast_cfg entry = {0}; - int err; - - entry.if_egress = port_priv->idx; - entry.type = DPSW_FDB_ENTRY_STATIC; - ether_addr_copy(entry.mac_addr, addr); - - err = dpsw_fdb_add_unicast(port_priv->ethsw_data->mc_io, 0, - port_priv->ethsw_data->dpsw_handle, - 0, &entry); - if (err) - netdev_err(port_priv->netdev, - "dpsw_fdb_add_unicast err %d\n", err); - return err; -} - -static int dpaa2_switch_port_fdb_del_uc(struct ethsw_port_priv *port_priv, - const unsigned char *addr) -{ - struct dpsw_fdb_unicast_cfg entry = {0}; - int err; - - entry.if_egress = port_priv->idx; - entry.type = DPSW_FDB_ENTRY_STATIC; - ether_addr_copy(entry.mac_addr, addr); - - err = dpsw_fdb_remove_unicast(port_priv->ethsw_data->mc_io, 0, - port_priv->ethsw_data->dpsw_handle, - 0, &entry); - /* Silently discard error for calling multiple times the del command */ - if (err && err != -ENXIO) - netdev_err(port_priv->netdev, - "dpsw_fdb_remove_unicast err %d\n", err); - return err; -} - -static int dpaa2_switch_port_fdb_add_mc(struct ethsw_port_priv *port_priv, - const unsigned char *addr) -{ - 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->idx; - - err = dpsw_fdb_add_multicast(port_priv->ethsw_data->mc_io, 0, - port_priv->ethsw_data->dpsw_handle, - 0, &entry); - /* Silently discard error for calling multiple times the add command */ - if (err && err != -ENXIO) - netdev_err(port_priv->netdev, "dpsw_fdb_add_multicast err %d\n", - err); - return err; -} - -static int dpaa2_switch_port_fdb_del_mc(struct ethsw_port_priv *port_priv, - const unsigned char *addr) -{ - 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->idx; - - err = dpsw_fdb_remove_multicast(port_priv->ethsw_data->mc_io, 0, - port_priv->ethsw_data->dpsw_handle, - 0, &entry); - /* Silently discard error for calling multiple times the del command */ - if (err && err != -ENAVAIL) - netdev_err(port_priv->netdev, - "dpsw_fdb_remove_multicast err %d\n", err); - return err; -} - -static int dpaa2_switch_port_fdb_add(struct ndmsg *ndm, struct nlattr *tb[], - struct net_device *dev, const unsigned char *addr, - u16 vid, u16 flags, - struct netlink_ext_ack *extack) -{ - if (is_unicast_ether_addr(addr)) - return dpaa2_switch_port_fdb_add_uc(netdev_priv(dev), - addr); - else - return dpaa2_switch_port_fdb_add_mc(netdev_priv(dev), - addr); -} - -static int dpaa2_switch_port_fdb_del(struct ndmsg *ndm, struct nlattr *tb[], - struct net_device *dev, - const unsigned char *addr, u16 vid) -{ - if (is_unicast_ether_addr(addr)) - return dpaa2_switch_port_fdb_del_uc(netdev_priv(dev), - addr); - else - return dpaa2_switch_port_fdb_del_mc(netdev_priv(dev), - addr); -} - -static void dpaa2_switch_port_get_stats(struct net_device *netdev, - struct rtnl_link_stats64 *stats) -{ - struct ethsw_port_priv *port_priv = netdev_priv(netdev); - u64 tmp; - int err; - - err = dpsw_if_get_counter(port_priv->ethsw_data->mc_io, 0, - port_priv->ethsw_data->dpsw_handle, - port_priv->idx, - DPSW_CNT_ING_FRAME, &stats->rx_packets); - if (err) - goto error; - - err = dpsw_if_get_counter(port_priv->ethsw_data->mc_io, 0, - port_priv->ethsw_data->dpsw_handle, - port_priv->idx, - DPSW_CNT_EGR_FRAME, &stats->tx_packets); - if (err) - goto error; - - err = dpsw_if_get_counter(port_priv->ethsw_data->mc_io, 0, - port_priv->ethsw_data->dpsw_handle, - port_priv->idx, - DPSW_CNT_ING_BYTE, &stats->rx_bytes); - if (err) - goto error; - - err = dpsw_if_get_counter(port_priv->ethsw_data->mc_io, 0, - port_priv->ethsw_data->dpsw_handle, - port_priv->idx, - DPSW_CNT_EGR_BYTE, &stats->tx_bytes); - if (err) - goto error; - - err = dpsw_if_get_counter(port_priv->ethsw_data->mc_io, 0, - port_priv->ethsw_data->dpsw_handle, - port_priv->idx, - DPSW_CNT_ING_FRAME_DISCARD, - &stats->rx_dropped); - if (err) - goto error; - - err = dpsw_if_get_counter(port_priv->ethsw_data->mc_io, 0, - port_priv->ethsw_data->dpsw_handle, - port_priv->idx, - DPSW_CNT_ING_FLTR_FRAME, - &tmp); - if (err) - goto error; - stats->rx_dropped += tmp; - - err = dpsw_if_get_counter(port_priv->ethsw_data->mc_io, 0, - port_priv->ethsw_data->dpsw_handle, - port_priv->idx, - DPSW_CNT_EGR_FRAME_DISCARD, - &stats->tx_dropped); - if (err) - goto error; - - return; - -error: - netdev_err(netdev, "dpsw_if_get_counter err %d\n", err); -} - -static bool dpaa2_switch_port_has_offload_stats(const struct net_device *netdev, - int attr_id) -{ - return (attr_id == IFLA_OFFLOAD_XSTATS_CPU_HIT); -} - -static int dpaa2_switch_port_get_offload_stats(int attr_id, - const struct net_device *netdev, - void *sp) -{ - switch (attr_id) { - case IFLA_OFFLOAD_XSTATS_CPU_HIT: - dpaa2_switch_port_get_stats((struct net_device *)netdev, sp); - return 0; - } - - return -EINVAL; -} - -static int dpaa2_switch_port_change_mtu(struct net_device *netdev, int mtu) -{ - struct ethsw_port_priv *port_priv = netdev_priv(netdev); - int err; - - err = dpsw_if_set_max_frame_length(port_priv->ethsw_data->mc_io, - 0, - port_priv->ethsw_data->dpsw_handle, - port_priv->idx, - (u16)ETHSW_L2_MAX_FRM(mtu)); - if (err) { - netdev_err(netdev, - "dpsw_if_set_max_frame_length() err %d\n", err); - return err; - } - - netdev->mtu = mtu; - return 0; -} - -static int dpaa2_switch_port_carrier_state_sync(struct net_device *netdev) -{ - struct ethsw_port_priv *port_priv = netdev_priv(netdev); - struct dpsw_link_state state; - int err; - - /* Interrupts are received even though no one issued an 'ifconfig up' - * on the switch interface. Ignore these link state update interrupts - */ - if (!netif_running(netdev)) - return 0; - - err = dpsw_if_get_link_state(port_priv->ethsw_data->mc_io, 0, - port_priv->ethsw_data->dpsw_handle, - port_priv->idx, &state); - if (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 != port_priv->link_state) { - if (state.up) - netif_carrier_on(netdev); - else - netif_carrier_off(netdev); - port_priv->link_state = state.up; - } - - return 0; -} - -static int dpaa2_switch_port_open(struct net_device *netdev) -{ - struct ethsw_port_priv *port_priv = netdev_priv(netdev); - int err; - - /* No need to allow Tx as control interface is disabled */ - netif_tx_stop_all_queues(netdev); - - /* Explicitly set carrier off, otherwise - * netif_carrier_ok() will return true and cause 'ip link show' - * to report the LOWER_UP flag, even though the link - * notification wasn't even received. - */ - netif_carrier_off(netdev); - - err = dpsw_if_enable(port_priv->ethsw_data->mc_io, 0, - port_priv->ethsw_data->dpsw_handle, - port_priv->idx); - if (err) { - netdev_err(netdev, "dpsw_if_enable err %d\n", err); - return err; - } - - /* sync carrier state */ - err = dpaa2_switch_port_carrier_state_sync(netdev); - if (err) { - netdev_err(netdev, - "dpaa2_switch_port_carrier_state_sync err %d\n", err); - goto err_carrier_sync; - } - - return 0; - -err_carrier_sync: - dpsw_if_disable(port_priv->ethsw_data->mc_io, 0, - port_priv->ethsw_data->dpsw_handle, - port_priv->idx); - return err; -} - -static int dpaa2_switch_port_stop(struct net_device *netdev) -{ - struct ethsw_port_priv *port_priv = netdev_priv(netdev); - int err; - - err = dpsw_if_disable(port_priv->ethsw_data->mc_io, 0, - port_priv->ethsw_data->dpsw_handle, - port_priv->idx); - if (err) { - netdev_err(netdev, "dpsw_if_disable err %d\n", err); - return err; - } - - return 0; -} - -static netdev_tx_t dpaa2_switch_port_dropframe(struct sk_buff *skb, - struct net_device *netdev) -{ - /* we don't support I/O for now, drop the frame */ - dev_kfree_skb_any(skb); - - return NETDEV_TX_OK; -} - -static int dpaa2_switch_port_parent_id(struct net_device *dev, - struct netdev_phys_item_id *ppid) -{ - struct ethsw_port_priv *port_priv = netdev_priv(dev); - - ppid->id_len = 1; - ppid->id[0] = port_priv->ethsw_data->dev_id; - - return 0; -} - -static int dpaa2_switch_port_get_phys_name(struct net_device *netdev, char *name, - size_t len) -{ - struct ethsw_port_priv *port_priv = netdev_priv(netdev); - int err; - - err = snprintf(name, len, "p%d", port_priv->idx); - if (err >= len) - return -EINVAL; - - return 0; -} - -struct ethsw_dump_ctx { - struct net_device *dev; - struct sk_buff *skb; - struct netlink_callback *cb; - int idx; -}; - -static int dpaa2_switch_fdb_dump_nl(struct fdb_dump_entry *entry, - struct ethsw_dump_ctx *dump) -{ - int is_dynamic = entry->type & DPSW_FDB_ENTRY_DINAMIC; - u32 portid = NETLINK_CB(dump->cb->skb).portid; - u32 seq = dump->cb->nlh->nlmsg_seq; - struct nlmsghdr *nlh; - struct ndmsg *ndm; - - if (dump->idx < dump->cb->args[2]) - goto skip; - - nlh = nlmsg_put(dump->skb, portid, seq, RTM_NEWNEIGH, - sizeof(*ndm), NLM_F_MULTI); - if (!nlh) - return -EMSGSIZE; - - ndm = nlmsg_data(nlh); - ndm->ndm_family = AF_BRIDGE; - ndm->ndm_pad1 = 0; - ndm->ndm_pad2 = 0; - ndm->ndm_flags = NTF_SELF; - ndm->ndm_type = 0; - ndm->ndm_ifindex = dump->dev->ifindex; - ndm->ndm_state = is_dynamic ? NUD_REACHABLE : NUD_NOARP; - - if (nla_put(dump->skb, NDA_LLADDR, ETH_ALEN, entry->mac_addr)) - goto nla_put_failure; - - nlmsg_end(dump->skb, nlh); - -skip: - dump->idx++; - return 0; - -nla_put_failure: - nlmsg_cancel(dump->skb, nlh); - return -EMSGSIZE; -} - -static int dpaa2_switch_port_fdb_valid_entry(struct fdb_dump_entry *entry, - struct ethsw_port_priv *port_priv) -{ - int idx = port_priv->idx; - int valid; - - if (entry->type & DPSW_FDB_ENTRY_TYPE_UNICAST) - valid = entry->if_info == port_priv->idx; - else - valid = entry->if_mask[idx / 8] & BIT(idx % 8); - - return valid; -} - -static int dpaa2_switch_port_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb, - struct net_device *net_dev, - struct net_device *filter_dev, int *idx) -{ - struct ethsw_port_priv *port_priv = netdev_priv(net_dev); - struct ethsw_core *ethsw = port_priv->ethsw_data; - struct device *dev = net_dev->dev.parent; - struct fdb_dump_entry *fdb_entries; - struct fdb_dump_entry fdb_entry; - struct ethsw_dump_ctx dump = { - .dev = net_dev, - .skb = skb, - .cb = cb, - .idx = *idx, - }; - dma_addr_t fdb_dump_iova; - u16 num_fdb_entries; - u32 fdb_dump_size; - int err = 0, i; - u8 *dma_mem; - - fdb_dump_size = ethsw->sw_attr.max_fdb_entries * sizeof(fdb_entry); - dma_mem = kzalloc(fdb_dump_size, GFP_KERNEL); - if (!dma_mem) - return -ENOMEM; - - fdb_dump_iova = dma_map_single(dev, dma_mem, fdb_dump_size, - DMA_FROM_DEVICE); - if (dma_mapping_error(dev, fdb_dump_iova)) { - netdev_err(net_dev, "dma_map_single() failed\n"); - err = -ENOMEM; - goto err_map; - } - - err = dpsw_fdb_dump(ethsw->mc_io, 0, ethsw->dpsw_handle, 0, - fdb_dump_iova, fdb_dump_size, &num_fdb_entries); - if (err) { - netdev_err(net_dev, "dpsw_fdb_dump() = %d\n", err); - goto err_dump; - } - - dma_unmap_single(dev, fdb_dump_iova, fdb_dump_size, DMA_FROM_DEVICE); - - fdb_entries = (struct fdb_dump_entry *)dma_mem; - for (i = 0; i < num_fdb_entries; i++) { - fdb_entry = fdb_entries[i]; - - if (!dpaa2_switch_port_fdb_valid_entry(&fdb_entry, port_priv)) - continue; - - err = dpaa2_switch_fdb_dump_nl(&fdb_entry, &dump); - if (err) - goto end; - } - -end: - *idx = dump.idx; - - kfree(dma_mem); - - return 0; - -err_dump: - dma_unmap_single(dev, fdb_dump_iova, fdb_dump_size, DMA_TO_DEVICE); -err_map: - kfree(dma_mem); - return err; -} - -static int dpaa2_switch_port_set_mac_addr(struct ethsw_port_priv *port_priv) -{ - struct ethsw_core *ethsw = port_priv->ethsw_data; - struct net_device *net_dev = port_priv->netdev; - struct device *dev = net_dev->dev.parent; - u8 mac_addr[ETH_ALEN]; - int err; - - if (!(ethsw->features & ETHSW_FEATURE_MAC_ADDR)) - return 0; - - /* Get firmware address, if any */ - err = dpsw_if_get_port_mac_addr(ethsw->mc_io, 0, ethsw->dpsw_handle, - port_priv->idx, mac_addr); - if (err) { - dev_err(dev, "dpsw_if_get_port_mac_addr() failed\n"); - return err; - } - - /* First check if firmware has any address configured by bootloader */ - if (!is_zero_ether_addr(mac_addr)) { - memcpy(net_dev->dev_addr, mac_addr, net_dev->addr_len); - } else { - /* No MAC address configured, fill in net_dev->dev_addr - * with a random one - */ - eth_hw_addr_random(net_dev); - dev_dbg_once(dev, "device(s) have all-zero hwaddr, replaced with random\n"); - - /* Override NET_ADDR_RANDOM set by eth_hw_addr_random(); for all - * practical purposes, this will be our "permanent" mac address, - * at least until the next reboot. This move will also permit - * register_netdevice() to properly fill up net_dev->perm_addr. - */ - net_dev->addr_assign_type = NET_ADDR_PERM; - } - - return 0; -} - -static const struct net_device_ops dpaa2_switch_port_ops = { - .ndo_open = dpaa2_switch_port_open, - .ndo_stop = dpaa2_switch_port_stop, - - .ndo_set_mac_address = eth_mac_addr, - .ndo_get_stats64 = dpaa2_switch_port_get_stats, - .ndo_change_mtu = dpaa2_switch_port_change_mtu, - .ndo_has_offload_stats = dpaa2_switch_port_has_offload_stats, - .ndo_get_offload_stats = dpaa2_switch_port_get_offload_stats, - .ndo_fdb_add = dpaa2_switch_port_fdb_add, - .ndo_fdb_del = dpaa2_switch_port_fdb_del, - .ndo_fdb_dump = dpaa2_switch_port_fdb_dump, - - .ndo_start_xmit = dpaa2_switch_port_dropframe, - .ndo_get_port_parent_id = dpaa2_switch_port_parent_id, - .ndo_get_phys_port_name = dpaa2_switch_port_get_phys_name, -}; - -static bool dpaa2_switch_port_dev_check(const struct net_device *netdev, - struct notifier_block *nb) -{ - struct ethsw_port_priv *port_priv = netdev_priv(netdev); - - if (netdev->netdev_ops == &dpaa2_switch_port_ops && - (!nb || &port_priv->ethsw_data->port_nb == nb || - &port_priv->ethsw_data->port_switchdev_nb == nb || - &port_priv->ethsw_data->port_switchdevb_nb == nb)) - return true; - - return false; -} - -static void dpaa2_switch_links_state_update(struct ethsw_core *ethsw) -{ - int i; - - for (i = 0; i < ethsw->sw_attr.num_ifs; i++) { - dpaa2_switch_port_carrier_state_sync(ethsw->ports[i]->netdev); - dpaa2_switch_port_set_mac_addr(ethsw->ports[i]); - } -} - -static irqreturn_t dpaa2_switch_irq0_handler_thread(int irq_num, void *arg) -{ - struct device *dev = (struct device *)arg; - struct ethsw_core *ethsw = dev_get_drvdata(dev); - - /* Mask the events and the if_id reserved bits to be cleared on read */ - u32 status = DPSW_IRQ_EVENT_LINK_CHANGED | 0xFFFF0000; - int err; - - err = dpsw_get_irq_status(ethsw->mc_io, 0, ethsw->dpsw_handle, - DPSW_IRQ_INDEX_IF, &status); - if (err) { - dev_err(dev, "Can't get irq status (err %d)\n", err); - - err = dpsw_clear_irq_status(ethsw->mc_io, 0, ethsw->dpsw_handle, - DPSW_IRQ_INDEX_IF, 0xFFFFFFFF); - if (err) - dev_err(dev, "Can't clear irq status (err %d)\n", err); - goto out; - } - - if (status & DPSW_IRQ_EVENT_LINK_CHANGED) - dpaa2_switch_links_state_update(ethsw); - -out: - return IRQ_HANDLED; -} - -static int dpaa2_switch_setup_irqs(struct fsl_mc_device *sw_dev) -{ - struct device *dev = &sw_dev->dev; - struct ethsw_core *ethsw = dev_get_drvdata(dev); - u32 mask = DPSW_IRQ_EVENT_LINK_CHANGED; - struct fsl_mc_device_irq *irq; - int err; - - err = fsl_mc_allocate_irqs(sw_dev); - if (err) { - dev_err(dev, "MC irqs allocation failed\n"); - return err; - } - - if (WARN_ON(sw_dev->obj_desc.irq_count != DPSW_IRQ_NUM)) { - err = -EINVAL; - goto free_irq; - } - - err = dpsw_set_irq_enable(ethsw->mc_io, 0, ethsw->dpsw_handle, - DPSW_IRQ_INDEX_IF, 0); - if (err) { - dev_err(dev, "dpsw_set_irq_enable err %d\n", err); - goto free_irq; - } - - irq = sw_dev->irqs[DPSW_IRQ_INDEX_IF]; - - err = devm_request_threaded_irq(dev, irq->msi_desc->irq, - NULL, - dpaa2_switch_irq0_handler_thread, - IRQF_NO_SUSPEND | IRQF_ONESHOT, - dev_name(dev), dev); - if (err) { - dev_err(dev, "devm_request_threaded_irq(): %d\n", err); - goto free_irq; - } - - err = dpsw_set_irq_mask(ethsw->mc_io, 0, ethsw->dpsw_handle, - DPSW_IRQ_INDEX_IF, mask); - if (err) { - dev_err(dev, "dpsw_set_irq_mask(): %d\n", err); - goto free_devm_irq; - } - - err = dpsw_set_irq_enable(ethsw->mc_io, 0, ethsw->dpsw_handle, - DPSW_IRQ_INDEX_IF, 1); - if (err) { - dev_err(dev, "dpsw_set_irq_enable(): %d\n", 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 dpaa2_switch_teardown_irqs(struct fsl_mc_device *sw_dev) -{ - struct device *dev = &sw_dev->dev; - struct ethsw_core *ethsw = dev_get_drvdata(dev); - int err; - - err = dpsw_set_irq_enable(ethsw->mc_io, 0, ethsw->dpsw_handle, - DPSW_IRQ_INDEX_IF, 0); - if (err) - dev_err(dev, "dpsw_set_irq_enable err %d\n", err); - - fsl_mc_free_irqs(sw_dev); -} - -static int dpaa2_switch_port_attr_stp_state_set(struct net_device *netdev, - u8 state) -{ - struct ethsw_port_priv *port_priv = netdev_priv(netdev); - - return dpaa2_switch_port_set_stp_state(port_priv, state); -} - -static int -dpaa2_switch_port_attr_br_flags_pre_set(struct net_device *netdev, - struct switchdev_brport_flags flags) -{ - if (flags.mask & ~(BR_LEARNING | BR_FLOOD)) - return -EINVAL; - - return 0; -} - -static int -dpaa2_switch_port_attr_br_flags_set(struct net_device *netdev, - struct switchdev_brport_flags flags) -{ - struct ethsw_port_priv *port_priv = netdev_priv(netdev); - int err = 0; - - if (flags.mask & BR_LEARNING) { - /* Learning is enabled per switch */ - err = dpaa2_switch_set_learning(port_priv->ethsw_data, - !!(flags.val & BR_LEARNING)); - if (err) - return err; - } - - if (flags.mask & BR_FLOOD) { - err = dpaa2_switch_port_set_flood(port_priv, - !!(flags.val & BR_FLOOD)); - if (err) - return err; - } - - return 0; -} - -static int dpaa2_switch_port_attr_set(struct net_device *netdev, - const struct switchdev_attr *attr) -{ - int err = 0; - - switch (attr->id) { - case SWITCHDEV_ATTR_ID_PORT_STP_STATE: - err = dpaa2_switch_port_attr_stp_state_set(netdev, - attr->u.stp_state); - break; - case SWITCHDEV_ATTR_ID_PORT_PRE_BRIDGE_FLAGS: - err = dpaa2_switch_port_attr_br_flags_pre_set(netdev, - attr->u.brport_flags); - break; - case SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS: - err = dpaa2_switch_port_attr_br_flags_set(netdev, - attr->u.brport_flags); - break; - case SWITCHDEV_ATTR_ID_BRIDGE_VLAN_FILTERING: - /* VLANs are supported by default */ - break; - default: - err = -EOPNOTSUPP; - break; - } - - return err; -} - -static int dpaa2_switch_port_vlans_add(struct net_device *netdev, - const struct switchdev_obj_port_vlan *vlan) -{ - struct ethsw_port_priv *port_priv = netdev_priv(netdev); - struct ethsw_core *ethsw = port_priv->ethsw_data; - struct dpsw_attr *attr = ðsw->sw_attr; - int err = 0; - - /* Make sure that the VLAN is not already configured - * on the switch port - */ - if (port_priv->vlans[vlan->vid] & ETHSW_VLAN_MEMBER) - return -EEXIST; - - /* Check if there is space for a new VLAN */ - err = dpsw_get_attributes(ethsw->mc_io, 0, ethsw->dpsw_handle, - ðsw->sw_attr); - if (err) { - netdev_err(netdev, "dpsw_get_attributes err %d\n", err); - return err; - } - if (attr->max_vlans - attr->num_vlans < 1) - return -ENOSPC; - - /* Check if there is space for a new VLAN */ - err = dpsw_get_attributes(ethsw->mc_io, 0, ethsw->dpsw_handle, - ðsw->sw_attr); - if (err) { - netdev_err(netdev, "dpsw_get_attributes err %d\n", err); - return err; - } - if (attr->max_vlans - attr->num_vlans < 1) - return -ENOSPC; - - if (!port_priv->ethsw_data->vlans[vlan->vid]) { - /* this is a new VLAN */ - err = dpaa2_switch_add_vlan(port_priv->ethsw_data, vlan->vid); - if (err) - return err; - - port_priv->ethsw_data->vlans[vlan->vid] |= ETHSW_VLAN_GLOBAL; - } - - return dpaa2_switch_port_add_vlan(port_priv, vlan->vid, vlan->flags); -} - -static int dpaa2_switch_port_lookup_address(struct net_device *netdev, int is_uc, - const unsigned char *addr) -{ - struct netdev_hw_addr_list *list = (is_uc) ? &netdev->uc : &netdev->mc; - struct netdev_hw_addr *ha; - - 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 dpaa2_switch_port_mdb_add(struct net_device *netdev, - const struct switchdev_obj_port_mdb *mdb) -{ - struct ethsw_port_priv *port_priv = netdev_priv(netdev); - int err; - - /* Check if address is already set on this port */ - if (dpaa2_switch_port_lookup_address(netdev, 0, mdb->addr)) - return -EEXIST; - - err = dpaa2_switch_port_fdb_add_mc(port_priv, mdb->addr); - if (err) - return err; - - err = dev_mc_add(netdev, mdb->addr); - if (err) { - netdev_err(netdev, "dev_mc_add err %d\n", err); - dpaa2_switch_port_fdb_del_mc(port_priv, mdb->addr); - } - - return err; -} - -static int dpaa2_switch_port_obj_add(struct net_device *netdev, - const struct switchdev_obj *obj) -{ - int err; - - switch (obj->id) { - case SWITCHDEV_OBJ_ID_PORT_VLAN: - err = dpaa2_switch_port_vlans_add(netdev, - SWITCHDEV_OBJ_PORT_VLAN(obj)); - break; - case SWITCHDEV_OBJ_ID_PORT_MDB: - err = dpaa2_switch_port_mdb_add(netdev, - SWITCHDEV_OBJ_PORT_MDB(obj)); - break; - default: - err = -EOPNOTSUPP; - break; - } - - return err; -} - -static int dpaa2_switch_port_del_vlan(struct ethsw_port_priv *port_priv, u16 vid) -{ - struct ethsw_core *ethsw = port_priv->ethsw_data; - struct net_device *netdev = port_priv->netdev; - struct dpsw_vlan_if_cfg vcfg; - int i, err; - - if (!port_priv->vlans[vid]) - return -ENOENT; - - if (port_priv->vlans[vid] & ETHSW_VLAN_PVID) { - err = dpaa2_switch_port_set_pvid(port_priv, 0); - if (err) - return err; - } - - vcfg.num_ifs = 1; - vcfg.if_id[0] = port_priv->idx; - if (port_priv->vlans[vid] & ETHSW_VLAN_UNTAGGED) { - err = dpsw_vlan_remove_if_untagged(ethsw->mc_io, 0, - ethsw->dpsw_handle, - vid, &vcfg); - if (err) { - netdev_err(netdev, - "dpsw_vlan_remove_if_untagged err %d\n", - err); - } - port_priv->vlans[vid] &= ~ETHSW_VLAN_UNTAGGED; - } - - if (port_priv->vlans[vid] & ETHSW_VLAN_MEMBER) { - err = dpsw_vlan_remove_if(ethsw->mc_io, 0, ethsw->dpsw_handle, - vid, &vcfg); - if (err) { - netdev_err(netdev, - "dpsw_vlan_remove_if err %d\n", err); - return err; - } - port_priv->vlans[vid] &= ~ETHSW_VLAN_MEMBER; - - /* Delete VLAN from switch if it is no longer configured on - * any port - */ - for (i = 0; i < ethsw->sw_attr.num_ifs; i++) - if (ethsw->ports[i]->vlans[vid] & ETHSW_VLAN_MEMBER) - return 0; /* Found a port member in VID */ - - ethsw->vlans[vid] &= ~ETHSW_VLAN_GLOBAL; - - err = dpaa2_switch_dellink(ethsw, vid); - if (err) - return err; - } - - return 0; -} - -static int dpaa2_switch_port_vlans_del(struct net_device *netdev, - const struct switchdev_obj_port_vlan *vlan) -{ - struct ethsw_port_priv *port_priv = netdev_priv(netdev); - - if (netif_is_bridge_master(vlan->obj.orig_dev)) - return -EOPNOTSUPP; - - return dpaa2_switch_port_del_vlan(port_priv, vlan->vid); -} - -static int dpaa2_switch_port_mdb_del(struct net_device *netdev, - const struct switchdev_obj_port_mdb *mdb) -{ - struct ethsw_port_priv *port_priv = netdev_priv(netdev); - int err; - - if (!dpaa2_switch_port_lookup_address(netdev, 0, mdb->addr)) - return -ENOENT; - - err = dpaa2_switch_port_fdb_del_mc(port_priv, mdb->addr); - if (err) - return err; - - err = dev_mc_del(netdev, mdb->addr); - if (err) { - netdev_err(netdev, "dev_mc_del err %d\n", err); - return err; - } - - return err; -} - -static int dpaa2_switch_port_obj_del(struct net_device *netdev, - const struct switchdev_obj *obj) -{ - int err; - - switch (obj->id) { - case SWITCHDEV_OBJ_ID_PORT_VLAN: - err = dpaa2_switch_port_vlans_del(netdev, SWITCHDEV_OBJ_PORT_VLAN(obj)); - break; - case SWITCHDEV_OBJ_ID_PORT_MDB: - err = dpaa2_switch_port_mdb_del(netdev, SWITCHDEV_OBJ_PORT_MDB(obj)); - break; - default: - err = -EOPNOTSUPP; - break; - } - return err; -} - -static int dpaa2_switch_port_attr_set_event(struct net_device *netdev, - struct switchdev_notifier_port_attr_info - *port_attr_info) -{ - int err; - - err = dpaa2_switch_port_attr_set(netdev, port_attr_info->attr); - - port_attr_info->handled = true; - return notifier_from_errno(err); -} - -/* For the moment, only flood setting needs to be updated */ -static int dpaa2_switch_port_bridge_join(struct net_device *netdev, - struct net_device *upper_dev) -{ - struct ethsw_port_priv *port_priv = netdev_priv(netdev); - struct ethsw_core *ethsw = port_priv->ethsw_data; - struct ethsw_port_priv *other_port_priv; - struct net_device *other_dev; - struct list_head *iter; - int i, err; - - for (i = 0; i < ethsw->sw_attr.num_ifs; i++) - if (ethsw->ports[i]->bridge_dev && - (ethsw->ports[i]->bridge_dev != upper_dev)) { - netdev_err(netdev, - "Only one bridge supported per DPSW object!\n"); - return -EINVAL; - } - - netdev_for_each_lower_dev(upper_dev, other_dev, iter) { - if (!dpaa2_switch_port_dev_check(other_dev, NULL)) - continue; - - other_port_priv = netdev_priv(other_dev); - if (other_port_priv->ethsw_data != port_priv->ethsw_data) { - netdev_err(netdev, - "Interface from a different DPSW is in the bridge already!\n"); - return -EINVAL; - } - } - - /* Enable flooding */ - err = dpaa2_switch_port_set_flood(port_priv, 1); - if (!err) - port_priv->bridge_dev = upper_dev; - - return err; -} - -static int dpaa2_switch_port_bridge_leave(struct net_device *netdev) -{ - struct ethsw_port_priv *port_priv = netdev_priv(netdev); - int err; - - /* Disable flooding */ - err = dpaa2_switch_port_set_flood(port_priv, 0); - if (!err) - port_priv->bridge_dev = NULL; - - return err; -} - -static int dpaa2_switch_port_netdevice_event(struct notifier_block *nb, - unsigned long event, void *ptr) -{ - struct net_device *netdev = netdev_notifier_info_to_dev(ptr); - struct netdev_notifier_changeupper_info *info = ptr; - struct net_device *upper_dev; - int err = 0; - - if (!dpaa2_switch_port_dev_check(netdev, nb)) - return NOTIFY_DONE; - - /* Handle just upper dev link/unlink for the moment */ - if (event == NETDEV_CHANGEUPPER) { - upper_dev = info->upper_dev; - if (netif_is_bridge_master(upper_dev)) { - if (info->linking) - err = dpaa2_switch_port_bridge_join(netdev, upper_dev); - else - err = dpaa2_switch_port_bridge_leave(netdev); - } - } - - return notifier_from_errno(err); -} - -struct ethsw_switchdev_event_work { - struct work_struct work; - struct switchdev_notifier_fdb_info fdb_info; - struct net_device *dev; - unsigned long event; -}; - -static void dpaa2_switch_event_work(struct work_struct *work) -{ - struct ethsw_switchdev_event_work *switchdev_work = - container_of(work, struct ethsw_switchdev_event_work, work); - struct net_device *dev = switchdev_work->dev; - struct switchdev_notifier_fdb_info *fdb_info; - int err; - - rtnl_lock(); - fdb_info = &switchdev_work->fdb_info; - - switch (switchdev_work->event) { - case SWITCHDEV_FDB_ADD_TO_DEVICE: - if (!fdb_info->added_by_user) - break; - if (is_unicast_ether_addr(fdb_info->addr)) - err = dpaa2_switch_port_fdb_add_uc(netdev_priv(dev), - fdb_info->addr); - else - err = dpaa2_switch_port_fdb_add_mc(netdev_priv(dev), - fdb_info->addr); - if (err) - break; - fdb_info->offloaded = true; - call_switchdev_notifiers(SWITCHDEV_FDB_OFFLOADED, dev, - &fdb_info->info, NULL); - break; - case SWITCHDEV_FDB_DEL_TO_DEVICE: - if (!fdb_info->added_by_user) - break; - if (is_unicast_ether_addr(fdb_info->addr)) - dpaa2_switch_port_fdb_del_uc(netdev_priv(dev), fdb_info->addr); - else - dpaa2_switch_port_fdb_del_mc(netdev_priv(dev), fdb_info->addr); - break; - } - - rtnl_unlock(); - kfree(switchdev_work->fdb_info.addr); - kfree(switchdev_work); - dev_put(dev); -} - -/* Called under rcu_read_lock() */ -static int dpaa2_switch_port_event(struct notifier_block *nb, - unsigned long event, void *ptr) -{ - struct net_device *dev = switchdev_notifier_info_to_dev(ptr); - struct ethsw_port_priv *port_priv = netdev_priv(dev); - struct ethsw_switchdev_event_work *switchdev_work; - struct switchdev_notifier_fdb_info *fdb_info = ptr; - struct ethsw_core *ethsw = port_priv->ethsw_data; - - if (!dpaa2_switch_port_dev_check(dev, nb)) - return NOTIFY_DONE; - - if (event == SWITCHDEV_PORT_ATTR_SET) - return dpaa2_switch_port_attr_set_event(dev, ptr); - - switchdev_work = kzalloc(sizeof(*switchdev_work), GFP_ATOMIC); - if (!switchdev_work) - return NOTIFY_BAD; - - INIT_WORK(&switchdev_work->work, dpaa2_switch_event_work); - switchdev_work->dev = dev; - switchdev_work->event = event; - - switch (event) { - case SWITCHDEV_FDB_ADD_TO_DEVICE: - case SWITCHDEV_FDB_DEL_TO_DEVICE: - memcpy(&switchdev_work->fdb_info, ptr, - sizeof(switchdev_work->fdb_info)); - switchdev_work->fdb_info.addr = kzalloc(ETH_ALEN, GFP_ATOMIC); - if (!switchdev_work->fdb_info.addr) - goto err_addr_alloc; - - ether_addr_copy((u8 *)switchdev_work->fdb_info.addr, - fdb_info->addr); - - /* Take a reference on the device to avoid being freed. */ - dev_hold(dev); - break; - default: - kfree(switchdev_work); - return NOTIFY_DONE; - } - - queue_work(ethsw->workqueue, &switchdev_work->work); - - return NOTIFY_DONE; - -err_addr_alloc: - kfree(switchdev_work); - return NOTIFY_BAD; -} - -static int dpaa2_switch_port_obj_event(unsigned long event, - struct net_device *netdev, - struct switchdev_notifier_port_obj_info *port_obj_info) -{ - int err = -EOPNOTSUPP; - - switch (event) { - case SWITCHDEV_PORT_OBJ_ADD: - err = dpaa2_switch_port_obj_add(netdev, port_obj_info->obj); - break; - case SWITCHDEV_PORT_OBJ_DEL: - err = dpaa2_switch_port_obj_del(netdev, port_obj_info->obj); - break; - } - - port_obj_info->handled = true; - return notifier_from_errno(err); -} - -static int dpaa2_switch_port_blocking_event(struct notifier_block *nb, - unsigned long event, void *ptr) -{ - struct net_device *dev = switchdev_notifier_info_to_dev(ptr); - - if (!dpaa2_switch_port_dev_check(dev, nb)) - return NOTIFY_DONE; - - switch (event) { - case SWITCHDEV_PORT_OBJ_ADD: - case SWITCHDEV_PORT_OBJ_DEL: - return dpaa2_switch_port_obj_event(event, dev, ptr); - case SWITCHDEV_PORT_ATTR_SET: - return dpaa2_switch_port_attr_set_event(dev, ptr); - } - - return NOTIFY_DONE; -} - -static int dpaa2_switch_register_notifier(struct device *dev) -{ - struct ethsw_core *ethsw = dev_get_drvdata(dev); - int err; - - ethsw->port_nb.notifier_call = dpaa2_switch_port_netdevice_event; - err = register_netdevice_notifier(ðsw->port_nb); - if (err) { - dev_err(dev, "Failed to register netdev notifier\n"); - return err; - } - - ethsw->port_switchdev_nb.notifier_call = dpaa2_switch_port_event; - err = register_switchdev_notifier(ðsw->port_switchdev_nb); - if (err) { - dev_err(dev, "Failed to register switchdev notifier\n"); - goto err_switchdev_nb; - } - - ethsw->port_switchdevb_nb.notifier_call = dpaa2_switch_port_blocking_event; - err = register_switchdev_blocking_notifier(ðsw->port_switchdevb_nb); - if (err) { - dev_err(dev, "Failed to register switchdev blocking notifier\n"); - goto err_switchdev_blocking_nb; - } - - return 0; - -err_switchdev_blocking_nb: - unregister_switchdev_notifier(ðsw->port_switchdev_nb); -err_switchdev_nb: - unregister_netdevice_notifier(ðsw->port_nb); - return err; -} - -static void dpaa2_switch_detect_features(struct ethsw_core *ethsw) -{ - ethsw->features = 0; - - if (ethsw->major > 8 || (ethsw->major == 8 && ethsw->minor >= 6)) - ethsw->features |= ETHSW_FEATURE_MAC_ADDR; -} - -static int dpaa2_switch_init(struct fsl_mc_device *sw_dev) -{ - struct device *dev = &sw_dev->dev; - struct ethsw_core *ethsw = dev_get_drvdata(dev); - struct dpsw_stp_cfg stp_cfg; - int err; - u16 i; - - ethsw->dev_id = sw_dev->obj_desc.id; - - err = dpsw_open(ethsw->mc_io, 0, ethsw->dev_id, ðsw->dpsw_handle); - if (err) { - dev_err(dev, "dpsw_open err %d\n", err); - return err; - } - - err = dpsw_get_attributes(ethsw->mc_io, 0, ethsw->dpsw_handle, - ðsw->sw_attr); - if (err) { - dev_err(dev, "dpsw_get_attributes err %d\n", err); - goto err_close; - } - - err = dpsw_get_api_version(ethsw->mc_io, 0, - ðsw->major, - ðsw->minor); - if (err) { - dev_err(dev, "dpsw_get_api_version err %d\n", err); - goto err_close; - } - - /* Minimum supported DPSW version check */ - if (ethsw->major < DPSW_MIN_VER_MAJOR || - (ethsw->major == DPSW_MIN_VER_MAJOR && - ethsw->minor < DPSW_MIN_VER_MINOR)) { - dev_err(dev, "DPSW version %d:%d not supported. Use %d.%d or greater.\n", - ethsw->major, - ethsw->minor, - DPSW_MIN_VER_MAJOR, DPSW_MIN_VER_MINOR); - err = -ENOTSUPP; - goto err_close; - } - - dpaa2_switch_detect_features(ethsw); - - err = dpsw_reset(ethsw->mc_io, 0, ethsw->dpsw_handle); - if (err) { - dev_err(dev, "dpsw_reset err %d\n", err); - goto err_close; - } - - err = dpsw_fdb_set_learning_mode(ethsw->mc_io, 0, ethsw->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; - } - - stp_cfg.vlan_id = DEFAULT_VLAN_ID; - stp_cfg.state = DPSW_STP_STATE_FORWARDING; - - for (i = 0; i < ethsw->sw_attr.num_ifs; i++) { - err = dpsw_if_set_stp(ethsw->mc_io, 0, ethsw->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(ethsw->mc_io, 0, - ethsw->dpsw_handle, i, 1); - if (err) { - dev_err(dev, - "dpsw_if_set_broadcast err %d for port %d\n", - err, i); - goto err_close; - } - } - - ethsw->workqueue = alloc_ordered_workqueue("%s_%d_ordered", - WQ_MEM_RECLAIM, "ethsw", - ethsw->sw_attr.id); - if (!ethsw->workqueue) { - err = -ENOMEM; - goto err_close; - } - - err = dpaa2_switch_register_notifier(dev); - if (err) - goto err_destroy_ordered_workqueue; - - return 0; - -err_destroy_ordered_workqueue: - destroy_workqueue(ethsw->workqueue); - -err_close: - dpsw_close(ethsw->mc_io, 0, ethsw->dpsw_handle); - return err; -} - -static int dpaa2_switch_port_init(struct ethsw_port_priv *port_priv, u16 port) -{ - struct net_device *netdev = port_priv->netdev; - struct ethsw_core *ethsw = port_priv->ethsw_data; - struct dpsw_vlan_if_cfg vcfg; - int err; - - /* Switch starts with all ports configured to VLAN 1. Need to - * remove this setting to allow configuration at bridge join - */ - vcfg.num_ifs = 1; - vcfg.if_id[0] = port_priv->idx; - - err = dpsw_vlan_remove_if_untagged(ethsw->mc_io, 0, ethsw->dpsw_handle, - DEFAULT_VLAN_ID, &vcfg); - if (err) { - netdev_err(netdev, "dpsw_vlan_remove_if_untagged err %d\n", - err); - return err; - } - - err = dpaa2_switch_port_set_pvid(port_priv, 0); - if (err) - return err; - - err = dpsw_vlan_remove_if(ethsw->mc_io, 0, ethsw->dpsw_handle, - DEFAULT_VLAN_ID, &vcfg); - if (err) - netdev_err(netdev, "dpsw_vlan_remove_if err %d\n", err); - - return err; -} - -static void dpaa2_switch_unregister_notifier(struct device *dev) -{ - struct ethsw_core *ethsw = dev_get_drvdata(dev); - struct notifier_block *nb; - int err; - - nb = ðsw->port_switchdevb_nb; - err = unregister_switchdev_blocking_notifier(nb); - if (err) - dev_err(dev, - "Failed to unregister switchdev blocking notifier (%d)\n", - err); - - err = unregister_switchdev_notifier(ðsw->port_switchdev_nb); - if (err) - dev_err(dev, - "Failed to unregister switchdev notifier (%d)\n", err); - - err = unregister_netdevice_notifier(ðsw->port_nb); - if (err) - dev_err(dev, - "Failed to unregister netdev notifier (%d)\n", err); -} - -static void dpaa2_switch_takedown(struct fsl_mc_device *sw_dev) -{ - struct device *dev = &sw_dev->dev; - struct ethsw_core *ethsw = dev_get_drvdata(dev); - int err; - - dpaa2_switch_unregister_notifier(dev); - - err = dpsw_close(ethsw->mc_io, 0, ethsw->dpsw_handle); - if (err) - dev_warn(dev, "dpsw_close err %d\n", err); -} - -static int dpaa2_switch_remove(struct fsl_mc_device *sw_dev) -{ - struct ethsw_port_priv *port_priv; - struct ethsw_core *ethsw; - struct device *dev; - int i; - - dev = &sw_dev->dev; - ethsw = dev_get_drvdata(dev); - - dpaa2_switch_teardown_irqs(sw_dev); - - dpsw_disable(ethsw->mc_io, 0, ethsw->dpsw_handle); - - for (i = 0; i < ethsw->sw_attr.num_ifs; i++) { - port_priv = ethsw->ports[i]; - unregister_netdev(port_priv->netdev); - free_netdev(port_priv->netdev); - } - kfree(ethsw->ports); - - dpaa2_switch_takedown(sw_dev); - - destroy_workqueue(ethsw->workqueue); - - fsl_mc_portal_free(ethsw->mc_io); - - kfree(ethsw); - - dev_set_drvdata(dev, NULL); - - return 0; -} - -static int dpaa2_switch_probe_port(struct ethsw_core *ethsw, - u16 port_idx) -{ - struct ethsw_port_priv *port_priv; - struct device *dev = ethsw->dev; - struct net_device *port_netdev; - int err; - - port_netdev = alloc_etherdev(sizeof(struct ethsw_port_priv)); - if (!port_netdev) { - dev_err(dev, "alloc_etherdev error\n"); - return -ENOMEM; - } - - port_priv = netdev_priv(port_netdev); - port_priv->netdev = port_netdev; - port_priv->ethsw_data = ethsw; - - port_priv->idx = port_idx; - port_priv->stp_state = BR_STATE_FORWARDING; - - /* Flooding is implicitly enabled */ - port_priv->flood = true; - - SET_NETDEV_DEV(port_netdev, dev); - port_netdev->netdev_ops = &dpaa2_switch_port_ops; - port_netdev->ethtool_ops = &dpaa2_switch_port_ethtool_ops; - - /* Set MTU limits */ - port_netdev->min_mtu = ETH_MIN_MTU; - port_netdev->max_mtu = ETHSW_MAX_FRAME_LENGTH; - - err = dpaa2_switch_port_init(port_priv, port_idx); - if (err) - goto err_port_probe; - - err = dpaa2_switch_port_set_mac_addr(port_priv); - if (err) - goto err_port_probe; - - err = register_netdev(port_netdev); - if (err < 0) { - dev_err(dev, "register_netdev error %d\n", err); - goto err_port_probe; - } - - ethsw->ports[port_idx] = port_priv; - - return 0; - -err_port_probe: - free_netdev(port_netdev); - - return err; -} - -static int dpaa2_switch_probe(struct fsl_mc_device *sw_dev) -{ - struct device *dev = &sw_dev->dev; - struct ethsw_core *ethsw; - int i, err; - - /* Allocate switch core*/ - ethsw = kzalloc(sizeof(*ethsw), GFP_KERNEL); - - if (!ethsw) - return -ENOMEM; - - ethsw->dev = dev; - dev_set_drvdata(dev, ethsw); - - err = fsl_mc_portal_allocate(sw_dev, FSL_MC_IO_ATOMIC_CONTEXT_PORTAL, - ðsw->mc_io); - if (err) { - if (err == -ENXIO) - err = -EPROBE_DEFER; - else - dev_err(dev, "fsl_mc_portal_allocate err %d\n", err); - goto err_free_drvdata; - } - - err = dpaa2_switch_init(sw_dev); - if (err) - goto err_free_cmdport; - - /* DEFAULT_VLAN_ID is implicitly configured on the switch */ - ethsw->vlans[DEFAULT_VLAN_ID] = ETHSW_VLAN_MEMBER; - - /* Learning is implicitly enabled */ - ethsw->learning = true; - - ethsw->ports = kcalloc(ethsw->sw_attr.num_ifs, sizeof(*ethsw->ports), - GFP_KERNEL); - if (!(ethsw->ports)) { - err = -ENOMEM; - goto err_takedown; - } - - for (i = 0; i < ethsw->sw_attr.num_ifs; i++) { - err = dpaa2_switch_probe_port(ethsw, i); - if (err) - goto err_free_ports; - } - - err = dpsw_enable(ethsw->mc_io, 0, ethsw->dpsw_handle); - if (err) { - dev_err(ethsw->dev, "dpsw_enable err %d\n", err); - goto err_free_ports; - } - - /* Make sure the switch ports are disabled at probe time */ - for (i = 0; i < ethsw->sw_attr.num_ifs; i++) - dpsw_if_disable(ethsw->mc_io, 0, ethsw->dpsw_handle, i); - - /* Setup IRQs */ - err = dpaa2_switch_setup_irqs(sw_dev); - if (err) - goto err_stop; - - dev_info(dev, "probed %d port switch\n", ethsw->sw_attr.num_ifs); - return 0; - -err_stop: - dpsw_disable(ethsw->mc_io, 0, ethsw->dpsw_handle); - -err_free_ports: - /* Cleanup registered ports only */ - for (i--; i >= 0; i--) { - unregister_netdev(ethsw->ports[i]->netdev); - free_netdev(ethsw->ports[i]->netdev); - } - kfree(ethsw->ports); - -err_takedown: - dpaa2_switch_takedown(sw_dev); - -err_free_cmdport: - fsl_mc_portal_free(ethsw->mc_io); - -err_free_drvdata: - kfree(ethsw); - dev_set_drvdata(dev, NULL); - - return err; -} - -static const struct fsl_mc_device_id dpaa2_switch_match_id_table[] = { - { - .vendor = FSL_MC_VENDOR_FREESCALE, - .obj_type = "dpsw", - }, - { .vendor = 0x0 } -}; -MODULE_DEVICE_TABLE(fslmc, dpaa2_switch_match_id_table); - -static struct fsl_mc_driver dpaa2_switch_drv = { - .driver = { - .name = KBUILD_MODNAME, - .owner = THIS_MODULE, - }, - .probe = dpaa2_switch_probe, - .remove = dpaa2_switch_remove, - .match_id_table = dpaa2_switch_match_id_table -}; - -module_fsl_mc_driver(dpaa2_switch_drv); - -MODULE_LICENSE("GPL v2"); -MODULE_DESCRIPTION("DPAA2 Ethernet Switch Driver"); diff --git a/drivers/staging/fsl-dpaa2/ethsw/ethsw.h b/drivers/staging/fsl-dpaa2/ethsw/ethsw.h deleted file mode 100644 index 5f9211ccb1ef..000000000000 --- a/drivers/staging/fsl-dpaa2/ethsw/ethsw.h +++ /dev/null @@ -1,80 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * DPAA2 Ethernet Switch declarations - * - * Copyright 2014-2016 Freescale Semiconductor Inc. - * Copyright 2017-2018 NXP - * - */ - -#ifndef __ETHSW_H -#define __ETHSW_H - -#include <linux/netdevice.h> -#include <linux/etherdevice.h> -#include <linux/rtnetlink.h> -#include <linux/if_vlan.h> -#include <uapi/linux/if_bridge.h> -#include <net/switchdev.h> -#include <linux/if_bridge.h> - -#include "dpsw.h" - -/* Number of IRQs supported */ -#define DPSW_IRQ_NUM 2 - -/* Port is member of VLAN */ -#define ETHSW_VLAN_MEMBER 1 -/* VLAN to be treated as untagged on egress */ -#define ETHSW_VLAN_UNTAGGED 2 -/* Untagged frames will be assigned to this VLAN */ -#define ETHSW_VLAN_PVID 4 -/* VLAN configured on the switch */ -#define ETHSW_VLAN_GLOBAL 8 - -/* Maximum Frame Length supported by HW (currently 10k) */ -#define DPAA2_MFL (10 * 1024) -#define ETHSW_MAX_FRAME_LENGTH (DPAA2_MFL - VLAN_ETH_HLEN - ETH_FCS_LEN) -#define ETHSW_L2_MAX_FRM(mtu) ((mtu) + VLAN_ETH_HLEN + ETH_FCS_LEN) - -#define ETHSW_FEATURE_MAC_ADDR BIT(0) - -extern const struct ethtool_ops dpaa2_switch_port_ethtool_ops; - -struct ethsw_core; - -/* Per port private data */ -struct ethsw_port_priv { - struct net_device *netdev; - u16 idx; - struct ethsw_core *ethsw_data; - u8 link_state; - u8 stp_state; - bool flood; - - u8 vlans[VLAN_VID_MASK + 1]; - u16 pvid; - struct net_device *bridge_dev; -}; - -/* Switch data */ -struct ethsw_core { - struct device *dev; - struct fsl_mc_io *mc_io; - u16 dpsw_handle; - struct dpsw_attr sw_attr; - u16 major, minor; - unsigned long features; - int dev_id; - struct ethsw_port_priv **ports; - - u8 vlans[VLAN_VID_MASK + 1]; - bool learning; - - struct notifier_block port_nb; - struct notifier_block port_switchdev_nb; - struct notifier_block port_switchdevb_nb; - struct workqueue_struct *workqueue; -}; - -#endif /* __ETHSW_H */ diff --git a/drivers/staging/octeon/ethernet.c b/drivers/staging/octeon/ethernet.c index 7c60b0cd8bf7..dcbba9621b21 100644 --- a/drivers/staging/octeon/ethernet.c +++ b/drivers/staging/octeon/ethernet.c @@ -407,14 +407,10 @@ static int cvm_oct_common_set_mac_address(struct net_device *dev, void *addr) int cvm_oct_common_init(struct net_device *dev) { struct octeon_ethernet *priv = netdev_priv(dev); - const u8 *mac = NULL; + int ret; - if (priv->of_node) - mac = of_get_mac_address(priv->of_node); - - if (!IS_ERR_OR_NULL(mac)) - ether_addr_copy(dev->dev_addr, mac); - else + ret = of_get_mac_address(priv->of_node, dev->dev_addr); + if (ret) eth_hw_addr_random(dev); /* diff --git a/drivers/staging/wfx/main.c b/drivers/staging/wfx/main.c index e7bc1988124a..4b9fdf99981b 100644 --- a/drivers/staging/wfx/main.c +++ b/drivers/staging/wfx/main.c @@ -334,7 +334,6 @@ int wfx_probe(struct wfx_dev *wdev) { int i; int err; - const void *macaddr; struct gpio_desc *gpio_saved; // During first part of boot, gpio_wakeup cannot yet been used. So @@ -423,9 +422,9 @@ int wfx_probe(struct wfx_dev *wdev) for (i = 0; i < ARRAY_SIZE(wdev->addresses); i++) { eth_zero_addr(wdev->addresses[i].addr); - macaddr = of_get_mac_address(wdev->dev->of_node); - if (!IS_ERR_OR_NULL(macaddr)) { - ether_addr_copy(wdev->addresses[i].addr, macaddr); + err = of_get_mac_address(wdev->dev->of_node, + wdev->addresses[i].addr); + if (!err) { wdev->addresses[i].addr[ETH_ALEN - 1] += i; } else { ether_addr_copy(wdev->addresses[i].addr, |