1 From 54bcaca10728c1a1c8adfa48124ea79cce4ef929 Mon Sep 17 00:00:00 2001
2 From: Razvan Stefanescu <razvan.stefanescu@freescale.com>
3 Date: Tue, 22 Sep 2015 08:43:08 +0300
4 Subject: [PATCH 215/226] dpaa2-evb: Added Edge Virtual Bridge driver
6 This is a commit of the cummulative, squashed dpaa2-evb patches.
7 All the commit logs are preserved below.
9 Signed-off-by: Stuart Yoder <stuart.yoder@nxp.com>
11 ----------------------------------------------------------------
13 dpaa2-evb: Added Edge Virtual Bridge driver
15 This contains the following patches migrated from linux-v4.0:
16 staging: fsl-dpaa2: evb: Added Edge Virtual Bridge driver
17 staging: fsl-dpaa2: evb: Added ethtool port counters
18 staging: fsl-dpaa2: evb: Include by default in configuration
19 staging: fsl-dpaa2: evb: Rebasing onto kernel 4.0
20 staging: fsl-dpaa2: evb: Port to MC-0.7 FLibs
21 dpaa2-evb: Set carrier state on port open
22 dpaa2-evb: Add support for link state update
23 dpaa2-evb: Update flib to MC 8.0.1
24 staging: fsl-mc: migrated remaining flibs for MC fw 8.0.0 (split)
26 Inital patches have been signed-off by:
27 Alex Marginean <alexandru.marginean@freescale.com>
28 J. German Rivera <German.Rivera@freescale.com>
29 Bogdan Hamciuc <bogdan.hamciuc@freescale.com>
30 Razvan Stefanescu <razvan.stefanescu@freescale.com>
33 Stuart Yoder <stuart.yoder@freescale.com>
35 Porting to linux-v4.1 requires changes related to iflink usage and
36 ndo_bridge_getlink() parameters list.
38 Signed-off-by: Razvan Stefanescu <razvan.stefanescu@freescale.com>
40 dpaa2-evb: Port to linux-v4.1
43 Update evb_getlink() parameter list to match ndo_bridge_getlink().
45 Signed-off-by: Razvan Stefanescu <razvan.stefanescu@freescale.com>
47 dpaa2-evb: Add VLAN_8021Q dependency
49 EVB traffic steering methods related to VLAN require VLAN support in kernel.
51 Signed-off-by: Razvan Stefanescu <razvan.stefanescu@freescale.com>
53 dpaa2-evb: Update dpdmux binary interface to 5.0
55 This corresponds to MC release 0.8.0.
57 Signed-off-by: Razvan Stefanescu <razvan.stefanescu@freescale.com>
59 dpaa2-evb: Add support to set max frame length.
61 All the packets bigger than max_frame_length will be dropped.
63 Signed-off-by: Mihaela Panescu <mihaela.panescu@freescale.com>
65 dpaa2-evb: resolve compile issues on uprev to 4.5
67 -irq_number field no longer exists in fsl-mc interrupt
69 -netdev_master_upper_dev_link() has 2 new parameters, which
70 are set to NULL for now
72 Signed-off-by: Stuart Yoder <stuart.yoder@nxp.com>
75 drivers/staging/fsl-dpaa2/Kconfig | 1 +
76 drivers/staging/fsl-dpaa2/Makefile | 1 +
77 drivers/staging/fsl-dpaa2/evb/Kconfig | 8 +
78 drivers/staging/fsl-dpaa2/evb/Makefile | 10 +
79 drivers/staging/fsl-dpaa2/evb/dpdmux-cmd.h | 256 ++++++
80 drivers/staging/fsl-dpaa2/evb/dpdmux.c | 567 +++++++++++++
81 drivers/staging/fsl-dpaa2/evb/dpdmux.h | 724 +++++++++++++++++
82 drivers/staging/fsl-dpaa2/evb/evb.c | 1216 ++++++++++++++++++++++++++++
83 9 files changed, 2789 insertions(+)
84 create mode 100644 drivers/staging/fsl-dpaa2/evb/Kconfig
85 create mode 100644 drivers/staging/fsl-dpaa2/evb/Makefile
86 create mode 100644 drivers/staging/fsl-dpaa2/evb/dpdmux-cmd.h
87 create mode 100644 drivers/staging/fsl-dpaa2/evb/dpdmux.c
88 create mode 100644 drivers/staging/fsl-dpaa2/evb/dpdmux.h
89 create mode 100644 drivers/staging/fsl-dpaa2/evb/evb.c
93 @@ -4560,6 +4560,12 @@ L: linux-kernel@vger.kernel.org
95 F: drivers/staging/fsl-dpaa2/mac/
97 ++FREESCALE DPAA2 EDGE VIRTUAL BRIDGE DRIVER
98 +M: Alex Marginean <Alexandru.Marginean@freescale.com>
99 +L: linux-kernel@vger.kernel.org
101 +F: drivers/staging/fsl-dpaa2/evb/
104 M: Christoph Hellwig <hch@infradead.org>
105 W: ftp://ftp.openlinux.org/pub/people/hch/vxfs
106 --- a/drivers/staging/fsl-dpaa2/Kconfig
107 +++ b/drivers/staging/fsl-dpaa2/Kconfig
108 @@ -10,3 +10,4 @@ config FSL_DPAA2
109 # TODO move DPIO driver in-here?
110 source "drivers/staging/fsl-dpaa2/ethernet/Kconfig"
111 source "drivers/staging/fsl-dpaa2/mac/Kconfig"
112 +source "drivers/staging/fsl-dpaa2/evb/Kconfig"
113 --- a/drivers/staging/fsl-dpaa2/Makefile
114 +++ b/drivers/staging/fsl-dpaa2/Makefile
117 obj-$(CONFIG_FSL_DPAA2_ETH) += ethernet/
118 obj-$(CONFIG_FSL_DPAA2_MAC) += mac/
119 +obj-$(CONFIG_FSL_DPAA2_EVB) += evb/
121 +++ b/drivers/staging/fsl-dpaa2/evb/Kconfig
123 +config FSL_DPAA2_EVB
124 + tristate "DPAA2 Edge Virtual Bridge"
125 + depends on FSL_MC_BUS && FSL_DPAA2 && FSL_DPAA2_ETH
126 + select FSL_DPAA2_MAC
130 + Prototype driver for DPAA2 Edge Virtual Bridge.
132 +++ b/drivers/staging/fsl-dpaa2/evb/Makefile
135 +obj-$(CONFIG_FSL_DPAA2_EVB) += dpaa2-evb.o
137 +dpaa2-evb-objs := evb.o dpdmux.o
140 + make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
143 + make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
145 +++ b/drivers/staging/fsl-dpaa2/evb/dpdmux-cmd.h
147 +/* Copyright 2013-2015 Freescale Semiconductor Inc.
149 + * Redistribution and use in source and binary forms, with or without
150 + * modification, are permitted provided that the following conditions are met:
151 + * * Redistributions of source code must retain the above copyright
152 + * notice, this list of conditions and the following disclaimer.
153 + * * Redistributions in binary form must reproduce the above copyright
154 + * notice, this list of conditions and the following disclaimer in the
155 + * documentation and/or other materials provided with the distribution.
156 + * * Neither the name of the above-listed copyright holders nor the
157 + * names of any contributors may be used to endorse or promote products
158 + * derived from this software without specific prior written permission.
161 + * ALTERNATIVELY, this software may be distributed under the terms of the
162 + * GNU General Public License ("GPL") as published by the Free Software
163 + * Foundation, either version 2 of that License or (at your option) any
166 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
167 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
168 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
169 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
170 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
171 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
172 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
173 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
174 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
175 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
176 + * POSSIBILITY OF SUCH DAMAGE.
178 +#ifndef _FSL_DPDMUX_CMD_H
179 +#define _FSL_DPDMUX_CMD_H
181 +/* DPDMUX Version */
182 +#define DPDMUX_VER_MAJOR 5
183 +#define DPDMUX_VER_MINOR 0
186 +#define DPDMUX_CMDID_CLOSE 0x800
187 +#define DPDMUX_CMDID_OPEN 0x806
188 +#define DPDMUX_CMDID_CREATE 0x906
189 +#define DPDMUX_CMDID_DESTROY 0x900
191 +#define DPDMUX_CMDID_ENABLE 0x002
192 +#define DPDMUX_CMDID_DISABLE 0x003
193 +#define DPDMUX_CMDID_GET_ATTR 0x004
194 +#define DPDMUX_CMDID_RESET 0x005
195 +#define DPDMUX_CMDID_IS_ENABLED 0x006
197 +#define DPDMUX_CMDID_SET_IRQ 0x010
198 +#define DPDMUX_CMDID_GET_IRQ 0x011
199 +#define DPDMUX_CMDID_SET_IRQ_ENABLE 0x012
200 +#define DPDMUX_CMDID_GET_IRQ_ENABLE 0x013
201 +#define DPDMUX_CMDID_SET_IRQ_MASK 0x014
202 +#define DPDMUX_CMDID_GET_IRQ_MASK 0x015
203 +#define DPDMUX_CMDID_GET_IRQ_STATUS 0x016
204 +#define DPDMUX_CMDID_CLEAR_IRQ_STATUS 0x017
206 +#define DPDMUX_CMDID_UL_SET_MAX_FRAME_LENGTH 0x0a1
208 +#define DPDMUX_CMDID_UL_RESET_COUNTERS 0x0a3
210 +#define DPDMUX_CMDID_IF_SET_ACCEPTED_FRAMES 0x0a7
211 +#define DPDMUX_CMDID_IF_GET_ATTR 0x0a8
213 +#define DPDMUX_CMDID_IF_ADD_L2_RULE 0x0b0
214 +#define DPDMUX_CMDID_IF_REMOVE_L2_RULE 0x0b1
215 +#define DPDMUX_CMDID_IF_GET_COUNTER 0x0b2
216 +#define DPDMUX_CMDID_IF_SET_LINK_CFG 0x0b3
217 +#define DPDMUX_CMDID_IF_GET_LINK_STATE 0x0b4
219 +/* cmd, param, offset, width, type, arg_name */
220 +#define DPDMUX_CMD_OPEN(cmd, dpdmux_id) \
221 + MC_CMD_OP(cmd, 0, 0, 32, int, dpdmux_id)
223 +/* cmd, param, offset, width, type, arg_name */
224 +#define DPDMUX_CMD_CREATE(cmd, cfg) \
226 + MC_CMD_OP(cmd, 0, 0, 8, enum dpdmux_method, cfg->method);\
227 + MC_CMD_OP(cmd, 0, 8, 8, enum dpdmux_manip, cfg->manip);\
228 + MC_CMD_OP(cmd, 0, 16, 16, uint16_t, cfg->num_ifs);\
229 + MC_CMD_OP(cmd, 1, 0, 16, uint16_t, cfg->adv.max_dmat_entries);\
230 + MC_CMD_OP(cmd, 1, 16, 16, uint16_t, cfg->adv.max_mc_groups);\
231 + MC_CMD_OP(cmd, 1, 32, 16, uint16_t, cfg->adv.max_vlan_ids);\
232 + MC_CMD_OP(cmd, 2, 0, 64, uint64_t, cfg->adv.options);\
235 +/* cmd, param, offset, width, type, arg_name */
236 +#define DPDMUX_RSP_IS_ENABLED(cmd, en) \
237 + MC_RSP_OP(cmd, 0, 0, 1, int, en)
239 +/* cmd, param, offset, width, type, arg_name */
240 +#define DPDMUX_CMD_SET_IRQ(cmd, irq_index, irq_cfg) \
242 + MC_CMD_OP(cmd, 0, 0, 8, uint8_t, irq_index);\
243 + MC_CMD_OP(cmd, 0, 32, 32, uint32_t, irq_cfg->val);\
244 + MC_CMD_OP(cmd, 1, 0, 64, uint64_t, irq_cfg->addr);\
245 + MC_CMD_OP(cmd, 2, 0, 32, int, irq_cfg->irq_num); \
248 +/* cmd, param, offset, width, type, arg_name */
249 +#define DPDMUX_CMD_GET_IRQ(cmd, irq_index) \
250 + MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index)
252 +/* cmd, param, offset, width, type, arg_name */
253 +#define DPDMUX_RSP_GET_IRQ(cmd, type, irq_cfg) \
255 + MC_RSP_OP(cmd, 0, 0, 32, uint32_t, irq_cfg->val); \
256 + MC_RSP_OP(cmd, 1, 0, 64, uint64_t, irq_cfg->addr); \
257 + MC_RSP_OP(cmd, 2, 0, 32, int, irq_cfg->irq_num); \
258 + MC_RSP_OP(cmd, 2, 32, 32, int, type); \
261 +/* cmd, param, offset, width, type, arg_name */
262 +#define DPDMUX_CMD_SET_IRQ_ENABLE(cmd, irq_index, en) \
264 + MC_CMD_OP(cmd, 0, 0, 8, uint8_t, en);\
265 + MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\
268 +/* cmd, param, offset, width, type, arg_name */
269 +#define DPDMUX_CMD_GET_IRQ_ENABLE(cmd, irq_index) \
270 + MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index)
272 +/* cmd, param, offset, width, type, arg_name */
273 +#define DPDMUX_RSP_GET_IRQ_ENABLE(cmd, en) \
274 + MC_RSP_OP(cmd, 0, 0, 8, uint8_t, en)
276 +/* cmd, param, offset, width, type, arg_name */
277 +#define DPDMUX_CMD_SET_IRQ_MASK(cmd, irq_index, mask) \
279 + MC_CMD_OP(cmd, 0, 0, 32, uint32_t, mask); \
280 + MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index); \
283 +/* cmd, param, offset, width, type, arg_name */
284 +#define DPDMUX_CMD_GET_IRQ_MASK(cmd, irq_index) \
285 + MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index)
287 +/* cmd, param, offset, width, type, arg_name */
288 +#define DPDMUX_RSP_GET_IRQ_MASK(cmd, mask) \
289 + MC_RSP_OP(cmd, 0, 0, 32, uint32_t, mask)
291 +/* cmd, param, offset, width, type, arg_name */
292 +#define DPDMUX_CMD_GET_IRQ_STATUS(cmd, irq_index, status) \
294 + MC_CMD_OP(cmd, 0, 0, 32, uint32_t, status);\
295 + MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\
298 +/* cmd, param, offset, width, type, arg_name */
299 +#define DPDMUX_RSP_GET_IRQ_STATUS(cmd, status) \
300 + MC_RSP_OP(cmd, 0, 0, 32, uint32_t, status) \
302 +/* cmd, param, offset, width, type, arg_name */
303 +#define DPDMUX_CMD_CLEAR_IRQ_STATUS(cmd, irq_index, status) \
305 + MC_CMD_OP(cmd, 0, 0, 32, uint32_t, status); \
306 + MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index); \
309 +#define DPDMUX_RSP_GET_ATTR(cmd, attr) \
311 + MC_RSP_OP(cmd, 0, 0, 8, enum dpdmux_method, attr->method);\
312 + MC_RSP_OP(cmd, 0, 8, 8, enum dpdmux_manip, attr->manip);\
313 + MC_RSP_OP(cmd, 0, 16, 16, uint16_t, attr->num_ifs);\
314 + MC_RSP_OP(cmd, 0, 32, 16, uint16_t, attr->mem_size);\
315 + MC_RSP_OP(cmd, 2, 0, 32, int, attr->id);\
316 + MC_RSP_OP(cmd, 3, 0, 64, uint64_t, attr->options);\
317 + MC_RSP_OP(cmd, 4, 0, 16, uint16_t, attr->version.major);\
318 + MC_RSP_OP(cmd, 4, 16, 16, uint16_t, attr->version.minor);\
321 +/* cmd, param, offset, width, type, arg_name */
322 +#define DPDMUX_CMD_UL_SET_MAX_FRAME_LENGTH(cmd, max_frame_length) \
323 + MC_CMD_OP(cmd, 0, 0, 16, uint16_t, max_frame_length)
325 +/* cmd, param, offset, width, type, arg_name */
326 +#define DPDMUX_CMD_IF_SET_ACCEPTED_FRAMES(cmd, if_id, cfg) \
328 + MC_CMD_OP(cmd, 0, 0, 16, uint16_t, if_id);\
329 + MC_CMD_OP(cmd, 0, 16, 4, enum dpdmux_accepted_frames_type, cfg->type);\
330 + MC_CMD_OP(cmd, 0, 20, 4, enum dpdmux_unaccepted_frames_action, \
331 + cfg->unaccept_act);\
334 +/* cmd, param, offset, width, type, arg_name */
335 +#define DPDMUX_CMD_IF_GET_ATTR(cmd, if_id) \
336 + MC_CMD_OP(cmd, 0, 0, 16, uint16_t, if_id)
338 +/* cmd, param, offset, width, type, arg_name */
339 +#define DPDMUX_RSP_IF_GET_ATTR(cmd, attr) \
341 + MC_RSP_OP(cmd, 0, 56, 4, enum dpdmux_accepted_frames_type, \
342 + attr->accept_frame_type);\
343 + MC_RSP_OP(cmd, 0, 24, 1, int, attr->enabled);\
344 + MC_RSP_OP(cmd, 1, 0, 32, uint32_t, attr->rate);\
347 +#define DPDMUX_CMD_IF_REMOVE_L2_RULE(cmd, if_id, l2_rule) \
349 + MC_CMD_OP(cmd, 0, 0, 16, uint16_t, if_id);\
350 + MC_CMD_OP(cmd, 0, 16, 8, uint8_t, l2_rule->mac_addr[5]);\
351 + MC_CMD_OP(cmd, 0, 24, 8, uint8_t, l2_rule->mac_addr[4]);\
352 + MC_CMD_OP(cmd, 0, 32, 8, uint8_t, l2_rule->mac_addr[3]);\
353 + MC_CMD_OP(cmd, 0, 40, 8, uint8_t, l2_rule->mac_addr[2]);\
354 + MC_CMD_OP(cmd, 0, 48, 8, uint8_t, l2_rule->mac_addr[1]);\
355 + MC_CMD_OP(cmd, 0, 56, 8, uint8_t, l2_rule->mac_addr[0]);\
356 + MC_CMD_OP(cmd, 1, 32, 16, uint16_t, l2_rule->vlan_id);\
359 +#define DPDMUX_CMD_IF_ADD_L2_RULE(cmd, if_id, l2_rule) \
361 + MC_CMD_OP(cmd, 0, 0, 16, uint16_t, if_id);\
362 + MC_CMD_OP(cmd, 0, 16, 8, uint8_t, l2_rule->mac_addr[5]);\
363 + MC_CMD_OP(cmd, 0, 24, 8, uint8_t, l2_rule->mac_addr[4]);\
364 + MC_CMD_OP(cmd, 0, 32, 8, uint8_t, l2_rule->mac_addr[3]);\
365 + MC_CMD_OP(cmd, 0, 40, 8, uint8_t, l2_rule->mac_addr[2]);\
366 + MC_CMD_OP(cmd, 0, 48, 8, uint8_t, l2_rule->mac_addr[1]);\
367 + MC_CMD_OP(cmd, 0, 56, 8, uint8_t, l2_rule->mac_addr[0]);\
368 + MC_CMD_OP(cmd, 1, 32, 16, uint16_t, l2_rule->vlan_id);\
371 +/* cmd, param, offset, width, type, arg_name */
372 +#define DPDMUX_CMD_IF_GET_COUNTER(cmd, if_id, counter_type) \
374 + MC_CMD_OP(cmd, 0, 0, 16, uint16_t, if_id);\
375 + MC_CMD_OP(cmd, 0, 16, 8, enum dpdmux_counter_type, counter_type);\
378 +/* cmd, param, offset, width, type, arg_name */
379 +#define DPDMUX_RSP_IF_GET_COUNTER(cmd, counter) \
380 + MC_RSP_OP(cmd, 1, 0, 64, uint64_t, counter)
382 +/* cmd, param, offset, width, type, arg_name */
383 +#define DPDMUX_CMD_IF_SET_LINK_CFG(cmd, if_id, cfg) \
385 + MC_CMD_OP(cmd, 0, 0, 16, uint16_t, if_id);\
386 + MC_CMD_OP(cmd, 1, 0, 32, uint32_t, cfg->rate);\
387 + MC_CMD_OP(cmd, 2, 0, 64, uint64_t, cfg->options);\
390 +/* cmd, param, offset, width, type, arg_name */
391 +#define DPDMUX_CMD_IF_GET_LINK_STATE(cmd, if_id) \
392 + MC_CMD_OP(cmd, 0, 0, 16, uint16_t, if_id)
394 +/* cmd, param, offset, width, type, arg_name */
395 +#define DPDMUX_RSP_IF_GET_LINK_STATE(cmd, state) \
397 + MC_RSP_OP(cmd, 0, 32, 1, int, state->up);\
398 + MC_RSP_OP(cmd, 1, 0, 32, uint32_t, state->rate);\
399 + MC_RSP_OP(cmd, 2, 0, 64, uint64_t, state->options);\
402 +#endif /* _FSL_DPDMUX_CMD_H */
404 +++ b/drivers/staging/fsl-dpaa2/evb/dpdmux.c
406 +/* Copyright 2013-2015 Freescale Semiconductor Inc.
408 + * Redistribution and use in source and binary forms, with or without
409 + * modification, are permitted provided that the following conditions are met:
410 + * * Redistributions of source code must retain the above copyright
411 + * notice, this list of conditions and the following disclaimer.
412 + * * Redistributions in binary form must reproduce the above copyright
413 + * notice, this list of conditions and the following disclaimer in the
414 + * documentation and/or other materials provided with the distribution.
415 + * * Neither the name of the above-listed copyright holders nor the
416 + * names of any contributors may be used to endorse or promote products
417 + * derived from this software without specific prior written permission.
420 + * ALTERNATIVELY, this software may be distributed under the terms of the
421 + * GNU General Public License ("GPL") as published by the Free Software
422 + * Foundation, either version 2 of that License or (at your option) any
425 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
426 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
427 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
428 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
429 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
430 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
431 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
432 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
433 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
434 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
435 + * POSSIBILITY OF SUCH DAMAGE.
437 +#include "../../fsl-mc/include/mc-sys.h"
438 +#include "../../fsl-mc/include/mc-cmd.h"
440 +#include "dpdmux-cmd.h"
442 +int dpdmux_open(struct fsl_mc_io *mc_io,
443 + uint32_t cmd_flags,
447 + struct mc_command cmd = { 0 };
450 + /* prepare command */
451 + cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_OPEN,
454 + DPDMUX_CMD_OPEN(cmd, dpdmux_id);
456 + /* send command to mc*/
457 + err = mc_send_command(mc_io, &cmd);
461 + /* retrieve response parameters */
462 + *token = MC_CMD_HDR_READ_TOKEN(cmd.header);
467 +int dpdmux_close(struct fsl_mc_io *mc_io,
468 + uint32_t cmd_flags,
471 + struct mc_command cmd = { 0 };
473 + /* prepare command */
474 + cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_CLOSE,
478 + /* send command to mc*/
479 + return mc_send_command(mc_io, &cmd);
482 +int dpdmux_create(struct fsl_mc_io *mc_io,
483 + uint32_t cmd_flags,
484 + const struct dpdmux_cfg *cfg,
487 + struct mc_command cmd = { 0 };
490 + /* prepare command */
491 + cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_CREATE,
494 + DPDMUX_CMD_CREATE(cmd, cfg);
496 + /* send command to mc*/
497 + err = mc_send_command(mc_io, &cmd);
501 + /* retrieve response parameters */
502 + *token = MC_CMD_HDR_READ_TOKEN(cmd.header);
507 +int dpdmux_destroy(struct fsl_mc_io *mc_io,
508 + uint32_t cmd_flags,
511 + struct mc_command cmd = { 0 };
513 + /* prepare command */
514 + cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_DESTROY,
518 + /* send command to mc*/
519 + return mc_send_command(mc_io, &cmd);
522 +int dpdmux_enable(struct fsl_mc_io *mc_io,
523 + uint32_t cmd_flags,
526 + struct mc_command cmd = { 0 };
528 + /* prepare command */
529 + cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_ENABLE,
533 + /* send command to mc*/
534 + return mc_send_command(mc_io, &cmd);
537 +int dpdmux_disable(struct fsl_mc_io *mc_io,
538 + uint32_t cmd_flags,
541 + struct mc_command cmd = { 0 };
543 + /* prepare command */
544 + cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_DISABLE,
548 + /* send command to mc*/
549 + return mc_send_command(mc_io, &cmd);
552 +int dpdmux_is_enabled(struct fsl_mc_io *mc_io,
553 + uint32_t cmd_flags,
557 + struct mc_command cmd = { 0 };
559 + /* prepare command */
560 + cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_IS_ENABLED,
564 + /* send command to mc*/
565 + err = mc_send_command(mc_io, &cmd);
569 + /* retrieve response parameters */
570 + DPDMUX_RSP_IS_ENABLED(cmd, *en);
575 +int dpdmux_reset(struct fsl_mc_io *mc_io,
576 + uint32_t cmd_flags,
579 + struct mc_command cmd = { 0 };
581 + /* prepare command */
582 + cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_RESET,
586 + /* send command to mc*/
587 + return mc_send_command(mc_io, &cmd);
590 +int dpdmux_set_irq(struct fsl_mc_io *mc_io,
591 + uint32_t cmd_flags,
594 + struct dpdmux_irq_cfg *irq_cfg)
596 + struct mc_command cmd = { 0 };
598 + /* prepare command */
599 + cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_SET_IRQ,
602 + DPDMUX_CMD_SET_IRQ(cmd, irq_index, irq_cfg);
604 + /* send command to mc*/
605 + return mc_send_command(mc_io, &cmd);
608 +int dpdmux_get_irq(struct fsl_mc_io *mc_io,
609 + uint32_t cmd_flags,
613 + struct dpdmux_irq_cfg *irq_cfg)
615 + struct mc_command cmd = { 0 };
618 + /* prepare command */
619 + cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_GET_IRQ,
622 + DPDMUX_CMD_GET_IRQ(cmd, irq_index);
624 + /* send command to mc*/
625 + err = mc_send_command(mc_io, &cmd);
629 + /* retrieve response parameters */
630 + DPDMUX_RSP_GET_IRQ(cmd, *type, irq_cfg);
635 +int dpdmux_set_irq_enable(struct fsl_mc_io *mc_io,
636 + uint32_t cmd_flags,
641 + struct mc_command cmd = { 0 };
643 + /* prepare command */
644 + cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_SET_IRQ_ENABLE,
647 + DPDMUX_CMD_SET_IRQ_ENABLE(cmd, irq_index, en);
649 + /* send command to mc*/
650 + return mc_send_command(mc_io, &cmd);
653 +int dpdmux_get_irq_enable(struct fsl_mc_io *mc_io,
654 + uint32_t cmd_flags,
659 + struct mc_command cmd = { 0 };
662 + /* prepare command */
663 + cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_GET_IRQ_ENABLE,
666 + DPDMUX_CMD_GET_IRQ_ENABLE(cmd, irq_index);
668 + /* send command to mc*/
669 + err = mc_send_command(mc_io, &cmd);
673 + /* retrieve response parameters */
674 + DPDMUX_RSP_GET_IRQ_ENABLE(cmd, *en);
679 +int dpdmux_set_irq_mask(struct fsl_mc_io *mc_io,
680 + uint32_t cmd_flags,
685 + struct mc_command cmd = { 0 };
687 + /* prepare command */
688 + cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_SET_IRQ_MASK,
691 + DPDMUX_CMD_SET_IRQ_MASK(cmd, irq_index, mask);
693 + /* send command to mc*/
694 + return mc_send_command(mc_io, &cmd);
697 +int dpdmux_get_irq_mask(struct fsl_mc_io *mc_io,
698 + uint32_t cmd_flags,
703 + struct mc_command cmd = { 0 };
706 + /* prepare command */
707 + cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_GET_IRQ_MASK,
710 + DPDMUX_CMD_GET_IRQ_MASK(cmd, irq_index);
712 + /* send command to mc*/
713 + err = mc_send_command(mc_io, &cmd);
717 + /* retrieve response parameters */
718 + DPDMUX_RSP_GET_IRQ_MASK(cmd, *mask);
723 +int dpdmux_get_irq_status(struct fsl_mc_io *mc_io,
724 + uint32_t cmd_flags,
729 + struct mc_command cmd = { 0 };
732 + /* prepare command */
733 + cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_GET_IRQ_STATUS,
736 + DPDMUX_CMD_GET_IRQ_STATUS(cmd, irq_index, *status);
738 + /* send command to mc*/
739 + err = mc_send_command(mc_io, &cmd);
743 + /* retrieve response parameters */
744 + DPDMUX_RSP_GET_IRQ_STATUS(cmd, *status);
749 +int dpdmux_clear_irq_status(struct fsl_mc_io *mc_io,
750 + uint32_t cmd_flags,
755 + struct mc_command cmd = { 0 };
757 + /* prepare command */
758 + cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_CLEAR_IRQ_STATUS,
761 + DPDMUX_CMD_CLEAR_IRQ_STATUS(cmd, irq_index, status);
763 + /* send command to mc*/
764 + return mc_send_command(mc_io, &cmd);
767 +int dpdmux_get_attributes(struct fsl_mc_io *mc_io,
768 + uint32_t cmd_flags,
770 + struct dpdmux_attr *attr)
772 + struct mc_command cmd = { 0 };
775 + /* prepare command */
776 + cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_GET_ATTR,
780 + /* send command to mc*/
781 + err = mc_send_command(mc_io, &cmd);
785 + /* retrieve response parameters */
786 + DPDMUX_RSP_GET_ATTR(cmd, attr);
791 +int dpdmux_ul_set_max_frame_length(struct fsl_mc_io *mc_io,
792 + uint32_t cmd_flags,
794 + uint16_t max_frame_length)
796 + struct mc_command cmd = { 0 };
798 + /* prepare command */
799 + cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_UL_SET_MAX_FRAME_LENGTH,
802 + DPDMUX_CMD_UL_SET_MAX_FRAME_LENGTH(cmd, max_frame_length);
804 + /* send command to mc*/
805 + return mc_send_command(mc_io, &cmd);
808 +int dpdmux_ul_reset_counters(struct fsl_mc_io *mc_io,
809 + uint32_t cmd_flags,
812 + struct mc_command cmd = { 0 };
814 + /* prepare command */
815 + cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_UL_RESET_COUNTERS,
819 + /* send command to mc*/
820 + return mc_send_command(mc_io, &cmd);
823 +int dpdmux_if_set_accepted_frames(struct fsl_mc_io *mc_io,
824 + uint32_t cmd_flags,
827 + const struct dpdmux_accepted_frames *cfg)
829 + struct mc_command cmd = { 0 };
831 + /* prepare command */
832 + cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_IF_SET_ACCEPTED_FRAMES,
835 + DPDMUX_CMD_IF_SET_ACCEPTED_FRAMES(cmd, if_id, cfg);
837 + /* send command to mc*/
838 + return mc_send_command(mc_io, &cmd);
841 +int dpdmux_if_get_attributes(struct fsl_mc_io *mc_io,
842 + uint32_t cmd_flags,
845 + struct dpdmux_if_attr *attr)
847 + struct mc_command cmd = { 0 };
850 + /* prepare command */
851 + cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_IF_GET_ATTR,
854 + DPDMUX_CMD_IF_GET_ATTR(cmd, if_id);
856 + /* send command to mc*/
857 + err = mc_send_command(mc_io, &cmd);
861 + /* retrieve response parameters */
862 + DPDMUX_RSP_IF_GET_ATTR(cmd, attr);
867 +int dpdmux_if_remove_l2_rule(struct fsl_mc_io *mc_io,
868 + uint32_t cmd_flags,
871 + const struct dpdmux_l2_rule *rule)
873 + struct mc_command cmd = { 0 };
875 + /* prepare command */
876 + cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_IF_REMOVE_L2_RULE,
879 + DPDMUX_CMD_IF_REMOVE_L2_RULE(cmd, if_id, rule);
881 + /* send command to mc*/
882 + return mc_send_command(mc_io, &cmd);
885 +int dpdmux_if_add_l2_rule(struct fsl_mc_io *mc_io,
886 + uint32_t cmd_flags,
889 + const struct dpdmux_l2_rule *rule)
891 + struct mc_command cmd = { 0 };
893 + /* prepare command */
894 + cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_IF_ADD_L2_RULE,
897 + DPDMUX_CMD_IF_ADD_L2_RULE(cmd, if_id, rule);
899 + /* send command to mc*/
900 + return mc_send_command(mc_io, &cmd);
903 +int dpdmux_if_get_counter(struct fsl_mc_io *mc_io,
904 + uint32_t cmd_flags,
907 + enum dpdmux_counter_type counter_type,
910 + struct mc_command cmd = { 0 };
913 + /* prepare command */
914 + cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_IF_GET_COUNTER,
917 + DPDMUX_CMD_IF_GET_COUNTER(cmd, if_id, counter_type);
919 + /* send command to mc*/
920 + err = mc_send_command(mc_io, &cmd);
924 + /* retrieve response parameters */
925 + DPDMUX_RSP_IF_GET_COUNTER(cmd, *counter);
930 +int dpdmux_if_set_link_cfg(struct fsl_mc_io *mc_io,
931 + uint32_t cmd_flags,
934 + struct dpdmux_link_cfg *cfg)
936 + struct mc_command cmd = { 0 };
938 + /* prepare command */
939 + cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_IF_SET_LINK_CFG,
942 + DPDMUX_CMD_IF_SET_LINK_CFG(cmd, if_id, cfg);
944 + /* send command to mc*/
945 + return mc_send_command(mc_io, &cmd);
948 +int dpdmux_if_get_link_state(struct fsl_mc_io *mc_io,
949 + uint32_t cmd_flags,
952 + struct dpdmux_link_state *state)
954 + struct mc_command cmd = { 0 };
957 + /* prepare command */
958 + cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_IF_GET_LINK_STATE,
961 + DPDMUX_CMD_IF_GET_LINK_STATE(cmd, if_id);
963 + /* send command to mc*/
964 + err = mc_send_command(mc_io, &cmd);
968 + /* retrieve response parameters */
969 + DPDMUX_RSP_IF_GET_LINK_STATE(cmd, state);
974 +++ b/drivers/staging/fsl-dpaa2/evb/dpdmux.h
976 +/* Copyright 2013-2015 Freescale Semiconductor Inc.
978 + * Redistribution and use in source and binary forms, with or without
979 + * modification, are permitted provided that the following conditions are met:
980 + * * Redistributions of source code must retain the above copyright
981 + * notice, this list of conditions and the following disclaimer.
982 + * * Redistributions in binary form must reproduce the above copyright
983 + * notice, this list of conditions and the following disclaimer in the
984 + * documentation and/or other materials provided with the distribution.
985 + * * Neither the name of the above-listed copyright holders nor the
986 + * names of any contributors may be used to endorse or promote products
987 + * derived from this software without specific prior written permission.
990 + * ALTERNATIVELY, this software may be distributed under the terms of the
991 + * GNU General Public License ("GPL") as published by the Free Software
992 + * Foundation, either version 2 of that License or (at your option) any
995 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
996 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
997 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
998 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
999 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
1000 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
1001 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
1002 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
1003 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
1004 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
1005 + * POSSIBILITY OF SUCH DAMAGE.
1007 +#ifndef __FSL_DPDMUX_H
1008 +#define __FSL_DPDMUX_H
1010 +#include "../../fsl-mc/include/net.h"
1014 +/* Data Path Demux API
1015 + * Contains API for handling DPDMUX topology and functionality
1019 + * dpdmux_open() - Open a control session for the specified object
1020 + * @mc_io: Pointer to MC portal's I/O object
1021 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
1022 + * @dpdmux_id: DPDMUX unique ID
1023 + * @token: Returned token; use in subsequent API calls
1025 + * This function can be used to open a control session for an
1026 + * already created object; an object may have been declared in
1027 + * the DPL or by calling the dpdmux_create() function.
1028 + * This function returns a unique authentication token,
1029 + * associated with the specific object ID and the specific MC
1030 + * portal; this token must be used in all subsequent commands for
1031 + * this specific object.
1033 + * Return: '0' on Success; Error code otherwise.
1035 +int dpdmux_open(struct fsl_mc_io *mc_io,
1036 + uint32_t cmd_flags,
1041 + * dpdmux_close() - Close the control session of the object
1042 + * @mc_io: Pointer to MC portal's I/O object
1043 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
1044 + * @token: Token of DPDMUX object
1046 + * After this function is called, no further operations are
1047 + * allowed on the object without opening a new control session.
1049 + * Return: '0' on Success; Error code otherwise.
1051 +int dpdmux_close(struct fsl_mc_io *mc_io,
1052 + uint32_t cmd_flags,
1056 + * DPDMUX general options
1060 + * Enable bridging between internal interfaces
1062 +#define DPDMUX_OPT_BRIDGE_EN 0x0000000000000002ULL
1064 +#define DPDMUX_IRQ_INDEX_IF 0x0000
1065 +#define DPDMUX_IRQ_INDEX 0x0001
1068 + * IRQ event - Indicates that the link state changed
1070 +#define DPDMUX_IRQ_EVENT_LINK_CHANGED 0x0001
1073 + * enum dpdmux_manip - DPDMUX manipulation operations
1074 + * @DPDMUX_MANIP_NONE: No manipulation on frames
1075 + * @DPDMUX_MANIP_ADD_REMOVE_S_VLAN: Add S-VLAN on egress, remove it on ingress
1077 +enum dpdmux_manip {
1078 + DPDMUX_MANIP_NONE = 0x0,
1079 + DPDMUX_MANIP_ADD_REMOVE_S_VLAN = 0x1
1083 + * enum dpdmux_method - DPDMUX method options
1084 + * @DPDMUX_METHOD_NONE: no DPDMUX method
1085 + * @DPDMUX_METHOD_C_VLAN_MAC: DPDMUX based on C-VLAN and MAC address
1086 + * @DPDMUX_METHOD_MAC: DPDMUX based on MAC address
1087 + * @DPDMUX_METHOD_C_VLAN: DPDMUX based on C-VLAN
1088 + * @DPDMUX_METHOD_S_VLAN: DPDMUX based on S-VLAN
1090 +enum dpdmux_method {
1091 + DPDMUX_METHOD_NONE = 0x0,
1092 + DPDMUX_METHOD_C_VLAN_MAC = 0x1,
1093 + DPDMUX_METHOD_MAC = 0x2,
1094 + DPDMUX_METHOD_C_VLAN = 0x3,
1095 + DPDMUX_METHOD_S_VLAN = 0x4
1099 + * struct dpdmux_cfg - DPDMUX configuration parameters
1100 + * @method: Defines the operation method for the DPDMUX address table
1101 + * @manip: Required manipulation operation
1102 + * @num_ifs: Number of interfaces (excluding the uplink interface)
1103 + * @adv: Advanced parameters; default is all zeros;
1104 + * use this structure to change default settings
1106 +struct dpdmux_cfg {
1107 + enum dpdmux_method method;
1108 + enum dpdmux_manip manip;
1111 + * struct adv - Advanced parameters
1112 + * @options: DPDMUX options - combination of 'DPDMUX_OPT_<X>' flags
1113 + * @max_dmat_entries: Maximum entries in DPDMUX address table
1114 + * 0 - indicates default: 64 entries per interface.
1115 + * @max_mc_groups: Number of multicast groups in DPDMUX table
1116 + * 0 - indicates default: 32 multicast groups
1117 + * @max_vlan_ids: max vlan ids allowed in the system -
1118 + * relevant only case of working in mac+vlan method.
1119 + * 0 - indicates default 16 vlan ids.
1123 + uint16_t max_dmat_entries;
1124 + uint16_t max_mc_groups;
1125 + uint16_t max_vlan_ids;
1130 + * dpdmux_create() - Create the DPDMUX object
1131 + * @mc_io: Pointer to MC portal's I/O object
1132 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
1133 + * @cfg: Configuration structure
1134 + * @token: Returned token; use in subsequent API calls
1136 + * Create the DPDMUX object, allocate required resources and
1137 + * perform required initialization.
1139 + * The object can be created either by declaring it in the
1140 + * DPL file, or by calling this function.
1142 + * This function returns a unique authentication token,
1143 + * associated with the specific object ID and the specific MC
1144 + * portal; this token must be used in all subsequent calls to
1145 + * this specific object. For objects that are created using the
1146 + * DPL file, call dpdmux_open() function to get an authentication
1149 + * Return: '0' on Success; Error code otherwise.
1151 +int dpdmux_create(struct fsl_mc_io *mc_io,
1152 + uint32_t cmd_flags,
1153 + const struct dpdmux_cfg *cfg,
1157 + * dpdmux_destroy() - Destroy the DPDMUX object and release all its resources.
1158 + * @mc_io: Pointer to MC portal's I/O object
1159 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
1160 + * @token: Token of DPDMUX object
1162 + * Return: '0' on Success; error code otherwise.
1164 +int dpdmux_destroy(struct fsl_mc_io *mc_io,
1165 + uint32_t cmd_flags,
1169 + * dpdmux_enable() - Enable DPDMUX functionality
1170 + * @mc_io: Pointer to MC portal's I/O object
1171 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
1172 + * @token: Token of DPDMUX object
1174 + * Return: '0' on Success; Error code otherwise.
1176 +int dpdmux_enable(struct fsl_mc_io *mc_io,
1177 + uint32_t cmd_flags,
1181 + * dpdmux_disable() - Disable DPDMUX functionality
1182 + * @mc_io: Pointer to MC portal's I/O object
1183 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
1184 + * @token: Token of DPDMUX object
1186 + * Return: '0' on Success; Error code otherwise.
1188 +int dpdmux_disable(struct fsl_mc_io *mc_io,
1189 + uint32_t cmd_flags,
1193 + * dpdmux_is_enabled() - Check if the DPDMUX is enabled.
1194 + * @mc_io: Pointer to MC portal's I/O object
1195 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
1196 + * @token: Token of DPDMUX object
1197 + * @en: Returns '1' if object is enabled; '0' otherwise
1199 + * Return: '0' on Success; Error code otherwise.
1201 +int dpdmux_is_enabled(struct fsl_mc_io *mc_io,
1202 + uint32_t cmd_flags,
1207 + * dpdmux_reset() - Reset the DPDMUX, returns the object to initial state.
1208 + * @mc_io: Pointer to MC portal's I/O object
1209 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
1210 + * @token: Token of DPDMUX object
1212 + * Return: '0' on Success; Error code otherwise.
1214 +int dpdmux_reset(struct fsl_mc_io *mc_io,
1215 + uint32_t cmd_flags,
1219 + * struct dpdmux_irq_cfg - IRQ configuration
1220 + * @addr: Address that must be written to signal a message-based interrupt
1221 + * @val: Value to write into irq_addr address
1222 + * @irq_num: A user defined number associated with this IRQ
1224 +struct dpdmux_irq_cfg {
1231 + * dpdmux_set_irq() - Set IRQ information for the DPDMUX to trigger an interrupt.
1232 + * @mc_io: Pointer to MC portal's I/O object
1233 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
1234 + * @token: Token of DPDMUX object
1235 + * @irq_index: Identifies the interrupt index to configure
1236 + * @irq_cfg: IRQ configuration
1238 + * Return: '0' on Success; Error code otherwise.
1240 +int dpdmux_set_irq(struct fsl_mc_io *mc_io,
1241 + uint32_t cmd_flags,
1243 + uint8_t irq_index,
1244 + struct dpdmux_irq_cfg *irq_cfg);
1247 + * dpdmux_get_irq() - Get IRQ information from the DPDMUX.
1248 + * @mc_io: Pointer to MC portal's I/O object
1249 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
1250 + * @token: Token of DPDMUX object
1251 + * @irq_index: The interrupt index to configure
1252 + * @type: Interrupt type: 0 represents message interrupt
1253 + * type (both irq_addr and irq_val are valid)
1254 + * @irq_cfg: IRQ attributes
1256 + * Return: '0' on Success; Error code otherwise.
1258 +int dpdmux_get_irq(struct fsl_mc_io *mc_io,
1259 + uint32_t cmd_flags,
1261 + uint8_t irq_index,
1263 + struct dpdmux_irq_cfg *irq_cfg);
1266 + * dpdmux_set_irq_enable() - Set overall interrupt state.
1267 + * @mc_io: Pointer to MC portal's I/O object
1268 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
1269 + * @token: Token of DPDMUX object
1270 + * @irq_index: The interrupt index to configure
1271 + * @en: Interrupt state - enable = 1, disable = 0
1273 + * Allows GPP software to control when interrupts are generated.
1274 + * Each interrupt can have up to 32 causes. The enable/disable control's the
1275 + * overall interrupt state. if the interrupt is disabled no causes will cause
1278 + * Return: '0' on Success; Error code otherwise.
1280 +int dpdmux_set_irq_enable(struct fsl_mc_io *mc_io,
1281 + uint32_t cmd_flags,
1283 + uint8_t irq_index,
1287 + * dpdmux_get_irq_enable() - Get overall interrupt state.
1288 + * @mc_io: Pointer to MC portal's I/O object
1289 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
1290 + * @token: Token of DPDMUX object
1291 + * @irq_index: The interrupt index to configure
1292 + * @en: Returned interrupt state - enable = 1, disable = 0
1294 + * Return: '0' on Success; Error code otherwise.
1296 +int dpdmux_get_irq_enable(struct fsl_mc_io *mc_io,
1297 + uint32_t cmd_flags,
1299 + uint8_t irq_index,
1303 + * dpdmux_set_irq_mask() - Set interrupt mask.
1304 + * @mc_io: Pointer to MC portal's I/O object
1305 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
1306 + * @token: Token of DPDMUX object
1307 + * @irq_index: The interrupt index to configure
1308 + * @mask: event mask to trigger interrupt;
1310 + * 0 = ignore event
1311 + * 1 = consider event for asserting IRQ
1313 + * Every interrupt can have up to 32 causes and the interrupt model supports
1314 + * masking/unmasking each cause independently
1316 + * Return: '0' on Success; Error code otherwise.
1318 +int dpdmux_set_irq_mask(struct fsl_mc_io *mc_io,
1319 + uint32_t cmd_flags,
1321 + uint8_t irq_index,
1325 + * dpdmux_get_irq_mask() - Get interrupt mask.
1326 + * @mc_io: Pointer to MC portal's I/O object
1327 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
1328 + * @token: Token of DPDMUX object
1329 + * @irq_index: The interrupt index to configure
1330 + * @mask: Returned event mask to trigger interrupt
1332 + * Every interrupt can have up to 32 causes and the interrupt model supports
1333 + * masking/unmasking each cause independently
1335 + * Return: '0' on Success; Error code otherwise.
1337 +int dpdmux_get_irq_mask(struct fsl_mc_io *mc_io,
1338 + uint32_t cmd_flags,
1340 + uint8_t irq_index,
1344 + * dpdmux_get_irq_status() - Get the current status of any pending interrupts.
1345 + * @mc_io: Pointer to MC portal's I/O object
1346 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
1347 + * @token: Token of DPDMUX object
1348 + * @irq_index: The interrupt index to configure
1349 + * @status: Returned interrupts status - one bit per cause:
1350 + * 0 = no interrupt pending
1351 + * 1 = interrupt pending
1353 + * Return: '0' on Success; Error code otherwise.
1355 +int dpdmux_get_irq_status(struct fsl_mc_io *mc_io,
1356 + uint32_t cmd_flags,
1358 + uint8_t irq_index,
1359 + uint32_t *status);
1362 + * dpdmux_clear_irq_status() - Clear a pending interrupt's status
1363 + * @mc_io: Pointer to MC portal's I/O object
1364 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
1365 + * @token: Token of DPDMUX object
1366 + * @irq_index: The interrupt index to configure
1367 + * @status: bits to clear (W1C) - one bit per cause:
1368 + * 0 = don't change
1369 + * 1 = clear status bit
1371 + * Return: '0' on Success; Error code otherwise.
1373 +int dpdmux_clear_irq_status(struct fsl_mc_io *mc_io,
1374 + uint32_t cmd_flags,
1376 + uint8_t irq_index,
1380 + * struct dpdmux_attr - Structure representing DPDMUX attributes
1381 + * @id: DPDMUX object ID
1382 + * @version: DPDMUX version
1383 + * @options: Configuration options (bitmap)
1384 + * @method: DPDMUX address table method
1385 + * @manip: DPDMUX manipulation type
1386 + * @num_ifs: Number of interfaces (excluding the uplink interface)
1387 + * @mem_size: DPDMUX frame storage memory size
1389 +struct dpdmux_attr {
1392 + * struct version - DPDMUX version
1393 + * @major: DPDMUX major version
1394 + * @minor: DPDMUX minor version
1401 + enum dpdmux_method method;
1402 + enum dpdmux_manip manip;
1404 + uint16_t mem_size;
1408 + * dpdmux_get_attributes() - Retrieve DPDMUX attributes
1409 + * @mc_io: Pointer to MC portal's I/O object
1410 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
1411 + * @token: Token of DPDMUX object
1412 + * @attr: Returned object's attributes
1414 + * Return: '0' on Success; Error code otherwise.
1416 +int dpdmux_get_attributes(struct fsl_mc_io *mc_io,
1417 + uint32_t cmd_flags,
1419 + struct dpdmux_attr *attr);
1422 + * dpdmux_ul_set_max_frame_length() - Set the maximum frame length in DPDMUX
1423 + * @mc_io: Pointer to MC portal's I/O object
1424 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
1425 + * @token: Token of DPDMUX object
1426 + * @max_frame_length: The required maximum frame length
1428 + * Return: '0' on Success; Error code otherwise.
1430 +int dpdmux_ul_set_max_frame_length(struct fsl_mc_io *mc_io,
1431 + uint32_t cmd_flags,
1433 + uint16_t max_frame_length);
1436 + * enum dpdmux_counter_type - Counter types
1437 + * @DPDMUX_CNT_ING_FRAME: Counts ingress frames
1438 + * @DPDMUX_CNT_ING_BYTE: Counts ingress bytes
1439 + * @DPDMUX_CNT_ING_FLTR_FRAME: Counts filtered ingress frames
1440 + * @DPDMUX_CNT_ING_FRAME_DISCARD: Counts discarded ingress frames
1441 + * @DPDMUX_CNT_ING_MCAST_FRAME: Counts ingress multicast frames
1442 + * @DPDMUX_CNT_ING_MCAST_BYTE: Counts ingress multicast bytes
1443 + * @DPDMUX_CNT_ING_BCAST_FRAME: Counts ingress broadcast frames
1444 + * @DPDMUX_CNT_ING_BCAST_BYTES: Counts ingress broadcast bytes
1445 + * @DPDMUX_CNT_EGR_FRAME: Counts egress frames
1446 + * @DPDMUX_CNT_EGR_BYTE: Counts egress bytes
1447 + * @DPDMUX_CNT_EGR_FRAME_DISCARD: Counts discarded egress frames
1449 +enum dpdmux_counter_type {
1450 + DPDMUX_CNT_ING_FRAME = 0x0,
1451 + DPDMUX_CNT_ING_BYTE = 0x1,
1452 + DPDMUX_CNT_ING_FLTR_FRAME = 0x2,
1453 + DPDMUX_CNT_ING_FRAME_DISCARD = 0x3,
1454 + DPDMUX_CNT_ING_MCAST_FRAME = 0x4,
1455 + DPDMUX_CNT_ING_MCAST_BYTE = 0x5,
1456 + DPDMUX_CNT_ING_BCAST_FRAME = 0x6,
1457 + DPDMUX_CNT_ING_BCAST_BYTES = 0x7,
1458 + DPDMUX_CNT_EGR_FRAME = 0x8,
1459 + DPDMUX_CNT_EGR_BYTE = 0x9,
1460 + DPDMUX_CNT_EGR_FRAME_DISCARD = 0xa
1464 + * enum dpdmux_accepted_frames_type - DPDMUX frame types
1465 + * @DPDMUX_ADMIT_ALL: The device accepts VLAN tagged, untagged and
1466 + * priority-tagged frames
1467 + * @DPDMUX_ADMIT_ONLY_VLAN_TAGGED: The device discards untagged frames or
1468 + * priority-tagged frames that are received on this
1470 + * @DPDMUX_ADMIT_ONLY_UNTAGGED: Untagged frames or priority-tagged frames
1471 + * received on this interface are accepted
1473 +enum dpdmux_accepted_frames_type {
1474 + DPDMUX_ADMIT_ALL = 0,
1475 + DPDMUX_ADMIT_ONLY_VLAN_TAGGED = 1,
1476 + DPDMUX_ADMIT_ONLY_UNTAGGED = 2
1480 + * enum dpdmux_action - DPDMUX action for un-accepted frames
1481 + * @DPDMUX_ACTION_DROP: Drop un-accepted frames
1482 + * @DPDMUX_ACTION_REDIRECT_TO_CTRL: Redirect un-accepted frames to the
1483 + * control interface
1485 +enum dpdmux_action {
1486 + DPDMUX_ACTION_DROP = 0,
1487 + DPDMUX_ACTION_REDIRECT_TO_CTRL = 1
1491 + * struct dpdmux_accepted_frames - Frame types configuration
1492 + * @type: Defines ingress accepted frames
1493 + * @unaccept_act: Defines action on frames not accepted
1495 +struct dpdmux_accepted_frames {
1496 + enum dpdmux_accepted_frames_type type;
1497 + enum dpdmux_action unaccept_act;
1501 + * dpdmux_if_set_accepted_frames() - Set the accepted frame types
1502 + * @mc_io: Pointer to MC portal's I/O object
1503 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
1504 + * @token: Token of DPDMUX object
1505 + * @if_id: Interface ID (0 for uplink, or 1-num_ifs);
1506 + * @cfg: Frame types configuration
1508 + * if 'DPDMUX_ADMIT_ONLY_VLAN_TAGGED' is set - untagged frames or
1509 + * priority-tagged frames are discarded.
1510 + * if 'DPDMUX_ADMIT_ONLY_UNTAGGED' is set - untagged frames or
1511 + * priority-tagged frames are accepted.
1512 + * if 'DPDMUX_ADMIT_ALL' is set (default mode) - all VLAN tagged,
1513 + * untagged and priority-tagged frame are accepted;
1515 + * Return: '0' on Success; Error code otherwise.
1517 +int dpdmux_if_set_accepted_frames(struct fsl_mc_io *mc_io,
1518 + uint32_t cmd_flags,
1521 + const struct dpdmux_accepted_frames *cfg);
1524 + * struct dpdmux_if_attr - Structure representing frame types configuration
1525 + * @rate: Configured interface rate (in bits per second)
1526 + * @enabled: Indicates if interface is enabled
1527 + * @accept_frame_type: Indicates type of accepted frames for the interface
1529 +struct dpdmux_if_attr {
1532 + enum dpdmux_accepted_frames_type accept_frame_type;
1536 + * dpdmux_if_get_attributes() - Obtain DPDMUX interface attributes
1537 + * @mc_io: Pointer to MC portal's I/O object
1538 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
1539 + * @token: Token of DPDMUX object
1540 + * @if_id: Interface ID (0 for uplink, or 1-num_ifs);
1541 + * @attr: Interface attributes
1543 + * Return: '0' on Success; Error code otherwise.
1545 +int dpdmux_if_get_attributes(struct fsl_mc_io *mc_io,
1546 + uint32_t cmd_flags,
1549 + struct dpdmux_if_attr *attr);
1552 + * struct dpdmux_l2_rule - Structure representing L2 rule
1553 + * @mac_addr: MAC address
1554 + * @vlan_id: VLAN ID
1556 +struct dpdmux_l2_rule {
1557 + uint8_t mac_addr[6];
1562 + * dpdmux_if_remove_l2_rule() - Remove L2 rule from DPDMUX table
1563 + * @mc_io: Pointer to MC portal's I/O object
1564 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
1565 + * @token: Token of DPDMUX object
1566 + * @if_id: Destination interface ID
1569 + * Function removes a L2 rule from DPDMUX table
1570 + * or adds an interface to an existing multicast address
1572 + * Return: '0' on Success; Error code otherwise.
1574 +int dpdmux_if_remove_l2_rule(struct fsl_mc_io *mc_io,
1575 + uint32_t cmd_flags,
1578 + const struct dpdmux_l2_rule *rule);
1581 + * dpdmux_if_add_l2_rule() - Add L2 rule into DPDMUX table
1582 + * @mc_io: Pointer to MC portal's I/O object
1583 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
1584 + * @token: Token of DPDMUX object
1585 + * @if_id: Destination interface ID
1588 + * Function adds a L2 rule into DPDMUX table
1589 + * or adds an interface to an existing multicast address
1591 + * Return: '0' on Success; Error code otherwise.
1593 +int dpdmux_if_add_l2_rule(struct fsl_mc_io *mc_io,
1594 + uint32_t cmd_flags,
1597 + const struct dpdmux_l2_rule *rule);
1600 +* dpdmux_if_get_counter() - Functions obtains specific counter of an interface
1601 +* @mc_io: Pointer to MC portal's I/O object
1602 +* @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
1603 +* @token: Token of DPDMUX object
1604 +* @if_id: Interface Id
1605 +* @counter_type: counter type
1606 +* @counter: Returned specific counter information
1608 +* Return: '0' on Success; Error code otherwise.
1610 +int dpdmux_if_get_counter(struct fsl_mc_io *mc_io,
1611 + uint32_t cmd_flags,
1614 + enum dpdmux_counter_type counter_type,
1615 + uint64_t *counter);
1618 +* dpdmux_ul_reset_counters() - Function resets the uplink counter
1619 +* @mc_io: Pointer to MC portal's I/O object
1620 +* @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
1621 +* @token: Token of DPDMUX object
1623 +* Return: '0' on Success; Error code otherwise.
1625 +int dpdmux_ul_reset_counters(struct fsl_mc_io *mc_io,
1626 + uint32_t cmd_flags,
1630 + * Enable auto-negotiation
1632 +#define DPDMUX_LINK_OPT_AUTONEG 0x0000000000000001ULL
1634 + * Enable half-duplex mode
1636 +#define DPDMUX_LINK_OPT_HALF_DUPLEX 0x0000000000000002ULL
1638 + * Enable pause frames
1640 +#define DPDMUX_LINK_OPT_PAUSE 0x0000000000000004ULL
1642 + * Enable a-symmetric pause frames
1644 +#define DPDMUX_LINK_OPT_ASYM_PAUSE 0x0000000000000008ULL
1647 + * struct dpdmux_link_cfg - Structure representing DPDMUX link configuration
1649 + * @options: Mask of available options; use 'DPDMUX_LINK_OPT_<X>' values
1651 +struct dpdmux_link_cfg {
1657 + * dpdmux_if_set_link_cfg() - set the link configuration.
1658 + * @mc_io: Pointer to MC portal's I/O object
1659 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
1660 + * @token: Token of DPSW object
1661 + * @if_id: interface id
1662 + * @cfg: Link configuration
1664 + * Return: '0' on Success; Error code otherwise.
1666 +int dpdmux_if_set_link_cfg(struct fsl_mc_io *mc_io,
1667 + uint32_t cmd_flags,
1670 + struct dpdmux_link_cfg *cfg);
1672 + * struct dpdmux_link_state - Structure representing DPDMUX link state
1674 + * @options: Mask of available options; use 'DPDMUX_LINK_OPT_<X>' values
1675 + * @up: 0 - down, 1 - up
1677 +struct dpdmux_link_state {
1684 + * dpdmux_if_get_link_state - Return the link state
1685 + * @mc_io: Pointer to MC portal's I/O object
1686 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
1687 + * @token: Token of DPSW object
1688 + * @if_id: interface id
1689 + * @state: link state
1691 + * @returns '0' on Success; Error code otherwise.
1693 +int dpdmux_if_get_link_state(struct fsl_mc_io *mc_io,
1694 + uint32_t cmd_flags,
1697 + struct dpdmux_link_state *state);
1699 +#endif /* __FSL_DPDMUX_H */
1701 +++ b/drivers/staging/fsl-dpaa2/evb/evb.c
1703 +/* Copyright 2015 Freescale Semiconductor Inc.
1705 + * Redistribution and use in source and binary forms, with or without
1706 + * modification, are permitted provided that the following conditions are met:
1707 + * * Redistributions of source code must retain the above copyright
1708 + * notice, this list of conditions and the following disclaimer.
1709 + * * Redistributions in binary form must reproduce the above copyright
1710 + * notice, this list of conditions and the following disclaimer in the
1711 + * documentation and/or other materials provided with the distribution.
1712 + * * Neither the name of Freescale Semiconductor nor the
1713 + * names of its contributors may be used to endorse or promote products
1714 + * derived from this software without specific prior written permission.
1717 + * ALTERNATIVELY, this software may be distributed under the terms of the
1718 + * GNU General Public License ("GPL") as published by the Free Software
1719 + * Foundation, either version 2 of that License or (at your option) any
1722 + * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
1723 + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
1724 + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
1725 + * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
1726 + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
1727 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
1728 + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
1729 + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
1730 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
1731 + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1733 +#include <linux/module.h>
1734 +#include <linux/netdevice.h>
1735 +#include <linux/etherdevice.h>
1736 +#include <linux/rtnetlink.h>
1737 +#include <linux/if_vlan.h>
1738 +#include <linux/interrupt.h>
1739 +#include <linux/msi.h>
1741 +#include <uapi/linux/if_bridge.h>
1742 +#include <net/netlink.h>
1744 +#include "../../fsl-mc/include/mc.h"
1746 +#include "dpdmux.h"
1747 +#include "dpdmux-cmd.h"
1750 +#define DPDMUX_MAX_IRQ_NUM 2
1752 +/* MAX FRAME LENGTH (currently 10k) */
1753 +#define EVB_MAX_FRAME_LENGTH (10 * 1024)
1754 +/* MIN FRAME LENGTH (64 bytes + 4 bytes CRC) */
1755 +#define EVB_MIN_FRAME_LENGTH 68
1757 +struct evb_port_priv {
1758 + struct net_device *netdev;
1759 + struct list_head list;
1761 + struct evb_priv *evb_priv;
1762 + u8 vlans[VLAN_VID_MASK+1];
1767 + struct evb_port_priv uplink;
1769 + struct fsl_mc_io *mc_io;
1770 + struct list_head port_list;
1771 + struct dpdmux_attr attr;
1772 + uint16_t mux_handle;
1776 +static int _evb_port_carrier_state_sync(struct net_device *netdev)
1778 + struct evb_port_priv *port_priv = netdev_priv(netdev);
1779 + struct dpdmux_link_state state;
1782 + err = dpdmux_if_get_link_state(port_priv->evb_priv->mc_io, 0,
1783 + port_priv->evb_priv->mux_handle,
1784 + port_priv->port_index, &state);
1785 + if (unlikely(err)) {
1786 + netdev_err(netdev, "dpdmux_if_get_link_state() err %d\n", err);
1790 + WARN_ONCE(state.up > 1, "Garbage read into link_state");
1793 + netif_carrier_on(port_priv->netdev);
1795 + netif_carrier_off(port_priv->netdev);
1800 +static int evb_port_open(struct net_device *netdev)
1804 + /* FIXME: enable port when support added */
1806 + err = _evb_port_carrier_state_sync(netdev);
1808 + netdev_err(netdev, "ethsw_port_carrier_state_sync err %d\n",
1816 +static netdev_tx_t evb_dropframe(struct sk_buff *skb, struct net_device *dev)
1818 + /* we don't support I/O for now, drop the frame */
1819 + dev_kfree_skb_any(skb);
1820 + return NETDEV_TX_OK;
1823 +static int evb_links_state_update(struct evb_priv *priv)
1825 + struct evb_port_priv *port_priv;
1826 + struct list_head *pos;
1829 + list_for_each(pos, &priv->port_list) {
1830 + port_priv = list_entry(pos, struct evb_port_priv, list);
1832 + err = _evb_port_carrier_state_sync(port_priv->netdev);
1834 + netdev_err(port_priv->netdev,
1835 + "_evb_port_carrier_state_sync err %d\n",
1842 +static irqreturn_t evb_irq0_handler(int irq_num, void *arg)
1844 + return IRQ_WAKE_THREAD;
1847 +static irqreturn_t _evb_irq0_handler_thread(int irq_num, void *arg)
1849 + struct device *dev = (struct device *)arg;
1850 + struct fsl_mc_device *evb_dev = to_fsl_mc_device(dev);
1851 + struct net_device *netdev = dev_get_drvdata(dev);
1852 + struct evb_priv *priv = netdev_priv(netdev);
1853 + struct fsl_mc_io *io = priv->mc_io;
1854 + uint16_t token = priv->mux_handle;
1855 + int irq_index = DPDMUX_IRQ_INDEX_IF;
1856 + uint32_t status = 0, clear = 0;
1859 + /* Sanity check */
1860 + if (WARN_ON(!evb_dev || !evb_dev->irqs || !evb_dev->irqs[irq_index]))
1862 + if (WARN_ON(evb_dev->irqs[irq_index]->msi_desc->irq != irq_num))
1865 + err = dpdmux_get_irq_status(io, 0, token, irq_index, &status);
1866 + if (unlikely(err)) {
1867 + netdev_err(netdev, "Can't get irq status (err %d)", err);
1868 + clear = 0xffffffff;
1872 + /* FIXME clear irq status */
1874 + if (status & DPDMUX_IRQ_EVENT_LINK_CHANGED) {
1875 + clear |= DPDMUX_IRQ_EVENT_LINK_CHANGED;
1877 + err = evb_links_state_update(priv);
1878 + if (unlikely(err))
1882 + err = dpdmux_clear_irq_status(io, 0, token, irq_index, clear);
1883 + if (unlikely(err))
1884 + netdev_err(netdev, "Can't clear irq status (err %d)", err);
1885 + return IRQ_HANDLED;
1888 +static int evb_setup_irqs(struct fsl_mc_device *evb_dev)
1890 + struct device *dev = &evb_dev->dev;
1891 + struct net_device *netdev = dev_get_drvdata(dev);
1892 + struct evb_priv *priv = netdev_priv(netdev);
1894 + struct fsl_mc_device_irq *irq;
1895 + const int irq_index = DPDMUX_IRQ_INDEX_IF;
1896 + uint32_t mask = ~0x0u; /* FIXME: unmask handled irqs */
1898 + err = fsl_mc_allocate_irqs(evb_dev);
1899 + if (unlikely(err)) {
1900 + dev_err(dev, "MC irqs allocation failed\n");
1904 + if (WARN_ON(evb_dev->obj_desc.irq_count != DPDMUX_MAX_IRQ_NUM)) {
1909 + err = dpdmux_set_irq_enable(priv->mc_io, 0, priv->mux_handle,
1911 + if (unlikely(err)) {
1912 + dev_err(dev, "dpdmux_set_irq_enable err %d\n", err);
1916 + irq = evb_dev->irqs[irq_index];
1918 + err = devm_request_threaded_irq(dev, irq->msi_desc->irq,
1920 + _evb_irq0_handler_thread,
1921 + IRQF_NO_SUSPEND | IRQF_ONESHOT,
1922 + dev_name(dev), dev);
1923 + if (unlikely(err)) {
1924 + dev_err(dev, "devm_request_threaded_irq(): %d", err);
1928 + err = dpdmux_set_irq_mask(priv->mc_io, 0, priv->mux_handle,
1930 + if (unlikely(err)) {
1931 + dev_err(dev, "dpdmux_set_irq_mask(): %d", err);
1932 + goto free_devm_irq;
1935 + err = dpdmux_set_irq_enable(priv->mc_io, 0, priv->mux_handle,
1937 + if (unlikely(err)) {
1938 + dev_err(dev, "dpdmux_set_irq_enable(): %d", err);
1939 + goto free_devm_irq;
1945 + devm_free_irq(dev, irq->msi_desc->irq, dev);
1947 + fsl_mc_free_irqs(evb_dev);
1951 +static void evb_teardown_irqs(struct fsl_mc_device *evb_dev)
1953 + struct device *dev = &evb_dev->dev;
1954 + struct net_device *netdev = dev_get_drvdata(dev);
1955 + struct evb_priv *priv = netdev_priv(netdev);
1957 + dpdmux_set_irq_enable(priv->mc_io, 0, priv->mux_handle,
1958 + DPDMUX_IRQ_INDEX_IF, 0);
1960 + devm_free_irq(dev,
1961 + evb_dev->irqs[DPDMUX_IRQ_INDEX_IF]->msi_desc->irq,
1963 + fsl_mc_free_irqs(evb_dev);
1966 +static int evb_port_add_rule(struct net_device *netdev,
1967 + const unsigned char *addr, u16 vid)
1969 + struct evb_port_priv *port_priv = netdev_priv(netdev);
1970 + struct dpdmux_l2_rule rule = { .vlan_id = vid };
1974 + ether_addr_copy(rule.mac_addr, addr);
1976 + err = dpdmux_if_add_l2_rule(port_priv->evb_priv->mc_io,
1978 + port_priv->evb_priv->mux_handle,
1979 + port_priv->port_index, &rule);
1980 + if (unlikely(err))
1981 + netdev_err(netdev, "dpdmux_if_add_l2_rule err %d\n", err);
1985 +static int evb_port_del_rule(struct net_device *netdev,
1986 + const unsigned char *addr, u16 vid)
1988 + struct evb_port_priv *port_priv = netdev_priv(netdev);
1989 + struct dpdmux_l2_rule rule = { .vlan_id = vid };
1993 + ether_addr_copy(rule.mac_addr, addr);
1995 + err = dpdmux_if_remove_l2_rule(port_priv->evb_priv->mc_io,
1997 + port_priv->evb_priv->mux_handle,
1998 + port_priv->port_index, &rule);
1999 + if (unlikely(err))
2000 + netdev_err(netdev, "dpdmux_if_remove_l2_rule err %d\n", err);
2004 +static bool _lookup_address(struct net_device *netdev,
2005 + const unsigned char *addr)
2007 + struct netdev_hw_addr *ha;
2008 + struct netdev_hw_addr_list *list = (is_unicast_ether_addr(addr)) ?
2009 + &netdev->uc : &netdev->mc;
2011 + netif_addr_lock_bh(netdev);
2012 + list_for_each_entry(ha, &list->list, list) {
2013 + if (ether_addr_equal(ha->addr, addr)) {
2014 + netif_addr_unlock_bh(netdev);
2018 + netif_addr_unlock_bh(netdev);
2022 +static inline int evb_port_fdb_prep(struct nlattr *tb[],
2023 + struct net_device *netdev,
2024 + const unsigned char *addr, u16 *vid,
2027 + struct evb_port_priv *port_priv = netdev_priv(netdev);
2028 + struct evb_priv *evb_priv = port_priv->evb_priv;
2032 + if (evb_priv->attr.method != DPDMUX_METHOD_MAC &&
2033 + evb_priv->attr.method != DPDMUX_METHOD_C_VLAN_MAC) {
2034 + netdev_err(netdev,
2035 + "EVB mode does not support MAC classification\n");
2036 + return -EOPNOTSUPP;
2039 + /* check if the address is configured on this port */
2040 + if (_lookup_address(netdev, addr)) {
2048 + if (tb[NDA_VLAN] && evb_priv->attr.method == DPDMUX_METHOD_C_VLAN_MAC) {
2049 + if (nla_len(tb[NDA_VLAN]) != sizeof(unsigned short)) {
2050 + netdev_err(netdev, "invalid vlan size %d\n",
2051 + nla_len(tb[NDA_VLAN]));
2055 + *vid = nla_get_u16(tb[NDA_VLAN]);
2057 + if (!*vid || *vid >= VLAN_VID_MASK) {
2058 + netdev_err(netdev, "invalid vid value 0x%04x\n", *vid);
2061 + } else if (evb_priv->attr.method == DPDMUX_METHOD_C_VLAN_MAC) {
2062 + netdev_err(netdev,
2063 + "EVB mode requires explicit VLAN configuration\n");
2065 + } else if (tb[NDA_VLAN]) {
2066 + netdev_warn(netdev, "VLAN not supported, argument ignored\n");
2072 +static int evb_port_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
2073 + struct net_device *netdev,
2074 + const unsigned char *addr, u16 vid, u16 flags)
2079 + /* TODO: add replace support when added to iproute bridge */
2080 + if (!(flags & NLM_F_REQUEST)) {
2081 + netdev_err(netdev,
2082 + "evb_port_fdb_add unexpected flags value %08x\n",
2087 + err = evb_port_fdb_prep(tb, netdev, addr, &_vid, 0);
2088 + if (unlikely(err))
2092 + err = evb_port_add_rule(netdev, addr, _vid);
2093 + if (unlikely(err))
2096 + if (is_unicast_ether_addr(addr)) {
2097 + err = dev_uc_add(netdev, addr);
2098 + if (unlikely(err)) {
2099 + netdev_err(netdev, "dev_uc_add err %d\n", err);
2103 + err = dev_mc_add(netdev, addr);
2104 + if (unlikely(err)) {
2105 + netdev_err(netdev, "dev_mc_add err %d\n", err);
2113 +static int evb_port_fdb_del(struct ndmsg *ndm, struct nlattr *tb[],
2114 + struct net_device *netdev,
2115 + const unsigned char *addr, u16 vid)
2120 + err = evb_port_fdb_prep(tb, netdev, addr, &_vid, 1);
2121 + if (unlikely(err))
2124 + err = evb_port_del_rule(netdev, addr, _vid);
2125 + if (unlikely(err))
2128 + if (is_unicast_ether_addr(addr)) {
2129 + err = dev_uc_del(netdev, addr);
2130 + if (unlikely(err)) {
2131 + netdev_err(netdev, "dev_uc_del err %d\n", err);
2135 + err = dev_mc_del(netdev, addr);
2136 + if (unlikely(err)) {
2137 + netdev_err(netdev, "dev_mc_del err %d\n", err);
2145 +static int evb_change_mtu(struct net_device *netdev,
2148 + struct evb_port_priv *port_priv = netdev_priv(netdev);
2149 + struct evb_priv *evb_priv = port_priv->evb_priv;
2150 + struct list_head *pos;
2153 + /* This operation is not permitted on downlinks */
2154 + if (port_priv->port_index > 0)
2157 + if (mtu < EVB_MIN_FRAME_LENGTH || mtu > EVB_MAX_FRAME_LENGTH) {
2158 + netdev_err(netdev, "Invalid MTU %d. Valid range is: %d..%d\n",
2159 + mtu, EVB_MIN_FRAME_LENGTH, EVB_MAX_FRAME_LENGTH);
2163 + err = dpdmux_ul_set_max_frame_length(evb_priv->mc_io,
2165 + evb_priv->mux_handle,
2168 + if (unlikely(err)) {
2169 + netdev_err(netdev, "dpdmux_ul_set_max_frame_length err %d\n",
2174 + /* Update the max frame length for downlinks */
2175 + list_for_each(pos, &evb_priv->port_list) {
2176 + port_priv = list_entry(pos, struct evb_port_priv, list);
2177 + port_priv->netdev->mtu = mtu;
2180 + netdev->mtu = mtu;
2184 +static const struct nla_policy ifla_br_policy[IFLA_MAX+1] = {
2185 + [IFLA_BRIDGE_FLAGS] = { .type = NLA_U16 },
2186 + [IFLA_BRIDGE_MODE] = { .type = NLA_U16 },
2187 + [IFLA_BRIDGE_VLAN_INFO] = { .type = NLA_BINARY,
2188 + .len = sizeof(struct bridge_vlan_info), },
2191 +static int evb_setlink_af_spec(struct net_device *netdev,
2192 + struct nlattr **tb)
2194 + struct bridge_vlan_info *vinfo;
2195 + struct evb_port_priv *port_priv = netdev_priv(netdev);
2198 + if (!tb[IFLA_BRIDGE_VLAN_INFO]) {
2199 + netdev_err(netdev, "no VLAN INFO in nlmsg\n");
2200 + return -EOPNOTSUPP;
2203 + vinfo = nla_data(tb[IFLA_BRIDGE_VLAN_INFO]);
2205 + if (!vinfo->vid || vinfo->vid > VLAN_VID_MASK)
2208 + err = evb_port_add_rule(netdev, NULL, vinfo->vid);
2209 + if (unlikely(err))
2212 + port_priv->vlans[vinfo->vid] = 1;
2217 +static int evb_setlink(struct net_device *netdev,
2218 + struct nlmsghdr *nlh,
2221 + struct evb_port_priv *port_priv = netdev_priv(netdev);
2222 + struct evb_priv *evb_priv = port_priv->evb_priv;
2223 + struct nlattr *attr;
2224 + struct nlattr *tb[(IFLA_BRIDGE_MAX > IFLA_BRPORT_MAX) ?
2225 + IFLA_BRIDGE_MAX : IFLA_BRPORT_MAX+1];
2228 + if (evb_priv->attr.method != DPDMUX_METHOD_C_VLAN &&
2229 + evb_priv->attr.method != DPDMUX_METHOD_S_VLAN) {
2230 + netdev_err(netdev,
2231 + "EVB mode does not support VLAN only classification\n");
2232 + return -EOPNOTSUPP;
2235 + attr = nlmsg_find_attr(nlh, sizeof(struct ifinfomsg), IFLA_AF_SPEC);
2237 + err = nla_parse_nested(tb, IFLA_BRIDGE_MAX, attr,
2239 + if (unlikely(err)) {
2240 + netdev_err(netdev,
2241 + "nla_parse_nested for br_policy err %d\n",
2246 + err = evb_setlink_af_spec(netdev, tb);
2250 + netdev_err(netdev, "nlmsg_find_attr found no AF_SPEC\n");
2251 + return -EOPNOTSUPP;
2254 +static int __nla_put_netdev(struct sk_buff *skb, struct net_device *netdev)
2256 + struct evb_port_priv *port_priv = netdev_priv(netdev);
2257 + struct evb_priv *evb_priv = port_priv->evb_priv;
2258 + u8 operstate = netif_running(netdev) ?
2259 + netdev->operstate : IF_OPER_DOWN;
2263 + err = nla_put_string(skb, IFLA_IFNAME, netdev->name);
2264 + if (unlikely(err))
2266 + err = nla_put_u32(skb, IFLA_MASTER, evb_priv->uplink.netdev->ifindex);
2267 + if (unlikely(err))
2269 + err = nla_put_u32(skb, IFLA_MTU, netdev->mtu);
2270 + if (unlikely(err))
2272 + err = nla_put_u8(skb, IFLA_OPERSTATE, operstate);
2273 + if (unlikely(err))
2275 + if (netdev->addr_len) {
2276 + err = nla_put(skb, IFLA_ADDRESS, netdev->addr_len,
2277 + netdev->dev_addr);
2278 + if (unlikely(err))
2282 + iflink = dev_get_iflink(netdev);
2283 + if (netdev->ifindex != iflink) {
2284 + err = nla_put_u32(skb, IFLA_LINK, iflink);
2285 + if (unlikely(err))
2292 + netdev_err(netdev, "nla_put_ err %d\n", err);
2296 +static int __nla_put_port(struct sk_buff *skb, struct net_device *netdev)
2298 + struct nlattr *nest;
2301 + nest = nla_nest_start(skb, IFLA_PROTINFO | NLA_F_NESTED);
2303 + netdev_err(netdev, "nla_nest_start failed\n");
2307 + err = nla_put_u8(skb, IFLA_BRPORT_STATE, BR_STATE_FORWARDING);
2308 + if (unlikely(err))
2310 + err = nla_put_u16(skb, IFLA_BRPORT_PRIORITY, 0);
2311 + if (unlikely(err))
2313 + err = nla_put_u32(skb, IFLA_BRPORT_COST, 0);
2314 + if (unlikely(err))
2316 + err = nla_put_u8(skb, IFLA_BRPORT_MODE, 0);
2317 + if (unlikely(err))
2319 + err = nla_put_u8(skb, IFLA_BRPORT_GUARD, 0);
2320 + if (unlikely(err))
2322 + err = nla_put_u8(skb, IFLA_BRPORT_PROTECT, 0);
2323 + if (unlikely(err))
2325 + err = nla_put_u8(skb, IFLA_BRPORT_FAST_LEAVE, 0);
2326 + if (unlikely(err))
2328 + err = nla_put_u8(skb, IFLA_BRPORT_LEARNING, 0);
2329 + if (unlikely(err))
2331 + err = nla_put_u8(skb, IFLA_BRPORT_UNICAST_FLOOD, 1);
2332 + if (unlikely(err))
2334 + nla_nest_end(skb, nest);
2339 + netdev_err(netdev, "nla_put_ err %d\n", err);
2340 + nla_nest_cancel(skb, nest);
2344 +static int __nla_put_vlan(struct sk_buff *skb, struct net_device *netdev)
2346 + struct evb_port_priv *port_priv = netdev_priv(netdev);
2347 + struct nlattr *nest;
2348 + struct bridge_vlan_info vinfo;
2349 + const u8 *vlans = port_priv->vlans;
2353 + nest = nla_nest_start(skb, IFLA_AF_SPEC);
2355 + netdev_err(netdev, "nla_nest_start failed");
2359 + for (i = 0; i < VLAN_VID_MASK+1; i++) {
2366 + err = nla_put(skb, IFLA_BRIDGE_VLAN_INFO,
2367 + sizeof(vinfo), &vinfo);
2368 + if (unlikely(err))
2372 + nla_nest_end(skb, nest);
2377 + netdev_err(netdev, "nla_put_ err %d\n", err);
2378 + nla_nest_cancel(skb, nest);
2382 +static int evb_getlink(struct sk_buff *skb, u32 pid, u32 seq,
2383 + struct net_device *netdev, u32 filter_mask, int nlflags)
2385 + struct evb_port_priv *port_priv = netdev_priv(netdev);
2386 + struct evb_priv *evb_priv = port_priv->evb_priv;
2387 + struct ifinfomsg *hdr;
2388 + struct nlmsghdr *nlh;
2391 + if (evb_priv->attr.method != DPDMUX_METHOD_C_VLAN &&
2392 + evb_priv->attr.method != DPDMUX_METHOD_S_VLAN) {
2396 + nlh = nlmsg_put(skb, pid, seq, RTM_NEWLINK, sizeof(*hdr), NLM_F_MULTI);
2400 + hdr = nlmsg_data(nlh);
2401 + memset(hdr, 0, sizeof(*hdr));
2402 + hdr->ifi_family = AF_BRIDGE;
2403 + hdr->ifi_type = netdev->type;
2404 + hdr->ifi_index = netdev->ifindex;
2405 + hdr->ifi_flags = dev_get_flags(netdev);
2407 + err = __nla_put_netdev(skb, netdev);
2408 + if (unlikely(err))
2411 + err = __nla_put_port(skb, netdev);
2412 + if (unlikely(err))
2415 + /* Check if the VID information is requested */
2416 + if (filter_mask & RTEXT_FILTER_BRVLAN) {
2417 + err = __nla_put_vlan(skb, netdev);
2418 + if (unlikely(err))
2422 + nlmsg_end(skb, nlh);
2426 + nlmsg_cancel(skb, nlh);
2430 +static int evb_dellink(struct net_device *netdev,
2431 + struct nlmsghdr *nlh,
2434 + struct nlattr *tb[IFLA_BRIDGE_MAX+1];
2435 + struct nlattr *spec;
2436 + struct bridge_vlan_info *vinfo;
2437 + struct evb_port_priv *port_priv = netdev_priv(netdev);
2440 + spec = nlmsg_find_attr(nlh, sizeof(struct ifinfomsg), IFLA_AF_SPEC);
2444 + err = nla_parse_nested(tb, IFLA_BRIDGE_MAX, spec, ifla_br_policy);
2445 + if (unlikely(err))
2448 + if (!tb[IFLA_BRIDGE_VLAN_INFO])
2449 + return -EOPNOTSUPP;
2451 + vinfo = nla_data(tb[IFLA_BRIDGE_VLAN_INFO]);
2453 + if (!vinfo->vid || vinfo->vid > VLAN_VID_MASK)
2456 + err = evb_port_del_rule(netdev, NULL, vinfo->vid);
2457 + if (unlikely(err)) {
2458 + netdev_err(netdev, "evb_port_del_rule err %d\n", err);
2461 + port_priv->vlans[vinfo->vid] = 0;
2466 +static struct rtnl_link_stats64 *
2467 +evb_port_get_stats(struct net_device *netdev,
2468 + struct rtnl_link_stats64 *storage)
2470 + struct evb_port_priv *port_priv = netdev_priv(netdev);
2474 + err = dpdmux_if_get_counter(port_priv->evb_priv->mc_io,
2476 + port_priv->evb_priv->mux_handle,
2477 + port_priv->port_index,
2478 + DPDMUX_CNT_ING_FRAME, &storage->rx_packets);
2479 + if (unlikely(err))
2482 + err = dpdmux_if_get_counter(port_priv->evb_priv->mc_io,
2484 + port_priv->evb_priv->mux_handle,
2485 + port_priv->port_index,
2486 + DPDMUX_CNT_ING_BYTE, &storage->rx_bytes);
2487 + if (unlikely(err))
2490 + err = dpdmux_if_get_counter(port_priv->evb_priv->mc_io,
2492 + port_priv->evb_priv->mux_handle,
2493 + port_priv->port_index,
2494 + DPDMUX_CNT_ING_FLTR_FRAME, &tmp);
2495 + if (unlikely(err))
2498 + err = dpdmux_if_get_counter(port_priv->evb_priv->mc_io,
2500 + port_priv->evb_priv->mux_handle,
2501 + port_priv->port_index,
2502 + DPDMUX_CNT_ING_FRAME_DISCARD,
2503 + &storage->rx_dropped);
2504 + if (unlikely(err)) {
2505 + storage->rx_dropped = tmp;
2508 + storage->rx_dropped += tmp;
2510 + err = dpdmux_if_get_counter(port_priv->evb_priv->mc_io,
2512 + port_priv->evb_priv->mux_handle,
2513 + port_priv->port_index,
2514 + DPDMUX_CNT_ING_MCAST_FRAME,
2515 + &storage->multicast);
2516 + if (unlikely(err))
2519 + err = dpdmux_if_get_counter(port_priv->evb_priv->mc_io,
2521 + port_priv->evb_priv->mux_handle,
2522 + port_priv->port_index,
2523 + DPDMUX_CNT_EGR_FRAME, &storage->tx_packets);
2524 + if (unlikely(err))
2527 + err = dpdmux_if_get_counter(port_priv->evb_priv->mc_io,
2529 + port_priv->evb_priv->mux_handle,
2530 + port_priv->port_index,
2531 + DPDMUX_CNT_EGR_BYTE, &storage->tx_bytes);
2532 + if (unlikely(err))
2535 + err = dpdmux_if_get_counter(port_priv->evb_priv->mc_io,
2537 + port_priv->evb_priv->mux_handle,
2538 + port_priv->port_index,
2539 + DPDMUX_CNT_EGR_FRAME_DISCARD,
2540 + &storage->tx_dropped);
2541 + if (unlikely(err))
2547 + netdev_err(netdev, "dpdmux_if_get_counter err %d\n", err);
2551 +static const struct net_device_ops evb_port_ops = {
2552 + .ndo_open = &evb_port_open,
2554 + .ndo_start_xmit = &evb_dropframe,
2556 + .ndo_fdb_add = &evb_port_fdb_add,
2557 + .ndo_fdb_del = &evb_port_fdb_del,
2559 + .ndo_get_stats64 = &evb_port_get_stats,
2560 + .ndo_change_mtu = &evb_change_mtu,
2564 + enum dpdmux_counter_type id;
2565 + char name[ETH_GSTRING_LEN];
2566 +} evb_ethtool_counters[] = {
2567 + {DPDMUX_CNT_ING_FRAME, "rx frames"},
2568 + {DPDMUX_CNT_ING_BYTE, "rx bytes"},
2569 + {DPDMUX_CNT_ING_FLTR_FRAME, "rx filtered frames"},
2570 + {DPDMUX_CNT_ING_FRAME_DISCARD, "rx discarded frames"},
2571 + {DPDMUX_CNT_ING_BCAST_FRAME, "rx b-cast frames"},
2572 + {DPDMUX_CNT_ING_BCAST_BYTES, "rx b-cast bytes"},
2573 + {DPDMUX_CNT_ING_MCAST_FRAME, "rx m-cast frames"},
2574 + {DPDMUX_CNT_ING_MCAST_BYTE, "rx m-cast bytes"},
2575 + {DPDMUX_CNT_EGR_FRAME, "tx frames"},
2576 + {DPDMUX_CNT_EGR_BYTE, "tx bytes"},
2577 + {DPDMUX_CNT_EGR_FRAME_DISCARD, "tx discarded frames"},
2580 +static int evb_ethtool_get_sset_count(struct net_device *dev, int sset)
2583 + case ETH_SS_STATS:
2584 + return ARRAY_SIZE(evb_ethtool_counters);
2586 + return -EOPNOTSUPP;
2590 +static void evb_ethtool_get_strings(struct net_device *netdev,
2591 + u32 stringset, u8 *data)
2595 + switch (stringset) {
2596 + case ETH_SS_STATS:
2597 + for (i = 0; i < ARRAY_SIZE(evb_ethtool_counters); i++)
2598 + memcpy(data + i * ETH_GSTRING_LEN,
2599 + evb_ethtool_counters[i].name, ETH_GSTRING_LEN);
2604 +static void evb_ethtool_get_stats(struct net_device *netdev,
2605 + struct ethtool_stats *stats,
2608 + struct evb_port_priv *port_priv = netdev_priv(netdev);
2612 + for (i = 0; i < ARRAY_SIZE(evb_ethtool_counters); i++) {
2613 + err = dpdmux_if_get_counter(port_priv->evb_priv->mc_io,
2615 + port_priv->evb_priv->mux_handle,
2616 + port_priv->port_index,
2617 + evb_ethtool_counters[i].id,
2620 + netdev_err(netdev, "dpdmux_if_get_counter[%s] err %d\n",
2621 + evb_ethtool_counters[i].name, err);
2625 +static const struct ethtool_ops evb_port_ethtool_ops = {
2626 + .get_strings = &evb_ethtool_get_strings,
2627 + .get_ethtool_stats = &evb_ethtool_get_stats,
2628 + .get_sset_count = &evb_ethtool_get_sset_count,
2631 +static int evb_open(struct net_device *netdev)
2633 + struct evb_priv *priv = netdev_priv(netdev);
2636 + err = dpdmux_enable(priv->mc_io, 0, priv->mux_handle);
2637 + if (unlikely(err))
2638 + netdev_err(netdev, "dpdmux_enable err %d\n", err);
2643 +static int evb_close(struct net_device *netdev)
2645 + struct evb_priv *priv = netdev_priv(netdev);
2648 + err = dpdmux_disable(priv->mc_io, 0, priv->mux_handle);
2649 + if (unlikely(err))
2650 + netdev_err(netdev, "dpdmux_disable err %d\n", err);
2655 +static const struct net_device_ops evb_ops = {
2656 + .ndo_start_xmit = &evb_dropframe,
2657 + .ndo_open = &evb_open,
2658 + .ndo_stop = &evb_close,
2660 + .ndo_bridge_setlink = &evb_setlink,
2661 + .ndo_bridge_getlink = &evb_getlink,
2662 + .ndo_bridge_dellink = &evb_dellink,
2664 + .ndo_get_stats64 = &evb_port_get_stats,
2665 + .ndo_change_mtu = &evb_change_mtu,
2668 +static int evb_takedown(struct fsl_mc_device *evb_dev)
2670 + struct device *dev = &evb_dev->dev;
2671 + struct net_device *netdev = dev_get_drvdata(dev);
2672 + struct evb_priv *priv = netdev_priv(netdev);
2675 + err = dpdmux_close(priv->mc_io, 0, priv->mux_handle);
2676 + if (unlikely(err))
2677 + dev_warn(dev, "dpdmux_close err %d\n", err);
2682 +static int evb_init(struct fsl_mc_device *evb_dev)
2684 + struct device *dev = &evb_dev->dev;
2685 + struct net_device *netdev = dev_get_drvdata(dev);
2686 + struct evb_priv *priv = netdev_priv(netdev);
2689 + priv->dev_id = evb_dev->obj_desc.id;
2691 + err = dpdmux_open(priv->mc_io, 0, priv->dev_id, &priv->mux_handle);
2692 + if (unlikely(err)) {
2693 + dev_err(dev, "dpdmux_open err %d\n", err);
2696 + if (!priv->mux_handle) {
2697 + dev_err(dev, "dpdmux_open returned null handle but no error\n");
2702 + err = dpdmux_get_attributes(priv->mc_io, 0, priv->mux_handle,
2704 + if (unlikely(err)) {
2705 + dev_err(dev, "dpdmux_get_attributes err %d\n", err);
2709 + err = dpdmux_reset(priv->mc_io, 0, priv->mux_handle);
2710 + if (unlikely(err)) {
2711 + dev_err(dev, "dpdmux_reset err %d\n", err);
2718 + dpdmux_close(priv->mc_io, 0, priv->mux_handle);
2723 +static int evb_remove(struct fsl_mc_device *evb_dev)
2725 + struct device *dev = &evb_dev->dev;
2726 + struct net_device *netdev = dev_get_drvdata(dev);
2727 + struct evb_priv *priv = netdev_priv(netdev);
2728 + struct evb_port_priv *port_priv;
2729 + struct list_head *pos;
2731 + list_for_each(pos, &priv->port_list) {
2732 + port_priv = list_entry(pos, struct evb_port_priv, list);
2735 + netdev_upper_dev_unlink(port_priv->netdev, netdev);
2738 + unregister_netdev(port_priv->netdev);
2739 + free_netdev(port_priv->netdev);
2742 + evb_teardown_irqs(evb_dev);
2744 + unregister_netdev(netdev);
2746 + evb_takedown(evb_dev);
2747 + fsl_mc_portal_free(priv->mc_io);
2749 + dev_set_drvdata(dev, NULL);
2750 + free_netdev(netdev);
2755 +static int evb_probe(struct fsl_mc_device *evb_dev)
2757 + struct device *dev;
2758 + struct evb_priv *priv = NULL;
2759 + struct net_device *netdev = NULL;
2760 + char port_name[IFNAMSIZ];
2764 + dev = &evb_dev->dev;
2766 + /* register switch device, it's for management only - no I/O */
2767 + netdev = alloc_etherdev(sizeof(*priv));
2769 + dev_err(dev, "alloc_etherdev error\n");
2772 + netdev->netdev_ops = &evb_ops;
2774 + dev_set_drvdata(dev, netdev);
2776 + priv = netdev_priv(netdev);
2778 + err = fsl_mc_portal_allocate(evb_dev, 0, &priv->mc_io);
2779 + if (unlikely(err)) {
2780 + dev_err(dev, "fsl_mc_portal_allocate err %d\n", err);
2781 + goto err_free_netdev;
2783 + if (!priv->mc_io) {
2784 + dev_err(dev, "fsl_mc_portal_allocate returned null handle but no error\n");
2786 + goto err_free_netdev;
2789 + err = evb_init(evb_dev);
2790 + if (unlikely(err)) {
2791 + dev_err(dev, "evb init err %d\n", err);
2792 + goto err_free_cmdport;
2795 + INIT_LIST_HEAD(&priv->port_list);
2796 + netdev->flags |= IFF_PROMISC | IFF_MASTER;
2798 + dev_alloc_name(netdev, "evb%d");
2800 + /* register switch ports */
2801 + snprintf(port_name, IFNAMSIZ, "%sp%%d", netdev->name);
2803 + /* only register downlinks? */
2804 + for (i = 0; i < priv->attr.num_ifs + 1; i++) {
2805 + struct net_device *port_netdev;
2806 + struct evb_port_priv *port_priv;
2810 + alloc_etherdev(sizeof(struct evb_port_priv));
2811 + if (!port_netdev) {
2812 + dev_err(dev, "alloc_etherdev error\n");
2813 + goto err_takedown;
2816 + port_priv = netdev_priv(port_netdev);
2818 + port_netdev->flags |= IFF_PROMISC | IFF_SLAVE;
2820 + dev_alloc_name(port_netdev, port_name);
2822 + port_netdev = netdev;
2823 + port_priv = &priv->uplink;
2826 + port_priv->netdev = port_netdev;
2827 + port_priv->evb_priv = priv;
2828 + port_priv->port_index = i;
2830 + SET_NETDEV_DEV(port_netdev, dev);
2833 + port_netdev->netdev_ops = &evb_port_ops;
2835 + err = register_netdev(port_netdev);
2837 + dev_err(dev, "register_netdev err %d\n", err);
2838 + free_netdev(port_netdev);
2839 + goto err_takedown;
2843 + err = netdev_master_upper_dev_link(port_netdev, netdev, NULL, NULL);
2844 + if (unlikely(err)) {
2845 + dev_err(dev, "netdev_master_upper_dev_link err %d\n",
2847 + unregister_netdev(port_netdev);
2848 + free_netdev(port_netdev);
2850 + goto err_takedown;
2852 + rtmsg_ifinfo(RTM_NEWLINK, port_netdev,
2853 + IFF_SLAVE, GFP_KERNEL);
2856 + list_add(&(port_priv->list), &(priv->port_list));
2858 + err = register_netdev(netdev);
2861 + dev_err(dev, "register_netdev error %d\n", err);
2862 + goto err_takedown;
2866 + port_netdev->ethtool_ops = &evb_port_ethtool_ops;
2868 + /* ports are up from init */
2870 + err = dev_open(port_netdev);
2872 + if (unlikely(err))
2873 + dev_warn(dev, "dev_open err %d\n", err);
2877 + err = evb_setup_irqs(evb_dev);
2878 + if (unlikely(err)) {
2879 + dev_warn(dev, "evb_setup_irqs err %d\n", err);
2880 + goto err_takedown;
2883 + dev_info(dev, "probed evb device with %d ports\n",
2884 + priv->attr.num_ifs);
2888 + evb_remove(evb_dev);
2890 + fsl_mc_portal_free(priv->mc_io);
2895 +static const struct fsl_mc_device_match_id evb_match_id_table[] = {
2897 + .vendor = FSL_MC_VENDOR_FREESCALE,
2898 + .obj_type = "dpdmux",
2899 + .ver_major = DPDMUX_VER_MAJOR,
2900 + .ver_minor = DPDMUX_VER_MINOR,
2905 +static struct fsl_mc_driver evb_drv = {
2907 + .name = KBUILD_MODNAME,
2908 + .owner = THIS_MODULE,
2910 + .probe = evb_probe,
2911 + .remove = evb_remove,
2912 + .match_id_table = evb_match_id_table,
2915 +module_fsl_mc_driver(evb_drv);
2917 +MODULE_LICENSE("GPL");
2918 +MODULE_DESCRIPTION("Layerscape DPAA Edge Virtual Bridge driver (prototype)");