layerscape: add ls1088ardb device support
[openwrt/openwrt.git] / target / linux / layerscape / patches-4.4 / 7220-dpaa2-ethsw-Ethernet-Switch-driver.patch
1 From 8df017d70c54ceafc99b7904785603c678a2e5c1 Mon Sep 17 00:00:00 2001
2 From: Razvan Stefanescu <razvan.stefanescu@freescale.com>
3 Date: Tue, 22 Sep 2015 11:36:34 +0300
4 Subject: [PATCH 220/226] dpaa2-ethsw: Ethernet Switch driver
5
6 This is a commit of the cummulative, squashed dpaa2-l2switch patches.
7 All the commit logs are preserved below.
8
9 Signed-off-by: Stuart Yoder <stuart.yoder@nxp.com>
10
11 ---------------------------------------------------------------------
12
13 dpaa2-ethsw: Ethernet Switch driver
14
15 Initial support for DPAA2 L2 switch. The switch and all ports are
16 presented as network interfaces in linux (swX and swXpY). I/O
17 functionality is not available on these interfaces, they are exclusively
18 for management.
19
20 Configuration is done using bridge tool. Supported commands are:
21 - fdb operations with unicast/multicast addresses
22 - vlan configuration
23 - setting STP state of ports
24 - flooding, learning control
25
26 Offers support for retrieving port statistics via ethtool (or similar
27 applications).
28
29 This patch contains the following patches squashed together:
30 staging: fsl-dpaa2: ethsw: ethernet switch driver
31 dpaa2-ethsw: Include by default in configuration
32 staging: fsl-dpaa2: ethsw: Rebasing onto kernel 4.0
33 staging: fsl-mc: migrated remaining flibs for MC fw 8.0.0
34 dpaa2-ethsw: Prefix driver name with dpaa2-
35 dpaa2-ethsw: Set carrier state on probe
36 dpaa2-ethsw: Add support for link state update
37
38 These patches were initally submitted by:
39 Alex Marginean <alexandru.marginean@freescale.com>
40 J. German Rivera <German.Rivera@freescale.com>
41 Razvan Stefanescu <razvan.stefanescu@freescale.com>
42
43 and reviewed by Stuart Yoder <stuart.yoder@freescale.com>
44
45 Ported to linux-v4.1 by updating iflink usage and ndo_bridge_getlink()
46 parameters list update.
47
48 Signed-off-by: Razvan Stefanescu <razvan.stefanescu@freescale.com>
49 [Stuart: resolved minor merge conflicts]
50 Signed-off-by: Stuart Yoder <stuart.yoder@nxp.com>
51
52 dpaa2-ethsw: Update dpsw binary interface to 7.0
53
54 This corresponds to MC release 0.8.0.
55
56 Signed-off-by: Razvan Stefanescu <razvan.stefanescu@freescale.com>
57
58 dpaa2-ethsw: Add object version check
59
60 Abort probing if DPSW object version is smaller than required.
61
62 Signed-off-by: Razvan Stefanescu <razvan.stefanescu@freescale.com>
63
64 dpaa2-ethsw: Fix interrupt handling
65
66 Mask only the events handled by the driver - DPSW_IRQ_EVENT_LINK_CHANGED.
67
68 Use clear-on-read mechanism for the interrupt status and avoid calling
69 dpsw_clear_irq_status(). Status contains the events handled (only link
70 state change for the moment) and masks the first 16-bits, as they are used
71 to store the interface ID that generated the event.
72
73 Signed-off-by: Razvan Stefanescu <razvan.stefanescu@freescale.com>
74
75 dpaa2-ethsw: resolve compile issues on uprev to 4.5
76
77 -irq_number field no longer exists in fsl-mc interrupt
78 struct
79 -netdev_master_upper_dev_link() has 2 new parameters, which
80 are set to NULL for now
81
82 Signed-off-by: Stuart Yoder <stuart.yoder@nxp.com>
83 ---
84 MAINTAINERS | 6 +
85 drivers/staging/fsl-dpaa2/Kconfig | 1 +
86 drivers/staging/fsl-dpaa2/Makefile | 1 +
87 drivers/staging/fsl-dpaa2/ethsw/Kconfig | 7 +
88 drivers/staging/fsl-dpaa2/ethsw/Makefile | 10 +
89 drivers/staging/fsl-dpaa2/ethsw/dpsw-cmd.h | 916 ++++++++++++
90 drivers/staging/fsl-dpaa2/ethsw/dpsw.c | 1639 +++++++++++++++++++++
91 drivers/staging/fsl-dpaa2/ethsw/dpsw.h | 2164 ++++++++++++++++++++++++++++
92 drivers/staging/fsl-dpaa2/ethsw/switch.c | 1711 ++++++++++++++++++++++
93 drivers/staging/fsl-mc/include/net.h | 1 -
94 10 files changed, 6455 insertions(+), 1 deletion(-)
95 create mode 100644 drivers/staging/fsl-dpaa2/ethsw/Kconfig
96 create mode 100644 drivers/staging/fsl-dpaa2/ethsw/Makefile
97 create mode 100644 drivers/staging/fsl-dpaa2/ethsw/dpsw-cmd.h
98 create mode 100644 drivers/staging/fsl-dpaa2/ethsw/dpsw.c
99 create mode 100644 drivers/staging/fsl-dpaa2/ethsw/dpsw.h
100 create mode 100644 drivers/staging/fsl-dpaa2/ethsw/switch.c
101
102 --- a/MAINTAINERS
103 +++ b/MAINTAINERS
104 @@ -4554,6 +4554,12 @@ S: Maintained
105 F: drivers/staging/fsl-mc/bus/mc-ioctl.h
106 F: drivers/staging/fsl-mc/bus/mc-restool.c
107
108 +FREESCALE DPAA2 ETHERNET SWITCH DRIVER
109 +M: Alex Marginean <Alexandru.Marginean@freescale.com>
110 +L: linux-kernel@vger.kernel.org
111 +S: Maintained
112 +F: drivers/staging/fsl-dpaa2/ethsw/
113 +
114 FREESCALE DPAA2 MAC/PHY INTERFACE DRIVER
115 M: Alex Marginean <Alexandru.Marginean@freescale.com>
116 L: linux-kernel@vger.kernel.org
117 --- a/drivers/staging/fsl-dpaa2/Kconfig
118 +++ b/drivers/staging/fsl-dpaa2/Kconfig
119 @@ -11,3 +11,4 @@ config FSL_DPAA2
120 source "drivers/staging/fsl-dpaa2/ethernet/Kconfig"
121 source "drivers/staging/fsl-dpaa2/mac/Kconfig"
122 source "drivers/staging/fsl-dpaa2/evb/Kconfig"
123 +source "drivers/staging/fsl-dpaa2/ethsw/Kconfig"
124 --- a/drivers/staging/fsl-dpaa2/Makefile
125 +++ b/drivers/staging/fsl-dpaa2/Makefile
126 @@ -5,3 +5,4 @@
127 obj-$(CONFIG_FSL_DPAA2_ETH) += ethernet/
128 obj-$(CONFIG_FSL_DPAA2_MAC) += mac/
129 obj-$(CONFIG_FSL_DPAA2_EVB) += evb/
130 +obj-$(CONFIG_FSL_DPAA2_ETHSW) += ethsw/
131 --- /dev/null
132 +++ b/drivers/staging/fsl-dpaa2/ethsw/Kconfig
133 @@ -0,0 +1,7 @@
134 +config FSL_DPAA2_ETHSW
135 + tristate "DPAA2 Ethernet Switch"
136 + depends on FSL_MC_BUS && FSL_DPAA2 && FSL_DPAA2_ETH
137 + select FSL_DPAA2_MAC
138 + default y
139 + ---help---
140 + Prototype driver for DPAA2 Ethernet Switch.
141 --- /dev/null
142 +++ b/drivers/staging/fsl-dpaa2/ethsw/Makefile
143 @@ -0,0 +1,10 @@
144 +
145 +obj-$(CONFIG_FSL_DPAA2_ETHSW) += dpaa2-ethsw.o
146 +
147 +dpaa2-ethsw-objs := switch.o dpsw.o
148 +
149 +all:
150 + make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
151 +
152 +clean:
153 + make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
154 --- /dev/null
155 +++ b/drivers/staging/fsl-dpaa2/ethsw/dpsw-cmd.h
156 @@ -0,0 +1,916 @@
157 +/* Copyright 2013-2015 Freescale Semiconductor Inc.
158 + *
159 + * Redistribution and use in source and binary forms, with or without
160 + * modification, are permitted provided that the following conditions are met:
161 + * * Redistributions of source code must retain the above copyright
162 + * notice, this list of conditions and the following disclaimer.
163 + * * Redistributions in binary form must reproduce the above copyright
164 + * notice, this list of conditions and the following disclaimer in the
165 + * documentation and/or other materials provided with the distribution.
166 + * * Neither the name of the above-listed copyright holders nor the
167 + * names of any contributors may be used to endorse or promote products
168 + * derived from this software without specific prior written permission.
169 + *
170 + *
171 + * ALTERNATIVELY, this software may be distributed under the terms of the
172 + * GNU General Public License ("GPL") as published by the Free Software
173 + * Foundation, either version 2 of that License or (at your option) any
174 + * later version.
175 + *
176 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
177 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
178 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
179 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
180 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
181 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
182 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
183 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
184 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
185 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
186 + * POSSIBILITY OF SUCH DAMAGE.
187 + */
188 +#ifndef __FSL_DPSW_CMD_H
189 +#define __FSL_DPSW_CMD_H
190 +
191 +/* DPSW Version */
192 +#define DPSW_VER_MAJOR 7
193 +#define DPSW_VER_MINOR 0
194 +
195 +/* Command IDs */
196 +#define DPSW_CMDID_CLOSE 0x800
197 +#define DPSW_CMDID_OPEN 0x802
198 +#define DPSW_CMDID_CREATE 0x902
199 +#define DPSW_CMDID_DESTROY 0x900
200 +
201 +#define DPSW_CMDID_ENABLE 0x002
202 +#define DPSW_CMDID_DISABLE 0x003
203 +#define DPSW_CMDID_GET_ATTR 0x004
204 +#define DPSW_CMDID_RESET 0x005
205 +#define DPSW_CMDID_IS_ENABLED 0x006
206 +
207 +#define DPSW_CMDID_SET_IRQ 0x010
208 +#define DPSW_CMDID_GET_IRQ 0x011
209 +#define DPSW_CMDID_SET_IRQ_ENABLE 0x012
210 +#define DPSW_CMDID_GET_IRQ_ENABLE 0x013
211 +#define DPSW_CMDID_SET_IRQ_MASK 0x014
212 +#define DPSW_CMDID_GET_IRQ_MASK 0x015
213 +#define DPSW_CMDID_GET_IRQ_STATUS 0x016
214 +#define DPSW_CMDID_CLEAR_IRQ_STATUS 0x017
215 +
216 +#define DPSW_CMDID_SET_REFLECTION_IF 0x022
217 +
218 +#define DPSW_CMDID_ADD_CUSTOM_TPID 0x024
219 +
220 +#define DPSW_CMDID_REMOVE_CUSTOM_TPID 0x026
221 +
222 +#define DPSW_CMDID_IF_SET_TCI 0x030
223 +#define DPSW_CMDID_IF_SET_STP 0x031
224 +#define DPSW_CMDID_IF_SET_ACCEPTED_FRAMES 0x032
225 +#define DPSW_CMDID_SET_IF_ACCEPT_ALL_VLAN 0x033
226 +#define DPSW_CMDID_IF_GET_COUNTER 0x034
227 +#define DPSW_CMDID_IF_SET_COUNTER 0x035
228 +#define DPSW_CMDID_IF_SET_TX_SELECTION 0x036
229 +#define DPSW_CMDID_IF_ADD_REFLECTION 0x037
230 +#define DPSW_CMDID_IF_REMOVE_REFLECTION 0x038
231 +#define DPSW_CMDID_IF_SET_FLOODING_METERING 0x039
232 +#define DPSW_CMDID_IF_SET_METERING 0x03A
233 +#define DPSW_CMDID_IF_SET_EARLY_DROP 0x03B
234 +
235 +#define DPSW_CMDID_IF_ENABLE 0x03D
236 +#define DPSW_CMDID_IF_DISABLE 0x03E
237 +
238 +#define DPSW_CMDID_IF_GET_ATTR 0x042
239 +
240 +#define DPSW_CMDID_IF_SET_MAX_FRAME_LENGTH 0x044
241 +#define DPSW_CMDID_IF_GET_MAX_FRAME_LENGTH 0x045
242 +#define DPSW_CMDID_IF_GET_LINK_STATE 0x046
243 +#define DPSW_CMDID_IF_SET_FLOODING 0x047
244 +#define DPSW_CMDID_IF_SET_BROADCAST 0x048
245 +#define DPSW_CMDID_IF_SET_MULTICAST 0x049
246 +#define DPSW_CMDID_IF_GET_TCI 0x04A
247 +
248 +#define DPSW_CMDID_IF_SET_LINK_CFG 0x04C
249 +
250 +#define DPSW_CMDID_VLAN_ADD 0x060
251 +#define DPSW_CMDID_VLAN_ADD_IF 0x061
252 +#define DPSW_CMDID_VLAN_ADD_IF_UNTAGGED 0x062
253 +#define DPSW_CMDID_VLAN_ADD_IF_FLOODING 0x063
254 +#define DPSW_CMDID_VLAN_REMOVE_IF 0x064
255 +#define DPSW_CMDID_VLAN_REMOVE_IF_UNTAGGED 0x065
256 +#define DPSW_CMDID_VLAN_REMOVE_IF_FLOODING 0x066
257 +#define DPSW_CMDID_VLAN_REMOVE 0x067
258 +#define DPSW_CMDID_VLAN_GET_IF 0x068
259 +#define DPSW_CMDID_VLAN_GET_IF_FLOODING 0x069
260 +#define DPSW_CMDID_VLAN_GET_IF_UNTAGGED 0x06A
261 +#define DPSW_CMDID_VLAN_GET_ATTRIBUTES 0x06B
262 +
263 +#define DPSW_CMDID_FDB_GET_MULTICAST 0x080
264 +#define DPSW_CMDID_FDB_GET_UNICAST 0x081
265 +#define DPSW_CMDID_FDB_ADD 0x082
266 +#define DPSW_CMDID_FDB_REMOVE 0x083
267 +#define DPSW_CMDID_FDB_ADD_UNICAST 0x084
268 +#define DPSW_CMDID_FDB_REMOVE_UNICAST 0x085
269 +#define DPSW_CMDID_FDB_ADD_MULTICAST 0x086
270 +#define DPSW_CMDID_FDB_REMOVE_MULTICAST 0x087
271 +#define DPSW_CMDID_FDB_SET_LEARNING_MODE 0x088
272 +#define DPSW_CMDID_FDB_GET_ATTR 0x089
273 +
274 +#define DPSW_CMDID_ACL_ADD 0x090
275 +#define DPSW_CMDID_ACL_REMOVE 0x091
276 +#define DPSW_CMDID_ACL_ADD_ENTRY 0x092
277 +#define DPSW_CMDID_ACL_REMOVE_ENTRY 0x093
278 +#define DPSW_CMDID_ACL_ADD_IF 0x094
279 +#define DPSW_CMDID_ACL_REMOVE_IF 0x095
280 +#define DPSW_CMDID_ACL_GET_ATTR 0x096
281 +
282 +#define DPSW_CMDID_CTRL_IF_GET_ATTR 0x0A0
283 +#define DPSW_CMDID_CTRL_IF_SET_POOLS 0x0A1
284 +#define DPSW_CMDID_CTRL_IF_ENABLE 0x0A2
285 +#define DPSW_CMDID_CTRL_IF_DISABLE 0x0A3
286 +
287 +/* cmd, param, offset, width, type, arg_name */
288 +#define DPSW_CMD_OPEN(cmd, dpsw_id) \
289 + MC_CMD_OP(cmd, 0, 0, 32, int, dpsw_id)
290 +
291 +/* cmd, param, offset, width, type, arg_name */
292 +#define DPSW_CMD_CREATE(cmd, cfg) \
293 +do { \
294 + MC_CMD_OP(cmd, 0, 0, 16, uint16_t, cfg->num_ifs);\
295 + MC_CMD_OP(cmd, 0, 16, 8, uint8_t, cfg->adv.max_fdbs);\
296 + MC_CMD_OP(cmd, 0, 24, 8, uint8_t, cfg->adv.max_meters_per_if);\
297 + MC_CMD_OP(cmd, 0, 32, 4, enum dpsw_component_type, \
298 + cfg->adv.component_type);\
299 + MC_CMD_OP(cmd, 1, 0, 16, uint16_t, cfg->adv.max_vlans);\
300 + MC_CMD_OP(cmd, 1, 16, 16, uint16_t, cfg->adv.max_fdb_entries);\
301 + MC_CMD_OP(cmd, 1, 32, 16, uint16_t, cfg->adv.fdb_aging_time);\
302 + MC_CMD_OP(cmd, 1, 48, 16, uint16_t, cfg->adv.max_fdb_mc_groups);\
303 + MC_CMD_OP(cmd, 2, 0, 64, uint64_t, cfg->adv.options);\
304 +} while (0)
305 +
306 +/* cmd, param, offset, width, type, arg_name */
307 +#define DPSW_RSP_IS_ENABLED(cmd, en) \
308 + MC_RSP_OP(cmd, 0, 0, 1, int, en)
309 +
310 +/* cmd, param, offset, width, type, arg_name */
311 +#define DPSW_CMD_SET_IRQ(cmd, irq_index, irq_cfg) \
312 +do { \
313 + MC_CMD_OP(cmd, 0, 0, 8, uint8_t, irq_index);\
314 + MC_CMD_OP(cmd, 0, 32, 32, uint32_t, irq_cfg->val);\
315 + MC_CMD_OP(cmd, 1, 0, 64, uint64_t, irq_cfg->addr);\
316 + MC_CMD_OP(cmd, 2, 0, 32, int, irq_cfg->irq_num); \
317 +} while (0)
318 +
319 +/* cmd, param, offset, width, type, arg_name */
320 +#define DPSW_CMD_GET_IRQ(cmd, irq_index) \
321 + MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index)
322 +
323 +/* cmd, param, offset, width, type, arg_name */
324 +#define DPSW_RSP_GET_IRQ(cmd, type, irq_cfg) \
325 +do { \
326 + MC_RSP_OP(cmd, 0, 0, 32, uint32_t, irq_cfg->val); \
327 + MC_RSP_OP(cmd, 1, 0, 64, uint64_t, irq_cfg->addr);\
328 + MC_RSP_OP(cmd, 2, 0, 32, int, irq_cfg->irq_num); \
329 + MC_RSP_OP(cmd, 2, 32, 32, int, type); \
330 +} while (0)
331 +
332 +/* cmd, param, offset, width, type, arg_name */
333 +#define DPSW_CMD_SET_IRQ_ENABLE(cmd, irq_index, enable_state) \
334 +do { \
335 + MC_CMD_OP(cmd, 0, 0, 8, uint8_t, enable_state); \
336 + MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\
337 +} while (0)
338 +
339 +/* cmd, param, offset, width, type, arg_name */
340 +#define DPSW_CMD_GET_IRQ_ENABLE(cmd, irq_index) \
341 + MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index)
342 +
343 +/* cmd, param, offset, width, type, arg_name */
344 +#define DPSW_RSP_GET_IRQ_ENABLE(cmd, enable_state) \
345 + MC_RSP_OP(cmd, 0, 0, 8, uint8_t, enable_state)
346 +
347 +/* cmd, param, offset, width, type, arg_name */
348 +#define DPSW_CMD_SET_IRQ_MASK(cmd, irq_index, mask) \
349 +do { \
350 + MC_CMD_OP(cmd, 0, 0, 32, uint32_t, mask); \
351 + MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\
352 +} while (0)
353 +
354 +/* cmd, param, offset, width, type, arg_name */
355 +#define DPSW_CMD_GET_IRQ_MASK(cmd, irq_index) \
356 + MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index)
357 +
358 +/* cmd, param, offset, width, type, arg_name */
359 +#define DPSW_RSP_GET_IRQ_MASK(cmd, mask) \
360 + MC_RSP_OP(cmd, 0, 0, 32, uint32_t, mask)
361 +
362 +/* cmd, param, offset, width, type, arg_name */
363 +#define DPSW_CMD_GET_IRQ_STATUS(cmd, irq_index, status) \
364 +do { \
365 + MC_CMD_OP(cmd, 0, 0, 32, uint32_t, status);\
366 + MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\
367 +} while (0)
368 +
369 +/* cmd, param, offset, width, type, arg_name */
370 +#define DPSW_RSP_GET_IRQ_STATUS(cmd, status) \
371 + MC_RSP_OP(cmd, 0, 0, 32, uint32_t, status)
372 +
373 +/* cmd, param, offset, width, type, arg_name */
374 +#define DPSW_CMD_CLEAR_IRQ_STATUS(cmd, irq_index, status) \
375 +do { \
376 + MC_CMD_OP(cmd, 0, 0, 32, uint32_t, status); \
377 + MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\
378 +} while (0)
379 +
380 +/* cmd, param, offset, width, type, arg_name */
381 +#define DPSW_RSP_GET_ATTR(cmd, attr) \
382 +do { \
383 + MC_RSP_OP(cmd, 0, 0, 16, uint16_t, attr->num_ifs);\
384 + MC_RSP_OP(cmd, 0, 16, 8, uint8_t, attr->max_fdbs);\
385 + MC_RSP_OP(cmd, 0, 24, 8, uint8_t, attr->num_fdbs);\
386 + MC_RSP_OP(cmd, 0, 32, 16, uint16_t, attr->max_vlans);\
387 + MC_RSP_OP(cmd, 0, 48, 16, uint16_t, attr->num_vlans);\
388 + MC_RSP_OP(cmd, 1, 0, 16, uint16_t, attr->version.major);\
389 + MC_RSP_OP(cmd, 1, 16, 16, uint16_t, attr->version.minor);\
390 + MC_RSP_OP(cmd, 1, 32, 16, uint16_t, attr->max_fdb_entries);\
391 + MC_RSP_OP(cmd, 1, 48, 16, uint16_t, attr->fdb_aging_time);\
392 + MC_RSP_OP(cmd, 2, 0, 32, int, attr->id);\
393 + MC_RSP_OP(cmd, 2, 32, 16, uint16_t, attr->mem_size);\
394 + MC_RSP_OP(cmd, 2, 48, 16, uint16_t, attr->max_fdb_mc_groups);\
395 + MC_RSP_OP(cmd, 3, 0, 64, uint64_t, attr->options);\
396 + MC_RSP_OP(cmd, 4, 0, 8, uint8_t, attr->max_meters_per_if);\
397 + MC_RSP_OP(cmd, 4, 8, 4, enum dpsw_component_type, \
398 + attr->component_type);\
399 +} while (0)
400 +
401 +/* cmd, param, offset, width, type, arg_name */
402 +#define DPSW_CMD_SET_REFLECTION_IF(cmd, if_id) \
403 + MC_CMD_OP(cmd, 0, 0, 16, uint16_t, if_id)
404 +
405 +/* cmd, param, offset, width, type, arg_name */
406 +#define DPSW_CMD_IF_SET_FLOODING(cmd, if_id, en) \
407 +do { \
408 + MC_CMD_OP(cmd, 0, 0, 16, uint16_t, if_id);\
409 + MC_CMD_OP(cmd, 0, 16, 1, int, en);\
410 +} while (0)
411 +
412 +/* cmd, param, offset, width, type, arg_name */
413 +#define DPSW_CMD_IF_SET_BROADCAST(cmd, if_id, en) \
414 +do { \
415 + MC_CMD_OP(cmd, 0, 0, 16, uint16_t, if_id);\
416 + MC_CMD_OP(cmd, 0, 16, 1, int, en);\
417 +} while (0)
418 +
419 +/* cmd, param, offset, width, type, arg_name */
420 +#define DPSW_CMD_IF_SET_MULTICAST(cmd, if_id, en) \
421 +do { \
422 + MC_CMD_OP(cmd, 0, 0, 16, uint16_t, if_id);\
423 + MC_CMD_OP(cmd, 0, 16, 1, int, en);\
424 +} while (0)
425 +
426 +/* cmd, param, offset, width, type, arg_name */
427 +#define DPSW_CMD_IF_SET_TCI(cmd, if_id, cfg) \
428 +do { \
429 + MC_CMD_OP(cmd, 0, 0, 16, uint16_t, if_id);\
430 + MC_CMD_OP(cmd, 0, 16, 12, uint16_t, cfg->vlan_id);\
431 + MC_CMD_OP(cmd, 0, 28, 1, uint8_t, cfg->dei);\
432 + MC_CMD_OP(cmd, 0, 29, 3, uint8_t, cfg->pcp);\
433 +} while (0)
434 +
435 +/* cmd, param, offset, width, type, arg_name */
436 +#define DPSW_CMD_IF_GET_TCI(cmd, if_id) \
437 + MC_CMD_OP(cmd, 0, 0, 16, uint16_t, if_id)
438 +
439 +/* cmd, param, offset, width, type, arg_name */
440 +#define DPSW_RSP_IF_GET_TCI(cmd, cfg) \
441 +do { \
442 + MC_RSP_OP(cmd, 0, 16, 16, uint16_t, cfg->vlan_id);\
443 + MC_RSP_OP(cmd, 0, 32, 8, uint8_t, cfg->dei);\
444 + MC_RSP_OP(cmd, 0, 40, 8, uint8_t, cfg->pcp);\
445 +} while (0)
446 +
447 +/* cmd, param, offset, width, type, arg_name */
448 +#define DPSW_CMD_IF_SET_STP(cmd, if_id, cfg) \
449 +do { \
450 + MC_CMD_OP(cmd, 0, 0, 16, uint16_t, if_id);\
451 + MC_CMD_OP(cmd, 0, 16, 16, uint16_t, cfg->vlan_id);\
452 + MC_CMD_OP(cmd, 0, 32, 4, enum dpsw_stp_state, cfg->state);\
453 +} while (0)
454 +
455 +/* cmd, param, offset, width, type, arg_name */
456 +#define DPSW_CMD_IF_SET_ACCEPTED_FRAMES(cmd, if_id, cfg) \
457 +do { \
458 + MC_CMD_OP(cmd, 0, 0, 16, uint16_t, if_id);\
459 + MC_CMD_OP(cmd, 0, 16, 4, enum dpsw_accepted_frames, cfg->type);\
460 + MC_CMD_OP(cmd, 0, 20, 4, enum dpsw_action, cfg->unaccept_act);\
461 +} while (0)
462 +
463 +/* cmd, param, offset, width, type, arg_name */
464 +#define DPSW_CMD_IF_SET_ACCEPT_ALL_VLAN(cmd, if_id, accept_all) \
465 +do { \
466 + MC_CMD_OP(cmd, 0, 0, 16, uint16_t, if_id);\
467 + MC_CMD_OP(cmd, 0, 16, 1, int, accept_all);\
468 +} while (0)
469 +
470 +/* cmd, param, offset, width, type, arg_name */
471 +#define DPSW_CMD_IF_GET_COUNTER(cmd, if_id, type) \
472 +do { \
473 + MC_CMD_OP(cmd, 0, 0, 16, uint16_t, if_id);\
474 + MC_CMD_OP(cmd, 0, 16, 5, enum dpsw_counter, type);\
475 +} while (0)
476 +
477 +/* cmd, param, offset, width, type, arg_name */
478 +#define DPSW_RSP_IF_GET_COUNTER(cmd, counter) \
479 + MC_RSP_OP(cmd, 1, 0, 64, uint64_t, counter)
480 +
481 +/* cmd, param, offset, width, type, arg_name */
482 +#define DPSW_CMD_IF_SET_COUNTER(cmd, if_id, type, counter) \
483 +do { \
484 + MC_CMD_OP(cmd, 0, 0, 16, uint16_t, if_id);\
485 + MC_CMD_OP(cmd, 0, 16, 5, enum dpsw_counter, type);\
486 + MC_CMD_OP(cmd, 1, 0, 64, uint64_t, counter);\
487 +} while (0)
488 +
489 +/* cmd, param, offset, width, type, arg_name */
490 +#define DPSW_CMD_IF_SET_TX_SELECTION(cmd, if_id, cfg) \
491 +do { \
492 + MC_CMD_OP(cmd, 0, 0, 16, uint16_t, if_id);\
493 + MC_CMD_OP(cmd, 0, 16, 3, enum dpsw_priority_selector, \
494 + cfg->priority_selector);\
495 + MC_CMD_OP(cmd, 1, 0, 8, uint8_t, cfg->tc_id[0]);\
496 + MC_CMD_OP(cmd, 1, 8, 8, uint8_t, cfg->tc_id[1]);\
497 + MC_CMD_OP(cmd, 1, 16, 8, uint8_t, cfg->tc_id[2]);\
498 + MC_CMD_OP(cmd, 1, 24, 8, uint8_t, cfg->tc_id[3]);\
499 + MC_CMD_OP(cmd, 1, 32, 8, uint8_t, cfg->tc_id[4]);\
500 + MC_CMD_OP(cmd, 1, 40, 8, uint8_t, cfg->tc_id[5]);\
501 + MC_CMD_OP(cmd, 1, 48, 8, uint8_t, cfg->tc_id[6]);\
502 + MC_CMD_OP(cmd, 1, 56, 8, uint8_t, cfg->tc_id[7]);\
503 + MC_CMD_OP(cmd, 2, 0, 16, uint16_t, cfg->tc_sched[0].delta_bandwidth);\
504 + MC_CMD_OP(cmd, 2, 16, 4, enum dpsw_schedule_mode, \
505 + cfg->tc_sched[0].mode);\
506 + MC_CMD_OP(cmd, 2, 32, 16, uint16_t, cfg->tc_sched[1].delta_bandwidth);\
507 + MC_CMD_OP(cmd, 2, 48, 4, enum dpsw_schedule_mode, \
508 + cfg->tc_sched[1].mode);\
509 + MC_CMD_OP(cmd, 3, 0, 16, uint16_t, cfg->tc_sched[2].delta_bandwidth);\
510 + MC_CMD_OP(cmd, 3, 16, 4, enum dpsw_schedule_mode, \
511 + cfg->tc_sched[2].mode);\
512 + MC_CMD_OP(cmd, 3, 32, 16, uint16_t, cfg->tc_sched[3].delta_bandwidth);\
513 + MC_CMD_OP(cmd, 3, 48, 4, enum dpsw_schedule_mode, \
514 + cfg->tc_sched[3].mode);\
515 + MC_CMD_OP(cmd, 4, 0, 16, uint16_t, cfg->tc_sched[4].delta_bandwidth);\
516 + MC_CMD_OP(cmd, 4, 16, 4, enum dpsw_schedule_mode, \
517 + cfg->tc_sched[4].mode);\
518 + MC_CMD_OP(cmd, 4, 32, 16, uint16_t, cfg->tc_sched[5].delta_bandwidth);\
519 + MC_CMD_OP(cmd, 4, 48, 4, enum dpsw_schedule_mode, \
520 + cfg->tc_sched[5].mode);\
521 + MC_CMD_OP(cmd, 5, 0, 16, uint16_t, cfg->tc_sched[6].delta_bandwidth);\
522 + MC_CMD_OP(cmd, 5, 16, 4, enum dpsw_schedule_mode, \
523 + cfg->tc_sched[6].mode);\
524 + MC_CMD_OP(cmd, 5, 32, 16, uint16_t, cfg->tc_sched[7].delta_bandwidth);\
525 + MC_CMD_OP(cmd, 5, 48, 4, enum dpsw_schedule_mode, \
526 + cfg->tc_sched[7].mode);\
527 +} while (0)
528 +
529 +/* cmd, param, offset, width, type, arg_name */
530 +#define DPSW_CMD_IF_ADD_REFLECTION(cmd, if_id, cfg) \
531 +do { \
532 + MC_CMD_OP(cmd, 0, 0, 16, uint16_t, if_id);\
533 + MC_CMD_OP(cmd, 0, 16, 16, uint16_t, cfg->vlan_id);\
534 + MC_CMD_OP(cmd, 0, 32, 2, enum dpsw_reflection_filter, cfg->filter);\
535 +} while (0)
536 +
537 +/* cmd, param, offset, width, type, arg_name */
538 +#define DPSW_CMD_IF_REMOVE_REFLECTION(cmd, if_id, cfg) \
539 +do { \
540 + MC_CMD_OP(cmd, 0, 0, 16, uint16_t, if_id);\
541 + MC_CMD_OP(cmd, 0, 16, 16, uint16_t, cfg->vlan_id);\
542 + MC_CMD_OP(cmd, 0, 32, 2, enum dpsw_reflection_filter, cfg->filter);\
543 +} while (0)
544 +
545 +/* cmd, param, offset, width, type, arg_name */
546 +#define DPSW_CMD_IF_SET_FLOODING_METERING(cmd, if_id, cfg) \
547 +do { \
548 + MC_CMD_OP(cmd, 0, 0, 16, uint16_t, if_id);\
549 + MC_CMD_OP(cmd, 0, 24, 4, enum dpsw_metering_mode, cfg->mode);\
550 + MC_CMD_OP(cmd, 0, 28, 4, enum dpsw_metering_unit, cfg->units);\
551 + MC_CMD_OP(cmd, 0, 32, 32, uint32_t, cfg->cir);\
552 + MC_CMD_OP(cmd, 1, 0, 32, uint32_t, cfg->eir);\
553 + MC_CMD_OP(cmd, 1, 32, 32, uint32_t, cfg->cbs);\
554 + MC_CMD_OP(cmd, 2, 0, 32, uint32_t, cfg->ebs);\
555 +} while (0)
556 +
557 +/* cmd, param, offset, width, type, arg_name */
558 +#define DPSW_CMD_IF_SET_METERING(cmd, if_id, tc_id, cfg) \
559 +do { \
560 + MC_CMD_OP(cmd, 0, 0, 16, uint16_t, if_id);\
561 + MC_CMD_OP(cmd, 0, 16, 8, uint8_t, tc_id);\
562 + MC_CMD_OP(cmd, 0, 24, 4, enum dpsw_metering_mode, cfg->mode);\
563 + MC_CMD_OP(cmd, 0, 28, 4, enum dpsw_metering_unit, cfg->units);\
564 + MC_CMD_OP(cmd, 0, 32, 32, uint32_t, cfg->cir);\
565 + MC_CMD_OP(cmd, 1, 0, 32, uint32_t, cfg->eir);\
566 + MC_CMD_OP(cmd, 1, 32, 32, uint32_t, cfg->cbs);\
567 + MC_CMD_OP(cmd, 2, 0, 32, uint32_t, cfg->ebs);\
568 +} while (0)
569 +
570 +/* cmd, param, offset, width, type, arg_name */
571 +#define DPSW_PREP_EARLY_DROP(ext, cfg) \
572 +do { \
573 + MC_PREP_OP(ext, 0, 0, 2, enum dpsw_early_drop_mode, cfg->drop_mode); \
574 + MC_PREP_OP(ext, 0, 2, 2, \
575 + enum dpsw_early_drop_unit, cfg->units); \
576 + MC_PREP_OP(ext, 0, 32, 32, uint32_t, cfg->tail_drop_threshold); \
577 + MC_PREP_OP(ext, 1, 0, 8, uint8_t, cfg->green.drop_probability); \
578 + MC_PREP_OP(ext, 2, 0, 64, uint64_t, cfg->green.max_threshold); \
579 + MC_PREP_OP(ext, 3, 0, 64, uint64_t, cfg->green.min_threshold); \
580 + MC_PREP_OP(ext, 5, 0, 8, uint8_t, cfg->yellow.drop_probability);\
581 + MC_PREP_OP(ext, 6, 0, 64, uint64_t, cfg->yellow.max_threshold); \
582 + MC_PREP_OP(ext, 7, 0, 64, uint64_t, cfg->yellow.min_threshold); \
583 +} while (0)
584 +
585 +/* cmd, param, offset, width, type, arg_name */
586 +#define DPSW_EXT_EARLY_DROP(ext, cfg) \
587 +do { \
588 + MC_EXT_OP(ext, 0, 0, 2, enum dpsw_early_drop_mode, cfg->drop_mode); \
589 + MC_EXT_OP(ext, 0, 2, 2, \
590 + enum dpsw_early_drop_unit, cfg->units); \
591 + MC_EXT_OP(ext, 0, 32, 32, uint32_t, cfg->tail_drop_threshold); \
592 + MC_EXT_OP(ext, 1, 0, 8, uint8_t, cfg->green.drop_probability); \
593 + MC_EXT_OP(ext, 2, 0, 64, uint64_t, cfg->green.max_threshold); \
594 + MC_EXT_OP(ext, 3, 0, 64, uint64_t, cfg->green.min_threshold); \
595 + MC_EXT_OP(ext, 5, 0, 8, uint8_t, cfg->yellow.drop_probability);\
596 + MC_EXT_OP(ext, 6, 0, 64, uint64_t, cfg->yellow.max_threshold); \
597 + MC_EXT_OP(ext, 7, 0, 64, uint64_t, cfg->yellow.min_threshold); \
598 +} while (0)
599 +
600 +/* cmd, param, offset, width, type, arg_name */
601 +#define DPSW_CMD_IF_SET_EARLY_DROP(cmd, if_id, tc_id, early_drop_iova) \
602 +do { \
603 + MC_CMD_OP(cmd, 0, 8, 8, uint8_t, tc_id); \
604 + MC_CMD_OP(cmd, 0, 16, 16, uint16_t, if_id); \
605 + MC_CMD_OP(cmd, 1, 0, 64, uint64_t, early_drop_iova); \
606 +} while (0)
607 +
608 +/* cmd, param, offset, width, type, arg_name */
609 +#define DPSW_CMD_ADD_CUSTOM_TPID(cmd, cfg) \
610 + MC_CMD_OP(cmd, 0, 16, 16, uint16_t, cfg->tpid)
611 +
612 +/* cmd, param, offset, width, type, arg_name */
613 +#define DPSW_CMD_REMOVE_CUSTOM_TPID(cmd, cfg) \
614 + MC_CMD_OP(cmd, 0, 16, 16, uint16_t, cfg->tpid)
615 +
616 +/* cmd, param, offset, width, type, arg_name */
617 +#define DPSW_CMD_IF_ENABLE(cmd, if_id) \
618 + MC_CMD_OP(cmd, 0, 0, 16, uint16_t, if_id)
619 +
620 +/* cmd, param, offset, width, type, arg_name */
621 +#define DPSW_CMD_IF_DISABLE(cmd, if_id) \
622 + MC_CMD_OP(cmd, 0, 0, 16, uint16_t, if_id)
623 +
624 +/* cmd, param, offset, width, type, arg_name */
625 +#define DPSW_CMD_IF_GET_ATTR(cmd, if_id) \
626 + MC_CMD_OP(cmd, 0, 0, 16, uint16_t, if_id)
627 +
628 +/* cmd, param, offset, width, type, arg_name */
629 +#define DPSW_RSP_IF_GET_ATTR(cmd, attr) \
630 +do { \
631 + MC_RSP_OP(cmd, 0, 0, 4, enum dpsw_accepted_frames, \
632 + attr->admit_untagged);\
633 + MC_RSP_OP(cmd, 0, 5, 1, int, attr->enabled);\
634 + MC_RSP_OP(cmd, 0, 6, 1, int, attr->accept_all_vlan);\
635 + MC_RSP_OP(cmd, 0, 16, 8, uint8_t, attr->num_tcs);\
636 + MC_RSP_OP(cmd, 0, 32, 16, uint16_t, attr->qdid);\
637 + MC_RSP_OP(cmd, 1, 0, 32, uint32_t, attr->options);\
638 + MC_RSP_OP(cmd, 2, 0, 32, uint32_t, attr->rate);\
639 +} while (0)
640 +
641 +/* cmd, param, offset, width, type, arg_name */
642 +#define DPSW_CMD_IF_SET_MAX_FRAME_LENGTH(cmd, if_id, frame_length) \
643 +do { \
644 + MC_CMD_OP(cmd, 0, 0, 16, uint16_t, if_id);\
645 + MC_CMD_OP(cmd, 0, 16, 16, uint16_t, frame_length);\
646 +} while (0)
647 +
648 +/* cmd, param, offset, width, type, arg_name */
649 +#define DPSW_CMD_IF_GET_MAX_FRAME_LENGTH(cmd, if_id) \
650 + MC_CMD_OP(cmd, 0, 0, 16, uint16_t, if_id)
651 +
652 +/* cmd, param, offset, width, type, arg_name */
653 +#define DPSW_RSP_IF_GET_MAX_FRAME_LENGTH(cmd, frame_length) \
654 + MC_RSP_OP(cmd, 0, 16, 16, uint16_t, frame_length)
655 +
656 +/* cmd, param, offset, width, type, arg_name */
657 +#define DPSW_CMD_IF_SET_LINK_CFG(cmd, if_id, cfg) \
658 +do { \
659 + MC_CMD_OP(cmd, 0, 0, 16, uint16_t, if_id);\
660 + MC_CMD_OP(cmd, 1, 0, 32, uint32_t, cfg->rate);\
661 + MC_CMD_OP(cmd, 2, 0, 64, uint64_t, cfg->options);\
662 +} while (0)
663 +
664 +/* cmd, param, offset, width, type, arg_name */
665 +#define DPSW_CMD_IF_GET_LINK_STATE(cmd, if_id) \
666 + MC_CMD_OP(cmd, 0, 0, 16, uint16_t, if_id)
667 +
668 +/* cmd, param, offset, width, type, arg_name */
669 +#define DPSW_RSP_IF_GET_LINK_STATE(cmd, state) \
670 +do { \
671 + MC_RSP_OP(cmd, 0, 32, 1, int, state->up);\
672 + MC_RSP_OP(cmd, 1, 0, 32, uint32_t, state->rate);\
673 + MC_RSP_OP(cmd, 2, 0, 64, uint64_t, state->options);\
674 +} while (0)
675 +
676 +/* cmd, param, offset, width, type, arg_name */
677 +#define DPSW_CMD_VLAN_ADD(cmd, vlan_id, cfg) \
678 +do { \
679 + MC_CMD_OP(cmd, 0, 0, 16, uint16_t, cfg->fdb_id);\
680 + MC_CMD_OP(cmd, 0, 16, 16, uint16_t, vlan_id);\
681 +} while (0)
682 +
683 +/* cmd, param, offset, width, type, arg_name */
684 +#define DPSW_CMD_VLAN_ADD_IF(cmd, vlan_id) \
685 + MC_CMD_OP(cmd, 0, 16, 16, uint16_t, vlan_id)
686 +
687 +/* cmd, param, offset, width, type, arg_name */
688 +#define DPSW_CMD_VLAN_ADD_IF_UNTAGGED(cmd, vlan_id) \
689 + MC_CMD_OP(cmd, 0, 16, 16, uint16_t, vlan_id)
690 +
691 +/* cmd, param, offset, width, type, arg_name */
692 +#define DPSW_CMD_VLAN_ADD_IF_FLOODING(cmd, vlan_id) \
693 + MC_CMD_OP(cmd, 0, 16, 16, uint16_t, vlan_id)
694 +
695 +#define DPSW_CMD_VLAN_REMOVE_IF(cmd, vlan_id) \
696 + MC_CMD_OP(cmd, 0, 16, 16, uint16_t, vlan_id)
697 +
698 +/* cmd, param, offset, width, type, arg_name */
699 +#define DPSW_CMD_VLAN_REMOVE_IF_UNTAGGED(cmd, vlan_id) \
700 + MC_CMD_OP(cmd, 0, 16, 16, uint16_t, vlan_id)
701 +
702 +/* cmd, param, offset, width, type, arg_name */
703 +#define DPSW_CMD_VLAN_REMOVE_IF_FLOODING(cmd, vlan_id) \
704 + MC_CMD_OP(cmd, 0, 16, 16, uint16_t, vlan_id)
705 +
706 +/* cmd, param, offset, width, type, arg_name */
707 +#define DPSW_CMD_VLAN_REMOVE(cmd, vlan_id) \
708 + MC_CMD_OP(cmd, 0, 16, 16, uint16_t, vlan_id)
709 +
710 +/* cmd, param, offset, width, type, arg_name */
711 +#define DPSW_CMD_VLAN_GET_ATTR(cmd, vlan_id) \
712 + MC_CMD_OP(cmd, 0, 0, 16, uint16_t, vlan_id)
713 +
714 +/* cmd, param, offset, width, type, arg_name */
715 +#define DPSW_RSP_VLAN_GET_ATTR(cmd, attr) \
716 +do { \
717 + MC_RSP_OP(cmd, 1, 0, 16, uint16_t, attr->fdb_id); \
718 + MC_RSP_OP(cmd, 1, 16, 16, uint16_t, attr->num_ifs); \
719 + MC_RSP_OP(cmd, 1, 32, 16, uint16_t, attr->num_untagged_ifs); \
720 + MC_RSP_OP(cmd, 1, 48, 16, uint16_t, attr->num_flooding_ifs); \
721 +} while (0)
722 +
723 +/* cmd, param, offset, width, type, arg_name */
724 +#define DPSW_CMD_VLAN_GET_IF(cmd, vlan_id) \
725 + MC_CMD_OP(cmd, 0, 0, 16, uint16_t, vlan_id)
726 +
727 +/* cmd, param, offset, width, type, arg_name */
728 +#define DPSW_RSP_VLAN_GET_IF(cmd, cfg) \
729 + MC_RSP_OP(cmd, 0, 16, 16, uint16_t, cfg->num_ifs)
730 +
731 +/* cmd, param, offset, width, type, arg_name */
732 +#define DPSW_CMD_VLAN_GET_IF_FLOODING(cmd, vlan_id) \
733 + MC_CMD_OP(cmd, 0, 0, 16, uint16_t, vlan_id)
734 +
735 +/* cmd, param, offset, width, type, arg_name */
736 +#define DPSW_RSP_VLAN_GET_IF_FLOODING(cmd, cfg) \
737 + MC_RSP_OP(cmd, 0, 16, 16, uint16_t, cfg->num_ifs)
738 +
739 +/* cmd, param, offset, width, type, arg_name */
740 +#define DPSW_CMD_VLAN_GET_IF_UNTAGGED(cmd, vlan_id) \
741 + MC_CMD_OP(cmd, 0, 0, 16, uint16_t, vlan_id)
742 +
743 +/* cmd, param, offset, width, type, arg_name */
744 +#define DPSW_RSP_VLAN_GET_IF_UNTAGGED(cmd, cfg) \
745 + MC_RSP_OP(cmd, 0, 16, 16, uint16_t, cfg->num_ifs)
746 +
747 +/* param, offset, width, type, arg_name */
748 +#define DPSW_CMD_FDB_ADD(cmd, cfg) \
749 +do { \
750 + MC_CMD_OP(cmd, 0, 32, 16, uint16_t, cfg->fdb_aging_time);\
751 + MC_CMD_OP(cmd, 0, 48, 16, uint16_t, cfg->num_fdb_entries);\
752 +} while (0)
753 +
754 +/* cmd, param, offset, width, type, arg_name */
755 +#define DPSW_RSP_FDB_ADD(cmd, fdb_id) \
756 + MC_RSP_OP(cmd, 0, 0, 16, uint16_t, fdb_id)
757 +
758 +/* cmd, param, offset, width, type, arg_name */
759 +#define DPSW_CMD_FDB_REMOVE(cmd, fdb_id) \
760 + MC_CMD_OP(cmd, 0, 0, 16, uint16_t, fdb_id)
761 +
762 +/* cmd, param, offset, width, type, arg_name */
763 +#define DPSW_CMD_FDB_ADD_UNICAST(cmd, fdb_id, cfg) \
764 +do { \
765 + MC_CMD_OP(cmd, 0, 0, 16, uint16_t, fdb_id);\
766 + MC_CMD_OP(cmd, 0, 16, 8, uint8_t, cfg->mac_addr[5]);\
767 + MC_CMD_OP(cmd, 0, 24, 8, uint8_t, cfg->mac_addr[4]);\
768 + MC_CMD_OP(cmd, 0, 32, 8, uint8_t, cfg->mac_addr[3]);\
769 + MC_CMD_OP(cmd, 0, 40, 8, uint8_t, cfg->mac_addr[2]);\
770 + MC_CMD_OP(cmd, 0, 48, 8, uint8_t, cfg->mac_addr[1]);\
771 + MC_CMD_OP(cmd, 0, 56, 8, uint8_t, cfg->mac_addr[0]);\
772 + MC_CMD_OP(cmd, 1, 0, 8, uint16_t, cfg->if_egress);\
773 + MC_CMD_OP(cmd, 1, 16, 4, enum dpsw_fdb_entry_type, cfg->type);\
774 +} while (0)
775 +
776 +/* cmd, param, offset, width, type, arg_name */
777 +#define DPSW_CMD_FDB_GET_UNICAST(cmd, fdb_id) \
778 +do { \
779 + MC_CMD_OP(cmd, 0, 0, 16, uint16_t, fdb_id);\
780 + MC_CMD_OP(cmd, 0, 16, 8, uint8_t, cfg->mac_addr[5]);\
781 + MC_CMD_OP(cmd, 0, 24, 8, uint8_t, cfg->mac_addr[4]);\
782 + MC_CMD_OP(cmd, 0, 32, 8, uint8_t, cfg->mac_addr[3]);\
783 + MC_CMD_OP(cmd, 0, 40, 8, uint8_t, cfg->mac_addr[2]);\
784 + MC_CMD_OP(cmd, 0, 48, 8, uint8_t, cfg->mac_addr[1]);\
785 + MC_CMD_OP(cmd, 0, 56, 8, uint8_t, cfg->mac_addr[0]);\
786 +} while (0)
787 +
788 +/* cmd, param, offset, width, type, arg_name */
789 +#define DPSW_RSP_FDB_GET_UNICAST(cmd, cfg) \
790 +do { \
791 + MC_RSP_OP(cmd, 1, 0, 16, uint16_t, cfg->if_egress);\
792 + MC_RSP_OP(cmd, 1, 16, 4, enum dpsw_fdb_entry_type, cfg->type);\
793 +} while (0)
794 +
795 +/* cmd, param, offset, width, type, arg_name */
796 +#define DPSW_CMD_FDB_REMOVE_UNICAST(cmd, fdb_id, cfg) \
797 +do { \
798 + MC_CMD_OP(cmd, 0, 0, 16, uint16_t, fdb_id);\
799 + MC_CMD_OP(cmd, 0, 16, 8, uint8_t, cfg->mac_addr[5]);\
800 + MC_CMD_OP(cmd, 0, 24, 8, uint8_t, cfg->mac_addr[4]);\
801 + MC_CMD_OP(cmd, 0, 32, 8, uint8_t, cfg->mac_addr[3]);\
802 + MC_CMD_OP(cmd, 0, 40, 8, uint8_t, cfg->mac_addr[2]);\
803 + MC_CMD_OP(cmd, 0, 48, 8, uint8_t, cfg->mac_addr[1]);\
804 + MC_CMD_OP(cmd, 0, 56, 8, uint8_t, cfg->mac_addr[0]);\
805 + MC_CMD_OP(cmd, 1, 0, 16, uint16_t, cfg->if_egress);\
806 + MC_CMD_OP(cmd, 1, 16, 4, enum dpsw_fdb_entry_type, cfg->type);\
807 +} while (0)
808 +
809 +/* cmd, param, offset, width, type, arg_name */
810 +#define DPSW_CMD_FDB_ADD_MULTICAST(cmd, fdb_id, cfg) \
811 +do { \
812 + MC_CMD_OP(cmd, 0, 0, 16, uint16_t, fdb_id);\
813 + MC_CMD_OP(cmd, 0, 16, 16, uint16_t, cfg->num_ifs);\
814 + MC_CMD_OP(cmd, 0, 32, 4, enum dpsw_fdb_entry_type, cfg->type);\
815 + MC_CMD_OP(cmd, 1, 0, 8, uint8_t, cfg->mac_addr[5]);\
816 + MC_CMD_OP(cmd, 1, 8, 8, uint8_t, cfg->mac_addr[4]);\
817 + MC_CMD_OP(cmd, 1, 16, 8, uint8_t, cfg->mac_addr[3]);\
818 + MC_CMD_OP(cmd, 1, 24, 8, uint8_t, cfg->mac_addr[2]);\
819 + MC_CMD_OP(cmd, 1, 32, 8, uint8_t, cfg->mac_addr[1]);\
820 + MC_CMD_OP(cmd, 1, 40, 8, uint8_t, cfg->mac_addr[0]);\
821 +} while (0)
822 +
823 +/* cmd, param, offset, width, type, arg_name */
824 +#define DPSW_CMD_FDB_GET_MULTICAST(cmd, fdb_id) \
825 +do { \
826 + MC_CMD_OP(cmd, 0, 0, 16, uint16_t, fdb_id);\
827 + MC_CMD_OP(cmd, 0, 16, 8, uint8_t, cfg->mac_addr[5]);\
828 + MC_CMD_OP(cmd, 0, 24, 8, uint8_t, cfg->mac_addr[4]);\
829 + MC_CMD_OP(cmd, 0, 32, 8, uint8_t, cfg->mac_addr[3]);\
830 + MC_CMD_OP(cmd, 0, 40, 8, uint8_t, cfg->mac_addr[2]);\
831 + MC_CMD_OP(cmd, 0, 48, 8, uint8_t, cfg->mac_addr[1]);\
832 + MC_CMD_OP(cmd, 0, 56, 8, uint8_t, cfg->mac_addr[0]);\
833 +} while (0)
834 +
835 +/* cmd, param, offset, width, type, arg_name */
836 +#define DPSW_RSP_FDB_GET_MULTICAST(cmd, cfg) \
837 +do { \
838 + MC_RSP_OP(cmd, 1, 0, 16, uint16_t, cfg->num_ifs);\
839 + MC_RSP_OP(cmd, 1, 16, 4, enum dpsw_fdb_entry_type, cfg->type);\
840 +} while (0)
841 +
842 +/* cmd, param, offset, width, type, arg_name */
843 +#define DPSW_CMD_FDB_REMOVE_MULTICAST(cmd, fdb_id, cfg) \
844 +do { \
845 + MC_CMD_OP(cmd, 0, 0, 16, uint16_t, fdb_id);\
846 + MC_CMD_OP(cmd, 0, 16, 16, uint16_t, cfg->num_ifs);\
847 + MC_CMD_OP(cmd, 0, 32, 4, enum dpsw_fdb_entry_type, cfg->type);\
848 + MC_CMD_OP(cmd, 1, 0, 8, uint8_t, cfg->mac_addr[5]);\
849 + MC_CMD_OP(cmd, 1, 8, 8, uint8_t, cfg->mac_addr[4]);\
850 + MC_CMD_OP(cmd, 1, 16, 8, uint8_t, cfg->mac_addr[3]);\
851 + MC_CMD_OP(cmd, 1, 24, 8, uint8_t, cfg->mac_addr[2]);\
852 + MC_CMD_OP(cmd, 1, 32, 8, uint8_t, cfg->mac_addr[1]);\
853 + MC_CMD_OP(cmd, 1, 40, 8, uint8_t, cfg->mac_addr[0]);\
854 +} while (0)
855 +
856 +/* cmd, param, offset, width, type, arg_name */
857 +#define DPSW_CMD_FDB_SET_LEARNING_MODE(cmd, fdb_id, mode) \
858 +do { \
859 + MC_CMD_OP(cmd, 0, 0, 16, uint16_t, fdb_id);\
860 + MC_CMD_OP(cmd, 0, 16, 4, enum dpsw_fdb_learning_mode, mode);\
861 +} while (0)
862 +
863 +/* cmd, param, offset, width, type, arg_name */
864 +#define DPSW_CMD_FDB_GET_ATTR(cmd, fdb_id) \
865 + MC_CMD_OP(cmd, 0, 0, 16, uint16_t, fdb_id)
866 +
867 +/* cmd, param, offset, width, type, arg_name */
868 +#define DPSW_RSP_FDB_GET_ATTR(cmd, attr) \
869 +do { \
870 + MC_RSP_OP(cmd, 0, 16, 16, uint16_t, attr->max_fdb_entries);\
871 + MC_RSP_OP(cmd, 0, 32, 16, uint16_t, attr->fdb_aging_time);\
872 + MC_RSP_OP(cmd, 0, 48, 16, uint16_t, attr->num_fdb_mc_groups);\
873 + MC_RSP_OP(cmd, 1, 0, 16, uint16_t, attr->max_fdb_mc_groups);\
874 + MC_RSP_OP(cmd, 1, 16, 4, enum dpsw_fdb_learning_mode, \
875 + attr->learning_mode);\
876 +} while (0)
877 +
878 +/* cmd, param, offset, width, type, arg_name */
879 +#define DPSW_CMD_ACL_ADD(cmd, cfg) \
880 + MC_CMD_OP(cmd, 0, 16, 16, uint16_t, cfg->max_entries)
881 +
882 +/* cmd, param, offset, width, type, arg_name */
883 +#define DPSW_RSP_ACL_ADD(cmd, acl_id) \
884 + MC_RSP_OP(cmd, 0, 0, 16, uint16_t, acl_id)
885 +
886 +/* cmd, param, offset, width, type, arg_name */
887 +#define DPSW_CMD_ACL_REMOVE(cmd, acl_id) \
888 + MC_CMD_OP(cmd, 0, 0, 16, uint16_t, acl_id)
889 +
890 +/* cmd, param, offset, width, type, arg_name */
891 +#define DPSW_PREP_ACL_ENTRY(ext, key) \
892 +do { \
893 + MC_PREP_OP(ext, 0, 0, 8, uint8_t, key->match.l2_dest_mac[5]);\
894 + MC_PREP_OP(ext, 0, 8, 8, uint8_t, key->match.l2_dest_mac[4]);\
895 + MC_PREP_OP(ext, 0, 16, 8, uint8_t, key->match.l2_dest_mac[3]);\
896 + MC_PREP_OP(ext, 0, 24, 8, uint8_t, key->match.l2_dest_mac[2]);\
897 + MC_PREP_OP(ext, 0, 32, 8, uint8_t, key->match.l2_dest_mac[1]);\
898 + MC_PREP_OP(ext, 0, 40, 8, uint8_t, key->match.l2_dest_mac[0]);\
899 + MC_PREP_OP(ext, 0, 48, 16, uint16_t, key->match.l2_tpid);\
900 + MC_PREP_OP(ext, 1, 0, 8, uint8_t, key->match.l2_source_mac[5]);\
901 + MC_PREP_OP(ext, 1, 8, 8, uint8_t, key->match.l2_source_mac[4]);\
902 + MC_PREP_OP(ext, 1, 16, 8, uint8_t, key->match.l2_source_mac[3]);\
903 + MC_PREP_OP(ext, 1, 24, 8, uint8_t, key->match.l2_source_mac[2]);\
904 + MC_PREP_OP(ext, 1, 32, 8, uint8_t, key->match.l2_source_mac[1]);\
905 + MC_PREP_OP(ext, 1, 40, 8, uint8_t, key->match.l2_source_mac[0]);\
906 + MC_PREP_OP(ext, 1, 48, 16, uint16_t, key->match.l2_vlan_id);\
907 + MC_PREP_OP(ext, 2, 0, 32, uint32_t, key->match.l3_dest_ip);\
908 + MC_PREP_OP(ext, 2, 32, 32, uint32_t, key->match.l3_source_ip);\
909 + MC_PREP_OP(ext, 3, 0, 16, uint16_t, key->match.l4_dest_port);\
910 + MC_PREP_OP(ext, 3, 16, 16, uint16_t, key->match.l4_source_port);\
911 + MC_PREP_OP(ext, 3, 32, 16, uint16_t, key->match.l2_ether_type);\
912 + MC_PREP_OP(ext, 3, 48, 8, uint8_t, key->match.l2_pcp_dei);\
913 + MC_PREP_OP(ext, 3, 56, 8, uint8_t, key->match.l3_dscp);\
914 + MC_PREP_OP(ext, 4, 0, 8, uint8_t, key->mask.l2_dest_mac[5]);\
915 + MC_PREP_OP(ext, 4, 8, 8, uint8_t, key->mask.l2_dest_mac[4]);\
916 + MC_PREP_OP(ext, 4, 16, 8, uint8_t, key->mask.l2_dest_mac[3]);\
917 + MC_PREP_OP(ext, 4, 24, 8, uint8_t, key->mask.l2_dest_mac[2]);\
918 + MC_PREP_OP(ext, 4, 32, 8, uint8_t, key->mask.l2_dest_mac[1]);\
919 + MC_PREP_OP(ext, 4, 40, 8, uint8_t, key->mask.l2_dest_mac[0]);\
920 + MC_PREP_OP(ext, 4, 48, 16, uint16_t, key->mask.l2_tpid);\
921 + MC_PREP_OP(ext, 5, 0, 8, uint8_t, key->mask.l2_source_mac[5]);\
922 + MC_PREP_OP(ext, 5, 8, 8, uint8_t, key->mask.l2_source_mac[4]);\
923 + MC_PREP_OP(ext, 5, 16, 8, uint8_t, key->mask.l2_source_mac[3]);\
924 + MC_PREP_OP(ext, 5, 24, 8, uint8_t, key->mask.l2_source_mac[2]);\
925 + MC_PREP_OP(ext, 5, 32, 8, uint8_t, key->mask.l2_source_mac[1]);\
926 + MC_PREP_OP(ext, 5, 40, 8, uint8_t, key->mask.l2_source_mac[0]);\
927 + MC_PREP_OP(ext, 5, 48, 16, uint16_t, key->mask.l2_vlan_id);\
928 + MC_PREP_OP(ext, 6, 0, 32, uint32_t, key->mask.l3_dest_ip);\
929 + MC_PREP_OP(ext, 6, 32, 32, uint32_t, key->mask.l3_source_ip);\
930 + MC_PREP_OP(ext, 7, 0, 16, uint16_t, key->mask.l4_dest_port);\
931 + MC_PREP_OP(ext, 7, 16, 16, uint16_t, key->mask.l4_source_port);\
932 + MC_PREP_OP(ext, 7, 32, 16, uint16_t, key->mask.l2_ether_type);\
933 + MC_PREP_OP(ext, 7, 48, 8, uint8_t, key->mask.l2_pcp_dei);\
934 + MC_PREP_OP(ext, 7, 56, 8, uint8_t, key->mask.l3_dscp);\
935 + MC_PREP_OP(ext, 8, 0, 8, uint8_t, key->match.l3_protocol);\
936 + MC_PREP_OP(ext, 8, 8, 8, uint8_t, key->mask.l3_protocol);\
937 +} while (0)
938 +
939 +/* cmd, param, offset, width, type, arg_name */
940 +#define DPSW_EXT_ACL_ENTRY(ext, key) \
941 +do { \
942 + MC_EXT_OP(ext, 0, 0, 8, uint8_t, key->match.l2_dest_mac[5]);\
943 + MC_EXT_OP(ext, 0, 8, 8, uint8_t, key->match.l2_dest_mac[4]);\
944 + MC_EXT_OP(ext, 0, 16, 8, uint8_t, key->match.l2_dest_mac[3]);\
945 + MC_EXT_OP(ext, 0, 24, 8, uint8_t, key->match.l2_dest_mac[2]);\
946 + MC_EXT_OP(ext, 0, 32, 8, uint8_t, key->match.l2_dest_mac[1]);\
947 + MC_EXT_OP(ext, 0, 40, 8, uint8_t, key->match.l2_dest_mac[0]);\
948 + MC_EXT_OP(ext, 0, 48, 16, uint16_t, key->match.l2_tpid);\
949 + MC_EXT_OP(ext, 1, 0, 8, uint8_t, key->match.l2_source_mac[5]);\
950 + MC_EXT_OP(ext, 1, 8, 8, uint8_t, key->match.l2_source_mac[4]);\
951 + MC_EXT_OP(ext, 1, 16, 8, uint8_t, key->match.l2_source_mac[3]);\
952 + MC_EXT_OP(ext, 1, 24, 8, uint8_t, key->match.l2_source_mac[2]);\
953 + MC_EXT_OP(ext, 1, 32, 8, uint8_t, key->match.l2_source_mac[1]);\
954 + MC_EXT_OP(ext, 1, 40, 8, uint8_t, key->match.l2_source_mac[0]);\
955 + MC_EXT_OP(ext, 1, 48, 16, uint16_t, key->match.l2_vlan_id);\
956 + MC_EXT_OP(ext, 2, 0, 32, uint32_t, key->match.l3_dest_ip);\
957 + MC_EXT_OP(ext, 2, 32, 32, uint32_t, key->match.l3_source_ip);\
958 + MC_EXT_OP(ext, 3, 0, 16, uint16_t, key->match.l4_dest_port);\
959 + MC_EXT_OP(ext, 3, 16, 16, uint16_t, key->match.l4_source_port);\
960 + MC_EXT_OP(ext, 3, 32, 16, uint16_t, key->match.l2_ether_type);\
961 + MC_EXT_OP(ext, 3, 48, 8, uint8_t, key->match.l2_pcp_dei);\
962 + MC_EXT_OP(ext, 3, 56, 8, uint8_t, key->match.l3_dscp);\
963 + MC_EXT_OP(ext, 4, 0, 8, uint8_t, key->mask.l2_dest_mac[5]);\
964 + MC_EXT_OP(ext, 4, 8, 8, uint8_t, key->mask.l2_dest_mac[4]);\
965 + MC_EXT_OP(ext, 4, 16, 8, uint8_t, key->mask.l2_dest_mac[3]);\
966 + MC_EXT_OP(ext, 4, 24, 8, uint8_t, key->mask.l2_dest_mac[2]);\
967 + MC_EXT_OP(ext, 4, 32, 8, uint8_t, key->mask.l2_dest_mac[1]);\
968 + MC_EXT_OP(ext, 4, 40, 8, uint8_t, key->mask.l2_dest_mac[0]);\
969 + MC_EXT_OP(ext, 4, 48, 16, uint16_t, key->mask.l2_tpid);\
970 + MC_EXT_OP(ext, 5, 0, 8, uint8_t, key->mask.l2_source_mac[5]);\
971 + MC_EXT_OP(ext, 5, 8, 8, uint8_t, key->mask.l2_source_mac[4]);\
972 + MC_EXT_OP(ext, 5, 16, 8, uint8_t, key->mask.l2_source_mac[3]);\
973 + MC_EXT_OP(ext, 5, 24, 8, uint8_t, key->mask.l2_source_mac[2]);\
974 + MC_EXT_OP(ext, 5, 32, 8, uint8_t, key->mask.l2_source_mac[1]);\
975 + MC_EXT_OP(ext, 5, 40, 8, uint8_t, key->mask.l2_source_mac[0]);\
976 + MC_EXT_OP(ext, 5, 48, 16, uint16_t, key->mask.l2_vlan_id);\
977 + MC_EXT_OP(ext, 6, 0, 32, uint32_t, key->mask.l3_dest_ip);\
978 + MC_EXT_OP(ext, 6, 32, 32, uint32_t, key->mask.l3_source_ip);\
979 + MC_EXT_OP(ext, 7, 0, 16, uint16_t, key->mask.l4_dest_port);\
980 + MC_EXT_OP(ext, 7, 16, 16, uint16_t, key->mask.l4_source_port);\
981 + MC_EXT_OP(ext, 7, 32, 16, uint16_t, key->mask.l2_ether_type);\
982 + MC_EXT_OP(ext, 7, 48, 8, uint8_t, key->mask.l2_pcp_dei);\
983 + MC_EXT_OP(ext, 7, 56, 8, uint8_t, key->mask.l3_dscp);\
984 + MC_EXT_OP(ext, 8, 0, 8, uint8_t, key->match.l3_protocol);\
985 + MC_EXT_OP(ext, 8, 8, 8, uint8_t, key->mask.l3_protocol);\
986 +} while (0)
987 +
988 +/* cmd, param, offset, width, type, arg_name */
989 +#define DPSW_CMD_ACL_ADD_ENTRY(cmd, acl_id, cfg) \
990 +do { \
991 + MC_CMD_OP(cmd, 0, 0, 16, uint16_t, acl_id);\
992 + MC_CMD_OP(cmd, 0, 16, 16, uint16_t, cfg->result.if_id);\
993 + MC_CMD_OP(cmd, 0, 32, 32, int, cfg->precedence);\
994 + MC_CMD_OP(cmd, 1, 0, 4, enum dpsw_acl_action, cfg->result.action);\
995 + MC_CMD_OP(cmd, 6, 0, 64, uint64_t, cfg->key_iova); \
996 +} while (0)
997 +
998 +/* cmd, param, offset, width, type, arg_name */
999 +#define DPSW_CMD_ACL_REMOVE_ENTRY(cmd, acl_id, cfg) \
1000 +do { \
1001 + MC_CMD_OP(cmd, 0, 0, 16, uint16_t, acl_id);\
1002 + MC_CMD_OP(cmd, 0, 16, 16, uint16_t, cfg->result.if_id);\
1003 + MC_CMD_OP(cmd, 0, 32, 32, int, cfg->precedence);\
1004 + MC_CMD_OP(cmd, 1, 0, 4, enum dpsw_acl_action, cfg->result.action);\
1005 + MC_CMD_OP(cmd, 6, 0, 64, uint64_t, cfg->key_iova); \
1006 +} while (0)
1007 +
1008 +/* cmd, param, offset, width, type, arg_name */
1009 +#define DPSW_CMD_ACL_ADD_IF(cmd, acl_id, cfg) \
1010 +do { \
1011 + MC_CMD_OP(cmd, 0, 0, 16, uint16_t, acl_id);\
1012 + MC_CMD_OP(cmd, 0, 16, 16, uint16_t, cfg->num_ifs); \
1013 +} while (0)
1014 +
1015 +/* cmd, param, offset, width, type, arg_name */
1016 +#define DPSW_CMD_ACL_REMOVE_IF(cmd, acl_id, cfg) \
1017 +do { \
1018 + MC_CMD_OP(cmd, 0, 0, 16, uint16_t, acl_id);\
1019 + MC_CMD_OP(cmd, 0, 16, 16, uint16_t, cfg->num_ifs); \
1020 +} while (0)
1021 +
1022 +/* cmd, param, offset, width, type, arg_name */
1023 +#define DPSW_CMD_ACL_GET_ATTR(cmd, acl_id) \
1024 + MC_CMD_OP(cmd, 0, 0, 16, uint16_t, acl_id)
1025 +
1026 +/* cmd, param, offset, width, type, arg_name */
1027 +#define DPSW_RSP_ACL_GET_ATTR(cmd, attr) \
1028 +do { \
1029 + MC_RSP_OP(cmd, 1, 0, 16, uint16_t, attr->max_entries);\
1030 + MC_RSP_OP(cmd, 1, 16, 16, uint16_t, attr->num_entries);\
1031 + MC_RSP_OP(cmd, 1, 32, 16, uint16_t, attr->num_ifs);\
1032 +} while (0)
1033 +
1034 +/* cmd, param, offset, width, type, arg_name */
1035 +#define DPSW_RSP_CTRL_IF_GET_ATTR(cmd, attr) \
1036 +do { \
1037 + MC_RSP_OP(cmd, 1, 0, 32, uint32_t, attr->rx_fqid);\
1038 + MC_RSP_OP(cmd, 1, 32, 32, uint32_t, attr->rx_err_fqid);\
1039 + MC_RSP_OP(cmd, 2, 0, 32, uint32_t, attr->tx_err_conf_fqid);\
1040 +} while (0)
1041 +
1042 +/* cmd, param, offset, width, type, arg_name */
1043 +#define DPSW_CMD_CTRL_IF_SET_POOLS(cmd, cfg) \
1044 +do { \
1045 + MC_CMD_OP(cmd, 0, 0, 8, uint8_t, cfg->num_dpbp); \
1046 + MC_CMD_OP(cmd, 0, 8, 1, int, cfg->pools[0].backup_pool); \
1047 + MC_CMD_OP(cmd, 0, 9, 1, int, cfg->pools[1].backup_pool); \
1048 + MC_CMD_OP(cmd, 0, 10, 1, int, cfg->pools[2].backup_pool); \
1049 + MC_CMD_OP(cmd, 0, 11, 1, int, cfg->pools[3].backup_pool); \
1050 + MC_CMD_OP(cmd, 0, 12, 1, int, cfg->pools[4].backup_pool); \
1051 + MC_CMD_OP(cmd, 0, 13, 1, int, cfg->pools[5].backup_pool); \
1052 + MC_CMD_OP(cmd, 0, 14, 1, int, cfg->pools[6].backup_pool); \
1053 + MC_CMD_OP(cmd, 0, 15, 1, int, cfg->pools[7].backup_pool); \
1054 + MC_CMD_OP(cmd, 0, 32, 32, int, cfg->pools[0].dpbp_id); \
1055 + MC_CMD_OP(cmd, 4, 32, 16, uint16_t, cfg->pools[0].buffer_size);\
1056 + MC_CMD_OP(cmd, 1, 0, 32, int, cfg->pools[1].dpbp_id); \
1057 + MC_CMD_OP(cmd, 4, 48, 16, uint16_t, cfg->pools[1].buffer_size);\
1058 + MC_CMD_OP(cmd, 1, 32, 32, int, cfg->pools[2].dpbp_id); \
1059 + MC_CMD_OP(cmd, 5, 0, 16, uint16_t, cfg->pools[2].buffer_size);\
1060 + MC_CMD_OP(cmd, 2, 0, 32, int, cfg->pools[3].dpbp_id); \
1061 + MC_CMD_OP(cmd, 5, 16, 16, uint16_t, cfg->pools[3].buffer_size);\
1062 + MC_CMD_OP(cmd, 2, 32, 32, int, cfg->pools[4].dpbp_id); \
1063 + MC_CMD_OP(cmd, 5, 32, 16, uint16_t, cfg->pools[4].buffer_size);\
1064 + MC_CMD_OP(cmd, 3, 0, 32, int, cfg->pools[5].dpbp_id); \
1065 + MC_CMD_OP(cmd, 5, 48, 16, uint16_t, cfg->pools[5].buffer_size);\
1066 + MC_CMD_OP(cmd, 3, 32, 32, int, cfg->pools[6].dpbp_id); \
1067 + MC_CMD_OP(cmd, 6, 0, 16, uint16_t, cfg->pools[6].buffer_size);\
1068 + MC_CMD_OP(cmd, 4, 0, 32, int, cfg->pools[7].dpbp_id); \
1069 + MC_CMD_OP(cmd, 6, 16, 16, uint16_t, cfg->pools[7].buffer_size);\
1070 +} while (0)
1071 +
1072 +#endif /* __FSL_DPSW_CMD_H */
1073 --- /dev/null
1074 +++ b/drivers/staging/fsl-dpaa2/ethsw/dpsw.c
1075 @@ -0,0 +1,1639 @@
1076 +/* Copyright 2013-2015 Freescale Semiconductor Inc.
1077 + *
1078 + * Redistribution and use in source and binary forms, with or without
1079 + * modification, are permitted provided that the following conditions are met:
1080 + * * Redistributions of source code must retain the above copyright
1081 + * notice, this list of conditions and the following disclaimer.
1082 + * * Redistributions in binary form must reproduce the above copyright
1083 + * notice, this list of conditions and the following disclaimer in the
1084 + * documentation and/or other materials provided with the distribution.
1085 + * * Neither the name of the above-listed copyright holders nor the
1086 + * names of any contributors may be used to endorse or promote products
1087 + * derived from this software without specific prior written permission.
1088 + *
1089 + *
1090 + * ALTERNATIVELY, this software may be distributed under the terms of the
1091 + * GNU General Public License ("GPL") as published by the Free Software
1092 + * Foundation, either version 2 of that License or (at your option) any
1093 + * later version.
1094 + *
1095 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
1096 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1097 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1098 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
1099 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
1100 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
1101 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
1102 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
1103 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
1104 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
1105 + * POSSIBILITY OF SUCH DAMAGE.
1106 + */
1107 +#include "../../fsl-mc/include/mc-sys.h"
1108 +#include "../../fsl-mc/include/mc-cmd.h"
1109 +#include "dpsw.h"
1110 +#include "dpsw-cmd.h"
1111 +
1112 +/* internal functions */
1113 +static void build_if_id_bitmap(const uint16_t *if_id,
1114 + const uint16_t num_ifs,
1115 + struct mc_command *cmd,
1116 + int start_param)
1117 +{
1118 + int i;
1119 +
1120 + for (i = 0; (i < num_ifs) && (i < DPSW_MAX_IF); i++)
1121 + cmd->params[start_param + (if_id[i] / 64)] |= mc_enc(
1122 + (if_id[i] % 64), 1, 1);
1123 +}
1124 +
1125 +static int read_if_id_bitmap(uint16_t *if_id,
1126 + uint16_t *num_ifs,
1127 + struct mc_command *cmd,
1128 + int start_param)
1129 +{
1130 + int bitmap[DPSW_MAX_IF] = { 0 };
1131 + int i, j = 0;
1132 + int count = 0;
1133 +
1134 + for (i = 0; i < DPSW_MAX_IF; i++) {
1135 + bitmap[i] = (int)mc_dec(cmd->params[start_param + i / 64],
1136 + i % 64, 1);
1137 + count += bitmap[i];
1138 + }
1139 +
1140 + *num_ifs = (uint16_t)count;
1141 +
1142 + for (i = 0; (i < DPSW_MAX_IF) && (j < count); i++) {
1143 + if (bitmap[i]) {
1144 + if_id[j] = (uint16_t)i;
1145 + j++;
1146 + }
1147 + }
1148 +
1149 + return 0;
1150 +}
1151 +
1152 +/* DPSW APIs */
1153 +int dpsw_open(struct fsl_mc_io *mc_io,
1154 + uint32_t cmd_flags,
1155 + int dpsw_id,
1156 + uint16_t *token)
1157 +{
1158 + struct mc_command cmd = { 0 };
1159 + int err;
1160 +
1161 + /* prepare command */
1162 + cmd.header = mc_encode_cmd_header(DPSW_CMDID_OPEN,
1163 + cmd_flags,
1164 + 0);
1165 + DPSW_CMD_OPEN(cmd, dpsw_id);
1166 +
1167 + /* send command to mc*/
1168 + err = mc_send_command(mc_io, &cmd);
1169 + if (err)
1170 + return err;
1171 +
1172 + /* retrieve response parameters */
1173 + *token = MC_CMD_HDR_READ_TOKEN(cmd.header);
1174 +
1175 + return 0;
1176 +}
1177 +
1178 +int dpsw_close(struct fsl_mc_io *mc_io,
1179 + uint32_t cmd_flags,
1180 + uint16_t token)
1181 +{
1182 + struct mc_command cmd = { 0 };
1183 +
1184 + /* prepare command */
1185 + cmd.header = mc_encode_cmd_header(DPSW_CMDID_CLOSE,
1186 + cmd_flags,
1187 + token);
1188 +
1189 + /* send command to mc*/
1190 + return mc_send_command(mc_io, &cmd);
1191 +}
1192 +
1193 +int dpsw_create(struct fsl_mc_io *mc_io,
1194 + uint32_t cmd_flags,
1195 + const struct dpsw_cfg *cfg,
1196 + uint16_t *token)
1197 +{
1198 + struct mc_command cmd = { 0 };
1199 + int err;
1200 +
1201 + /* prepare command */
1202 + cmd.header = mc_encode_cmd_header(DPSW_CMDID_CREATE,
1203 + cmd_flags,
1204 + 0);
1205 + DPSW_CMD_CREATE(cmd, cfg);
1206 +
1207 + /* send command to mc*/
1208 + err = mc_send_command(mc_io, &cmd);
1209 + if (err)
1210 + return err;
1211 +
1212 + /* retrieve response parameters */
1213 + *token = MC_CMD_HDR_READ_TOKEN(cmd.header);
1214 +
1215 + return 0;
1216 +}
1217 +
1218 +int dpsw_destroy(struct fsl_mc_io *mc_io,
1219 + uint32_t cmd_flags,
1220 + uint16_t token)
1221 +{
1222 + struct mc_command cmd = { 0 };
1223 +
1224 + /* prepare command */
1225 + cmd.header = mc_encode_cmd_header(DPSW_CMDID_DESTROY,
1226 + cmd_flags,
1227 + token);
1228 +
1229 + /* send command to mc*/
1230 + return mc_send_command(mc_io, &cmd);
1231 +}
1232 +
1233 +int dpsw_enable(struct fsl_mc_io *mc_io,
1234 + uint32_t cmd_flags,
1235 + uint16_t token)
1236 +{
1237 + struct mc_command cmd = { 0 };
1238 +
1239 + /* prepare command */
1240 + cmd.header = mc_encode_cmd_header(DPSW_CMDID_ENABLE,
1241 + cmd_flags,
1242 + token);
1243 +
1244 + /* send command to mc*/
1245 + return mc_send_command(mc_io, &cmd);
1246 +}
1247 +
1248 +int dpsw_disable(struct fsl_mc_io *mc_io,
1249 + uint32_t cmd_flags,
1250 + uint16_t token)
1251 +{
1252 + struct mc_command cmd = { 0 };
1253 +
1254 + /* prepare command */
1255 + cmd.header = mc_encode_cmd_header(DPSW_CMDID_DISABLE,
1256 + cmd_flags,
1257 + token);
1258 +
1259 + /* send command to mc*/
1260 + return mc_send_command(mc_io, &cmd);
1261 +}
1262 +
1263 +int dpsw_is_enabled(struct fsl_mc_io *mc_io,
1264 + uint32_t cmd_flags,
1265 + uint16_t token,
1266 + int *en)
1267 +{
1268 + struct mc_command cmd = { 0 };
1269 + int err;
1270 +
1271 + /* prepare command */
1272 + cmd.header = mc_encode_cmd_header(DPSW_CMDID_IS_ENABLED, cmd_flags,
1273 + token);
1274 +
1275 + /* send command to mc*/
1276 + err = mc_send_command(mc_io, &cmd);
1277 + if (err)
1278 + return err;
1279 +
1280 + /* retrieve response parameters */
1281 + DPSW_RSP_IS_ENABLED(cmd, *en);
1282 +
1283 + return 0;
1284 +}
1285 +
1286 +int dpsw_reset(struct fsl_mc_io *mc_io,
1287 + uint32_t cmd_flags,
1288 + uint16_t token)
1289 +{
1290 + struct mc_command cmd = { 0 };
1291 +
1292 + /* prepare command */
1293 + cmd.header = mc_encode_cmd_header(DPSW_CMDID_RESET,
1294 + cmd_flags,
1295 + token);
1296 +
1297 + /* send command to mc*/
1298 + return mc_send_command(mc_io, &cmd);
1299 +}
1300 +
1301 +int dpsw_set_irq(struct fsl_mc_io *mc_io,
1302 + uint32_t cmd_flags,
1303 + uint16_t token,
1304 + uint8_t irq_index,
1305 + struct dpsw_irq_cfg *irq_cfg)
1306 +{
1307 + struct mc_command cmd = { 0 };
1308 +
1309 + /* prepare command */
1310 + cmd.header = mc_encode_cmd_header(DPSW_CMDID_SET_IRQ,
1311 + cmd_flags,
1312 + token);
1313 + DPSW_CMD_SET_IRQ(cmd, irq_index, irq_cfg);
1314 +
1315 + /* send command to mc*/
1316 + return mc_send_command(mc_io, &cmd);
1317 +}
1318 +
1319 +int dpsw_get_irq(struct fsl_mc_io *mc_io,
1320 + uint32_t cmd_flags,
1321 + uint16_t token,
1322 + uint8_t irq_index,
1323 + int *type,
1324 + struct dpsw_irq_cfg *irq_cfg)
1325 +{
1326 + struct mc_command cmd = { 0 };
1327 + int err;
1328 +
1329 + /* prepare command */
1330 + cmd.header = mc_encode_cmd_header(DPSW_CMDID_GET_IRQ,
1331 + cmd_flags,
1332 + token);
1333 + DPSW_CMD_GET_IRQ(cmd, irq_index);
1334 +
1335 + /* send command to mc*/
1336 + err = mc_send_command(mc_io, &cmd);
1337 + if (err)
1338 + return err;
1339 +
1340 + /* retrieve response parameters */
1341 + DPSW_RSP_GET_IRQ(cmd, *type, irq_cfg);
1342 +
1343 + return 0;
1344 +}
1345 +
1346 +int dpsw_set_irq_enable(struct fsl_mc_io *mc_io,
1347 + uint32_t cmd_flags,
1348 + uint16_t token,
1349 + uint8_t irq_index,
1350 + uint8_t en)
1351 +{
1352 + struct mc_command cmd = { 0 };
1353 +
1354 + /* prepare command */
1355 + cmd.header = mc_encode_cmd_header(DPSW_CMDID_SET_IRQ_ENABLE,
1356 + cmd_flags,
1357 + token);
1358 + DPSW_CMD_SET_IRQ_ENABLE(cmd, irq_index, en);
1359 +
1360 + /* send command to mc*/
1361 + return mc_send_command(mc_io, &cmd);
1362 +}
1363 +
1364 +int dpsw_get_irq_enable(struct fsl_mc_io *mc_io,
1365 + uint32_t cmd_flags,
1366 + uint16_t token,
1367 + uint8_t irq_index,
1368 + uint8_t *en)
1369 +{
1370 + struct mc_command cmd = { 0 };
1371 + int err;
1372 +
1373 + /* prepare command */
1374 + cmd.header = mc_encode_cmd_header(DPSW_CMDID_GET_IRQ_ENABLE,
1375 + cmd_flags,
1376 + token);
1377 + DPSW_CMD_GET_IRQ_ENABLE(cmd, irq_index);
1378 +
1379 + /* send command to mc*/
1380 + err = mc_send_command(mc_io, &cmd);
1381 + if (err)
1382 + return err;
1383 +
1384 + /* retrieve response parameters */
1385 + DPSW_RSP_GET_IRQ_ENABLE(cmd, *en);
1386 +
1387 + return 0;
1388 +}
1389 +
1390 +int dpsw_set_irq_mask(struct fsl_mc_io *mc_io,
1391 + uint32_t cmd_flags,
1392 + uint16_t token,
1393 + uint8_t irq_index,
1394 + uint32_t mask)
1395 +{
1396 + struct mc_command cmd = { 0 };
1397 +
1398 + /* prepare command */
1399 + cmd.header = mc_encode_cmd_header(DPSW_CMDID_SET_IRQ_MASK,
1400 + cmd_flags,
1401 + token);
1402 + DPSW_CMD_SET_IRQ_MASK(cmd, irq_index, mask);
1403 +
1404 + /* send command to mc*/
1405 + return mc_send_command(mc_io, &cmd);
1406 +}
1407 +
1408 +int dpsw_get_irq_mask(struct fsl_mc_io *mc_io,
1409 + uint32_t cmd_flags,
1410 + uint16_t token,
1411 + uint8_t irq_index,
1412 + uint32_t *mask)
1413 +{
1414 + struct mc_command cmd = { 0 };
1415 + int err;
1416 +
1417 + /* prepare command */
1418 + cmd.header = mc_encode_cmd_header(DPSW_CMDID_GET_IRQ_MASK,
1419 + cmd_flags,
1420 + token);
1421 + DPSW_CMD_GET_IRQ_MASK(cmd, irq_index);
1422 +
1423 + /* send command to mc*/
1424 + err = mc_send_command(mc_io, &cmd);
1425 + if (err)
1426 + return err;
1427 +
1428 + /* retrieve response parameters */
1429 + DPSW_RSP_GET_IRQ_MASK(cmd, *mask);
1430 +
1431 + return 0;
1432 +}
1433 +
1434 +int dpsw_get_irq_status(struct fsl_mc_io *mc_io,
1435 + uint32_t cmd_flags,
1436 + uint16_t token,
1437 + uint8_t irq_index,
1438 + uint32_t *status)
1439 +{
1440 + struct mc_command cmd = { 0 };
1441 + int err;
1442 +
1443 + /* prepare command */
1444 + cmd.header = mc_encode_cmd_header(DPSW_CMDID_GET_IRQ_STATUS,
1445 + cmd_flags,
1446 + token);
1447 + DPSW_CMD_GET_IRQ_STATUS(cmd, irq_index, *status);
1448 +
1449 + /* send command to mc*/
1450 + err = mc_send_command(mc_io, &cmd);
1451 + if (err)
1452 + return err;
1453 +
1454 + /* retrieve response parameters */
1455 + DPSW_RSP_GET_IRQ_STATUS(cmd, *status);
1456 +
1457 + return 0;
1458 +}
1459 +
1460 +int dpsw_clear_irq_status(struct fsl_mc_io *mc_io,
1461 + uint32_t cmd_flags,
1462 + uint16_t token,
1463 + uint8_t irq_index,
1464 + uint32_t status)
1465 +{
1466 + struct mc_command cmd = { 0 };
1467 +
1468 + /* prepare command */
1469 + cmd.header = mc_encode_cmd_header(DPSW_CMDID_CLEAR_IRQ_STATUS,
1470 + cmd_flags,
1471 + token);
1472 + DPSW_CMD_CLEAR_IRQ_STATUS(cmd, irq_index, status);
1473 +
1474 + /* send command to mc*/
1475 + return mc_send_command(mc_io, &cmd);
1476 +}
1477 +
1478 +int dpsw_get_attributes(struct fsl_mc_io *mc_io,
1479 + uint32_t cmd_flags,
1480 + uint16_t token,
1481 + struct dpsw_attr *attr)
1482 +{
1483 + struct mc_command cmd = { 0 };
1484 + int err;
1485 +
1486 + /* prepare command */
1487 + cmd.header = mc_encode_cmd_header(DPSW_CMDID_GET_ATTR,
1488 + cmd_flags,
1489 + token);
1490 +
1491 + /* send command to mc*/
1492 + err = mc_send_command(mc_io, &cmd);
1493 + if (err)
1494 + return err;
1495 +
1496 + /* retrieve response parameters */
1497 + DPSW_RSP_GET_ATTR(cmd, attr);
1498 +
1499 + return 0;
1500 +}
1501 +
1502 +int dpsw_set_reflection_if(struct fsl_mc_io *mc_io,
1503 + uint32_t cmd_flags,
1504 + uint16_t token,
1505 + uint16_t if_id)
1506 +{
1507 + struct mc_command cmd = { 0 };
1508 +
1509 + /* prepare command */
1510 + cmd.header = mc_encode_cmd_header(DPSW_CMDID_SET_REFLECTION_IF,
1511 + cmd_flags,
1512 + token);
1513 + DPSW_CMD_SET_REFLECTION_IF(cmd, if_id);
1514 +
1515 + /* send command to mc*/
1516 + return mc_send_command(mc_io, &cmd);
1517 +}
1518 +
1519 +int dpsw_if_set_link_cfg(struct fsl_mc_io *mc_io,
1520 + uint32_t cmd_flags,
1521 + uint16_t token,
1522 + uint16_t if_id,
1523 + struct dpsw_link_cfg *cfg)
1524 +{
1525 + struct mc_command cmd = { 0 };
1526 +
1527 + /* prepare command */
1528 + cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_SET_LINK_CFG,
1529 + cmd_flags,
1530 + token);
1531 + DPSW_CMD_IF_SET_LINK_CFG(cmd, if_id, cfg);
1532 +
1533 + /* send command to mc*/
1534 + return mc_send_command(mc_io, &cmd);
1535 +}
1536 +
1537 +int dpsw_if_get_link_state(struct fsl_mc_io *mc_io,
1538 + uint32_t cmd_flags,
1539 + uint16_t token,
1540 + uint16_t if_id,
1541 + struct dpsw_link_state *state)
1542 +{
1543 + struct mc_command cmd = { 0 };
1544 + int err;
1545 +
1546 + /* prepare command */
1547 + cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_GET_LINK_STATE,
1548 + cmd_flags,
1549 + token);
1550 + DPSW_CMD_IF_GET_LINK_STATE(cmd, if_id);
1551 +
1552 + /* send command to mc*/
1553 + err = mc_send_command(mc_io, &cmd);
1554 + if (err)
1555 + return err;
1556 +
1557 + /* retrieve response parameters */
1558 + DPSW_RSP_IF_GET_LINK_STATE(cmd, state);
1559 +
1560 + return 0;
1561 +}
1562 +
1563 +int dpsw_if_set_flooding(struct fsl_mc_io *mc_io,
1564 + uint32_t cmd_flags,
1565 + uint16_t token,
1566 + uint16_t if_id,
1567 + int en)
1568 +{
1569 + struct mc_command cmd = { 0 };
1570 +
1571 + /* prepare command */
1572 + cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_SET_FLOODING,
1573 + cmd_flags,
1574 + token);
1575 + DPSW_CMD_IF_SET_FLOODING(cmd, if_id, en);
1576 +
1577 + /* send command to mc*/
1578 + return mc_send_command(mc_io, &cmd);
1579 +}
1580 +
1581 +int dpsw_if_set_broadcast(struct fsl_mc_io *mc_io,
1582 + uint32_t cmd_flags,
1583 + uint16_t token,
1584 + uint16_t if_id,
1585 + int en)
1586 +{
1587 + struct mc_command cmd = { 0 };
1588 +
1589 + /* prepare command */
1590 + cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_SET_BROADCAST,
1591 + cmd_flags,
1592 + token);
1593 + DPSW_CMD_IF_SET_FLOODING(cmd, if_id, en);
1594 +
1595 + /* send command to mc*/
1596 + return mc_send_command(mc_io, &cmd);
1597 +}
1598 +
1599 +int dpsw_if_set_multicast(struct fsl_mc_io *mc_io,
1600 + uint32_t cmd_flags,
1601 + uint16_t token,
1602 + uint16_t if_id,
1603 + int en)
1604 +{
1605 + struct mc_command cmd = { 0 };
1606 +
1607 + /* prepare command */
1608 + cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_SET_MULTICAST,
1609 + cmd_flags,
1610 + token);
1611 + DPSW_CMD_IF_SET_FLOODING(cmd, if_id, en);
1612 +
1613 + /* send command to mc*/
1614 + return mc_send_command(mc_io, &cmd);
1615 +}
1616 +
1617 +int dpsw_if_set_tci(struct fsl_mc_io *mc_io,
1618 + uint32_t cmd_flags,
1619 + uint16_t token,
1620 + uint16_t if_id,
1621 + const struct dpsw_tci_cfg *cfg)
1622 +{
1623 + struct mc_command cmd = { 0 };
1624 +
1625 + /* prepare command */
1626 + cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_SET_TCI,
1627 + cmd_flags,
1628 + token);
1629 + DPSW_CMD_IF_SET_TCI(cmd, if_id, cfg);
1630 +
1631 + /* send command to mc*/
1632 + return mc_send_command(mc_io, &cmd);
1633 +}
1634 +
1635 +int dpsw_if_get_tci(struct fsl_mc_io *mc_io,
1636 + uint32_t cmd_flags,
1637 + uint16_t token,
1638 + uint16_t if_id,
1639 + struct dpsw_tci_cfg *cfg)
1640 +{
1641 + struct mc_command cmd = { 0 };
1642 + int err = 0;
1643 +
1644 + /* prepare command */
1645 + cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_GET_TCI,
1646 + cmd_flags,
1647 + token);
1648 + DPSW_CMD_IF_GET_TCI(cmd, if_id);
1649 +
1650 + /* send command to mc*/
1651 + err = mc_send_command(mc_io, &cmd);
1652 + if (err)
1653 + return err;
1654 +
1655 + /* retrieve response parameters */
1656 + DPSW_RSP_IF_GET_TCI(cmd, cfg);
1657 +
1658 + return 0;
1659 +}
1660 +
1661 +int dpsw_if_set_stp(struct fsl_mc_io *mc_io,
1662 + uint32_t cmd_flags,
1663 + uint16_t token,
1664 + uint16_t if_id,
1665 + const struct dpsw_stp_cfg *cfg)
1666 +{
1667 + struct mc_command cmd = { 0 };
1668 +
1669 + /* prepare command */
1670 + cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_SET_STP,
1671 + cmd_flags,
1672 + token);
1673 + DPSW_CMD_IF_SET_STP(cmd, if_id, cfg);
1674 +
1675 + /* send command to mc*/
1676 + return mc_send_command(mc_io, &cmd);
1677 +}
1678 +
1679 +int dpsw_if_set_accepted_frames(struct fsl_mc_io *mc_io,
1680 + uint32_t cmd_flags,
1681 + uint16_t token,
1682 + uint16_t if_id,
1683 + const struct dpsw_accepted_frames_cfg *cfg)
1684 +{
1685 + struct mc_command cmd = { 0 };
1686 +
1687 + /* prepare command */
1688 + cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_SET_ACCEPTED_FRAMES,
1689 + cmd_flags,
1690 + token);
1691 + DPSW_CMD_IF_SET_ACCEPTED_FRAMES(cmd, if_id, cfg);
1692 +
1693 + /* send command to mc*/
1694 + return mc_send_command(mc_io, &cmd);
1695 +}
1696 +
1697 +int dpsw_if_set_accept_all_vlan(struct fsl_mc_io *mc_io,
1698 + uint32_t cmd_flags,
1699 + uint16_t token,
1700 + uint16_t if_id,
1701 + int accept_all)
1702 +{
1703 + struct mc_command cmd = { 0 };
1704 +
1705 + /* prepare command */
1706 + cmd.header = mc_encode_cmd_header(DPSW_CMDID_SET_IF_ACCEPT_ALL_VLAN,
1707 + cmd_flags,
1708 + token);
1709 + DPSW_CMD_IF_SET_ACCEPT_ALL_VLAN(cmd, if_id, accept_all);
1710 +
1711 + /* send command to mc*/
1712 + return mc_send_command(mc_io, &cmd);
1713 +}
1714 +
1715 +int dpsw_if_get_counter(struct fsl_mc_io *mc_io,
1716 + uint32_t cmd_flags,
1717 + uint16_t token,
1718 + uint16_t if_id,
1719 + enum dpsw_counter type,
1720 + uint64_t *counter)
1721 +{
1722 + struct mc_command cmd = { 0 };
1723 + int err;
1724 +
1725 + /* prepare command */
1726 + cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_GET_COUNTER,
1727 + cmd_flags,
1728 + token);
1729 + DPSW_CMD_IF_GET_COUNTER(cmd, if_id, type);
1730 +
1731 + /* send command to mc*/
1732 + err = mc_send_command(mc_io, &cmd);
1733 + if (err)
1734 + return err;
1735 +
1736 + /* retrieve response parameters */
1737 + DPSW_RSP_IF_GET_COUNTER(cmd, *counter);
1738 +
1739 + return 0;
1740 +}
1741 +
1742 +int dpsw_if_set_counter(struct fsl_mc_io *mc_io,
1743 + uint32_t cmd_flags,
1744 + uint16_t token,
1745 + uint16_t if_id,
1746 + enum dpsw_counter type,
1747 + uint64_t counter)
1748 +{
1749 + struct mc_command cmd = { 0 };
1750 +
1751 + /* prepare command */
1752 + cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_SET_COUNTER,
1753 + cmd_flags,
1754 + token);
1755 + DPSW_CMD_IF_SET_COUNTER(cmd, if_id, type, counter);
1756 +
1757 + /* send command to mc*/
1758 + return mc_send_command(mc_io, &cmd);
1759 +}
1760 +
1761 +int dpsw_if_set_tx_selection(struct fsl_mc_io *mc_io,
1762 + uint32_t cmd_flags,
1763 + uint16_t token,
1764 + uint16_t if_id,
1765 + const struct dpsw_tx_selection_cfg *cfg)
1766 +{
1767 + struct mc_command cmd = { 0 };
1768 +
1769 + /* prepare command */
1770 + cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_SET_TX_SELECTION,
1771 + cmd_flags,
1772 + token);
1773 + DPSW_CMD_IF_SET_TX_SELECTION(cmd, if_id, cfg);
1774 +
1775 + /* send command to mc*/
1776 + return mc_send_command(mc_io, &cmd);
1777 +}
1778 +
1779 +int dpsw_if_add_reflection(struct fsl_mc_io *mc_io,
1780 + uint32_t cmd_flags,
1781 + uint16_t token,
1782 + uint16_t if_id,
1783 + const struct dpsw_reflection_cfg *cfg)
1784 +{
1785 + struct mc_command cmd = { 0 };
1786 +
1787 + /* prepare command */
1788 + cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_ADD_REFLECTION,
1789 + cmd_flags,
1790 + token);
1791 + DPSW_CMD_IF_ADD_REFLECTION(cmd, if_id, cfg);
1792 +
1793 + /* send command to mc*/
1794 + return mc_send_command(mc_io, &cmd);
1795 +}
1796 +
1797 +int dpsw_if_remove_reflection(struct fsl_mc_io *mc_io,
1798 + uint32_t cmd_flags,
1799 + uint16_t token,
1800 + uint16_t if_id,
1801 + const struct dpsw_reflection_cfg *cfg)
1802 +{
1803 + struct mc_command cmd = { 0 };
1804 +
1805 + /* prepare command */
1806 + cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_REMOVE_REFLECTION,
1807 + cmd_flags,
1808 + token);
1809 + DPSW_CMD_IF_REMOVE_REFLECTION(cmd, if_id, cfg);
1810 +
1811 + /* send command to mc*/
1812 + return mc_send_command(mc_io, &cmd);
1813 +}
1814 +
1815 +int dpsw_if_set_flooding_metering(struct fsl_mc_io *mc_io,
1816 + uint32_t cmd_flags,
1817 + uint16_t token,
1818 + uint16_t if_id,
1819 + const struct dpsw_metering_cfg *cfg)
1820 +{
1821 + struct mc_command cmd = { 0 };
1822 +
1823 + /* prepare command */
1824 + cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_SET_FLOODING_METERING,
1825 + cmd_flags,
1826 + token);
1827 + DPSW_CMD_IF_SET_FLOODING_METERING(cmd, if_id, cfg);
1828 +
1829 + /* send command to mc*/
1830 + return mc_send_command(mc_io, &cmd);
1831 +}
1832 +
1833 +int dpsw_if_set_metering(struct fsl_mc_io *mc_io,
1834 + uint32_t cmd_flags,
1835 + uint16_t token,
1836 + uint16_t if_id,
1837 + uint8_t tc_id,
1838 + const struct dpsw_metering_cfg *cfg)
1839 +{
1840 + struct mc_command cmd = { 0 };
1841 +
1842 + /* prepare command */
1843 + cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_SET_METERING,
1844 + cmd_flags,
1845 + token);
1846 + DPSW_CMD_IF_SET_METERING(cmd, if_id, tc_id, cfg);
1847 +
1848 + /* send command to mc*/
1849 + return mc_send_command(mc_io, &cmd);
1850 +}
1851 +
1852 +void dpsw_prepare_early_drop(const struct dpsw_early_drop_cfg *cfg,
1853 + uint8_t *early_drop_buf)
1854 +{
1855 + uint64_t *ext_params = (uint64_t *)early_drop_buf;
1856 +
1857 + DPSW_PREP_EARLY_DROP(ext_params, cfg);
1858 +}
1859 +
1860 +int dpsw_if_set_early_drop(struct fsl_mc_io *mc_io,
1861 + uint32_t cmd_flags,
1862 + uint16_t token,
1863 + uint16_t if_id,
1864 + uint8_t tc_id,
1865 + uint64_t early_drop_iova)
1866 +{
1867 + struct mc_command cmd = { 0 };
1868 +
1869 + /* prepare command */
1870 + cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_SET_EARLY_DROP,
1871 + cmd_flags,
1872 + token);
1873 + DPSW_CMD_IF_SET_EARLY_DROP(cmd, if_id, tc_id, early_drop_iova);
1874 +
1875 + /* send command to mc*/
1876 + return mc_send_command(mc_io, &cmd);
1877 +}
1878 +
1879 +int dpsw_add_custom_tpid(struct fsl_mc_io *mc_io,
1880 + uint32_t cmd_flags,
1881 + uint16_t token,
1882 + const struct dpsw_custom_tpid_cfg *cfg)
1883 +{
1884 + struct mc_command cmd = { 0 };
1885 +
1886 + /* prepare command */
1887 + cmd.header = mc_encode_cmd_header(DPSW_CMDID_ADD_CUSTOM_TPID,
1888 + cmd_flags,
1889 + token);
1890 + DPSW_CMD_ADD_CUSTOM_TPID(cmd, cfg);
1891 +
1892 + /* send command to mc*/
1893 + return mc_send_command(mc_io, &cmd);
1894 +}
1895 +
1896 +int dpsw_remove_custom_tpid(struct fsl_mc_io *mc_io,
1897 + uint32_t cmd_flags,
1898 + uint16_t token,
1899 + const struct dpsw_custom_tpid_cfg *cfg)
1900 +{
1901 + struct mc_command cmd = { 0 };
1902 +
1903 + /* prepare command */
1904 + cmd.header = mc_encode_cmd_header(DPSW_CMDID_REMOVE_CUSTOM_TPID,
1905 + cmd_flags,
1906 + token);
1907 + DPSW_CMD_REMOVE_CUSTOM_TPID(cmd, cfg);
1908 +
1909 + /* send command to mc*/
1910 + return mc_send_command(mc_io, &cmd);
1911 +}
1912 +
1913 +int dpsw_if_enable(struct fsl_mc_io *mc_io,
1914 + uint32_t cmd_flags,
1915 + uint16_t token,
1916 + uint16_t if_id)
1917 +{
1918 + struct mc_command cmd = { 0 };
1919 +
1920 + /* prepare command */
1921 + cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_ENABLE,
1922 + cmd_flags,
1923 + token);
1924 + DPSW_CMD_IF_ENABLE(cmd, if_id);
1925 +
1926 + /* send command to mc*/
1927 + return mc_send_command(mc_io, &cmd);
1928 +}
1929 +
1930 +int dpsw_if_disable(struct fsl_mc_io *mc_io,
1931 + uint32_t cmd_flags,
1932 + uint16_t token,
1933 + uint16_t if_id)
1934 +{
1935 + struct mc_command cmd = { 0 };
1936 +
1937 + /* prepare command */
1938 + cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_DISABLE,
1939 + cmd_flags,
1940 + token);
1941 + DPSW_CMD_IF_DISABLE(cmd, if_id);
1942 +
1943 + /* send command to mc*/
1944 + return mc_send_command(mc_io, &cmd);
1945 +}
1946 +
1947 +int dpsw_if_get_attributes(struct fsl_mc_io *mc_io,
1948 + uint32_t cmd_flags,
1949 + uint16_t token,
1950 + uint16_t if_id,
1951 + struct dpsw_if_attr *attr)
1952 +{
1953 + struct mc_command cmd = { 0 };
1954 + int err;
1955 +
1956 + /* prepare command */
1957 + cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_GET_ATTR,
1958 + cmd_flags,
1959 + token);
1960 + DPSW_CMD_IF_GET_ATTR(cmd, if_id);
1961 +
1962 + /* send command to mc*/
1963 + err = mc_send_command(mc_io, &cmd);
1964 + if (err)
1965 + return err;
1966 +
1967 + /* retrieve response parameters */
1968 + DPSW_RSP_IF_GET_ATTR(cmd, attr);
1969 +
1970 + return 0;
1971 +}
1972 +
1973 +int dpsw_if_set_max_frame_length(struct fsl_mc_io *mc_io,
1974 + uint32_t cmd_flags,
1975 + uint16_t token,
1976 + uint16_t if_id,
1977 + uint16_t frame_length)
1978 +{
1979 + struct mc_command cmd = { 0 };
1980 +
1981 + /* prepare command */
1982 + cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_SET_MAX_FRAME_LENGTH,
1983 + cmd_flags,
1984 + token);
1985 + DPSW_CMD_IF_SET_MAX_FRAME_LENGTH(cmd, if_id, frame_length);
1986 +
1987 + /* send command to mc*/
1988 + return mc_send_command(mc_io, &cmd);
1989 +}
1990 +
1991 +int dpsw_if_get_max_frame_length(struct fsl_mc_io *mc_io,
1992 + uint32_t cmd_flags,
1993 + uint16_t token,
1994 + uint16_t if_id,
1995 + uint16_t *frame_length)
1996 +{
1997 + struct mc_command cmd = { 0 };
1998 + int err;
1999 +
2000 + /* prepare command */
2001 + cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_GET_MAX_FRAME_LENGTH,
2002 + cmd_flags,
2003 + token);
2004 + DPSW_CMD_IF_GET_MAX_FRAME_LENGTH(cmd, if_id);
2005 +
2006 + /* send command to mc*/
2007 + err = mc_send_command(mc_io, &cmd);
2008 + if (err)
2009 + return err;
2010 +
2011 + DPSW_RSP_IF_GET_MAX_FRAME_LENGTH(cmd, *frame_length);
2012 +
2013 + return 0;
2014 +}
2015 +
2016 +int dpsw_vlan_add(struct fsl_mc_io *mc_io,
2017 + uint32_t cmd_flags,
2018 + uint16_t token,
2019 + uint16_t vlan_id,
2020 + const struct dpsw_vlan_cfg *cfg)
2021 +{
2022 + struct mc_command cmd = { 0 };
2023 +
2024 + /* prepare command */
2025 + cmd.header = mc_encode_cmd_header(DPSW_CMDID_VLAN_ADD,
2026 + cmd_flags,
2027 + token);
2028 + DPSW_CMD_VLAN_ADD(cmd, vlan_id, cfg);
2029 +
2030 + /* send command to mc*/
2031 + return mc_send_command(mc_io, &cmd);
2032 +}
2033 +
2034 +int dpsw_vlan_add_if(struct fsl_mc_io *mc_io,
2035 + uint32_t cmd_flags,
2036 + uint16_t token,
2037 + uint16_t vlan_id,
2038 + const struct dpsw_vlan_if_cfg *cfg)
2039 +{
2040 + struct mc_command cmd = { 0 };
2041 +
2042 + /* prepare command */
2043 + build_if_id_bitmap(cfg->if_id, cfg->num_ifs, &cmd, 1);
2044 + cmd.header = mc_encode_cmd_header(DPSW_CMDID_VLAN_ADD_IF,
2045 + cmd_flags,
2046 + token);
2047 + DPSW_CMD_VLAN_ADD_IF(cmd, vlan_id);
2048 +
2049 + /* send command to mc*/
2050 + return mc_send_command(mc_io, &cmd);
2051 +}
2052 +
2053 +int dpsw_vlan_add_if_untagged(struct fsl_mc_io *mc_io,
2054 + uint32_t cmd_flags,
2055 + uint16_t token,
2056 + uint16_t vlan_id,
2057 + const struct dpsw_vlan_if_cfg *cfg)
2058 +{
2059 + struct mc_command cmd = { 0 };
2060 +
2061 + /* prepare command */
2062 + build_if_id_bitmap(cfg->if_id, cfg->num_ifs, &cmd, 1);
2063 + cmd.header = mc_encode_cmd_header(DPSW_CMDID_VLAN_ADD_IF_UNTAGGED,
2064 + cmd_flags,
2065 + token);
2066 + DPSW_CMD_VLAN_ADD_IF_UNTAGGED(cmd, vlan_id);
2067 +
2068 + /* send command to mc*/
2069 + return mc_send_command(mc_io, &cmd);
2070 +}
2071 +
2072 +int dpsw_vlan_add_if_flooding(struct fsl_mc_io *mc_io,
2073 + uint32_t cmd_flags,
2074 + uint16_t token,
2075 + uint16_t vlan_id,
2076 + const struct dpsw_vlan_if_cfg *cfg)
2077 +{
2078 + struct mc_command cmd = { 0 };
2079 +
2080 + /* prepare command */
2081 + build_if_id_bitmap(cfg->if_id, cfg->num_ifs, &cmd, 1);
2082 + cmd.header = mc_encode_cmd_header(DPSW_CMDID_VLAN_ADD_IF_FLOODING,
2083 + cmd_flags,
2084 + token);
2085 + DPSW_CMD_VLAN_ADD_IF_FLOODING(cmd, vlan_id);
2086 +
2087 + /* send command to mc*/
2088 + return mc_send_command(mc_io, &cmd);
2089 +}
2090 +
2091 +int dpsw_vlan_remove_if(struct fsl_mc_io *mc_io,
2092 + uint32_t cmd_flags,
2093 + uint16_t token,
2094 + uint16_t vlan_id,
2095 + const struct dpsw_vlan_if_cfg *cfg)
2096 +{
2097 + struct mc_command cmd = { 0 };
2098 +
2099 + /* prepare command */
2100 + build_if_id_bitmap(cfg->if_id, cfg->num_ifs, &cmd, 1);
2101 + cmd.header = mc_encode_cmd_header(DPSW_CMDID_VLAN_REMOVE_IF,
2102 + cmd_flags,
2103 + token);
2104 + DPSW_CMD_VLAN_REMOVE_IF(cmd, vlan_id);
2105 +
2106 + /* send command to mc*/
2107 + return mc_send_command(mc_io, &cmd);
2108 +}
2109 +
2110 +int dpsw_vlan_remove_if_untagged(struct fsl_mc_io *mc_io,
2111 + uint32_t cmd_flags,
2112 + uint16_t token,
2113 + uint16_t vlan_id,
2114 + const struct dpsw_vlan_if_cfg *cfg)
2115 +{
2116 + struct mc_command cmd = { 0 };
2117 +
2118 + /* prepare command */
2119 + build_if_id_bitmap(cfg->if_id, cfg->num_ifs, &cmd, 1);
2120 + cmd.header = mc_encode_cmd_header(DPSW_CMDID_VLAN_REMOVE_IF_UNTAGGED,
2121 + cmd_flags,
2122 + token);
2123 + DPSW_CMD_VLAN_REMOVE_IF_UNTAGGED(cmd, vlan_id);
2124 +
2125 + /* send command to mc*/
2126 + return mc_send_command(mc_io, &cmd);
2127 +}
2128 +
2129 +int dpsw_vlan_remove_if_flooding(struct fsl_mc_io *mc_io,
2130 + uint32_t cmd_flags,
2131 + uint16_t token,
2132 + uint16_t vlan_id,
2133 + const struct dpsw_vlan_if_cfg *cfg)
2134 +{
2135 + struct mc_command cmd = { 0 };
2136 +
2137 + /* prepare command */
2138 + build_if_id_bitmap(cfg->if_id, cfg->num_ifs, &cmd, 1);
2139 + cmd.header = mc_encode_cmd_header(DPSW_CMDID_VLAN_REMOVE_IF_FLOODING,
2140 + cmd_flags,
2141 + token);
2142 + DPSW_CMD_VLAN_REMOVE_IF_FLOODING(cmd, vlan_id);
2143 +
2144 + /* send command to mc*/
2145 + return mc_send_command(mc_io, &cmd);
2146 +}
2147 +
2148 +int dpsw_vlan_remove(struct fsl_mc_io *mc_io,
2149 + uint32_t cmd_flags,
2150 + uint16_t token,
2151 + uint16_t vlan_id)
2152 +{
2153 + struct mc_command cmd = { 0 };
2154 +
2155 + /* prepare command */
2156 + cmd.header = mc_encode_cmd_header(DPSW_CMDID_VLAN_REMOVE,
2157 + cmd_flags,
2158 + token);
2159 + DPSW_CMD_VLAN_REMOVE(cmd, vlan_id);
2160 +
2161 + /* send command to mc*/
2162 + return mc_send_command(mc_io, &cmd);
2163 +}
2164 +
2165 +int dpsw_vlan_get_attributes(struct fsl_mc_io *mc_io,
2166 + uint32_t cmd_flags,
2167 + uint16_t token,
2168 + uint16_t vlan_id,
2169 + struct dpsw_vlan_attr *attr)
2170 +{
2171 + struct mc_command cmd = { 0 };
2172 + int err;
2173 +
2174 + /* prepare command */
2175 + cmd.header = mc_encode_cmd_header(DPSW_CMDID_VLAN_GET_ATTRIBUTES,
2176 + cmd_flags,
2177 + token);
2178 + DPSW_CMD_VLAN_GET_ATTR(cmd, vlan_id);
2179 +
2180 + /* send command to mc*/
2181 + err = mc_send_command(mc_io, &cmd);
2182 + if (err)
2183 + return err;
2184 +
2185 + /* retrieve response parameters */
2186 + DPSW_RSP_VLAN_GET_ATTR(cmd, attr);
2187 +
2188 + return 0;
2189 +}
2190 +
2191 +int dpsw_vlan_get_if(struct fsl_mc_io *mc_io,
2192 + uint32_t cmd_flags,
2193 + uint16_t token,
2194 + uint16_t vlan_id,
2195 + struct dpsw_vlan_if_cfg *cfg)
2196 +{
2197 + struct mc_command cmd = { 0 };
2198 + int err;
2199 +
2200 + /* prepare command */
2201 + cmd.header = mc_encode_cmd_header(DPSW_CMDID_VLAN_GET_IF,
2202 + cmd_flags,
2203 + token);
2204 + DPSW_CMD_VLAN_GET_IF(cmd, vlan_id);
2205 +
2206 + /* send command to mc*/
2207 + err = mc_send_command(mc_io, &cmd);
2208 + if (err)
2209 + return err;
2210 +
2211 + /* retrieve response parameters */
2212 + DPSW_RSP_VLAN_GET_IF(cmd, cfg);
2213 + read_if_id_bitmap(cfg->if_id, &cfg->num_ifs, &cmd, 1);
2214 +
2215 + return 0;
2216 +}
2217 +
2218 +int dpsw_vlan_get_if_flooding(struct fsl_mc_io *mc_io,
2219 + uint32_t cmd_flags,
2220 + uint16_t token,
2221 + uint16_t vlan_id,
2222 + struct dpsw_vlan_if_cfg *cfg)
2223 +{
2224 + struct mc_command cmd = { 0 };
2225 + int err;
2226 +
2227 + /* prepare command */
2228 + cmd.header = mc_encode_cmd_header(DPSW_CMDID_VLAN_GET_IF_FLOODING,
2229 + cmd_flags,
2230 + token);
2231 + DPSW_CMD_VLAN_GET_IF_FLOODING(cmd, vlan_id);
2232 +
2233 + /* send command to mc*/
2234 + err = mc_send_command(mc_io, &cmd);
2235 + if (err)
2236 + return err;
2237 +
2238 + /* retrieve response parameters */
2239 + DPSW_RSP_VLAN_GET_IF_FLOODING(cmd, cfg);
2240 + read_if_id_bitmap(cfg->if_id, &cfg->num_ifs, &cmd, 1);
2241 +
2242 + return 0;
2243 +}
2244 +
2245 +int dpsw_vlan_get_if_untagged(struct fsl_mc_io *mc_io,
2246 + uint32_t cmd_flags,
2247 + uint16_t token,
2248 + uint16_t vlan_id,
2249 + struct dpsw_vlan_if_cfg *cfg)
2250 +{
2251 + struct mc_command cmd = { 0 };
2252 + int err;
2253 +
2254 + /* prepare command */
2255 + cmd.header = mc_encode_cmd_header(DPSW_CMDID_VLAN_GET_IF_UNTAGGED,
2256 + cmd_flags,
2257 + token);
2258 + DPSW_CMD_VLAN_GET_IF_UNTAGGED(cmd, vlan_id);
2259 +
2260 + /* send command to mc*/
2261 + err = mc_send_command(mc_io, &cmd);
2262 + if (err)
2263 + return err;
2264 +
2265 + /* retrieve response parameters */
2266 + DPSW_RSP_VLAN_GET_IF(cmd, cfg);
2267 + read_if_id_bitmap(cfg->if_id, &cfg->num_ifs, &cmd, 1);
2268 +
2269 + return 0;
2270 +}
2271 +
2272 +int dpsw_fdb_add(struct fsl_mc_io *mc_io,
2273 + uint32_t cmd_flags,
2274 + uint16_t token,
2275 + uint16_t *fdb_id,
2276 + const struct dpsw_fdb_cfg *cfg)
2277 +{
2278 + struct mc_command cmd = { 0 };
2279 + int err;
2280 +
2281 + /* prepare command */
2282 + cmd.header = mc_encode_cmd_header(DPSW_CMDID_FDB_ADD,
2283 + cmd_flags,
2284 + token);
2285 + DPSW_CMD_FDB_ADD(cmd, cfg);
2286 +
2287 + /* send command to mc*/
2288 + err = mc_send_command(mc_io, &cmd);
2289 + if (err)
2290 + return err;
2291 +
2292 + /* retrieve response parameters */
2293 + DPSW_RSP_FDB_ADD(cmd, *fdb_id);
2294 +
2295 + return 0;
2296 +}
2297 +
2298 +int dpsw_fdb_remove(struct fsl_mc_io *mc_io,
2299 + uint32_t cmd_flags,
2300 + uint16_t token,
2301 + uint16_t fdb_id)
2302 +{
2303 + struct mc_command cmd = { 0 };
2304 +
2305 + /* prepare command */
2306 + cmd.header = mc_encode_cmd_header(DPSW_CMDID_FDB_REMOVE,
2307 + cmd_flags,
2308 + token);
2309 + DPSW_CMD_FDB_REMOVE(cmd, fdb_id);
2310 +
2311 + /* send command to mc*/
2312 + return mc_send_command(mc_io, &cmd);
2313 +}
2314 +
2315 +int dpsw_fdb_add_unicast(struct fsl_mc_io *mc_io,
2316 + uint32_t cmd_flags,
2317 + uint16_t token,
2318 + uint16_t fdb_id,
2319 + const struct dpsw_fdb_unicast_cfg *cfg)
2320 +{
2321 + struct mc_command cmd = { 0 };
2322 +
2323 + /* prepare command */
2324 + cmd.header = mc_encode_cmd_header(DPSW_CMDID_FDB_ADD_UNICAST,
2325 + cmd_flags,
2326 + token);
2327 + DPSW_CMD_FDB_ADD_UNICAST(cmd, fdb_id, cfg);
2328 +
2329 + /* send command to mc*/
2330 + return mc_send_command(mc_io, &cmd);
2331 +}
2332 +
2333 +int dpsw_fdb_get_unicast(struct fsl_mc_io *mc_io,
2334 + uint32_t cmd_flags,
2335 + uint16_t token,
2336 + uint16_t fdb_id,
2337 + struct dpsw_fdb_unicast_cfg *cfg)
2338 +{
2339 + struct mc_command cmd = { 0 };
2340 + int err;
2341 +
2342 + /* prepare command */
2343 + cmd.header = mc_encode_cmd_header(DPSW_CMDID_FDB_GET_UNICAST,
2344 + cmd_flags,
2345 + token);
2346 + DPSW_CMD_FDB_GET_UNICAST(cmd, fdb_id);
2347 +
2348 + /* send command to mc*/
2349 + err = mc_send_command(mc_io, &cmd);
2350 + if (err)
2351 + return err;
2352 +
2353 + /* retrieve response parameters */
2354 + DPSW_RSP_FDB_GET_UNICAST(cmd, cfg);
2355 +
2356 + return 0;
2357 +}
2358 +
2359 +int dpsw_fdb_remove_unicast(struct fsl_mc_io *mc_io,
2360 + uint32_t cmd_flags,
2361 + uint16_t token,
2362 + uint16_t fdb_id,
2363 + const struct dpsw_fdb_unicast_cfg *cfg)
2364 +{
2365 + struct mc_command cmd = { 0 };
2366 +
2367 + /* prepare command */
2368 + cmd.header = mc_encode_cmd_header(DPSW_CMDID_FDB_REMOVE_UNICAST,
2369 + cmd_flags,
2370 + token);
2371 + DPSW_CMD_FDB_REMOVE_UNICAST(cmd, fdb_id, cfg);
2372 +
2373 + /* send command to mc*/
2374 + return mc_send_command(mc_io, &cmd);
2375 +}
2376 +
2377 +int dpsw_fdb_add_multicast(struct fsl_mc_io *mc_io,
2378 + uint32_t cmd_flags,
2379 + uint16_t token,
2380 + uint16_t fdb_id,
2381 + const struct dpsw_fdb_multicast_cfg *cfg)
2382 +{
2383 + struct mc_command cmd = { 0 };
2384 +
2385 + /* prepare command */
2386 + build_if_id_bitmap(cfg->if_id, cfg->num_ifs, &cmd, 2);
2387 + cmd.header = mc_encode_cmd_header(DPSW_CMDID_FDB_ADD_MULTICAST,
2388 + cmd_flags,
2389 + token);
2390 + DPSW_CMD_FDB_ADD_MULTICAST(cmd, fdb_id, cfg);
2391 +
2392 + /* send command to mc*/
2393 + return mc_send_command(mc_io, &cmd);
2394 +}
2395 +
2396 +int dpsw_fdb_get_multicast(struct fsl_mc_io *mc_io,
2397 + uint32_t cmd_flags,
2398 + uint16_t token,
2399 + uint16_t fdb_id,
2400 + struct dpsw_fdb_multicast_cfg *cfg)
2401 +{
2402 + struct mc_command cmd = { 0 };
2403 + int err;
2404 +
2405 + /* prepare command */
2406 + cmd.header = mc_encode_cmd_header(DPSW_CMDID_FDB_GET_MULTICAST,
2407 + cmd_flags,
2408 + token);
2409 + DPSW_CMD_FDB_GET_MULTICAST(cmd, fdb_id);
2410 +
2411 + /* send command to mc*/
2412 + err = mc_send_command(mc_io, &cmd);
2413 + if (err)
2414 + return err;
2415 +
2416 + /* retrieve response parameters */
2417 + DPSW_RSP_FDB_GET_MULTICAST(cmd, cfg);
2418 + read_if_id_bitmap(cfg->if_id, &cfg->num_ifs, &cmd, 2);
2419 +
2420 + return 0;
2421 +}
2422 +
2423 +int dpsw_fdb_remove_multicast(struct fsl_mc_io *mc_io,
2424 + uint32_t cmd_flags,
2425 + uint16_t token,
2426 + uint16_t fdb_id,
2427 + const struct dpsw_fdb_multicast_cfg *cfg)
2428 +{
2429 + struct mc_command cmd = { 0 };
2430 +
2431 + /* prepare command */
2432 + build_if_id_bitmap(cfg->if_id, cfg->num_ifs, &cmd, 2);
2433 + cmd.header = mc_encode_cmd_header(DPSW_CMDID_FDB_REMOVE_MULTICAST,
2434 + cmd_flags,
2435 + token);
2436 + DPSW_CMD_FDB_REMOVE_MULTICAST(cmd, fdb_id, cfg);
2437 +
2438 + /* send command to mc*/
2439 + return mc_send_command(mc_io, &cmd);
2440 +}
2441 +
2442 +int dpsw_fdb_set_learning_mode(struct fsl_mc_io *mc_io,
2443 + uint32_t cmd_flags,
2444 + uint16_t token,
2445 + uint16_t fdb_id,
2446 + enum dpsw_fdb_learning_mode mode)
2447 +{
2448 + struct mc_command cmd = { 0 };
2449 +
2450 + /* prepare command */
2451 + cmd.header = mc_encode_cmd_header(DPSW_CMDID_FDB_SET_LEARNING_MODE,
2452 + cmd_flags,
2453 + token);
2454 + DPSW_CMD_FDB_SET_LEARNING_MODE(cmd, fdb_id, mode);
2455 +
2456 + /* send command to mc*/
2457 + return mc_send_command(mc_io, &cmd);
2458 +}
2459 +
2460 +int dpsw_fdb_get_attributes(struct fsl_mc_io *mc_io,
2461 + uint32_t cmd_flags,
2462 + uint16_t token,
2463 + uint16_t fdb_id,
2464 + struct dpsw_fdb_attr *attr)
2465 +{
2466 + struct mc_command cmd = { 0 };
2467 + int err;
2468 +
2469 + /* prepare command */
2470 + cmd.header = mc_encode_cmd_header(DPSW_CMDID_FDB_GET_ATTR,
2471 + cmd_flags,
2472 + token);
2473 + DPSW_CMD_FDB_GET_ATTR(cmd, fdb_id);
2474 +
2475 + /* send command to mc*/
2476 + err = mc_send_command(mc_io, &cmd);
2477 + if (err)
2478 + return err;
2479 +
2480 + /* retrieve response parameters */
2481 + DPSW_RSP_FDB_GET_ATTR(cmd, attr);
2482 +
2483 + return 0;
2484 +}
2485 +
2486 +int dpsw_acl_add(struct fsl_mc_io *mc_io,
2487 + uint32_t cmd_flags,
2488 + uint16_t token,
2489 + uint16_t *acl_id,
2490 + const struct dpsw_acl_cfg *cfg)
2491 +{
2492 + struct mc_command cmd = { 0 };
2493 + int err;
2494 +
2495 + /* prepare command */
2496 + cmd.header = mc_encode_cmd_header(DPSW_CMDID_ACL_ADD,
2497 + cmd_flags,
2498 + token);
2499 + DPSW_CMD_ACL_ADD(cmd, cfg);
2500 +
2501 + /* send command to mc*/
2502 + err = mc_send_command(mc_io, &cmd);
2503 + if (err)
2504 + return err;
2505 +
2506 + /* retrieve response parameters */
2507 + DPSW_RSP_ACL_ADD(cmd, *acl_id);
2508 +
2509 + return 0;
2510 +}
2511 +
2512 +int dpsw_acl_remove(struct fsl_mc_io *mc_io,
2513 + uint32_t cmd_flags,
2514 + uint16_t token,
2515 + uint16_t acl_id)
2516 +{
2517 + struct mc_command cmd = { 0 };
2518 +
2519 + /* prepare command */
2520 + cmd.header = mc_encode_cmd_header(DPSW_CMDID_ACL_REMOVE,
2521 + cmd_flags,
2522 + token);
2523 + DPSW_CMD_ACL_REMOVE(cmd, acl_id);
2524 +
2525 + /* send command to mc*/
2526 + return mc_send_command(mc_io, &cmd);
2527 +}
2528 +
2529 +void dpsw_acl_prepare_entry_cfg(const struct dpsw_acl_key *key,
2530 + uint8_t *entry_cfg_buf)
2531 +{
2532 + uint64_t *ext_params = (uint64_t *)entry_cfg_buf;
2533 +
2534 + DPSW_PREP_ACL_ENTRY(ext_params, key);
2535 +}
2536 +
2537 +int dpsw_acl_add_entry(struct fsl_mc_io *mc_io,
2538 + uint32_t cmd_flags,
2539 + uint16_t token,
2540 + uint16_t acl_id,
2541 + const struct dpsw_acl_entry_cfg *cfg)
2542 +{
2543 + struct mc_command cmd = { 0 };
2544 +
2545 + /* prepare command */
2546 + cmd.header = mc_encode_cmd_header(DPSW_CMDID_ACL_ADD_ENTRY,
2547 + cmd_flags,
2548 + token);
2549 + DPSW_CMD_ACL_ADD_ENTRY(cmd, acl_id, cfg);
2550 +
2551 + /* send command to mc*/
2552 + return mc_send_command(mc_io, &cmd);
2553 +}
2554 +
2555 +int dpsw_acl_remove_entry(struct fsl_mc_io *mc_io,
2556 + uint32_t cmd_flags,
2557 + uint16_t token,
2558 + uint16_t acl_id,
2559 + const struct dpsw_acl_entry_cfg *cfg)
2560 +{
2561 + struct mc_command cmd = { 0 };
2562 +
2563 + /* prepare command */
2564 + cmd.header = mc_encode_cmd_header(DPSW_CMDID_ACL_REMOVE_ENTRY,
2565 + cmd_flags,
2566 + token);
2567 + DPSW_CMD_ACL_REMOVE_ENTRY(cmd, acl_id, cfg);
2568 +
2569 + /* send command to mc*/
2570 + return mc_send_command(mc_io, &cmd);
2571 +}
2572 +
2573 +int dpsw_acl_add_if(struct fsl_mc_io *mc_io,
2574 + uint32_t cmd_flags,
2575 + uint16_t token,
2576 + uint16_t acl_id,
2577 + const struct dpsw_acl_if_cfg *cfg)
2578 +{
2579 + struct mc_command cmd = { 0 };
2580 +
2581 + /* prepare command */
2582 + build_if_id_bitmap(cfg->if_id, cfg->num_ifs, &cmd, 1);
2583 + cmd.header = mc_encode_cmd_header(DPSW_CMDID_ACL_ADD_IF,
2584 + cmd_flags,
2585 + token);
2586 + DPSW_CMD_ACL_ADD_IF(cmd, acl_id, cfg);
2587 +
2588 + /* send command to mc*/
2589 + return mc_send_command(mc_io, &cmd);
2590 +}
2591 +
2592 +int dpsw_acl_remove_if(struct fsl_mc_io *mc_io,
2593 + uint32_t cmd_flags,
2594 + uint16_t token,
2595 + uint16_t acl_id,
2596 + const struct dpsw_acl_if_cfg *cfg)
2597 +{
2598 + struct mc_command cmd = { 0 };
2599 +
2600 + /* prepare command */
2601 + build_if_id_bitmap(cfg->if_id, cfg->num_ifs, &cmd, 1);
2602 + cmd.header = mc_encode_cmd_header(DPSW_CMDID_ACL_REMOVE_IF,
2603 + cmd_flags,
2604 + token);
2605 + DPSW_CMD_ACL_REMOVE_IF(cmd, acl_id, cfg);
2606 +
2607 + /* send command to mc*/
2608 + return mc_send_command(mc_io, &cmd);
2609 +}
2610 +
2611 +int dpsw_acl_get_attributes(struct fsl_mc_io *mc_io,
2612 + uint32_t cmd_flags,
2613 + uint16_t token,
2614 + uint16_t acl_id,
2615 + struct dpsw_acl_attr *attr)
2616 +{
2617 + struct mc_command cmd = { 0 };
2618 + int err;
2619 +
2620 + /* prepare command */
2621 + cmd.header = mc_encode_cmd_header(DPSW_CMDID_ACL_GET_ATTR,
2622 + cmd_flags,
2623 + token);
2624 + DPSW_CMD_ACL_GET_ATTR(cmd, acl_id);
2625 +
2626 + /* send command to mc*/
2627 + err = mc_send_command(mc_io, &cmd);
2628 + if (err)
2629 + return err;
2630 +
2631 + /* retrieve response parameters */
2632 + DPSW_RSP_ACL_GET_ATTR(cmd, attr);
2633 +
2634 + return 0;
2635 +}
2636 +
2637 +int dpsw_ctrl_if_get_attributes(struct fsl_mc_io *mc_io,
2638 + uint32_t cmd_flags,
2639 + uint16_t token,
2640 + struct dpsw_ctrl_if_attr *attr)
2641 +{
2642 + struct mc_command cmd = { 0 };
2643 + int err;
2644 +
2645 + /* prepare command */
2646 + cmd.header = mc_encode_cmd_header(DPSW_CMDID_CTRL_IF_GET_ATTR,
2647 + cmd_flags,
2648 + token);
2649 +
2650 + /* send command to mc*/
2651 + err = mc_send_command(mc_io, &cmd);
2652 + if (err)
2653 + return err;
2654 +
2655 + /* retrieve response parameters */
2656 + DPSW_RSP_CTRL_IF_GET_ATTR(cmd, attr);
2657 +
2658 + return 0;
2659 +}
2660 +
2661 +int dpsw_ctrl_if_set_pools(struct fsl_mc_io *mc_io,
2662 + uint32_t cmd_flags,
2663 + uint16_t token,
2664 + const struct dpsw_ctrl_if_pools_cfg *pools)
2665 +{
2666 + struct mc_command cmd = { 0 };
2667 +
2668 + /* prepare command */
2669 + cmd.header = mc_encode_cmd_header(DPSW_CMDID_CTRL_IF_SET_POOLS,
2670 + cmd_flags,
2671 + token);
2672 + DPSW_CMD_CTRL_IF_SET_POOLS(cmd, pools);
2673 +
2674 + /* send command to mc*/
2675 + return mc_send_command(mc_io, &cmd);
2676 +}
2677 +
2678 +int dpsw_ctrl_if_enable(struct fsl_mc_io *mc_io,
2679 + uint32_t cmd_flags,
2680 + uint16_t token)
2681 +{
2682 + struct mc_command cmd = { 0 };
2683 +
2684 + /* prepare command */
2685 + cmd.header = mc_encode_cmd_header(DPSW_CMDID_CTRL_IF_ENABLE,
2686 + cmd_flags,
2687 + token);
2688 +
2689 + /* send command to mc*/
2690 + return mc_send_command(mc_io, &cmd);
2691 +}
2692 +
2693 +/**
2694 +* @brief Function disables control interface
2695 +* @mc_io: Pointer to MC portal's I/O object
2696 +* @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
2697 +* @token: Token of DPSW object
2698 +*
2699 +* Return: '0' on Success; Error code otherwise.
2700 +*/
2701 +int dpsw_ctrl_if_disable(struct fsl_mc_io *mc_io,
2702 + uint32_t cmd_flags,
2703 + uint16_t token)
2704 +{
2705 + struct mc_command cmd = { 0 };
2706 +
2707 + /* prepare command */
2708 + cmd.header = mc_encode_cmd_header(DPSW_CMDID_CTRL_IF_DISABLE,
2709 + cmd_flags,
2710 + token);
2711 +
2712 + /* send command to mc*/
2713 + return mc_send_command(mc_io, &cmd);
2714 +}
2715 --- /dev/null
2716 +++ b/drivers/staging/fsl-dpaa2/ethsw/dpsw.h
2717 @@ -0,0 +1,2164 @@
2718 +/* Copyright 2013-2015 Freescale Semiconductor Inc.
2719 + *
2720 + * Redistribution and use in source and binary forms, with or without
2721 + * modification, are permitted provided that the following conditions are met:
2722 + * * Redistributions of source code must retain the above copyright
2723 + * notice, this list of conditions and the following disclaimer.
2724 + * * Redistributions in binary form must reproduce the above copyright
2725 + * notice, this list of conditions and the following disclaimer in the
2726 + * documentation and/or other materials provided with the distribution.
2727 + * * Neither the name of the above-listed copyright holders nor the
2728 + * names of any contributors may be used to endorse or promote products
2729 + * derived from this software without specific prior written permission.
2730 + *
2731 + *
2732 + * ALTERNATIVELY, this software may be distributed under the terms of the
2733 + * GNU General Public License ("GPL") as published by the Free Software
2734 + * Foundation, either version 2 of that License or (at your option) any
2735 + * later version.
2736 + *
2737 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
2738 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2739 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2740 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
2741 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2742 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2743 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2744 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2745 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2746 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2747 + * POSSIBILITY OF SUCH DAMAGE.
2748 + */
2749 +#ifndef __FSL_DPSW_H
2750 +#define __FSL_DPSW_H
2751 +
2752 +#include "../../fsl-mc/include/net.h"
2753 +
2754 +/* Data Path L2-Switch API
2755 + * Contains API for handling DPSW topology and functionality
2756 + */
2757 +
2758 +struct fsl_mc_io;
2759 +
2760 +/**
2761 + * DPSW general definitions
2762 + */
2763 +
2764 +/**
2765 + * Maximum number of traffic class priorities
2766 + */
2767 +#define DPSW_MAX_PRIORITIES 8
2768 +/**
2769 + * Maximum number of interfaces
2770 + */
2771 +#define DPSW_MAX_IF 64
2772 +
2773 +/**
2774 + * dpsw_open() - Open a control session for the specified object
2775 + * @mc_io: Pointer to MC portal's I/O object
2776 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
2777 + * @dpsw_id: DPSW unique ID
2778 + * @token: Returned token; use in subsequent API calls
2779 + *
2780 + * This function can be used to open a control session for an
2781 + * already created object; an object may have been declared in
2782 + * the DPL or by calling the dpsw_create() function.
2783 + * This function returns a unique authentication token,
2784 + * associated with the specific object ID and the specific MC
2785 + * portal; this token must be used in all subsequent commands for
2786 + * this specific object
2787 + *
2788 + * Return: '0' on Success; Error code otherwise.
2789 + */
2790 +int dpsw_open(struct fsl_mc_io *mc_io,
2791 + uint32_t cmd_flags,
2792 + int dpsw_id,
2793 + uint16_t *token);
2794 +
2795 +/**
2796 + * dpsw_close() - Close the control session of the object
2797 + * @mc_io: Pointer to MC portal's I/O object
2798 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
2799 + * @token: Token of DPSW object
2800 + *
2801 + * After this function is called, no further operations are
2802 + * allowed on the object without opening a new control session.
2803 + *
2804 + * Return: '0' on Success; Error code otherwise.
2805 + */
2806 +int dpsw_close(struct fsl_mc_io *mc_io,
2807 + uint32_t cmd_flags,
2808 + uint16_t token);
2809 +
2810 +/**
2811 + * DPSW options
2812 + */
2813 +
2814 +/**
2815 + * Disable flooding
2816 + */
2817 +#define DPSW_OPT_FLOODING_DIS 0x0000000000000001ULL
2818 +/**
2819 + * Disable Multicast
2820 + */
2821 +#define DPSW_OPT_MULTICAST_DIS 0x0000000000000004ULL
2822 +/**
2823 + * Support control interface
2824 + */
2825 +#define DPSW_OPT_CTRL_IF_DIS 0x0000000000000010ULL
2826 +/**
2827 + * Disable flooding metering
2828 + */
2829 +#define DPSW_OPT_FLOODING_METERING_DIS 0x0000000000000020ULL
2830 +/**
2831 + * Enable metering
2832 + */
2833 +#define DPSW_OPT_METERING_EN 0x0000000000000040ULL
2834 +
2835 +/**
2836 + * enum dpsw_component_type - component type of a bridge
2837 + * @DPSW_COMPONENT_TYPE_C_VLAN: A C-VLAN component of an
2838 + * enterprise VLAN bridge or of a Provider Bridge used
2839 + * to process C-tagged frames
2840 + * @DPSW_COMPONENT_TYPE_S_VLAN: An S-VLAN component of a
2841 + * Provider Bridge
2842 + *
2843 + */
2844 +enum dpsw_component_type {
2845 + DPSW_COMPONENT_TYPE_C_VLAN = 0,
2846 + DPSW_COMPONENT_TYPE_S_VLAN
2847 +};
2848 +
2849 +/**
2850 + * struct dpsw_cfg - DPSW configuration
2851 + * @num_ifs: Number of external and internal interfaces
2852 + * @adv: Advanced parameters; default is all zeros;
2853 + * use this structure to change default settings
2854 + */
2855 +struct dpsw_cfg {
2856 + uint16_t num_ifs;
2857 + /**
2858 + * struct adv - Advanced parameters
2859 + * @options: Enable/Disable DPSW features (bitmap)
2860 + * @max_vlans: Maximum Number of VLAN's; 0 - indicates default 16
2861 + * @max_meters_per_if: Number of meters per interface
2862 + * @max_fdbs: Maximum Number of FDB's; 0 - indicates default 16
2863 + * @max_fdb_entries: Number of FDB entries for default FDB table;
2864 + * 0 - indicates default 1024 entries.
2865 + * @fdb_aging_time: Default FDB aging time for default FDB table;
2866 + * 0 - indicates default 300 seconds
2867 + * @max_fdb_mc_groups: Number of multicast groups in each FDB table;
2868 + * 0 - indicates default 32
2869 + * @component_type: Indicates the component type of this bridge
2870 + */
2871 + struct {
2872 + uint64_t options;
2873 + uint16_t max_vlans;
2874 + uint8_t max_meters_per_if;
2875 + uint8_t max_fdbs;
2876 + uint16_t max_fdb_entries;
2877 + uint16_t fdb_aging_time;
2878 + uint16_t max_fdb_mc_groups;
2879 + enum dpsw_component_type component_type;
2880 + } adv;
2881 +};
2882 +
2883 +/**
2884 + * dpsw_create() - Create the DPSW object.
2885 + * @mc_io: Pointer to MC portal's I/O object
2886 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
2887 + * @cfg: Configuration structure
2888 + * @token: Returned token; use in subsequent API calls
2889 + *
2890 + * Create the DPSW object, allocate required resources and
2891 + * perform required initialization.
2892 + *
2893 + * The object can be created either by declaring it in the
2894 + * DPL file, or by calling this function.
2895 + *
2896 + * This function returns a unique authentication token,
2897 + * associated with the specific object ID and the specific MC
2898 + * portal; this token must be used in all subsequent calls to
2899 + * this specific object. For objects that are created using the
2900 + * DPL file, call dpsw_open() function to get an authentication
2901 + * token first
2902 + *
2903 + * Return: '0' on Success; Error code otherwise.
2904 + */
2905 +int dpsw_create(struct fsl_mc_io *mc_io,
2906 + uint32_t cmd_flags,
2907 + const struct dpsw_cfg *cfg,
2908 + uint16_t *token);
2909 +
2910 +/**
2911 + * dpsw_destroy() - Destroy the DPSW object and release all its resources.
2912 + * @mc_io: Pointer to MC portal's I/O object
2913 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
2914 + * @token: Token of DPSW object
2915 + *
2916 + * Return: '0' on Success; error code otherwise.
2917 + */
2918 +int dpsw_destroy(struct fsl_mc_io *mc_io,
2919 + uint32_t cmd_flags,
2920 + uint16_t token);
2921 +
2922 +/**
2923 + * dpsw_enable() - Enable DPSW functionality
2924 + * @mc_io: Pointer to MC portal's I/O object
2925 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
2926 + * @token: Token of DPSW object
2927 + *
2928 + * Return: Completion status. '0' on Success; Error code otherwise.
2929 + */
2930 +int dpsw_enable(struct fsl_mc_io *mc_io,
2931 + uint32_t cmd_flags,
2932 + uint16_t token);
2933 +
2934 +/**
2935 + * dpsw_disable() - Disable DPSW functionality
2936 + * @mc_io: Pointer to MC portal's I/O object
2937 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
2938 + * @token: Token of DPSW object
2939 + *
2940 + * Return: Completion status. '0' on Success; Error code otherwise.
2941 + */
2942 +int dpsw_disable(struct fsl_mc_io *mc_io,
2943 + uint32_t cmd_flags,
2944 + uint16_t token);
2945 +
2946 +/**
2947 + * dpsw_is_enabled() - Check if the DPSW is enabled
2948 + *
2949 + * @mc_io: Pointer to MC portal's I/O object
2950 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
2951 + * @token: Token of DPSW object
2952 + * @en: Returns '1' if object is enabled; '0' otherwise
2953 + *
2954 + * Return: '0' on Success; Error code otherwise
2955 + */
2956 +int dpsw_is_enabled(struct fsl_mc_io *mc_io,
2957 + uint32_t cmd_flags,
2958 + uint16_t token,
2959 + int *en);
2960 +
2961 +/**
2962 + * dpsw_reset() - Reset the DPSW, returns the object to initial state.
2963 + * @mc_io: Pointer to MC portal's I/O object
2964 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
2965 + * @token: Token of DPSW object
2966 + *
2967 + * Return: '0' on Success; Error code otherwise.
2968 + */
2969 +int dpsw_reset(struct fsl_mc_io *mc_io,
2970 + uint32_t cmd_flags,
2971 + uint16_t token);
2972 +
2973 +/**
2974 + * DPSW IRQ Index and Events
2975 + */
2976 +
2977 +#define DPSW_IRQ_INDEX_IF 0x0000
2978 +#define DPSW_IRQ_INDEX_L2SW 0x0001
2979 +
2980 +/**
2981 + * IRQ event - Indicates that the link state changed
2982 + */
2983 +#define DPSW_IRQ_EVENT_LINK_CHANGED 0x0001
2984 +
2985 +/**
2986 + * struct dpsw_irq_cfg - IRQ configuration
2987 + * @addr: Address that must be written to signal a message-based interrupt
2988 + * @val: Value to write into irq_addr address
2989 + * @irq_num: A user defined number associated with this IRQ
2990 + */
2991 +struct dpsw_irq_cfg {
2992 + uint64_t addr;
2993 + uint32_t val;
2994 + int irq_num;
2995 +};
2996 +
2997 +/**
2998 + * dpsw_set_irq() - Set IRQ information for the DPSW to trigger an interrupt.
2999 + * @mc_io: Pointer to MC portal's I/O object
3000 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
3001 + * @token: Token of DPSW object
3002 + * @irq_index: Identifies the interrupt index to configure
3003 + * @irq_cfg: IRQ configuration
3004 + *
3005 + * Return: '0' on Success; Error code otherwise.
3006 + */
3007 +int dpsw_set_irq(struct fsl_mc_io *mc_io,
3008 + uint32_t cmd_flags,
3009 + uint16_t token,
3010 + uint8_t irq_index,
3011 + struct dpsw_irq_cfg *irq_cfg);
3012 +
3013 +/**
3014 + * dpsw_get_irq() - Get IRQ information from the DPSW
3015 + *
3016 + * @mc_io: Pointer to MC portal's I/O object
3017 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
3018 + * @token: Token of DPSW object
3019 + * @irq_index: The interrupt index to configure
3020 + * @type: Interrupt type: 0 represents message interrupt
3021 + * type (both irq_addr and irq_val are valid)
3022 + * @irq_cfg: IRQ attributes
3023 + *
3024 + * Return: '0' on Success; Error code otherwise.
3025 + */
3026 +int dpsw_get_irq(struct fsl_mc_io *mc_io,
3027 + uint32_t cmd_flags,
3028 + uint16_t token,
3029 + uint8_t irq_index,
3030 + int *type,
3031 + struct dpsw_irq_cfg *irq_cfg);
3032 +
3033 +/**
3034 + * dpsw_set_irq_enable() - Set overall interrupt state.
3035 + * @mc_io: Pointer to MC portal's I/O object
3036 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
3037 + * @token: Token of DPCI object
3038 + * @irq_index: The interrupt index to configure
3039 + * @en: Interrupt state - enable = 1, disable = 0
3040 + *
3041 + * Allows GPP software to control when interrupts are generated.
3042 + * Each interrupt can have up to 32 causes. The enable/disable control's the
3043 + * overall interrupt state. if the interrupt is disabled no causes will cause
3044 + * an interrupt
3045 + *
3046 + * Return: '0' on Success; Error code otherwise.
3047 + */
3048 +int dpsw_set_irq_enable(struct fsl_mc_io *mc_io,
3049 + uint32_t cmd_flags,
3050 + uint16_t token,
3051 + uint8_t irq_index,
3052 + uint8_t en);
3053 +
3054 +/**
3055 + * dpsw_get_irq_enable() - Get overall interrupt state
3056 + * @mc_io: Pointer to MC portal's I/O object
3057 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
3058 + * @token: Token of DPSW object
3059 + * @irq_index: The interrupt index to configure
3060 + * @en: Returned Interrupt state - enable = 1, disable = 0
3061 + *
3062 + * Return: '0' on Success; Error code otherwise.
3063 + */
3064 +int dpsw_get_irq_enable(struct fsl_mc_io *mc_io,
3065 + uint32_t cmd_flags,
3066 + uint16_t token,
3067 + uint8_t irq_index,
3068 + uint8_t *en);
3069 +
3070 +/**
3071 + * dpsw_set_irq_mask() - Set interrupt mask.
3072 + * @mc_io: Pointer to MC portal's I/O object
3073 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
3074 + * @token: Token of DPCI object
3075 + * @irq_index: The interrupt index to configure
3076 + * @mask: event mask to trigger interrupt;
3077 + * each bit:
3078 + * 0 = ignore event
3079 + * 1 = consider event for asserting IRQ
3080 + *
3081 + * Every interrupt can have up to 32 causes and the interrupt model supports
3082 + * masking/unmasking each cause independently
3083 + *
3084 + * Return: '0' on Success; Error code otherwise.
3085 + */
3086 +int dpsw_set_irq_mask(struct fsl_mc_io *mc_io,
3087 + uint32_t cmd_flags,
3088 + uint16_t token,
3089 + uint8_t irq_index,
3090 + uint32_t mask);
3091 +
3092 +/**
3093 + * dpsw_get_irq_mask() - Get interrupt mask.
3094 + * @mc_io: Pointer to MC portal's I/O object
3095 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
3096 + * @token: Token of DPSW object
3097 + * @irq_index: The interrupt index to configure
3098 + * @mask: Returned event mask to trigger interrupt
3099 + *
3100 + * Every interrupt can have up to 32 causes and the interrupt model supports
3101 + * masking/unmasking each cause independently
3102 + *
3103 + * Return: '0' on Success; Error code otherwise.
3104 + */
3105 +int dpsw_get_irq_mask(struct fsl_mc_io *mc_io,
3106 + uint32_t cmd_flags,
3107 + uint16_t token,
3108 + uint8_t irq_index,
3109 + uint32_t *mask);
3110 +
3111 +/**
3112 + * dpsw_get_irq_status() - Get the current status of any pending interrupts
3113 + * @mc_io: Pointer to MC portal's I/O object
3114 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
3115 + * @token: Token of DPSW object
3116 + * @irq_index: The interrupt index to configure
3117 + * @status: Returned interrupts status - one bit per cause:
3118 + * 0 = no interrupt pending
3119 + * 1 = interrupt pending
3120 + *
3121 + * Return: '0' on Success; Error code otherwise.
3122 + */
3123 +int dpsw_get_irq_status(struct fsl_mc_io *mc_io,
3124 + uint32_t cmd_flags,
3125 + uint16_t token,
3126 + uint8_t irq_index,
3127 + uint32_t *status);
3128 +
3129 +/**
3130 + * dpsw_clear_irq_status() - Clear a pending interrupt's status
3131 + * @mc_io: Pointer to MC portal's I/O object
3132 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
3133 + * @token: Token of DPCI object
3134 + * @irq_index: The interrupt index to configure
3135 + * @status: bits to clear (W1C) - one bit per cause:
3136 + * 0 = don't change
3137 + * 1 = clear status bit
3138 + *
3139 + * Return: '0' on Success; Error code otherwise.
3140 + */
3141 +int dpsw_clear_irq_status(struct fsl_mc_io *mc_io,
3142 + uint32_t cmd_flags,
3143 + uint16_t token,
3144 + uint8_t irq_index,
3145 + uint32_t status);
3146 +/**
3147 + * struct dpsw_attr - Structure representing DPSW attributes
3148 + * @id: DPSW object ID
3149 + * @version: DPSW version
3150 + * @options: Enable/Disable DPSW features
3151 + * @max_vlans: Maximum Number of VLANs
3152 + * @max_meters_per_if: Number of meters per interface
3153 + * @max_fdbs: Maximum Number of FDBs
3154 + * @max_fdb_entries: Number of FDB entries for default FDB table;
3155 + * 0 - indicates default 1024 entries.
3156 + * @fdb_aging_time: Default FDB aging time for default FDB table;
3157 + * 0 - indicates default 300 seconds
3158 + * @max_fdb_mc_groups: Number of multicast groups in each FDB table;
3159 + * 0 - indicates default 32
3160 + * @mem_size: DPSW frame storage memory size
3161 + * @num_ifs: Number of interfaces
3162 + * @num_vlans: Current number of VLANs
3163 + * @num_fdbs: Current number of FDBs
3164 + * @component_type: Component type of this bridge
3165 + */
3166 +struct dpsw_attr {
3167 + int id;
3168 + /**
3169 + * struct version - DPSW version
3170 + * @major: DPSW major version
3171 + * @minor: DPSW minor version
3172 + */
3173 + struct {
3174 + uint16_t major;
3175 + uint16_t minor;
3176 + } version;
3177 + uint64_t options;
3178 + uint16_t max_vlans;
3179 + uint8_t max_meters_per_if;
3180 + uint8_t max_fdbs;
3181 + uint16_t max_fdb_entries;
3182 + uint16_t fdb_aging_time;
3183 + uint16_t max_fdb_mc_groups;
3184 + uint16_t num_ifs;
3185 + uint16_t mem_size;
3186 + uint16_t num_vlans;
3187 + uint8_t num_fdbs;
3188 + enum dpsw_component_type component_type;
3189 +};
3190 +
3191 +/**
3192 + * dpsw_get_attributes() - Retrieve DPSW attributes
3193 + * @mc_io: Pointer to MC portal's I/O object
3194 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
3195 + * @token: Token of DPSW object
3196 + * @attr: Returned DPSW attributes
3197 + *
3198 + * Return: Completion status. '0' on Success; Error code otherwise.
3199 + */
3200 +int dpsw_get_attributes(struct fsl_mc_io *mc_io,
3201 + uint32_t cmd_flags,
3202 + uint16_t token,
3203 + struct dpsw_attr *attr);
3204 +
3205 +/**
3206 + * dpsw_set_reflection_if() - Set target interface for reflected interfaces.
3207 + * @mc_io: Pointer to MC portal's I/O object
3208 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
3209 + * @token: Token of DPSW object
3210 + * @if_id: Interface Id
3211 + *
3212 + * Only one reflection receive interface is allowed per switch
3213 + *
3214 + * Return: Completion status. '0' on Success; Error code otherwise.
3215 + */
3216 +int dpsw_set_reflection_if(struct fsl_mc_io *mc_io,
3217 + uint32_t cmd_flags,
3218 + uint16_t token,
3219 + uint16_t if_id);
3220 +
3221 +/**
3222 + * enum dpsw_action - Action selection for special/control frames
3223 + * @DPSW_ACTION_DROP: Drop frame
3224 + * @DPSW_ACTION_REDIRECT: Redirect frame to control port
3225 + */
3226 +enum dpsw_action {
3227 + DPSW_ACTION_DROP = 0,
3228 + DPSW_ACTION_REDIRECT = 1
3229 +};
3230 +
3231 +/**
3232 + * Enable auto-negotiation
3233 + */
3234 +#define DPSW_LINK_OPT_AUTONEG 0x0000000000000001ULL
3235 +/**
3236 + * Enable half-duplex mode
3237 + */
3238 +#define DPSW_LINK_OPT_HALF_DUPLEX 0x0000000000000002ULL
3239 +/**
3240 + * Enable pause frames
3241 + */
3242 +#define DPSW_LINK_OPT_PAUSE 0x0000000000000004ULL
3243 +/**
3244 + * Enable a-symmetric pause frames
3245 + */
3246 +#define DPSW_LINK_OPT_ASYM_PAUSE 0x0000000000000008ULL
3247 +
3248 +/**
3249 + * struct dpsw_link_cfg - Structure representing DPSW link configuration
3250 + * @rate: Rate
3251 + * @options: Mask of available options; use 'DPSW_LINK_OPT_<X>' values
3252 + */
3253 +struct dpsw_link_cfg {
3254 + uint32_t rate;
3255 + uint64_t options;
3256 +};
3257 +
3258 +/**
3259 + * dpsw_if_set_link_cfg() - set the link configuration.
3260 + * @mc_io: Pointer to MC portal's I/O object
3261 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
3262 + * @token: Token of DPSW object
3263 + * @if_id: interface id
3264 + * @cfg: Link configuration
3265 + *
3266 + * Return: '0' on Success; Error code otherwise.
3267 + */
3268 +int dpsw_if_set_link_cfg(struct fsl_mc_io *mc_io,
3269 + uint32_t cmd_flags,
3270 + uint16_t token,
3271 + uint16_t if_id,
3272 + struct dpsw_link_cfg *cfg);
3273 +/**
3274 + * struct dpsw_link_state - Structure representing DPSW link state
3275 + * @rate: Rate
3276 + * @options: Mask of available options; use 'DPSW_LINK_OPT_<X>' values
3277 + * @up: 0 - covers two cases: down and disconnected, 1 - up
3278 + */
3279 +struct dpsw_link_state {
3280 + uint32_t rate;
3281 + uint64_t options;
3282 + int up;
3283 +};
3284 +
3285 +/**
3286 + * dpsw_if_get_link_state - Return the link state
3287 + * @mc_io: Pointer to MC portal's I/O object
3288 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
3289 + * @token: Token of DPSW object
3290 + * @if_id: interface id
3291 + * @state: link state 1 - linkup, 0 - link down or disconnected
3292 + *
3293 + * @returns '0' on Success; Error code otherwise.
3294 + */
3295 +int dpsw_if_get_link_state(struct fsl_mc_io *mc_io,
3296 + uint32_t cmd_flags,
3297 + uint16_t token,
3298 + uint16_t if_id,
3299 + struct dpsw_link_state *state);
3300 +
3301 +/**
3302 + * dpsw_if_set_flooding() - Enable Disable flooding for particular interface
3303 + * @mc_io: Pointer to MC portal's I/O object
3304 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
3305 + * @token: Token of DPSW object
3306 + * @if_id: Interface Identifier
3307 + * @en: 1 - enable, 0 - disable
3308 + *
3309 + * Return: Completion status. '0' on Success; Error code otherwise.
3310 + */
3311 +int dpsw_if_set_flooding(struct fsl_mc_io *mc_io,
3312 + uint32_t cmd_flags,
3313 + uint16_t token,
3314 + uint16_t if_id,
3315 + int en);
3316 +
3317 +/**
3318 + * dpsw_if_set_broadcast() - Enable/disable broadcast for particular interface
3319 + * @mc_io: Pointer to MC portal's I/O object
3320 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
3321 + * @token: Token of DPSW object
3322 + * @if_id: Interface Identifier
3323 + * @en: 1 - enable, 0 - disable
3324 + *
3325 + * Return: Completion status. '0' on Success; Error code otherwise.
3326 + */
3327 +int dpsw_if_set_broadcast(struct fsl_mc_io *mc_io,
3328 + uint32_t cmd_flags,
3329 + uint16_t token,
3330 + uint16_t if_id,
3331 + int en);
3332 +
3333 +/**
3334 + * dpsw_if_set_multicast() - Enable/disable multicast for particular interface
3335 + * @mc_io: Pointer to MC portal's I/O object
3336 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
3337 + * @token: Token of DPSW object
3338 + * @if_id: Interface Identifier
3339 + * @en: 1 - enable, 0 - disable
3340 + *
3341 + * Return: Completion status. '0' on Success; Error code otherwise.
3342 + */
3343 +int dpsw_if_set_multicast(struct fsl_mc_io *mc_io,
3344 + uint32_t cmd_flags,
3345 + uint16_t token,
3346 + uint16_t if_id,
3347 + int en);
3348 +
3349 +/**
3350 + * struct dpsw_tci_cfg - Tag Contorl Information (TCI) configuration
3351 + * @pcp: Priority Code Point (PCP): a 3-bit field which refers
3352 + * to the IEEE 802.1p priority
3353 + * @dei: Drop Eligible Indicator (DEI): a 1-bit field. May be used
3354 + * separately or in conjunction with PCP to indicate frames
3355 + * eligible to be dropped in the presence of congestion
3356 + * @vlan_id: VLAN Identifier (VID): a 12-bit field specifying the VLAN
3357 + * to which the frame belongs. The hexadecimal values
3358 + * of 0x000 and 0xFFF are reserved;
3359 + * all other values may be used as VLAN identifiers,
3360 + * allowing up to 4,094 VLANs
3361 + */
3362 +struct dpsw_tci_cfg {
3363 + uint8_t pcp;
3364 + uint8_t dei;
3365 + uint16_t vlan_id;
3366 +};
3367 +
3368 +/**
3369 + * dpsw_if_set_tci() - Set default VLAN Tag Control Information (TCI)
3370 + * @mc_io: Pointer to MC portal's I/O object
3371 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
3372 + * @token: Token of DPSW object
3373 + * @if_id: Interface Identifier
3374 + * @cfg: Tag Control Information Configuration
3375 + *
3376 + * Return: Completion status. '0' on Success; Error code otherwise.
3377 + */
3378 +int dpsw_if_set_tci(struct fsl_mc_io *mc_io,
3379 + uint32_t cmd_flags,
3380 + uint16_t token,
3381 + uint16_t if_id,
3382 + const struct dpsw_tci_cfg *cfg);
3383 +
3384 +/**
3385 + * dpsw_if_get_tci() - Get default VLAN Tag Control Information (TCI)
3386 + * @mc_io: Pointer to MC portal's I/O object
3387 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
3388 + * @token: Token of DPSW object
3389 + * @if_id: Interface Identifier
3390 + * @cfg: Tag Control Information Configuration
3391 + *
3392 + * Return: Completion status. '0' on Success; Error code otherwise.
3393 + */
3394 +int dpsw_if_get_tci(struct fsl_mc_io *mc_io,
3395 + uint32_t cmd_flags,
3396 + uint16_t token,
3397 + uint16_t if_id,
3398 + struct dpsw_tci_cfg *cfg);
3399 +
3400 +/**
3401 + * enum dpsw_stp_state - Spanning Tree Protocol (STP) states
3402 + * @DPSW_STP_STATE_BLOCKING: Blocking state
3403 + * @DPSW_STP_STATE_LISTENING: Listening state
3404 + * @DPSW_STP_STATE_LEARNING: Learning state
3405 + * @DPSW_STP_STATE_FORWARDING: Forwarding state
3406 + *
3407 + */
3408 +enum dpsw_stp_state {
3409 + DPSW_STP_STATE_BLOCKING = 0,
3410 + DPSW_STP_STATE_LISTENING = 1,
3411 + DPSW_STP_STATE_LEARNING = 2,
3412 + DPSW_STP_STATE_FORWARDING = 3
3413 +};
3414 +
3415 +/**
3416 + * struct dpsw_stp_cfg - Spanning Tree Protocol (STP) Configuration
3417 + * @vlan_id: VLAN ID STP state
3418 + * @state: STP state
3419 + */
3420 +struct dpsw_stp_cfg {
3421 + uint16_t vlan_id;
3422 + enum dpsw_stp_state state;
3423 +};
3424 +
3425 +/**
3426 + * dpsw_if_set_stp() - Function sets Spanning Tree Protocol (STP) state.
3427 + * @mc_io: Pointer to MC portal's I/O object
3428 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
3429 + * @token: Token of DPSW object
3430 + * @if_id: Interface Identifier
3431 + * @cfg: STP State configuration parameters
3432 + *
3433 + * The following STP states are supported -
3434 + * blocking, listening, learning, forwarding and disabled.
3435 + *
3436 + * Return: Completion status. '0' on Success; Error code otherwise.
3437 + */
3438 +int dpsw_if_set_stp(struct fsl_mc_io *mc_io,
3439 + uint32_t cmd_flags,
3440 + uint16_t token,
3441 + uint16_t if_id,
3442 + const struct dpsw_stp_cfg *cfg);
3443 +
3444 +/**
3445 + * enum dpsw_accepted_frames - Types of frames to accept
3446 + * @DPSW_ADMIT_ALL: The device accepts VLAN tagged, untagged and
3447 + * priority tagged frames
3448 + * @DPSW_ADMIT_ONLY_VLAN_TAGGED: The device discards untagged frames or
3449 + * Priority-Tagged frames received on this interface.
3450 + *
3451 + */
3452 +enum dpsw_accepted_frames {
3453 + DPSW_ADMIT_ALL = 1,
3454 + DPSW_ADMIT_ONLY_VLAN_TAGGED = 3
3455 +};
3456 +
3457 +/**
3458 + * struct dpsw_accepted_frames_cfg - Types of frames to accept configuration
3459 + * @type: Defines ingress accepted frames
3460 + * @unaccept_act: When a frame is not accepted, it may be discarded or
3461 + * redirected to control interface depending on this mode
3462 + */
3463 +struct dpsw_accepted_frames_cfg {
3464 + enum dpsw_accepted_frames type;
3465 + enum dpsw_action unaccept_act;
3466 +};
3467 +
3468 +/**
3469 + * dpsw_if_set_accepted_frames()
3470 + * @mc_io: Pointer to MC portal's I/O object
3471 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
3472 + * @token: Token of DPSW object
3473 + * @if_id: Interface Identifier
3474 + * @cfg: Frame types configuration
3475 + *
3476 + * When is admit_only_vlan_tagged- the device will discard untagged
3477 + * frames or Priority-Tagged frames received on this interface.
3478 + * When admit_only_untagged- untagged frames or Priority-Tagged
3479 + * frames received on this interface will be accepted and assigned
3480 + * to a VID based on the PVID and VID Set for this interface.
3481 + * When admit_all - the device will accept VLAN tagged, untagged
3482 + * and priority tagged frames.
3483 + * The default is admit_all
3484 + *
3485 + * Return: Completion status. '0' on Success; Error code otherwise.
3486 + */
3487 +int dpsw_if_set_accepted_frames(struct fsl_mc_io *mc_io,
3488 + uint32_t cmd_flags,
3489 + uint16_t token,
3490 + uint16_t if_id,
3491 + const struct dpsw_accepted_frames_cfg *cfg);
3492 +
3493 +/**
3494 + * dpsw_if_set_accept_all_vlan()
3495 + * @mc_io: Pointer to MC portal's I/O object
3496 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
3497 + * @token: Token of DPSW object
3498 + * @if_id: Interface Identifier
3499 + * @accept_all: Accept or drop frames having different VLAN
3500 + *
3501 + * When this is accept (FALSE), the device will discard incoming
3502 + * frames for VLANs that do not include this interface in its
3503 + * Member set. When accept (TRUE), the interface will accept all incoming frames
3504 + *
3505 + * Return: Completion status. '0' on Success; Error code otherwise.
3506 + */
3507 +int dpsw_if_set_accept_all_vlan(struct fsl_mc_io *mc_io,
3508 + uint32_t cmd_flags,
3509 + uint16_t token,
3510 + uint16_t if_id,
3511 + int accept_all);
3512 +
3513 +/**
3514 + * enum dpsw_counter - Counters types
3515 + * @DPSW_CNT_ING_FRAME: Counts ingress frames
3516 + * @DPSW_CNT_ING_BYTE: Counts ingress bytes
3517 + * @DPSW_CNT_ING_FLTR_FRAME: Counts filtered ingress frames
3518 + * @DPSW_CNT_ING_FRAME_DISCARD: Counts discarded ingress frame
3519 + * @DPSW_CNT_ING_MCAST_FRAME: Counts ingress multicast frames
3520 + * @DPSW_CNT_ING_MCAST_BYTE: Counts ingress multicast bytes
3521 + * @DPSW_CNT_ING_BCAST_FRAME: Counts ingress broadcast frames
3522 + * @DPSW_CNT_ING_BCAST_BYTES: Counts ingress broadcast bytes
3523 + * @DPSW_CNT_EGR_FRAME: Counts egress frames
3524 + * @DPSW_CNT_EGR_BYTE: Counts eEgress bytes
3525 + * @DPSW_CNT_EGR_FRAME_DISCARD: Counts discarded egress frames
3526 + * @DPSW_CNT_EGR_STP_FRAME_DISCARD: Counts egress STP discarded frames
3527 + */
3528 +enum dpsw_counter {
3529 + DPSW_CNT_ING_FRAME = 0x0,
3530 + DPSW_CNT_ING_BYTE = 0x1,
3531 + DPSW_CNT_ING_FLTR_FRAME = 0x2,
3532 + DPSW_CNT_ING_FRAME_DISCARD = 0x3,
3533 + DPSW_CNT_ING_MCAST_FRAME = 0x4,
3534 + DPSW_CNT_ING_MCAST_BYTE = 0x5,
3535 + DPSW_CNT_ING_BCAST_FRAME = 0x6,
3536 + DPSW_CNT_ING_BCAST_BYTES = 0x7,
3537 + DPSW_CNT_EGR_FRAME = 0x8,
3538 + DPSW_CNT_EGR_BYTE = 0x9,
3539 + DPSW_CNT_EGR_FRAME_DISCARD = 0xa,
3540 + DPSW_CNT_EGR_STP_FRAME_DISCARD = 0xb
3541 +};
3542 +
3543 +/**
3544 + * dpsw_if_get_counter() - Get specific counter of particular interface
3545 + * @mc_io: Pointer to MC portal's I/O object
3546 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
3547 + * @token: Token of DPSW object
3548 + * @if_id: Interface Identifier
3549 + * @type: Counter type
3550 + * @counter: return value
3551 + *
3552 + * Return: Completion status. '0' on Success; Error code otherwise.
3553 + */
3554 +int dpsw_if_get_counter(struct fsl_mc_io *mc_io,
3555 + uint32_t cmd_flags,
3556 + uint16_t token,
3557 + uint16_t if_id,
3558 + enum dpsw_counter type,
3559 + uint64_t *counter);
3560 +
3561 +/**
3562 + * dpsw_if_set_counter() - Set specific counter of particular interface
3563 + * @mc_io: Pointer to MC portal's I/O object
3564 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
3565 + * @token: Token of DPSW object
3566 + * @if_id: Interface Identifier
3567 + * @type: Counter type
3568 + * @counter: New counter value
3569 + *
3570 + * Return: Completion status. '0' on Success; Error code otherwise.
3571 + */
3572 +int dpsw_if_set_counter(struct fsl_mc_io *mc_io,
3573 + uint32_t cmd_flags,
3574 + uint16_t token,
3575 + uint16_t if_id,
3576 + enum dpsw_counter type,
3577 + uint64_t counter);
3578 +
3579 +/**
3580 + * Maximum number of TC
3581 + */
3582 +#define DPSW_MAX_TC 8
3583 +
3584 +/**
3585 + * enum dpsw_priority_selector - User priority
3586 + * @DPSW_UP_PCP: Priority Code Point (PCP): a 3-bit field which
3587 + * refers to the IEEE 802.1p priority.
3588 + * @DPSW_UP_DSCP: Differentiated services Code Point (DSCP): 6 bit
3589 + * field from IP header
3590 + *
3591 + */
3592 +enum dpsw_priority_selector {
3593 + DPSW_UP_PCP = 0,
3594 + DPSW_UP_DSCP = 1
3595 +};
3596 +
3597 +/**
3598 + * enum dpsw_schedule_mode - Traffic classes scheduling
3599 + * @DPSW_SCHED_STRICT_PRIORITY: schedule strict priority
3600 + * @DPSW_SCHED_WEIGHTED: schedule based on token bucket created algorithm
3601 + */
3602 +enum dpsw_schedule_mode {
3603 + DPSW_SCHED_STRICT_PRIORITY,
3604 + DPSW_SCHED_WEIGHTED
3605 +};
3606 +
3607 +/**
3608 + * struct dpsw_tx_schedule_cfg - traffic class configuration
3609 + * @mode: Strict or weight-based scheduling
3610 + * @delta_bandwidth: weighted Bandwidth in range from 100 to 10000
3611 + */
3612 +struct dpsw_tx_schedule_cfg {
3613 + enum dpsw_schedule_mode mode;
3614 + uint16_t delta_bandwidth;
3615 +};
3616 +
3617 +/**
3618 + * struct dpsw_tx_selection_cfg - Mapping user priority into traffic
3619 + * class configuration
3620 + * @priority_selector: Source for user priority regeneration
3621 + * @tc_id: The Regenerated User priority that the incoming
3622 + * User Priority is mapped to for this interface
3623 + * @tc_sched: Traffic classes configuration
3624 + */
3625 +struct dpsw_tx_selection_cfg {
3626 + enum dpsw_priority_selector priority_selector;
3627 + uint8_t tc_id[DPSW_MAX_PRIORITIES];
3628 + struct dpsw_tx_schedule_cfg tc_sched[DPSW_MAX_TC];
3629 +};
3630 +
3631 +/**
3632 + * dpsw_if_set_tx_selection() - Function is used for mapping variety
3633 + * of frame fields
3634 + * @mc_io: Pointer to MC portal's I/O object
3635 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
3636 + * @token: Token of DPSW object
3637 + * @if_id: Interface Identifier
3638 + * @cfg: Traffic class mapping configuration
3639 + *
3640 + * Function is used for mapping variety of frame fields (DSCP, PCP)
3641 + * to Traffic Class. Traffic class is a number
3642 + * in the range from 0 to 7
3643 + *
3644 + * Return: Completion status. '0' on Success; Error code otherwise.
3645 + */
3646 +int dpsw_if_set_tx_selection(struct fsl_mc_io *mc_io,
3647 + uint32_t cmd_flags,
3648 + uint16_t token,
3649 + uint16_t if_id,
3650 + const struct dpsw_tx_selection_cfg *cfg);
3651 +
3652 +/**
3653 + * enum dpsw_reflection_filter - Filter type for frames to reflect
3654 + * @DPSW_REFLECTION_FILTER_INGRESS_ALL: Reflect all frames
3655 + * @DPSW_REFLECTION_FILTER_INGRESS_VLAN: Reflect only frames belong to
3656 + * particular VLAN defined by vid parameter
3657 + *
3658 + */
3659 +enum dpsw_reflection_filter {
3660 + DPSW_REFLECTION_FILTER_INGRESS_ALL = 0,
3661 + DPSW_REFLECTION_FILTER_INGRESS_VLAN = 1
3662 +};
3663 +
3664 +/**
3665 + * struct dpsw_reflection_cfg - Structure representing reflection information
3666 + * @filter: Filter type for frames to reflect
3667 + * @vlan_id: Vlan Id to reflect; valid only when filter type is
3668 + * DPSW_INGRESS_VLAN
3669 + */
3670 +struct dpsw_reflection_cfg {
3671 + enum dpsw_reflection_filter filter;
3672 + uint16_t vlan_id;
3673 +};
3674 +
3675 +/**
3676 + * dpsw_if_add_reflection() - Identify interface to be reflected or mirrored
3677 + * @mc_io: Pointer to MC portal's I/O object
3678 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
3679 + * @token: Token of DPSW object
3680 + * @if_id: Interface Identifier
3681 + * @cfg: Reflection configuration
3682 + *
3683 + * Return: Completion status. '0' on Success; Error code otherwise.
3684 + */
3685 +int dpsw_if_add_reflection(struct fsl_mc_io *mc_io,
3686 + uint32_t cmd_flags,
3687 + uint16_t token,
3688 + uint16_t if_id,
3689 + const struct dpsw_reflection_cfg *cfg);
3690 +
3691 +/**
3692 + * dpsw_if_remove_reflection() - Remove interface to be reflected or mirrored
3693 + * @mc_io: Pointer to MC portal's I/O object
3694 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
3695 + * @token: Token of DPSW object
3696 + * @if_id: Interface Identifier
3697 + * @cfg: Reflection configuration
3698 + *
3699 + * Return: Completion status. '0' on Success; Error code otherwise.
3700 + */
3701 +int dpsw_if_remove_reflection(struct fsl_mc_io *mc_io,
3702 + uint32_t cmd_flags,
3703 + uint16_t token,
3704 + uint16_t if_id,
3705 + const struct dpsw_reflection_cfg *cfg);
3706 +
3707 +/**
3708 + * enum dpsw_metering_mode - Metering modes
3709 + * @DPSW_METERING_MODE_NONE: metering disabled
3710 + * @DPSW_METERING_MODE_RFC2698: RFC 2698
3711 + * @DPSW_METERING_MODE_RFC4115: RFC 4115
3712 + */
3713 +enum dpsw_metering_mode {
3714 + DPSW_METERING_MODE_NONE = 0,
3715 + DPSW_METERING_MODE_RFC2698,
3716 + DPSW_METERING_MODE_RFC4115
3717 +};
3718 +
3719 +/**
3720 + * enum dpsw_metering_unit - Metering count
3721 + * @DPSW_METERING_UNIT_BYTES: count bytes
3722 + * @DPSW_METERING_UNIT_FRAMES: count frames
3723 + */
3724 +enum dpsw_metering_unit {
3725 + DPSW_METERING_UNIT_BYTES = 0,
3726 + DPSW_METERING_UNIT_FRAMES
3727 +};
3728 +
3729 +/**
3730 + * struct dpsw_metering_cfg - Metering configuration
3731 + * @mode: metering modes
3732 + * @units: Bytes or frame units
3733 + * @cir: Committed information rate (CIR) in Kbits/s
3734 + * @eir: Peak information rate (PIR) Kbit/s rfc2698
3735 + * Excess information rate (EIR) Kbit/s rfc4115
3736 + * @cbs: Committed burst size (CBS) in bytes
3737 + * @ebs: Peak burst size (PBS) in bytes for rfc2698
3738 + * Excess bust size (EBS) in bytes rfc4115
3739 + *
3740 + */
3741 +struct dpsw_metering_cfg {
3742 + enum dpsw_metering_mode mode;
3743 + enum dpsw_metering_unit units;
3744 + uint32_t cir;
3745 + uint32_t eir;
3746 + uint32_t cbs;
3747 + uint32_t ebs;
3748 +};
3749 +
3750 +/**
3751 + * dpsw_if_set_flooding_metering() - Set flooding metering
3752 + * @mc_io: Pointer to MC portal's I/O object
3753 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
3754 + * @token: Token of DPSW object
3755 + * @if_id: Interface Identifier
3756 + * @cfg: Metering parameters
3757 + *
3758 + * Return: Completion status. '0' on Success; Error code otherwise.
3759 + */
3760 +int dpsw_if_set_flooding_metering(struct fsl_mc_io *mc_io,
3761 + uint32_t cmd_flags,
3762 + uint16_t token,
3763 + uint16_t if_id,
3764 + const struct dpsw_metering_cfg *cfg);
3765 +
3766 +/**
3767 + * dpsw_if_set_metering() - Set interface metering for flooding
3768 + * @mc_io: Pointer to MC portal's I/O object
3769 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
3770 + * @token: Token of DPSW object
3771 + * @if_id: Interface Identifier
3772 + * @tc_id: Traffic class ID
3773 + * @cfg: Metering parameters
3774 + *
3775 + * Return: Completion status. '0' on Success; Error code otherwise.
3776 + */
3777 +int dpsw_if_set_metering(struct fsl_mc_io *mc_io,
3778 + uint32_t cmd_flags,
3779 + uint16_t token,
3780 + uint16_t if_id,
3781 + uint8_t tc_id,
3782 + const struct dpsw_metering_cfg *cfg);
3783 +
3784 +/**
3785 + * enum dpsw_early_drop_unit - DPSW early drop unit
3786 + * @DPSW_EARLY_DROP_UNIT_BYTE: count bytes
3787 + * @DPSW_EARLY_DROP_UNIT_FRAMES: count frames
3788 + */
3789 +enum dpsw_early_drop_unit {
3790 + DPSW_EARLY_DROP_UNIT_BYTE = 0,
3791 + DPSW_EARLY_DROP_UNIT_FRAMES
3792 +};
3793 +
3794 +/**
3795 + * enum dpsw_early_drop_mode - DPSW early drop mode
3796 + * @DPSW_EARLY_DROP_MODE_NONE: early drop is disabled
3797 + * @DPSW_EARLY_DROP_MODE_TAIL: early drop in taildrop mode
3798 + * @DPSW_EARLY_DROP_MODE_WRED: early drop in WRED mode
3799 + */
3800 +enum dpsw_early_drop_mode {
3801 + DPSW_EARLY_DROP_MODE_NONE = 0,
3802 + DPSW_EARLY_DROP_MODE_TAIL,
3803 + DPSW_EARLY_DROP_MODE_WRED
3804 +};
3805 +
3806 +/**
3807 + * struct dpsw_wred_cfg - WRED configuration
3808 + * @max_threshold: maximum threshold that packets may be discarded. Above this
3809 + * threshold all packets are discarded; must be less than 2^39;
3810 + * approximated to be expressed as (x+256)*2^(y-1) due to HW
3811 + * implementation.
3812 + * @min_threshold: minimum threshold that packets may be discarded at
3813 + * @drop_probability: probability that a packet will be discarded (1-100,
3814 + * associated with the maximum threshold)
3815 + */
3816 +struct dpsw_wred_cfg {
3817 + uint64_t min_threshold;
3818 + uint64_t max_threshold;
3819 + uint8_t drop_probability;
3820 +};
3821 +
3822 +/**
3823 + * struct dpsw_early_drop_cfg - early-drop configuration
3824 + * @drop_mode: drop mode
3825 + * @units: count units
3826 + * @yellow: WRED - 'yellow' configuration
3827 + * @green: WRED - 'green' configuration
3828 + * @tail_drop_threshold: tail drop threshold
3829 + */
3830 +struct dpsw_early_drop_cfg {
3831 + enum dpsw_early_drop_mode drop_mode;
3832 + enum dpsw_early_drop_unit units;
3833 + struct dpsw_wred_cfg yellow;
3834 + struct dpsw_wred_cfg green;
3835 + uint32_t tail_drop_threshold;
3836 +};
3837 +
3838 +/**
3839 + * dpsw_prepare_early_drop() - Prepare an early drop for setting in to interface
3840 + * @cfg: Early-drop configuration
3841 + * @early_drop_buf: Zeroed 256 bytes of memory before mapping it to DMA
3842 + *
3843 + * This function has to be called before dpsw_if_tc_set_early_drop
3844 + *
3845 + */
3846 +void dpsw_prepare_early_drop(const struct dpsw_early_drop_cfg *cfg,
3847 + uint8_t *early_drop_buf);
3848 +
3849 +/**
3850 + * dpsw_if_set_early_drop() - Set interface traffic class early-drop
3851 + * configuration
3852 + * @mc_io: Pointer to MC portal's I/O object
3853 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
3854 + * @token: Token of DPSW object
3855 + * @if_id: Interface Identifier
3856 + * @tc_id: Traffic class selection (0-7)
3857 + * @early_drop_iova: I/O virtual address of 64 bytes;
3858 + * Must be cacheline-aligned and DMA-able memory
3859 + *
3860 + * warning: Before calling this function, call dpsw_prepare_if_tc_early_drop()
3861 + * to prepare the early_drop_iova parameter
3862 + *
3863 + * Return: '0' on Success; error code otherwise.
3864 + */
3865 +int dpsw_if_set_early_drop(struct fsl_mc_io *mc_io,
3866 + uint32_t cmd_flags,
3867 + uint16_t token,
3868 + uint16_t if_id,
3869 + uint8_t tc_id,
3870 + uint64_t early_drop_iova);
3871 +
3872 +/**
3873 + * struct dpsw_custom_tpid_cfg - Structure representing tag Protocol identifier
3874 + * @tpid: An additional tag protocol identifier
3875 + */
3876 +struct dpsw_custom_tpid_cfg {
3877 + uint16_t tpid;
3878 +};
3879 +
3880 +/**
3881 + * dpsw_add_custom_tpid() - API Configures a distinct Ethernet type value
3882 + * @mc_io: Pointer to MC portal's I/O object
3883 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
3884 + * @token: Token of DPSW object
3885 + * @cfg: Tag Protocol identifier
3886 + *
3887 + * API Configures a distinct Ethernet type value (or TPID value)
3888 + * to indicate a VLAN tag in addition to the common
3889 + * TPID values 0x8100 and 0x88A8.
3890 + * Two additional TPID's are supported
3891 + *
3892 + * Return: Completion status. '0' on Success; Error code otherwise.
3893 + */
3894 +int dpsw_add_custom_tpid(struct fsl_mc_io *mc_io,
3895 + uint32_t cmd_flags,
3896 + uint16_t token,
3897 + const struct dpsw_custom_tpid_cfg *cfg);
3898 +
3899 +/**
3900 + * dpsw_remove_custom_tpid - API removes a distinct Ethernet type value
3901 + * @mc_io: Pointer to MC portal's I/O object
3902 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
3903 + * @token: Token of DPSW object
3904 + * @cfg: Tag Protocol identifier
3905 + *
3906 + * Return: Completion status. '0' on Success; Error code otherwise.
3907 + */
3908 +int dpsw_remove_custom_tpid(struct fsl_mc_io *mc_io,
3909 + uint32_t cmd_flags,
3910 + uint16_t token,
3911 + const struct dpsw_custom_tpid_cfg *cfg);
3912 +
3913 +/**
3914 + * dpsw_if_enable() - Enable Interface
3915 + * @mc_io: Pointer to MC portal's I/O object
3916 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
3917 + * @token: Token of DPSW object
3918 + * @if_id: Interface Identifier
3919 + *
3920 + * Return: Completion status. '0' on Success; Error code otherwise.
3921 + */
3922 +int dpsw_if_enable(struct fsl_mc_io *mc_io,
3923 + uint32_t cmd_flags,
3924 + uint16_t token,
3925 + uint16_t if_id);
3926 +
3927 +/**
3928 + * dpsw_if_disable() - Disable Interface
3929 + * @mc_io: Pointer to MC portal's I/O object
3930 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
3931 + * @token: Token of DPSW object
3932 + * @if_id: Interface Identifier
3933 + *
3934 + * Return: Completion status. '0' on Success; Error code otherwise.
3935 + */
3936 +int dpsw_if_disable(struct fsl_mc_io *mc_io,
3937 + uint32_t cmd_flags,
3938 + uint16_t token,
3939 + uint16_t if_id);
3940 +
3941 +/**
3942 + * struct dpsw_if_attr - Structure representing DPSW interface attributes
3943 + * @num_tcs: Number of traffic classes
3944 + * @rate: Transmit rate in bits per second
3945 + * @options: Interface configuration options (bitmap)
3946 + * @enabled: Indicates if interface is enabled
3947 + * @accept_all_vlan: The device discards/accepts incoming frames
3948 + * for VLANs that do not include this interface
3949 + * @admit_untagged: When set to 'DPSW_ADMIT_ONLY_VLAN_TAGGED', the device
3950 + * discards untagged frames or priority-tagged frames received on
3951 + * this interface;
3952 + * When set to 'DPSW_ADMIT_ALL', untagged frames or priority-
3953 + * tagged frames received on this interface are accepted
3954 + * @qdid: control frames transmit qdid
3955 + */
3956 +struct dpsw_if_attr {
3957 + uint8_t num_tcs;
3958 + uint32_t rate;
3959 + uint32_t options;
3960 + int enabled;
3961 + int accept_all_vlan;
3962 + enum dpsw_accepted_frames admit_untagged;
3963 + uint16_t qdid;
3964 +};
3965 +
3966 +/**
3967 + * dpsw_if_get_attributes() - Function obtains attributes of interface
3968 + * @mc_io: Pointer to MC portal's I/O object
3969 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
3970 + * @token: Token of DPSW object
3971 + * @if_id: Interface Identifier
3972 + * @attr: Returned interface attributes
3973 + *
3974 + * Return: Completion status. '0' on Success; Error code otherwise.
3975 + */
3976 +int dpsw_if_get_attributes(struct fsl_mc_io *mc_io,
3977 + uint32_t cmd_flags,
3978 + uint16_t token,
3979 + uint16_t if_id,
3980 + struct dpsw_if_attr *attr);
3981 +
3982 +/**
3983 + * dpsw_if_set_max_frame_length() - Set Maximum Receive frame length.
3984 + * @mc_io: Pointer to MC portal's I/O object
3985 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
3986 + * @token: Token of DPSW object
3987 + * @if_id: Interface Identifier
3988 + * @frame_length: Maximum Frame Length
3989 + *
3990 + * Return: Completion status. '0' on Success; Error code otherwise.
3991 + */
3992 +int dpsw_if_set_max_frame_length(struct fsl_mc_io *mc_io,
3993 + uint32_t cmd_flags,
3994 + uint16_t token,
3995 + uint16_t if_id,
3996 + uint16_t frame_length);
3997 +
3998 +/**
3999 + * dpsw_if_get_max_frame_length() - Get Maximum Receive frame length.
4000 + * @mc_io: Pointer to MC portal's I/O object
4001 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
4002 + * @token: Token of DPSW object
4003 + * @if_id: Interface Identifier
4004 + * @frame_length: Returned maximum Frame Length
4005 + *
4006 + * Return: Completion status. '0' on Success; Error code otherwise.
4007 + */
4008 +int dpsw_if_get_max_frame_length(struct fsl_mc_io *mc_io,
4009 + uint32_t cmd_flags,
4010 + uint16_t token,
4011 + uint16_t if_id,
4012 + uint16_t *frame_length);
4013 +
4014 +/**
4015 + * struct dpsw_vlan_cfg - VLAN Configuration
4016 + * @fdb_id: Forwarding Data Base
4017 + */
4018 +struct dpsw_vlan_cfg {
4019 + uint16_t fdb_id;
4020 +};
4021 +
4022 +/**
4023 + * dpsw_vlan_add() - Adding new VLAN to DPSW.
4024 + * @mc_io: Pointer to MC portal's I/O object
4025 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
4026 + * @token: Token of DPSW object
4027 + * @vlan_id: VLAN Identifier
4028 + * @cfg: VLAN configuration
4029 + *
4030 + * Only VLAN ID and FDB ID are required parameters here.
4031 + * 12 bit VLAN ID is defined in IEEE802.1Q.
4032 + * Adding a duplicate VLAN ID is not allowed.
4033 + * FDB ID can be shared across multiple VLANs. Shared learning
4034 + * is obtained by calling dpsw_vlan_add for multiple VLAN IDs
4035 + * with same fdb_id
4036 + *
4037 + * Return: Completion status. '0' on Success; Error code otherwise.
4038 + */
4039 +int dpsw_vlan_add(struct fsl_mc_io *mc_io,
4040 + uint32_t cmd_flags,
4041 + uint16_t token,
4042 + uint16_t vlan_id,
4043 + const struct dpsw_vlan_cfg *cfg);
4044 +
4045 +/**
4046 + * struct dpsw_vlan_if_cfg - Set of VLAN Interfaces
4047 + * @num_ifs: The number of interfaces that are assigned to the egress
4048 + * list for this VLAN
4049 + * @if_id: The set of interfaces that are
4050 + * assigned to the egress list for this VLAN
4051 + */
4052 +struct dpsw_vlan_if_cfg {
4053 + uint16_t num_ifs;
4054 + uint16_t if_id[DPSW_MAX_IF];
4055 +};
4056 +
4057 +/**
4058 + * dpsw_vlan_add_if() - Adding a set of interfaces to an existing VLAN.
4059 + * @mc_io: Pointer to MC portal's I/O object
4060 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
4061 + * @token: Token of DPSW object
4062 + * @vlan_id: VLAN Identifier
4063 + * @cfg: Set of interfaces to add
4064 + *
4065 + * It adds only interfaces not belonging to this VLAN yet,
4066 + * otherwise an error is generated and an entire command is
4067 + * ignored. This function can be called numerous times always
4068 + * providing required interfaces delta.
4069 + *
4070 + * Return: Completion status. '0' on Success; Error code otherwise.
4071 + */
4072 +int dpsw_vlan_add_if(struct fsl_mc_io *mc_io,
4073 + uint32_t cmd_flags,
4074 + uint16_t token,
4075 + uint16_t vlan_id,
4076 + const struct dpsw_vlan_if_cfg *cfg);
4077 +
4078 +/**
4079 + * dpsw_vlan_add_if_untagged() - Defining a set of interfaces that should be
4080 + * transmitted as untagged.
4081 + * @mc_io: Pointer to MC portal's I/O object
4082 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
4083 + * @token: Token of DPSW object
4084 + * @vlan_id: VLAN Identifier
4085 + * @cfg: set of interfaces that should be transmitted as untagged
4086 + *
4087 + * These interfaces should already belong to this VLAN.
4088 + * By default all interfaces are transmitted as tagged.
4089 + * Providing un-existing interface or untagged interface that is
4090 + * configured untagged already generates an error and the entire
4091 + * command is ignored.
4092 + *
4093 + * Return: Completion status. '0' on Success; Error code otherwise.
4094 + */
4095 +int dpsw_vlan_add_if_untagged(struct fsl_mc_io *mc_io,
4096 + uint32_t cmd_flags,
4097 + uint16_t token,
4098 + uint16_t vlan_id,
4099 + const struct dpsw_vlan_if_cfg *cfg);
4100 +
4101 +/**
4102 + * dpsw_vlan_add_if_flooding() - Define a set of interfaces that should be
4103 + * included in flooding when frame with unknown destination
4104 + * unicast MAC arrived.
4105 + * @mc_io: Pointer to MC portal's I/O object
4106 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
4107 + * @token: Token of DPSW object
4108 + * @vlan_id: VLAN Identifier
4109 + * @cfg: Set of interfaces that should be used for flooding
4110 + *
4111 + * These interfaces should belong to this VLAN. By default all
4112 + * interfaces are included into flooding list. Providing
4113 + * un-existing interface or an interface that already in the
4114 + * flooding list generates an error and the entire command is
4115 + * ignored.
4116 + *
4117 + * Return: Completion status. '0' on Success; Error code otherwise.
4118 + */
4119 +int dpsw_vlan_add_if_flooding(struct fsl_mc_io *mc_io,
4120 + uint32_t cmd_flags,
4121 + uint16_t token,
4122 + uint16_t vlan_id,
4123 + const struct dpsw_vlan_if_cfg *cfg);
4124 +
4125 +/**
4126 + * dpsw_vlan_remove_if() - Remove interfaces from an existing VLAN.
4127 + * @mc_io: Pointer to MC portal's I/O object
4128 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
4129 + * @token: Token of DPSW object
4130 + * @vlan_id: VLAN Identifier
4131 + * @cfg: Set of interfaces that should be removed
4132 + *
4133 + * Interfaces must belong to this VLAN, otherwise an error
4134 + * is returned and an the command is ignored
4135 + *
4136 + * Return: Completion status. '0' on Success; Error code otherwise.
4137 + */
4138 +int dpsw_vlan_remove_if(struct fsl_mc_io *mc_io,
4139 + uint32_t cmd_flags,
4140 + uint16_t token,
4141 + uint16_t vlan_id,
4142 + const struct dpsw_vlan_if_cfg *cfg);
4143 +
4144 +/**
4145 + * dpsw_vlan_remove_if_untagged() - Define a set of interfaces that should be
4146 + * converted from transmitted as untagged to transmit as tagged.
4147 + * @mc_io: Pointer to MC portal's I/O object
4148 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
4149 + * @token: Token of DPSW object
4150 + * @vlan_id: VLAN Identifier
4151 + * @cfg: set of interfaces that should be removed
4152 + *
4153 + * Interfaces provided by API have to belong to this VLAN and
4154 + * configured untagged, otherwise an error is returned and the
4155 + * command is ignored
4156 + *
4157 + * Return: Completion status. '0' on Success; Error code otherwise.
4158 + */
4159 +int dpsw_vlan_remove_if_untagged(struct fsl_mc_io *mc_io,
4160 + uint32_t cmd_flags,
4161 + uint16_t token,
4162 + uint16_t vlan_id,
4163 + const struct dpsw_vlan_if_cfg *cfg);
4164 +
4165 +/**
4166 + * dpsw_vlan_remove_if_flooding() - Define a set of interfaces that should be
4167 + * removed from the flooding list.
4168 + * @mc_io: Pointer to MC portal's I/O object
4169 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
4170 + * @token: Token of DPSW object
4171 + * @vlan_id: VLAN Identifier
4172 + * @cfg: set of interfaces used for flooding
4173 + *
4174 + * Return: Completion status. '0' on Success; Error code otherwise.
4175 + */
4176 +int dpsw_vlan_remove_if_flooding(struct fsl_mc_io *mc_io,
4177 + uint32_t cmd_flags,
4178 + uint16_t token,
4179 + uint16_t vlan_id,
4180 + const struct dpsw_vlan_if_cfg *cfg);
4181 +
4182 +/**
4183 + * dpsw_vlan_remove() - Remove an entire VLAN
4184 + * @mc_io: Pointer to MC portal's I/O object
4185 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
4186 + * @token: Token of DPSW object
4187 + * @vlan_id: VLAN Identifier
4188 + *
4189 + * Return: Completion status. '0' on Success; Error code otherwise.
4190 + */
4191 +int dpsw_vlan_remove(struct fsl_mc_io *mc_io,
4192 + uint32_t cmd_flags,
4193 + uint16_t token,
4194 + uint16_t vlan_id);
4195 +
4196 +/**
4197 + * struct dpsw_vlan_attr - VLAN attributes
4198 + * @fdb_id: Associated FDB ID
4199 + * @num_ifs: Number of interfaces
4200 + * @num_untagged_ifs: Number of untagged interfaces
4201 + * @num_flooding_ifs: Number of flooding interfaces
4202 + */
4203 +struct dpsw_vlan_attr {
4204 + uint16_t fdb_id;
4205 + uint16_t num_ifs;
4206 + uint16_t num_untagged_ifs;
4207 + uint16_t num_flooding_ifs;
4208 +};
4209 +
4210 +/**
4211 + * dpsw_vlan_get_attributes() - Get VLAN attributes
4212 + * @mc_io: Pointer to MC portal's I/O object
4213 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
4214 + * @token: Token of DPSW object
4215 + * @vlan_id: VLAN Identifier
4216 + * @attr: Returned DPSW attributes
4217 + *
4218 + * Return: Completion status. '0' on Success; Error code otherwise.
4219 + */
4220 +int dpsw_vlan_get_attributes(struct fsl_mc_io *mc_io,
4221 + uint32_t cmd_flags,
4222 + uint16_t token,
4223 + uint16_t vlan_id,
4224 + struct dpsw_vlan_attr *attr);
4225 +
4226 +/**
4227 + * dpsw_vlan_get_if() - Get interfaces belong to this VLAN
4228 + * @mc_io: Pointer to MC portal's I/O object
4229 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
4230 + * @token: Token of DPSW object
4231 + * @vlan_id: VLAN Identifier
4232 + * @cfg: Returned set of interfaces belong to this VLAN
4233 + *
4234 + * Return: Completion status. '0' on Success; Error code otherwise.
4235 + */
4236 +int dpsw_vlan_get_if(struct fsl_mc_io *mc_io,
4237 + uint32_t cmd_flags,
4238 + uint16_t token,
4239 + uint16_t vlan_id,
4240 + struct dpsw_vlan_if_cfg *cfg);
4241 +
4242 +/**
4243 + * dpsw_vlan_get_if_flooding() - Get interfaces used in flooding for this VLAN
4244 + * @mc_io: Pointer to MC portal's I/O object
4245 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
4246 + * @token: Token of DPSW object
4247 + * @vlan_id: VLAN Identifier
4248 + * @cfg: Returned set of flooding interfaces
4249 + *
4250 + * Return: Completion status. '0' on Success; Error code otherwise.
4251 + */
4252 +int dpsw_vlan_get_if_flooding(struct fsl_mc_io *mc_io,
4253 + uint32_t cmd_flags,
4254 + uint16_t token,
4255 + uint16_t vlan_id,
4256 + struct dpsw_vlan_if_cfg *cfg);
4257 +
4258 +/**
4259 + * dpsw_vlan_get_if_untagged() - Get interfaces that should be transmitted as
4260 + * untagged
4261 + * @mc_io: Pointer to MC portal's I/O object
4262 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
4263 + * @token: Token of DPSW object
4264 + * @vlan_id: VLAN Identifier
4265 + * @cfg: Returned set of untagged interfaces
4266 + *
4267 + * Return: Completion status. '0' on Success; Error code otherwise.
4268 + */
4269 +int dpsw_vlan_get_if_untagged(struct fsl_mc_io *mc_io,
4270 + uint32_t cmd_flags,
4271 + uint16_t token,
4272 + uint16_t vlan_id,
4273 + struct dpsw_vlan_if_cfg *cfg);
4274 +
4275 +/**
4276 + * struct dpsw_fdb_cfg - FDB Configuration
4277 + * @num_fdb_entries: Number of FDB entries
4278 + * @fdb_aging_time: Aging time in seconds
4279 + */
4280 +struct dpsw_fdb_cfg {
4281 + uint16_t num_fdb_entries;
4282 + uint16_t fdb_aging_time;
4283 +};
4284 +
4285 +/**
4286 + * dpsw_fdb_add() - Add FDB to switch and Returns handle to FDB table for
4287 + * the reference
4288 + * @mc_io: Pointer to MC portal's I/O object
4289 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
4290 + * @token: Token of DPSW object
4291 + * @fdb_id: Returned Forwarding Database Identifier
4292 + * @cfg: FDB Configuration
4293 + *
4294 + * Return: Completion status. '0' on Success; Error code otherwise.
4295 + */
4296 +int dpsw_fdb_add(struct fsl_mc_io *mc_io,
4297 + uint32_t cmd_flags,
4298 + uint16_t token,
4299 + uint16_t *fdb_id,
4300 + const struct dpsw_fdb_cfg *cfg);
4301 +
4302 +/**
4303 + * dpsw_fdb_remove() - Remove FDB from switch
4304 + * @mc_io: Pointer to MC portal's I/O object
4305 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
4306 + * @token: Token of DPSW object
4307 + * @fdb_id: Forwarding Database Identifier
4308 + *
4309 + * Return: Completion status. '0' on Success; Error code otherwise.
4310 + */
4311 +int dpsw_fdb_remove(struct fsl_mc_io *mc_io,
4312 + uint32_t cmd_flags,
4313 + uint16_t token,
4314 + uint16_t fdb_id);
4315 +
4316 +/**
4317 + * enum dpsw_fdb_entry_type - FDB Entry type - Static/Dynamic
4318 + * @DPSW_FDB_ENTRY_STATIC: Static entry
4319 + * @DPSW_FDB_ENTRY_DINAMIC: Dynamic entry
4320 + */
4321 +enum dpsw_fdb_entry_type {
4322 + DPSW_FDB_ENTRY_STATIC = 0,
4323 + DPSW_FDB_ENTRY_DINAMIC = 1
4324 +};
4325 +
4326 +/**
4327 + * struct dpsw_fdb_unicast_cfg - Unicast entry configuration
4328 + * @type: Select static or dynamic entry
4329 + * @mac_addr: MAC address
4330 + * @if_egress: Egress interface ID
4331 + */
4332 +struct dpsw_fdb_unicast_cfg {
4333 + enum dpsw_fdb_entry_type type;
4334 + uint8_t mac_addr[6];
4335 + uint16_t if_egress;
4336 +};
4337 +
4338 +/**
4339 + * dpsw_fdb_add_unicast() - Function adds an unicast entry into MAC lookup table
4340 + * @mc_io: Pointer to MC portal's I/O object
4341 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
4342 + * @token: Token of DPSW object
4343 + * @fdb_id: Forwarding Database Identifier
4344 + * @cfg: Unicast entry configuration
4345 + *
4346 + * Return: Completion status. '0' on Success; Error code otherwise.
4347 + */
4348 +int dpsw_fdb_add_unicast(struct fsl_mc_io *mc_io,
4349 + uint32_t cmd_flags,
4350 + uint16_t token,
4351 + uint16_t fdb_id,
4352 + const struct dpsw_fdb_unicast_cfg *cfg);
4353 +
4354 +/**
4355 + * dpsw_fdb_get_unicast() - Get unicast entry from MAC lookup table by
4356 + * unicast Ethernet address
4357 + * @mc_io: Pointer to MC portal's I/O object
4358 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
4359 + * @token: Token of DPSW object
4360 + * @fdb_id: Forwarding Database Identifier
4361 + * @cfg: Returned unicast entry configuration
4362 + *
4363 + * Return: Completion status. '0' on Success; Error code otherwise.
4364 + */
4365 +int dpsw_fdb_get_unicast(struct fsl_mc_io *mc_io,
4366 + uint32_t cmd_flags,
4367 + uint16_t token,
4368 + uint16_t fdb_id,
4369 + struct dpsw_fdb_unicast_cfg *cfg);
4370 +
4371 +/**
4372 + * dpsw_fdb_remove_unicast() - removes an entry from MAC lookup table
4373 + * @mc_io: Pointer to MC portal's I/O object
4374 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
4375 + * @token: Token of DPSW object
4376 + * @fdb_id: Forwarding Database Identifier
4377 + * @cfg: Unicast entry configuration
4378 + *
4379 + * Return: Completion status. '0' on Success; Error code otherwise.
4380 + */
4381 +int dpsw_fdb_remove_unicast(struct fsl_mc_io *mc_io,
4382 + uint32_t cmd_flags,
4383 + uint16_t token,
4384 + uint16_t fdb_id,
4385 + const struct dpsw_fdb_unicast_cfg *cfg);
4386 +
4387 +/**
4388 + * struct dpsw_fdb_multicast_cfg - Multi-cast entry configuration
4389 + * @type: Select static or dynamic entry
4390 + * @mac_addr: MAC address
4391 + * @num_ifs: Number of external and internal interfaces
4392 + * @if_id: Egress interface IDs
4393 + */
4394 +struct dpsw_fdb_multicast_cfg {
4395 + enum dpsw_fdb_entry_type type;
4396 + uint8_t mac_addr[6];
4397 + uint16_t num_ifs;
4398 + uint16_t if_id[DPSW_MAX_IF];
4399 +};
4400 +
4401 +/**
4402 + * dpsw_fdb_add_multicast() - Add a set of egress interfaces to multi-cast group
4403 + * @mc_io: Pointer to MC portal's I/O object
4404 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
4405 + * @token: Token of DPSW object
4406 + * @fdb_id: Forwarding Database Identifier
4407 + * @cfg: Multicast entry configuration
4408 + *
4409 + * If group doesn't exist, it will be created.
4410 + * It adds only interfaces not belonging to this multicast group
4411 + * yet, otherwise error will be generated and the command is
4412 + * ignored.
4413 + * This function may be called numerous times always providing
4414 + * required interfaces delta.
4415 + *
4416 + * Return: Completion status. '0' on Success; Error code otherwise.
4417 + */
4418 +int dpsw_fdb_add_multicast(struct fsl_mc_io *mc_io,
4419 + uint32_t cmd_flags,
4420 + uint16_t token,
4421 + uint16_t fdb_id,
4422 + const struct dpsw_fdb_multicast_cfg *cfg);
4423 +
4424 +/**
4425 + * dpsw_fdb_get_multicast() - Reading multi-cast group by multi-cast Ethernet
4426 + * address.
4427 + * @mc_io: Pointer to MC portal's I/O object
4428 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
4429 + * @token: Token of DPSW object
4430 + * @fdb_id: Forwarding Database Identifier
4431 + * @cfg: Returned multicast entry configuration
4432 + *
4433 + * Return: Completion status. '0' on Success; Error code otherwise.
4434 + */
4435 +int dpsw_fdb_get_multicast(struct fsl_mc_io *mc_io,
4436 + uint32_t cmd_flags,
4437 + uint16_t token,
4438 + uint16_t fdb_id,
4439 + struct dpsw_fdb_multicast_cfg *cfg);
4440 +
4441 +/**
4442 + * dpsw_fdb_remove_multicast() - Removing interfaces from an existing multicast
4443 + * group.
4444 + * @mc_io: Pointer to MC portal's I/O object
4445 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
4446 + * @token: Token of DPSW object
4447 + * @fdb_id: Forwarding Database Identifier
4448 + * @cfg: Multicast entry configuration
4449 + *
4450 + * Interfaces provided by this API have to exist in the group,
4451 + * otherwise an error will be returned and an entire command
4452 + * ignored. If there is no interface left in the group,
4453 + * an entire group is deleted
4454 + *
4455 + * Return: Completion status. '0' on Success; Error code otherwise.
4456 + */
4457 +int dpsw_fdb_remove_multicast(struct fsl_mc_io *mc_io,
4458 + uint32_t cmd_flags,
4459 + uint16_t token,
4460 + uint16_t fdb_id,
4461 + const struct dpsw_fdb_multicast_cfg *cfg);
4462 +
4463 +/**
4464 + * enum dpsw_fdb_learning_mode - Auto-learning modes
4465 + * @DPSW_FDB_LEARNING_MODE_DIS: Disable Auto-learning
4466 + * @DPSW_FDB_LEARNING_MODE_HW: Enable HW auto-Learning
4467 + * @DPSW_FDB_LEARNING_MODE_NON_SECURE: Enable None secure learning by CPU
4468 + * @DPSW_FDB_LEARNING_MODE_SECURE: Enable secure learning by CPU
4469 + *
4470 + * NONE - SECURE LEARNING
4471 + * SMAC found DMAC found CTLU Action
4472 + * v v Forward frame to
4473 + * 1. DMAC destination
4474 + * - v Forward frame to
4475 + * 1. DMAC destination
4476 + * 2. Control interface
4477 + * v - Forward frame to
4478 + * 1. Flooding list of interfaces
4479 + * - - Forward frame to
4480 + * 1. Flooding list of interfaces
4481 + * 2. Control interface
4482 + * SECURE LEARING
4483 + * SMAC found DMAC found CTLU Action
4484 + * v v Forward frame to
4485 + * 1. DMAC destination
4486 + * - v Forward frame to
4487 + * 1. Control interface
4488 + * v - Forward frame to
4489 + * 1. Flooding list of interfaces
4490 + * - - Forward frame to
4491 + * 1. Control interface
4492 + */
4493 +enum dpsw_fdb_learning_mode {
4494 + DPSW_FDB_LEARNING_MODE_DIS = 0,
4495 + DPSW_FDB_LEARNING_MODE_HW = 1,
4496 + DPSW_FDB_LEARNING_MODE_NON_SECURE = 2,
4497 + DPSW_FDB_LEARNING_MODE_SECURE = 3
4498 +};
4499 +
4500 +/**
4501 + * dpsw_fdb_set_learning_mode() - Define FDB learning mode
4502 + * @mc_io: Pointer to MC portal's I/O object
4503 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
4504 + * @token: Token of DPSW object
4505 + * @fdb_id: Forwarding Database Identifier
4506 + * @mode: learning mode
4507 + *
4508 + * Return: Completion status. '0' on Success; Error code otherwise.
4509 + */
4510 +int dpsw_fdb_set_learning_mode(struct fsl_mc_io *mc_io,
4511 + uint32_t cmd_flags,
4512 + uint16_t token,
4513 + uint16_t fdb_id,
4514 + enum dpsw_fdb_learning_mode mode);
4515 +
4516 +/**
4517 + * struct dpsw_fdb_attr - FDB Attributes
4518 + * @max_fdb_entries: Number of FDB entries
4519 + * @fdb_aging_time: Aging time in seconds
4520 + * @learning_mode: Learning mode
4521 + * @num_fdb_mc_groups: Current number of multicast groups
4522 + * @max_fdb_mc_groups: Maximum number of multicast groups
4523 + */
4524 +struct dpsw_fdb_attr {
4525 + uint16_t max_fdb_entries;
4526 + uint16_t fdb_aging_time;
4527 + enum dpsw_fdb_learning_mode learning_mode;
4528 + uint16_t num_fdb_mc_groups;
4529 + uint16_t max_fdb_mc_groups;
4530 +};
4531 +
4532 +/**
4533 + * dpsw_fdb_get_attributes() - Get FDB attributes
4534 + * @mc_io: Pointer to MC portal's I/O object
4535 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
4536 + * @token: Token of DPSW object
4537 + * @fdb_id: Forwarding Database Identifier
4538 + * @attr: Returned FDB attributes
4539 + *
4540 + * Return: Completion status. '0' on Success; Error code otherwise.
4541 + */
4542 +int dpsw_fdb_get_attributes(struct fsl_mc_io *mc_io,
4543 + uint32_t cmd_flags,
4544 + uint16_t token,
4545 + uint16_t fdb_id,
4546 + struct dpsw_fdb_attr *attr);
4547 +
4548 +/**
4549 + * struct dpsw_acl_cfg - ACL Configuration
4550 + * @max_entries: Number of FDB entries
4551 + */
4552 +struct dpsw_acl_cfg {
4553 + uint16_t max_entries;
4554 +};
4555 +
4556 +/**
4557 + * struct dpsw_acl_fields - ACL fields.
4558 + * @l2_dest_mac: Destination MAC address: BPDU, Multicast, Broadcast, Unicast,
4559 + * slow protocols, MVRP, STP
4560 + * @l2_source_mac: Source MAC address
4561 + * @l2_tpid: Layer 2 (Ethernet) protocol type, used to identify the following
4562 + * protocols: MPLS, PTP, PFC, ARP, Jumbo frames, LLDP, IEEE802.1ae,
4563 + * Q-in-Q, IPv4, IPv6, PPPoE
4564 + * @l2_pcp_dei: indicate which protocol is encapsulated in the payload
4565 + * @l2_vlan_id: layer 2 VLAN ID
4566 + * @l2_ether_type: layer 2 Ethernet type
4567 + * @l3_dscp: Layer 3 differentiated services code point
4568 + * @l3_protocol: Tells the Network layer at the destination host, to which
4569 + * Protocol this packet belongs to. The following protocol are
4570 + * supported: ICMP, IGMP, IPv4 (encapsulation), TCP, IPv6
4571 + * (encapsulation), GRE, PTP
4572 + * @l3_source_ip: Source IPv4 IP
4573 + * @l3_dest_ip: Destination IPv4 IP
4574 + * @l4_source_port: Source TCP/UDP Port
4575 + * @l4_dest_port: Destination TCP/UDP Port
4576 + */
4577 +struct dpsw_acl_fields {
4578 + uint8_t l2_dest_mac[6];
4579 + uint8_t l2_source_mac[6];
4580 + uint16_t l2_tpid;
4581 + uint8_t l2_pcp_dei;
4582 + uint16_t l2_vlan_id;
4583 + uint16_t l2_ether_type;
4584 + uint8_t l3_dscp;
4585 + uint8_t l3_protocol;
4586 + uint32_t l3_source_ip;
4587 + uint32_t l3_dest_ip;
4588 + uint16_t l4_source_port;
4589 + uint16_t l4_dest_port;
4590 +};
4591 +
4592 +/**
4593 + * struct dpsw_acl_key - ACL key
4594 + * @match: Match fields
4595 + * @mask: Mask: b'1 - valid, b'0 don't care
4596 + */
4597 +struct dpsw_acl_key {
4598 + struct dpsw_acl_fields match;
4599 + struct dpsw_acl_fields mask;
4600 +};
4601 +
4602 +/**
4603 + * enum dpsw_acl_action
4604 + * @DPSW_ACL_ACTION_DROP: Drop frame
4605 + * @DPSW_ACL_ACTION_REDIRECT: Redirect to certain port
4606 + * @DPSW_ACL_ACTION_ACCEPT: Accept frame
4607 + * @DPSW_ACL_ACTION_REDIRECT_TO_CTRL_IF: Redirect to control interface
4608 + */
4609 +enum dpsw_acl_action {
4610 + DPSW_ACL_ACTION_DROP,
4611 + DPSW_ACL_ACTION_REDIRECT,
4612 + DPSW_ACL_ACTION_ACCEPT,
4613 + DPSW_ACL_ACTION_REDIRECT_TO_CTRL_IF
4614 +};
4615 +
4616 +/**
4617 + * struct dpsw_acl_result - ACL action
4618 + * @action: Action should be taken when ACL entry hit
4619 + * @if_id: Interface IDs to redirect frame. Valid only if redirect selected for
4620 + * action
4621 + */
4622 +struct dpsw_acl_result {
4623 + enum dpsw_acl_action action;
4624 + uint16_t if_id;
4625 +};
4626 +
4627 +/**
4628 + * struct dpsw_acl_entry_cfg - ACL entry
4629 + * @key_iova: I/O virtual address of DMA-able memory filled with key after call
4630 + * to dpsw_acl_prepare_entry_cfg()
4631 + * @result: Required action when entry hit occurs
4632 + * @precedence: Precedence inside ACL 0 is lowest; This priority can not change
4633 + * during the lifetime of a Policy. It is user responsibility to
4634 + * space the priorities according to consequent rule additions.
4635 + */
4636 +struct dpsw_acl_entry_cfg {
4637 + uint64_t key_iova;
4638 + struct dpsw_acl_result result;
4639 + int precedence;
4640 +};
4641 +
4642 +/**
4643 + * dpsw_acl_add() - Adds ACL to L2 switch.
4644 + * @mc_io: Pointer to MC portal's I/O object
4645 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
4646 + * @token: Token of DPSW object
4647 + * @acl_id: Returned ACL ID, for the future reference
4648 + * @cfg: ACL configuration
4649 + *
4650 + * Create Access Control List. Multiple ACLs can be created and
4651 + * co-exist in L2 switch
4652 + *
4653 + * Return: '0' on Success; Error code otherwise.
4654 + */
4655 +int dpsw_acl_add(struct fsl_mc_io *mc_io,
4656 + uint32_t cmd_flags,
4657 + uint16_t token,
4658 + uint16_t *acl_id,
4659 + const struct dpsw_acl_cfg *cfg);
4660 +
4661 +/**
4662 + * dpsw_acl_remove() - Removes ACL from L2 switch.
4663 + * @mc_io: Pointer to MC portal's I/O object
4664 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
4665 + * @token: Token of DPSW object
4666 + * @acl_id: ACL ID
4667 + *
4668 + * Return: '0' on Success; Error code otherwise.
4669 + */
4670 +int dpsw_acl_remove(struct fsl_mc_io *mc_io,
4671 + uint32_t cmd_flags,
4672 + uint16_t token,
4673 + uint16_t acl_id);
4674 +
4675 +/**
4676 + * dpsw_acl_prepare_entry_cfg() - Set an entry to ACL.
4677 + * @key: key
4678 + * @entry_cfg_buf: Zeroed 256 bytes of memory before mapping it to DMA
4679 + *
4680 + * This function has to be called before adding or removing acl_entry
4681 + *
4682 + */
4683 +void dpsw_acl_prepare_entry_cfg(const struct dpsw_acl_key *key,
4684 + uint8_t *entry_cfg_buf);
4685 +
4686 +/**
4687 + * dpsw_acl_add_entry() - Adds an entry to ACL.
4688 + * @mc_io: Pointer to MC portal's I/O object
4689 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
4690 + * @token: Token of DPSW object
4691 + * @acl_id: ACL ID
4692 + * @cfg: entry configuration
4693 + *
4694 + * warning: This function has to be called after dpsw_acl_set_entry_cfg()
4695 + *
4696 + * Return: '0' on Success; Error code otherwise.
4697 + */
4698 +int dpsw_acl_add_entry(struct fsl_mc_io *mc_io,
4699 + uint32_t cmd_flags,
4700 + uint16_t token,
4701 + uint16_t acl_id,
4702 + const struct dpsw_acl_entry_cfg *cfg);
4703 +
4704 +/**
4705 + * dpsw_acl_remove_entry() - Removes an entry from ACL.
4706 + * @mc_io: Pointer to MC portal's I/O object
4707 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
4708 + * @token: Token of DPSW object
4709 + * @acl_id: ACL ID
4710 + * @cfg: entry configuration
4711 + *
4712 + * warning: This function has to be called after dpsw_acl_set_entry_cfg()
4713 + *
4714 + * Return: '0' on Success; Error code otherwise.
4715 + */
4716 +int dpsw_acl_remove_entry(struct fsl_mc_io *mc_io,
4717 + uint32_t cmd_flags,
4718 + uint16_t token,
4719 + uint16_t acl_id,
4720 + const struct dpsw_acl_entry_cfg *cfg);
4721 +
4722 +/**
4723 + * struct dpsw_acl_if_cfg - List of interfaces to Associate with ACL
4724 + * @num_ifs: Number of interfaces
4725 + * @if_id: List of interfaces
4726 + */
4727 +struct dpsw_acl_if_cfg {
4728 + uint16_t num_ifs;
4729 + uint16_t if_id[DPSW_MAX_IF];
4730 +};
4731 +
4732 +/**
4733 + * dpsw_acl_add_if() - Associate interface/interfaces with ACL.
4734 + * @mc_io: Pointer to MC portal's I/O object
4735 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
4736 + * @token: Token of DPSW object
4737 + * @acl_id: ACL ID
4738 + * @cfg: interfaces list
4739 + *
4740 + * Return: '0' on Success; Error code otherwise.
4741 + */
4742 +int dpsw_acl_add_if(struct fsl_mc_io *mc_io,
4743 + uint32_t cmd_flags,
4744 + uint16_t token,
4745 + uint16_t acl_id,
4746 + const struct dpsw_acl_if_cfg *cfg);
4747 +
4748 +/**
4749 + * dpsw_acl_remove_if() - De-associate interface/interfaces from ACL.
4750 + * @mc_io: Pointer to MC portal's I/O object
4751 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
4752 + * @token: Token of DPSW object
4753 + * @acl_id: ACL ID
4754 + * @cfg: interfaces list
4755 + *
4756 + * Return: '0' on Success; Error code otherwise.
4757 + */
4758 +int dpsw_acl_remove_if(struct fsl_mc_io *mc_io,
4759 + uint32_t cmd_flags,
4760 + uint16_t token,
4761 + uint16_t acl_id,
4762 + const struct dpsw_acl_if_cfg *cfg);
4763 +
4764 +/**
4765 + * struct dpsw_acl_attr - ACL Attributes
4766 + * @max_entries: Max number of ACL entries
4767 + * @num_entries: Number of used ACL entries
4768 + * @num_ifs: Number of interfaces associated with ACL
4769 + */
4770 +struct dpsw_acl_attr {
4771 + uint16_t max_entries;
4772 + uint16_t num_entries;
4773 + uint16_t num_ifs;
4774 +};
4775 +
4776 +/**
4777 +* dpsw_acl_get_attributes() - Get specific counter of particular interface
4778 +* @mc_io: Pointer to MC portal's I/O object
4779 +* @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
4780 +* @token: Token of DPSW object
4781 +* @acl_id: ACL Identifier
4782 +* @attr: Returned ACL attributes
4783 +*
4784 +* Return: '0' on Success; Error code otherwise.
4785 +*/
4786 +int dpsw_acl_get_attributes(struct fsl_mc_io *mc_io,
4787 + uint32_t cmd_flags,
4788 + uint16_t token,
4789 + uint16_t acl_id,
4790 + struct dpsw_acl_attr *attr);
4791 +/**
4792 +* struct dpsw_ctrl_if_attr - Control interface attributes
4793 +* @rx_fqid: Receive FQID
4794 +* @rx_err_fqid: Receive error FQID
4795 +* @tx_err_conf_fqid: Transmit error and confirmation FQID
4796 +*/
4797 +struct dpsw_ctrl_if_attr {
4798 + uint32_t rx_fqid;
4799 + uint32_t rx_err_fqid;
4800 + uint32_t tx_err_conf_fqid;
4801 +};
4802 +
4803 +/**
4804 +* dpsw_ctrl_if_get_attributes() - Obtain control interface attributes
4805 +* @mc_io: Pointer to MC portal's I/O object
4806 +* @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
4807 +* @token: Token of DPSW object
4808 +* @attr: Returned control interface attributes
4809 +*
4810 +* Return: '0' on Success; Error code otherwise.
4811 +*/
4812 +int dpsw_ctrl_if_get_attributes(struct fsl_mc_io *mc_io,
4813 + uint32_t cmd_flags,
4814 + uint16_t token,
4815 + struct dpsw_ctrl_if_attr *attr);
4816 +
4817 +/**
4818 + * Maximum number of DPBP
4819 + */
4820 +#define DPSW_MAX_DPBP 8
4821 +
4822 +/**
4823 + * struct dpsw_ctrl_if_pools_cfg - Control interface buffer pools configuration
4824 + * @num_dpbp: Number of DPBPs
4825 + * @pools: Array of buffer pools parameters; The number of valid entries
4826 + * must match 'num_dpbp' value
4827 + */
4828 +struct dpsw_ctrl_if_pools_cfg {
4829 + uint8_t num_dpbp;
4830 + /**
4831 + * struct pools - Buffer pools parameters
4832 + * @dpbp_id: DPBP object ID
4833 + * @buffer_size: Buffer size
4834 + * @backup_pool: Backup pool
4835 + */
4836 + struct {
4837 + int dpbp_id;
4838 + uint16_t buffer_size;
4839 + int backup_pool;
4840 + } pools[DPSW_MAX_DPBP];
4841 +};
4842 +
4843 +/**
4844 +* dpsw_ctrl_if_set_pools() - Set control interface buffer pools
4845 +* @mc_io: Pointer to MC portal's I/O object
4846 +* @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
4847 +* @token: Token of DPSW object
4848 +* @cfg: buffer pools configuration
4849 +*
4850 +* Return: '0' on Success; Error code otherwise.
4851 +*/
4852 +int dpsw_ctrl_if_set_pools(struct fsl_mc_io *mc_io,
4853 + uint32_t cmd_flags,
4854 + uint16_t token,
4855 + const struct dpsw_ctrl_if_pools_cfg *cfg);
4856 +
4857 +/**
4858 +* dpsw_ctrl_if_enable() - Enable control interface
4859 +* @mc_io: Pointer to MC portal's I/O object
4860 +* @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
4861 +* @token: Token of DPSW object
4862 +*
4863 +* Return: '0' on Success; Error code otherwise.
4864 +*/
4865 +int dpsw_ctrl_if_enable(struct fsl_mc_io *mc_io,
4866 + uint32_t cmd_flags,
4867 + uint16_t token);
4868 +
4869 +/**
4870 +* dpsw_ctrl_if_disable() - Function disables control interface
4871 +* @mc_io: Pointer to MC portal's I/O object
4872 +* @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
4873 +* @token: Token of DPSW object
4874 +*
4875 +* Return: '0' on Success; Error code otherwise.
4876 +*/
4877 +int dpsw_ctrl_if_disable(struct fsl_mc_io *mc_io,
4878 + uint32_t cmd_flags,
4879 + uint16_t token);
4880 +
4881 +#endif /* __FSL_DPSW_H */
4882 --- /dev/null
4883 +++ b/drivers/staging/fsl-dpaa2/ethsw/switch.c
4884 @@ -0,0 +1,1711 @@
4885 +/* Copyright 2014-2015 Freescale Semiconductor Inc.
4886 + *
4887 + * Redistribution and use in source and binary forms, with or without
4888 + * modification, are permitted provided that the following conditions are met:
4889 + * * Redistributions of source code must retain the above copyright
4890 + * notice, this list of conditions and the following disclaimer.
4891 + * * Redistributions in binary form must reproduce the above copyright
4892 + * notice, this list of conditions and the following disclaimer in the
4893 + * documentation and/or other materials provided with the distribution.
4894 + * * Neither the name of Freescale Semiconductor nor the
4895 + * names of its contributors may be used to endorse or promote products
4896 + * derived from this software without specific prior written permission.
4897 + *
4898 + *
4899 + * ALTERNATIVELY, this software may be distributed under the terms of the
4900 + * GNU General Public License ("GPL") as published by the Free Software
4901 + * Foundation, either version 2 of that License or (at your option) any
4902 + * later version.
4903 + *
4904 + * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
4905 + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
4906 + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
4907 + * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
4908 + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
4909 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
4910 + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
4911 + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
4912 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
4913 + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
4914 + */
4915 +
4916 +#include <linux/module.h>
4917 +
4918 +#include <linux/netdevice.h>
4919 +#include <linux/etherdevice.h>
4920 +#include <linux/rtnetlink.h>
4921 +#include <linux/if_vlan.h>
4922 +#include <linux/interrupt.h>
4923 +#include <linux/msi.h>
4924 +
4925 +#include <uapi/linux/if_bridge.h>
4926 +#include <net/netlink.h>
4927 +
4928 +#include "../../fsl-mc/include/mc.h"
4929 +#include "dpsw.h"
4930 +#include "dpsw-cmd.h"
4931 +
4932 +/* Minimal supported DPSE version */
4933 +#define DPSW_MIN_VER_MAJOR 7
4934 +#define DPSW_MIN_VER_MINOR 0
4935 +
4936 +/* IRQ index */
4937 +#define DPSW_MAX_IRQ_NUM 2
4938 +
4939 +#define ETHSW_VLAN_MEMBER 1
4940 +#define ETHSW_VLAN_UNTAGGED 2
4941 +#define ETHSW_VLAN_PVID 4
4942 +#define ETHSW_VLAN_GLOBAL 8
4943 +
4944 +struct ethsw_port_priv {
4945 + struct net_device *netdev;
4946 + struct list_head list;
4947 + u16 port_index;
4948 + struct ethsw_dev_priv *ethsw_priv;
4949 + u8 stp_state;
4950 +
4951 + char vlans[VLAN_VID_MASK+1];
4952 +
4953 +};
4954 +
4955 +struct ethsw_dev_priv {
4956 + struct net_device *netdev;
4957 + struct fsl_mc_io *mc_io;
4958 + uint16_t dpsw_handle;
4959 + struct dpsw_attr sw_attr;
4960 + int dev_id;
4961 + /*TODO: redundant, we can use the slave dev list */
4962 + struct list_head port_list;
4963 +
4964 + bool flood;
4965 + bool learning;
4966 +
4967 + char vlans[VLAN_VID_MASK+1];
4968 +};
4969 +
4970 +static int ethsw_port_stop(struct net_device *netdev);
4971 +static int ethsw_port_open(struct net_device *netdev);
4972 +
4973 +static inline void __get_priv(struct net_device *netdev,
4974 + struct ethsw_dev_priv **priv,
4975 + struct ethsw_port_priv **port_priv)
4976 +{
4977 + struct ethsw_dev_priv *_priv = NULL;
4978 + struct ethsw_port_priv *_port_priv = NULL;
4979 +
4980 + if (netdev->flags & IFF_MASTER) {
4981 + _priv = netdev_priv(netdev);
4982 + } else {
4983 + _port_priv = netdev_priv(netdev);
4984 + _priv = _port_priv->ethsw_priv;
4985 + }
4986 +
4987 + if (priv)
4988 + *priv = _priv;
4989 + if (port_priv)
4990 + *port_priv = _port_priv;
4991 +}
4992 +
4993 +/* -------------------------------------------------------------------------- */
4994 +/* ethsw netdevice ops */
4995 +
4996 +static netdev_tx_t ethsw_dropframe(struct sk_buff *skb, struct net_device *dev)
4997 +{
4998 + /* we don't support I/O for now, drop the frame */
4999 + dev_kfree_skb_any(skb);
5000 + return NETDEV_TX_OK;
5001 +}
5002 +
5003 +static int ethsw_open(struct net_device *netdev)
5004 +{
5005 + struct ethsw_dev_priv *priv = netdev_priv(netdev);
5006 + struct list_head *pos;
5007 + struct ethsw_port_priv *port_priv = NULL;
5008 + int err;
5009 +
5010 + err = dpsw_enable(priv->mc_io, 0, priv->dpsw_handle);
5011 + if (err) {
5012 + netdev_err(netdev, "dpsw_enable err %d\n", err);
5013 + return err;
5014 + }
5015 +
5016 + list_for_each(pos, &priv->port_list) {
5017 + port_priv = list_entry(pos, struct ethsw_port_priv, list);
5018 + err = dev_open(port_priv->netdev);
5019 + if (err)
5020 + netdev_err(port_priv->netdev, "dev_open err %d\n", err);
5021 + }
5022 +
5023 + return 0;
5024 +}
5025 +
5026 +static int ethsw_stop(struct net_device *netdev)
5027 +{
5028 + struct ethsw_dev_priv *priv = netdev_priv(netdev);
5029 + struct list_head *pos;
5030 + struct ethsw_port_priv *port_priv = NULL;
5031 + int err;
5032 +
5033 + err = dpsw_disable(priv->mc_io, 0, priv->dpsw_handle);
5034 + if (err) {
5035 + netdev_err(netdev, "dpsw_disable err %d\n", err);
5036 + return err;
5037 + }
5038 +
5039 + list_for_each(pos, &priv->port_list) {
5040 + port_priv = list_entry(pos, struct ethsw_port_priv, list);
5041 + err = dev_close(port_priv->netdev);
5042 + if (err)
5043 + netdev_err(port_priv->netdev,
5044 + "dev_close err %d\n", err);
5045 + }
5046 +
5047 + return 0;
5048 +}
5049 +
5050 +static int ethsw_add_vlan(struct net_device *netdev, u16 vid)
5051 +{
5052 + struct ethsw_dev_priv *priv = netdev_priv(netdev);
5053 + int err;
5054 +
5055 + struct dpsw_vlan_cfg vcfg = {
5056 + /* TODO: add support for VLAN private FDBs */
5057 + .fdb_id = 0,
5058 + };
5059 + if (priv->vlans[vid]) {
5060 + netdev_err(netdev, "VLAN already configured\n");
5061 + return -EEXIST;
5062 + }
5063 +
5064 + err = dpsw_vlan_add(priv->mc_io, 0, priv->dpsw_handle, vid, &vcfg);
5065 + if (err) {
5066 + netdev_err(netdev, "dpsw_vlan_add err %d\n", err);
5067 + return err;
5068 + }
5069 + priv->vlans[vid] = ETHSW_VLAN_MEMBER;
5070 +
5071 + return 0;
5072 +}
5073 +
5074 +static int ethsw_port_add_vlan(struct net_device *netdev, u16 vid, u16 flags)
5075 +{
5076 + struct ethsw_port_priv *port_priv = netdev_priv(netdev);
5077 + struct ethsw_dev_priv *priv = port_priv->ethsw_priv;
5078 + int err;
5079 +
5080 + struct dpsw_vlan_if_cfg vcfg = {
5081 + .num_ifs = 1,
5082 + .if_id[0] = port_priv->port_index,
5083 + };
5084 +
5085 + if (port_priv->vlans[vid]) {
5086 + netdev_err(netdev, "VLAN already configured\n");
5087 + return -EEXIST;
5088 + }
5089 +
5090 + if (flags & BRIDGE_VLAN_INFO_PVID && netif_oper_up(netdev)) {
5091 + netdev_err(netdev, "interface must be down to change PVID!\n");
5092 + return -EBUSY;
5093 + }
5094 +
5095 + err = dpsw_vlan_add_if(priv->mc_io, 0, priv->dpsw_handle, vid, &vcfg);
5096 + if (err) {
5097 + netdev_err(netdev, "dpsw_vlan_add_if err %d\n", err);
5098 + return err;
5099 + }
5100 + port_priv->vlans[vid] = ETHSW_VLAN_MEMBER;
5101 +
5102 + if (flags & BRIDGE_VLAN_INFO_UNTAGGED) {
5103 + err = dpsw_vlan_add_if_untagged(priv->mc_io, 0,
5104 + priv->dpsw_handle, vid, &vcfg);
5105 + if (err) {
5106 + netdev_err(netdev, "dpsw_vlan_add_if_untagged err %d\n",
5107 + err);
5108 + return err;
5109 + }
5110 + port_priv->vlans[vid] |= ETHSW_VLAN_UNTAGGED;
5111 + }
5112 +
5113 + if (flags & BRIDGE_VLAN_INFO_PVID) {
5114 + struct dpsw_tci_cfg tci_cfg = {
5115 + /* TODO: at least add better defaults if these cannot
5116 + * be configured
5117 + */
5118 + .pcp = 0,
5119 + .dei = 0,
5120 + .vlan_id = vid,
5121 + };
5122 +
5123 + err = dpsw_if_set_tci(priv->mc_io, 0, priv->dpsw_handle,
5124 + port_priv->port_index, &tci_cfg);
5125 + if (err) {
5126 + netdev_err(netdev, "dpsw_if_set_tci err %d\n", err);
5127 + return err;
5128 + }
5129 + port_priv->vlans[vid] |= ETHSW_VLAN_PVID;
5130 + }
5131 +
5132 + return 0;
5133 +}
5134 +
5135 +static const struct nla_policy ifla_br_policy[IFLA_MAX+1] = {
5136 + [IFLA_BRIDGE_FLAGS] = { .type = NLA_U16 },
5137 + [IFLA_BRIDGE_MODE] = { .type = NLA_U16 },
5138 + [IFLA_BRIDGE_VLAN_INFO] = { .type = NLA_BINARY,
5139 + .len = sizeof(struct bridge_vlan_info), },
5140 +};
5141 +
5142 +static int ethsw_setlink_af_spec(struct net_device *netdev,
5143 + struct nlattr **tb)
5144 +{
5145 + struct bridge_vlan_info *vinfo;
5146 + struct ethsw_dev_priv *priv = NULL;
5147 + struct ethsw_port_priv *port_priv = NULL;
5148 + int err = 0;
5149 +
5150 + if (!tb[IFLA_BRIDGE_VLAN_INFO]) {
5151 + netdev_err(netdev, "no VLAN INFO in nlmsg\n");
5152 + return -EOPNOTSUPP;
5153 + }
5154 +
5155 + vinfo = nla_data(tb[IFLA_BRIDGE_VLAN_INFO]);
5156 +
5157 + if (!vinfo->vid || vinfo->vid > VLAN_VID_MASK)
5158 + return -EINVAL;
5159 +
5160 + __get_priv(netdev, &priv, &port_priv);
5161 +
5162 + if (!port_priv || !priv->vlans[vinfo->vid]) {
5163 + /* command targets switch device or this is a new VLAN */
5164 + err = ethsw_add_vlan(priv->netdev, vinfo->vid);
5165 + if (err)
5166 + return err;
5167 +
5168 + /* command targets switch device; mark it*/
5169 + if (!port_priv)
5170 + priv->vlans[vinfo->vid] |= ETHSW_VLAN_GLOBAL;
5171 + }
5172 +
5173 + if (port_priv) {
5174 + /* command targets switch port */
5175 + err = ethsw_port_add_vlan(netdev, vinfo->vid, vinfo->flags);
5176 + if (err)
5177 + return err;
5178 + }
5179 +
5180 + return 0;
5181 +}
5182 +
5183 +static const struct nla_policy ifla_brport_policy[IFLA_BRPORT_MAX + 1] = {
5184 + [IFLA_BRPORT_STATE] = { .type = NLA_U8 },
5185 + [IFLA_BRPORT_COST] = { .type = NLA_U32 },
5186 + [IFLA_BRPORT_PRIORITY] = { .type = NLA_U16 },
5187 + [IFLA_BRPORT_MODE] = { .type = NLA_U8 },
5188 + [IFLA_BRPORT_GUARD] = { .type = NLA_U8 },
5189 + [IFLA_BRPORT_PROTECT] = { .type = NLA_U8 },
5190 + [IFLA_BRPORT_LEARNING] = { .type = NLA_U8 },
5191 + [IFLA_BRPORT_UNICAST_FLOOD] = { .type = NLA_U8 },
5192 +};
5193 +
5194 +static int ethsw_set_learning(struct net_device *netdev, u8 flag)
5195 +{
5196 + struct ethsw_dev_priv *priv = netdev_priv(netdev);
5197 + enum dpsw_fdb_learning_mode learn_mode;
5198 + int err;
5199 +
5200 + if (flag)
5201 + learn_mode = DPSW_FDB_LEARNING_MODE_HW;
5202 + else
5203 + learn_mode = DPSW_FDB_LEARNING_MODE_DIS;
5204 +
5205 + err = dpsw_fdb_set_learning_mode(priv->mc_io, 0, priv->dpsw_handle,
5206 + 0, learn_mode);
5207 + if (err) {
5208 + netdev_err(netdev, "dpsw_fdb_set_learning_mode err %d\n", err);
5209 + return err;
5210 + }
5211 + priv->learning = !!flag;
5212 +
5213 + return 0;
5214 +}
5215 +
5216 +static int ethsw_port_set_flood(struct net_device *netdev, u8 flag)
5217 +{
5218 + struct ethsw_port_priv *port_priv = netdev_priv(netdev);
5219 + struct ethsw_dev_priv *priv = port_priv->ethsw_priv;
5220 + int err;
5221 +
5222 + err = dpsw_if_set_flooding(priv->mc_io, 0, priv->dpsw_handle,
5223 + port_priv->port_index, (int)flag);
5224 + if (err) {
5225 + netdev_err(netdev, "dpsw_fdb_set_learning_mode err %d\n", err);
5226 + return err;
5227 + }
5228 + priv->flood = !!flag;
5229 +
5230 + return 0;
5231 +}
5232 +
5233 +static int ethsw_port_set_state(struct net_device *netdev, u8 state)
5234 +{
5235 + struct ethsw_port_priv *port_priv = netdev_priv(netdev);
5236 + struct ethsw_dev_priv *priv = port_priv->ethsw_priv;
5237 + u8 old_state = port_priv->stp_state;
5238 + int err;
5239 +
5240 + struct dpsw_stp_cfg stp_cfg = {
5241 + .vlan_id = 1,
5242 + .state = state,
5243 + };
5244 + /* TODO: check port state, interface may be down */
5245 +
5246 + if (state > BR_STATE_BLOCKING)
5247 + return -EINVAL;
5248 +
5249 + if (state == port_priv->stp_state)
5250 + return 0;
5251 +
5252 + if (state == BR_STATE_DISABLED) {
5253 + port_priv->stp_state = state;
5254 +
5255 + err = ethsw_port_stop(netdev);
5256 + if (err)
5257 + goto error;
5258 + } else {
5259 + err = dpsw_if_set_stp(priv->mc_io, 0, priv->dpsw_handle,
5260 + port_priv->port_index, &stp_cfg);
5261 + if (err) {
5262 + netdev_err(netdev, "dpsw_if_set_stp err %d\n", err);
5263 + return err;
5264 + }
5265 +
5266 + port_priv->stp_state = state;
5267 +
5268 + if (old_state == BR_STATE_DISABLED) {
5269 + err = ethsw_port_open(netdev);
5270 + if (err)
5271 + goto error;
5272 + }
5273 + }
5274 +
5275 + return 0;
5276 +error:
5277 + port_priv->stp_state = old_state;
5278 + return err;
5279 +}
5280 +
5281 +static int ethsw_setlink_protinfo(struct net_device *netdev,
5282 + struct nlattr **tb)
5283 +{
5284 + struct ethsw_dev_priv *priv;
5285 + struct ethsw_port_priv *port_priv = NULL;
5286 + int err = 0;
5287 +
5288 + __get_priv(netdev, &priv, &port_priv);
5289 +
5290 + if (tb[IFLA_BRPORT_LEARNING]) {
5291 + u8 flag = nla_get_u8(tb[IFLA_BRPORT_LEARNING]);
5292 +
5293 + if (port_priv)
5294 + netdev_warn(netdev,
5295 + "learning set on whole switch dev\n");
5296 +
5297 + err = ethsw_set_learning(priv->netdev, flag);
5298 + if (err)
5299 + return err;
5300 +
5301 + } else if (tb[IFLA_BRPORT_UNICAST_FLOOD] && port_priv) {
5302 + u8 flag = nla_get_u8(tb[IFLA_BRPORT_UNICAST_FLOOD]);
5303 +
5304 + err = ethsw_port_set_flood(port_priv->netdev, flag);
5305 + if (err)
5306 + return err;
5307 +
5308 + } else if (tb[IFLA_BRPORT_STATE] && port_priv) {
5309 + u8 state = nla_get_u8(tb[IFLA_BRPORT_STATE]);
5310 +
5311 + err = ethsw_port_set_state(port_priv->netdev, state);
5312 + if (err)
5313 + return err;
5314 +
5315 + } else {
5316 + return -EOPNOTSUPP;
5317 + }
5318 +
5319 + return 0;
5320 +}
5321 +
5322 +static int ethsw_setlink(struct net_device *netdev,
5323 + struct nlmsghdr *nlh,
5324 + u16 flags)
5325 +{
5326 + struct nlattr *attr;
5327 + struct nlattr *tb[(IFLA_BRIDGE_MAX > IFLA_BRPORT_MAX) ?
5328 + IFLA_BRIDGE_MAX : IFLA_BRPORT_MAX+1];
5329 + int err = 0;
5330 +
5331 + attr = nlmsg_find_attr(nlh, sizeof(struct ifinfomsg), IFLA_AF_SPEC);
5332 + if (attr) {
5333 + err = nla_parse_nested(tb, IFLA_BRIDGE_MAX, attr,
5334 + ifla_br_policy);
5335 + if (err) {
5336 + netdev_err(netdev,
5337 + "nla_parse_nested for br_policy err %d\n",
5338 + err);
5339 + return err;
5340 + }
5341 +
5342 + err = ethsw_setlink_af_spec(netdev, tb);
5343 + return err;
5344 + }
5345 +
5346 + attr = nlmsg_find_attr(nlh, sizeof(struct ifinfomsg), IFLA_PROTINFO);
5347 + if (attr) {
5348 + err = nla_parse_nested(tb, IFLA_BRPORT_MAX, attr,
5349 + ifla_brport_policy);
5350 + if (err) {
5351 + netdev_err(netdev,
5352 + "nla_parse_nested for brport_policy err %d\n",
5353 + err);
5354 + return err;
5355 + }
5356 +
5357 + err = ethsw_setlink_protinfo(netdev, tb);
5358 + return err;
5359 + }
5360 +
5361 + netdev_err(netdev, "nlmsg_find_attr found no AF_SPEC/PROTINFO\n");
5362 + return -EOPNOTSUPP;
5363 +}
5364 +
5365 +static int __nla_put_netdev(struct sk_buff *skb, struct net_device *netdev,
5366 + struct ethsw_dev_priv *priv)
5367 +{
5368 + u8 operstate = netif_running(netdev) ? netdev->operstate : IF_OPER_DOWN;
5369 + int iflink;
5370 + int err;
5371 +
5372 + err = nla_put_string(skb, IFLA_IFNAME, netdev->name);
5373 + if (err)
5374 + goto nla_put_err;
5375 + err = nla_put_u32(skb, IFLA_MASTER, priv->netdev->ifindex);
5376 + if (err)
5377 + goto nla_put_err;
5378 + err = nla_put_u32(skb, IFLA_MTU, netdev->mtu);
5379 + if (err)
5380 + goto nla_put_err;
5381 + err = nla_put_u8(skb, IFLA_OPERSTATE, operstate);
5382 + if (err)
5383 + goto nla_put_err;
5384 + if (netdev->addr_len) {
5385 + err = nla_put(skb, IFLA_ADDRESS, netdev->addr_len,
5386 + netdev->dev_addr);
5387 + if (err)
5388 + goto nla_put_err;
5389 + }
5390 +
5391 + iflink = dev_get_iflink(netdev);
5392 + if (netdev->ifindex != iflink) {
5393 + err = nla_put_u32(skb, IFLA_LINK, iflink);
5394 + if (err)
5395 + goto nla_put_err;
5396 + }
5397 +
5398 + return 0;
5399 +
5400 +nla_put_err:
5401 + netdev_err(netdev, "nla_put_ err %d\n", err);
5402 + return err;
5403 +}
5404 +
5405 +static int __nla_put_port(struct sk_buff *skb, struct net_device *netdev,
5406 + struct ethsw_port_priv *port_priv)
5407 +{
5408 + struct nlattr *nest;
5409 + int err;
5410 +
5411 + u8 stp_state = port_priv->stp_state;
5412 +
5413 + if (port_priv->stp_state == DPSW_STP_STATE_BLOCKING)
5414 + stp_state = BR_STATE_BLOCKING;
5415 +
5416 + nest = nla_nest_start(skb, IFLA_PROTINFO | NLA_F_NESTED);
5417 + if (!nest) {
5418 + netdev_err(netdev, "nla_nest_start failed\n");
5419 + return -ENOMEM;
5420 + }
5421 +
5422 + err = nla_put_u8(skb, IFLA_BRPORT_STATE, stp_state);
5423 + if (err)
5424 + goto nla_put_err;
5425 + err = nla_put_u16(skb, IFLA_BRPORT_PRIORITY, 0);
5426 + if (err)
5427 + goto nla_put_err;
5428 + err = nla_put_u32(skb, IFLA_BRPORT_COST, 0);
5429 + if (err)
5430 + goto nla_put_err;
5431 + err = nla_put_u8(skb, IFLA_BRPORT_MODE, 0);
5432 + if (err)
5433 + goto nla_put_err;
5434 + err = nla_put_u8(skb, IFLA_BRPORT_GUARD, 0);
5435 + if (err)
5436 + goto nla_put_err;
5437 + err = nla_put_u8(skb, IFLA_BRPORT_PROTECT, 0);
5438 + if (err)
5439 + goto nla_put_err;
5440 + err = nla_put_u8(skb, IFLA_BRPORT_FAST_LEAVE, 0);
5441 + if (err)
5442 + goto nla_put_err;
5443 + err = nla_put_u8(skb, IFLA_BRPORT_LEARNING,
5444 + port_priv->ethsw_priv->learning);
5445 + if (err)
5446 + goto nla_put_err;
5447 + err = nla_put_u8(skb, IFLA_BRPORT_UNICAST_FLOOD,
5448 + port_priv->ethsw_priv->flood);
5449 + if (err)
5450 + goto nla_put_err;
5451 + nla_nest_end(skb, nest);
5452 +
5453 + return 0;
5454 +
5455 +nla_put_err:
5456 + netdev_err(netdev, "nla_put_ err %d\n", err);
5457 + nla_nest_cancel(skb, nest);
5458 + return err;
5459 +}
5460 +
5461 +static int __nla_put_vlan(struct sk_buff *skb, struct net_device *netdev,
5462 + struct ethsw_dev_priv *priv,
5463 + struct ethsw_port_priv *port_priv)
5464 +{
5465 + struct nlattr *nest;
5466 + struct bridge_vlan_info vinfo;
5467 + const char *vlans;
5468 + u16 i;
5469 + int err;
5470 +
5471 + nest = nla_nest_start(skb, IFLA_AF_SPEC);
5472 + if (!nest) {
5473 + netdev_err(netdev, "nla_nest_start failed");
5474 + return -ENOMEM;
5475 + }
5476 +
5477 + if (port_priv)
5478 + vlans = port_priv->vlans;
5479 + else
5480 + vlans = priv->vlans;
5481 +
5482 + for (i = 0; i < VLAN_VID_MASK+1; i++) {
5483 + vinfo.flags = 0;
5484 + vinfo.vid = i;
5485 +
5486 + if (vlans[i] & ETHSW_VLAN_UNTAGGED)
5487 + vinfo.flags |= BRIDGE_VLAN_INFO_UNTAGGED;
5488 +
5489 + if (vlans[i] & ETHSW_VLAN_PVID)
5490 + vinfo.flags |= BRIDGE_VLAN_INFO_PVID;
5491 +
5492 + if (vlans[i] & ETHSW_VLAN_MEMBER) {
5493 + err = nla_put(skb, IFLA_BRIDGE_VLAN_INFO,
5494 + sizeof(vinfo), &vinfo);
5495 + if (err)
5496 + goto nla_put_err;
5497 + }
5498 + }
5499 +
5500 + nla_nest_end(skb, nest);
5501 +
5502 + return 0;
5503 +nla_put_err:
5504 + netdev_err(netdev, "nla_put_ err %d\n", err);
5505 + nla_nest_cancel(skb, nest);
5506 + return err;
5507 +}
5508 +
5509 +static int ethsw_getlink(struct sk_buff *skb, u32 pid, u32 seq,
5510 + struct net_device *netdev, u32 filter_mask,
5511 + int nlflags)
5512 +{
5513 + struct ethsw_dev_priv *priv;
5514 + struct ethsw_port_priv *port_priv = NULL;
5515 + struct ifinfomsg *hdr;
5516 + struct nlmsghdr *nlh;
5517 + int err;
5518 +
5519 + __get_priv(netdev, &priv, &port_priv);
5520 +
5521 + nlh = nlmsg_put(skb, pid, seq, RTM_NEWLINK, sizeof(*hdr), NLM_F_MULTI);
5522 + if (!nlh)
5523 + return -EMSGSIZE;
5524 +
5525 + hdr = nlmsg_data(nlh);
5526 + memset(hdr, 0, sizeof(*hdr));
5527 + hdr->ifi_family = AF_BRIDGE;
5528 + hdr->ifi_type = netdev->type;
5529 + hdr->ifi_index = netdev->ifindex;
5530 + hdr->ifi_flags = dev_get_flags(netdev);
5531 +
5532 + err = __nla_put_netdev(skb, netdev, priv);
5533 + if (err)
5534 + goto nla_put_err;
5535 +
5536 + if (port_priv) {
5537 + err = __nla_put_port(skb, netdev, port_priv);
5538 + if (err)
5539 + goto nla_put_err;
5540 + }
5541 +
5542 + /* Check if the VID information is requested */
5543 + if (filter_mask & RTEXT_FILTER_BRVLAN) {
5544 + err = __nla_put_vlan(skb, netdev, priv, port_priv);
5545 + if (err)
5546 + goto nla_put_err;
5547 + }
5548 +
5549 + nlmsg_end(skb, nlh);
5550 + return skb->len;
5551 +
5552 +nla_put_err:
5553 + nlmsg_cancel(skb, nlh);
5554 + return -EMSGSIZE;
5555 +}
5556 +
5557 +static int ethsw_dellink_switch(struct ethsw_dev_priv *priv, u16 vid)
5558 +{
5559 + struct list_head *pos;
5560 + struct ethsw_port_priv *ppriv_local = NULL;
5561 + int err = 0;
5562 +
5563 + if (!priv->vlans[vid])
5564 + return -ENOENT;
5565 +
5566 + err = dpsw_vlan_remove(priv->mc_io, 0, priv->dpsw_handle, vid);
5567 + if (err) {
5568 + netdev_err(priv->netdev, "dpsw_vlan_remove err %d\n", err);
5569 + return err;
5570 + }
5571 + priv->vlans[vid] = 0;
5572 +
5573 + list_for_each(pos, &priv->port_list) {
5574 + ppriv_local = list_entry(pos, struct ethsw_port_priv,
5575 + list);
5576 + ppriv_local->vlans[vid] = 0;
5577 + }
5578 +
5579 + return 0;
5580 +}
5581 +
5582 +static int ethsw_dellink_port(struct ethsw_dev_priv *priv,
5583 + struct ethsw_port_priv *port_priv,
5584 + u16 vid)
5585 +{
5586 + struct list_head *pos;
5587 + struct ethsw_port_priv *ppriv_local = NULL;
5588 + struct dpsw_vlan_if_cfg vcfg = {
5589 + .num_ifs = 1,
5590 + .if_id[0] = port_priv->port_index,
5591 + };
5592 + unsigned int count = 0;
5593 + int err = 0;
5594 +
5595 + if (!port_priv->vlans[vid])
5596 + return -ENOENT;
5597 +
5598 + /* VLAN will be deleted from switch if global flag is not set
5599 + * and is configured on only one port
5600 + */
5601 + if (!(priv->vlans[vid] & ETHSW_VLAN_GLOBAL)) {
5602 + list_for_each(pos, &priv->port_list) {
5603 + ppriv_local = list_entry(pos, struct ethsw_port_priv,
5604 + list);
5605 + if (ppriv_local->vlans[vid] & ETHSW_VLAN_MEMBER)
5606 + count++;
5607 + }
5608 +
5609 + if (count == 1)
5610 + return ethsw_dellink_switch(priv, vid);
5611 + }
5612 +
5613 + err = dpsw_vlan_remove_if(priv->mc_io, 0, priv->dpsw_handle,
5614 + vid, &vcfg);
5615 + if (err) {
5616 + netdev_err(priv->netdev, "dpsw_vlan_remove_if err %d\n", err);
5617 + return err;
5618 + }
5619 + port_priv->vlans[vid] = 0;
5620 + return 0;
5621 +}
5622 +
5623 +static int ethsw_dellink(struct net_device *netdev,
5624 + struct nlmsghdr *nlh,
5625 + u16 flags)
5626 +{
5627 + struct nlattr *tb[IFLA_BRIDGE_MAX+1];
5628 + struct nlattr *spec;
5629 + struct bridge_vlan_info *vinfo;
5630 + struct ethsw_dev_priv *priv;
5631 + struct ethsw_port_priv *port_priv = NULL;
5632 + int err = 0;
5633 +
5634 + spec = nlmsg_find_attr(nlh, sizeof(struct ifinfomsg), IFLA_AF_SPEC);
5635 + if (!spec)
5636 + return 0;
5637 +
5638 + err = nla_parse_nested(tb, IFLA_BRIDGE_MAX, spec, ifla_br_policy);
5639 + if (err)
5640 + return err;
5641 +
5642 + if (!tb[IFLA_BRIDGE_VLAN_INFO])
5643 + return -EOPNOTSUPP;
5644 +
5645 + vinfo = nla_data(tb[IFLA_BRIDGE_VLAN_INFO]);
5646 +
5647 + if (!vinfo->vid || vinfo->vid > VLAN_VID_MASK)
5648 + return -EINVAL;
5649 +
5650 + __get_priv(netdev, &priv, &port_priv);
5651 +
5652 + /* decide if command targets switch device or port */
5653 + if (!port_priv)
5654 + err = ethsw_dellink_switch(priv, vinfo->vid);
5655 + else
5656 + err = ethsw_dellink_port(priv, port_priv, vinfo->vid);
5657 +
5658 + return err;
5659 +}
5660 +
5661 +static const struct net_device_ops ethsw_ops = {
5662 + .ndo_open = &ethsw_open,
5663 + .ndo_stop = &ethsw_stop,
5664 +
5665 + .ndo_bridge_setlink = &ethsw_setlink,
5666 + .ndo_bridge_getlink = &ethsw_getlink,
5667 + .ndo_bridge_dellink = &ethsw_dellink,
5668 +
5669 + .ndo_start_xmit = &ethsw_dropframe,
5670 +};
5671 +
5672 +/*--------------------------------------------------------------------------- */
5673 +/* switch port netdevice ops */
5674 +
5675 +static int _ethsw_port_carrier_state_sync(struct net_device *netdev)
5676 +{
5677 + struct ethsw_port_priv *port_priv = netdev_priv(netdev);
5678 + struct dpsw_link_state state;
5679 + int err;
5680 +
5681 + err = dpsw_if_get_link_state(port_priv->ethsw_priv->mc_io, 0,
5682 + port_priv->ethsw_priv->dpsw_handle,
5683 + port_priv->port_index, &state);
5684 + if (unlikely(err)) {
5685 + netdev_err(netdev, "dpsw_if_get_link_state() err %d\n", err);
5686 + return err;
5687 + }
5688 +
5689 + WARN_ONCE(state.up > 1, "Garbage read into link_state");
5690 +
5691 + if (state.up)
5692 + netif_carrier_on(port_priv->netdev);
5693 + else
5694 + netif_carrier_off(port_priv->netdev);
5695 +
5696 + return 0;
5697 +}
5698 +
5699 +static int ethsw_port_open(struct net_device *netdev)
5700 +{
5701 + struct ethsw_port_priv *port_priv = netdev_priv(netdev);
5702 + int err;
5703 +
5704 + if (!netif_oper_up(netdev) ||
5705 + port_priv->stp_state == BR_STATE_DISABLED)
5706 + return 0;
5707 +
5708 + err = dpsw_if_enable(port_priv->ethsw_priv->mc_io, 0,
5709 + port_priv->ethsw_priv->dpsw_handle,
5710 + port_priv->port_index);
5711 + if (err) {
5712 + netdev_err(netdev, "dpsw_if_enable err %d\n", err);
5713 + return err;
5714 + }
5715 +
5716 + return 0;
5717 +}
5718 +
5719 +static int ethsw_port_stop(struct net_device *netdev)
5720 +{
5721 + struct ethsw_port_priv *port_priv = netdev_priv(netdev);
5722 + int err;
5723 +
5724 + err = dpsw_if_disable(port_priv->ethsw_priv->mc_io, 0,
5725 + port_priv->ethsw_priv->dpsw_handle,
5726 + port_priv->port_index);
5727 + if (err) {
5728 + netdev_err(netdev, "dpsw_if_disable err %d\n", err);
5729 + return err;
5730 + }
5731 +
5732 + return 0;
5733 +}
5734 +
5735 +static int ethsw_port_fdb_add_uc(struct net_device *netdev,
5736 + const unsigned char *addr)
5737 +{
5738 + struct ethsw_port_priv *port_priv = netdev_priv(netdev);
5739 + struct dpsw_fdb_unicast_cfg entry = {0};
5740 + int err;
5741 +
5742 + entry.if_egress = port_priv->port_index;
5743 + entry.type = DPSW_FDB_ENTRY_STATIC;
5744 + ether_addr_copy(entry.mac_addr, addr);
5745 +
5746 + err = dpsw_fdb_add_unicast(port_priv->ethsw_priv->mc_io, 0,
5747 + port_priv->ethsw_priv->dpsw_handle,
5748 + 0, &entry);
5749 + if (err)
5750 + netdev_err(netdev, "dpsw_fdb_add_unicast err %d\n", err);
5751 + return err;
5752 +}
5753 +
5754 +static int ethsw_port_fdb_del_uc(struct net_device *netdev,
5755 + const unsigned char *addr)
5756 +{
5757 + struct ethsw_port_priv *port_priv = netdev_priv(netdev);
5758 + struct dpsw_fdb_unicast_cfg entry = {0};
5759 + int err;
5760 +
5761 + entry.if_egress = port_priv->port_index;
5762 + entry.type = DPSW_FDB_ENTRY_STATIC;
5763 + ether_addr_copy(entry.mac_addr, addr);
5764 +
5765 + err = dpsw_fdb_remove_unicast(port_priv->ethsw_priv->mc_io, 0,
5766 + port_priv->ethsw_priv->dpsw_handle,
5767 + 0, &entry);
5768 + if (err)
5769 + netdev_err(netdev, "dpsw_fdb_remove_unicast err %d\n", err);
5770 + return err;
5771 +}
5772 +
5773 +static int ethsw_port_fdb_add_mc(struct net_device *netdev,
5774 + const unsigned char *addr)
5775 +{
5776 + struct ethsw_port_priv *port_priv = netdev_priv(netdev);
5777 + struct dpsw_fdb_multicast_cfg entry = {0};
5778 + int err;
5779 +
5780 + ether_addr_copy(entry.mac_addr, addr);
5781 + entry.type = DPSW_FDB_ENTRY_STATIC;
5782 + entry.num_ifs = 1;
5783 + entry.if_id[0] = port_priv->port_index;
5784 +
5785 + err = dpsw_fdb_add_multicast(port_priv->ethsw_priv->mc_io, 0,
5786 + port_priv->ethsw_priv->dpsw_handle,
5787 + 0, &entry);
5788 + if (err)
5789 + netdev_err(netdev, "dpsw_fdb_add_multicast err %d\n", err);
5790 + return err;
5791 +}
5792 +
5793 +static int ethsw_port_fdb_del_mc(struct net_device *netdev,
5794 + const unsigned char *addr)
5795 +{
5796 + struct ethsw_port_priv *port_priv = netdev_priv(netdev);
5797 + struct dpsw_fdb_multicast_cfg entry = {0};
5798 + int err;
5799 +
5800 + ether_addr_copy(entry.mac_addr, addr);
5801 + entry.type = DPSW_FDB_ENTRY_STATIC;
5802 + entry.num_ifs = 1;
5803 + entry.if_id[0] = port_priv->port_index;
5804 +
5805 + err = dpsw_fdb_remove_multicast(port_priv->ethsw_priv->mc_io, 0,
5806 + port_priv->ethsw_priv->dpsw_handle,
5807 + 0, &entry);
5808 + if (err)
5809 + netdev_err(netdev, "dpsw_fdb_remove_multicast err %d\n", err);
5810 + return err;
5811 +}
5812 +
5813 +static int _lookup_address(struct net_device *netdev, int is_uc,
5814 + const unsigned char *addr)
5815 +{
5816 + struct netdev_hw_addr *ha;
5817 + struct netdev_hw_addr_list *list = (is_uc) ? &netdev->uc : &netdev->mc;
5818 +
5819 + netif_addr_lock_bh(netdev);
5820 + list_for_each_entry(ha, &list->list, list) {
5821 + if (ether_addr_equal(ha->addr, addr)) {
5822 + netif_addr_unlock_bh(netdev);
5823 + return 1;
5824 + }
5825 + }
5826 + netif_addr_unlock_bh(netdev);
5827 + return 0;
5828 +}
5829 +
5830 +static int ethsw_port_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
5831 + struct net_device *netdev,
5832 + const unsigned char *addr, u16 vid,
5833 + u16 flags)
5834 +{
5835 + struct list_head *pos;
5836 + struct ethsw_port_priv *port_priv = netdev_priv(netdev);
5837 + struct ethsw_dev_priv *priv = port_priv->ethsw_priv;
5838 + int err;
5839 +
5840 + /* TODO: add replace support when added to iproute bridge */
5841 + if (!(flags & NLM_F_REQUEST)) {
5842 + netdev_err(netdev,
5843 + "ethsw_port_fdb_add unexpected flags value %08x\n",
5844 + flags);
5845 + return -EINVAL;
5846 + }
5847 +
5848 + if (is_unicast_ether_addr(addr)) {
5849 + /* if entry cannot be replaced, return error if exists */
5850 + if (flags & NLM_F_EXCL || flags & NLM_F_APPEND) {
5851 + list_for_each(pos, &priv->port_list) {
5852 + port_priv = list_entry(pos,
5853 + struct ethsw_port_priv,
5854 + list);
5855 + if (_lookup_address(port_priv->netdev,
5856 + 1, addr))
5857 + return -EEXIST;
5858 + }
5859 + }
5860 +
5861 + err = ethsw_port_fdb_add_uc(netdev, addr);
5862 + if (err) {
5863 + netdev_err(netdev, "ethsw_port_fdb_add_uc err %d\n",
5864 + err);
5865 + return err;
5866 + }
5867 +
5868 + /* we might have replaced an existing entry for a different
5869 + * switch port, make sure the address doesn't linger in any
5870 + * port address list
5871 + */
5872 + list_for_each(pos, &priv->port_list) {
5873 + port_priv = list_entry(pos, struct ethsw_port_priv,
5874 + list);
5875 + dev_uc_del(port_priv->netdev, addr);
5876 + }
5877 +
5878 + err = dev_uc_add(netdev, addr);
5879 + if (err) {
5880 + netdev_err(netdev, "dev_uc_add err %d\n", err);
5881 + return err;
5882 + }
5883 + } else {
5884 + struct dpsw_fdb_multicast_cfg entry = {
5885 + .type = DPSW_FDB_ENTRY_STATIC,
5886 + .num_ifs = 0,
5887 + };
5888 +
5889 + /* check if address is already set on this port */
5890 + if (_lookup_address(netdev, 0, addr))
5891 + return -EEXIST;
5892 +
5893 + /* check if the address exists on other port */
5894 + ether_addr_copy(entry.mac_addr, addr);
5895 + err = dpsw_fdb_get_multicast(priv->mc_io, 0, priv->dpsw_handle,
5896 + 0, &entry);
5897 + if (!err) {
5898 + /* entry exists, can we replace it? */
5899 + if (flags & NLM_F_EXCL)
5900 + return -EEXIST;
5901 + } else if (err != -ENAVAIL) {
5902 + netdev_err(netdev, "dpsw_fdb_get_unicast err %d\n",
5903 + err);
5904 + return err;
5905 + }
5906 +
5907 + err = ethsw_port_fdb_add_mc(netdev, addr);
5908 + if (err) {
5909 + netdev_err(netdev, "ethsw_port_fdb_add_mc err %d\n",
5910 + err);
5911 + return err;
5912 + }
5913 +
5914 + err = dev_mc_add(netdev, addr);
5915 + if (err) {
5916 + netdev_err(netdev, "dev_mc_add err %d\n", err);
5917 + return err;
5918 + }
5919 + }
5920 +
5921 + return 0;
5922 +}
5923 +
5924 +static int ethsw_port_fdb_del(struct ndmsg *ndm, struct nlattr *tb[],
5925 + struct net_device *netdev,
5926 + const unsigned char *addr, u16 vid)
5927 +{
5928 + int err;
5929 +
5930 + if (is_unicast_ether_addr(addr)) {
5931 + err = ethsw_port_fdb_del_uc(netdev, addr);
5932 + if (err) {
5933 + netdev_err(netdev, "ethsw_port_fdb_del_uc err %d\n",
5934 + err);
5935 + return err;
5936 + }
5937 +
5938 + /* also delete if configured on port */
5939 + err = dev_uc_del(netdev, addr);
5940 + if (err && err != -ENOENT) {
5941 + netdev_err(netdev, "dev_uc_del err %d\n", err);
5942 + return err;
5943 + }
5944 + } else {
5945 + if (!_lookup_address(netdev, 0, addr))
5946 + return -ENOENT;
5947 +
5948 + err = dev_mc_del(netdev, addr);
5949 + if (err) {
5950 + netdev_err(netdev, "dev_mc_del err %d\n", err);
5951 + return err;
5952 + }
5953 +
5954 + err = ethsw_port_fdb_del_mc(netdev, addr);
5955 + if (err) {
5956 + netdev_err(netdev, "ethsw_port_fdb_del_mc err %d\n",
5957 + err);
5958 + return err;
5959 + }
5960 + }
5961 +
5962 + return 0;
5963 +}
5964 +
5965 +static struct rtnl_link_stats64 *
5966 +ethsw_port_get_stats(struct net_device *netdev,
5967 + struct rtnl_link_stats64 *storage)
5968 +{
5969 + struct ethsw_port_priv *port_priv = netdev_priv(netdev);
5970 + u64 tmp;
5971 + int err;
5972 +
5973 + err = dpsw_if_get_counter(port_priv->ethsw_priv->mc_io, 0,
5974 + port_priv->ethsw_priv->dpsw_handle,
5975 + port_priv->port_index,
5976 + DPSW_CNT_ING_FRAME, &storage->rx_packets);
5977 + if (err)
5978 + goto error;
5979 +
5980 + err = dpsw_if_get_counter(port_priv->ethsw_priv->mc_io, 0,
5981 + port_priv->ethsw_priv->dpsw_handle,
5982 + port_priv->port_index,
5983 + DPSW_CNT_EGR_FRAME, &storage->tx_packets);
5984 + if (err)
5985 + goto error;
5986 +
5987 + err = dpsw_if_get_counter(port_priv->ethsw_priv->mc_io, 0,
5988 + port_priv->ethsw_priv->dpsw_handle,
5989 + port_priv->port_index,
5990 + DPSW_CNT_ING_BYTE, &storage->rx_bytes);
5991 + if (err)
5992 + goto error;
5993 +
5994 + err = dpsw_if_get_counter(port_priv->ethsw_priv->mc_io, 0,
5995 + port_priv->ethsw_priv->dpsw_handle,
5996 + port_priv->port_index,
5997 + DPSW_CNT_EGR_BYTE, &storage->tx_bytes);
5998 + if (err)
5999 + goto error;
6000 +
6001 + err = dpsw_if_get_counter(port_priv->ethsw_priv->mc_io, 0,
6002 + port_priv->ethsw_priv->dpsw_handle,
6003 + port_priv->port_index,
6004 + DPSW_CNT_ING_FRAME_DISCARD,
6005 + &storage->rx_dropped);
6006 + if (err)
6007 + goto error;
6008 +
6009 + err = dpsw_if_get_counter(port_priv->ethsw_priv->mc_io, 0,
6010 + port_priv->ethsw_priv->dpsw_handle,
6011 + port_priv->port_index,
6012 + DPSW_CNT_ING_FLTR_FRAME,
6013 + &tmp);
6014 + if (err)
6015 + goto error;
6016 + storage->rx_dropped += tmp;
6017 +
6018 + err = dpsw_if_get_counter(port_priv->ethsw_priv->mc_io, 0,
6019 + port_priv->ethsw_priv->dpsw_handle,
6020 + port_priv->port_index,
6021 + DPSW_CNT_EGR_FRAME_DISCARD,
6022 + &storage->tx_dropped);
6023 + if (err)
6024 + goto error;
6025 +
6026 + return storage;
6027 +
6028 +error:
6029 + netdev_err(netdev, "dpsw_if_get_counter err %d\n", err);
6030 + return storage;
6031 +}
6032 +
6033 +static const struct net_device_ops ethsw_port_ops = {
6034 + .ndo_open = &ethsw_port_open,
6035 + .ndo_stop = &ethsw_port_stop,
6036 +
6037 + .ndo_fdb_add = &ethsw_port_fdb_add,
6038 + .ndo_fdb_del = &ethsw_port_fdb_del,
6039 + .ndo_fdb_dump = &ndo_dflt_fdb_dump,
6040 +
6041 + .ndo_get_stats64 = &ethsw_port_get_stats,
6042 +
6043 + .ndo_start_xmit = &ethsw_dropframe,
6044 +};
6045 +
6046 +static struct {
6047 + enum dpsw_counter id;
6048 + char name[ETH_GSTRING_LEN];
6049 +} ethsw_ethtool_counters[] = {
6050 + {DPSW_CNT_ING_FRAME, "rx frames"},
6051 + {DPSW_CNT_ING_BYTE, "rx bytes"},
6052 + {DPSW_CNT_ING_FLTR_FRAME, "rx filtered frames"},
6053 + {DPSW_CNT_ING_FRAME_DISCARD, "rx discarded frames"},
6054 + {DPSW_CNT_ING_BCAST_FRAME, "rx b-cast frames"},
6055 + {DPSW_CNT_ING_BCAST_BYTES, "rx b-cast bytes"},
6056 + {DPSW_CNT_ING_MCAST_FRAME, "rx m-cast frames"},
6057 + {DPSW_CNT_ING_MCAST_BYTE, "rx m-cast bytes"},
6058 + {DPSW_CNT_EGR_FRAME, "tx frames"},
6059 + {DPSW_CNT_EGR_BYTE, "tx bytes"},
6060 + {DPSW_CNT_EGR_FRAME_DISCARD, "tx discarded frames"},
6061 +
6062 +};
6063 +
6064 +static int ethsw_ethtool_get_sset_count(struct net_device *dev, int sset)
6065 +{
6066 + switch (sset) {
6067 + case ETH_SS_STATS:
6068 + return ARRAY_SIZE(ethsw_ethtool_counters);
6069 + default:
6070 + return -EOPNOTSUPP;
6071 + }
6072 +}
6073 +
6074 +static void ethsw_ethtool_get_strings(struct net_device *netdev,
6075 + u32 stringset, u8 *data)
6076 +{
6077 + int i;
6078 +
6079 + switch (stringset) {
6080 + case ETH_SS_STATS:
6081 + for (i = 0; i < ARRAY_SIZE(ethsw_ethtool_counters); i++)
6082 + memcpy(data + i * ETH_GSTRING_LEN,
6083 + ethsw_ethtool_counters[i].name, ETH_GSTRING_LEN);
6084 + break;
6085 + }
6086 +}
6087 +
6088 +static void ethsw_ethtool_get_stats(struct net_device *netdev,
6089 + struct ethtool_stats *stats,
6090 + u64 *data)
6091 +{
6092 + struct ethsw_port_priv *port_priv = netdev_priv(netdev);
6093 + int i;
6094 + int err;
6095 +
6096 + for (i = 0; i < ARRAY_SIZE(ethsw_ethtool_counters); i++) {
6097 + err = dpsw_if_get_counter(port_priv->ethsw_priv->mc_io, 0,
6098 + port_priv->ethsw_priv->dpsw_handle,
6099 + port_priv->port_index,
6100 + ethsw_ethtool_counters[i].id,
6101 + &data[i]);
6102 + if (err)
6103 + netdev_err(netdev, "dpsw_if_get_counter[%s] err %d\n",
6104 + ethsw_ethtool_counters[i].name, err);
6105 + }
6106 +}
6107 +
6108 +static const struct ethtool_ops ethsw_port_ethtool_ops = {
6109 + .get_strings = &ethsw_ethtool_get_strings,
6110 + .get_ethtool_stats = &ethsw_ethtool_get_stats,
6111 + .get_sset_count = &ethsw_ethtool_get_sset_count,
6112 +};
6113 +
6114 +/* -------------------------------------------------------------------------- */
6115 +/* ethsw driver functions */
6116 +
6117 +static int ethsw_links_state_update(struct ethsw_dev_priv *priv)
6118 +{
6119 + struct list_head *pos;
6120 + struct ethsw_port_priv *port_priv;
6121 + int err;
6122 +
6123 + list_for_each(pos, &priv->port_list) {
6124 + port_priv = list_entry(pos, struct ethsw_port_priv,
6125 + list);
6126 +
6127 + err = _ethsw_port_carrier_state_sync(port_priv->netdev);
6128 + if (err)
6129 + netdev_err(port_priv->netdev,
6130 + "_ethsw_port_carrier_state_sync err %d\n",
6131 + err);
6132 + }
6133 +
6134 + return 0;
6135 +}
6136 +
6137 +static irqreturn_t ethsw_irq0_handler(int irq_num, void *arg)
6138 +{
6139 + return IRQ_WAKE_THREAD;
6140 +}
6141 +
6142 +static irqreturn_t _ethsw_irq0_handler_thread(int irq_num, void *arg)
6143 +{
6144 + struct device *dev = (struct device *)arg;
6145 + struct fsl_mc_device *sw_dev = to_fsl_mc_device(dev);
6146 + struct net_device *netdev = dev_get_drvdata(dev);
6147 + struct ethsw_dev_priv *priv = netdev_priv(netdev);
6148 +
6149 + struct fsl_mc_io *io = priv->mc_io;
6150 + uint16_t token = priv->dpsw_handle;
6151 + int irq_index = DPSW_IRQ_INDEX_IF;
6152 +
6153 + /* Mask the events and the if_id reserved bits to be cleared on read */
6154 + uint32_t status = DPSW_IRQ_EVENT_LINK_CHANGED | 0xFFFF0000;
6155 + int err;
6156 +
6157 + /* Sanity check */
6158 + if (WARN_ON(!sw_dev || !sw_dev->irqs || !sw_dev->irqs[irq_index]))
6159 + goto out;
6160 + if (WARN_ON(sw_dev->irqs[irq_index]->msi_desc->irq != irq_num))
6161 + goto out;
6162 +
6163 + err = dpsw_get_irq_status(io, 0, token, irq_index, &status);
6164 + if (unlikely(err)) {
6165 + netdev_err(netdev, "Can't get irq status (err %d)", err);
6166 +
6167 + err = dpsw_clear_irq_status(io, 0, token, irq_index,
6168 + 0xFFFFFFFF);
6169 + if (unlikely(err))
6170 + netdev_err(netdev, "Can't clear irq status (err %d)",
6171 + err);
6172 + goto out;
6173 + }
6174 +
6175 + if (status & DPSW_IRQ_EVENT_LINK_CHANGED) {
6176 + err = ethsw_links_state_update(priv);
6177 + if (unlikely(err))
6178 + goto out;
6179 + }
6180 +
6181 +out:
6182 + return IRQ_HANDLED;
6183 +}
6184 +
6185 +static int ethsw_setup_irqs(struct fsl_mc_device *sw_dev)
6186 +{
6187 + struct device *dev = &sw_dev->dev;
6188 + struct net_device *netdev = dev_get_drvdata(dev);
6189 + struct ethsw_dev_priv *priv = netdev_priv(netdev);
6190 + int err = 0;
6191 + struct fsl_mc_device_irq *irq;
6192 + const int irq_index = DPSW_IRQ_INDEX_IF;
6193 + uint32_t mask = DPSW_IRQ_EVENT_LINK_CHANGED;
6194 +
6195 + err = fsl_mc_allocate_irqs(sw_dev);
6196 + if (unlikely(err)) {
6197 + dev_err(dev, "MC irqs allocation failed\n");
6198 + return err;
6199 + }
6200 +
6201 + if (WARN_ON(sw_dev->obj_desc.irq_count != DPSW_MAX_IRQ_NUM)) {
6202 + err = -EINVAL;
6203 + goto free_irq;
6204 + }
6205 +
6206 + err = dpsw_set_irq_enable(priv->mc_io, 0, priv->dpsw_handle,
6207 + irq_index, 0);
6208 + if (unlikely(err)) {
6209 + dev_err(dev, "dpsw_set_irq_enable err %d\n", err);
6210 + goto free_irq;
6211 + }
6212 +
6213 + irq = sw_dev->irqs[irq_index];
6214 +
6215 + err = devm_request_threaded_irq(dev, irq->msi_desc->irq,
6216 + ethsw_irq0_handler,
6217 + _ethsw_irq0_handler_thread,
6218 + IRQF_NO_SUSPEND | IRQF_ONESHOT,
6219 + dev_name(dev), dev);
6220 + if (unlikely(err)) {
6221 + dev_err(dev, "devm_request_threaded_irq(): %d", err);
6222 + goto free_irq;
6223 + }
6224 +
6225 + err = dpsw_set_irq_mask(priv->mc_io, 0, priv->dpsw_handle,
6226 + irq_index, mask);
6227 + if (unlikely(err)) {
6228 + dev_err(dev, "dpsw_set_irq_mask(): %d", err);
6229 + goto free_devm_irq;
6230 + }
6231 +
6232 + err = dpsw_set_irq_enable(priv->mc_io, 0, priv->dpsw_handle,
6233 + irq_index, 1);
6234 + if (unlikely(err)) {
6235 + dev_err(dev, "dpsw_set_irq_enable(): %d", err);
6236 + goto free_devm_irq;
6237 + }
6238 +
6239 + return 0;
6240 +
6241 +free_devm_irq:
6242 + devm_free_irq(dev, irq->msi_desc->irq, dev);
6243 +free_irq:
6244 + fsl_mc_free_irqs(sw_dev);
6245 + return err;
6246 +}
6247 +
6248 +static void ethsw_teardown_irqs(struct fsl_mc_device *sw_dev)
6249 +{
6250 + struct device *dev = &sw_dev->dev;
6251 + struct net_device *netdev = dev_get_drvdata(dev);
6252 + struct ethsw_dev_priv *priv = netdev_priv(netdev);
6253 +
6254 + dpsw_set_irq_enable(priv->mc_io, 0, priv->dpsw_handle,
6255 + DPSW_IRQ_INDEX_IF, 0);
6256 + devm_free_irq(dev,
6257 + sw_dev->irqs[DPSW_IRQ_INDEX_IF]->msi_desc->irq,
6258 + dev);
6259 + fsl_mc_free_irqs(sw_dev);
6260 +}
6261 +
6262 +static int __cold
6263 +ethsw_init(struct fsl_mc_device *sw_dev)
6264 +{
6265 + struct device *dev = &sw_dev->dev;
6266 + struct ethsw_dev_priv *priv;
6267 + struct net_device *netdev;
6268 + int err = 0;
6269 + u16 i;
6270 + const struct dpsw_stp_cfg stp_cfg = {
6271 + .vlan_id = 1,
6272 + .state = DPSW_STP_STATE_FORWARDING,
6273 + };
6274 +
6275 + netdev = dev_get_drvdata(dev);
6276 + priv = netdev_priv(netdev);
6277 +
6278 + priv->dev_id = sw_dev->obj_desc.id;
6279 +
6280 + err = dpsw_open(priv->mc_io, 0, priv->dev_id, &priv->dpsw_handle);
6281 + if (err) {
6282 + dev_err(dev, "dpsw_open err %d\n", err);
6283 + goto err_exit;
6284 + }
6285 + if (!priv->dpsw_handle) {
6286 + dev_err(dev, "dpsw_open returned null handle but no error\n");
6287 + err = -EFAULT;
6288 + goto err_exit;
6289 + }
6290 +
6291 + err = dpsw_get_attributes(priv->mc_io, 0, priv->dpsw_handle,
6292 + &priv->sw_attr);
6293 + if (err) {
6294 + dev_err(dev, "dpsw_get_attributes err %d\n", err);
6295 + goto err_close;
6296 + }
6297 +
6298 + /* Minimum supported DPSW version check */
6299 + if (priv->sw_attr.version.major < DPSW_MIN_VER_MAJOR ||
6300 + (priv->sw_attr.version.major == DPSW_MIN_VER_MAJOR &&
6301 + priv->sw_attr.version.minor < DPSW_MIN_VER_MINOR)) {
6302 + dev_err(dev, "DPSW version %d:%d not supported. Use %d.%d or greater.\n",
6303 + priv->sw_attr.version.major,
6304 + priv->sw_attr.version.minor,
6305 + DPSW_MIN_VER_MAJOR, DPSW_MIN_VER_MINOR);
6306 + err = -ENOTSUPP;
6307 + goto err_close;
6308 + }
6309 +
6310 + err = dpsw_reset(priv->mc_io, 0, priv->dpsw_handle);
6311 + if (err) {
6312 + dev_err(dev, "dpsw_reset err %d\n", err);
6313 + goto err_close;
6314 + }
6315 +
6316 + err = dpsw_fdb_set_learning_mode(priv->mc_io, 0, priv->dpsw_handle, 0,
6317 + DPSW_FDB_LEARNING_MODE_HW);
6318 + if (err) {
6319 + dev_err(dev, "dpsw_fdb_set_learning_mode err %d\n", err);
6320 + goto err_close;
6321 + }
6322 +
6323 + for (i = 0; i < priv->sw_attr.num_ifs; i++) {
6324 + err = dpsw_if_set_stp(priv->mc_io, 0, priv->dpsw_handle, i,
6325 + &stp_cfg);
6326 + if (err) {
6327 + dev_err(dev, "dpsw_if_set_stp err %d for port %d\n",
6328 + err, i);
6329 + goto err_close;
6330 + }
6331 +
6332 + err = dpsw_if_set_broadcast(priv->mc_io, 0,
6333 + priv->dpsw_handle, i, 1);
6334 + if (err) {
6335 + dev_err(dev,
6336 + "dpsw_if_set_broadcast err %d for port %d\n",
6337 + err, i);
6338 + goto err_close;
6339 + }
6340 + }
6341 +
6342 + return 0;
6343 +
6344 +err_close:
6345 + dpsw_close(priv->mc_io, 0, priv->dpsw_handle);
6346 +err_exit:
6347 + return err;
6348 +}
6349 +
6350 +static int __cold
6351 +ethsw_takedown(struct fsl_mc_device *sw_dev)
6352 +{
6353 + struct device *dev = &sw_dev->dev;
6354 + struct net_device *netdev;
6355 + struct ethsw_dev_priv *priv;
6356 + int err;
6357 +
6358 + netdev = dev_get_drvdata(dev);
6359 + priv = netdev_priv(netdev);
6360 +
6361 + err = dpsw_close(priv->mc_io, 0, priv->dpsw_handle);
6362 + if (err)
6363 + dev_warn(dev, "dpsw_close err %d\n", err);
6364 +
6365 + return 0;
6366 +}
6367 +
6368 +static int __cold
6369 +ethsw_remove(struct fsl_mc_device *sw_dev)
6370 +{
6371 + struct device *dev;
6372 + struct net_device *netdev;
6373 + struct ethsw_dev_priv *priv;
6374 + struct ethsw_port_priv *port_priv;
6375 + struct list_head *pos;
6376 +
6377 + dev = &sw_dev->dev;
6378 + netdev = dev_get_drvdata(dev);
6379 + priv = netdev_priv(netdev);
6380 +
6381 + list_for_each(pos, &priv->port_list) {
6382 + port_priv = list_entry(pos, struct ethsw_port_priv, list);
6383 +
6384 + rtnl_lock();
6385 + netdev_upper_dev_unlink(port_priv->netdev, netdev);
6386 + rtnl_unlock();
6387 +
6388 + unregister_netdev(port_priv->netdev);
6389 + free_netdev(port_priv->netdev);
6390 + }
6391 +
6392 + ethsw_teardown_irqs(sw_dev);
6393 +
6394 + unregister_netdev(netdev);
6395 +
6396 + ethsw_takedown(sw_dev);
6397 + fsl_mc_portal_free(priv->mc_io);
6398 +
6399 + dev_set_drvdata(dev, NULL);
6400 + free_netdev(netdev);
6401 +
6402 + return 0;
6403 +}
6404 +
6405 +static int __cold
6406 +ethsw_probe(struct fsl_mc_device *sw_dev)
6407 +{
6408 + struct device *dev;
6409 + struct net_device *netdev = NULL;
6410 + struct ethsw_dev_priv *priv = NULL;
6411 + int err = 0;
6412 + u16 i;
6413 + const char def_mcast[ETH_ALEN] = {
6414 + 0x01, 0x00, 0x5e, 0x00, 0x00, 0x01,
6415 + };
6416 + char port_name[IFNAMSIZ];
6417 +
6418 + dev = &sw_dev->dev;
6419 +
6420 + /* register switch device, it's for management only - no I/O */
6421 + netdev = alloc_etherdev(sizeof(*priv));
6422 + if (!netdev) {
6423 + dev_err(dev, "alloc_etherdev error\n");
6424 + return -ENOMEM;
6425 + }
6426 + netdev->netdev_ops = &ethsw_ops;
6427 +
6428 + SET_NETDEV_DEV(netdev, dev);
6429 + dev_set_drvdata(dev, netdev);
6430 +
6431 + priv = netdev_priv(netdev);
6432 + priv->netdev = netdev;
6433 +
6434 + err = fsl_mc_portal_allocate(sw_dev, 0, &priv->mc_io);
6435 + if (err) {
6436 + dev_err(dev, "fsl_mc_portal_allocate err %d\n", err);
6437 + goto err_free_netdev;
6438 + }
6439 + if (!priv->mc_io) {
6440 + dev_err(dev, "fsl_mc_portal_allocate returned null handle but no error\n");
6441 + err = -EFAULT;
6442 + goto err_free_netdev;
6443 + }
6444 +
6445 + err = ethsw_init(sw_dev);
6446 + if (err) {
6447 + dev_err(dev, "switch init err %d\n", err);
6448 + goto err_free_cmdport;
6449 + }
6450 +
6451 + netdev->flags = netdev->flags | IFF_PROMISC | IFF_MASTER;
6452 +
6453 + /* TODO: should we hold rtnl_lock here? We can't register_netdev under
6454 + * lock
6455 + */
6456 + dev_alloc_name(netdev, "sw%d");
6457 + err = register_netdev(netdev);
6458 + if (err < 0) {
6459 + dev_err(dev, "register_netdev error %d\n", err);
6460 + goto err_takedown;
6461 + }
6462 + if (err)
6463 + dev_info(dev, "register_netdev res %d\n", err);
6464 +
6465 + /* VLAN 1 is implicitly configured on the switch */
6466 + priv->vlans[1] = ETHSW_VLAN_MEMBER;
6467 + /* Flooding, learning are implicitly enabled */
6468 + priv->learning = true;
6469 + priv->flood = true;
6470 +
6471 + /* register switch ports */
6472 + snprintf(port_name, IFNAMSIZ, "%sp%%d", netdev->name);
6473 +
6474 + INIT_LIST_HEAD(&priv->port_list);
6475 + for (i = 0; i < priv->sw_attr.num_ifs; i++) {
6476 + struct net_device *port_netdev;
6477 + struct ethsw_port_priv *port_priv;
6478 +
6479 + port_netdev = alloc_etherdev(sizeof(struct ethsw_port_priv));
6480 + if (!port_netdev) {
6481 + dev_err(dev, "alloc_etherdev error\n");
6482 + goto err_takedown;
6483 + }
6484 +
6485 + port_priv = netdev_priv(port_netdev);
6486 + port_priv->netdev = port_netdev;
6487 + port_priv->ethsw_priv = priv;
6488 +
6489 + port_priv->port_index = i;
6490 + port_priv->stp_state = BR_STATE_FORWARDING;
6491 + /* VLAN 1 is configured by default on all switch ports */
6492 + port_priv->vlans[1] = ETHSW_VLAN_MEMBER | ETHSW_VLAN_UNTAGGED |
6493 + ETHSW_VLAN_PVID;
6494 +
6495 + SET_NETDEV_DEV(port_netdev, dev);
6496 + port_netdev->netdev_ops = &ethsw_port_ops;
6497 + port_netdev->ethtool_ops = &ethsw_port_ethtool_ops;
6498 +
6499 + port_netdev->flags = port_netdev->flags |
6500 + IFF_PROMISC | IFF_SLAVE;
6501 +
6502 + dev_alloc_name(port_netdev, port_name);
6503 + err = register_netdev(port_netdev);
6504 + if (err < 0) {
6505 + dev_err(dev, "register_netdev error %d\n", err);
6506 + free_netdev(port_netdev);
6507 + goto err_takedown;
6508 + }
6509 +
6510 + rtnl_lock();
6511 +
6512 + err = netdev_master_upper_dev_link(port_netdev, netdev, NULL, NULL);
6513 + if (err) {
6514 + dev_err(dev, "netdev_master_upper_dev_link error %d\n",
6515 + err);
6516 + unregister_netdev(port_netdev);
6517 + free_netdev(port_netdev);
6518 + rtnl_unlock();
6519 + goto err_takedown;
6520 + }
6521 +
6522 + rtmsg_ifinfo(RTM_NEWLINK, port_netdev, IFF_SLAVE, GFP_KERNEL);
6523 +
6524 + rtnl_unlock();
6525 +
6526 + list_add(&port_priv->list, &priv->port_list);
6527 +
6528 + /* TODO: implmenet set_rm_mode instead of this */
6529 + err = ethsw_port_fdb_add_mc(port_netdev, def_mcast);
6530 + if (err)
6531 + dev_warn(&netdev->dev,
6532 + "ethsw_port_fdb_add_mc err %d\n", err);
6533 +
6534 +
6535 + /* sync carrier state */
6536 + err = _ethsw_port_carrier_state_sync(port_netdev);
6537 + if (err)
6538 + netdev_err(netdev,
6539 + "_ethsw_port_carrier_state_sync err %d\n",
6540 + err);
6541 + }
6542 +
6543 + /* the switch starts up enabled */
6544 + rtnl_lock();
6545 + err = dev_open(netdev);
6546 + rtnl_unlock();
6547 + if (err)
6548 + dev_warn(dev, "dev_open err %d\n", err);
6549 +
6550 + /* setup irqs */
6551 + err = ethsw_setup_irqs(sw_dev);
6552 + if (unlikely(err)) {
6553 + dev_warn(dev, "ethsw_setup_irqs err %d\n", err);
6554 + goto err_takedown;
6555 + }
6556 +
6557 + dev_info(&netdev->dev,
6558 + "probed %d port switch\n", priv->sw_attr.num_ifs);
6559 + return 0;
6560 +
6561 +err_takedown:
6562 + ethsw_remove(sw_dev);
6563 +err_free_cmdport:
6564 + fsl_mc_portal_free(priv->mc_io);
6565 +err_free_netdev:
6566 + dev_set_drvdata(dev, NULL);
6567 + free_netdev(netdev);
6568 +
6569 + return err;
6570 +}
6571 +
6572 +static const struct fsl_mc_device_match_id ethsw_match_id_table[] = {
6573 + {
6574 + .vendor = FSL_MC_VENDOR_FREESCALE,
6575 + .obj_type = "dpsw",
6576 + .ver_major = DPSW_VER_MAJOR,
6577 + .ver_minor = DPSW_VER_MINOR,
6578 + },
6579 + {}
6580 +};
6581 +
6582 +static struct fsl_mc_driver eth_sw_drv = {
6583 + .driver = {
6584 + .name = KBUILD_MODNAME,
6585 + .owner = THIS_MODULE,
6586 + },
6587 + .probe = ethsw_probe,
6588 + .remove = ethsw_remove,
6589 + .match_id_table = ethsw_match_id_table,
6590 +};
6591 +
6592 +module_fsl_mc_driver(eth_sw_drv);
6593 +
6594 +MODULE_LICENSE("GPL");
6595 +MODULE_DESCRIPTION("DPAA2 Ethernet Switch Driver (prototype)");
6596 --- a/drivers/staging/fsl-mc/include/net.h
6597 +++ b/drivers/staging/fsl-mc/include/net.h
6598 @@ -367,7 +367,6 @@
6599 /*************************** GTP fields ************************************/
6600 #define NH_FLD_GTP_TEID (1)
6601
6602 -
6603 /* Protocol options */
6604
6605 /* Ethernet options */