2019-05-26 23:55:01 -07:00
|
|
|
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
2016-11-03 19:23:26 -07:00
|
|
|
/*
|
|
|
|
* Marvell 88E6xxx Switch Port Registers support
|
|
|
|
*
|
|
|
|
* Copyright (c) 2008 Marvell Semiconductor
|
|
|
|
*
|
2017-03-28 12:10:36 -07:00
|
|
|
* Copyright (c) 2016-2017 Savoir-faire Linux Inc.
|
|
|
|
* Vivien Didelot <vivien.didelot@savoirfairelinux.com>
|
2016-11-03 19:23:26 -07:00
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef _MV88E6XXX_PORT_H
|
|
|
|
#define _MV88E6XXX_PORT_H
|
|
|
|
|
2017-06-02 14:06:15 -07:00
|
|
|
#include "chip.h"
|
2016-11-03 19:23:26 -07:00
|
|
|
|
2017-06-12 09:37:33 -07:00
|
|
|
/* Offset 0x00: Port Status Register */
|
|
|
|
#define MV88E6XXX_PORT_STS 0x00
|
|
|
|
#define MV88E6XXX_PORT_STS_PAUSE_EN 0x8000
|
|
|
|
#define MV88E6XXX_PORT_STS_MY_PAUSE 0x4000
|
|
|
|
#define MV88E6XXX_PORT_STS_HD_FLOW 0x2000
|
|
|
|
#define MV88E6XXX_PORT_STS_PHY_DETECT 0x1000
|
net: dsa: mv88e6xxx: implement port_link_state for mv88e6250
The mv88e6250 has a rather different way of reporting the link, speed
and duplex status. A simple difference is that the link bit is bit 12
rather than bit 11 of the port status register.
It gets more complicated for speed and duplex, which do not have
separate fields. Instead, there's a four-bit PortMode field, and
decoding that depends on whether it's a phy or mii port. For the phy
ports, only four of the 16 values have defined meaning; the rest are
called "reserved", so returning {SPEED,DUPLEX}_UNKNOWN seems
reasonable.
For the mii ports, most possible values are documented (0x3 and 0x5
are reserved), but I'm unable to make sense of them all. Since the
bits simply reflect the Px_MODE[3:0] configuration pins, just support
the subset that I'm certain about. Support for other setups can be
added later.
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: Rasmus Villemoes <rasmus.villemoes@prevas.dk>
Signed-off-by: David S. Miller <davem@davemloft.net>
2019-06-04 00:34:30 -07:00
|
|
|
#define MV88E6250_PORT_STS_LINK 0x1000
|
|
|
|
#define MV88E6250_PORT_STS_PORTMODE_MASK 0x0f00
|
|
|
|
#define MV88E6250_PORT_STS_PORTMODE_PHY_10_HALF 0x0800
|
|
|
|
#define MV88E6250_PORT_STS_PORTMODE_PHY_100_HALF 0x0900
|
|
|
|
#define MV88E6250_PORT_STS_PORTMODE_PHY_10_FULL 0x0a00
|
|
|
|
#define MV88E6250_PORT_STS_PORTMODE_PHY_100_FULL 0x0b00
|
2024-04-17 03:37:37 -07:00
|
|
|
/* - Modes with PHY suffix use output instead of input clock
|
|
|
|
* - Modes without RMII or RGMII use MII
|
|
|
|
* - Modes without speed do not have a fixed speed specified in the manual
|
|
|
|
* ("DC to x MHz" - variable clock support?)
|
|
|
|
*/
|
|
|
|
#define MV88E6250_PORT_STS_PORTMODE_MII_DISABLED 0x0000
|
|
|
|
#define MV88E6250_PORT_STS_PORTMODE_MII_100_RGMII 0x0100
|
|
|
|
#define MV88E6250_PORT_STS_PORTMODE_MII_DUAL_100_RMII_FULL_PHY 0x0200
|
|
|
|
#define MV88E6250_PORT_STS_PORTMODE_MII_200_RMII_FULL_PHY 0x0400
|
|
|
|
#define MV88E6250_PORT_STS_PORTMODE_MII_DUAL_100_RMII_FULL 0x0600
|
|
|
|
#define MV88E6250_PORT_STS_PORTMODE_MII_10_100_RMII_FULL 0x0700
|
|
|
|
#define MV88E6250_PORT_STS_PORTMODE_MII_HALF 0x0800
|
|
|
|
#define MV88E6250_PORT_STS_PORTMODE_MII_10_100_RMII_HALF_PHY 0x0900
|
|
|
|
#define MV88E6250_PORT_STS_PORTMODE_MII_FULL 0x0a00
|
|
|
|
#define MV88E6250_PORT_STS_PORTMODE_MII_10_100_RMII_FULL_PHY 0x0b00
|
|
|
|
#define MV88E6250_PORT_STS_PORTMODE_MII_10_HALF_PHY 0x0c00
|
|
|
|
#define MV88E6250_PORT_STS_PORTMODE_MII_100_HALF_PHY 0x0d00
|
|
|
|
#define MV88E6250_PORT_STS_PORTMODE_MII_10_FULL_PHY 0x0e00
|
|
|
|
#define MV88E6250_PORT_STS_PORTMODE_MII_100_FULL_PHY 0x0f00
|
2017-06-12 09:37:33 -07:00
|
|
|
#define MV88E6XXX_PORT_STS_LINK 0x0800
|
|
|
|
#define MV88E6XXX_PORT_STS_DUPLEX 0x0400
|
|
|
|
#define MV88E6XXX_PORT_STS_SPEED_MASK 0x0300
|
|
|
|
#define MV88E6XXX_PORT_STS_SPEED_10 0x0000
|
|
|
|
#define MV88E6XXX_PORT_STS_SPEED_100 0x0100
|
|
|
|
#define MV88E6XXX_PORT_STS_SPEED_1000 0x0200
|
2018-05-10 13:17:35 -07:00
|
|
|
#define MV88E6XXX_PORT_STS_SPEED_10000 0x0300
|
2017-06-12 09:37:33 -07:00
|
|
|
#define MV88E6352_PORT_STS_EEE 0x0040
|
|
|
|
#define MV88E6165_PORT_STS_AM_DIS 0x0040
|
|
|
|
#define MV88E6185_PORT_STS_MGMII 0x0040
|
|
|
|
#define MV88E6XXX_PORT_STS_TX_PAUSED 0x0020
|
|
|
|
#define MV88E6XXX_PORT_STS_FLOW_CTL 0x0010
|
|
|
|
#define MV88E6XXX_PORT_STS_CMODE_MASK 0x000f
|
2022-02-03 06:30:42 -07:00
|
|
|
#define MV88E6XXX_PORT_STS_CMODE_MII_PHY 0x0001
|
|
|
|
#define MV88E6XXX_PORT_STS_CMODE_MII 0x0002
|
|
|
|
#define MV88E6XXX_PORT_STS_CMODE_GMII 0x0003
|
|
|
|
#define MV88E6XXX_PORT_STS_CMODE_RMII_PHY 0x0004
|
|
|
|
#define MV88E6XXX_PORT_STS_CMODE_RMII 0x0005
|
2019-08-14 07:40:24 -07:00
|
|
|
#define MV88E6XXX_PORT_STS_CMODE_RGMII 0x0007
|
2019-08-26 14:31:54 -07:00
|
|
|
#define MV88E6XXX_PORT_STS_CMODE_100BASEX 0x0008
|
|
|
|
#define MV88E6XXX_PORT_STS_CMODE_1000BASEX 0x0009
|
2017-06-12 09:37:33 -07:00
|
|
|
#define MV88E6XXX_PORT_STS_CMODE_SGMII 0x000a
|
|
|
|
#define MV88E6XXX_PORT_STS_CMODE_2500BASEX 0x000b
|
|
|
|
#define MV88E6XXX_PORT_STS_CMODE_XAUI 0x000c
|
|
|
|
#define MV88E6XXX_PORT_STS_CMODE_RXAUI 0x000d
|
2021-03-17 06:46:42 -07:00
|
|
|
#define MV88E6393X_PORT_STS_CMODE_5GBASER 0x000c
|
|
|
|
#define MV88E6393X_PORT_STS_CMODE_10GBASER 0x000d
|
|
|
|
#define MV88E6393X_PORT_STS_CMODE_USXGMII 0x000e
|
2018-08-09 06:38:39 -07:00
|
|
|
#define MV88E6185_PORT_STS_CDUPLEX 0x0008
|
|
|
|
#define MV88E6185_PORT_STS_CMODE_MASK 0x0007
|
|
|
|
#define MV88E6185_PORT_STS_CMODE_GMII_FD 0x0000
|
|
|
|
#define MV88E6185_PORT_STS_CMODE_MII_100_FD_PS 0x0001
|
|
|
|
#define MV88E6185_PORT_STS_CMODE_MII_100 0x0002
|
|
|
|
#define MV88E6185_PORT_STS_CMODE_MII_10 0x0003
|
|
|
|
#define MV88E6185_PORT_STS_CMODE_SERDES 0x0004
|
|
|
|
#define MV88E6185_PORT_STS_CMODE_1000BASE_X 0x0005
|
|
|
|
#define MV88E6185_PORT_STS_CMODE_PHY 0x0006
|
|
|
|
#define MV88E6185_PORT_STS_CMODE_DISABLED 0x0007
|
2017-06-12 09:37:33 -07:00
|
|
|
|
2017-06-12 09:37:34 -07:00
|
|
|
/* Offset 0x01: MAC (or PCS or Physical) Control Register */
|
|
|
|
#define MV88E6XXX_PORT_MAC_CTL 0x01
|
|
|
|
#define MV88E6XXX_PORT_MAC_CTL_RGMII_DELAY_RXCLK 0x8000
|
|
|
|
#define MV88E6XXX_PORT_MAC_CTL_RGMII_DELAY_TXCLK 0x4000
|
2018-08-09 06:38:39 -07:00
|
|
|
#define MV88E6185_PORT_MAC_CTL_SYNC_OK 0x4000
|
2017-06-12 09:37:34 -07:00
|
|
|
#define MV88E6390_PORT_MAC_CTL_FORCE_SPEED 0x2000
|
|
|
|
#define MV88E6390_PORT_MAC_CTL_ALTSPEED 0x1000
|
|
|
|
#define MV88E6352_PORT_MAC_CTL_200BASE 0x1000
|
2021-03-17 06:46:42 -07:00
|
|
|
#define MV88E6XXX_PORT_MAC_CTL_EEE 0x0200
|
|
|
|
#define MV88E6XXX_PORT_MAC_CTL_FORCE_EEE 0x0100
|
2018-08-09 06:38:39 -07:00
|
|
|
#define MV88E6185_PORT_MAC_CTL_AN_EN 0x0400
|
|
|
|
#define MV88E6185_PORT_MAC_CTL_AN_RESTART 0x0200
|
|
|
|
#define MV88E6185_PORT_MAC_CTL_AN_DONE 0x0100
|
2017-06-12 09:37:34 -07:00
|
|
|
#define MV88E6XXX_PORT_MAC_CTL_FC 0x0080
|
|
|
|
#define MV88E6XXX_PORT_MAC_CTL_FORCE_FC 0x0040
|
|
|
|
#define MV88E6XXX_PORT_MAC_CTL_LINK_UP 0x0020
|
|
|
|
#define MV88E6XXX_PORT_MAC_CTL_FORCE_LINK 0x0010
|
|
|
|
#define MV88E6XXX_PORT_MAC_CTL_DUPLEX_FULL 0x0008
|
|
|
|
#define MV88E6XXX_PORT_MAC_CTL_FORCE_DUPLEX 0x0004
|
|
|
|
#define MV88E6XXX_PORT_MAC_CTL_SPEED_MASK 0x0003
|
|
|
|
#define MV88E6XXX_PORT_MAC_CTL_SPEED_10 0x0000
|
|
|
|
#define MV88E6XXX_PORT_MAC_CTL_SPEED_100 0x0001
|
|
|
|
#define MV88E6065_PORT_MAC_CTL_SPEED_200 0x0002
|
|
|
|
#define MV88E6XXX_PORT_MAC_CTL_SPEED_1000 0x0002
|
|
|
|
#define MV88E6390_PORT_MAC_CTL_SPEED_10000 0x0003
|
|
|
|
#define MV88E6XXX_PORT_MAC_CTL_SPEED_UNFORCED 0x0003
|
|
|
|
|
2017-06-12 09:37:35 -07:00
|
|
|
/* Offset 0x02: Jamming Control Register */
|
|
|
|
#define MV88E6097_PORT_JAM_CTL 0x02
|
|
|
|
#define MV88E6097_PORT_JAM_CTL_LIMIT_OUT_MASK 0xff00
|
|
|
|
#define MV88E6097_PORT_JAM_CTL_LIMIT_IN_MASK 0x00ff
|
|
|
|
|
|
|
|
/* Offset 0x02: Flow Control Register */
|
|
|
|
#define MV88E6390_PORT_FLOW_CTL 0x02
|
|
|
|
#define MV88E6390_PORT_FLOW_CTL_UPDATE 0x8000
|
|
|
|
#define MV88E6390_PORT_FLOW_CTL_PTR_MASK 0x7f00
|
|
|
|
#define MV88E6390_PORT_FLOW_CTL_LIMIT_IN 0x0000
|
|
|
|
#define MV88E6390_PORT_FLOW_CTL_LIMIT_OUT 0x0100
|
|
|
|
#define MV88E6390_PORT_FLOW_CTL_DATA_MASK 0x00ff
|
|
|
|
|
2017-06-12 09:37:36 -07:00
|
|
|
/* Offset 0x03: Switch Identifier Register */
|
|
|
|
#define MV88E6XXX_PORT_SWITCH_ID 0x03
|
|
|
|
#define MV88E6XXX_PORT_SWITCH_ID_PROD_MASK 0xfff0
|
2023-05-30 01:39:15 -07:00
|
|
|
#define MV88E6XXX_PORT_SWITCH_ID_PROD_6020 0x0200
|
2023-05-30 01:39:16 -07:00
|
|
|
#define MV88E6XXX_PORT_SWITCH_ID_PROD_6071 0x0710
|
2017-06-12 09:37:36 -07:00
|
|
|
#define MV88E6XXX_PORT_SWITCH_ID_PROD_6085 0x04a0
|
|
|
|
#define MV88E6XXX_PORT_SWITCH_ID_PROD_6095 0x0950
|
|
|
|
#define MV88E6XXX_PORT_SWITCH_ID_PROD_6097 0x0990
|
|
|
|
#define MV88E6XXX_PORT_SWITCH_ID_PROD_6190X 0x0a00
|
|
|
|
#define MV88E6XXX_PORT_SWITCH_ID_PROD_6390X 0x0a10
|
|
|
|
#define MV88E6XXX_PORT_SWITCH_ID_PROD_6131 0x1060
|
|
|
|
#define MV88E6XXX_PORT_SWITCH_ID_PROD_6320 0x1150
|
|
|
|
#define MV88E6XXX_PORT_SWITCH_ID_PROD_6123 0x1210
|
|
|
|
#define MV88E6XXX_PORT_SWITCH_ID_PROD_6161 0x1610
|
|
|
|
#define MV88E6XXX_PORT_SWITCH_ID_PROD_6165 0x1650
|
|
|
|
#define MV88E6XXX_PORT_SWITCH_ID_PROD_6171 0x1710
|
|
|
|
#define MV88E6XXX_PORT_SWITCH_ID_PROD_6172 0x1720
|
|
|
|
#define MV88E6XXX_PORT_SWITCH_ID_PROD_6175 0x1750
|
|
|
|
#define MV88E6XXX_PORT_SWITCH_ID_PROD_6176 0x1760
|
|
|
|
#define MV88E6XXX_PORT_SWITCH_ID_PROD_6190 0x1900
|
|
|
|
#define MV88E6XXX_PORT_SWITCH_ID_PROD_6191 0x1910
|
2021-03-17 06:46:42 -07:00
|
|
|
#define MV88E6XXX_PORT_SWITCH_ID_PROD_6191X 0x1920
|
|
|
|
#define MV88E6XXX_PORT_SWITCH_ID_PROD_6193X 0x1930
|
2017-06-12 09:37:36 -07:00
|
|
|
#define MV88E6XXX_PORT_SWITCH_ID_PROD_6185 0x1a70
|
2019-07-31 01:23:46 -07:00
|
|
|
#define MV88E6XXX_PORT_SWITCH_ID_PROD_6220 0x2200
|
2017-06-12 09:37:36 -07:00
|
|
|
#define MV88E6XXX_PORT_SWITCH_ID_PROD_6240 0x2400
|
net: dsa: mv88e6xxx: add support for mv88e6250
This adds support for the Marvell 88E6250. I've checked that each
member in the ops-structure makes sense, and basic switchdev
functionality works fine.
It uses the new dual_chip option, and since its port registers start
at SMI address 0x08 or 0x18 (i.e., always sw_addr + 0x08), we need to
introduce a new compatible string in order for the auto-identification
in mv88e6xxx_detect() to work.
The chip has four per port 16-bits statistics registers, two of which
correspond to the existing "sw_in_filtered" and "sw_out_filtered" (but
at offsets 0x13 and 0x10 rather than 0x12 and 0x13, because why should
this be easy...). Wiring up those four statistics seems to require
introducing a STATS_TYPE_PORT_6250 bit or similar, which seems a tad
ugly, so for now this just allows access to the STATS_TYPE_BANK0 ones.
The chip does have ptp support, and the existing
mv88e6352_{gpio,avb,ptp}_ops at first glance seem like they would work
out-of-the-box, but for simplicity (and lack of testing) I'm eliding
this.
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: Rasmus Villemoes <rasmus.villemoes@prevas.dk>
Signed-off-by: David S. Miller <davem@davemloft.net>
2019-06-04 00:34:32 -07:00
|
|
|
#define MV88E6XXX_PORT_SWITCH_ID_PROD_6250 0x2500
|
2023-05-29 01:02:46 -07:00
|
|
|
#define MV88E6XXX_PORT_SWITCH_ID_PROD_6361 0x2610
|
2017-06-12 09:37:36 -07:00
|
|
|
#define MV88E6XXX_PORT_SWITCH_ID_PROD_6290 0x2900
|
|
|
|
#define MV88E6XXX_PORT_SWITCH_ID_PROD_6321 0x3100
|
|
|
|
#define MV88E6XXX_PORT_SWITCH_ID_PROD_6141 0x3400
|
|
|
|
#define MV88E6XXX_PORT_SWITCH_ID_PROD_6341 0x3410
|
|
|
|
#define MV88E6XXX_PORT_SWITCH_ID_PROD_6352 0x3520
|
|
|
|
#define MV88E6XXX_PORT_SWITCH_ID_PROD_6350 0x3710
|
|
|
|
#define MV88E6XXX_PORT_SWITCH_ID_PROD_6351 0x3750
|
|
|
|
#define MV88E6XXX_PORT_SWITCH_ID_PROD_6390 0x3900
|
2021-03-17 06:46:42 -07:00
|
|
|
#define MV88E6XXX_PORT_SWITCH_ID_PROD_6393X 0x3930
|
2017-06-12 09:37:36 -07:00
|
|
|
#define MV88E6XXX_PORT_SWITCH_ID_REV_MASK 0x000f
|
|
|
|
|
2017-06-12 09:37:37 -07:00
|
|
|
/* Offset 0x04: Port Control Register */
|
|
|
|
#define MV88E6XXX_PORT_CTL0 0x04
|
|
|
|
#define MV88E6XXX_PORT_CTL0_USE_CORE_TAG 0x8000
|
2022-02-23 03:16:49 -07:00
|
|
|
#define MV88E6XXX_PORT_CTL0_SA_FILT_MASK 0xc000
|
|
|
|
#define MV88E6XXX_PORT_CTL0_SA_FILT_DISABLED 0x0000
|
|
|
|
#define MV88E6XXX_PORT_CTL0_SA_FILT_DROP_ON_LOCK 0x4000
|
|
|
|
#define MV88E6XXX_PORT_CTL0_SA_FILT_DROP_ON_UNLOCK 0x8000
|
|
|
|
#define MV88E6XXX_PORT_CTL0_SA_FILT_DROP_ON_CPU 0xc000
|
2017-06-12 09:37:37 -07:00
|
|
|
#define MV88E6XXX_PORT_CTL0_EGRESS_MODE_MASK 0x3000
|
|
|
|
#define MV88E6XXX_PORT_CTL0_EGRESS_MODE_UNMODIFIED 0x0000
|
|
|
|
#define MV88E6XXX_PORT_CTL0_EGRESS_MODE_UNTAGGED 0x1000
|
|
|
|
#define MV88E6XXX_PORT_CTL0_EGRESS_MODE_TAGGED 0x2000
|
|
|
|
#define MV88E6XXX_PORT_CTL0_EGRESS_MODE_ETHER_TYPE_DSA 0x3000
|
|
|
|
#define MV88E6XXX_PORT_CTL0_HEADER 0x0800
|
|
|
|
#define MV88E6XXX_PORT_CTL0_IGMP_MLD_SNOOP 0x0400
|
|
|
|
#define MV88E6XXX_PORT_CTL0_DOUBLE_TAG 0x0200
|
|
|
|
#define MV88E6XXX_PORT_CTL0_FRAME_MODE_MASK 0x0300
|
|
|
|
#define MV88E6XXX_PORT_CTL0_FRAME_MODE_NORMAL 0x0000
|
|
|
|
#define MV88E6XXX_PORT_CTL0_FRAME_MODE_DSA 0x0100
|
|
|
|
#define MV88E6XXX_PORT_CTL0_FRAME_MODE_PROVIDER 0x0200
|
|
|
|
#define MV88E6XXX_PORT_CTL0_FRAME_MODE_ETHER_TYPE_DSA 0x0300
|
|
|
|
#define MV88E6XXX_PORT_CTL0_DSA_TAG 0x0100
|
|
|
|
#define MV88E6XXX_PORT_CTL0_VLAN_TUNNEL 0x0080
|
|
|
|
#define MV88E6XXX_PORT_CTL0_TAG_IF_BOTH 0x0040
|
|
|
|
#define MV88E6185_PORT_CTL0_USE_IP 0x0020
|
|
|
|
#define MV88E6185_PORT_CTL0_USE_TAG 0x0010
|
|
|
|
#define MV88E6185_PORT_CTL0_FORWARD_UNKNOWN 0x0004
|
net: dsa: act as passthrough for bridge port flags
There are multiple ways in which a PORT_BRIDGE_FLAGS attribute can be
expressed by the bridge through switchdev, and not all of them can be
emulated by DSA mid-layer API at the same time.
One possible configuration is when the bridge offloads the port flags
using a mask that has a single bit set - therefore only one feature
should change. However, DSA currently groups together unicast and
multicast flooding in the .port_egress_floods method, which limits our
options when we try to add support for turning off broadcast flooding:
do we extend .port_egress_floods with a third parameter which b53 and
mv88e6xxx will ignore? But that means that the DSA layer, which
currently implements the PRE_BRIDGE_FLAGS attribute all by itself, will
see that .port_egress_floods is implemented, and will report that all 3
types of flooding are supported - not necessarily true.
Another configuration is when the user specifies more than one flag at
the same time, in the same netlink message. If we were to create one
individual function per offloadable bridge port flag, we would limit the
expressiveness of the switch driver of refusing certain combinations of
flag values. For example, a switch may not have an explicit knob for
flooding of unknown multicast, just for flooding in general. In that
case, the only correct thing to do is to allow changes to BR_FLOOD and
BR_MCAST_FLOOD in tandem, and never allow mismatched values. But having
a separate .port_set_unicast_flood and .port_set_multicast_flood would
not allow the driver to possibly reject that.
Also, DSA doesn't consider it necessary to inform the driver that a
SWITCHDEV_ATTR_ID_BRIDGE_MROUTER attribute was offloaded, because it
just calls .port_egress_floods for the CPU port. When we'll add support
for the plain SWITCHDEV_ATTR_ID_PORT_MROUTER, that will become a real
problem because the flood settings will need to be held statefully in
the DSA middle layer, otherwise changing the mrouter port attribute will
impact the flooding attribute. And that's _assuming_ that the underlying
hardware doesn't have anything else to do when a multicast router
attaches to a port than flood unknown traffic to it. If it does, there
will need to be a dedicated .port_set_mrouter anyway.
So we need to let the DSA drivers see the exact form that the bridge
passes this switchdev attribute in, otherwise we are standing in the
way. Therefore we also need to use this form of language when
communicating to the driver that it needs to configure its initial
(before bridge join) and final (after bridge leave) port flags.
The b53 and mv88e6xxx drivers are converted to the passthrough API and
their implementation of .port_egress_floods is split into two: a
function that configures unicast flooding and another for multicast.
The mv88e6xxx implementation is quite hairy, and it turns out that
the implementations of unknown unicast flooding are actually the same
for 6185 and for 6352:
behind the confusing names actually lie two individual bits:
NO_UNKNOWN_MC -> FLOOD_UC = 0x4 = BIT(2)
NO_UNKNOWN_UC -> FLOOD_MC = 0x8 = BIT(3)
so there was no reason to entangle them in the first place.
Whereas the 6185 writes to MV88E6185_PORT_CTL0_FORWARD_UNKNOWN of
PORT_CTL0, which has the exact same bit index. I have left the
implementations separate though, for the only reason that the names are
different enough to confuse me, since I am not able to double-check with
a user manual. The multicast flooding setting for 6185 is in a different
register than for 6352 though.
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2021-02-12 08:15:56 -07:00
|
|
|
#define MV88E6352_PORT_CTL0_EGRESS_FLOODS_UC 0x0004
|
|
|
|
#define MV88E6352_PORT_CTL0_EGRESS_FLOODS_MC 0x0008
|
2017-06-12 09:37:37 -07:00
|
|
|
#define MV88E6XXX_PORT_CTL0_STATE_MASK 0x0003
|
|
|
|
#define MV88E6XXX_PORT_CTL0_STATE_DISABLED 0x0000
|
|
|
|
#define MV88E6XXX_PORT_CTL0_STATE_BLOCKING 0x0001
|
|
|
|
#define MV88E6XXX_PORT_CTL0_STATE_LEARNING 0x0002
|
|
|
|
#define MV88E6XXX_PORT_CTL0_STATE_FORWARDING 0x0003
|
|
|
|
|
2017-06-12 09:37:38 -07:00
|
|
|
/* Offset 0x05: Port Control 1 */
|
|
|
|
#define MV88E6XXX_PORT_CTL1 0x05
|
|
|
|
#define MV88E6XXX_PORT_CTL1_MESSAGE_PORT 0x8000
|
2021-01-13 01:42:54 -07:00
|
|
|
#define MV88E6XXX_PORT_CTL1_TRUNK_PORT 0x4000
|
|
|
|
#define MV88E6XXX_PORT_CTL1_TRUNK_ID_MASK 0x0f00
|
|
|
|
#define MV88E6XXX_PORT_CTL1_TRUNK_ID_SHIFT 8
|
2017-06-12 09:37:38 -07:00
|
|
|
#define MV88E6XXX_PORT_CTL1_FID_11_4_MASK 0x00ff
|
|
|
|
|
2017-06-12 09:37:39 -07:00
|
|
|
/* Offset 0x06: Port Based VLAN Map */
|
|
|
|
#define MV88E6XXX_PORT_BASE_VLAN 0x06
|
|
|
|
#define MV88E6XXX_PORT_BASE_VLAN_FID_3_0_MASK 0xf000
|
|
|
|
|
2017-06-12 09:37:40 -07:00
|
|
|
/* Offset 0x07: Default Port VLAN ID & Priority */
|
|
|
|
#define MV88E6XXX_PORT_DEFAULT_VLAN 0x07
|
|
|
|
#define MV88E6XXX_PORT_DEFAULT_VLAN_MASK 0x0fff
|
|
|
|
|
2017-06-12 09:37:41 -07:00
|
|
|
/* Offset 0x08: Port Control 2 Register */
|
|
|
|
#define MV88E6XXX_PORT_CTL2 0x08
|
|
|
|
#define MV88E6XXX_PORT_CTL2_IGNORE_FCS 0x8000
|
|
|
|
#define MV88E6XXX_PORT_CTL2_VTU_PRI_OVERRIDE 0x4000
|
|
|
|
#define MV88E6XXX_PORT_CTL2_SA_PRIO_OVERRIDE 0x2000
|
|
|
|
#define MV88E6XXX_PORT_CTL2_DA_PRIO_OVERRIDE 0x1000
|
|
|
|
#define MV88E6XXX_PORT_CTL2_JUMBO_MODE_MASK 0x3000
|
|
|
|
#define MV88E6XXX_PORT_CTL2_JUMBO_MODE_1522 0x0000
|
|
|
|
#define MV88E6XXX_PORT_CTL2_JUMBO_MODE_2048 0x1000
|
|
|
|
#define MV88E6XXX_PORT_CTL2_JUMBO_MODE_10240 0x2000
|
|
|
|
#define MV88E6XXX_PORT_CTL2_8021Q_MODE_MASK 0x0c00
|
|
|
|
#define MV88E6XXX_PORT_CTL2_8021Q_MODE_DISABLED 0x0000
|
|
|
|
#define MV88E6XXX_PORT_CTL2_8021Q_MODE_FALLBACK 0x0400
|
|
|
|
#define MV88E6XXX_PORT_CTL2_8021Q_MODE_CHECK 0x0800
|
|
|
|
#define MV88E6XXX_PORT_CTL2_8021Q_MODE_SECURE 0x0c00
|
|
|
|
#define MV88E6XXX_PORT_CTL2_DISCARD_TAGGED 0x0200
|
|
|
|
#define MV88E6XXX_PORT_CTL2_DISCARD_UNTAGGED 0x0100
|
|
|
|
#define MV88E6XXX_PORT_CTL2_MAP_DA 0x0080
|
|
|
|
#define MV88E6XXX_PORT_CTL2_DEFAULT_FORWARD 0x0040
|
|
|
|
#define MV88E6XXX_PORT_CTL2_EGRESS_MONITOR 0x0020
|
|
|
|
#define MV88E6XXX_PORT_CTL2_INGRESS_MONITOR 0x0010
|
|
|
|
#define MV88E6095_PORT_CTL2_CPU_PORT_MASK 0x000f
|
|
|
|
|
2017-06-12 09:37:42 -07:00
|
|
|
/* Offset 0x09: Egress Rate Control */
|
|
|
|
#define MV88E6XXX_PORT_EGRESS_RATE_CTL1 0x09
|
|
|
|
|
|
|
|
/* Offset 0x0A: Egress Rate Control 2 */
|
|
|
|
#define MV88E6XXX_PORT_EGRESS_RATE_CTL2 0x0a
|
|
|
|
|
2017-06-12 09:37:43 -07:00
|
|
|
/* Offset 0x0B: Port Association Vector */
|
|
|
|
#define MV88E6XXX_PORT_ASSOC_VECTOR 0x0b
|
|
|
|
#define MV88E6XXX_PORT_ASSOC_VECTOR_HOLD_AT_1 0x8000
|
|
|
|
#define MV88E6XXX_PORT_ASSOC_VECTOR_INT_AGE_OUT 0x4000
|
|
|
|
#define MV88E6XXX_PORT_ASSOC_VECTOR_LOCKED_PORT 0x2000
|
|
|
|
#define MV88E6XXX_PORT_ASSOC_VECTOR_IGNORE_WRONG 0x1000
|
|
|
|
#define MV88E6XXX_PORT_ASSOC_VECTOR_REFRESH_LOCKED 0x0800
|
|
|
|
|
2017-06-12 09:37:45 -07:00
|
|
|
/* Offset 0x0C: Port ATU Control */
|
|
|
|
#define MV88E6XXX_PORT_ATU_CTL 0x0c
|
|
|
|
|
|
|
|
/* Offset 0x0D: Priority Override Register */
|
|
|
|
#define MV88E6XXX_PORT_PRI_OVERRIDE 0x0d
|
|
|
|
|
|
|
|
/* Offset 0x0E: Policy Control Register */
|
2019-09-07 13:00:48 -07:00
|
|
|
#define MV88E6XXX_PORT_POLICY_CTL 0x0e
|
|
|
|
#define MV88E6XXX_PORT_POLICY_CTL_DA_MASK 0xc000
|
|
|
|
#define MV88E6XXX_PORT_POLICY_CTL_SA_MASK 0x3000
|
|
|
|
#define MV88E6XXX_PORT_POLICY_CTL_VTU_MASK 0x0c00
|
|
|
|
#define MV88E6XXX_PORT_POLICY_CTL_ETYPE_MASK 0x0300
|
|
|
|
#define MV88E6XXX_PORT_POLICY_CTL_PPPOE_MASK 0x00c0
|
|
|
|
#define MV88E6XXX_PORT_POLICY_CTL_VBAS_MASK 0x0030
|
|
|
|
#define MV88E6XXX_PORT_POLICY_CTL_OPT82_MASK 0x000c
|
|
|
|
#define MV88E6XXX_PORT_POLICY_CTL_UDP_MASK 0x0003
|
|
|
|
#define MV88E6XXX_PORT_POLICY_CTL_NORMAL 0x0000
|
|
|
|
#define MV88E6XXX_PORT_POLICY_CTL_MIRROR 0x0001
|
|
|
|
#define MV88E6XXX_PORT_POLICY_CTL_TRAP 0x0002
|
|
|
|
#define MV88E6XXX_PORT_POLICY_CTL_DISCARD 0x0003
|
2017-06-12 09:37:45 -07:00
|
|
|
|
2021-03-17 06:46:42 -07:00
|
|
|
/* Offset 0x0E: Policy & MGMT Control Register (FAMILY_6393X) */
|
|
|
|
#define MV88E6393X_PORT_POLICY_MGMT_CTL 0x0e
|
|
|
|
#define MV88E6393X_PORT_POLICY_MGMT_CTL_UPDATE 0x8000
|
|
|
|
#define MV88E6393X_PORT_POLICY_MGMT_CTL_PTR_MASK 0x3f00
|
|
|
|
#define MV88E6393X_PORT_POLICY_MGMT_CTL_DATA_MASK 0x00ff
|
|
|
|
#define MV88E6393X_PORT_POLICY_MGMT_CTL_PTR_01C280000000XLO 0x2000
|
|
|
|
#define MV88E6393X_PORT_POLICY_MGMT_CTL_PTR_01C280000000XHI 0x2100
|
|
|
|
#define MV88E6393X_PORT_POLICY_MGMT_CTL_PTR_01C280000002XLO 0x2400
|
|
|
|
#define MV88E6393X_PORT_POLICY_MGMT_CTL_PTR_01C280000002XHI 0x2500
|
|
|
|
#define MV88E6393X_PORT_POLICY_MGMT_CTL_PTR_INGRESS_DEST 0x3000
|
|
|
|
#define MV88E6393X_PORT_POLICY_MGMT_CTL_PTR_CPU_DEST 0x3800
|
|
|
|
#define MV88E6393X_PORT_POLICY_MGMT_CTL_CPU_DEST_MGMTPRI 0x00e0
|
|
|
|
|
2017-06-12 09:37:45 -07:00
|
|
|
/* Offset 0x0F: Port Special Ether Type */
|
|
|
|
#define MV88E6XXX_PORT_ETH_TYPE 0x0f
|
|
|
|
#define MV88E6XXX_PORT_ETH_TYPE_DEFAULT 0x9100
|
|
|
|
|
|
|
|
/* Offset 0x10: InDiscards Low Counter */
|
|
|
|
#define MV88E6XXX_PORT_IN_DISCARD_LO 0x10
|
|
|
|
|
2021-03-17 06:46:42 -07:00
|
|
|
/* Offset 0x10: Extended Port Control Command */
|
|
|
|
#define MV88E6393X_PORT_EPC_CMD 0x10
|
|
|
|
#define MV88E6393X_PORT_EPC_CMD_BUSY 0x8000
|
2023-05-16 00:38:54 -07:00
|
|
|
#define MV88E6393X_PORT_EPC_CMD_WRITE 0x3000
|
2021-03-17 06:46:42 -07:00
|
|
|
#define MV88E6393X_PORT_EPC_INDEX_PORT_ETYPE 0x02
|
|
|
|
|
|
|
|
/* Offset 0x11: Extended Port Control Data */
|
|
|
|
#define MV88E6393X_PORT_EPC_DATA 0x11
|
|
|
|
|
2017-06-12 09:37:45 -07:00
|
|
|
/* Offset 0x11: InDiscards High Counter */
|
|
|
|
#define MV88E6XXX_PORT_IN_DISCARD_HI 0x11
|
|
|
|
|
|
|
|
/* Offset 0x12: InFiltered Counter */
|
|
|
|
#define MV88E6XXX_PORT_IN_FILTERED 0x12
|
|
|
|
|
|
|
|
/* Offset 0x13: OutFiltered Counter */
|
|
|
|
#define MV88E6XXX_PORT_OUT_FILTERED 0x13
|
|
|
|
|
2017-06-12 09:37:44 -07:00
|
|
|
/* Offset 0x18: IEEE Priority Mapping Table */
|
|
|
|
#define MV88E6390_PORT_IEEE_PRIO_MAP_TABLE 0x18
|
|
|
|
#define MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_UPDATE 0x8000
|
2017-06-17 20:07:14 -07:00
|
|
|
#define MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_MASK 0x7000
|
2017-06-12 09:37:44 -07:00
|
|
|
#define MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_INGRESS_PCP 0x0000
|
|
|
|
#define MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_EGRESS_GREEN_PCP 0x1000
|
|
|
|
#define MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_EGRESS_YELLOW_PCP 0x2000
|
|
|
|
#define MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_EGRESS_AVB_PCP 0x3000
|
|
|
|
#define MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_EGRESS_GREEN_DSCP 0x5000
|
|
|
|
#define MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_EGRESS_YELLOW_DSCP 0x6000
|
|
|
|
#define MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_EGRESS_AVB_DSCP 0x7000
|
2017-06-17 20:07:14 -07:00
|
|
|
#define MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_PTR_MASK 0x0e00
|
|
|
|
#define MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_DATA_MASK 0x01ff
|
2017-06-12 09:37:44 -07:00
|
|
|
|
|
|
|
/* Offset 0x18: Port IEEE Priority Remapping Registers (0-3) */
|
|
|
|
#define MV88E6095_PORT_IEEE_PRIO_REMAP_0123 0x18
|
|
|
|
|
|
|
|
/* Offset 0x19: Port IEEE Priority Remapping Registers (4-7) */
|
|
|
|
#define MV88E6095_PORT_IEEE_PRIO_REMAP_4567 0x19
|
2017-06-02 14:06:17 -07:00
|
|
|
|
2019-01-08 16:24:03 -07:00
|
|
|
/* Offset 0x1a: Magic undocumented errata register */
|
2019-08-26 14:31:51 -07:00
|
|
|
#define MV88E6XXX_PORT_RESERVED_1A 0x1a
|
|
|
|
#define MV88E6XXX_PORT_RESERVED_1A_BUSY 0x8000
|
|
|
|
#define MV88E6XXX_PORT_RESERVED_1A_WRITE 0x4000
|
|
|
|
#define MV88E6XXX_PORT_RESERVED_1A_READ 0x0000
|
|
|
|
#define MV88E6XXX_PORT_RESERVED_1A_PORT_SHIFT 5
|
|
|
|
#define MV88E6XXX_PORT_RESERVED_1A_BLOCK_SHIFT 10
|
|
|
|
#define MV88E6XXX_PORT_RESERVED_1A_CTRL_PORT 0x04
|
|
|
|
#define MV88E6XXX_PORT_RESERVED_1A_DATA_PORT 0x05
|
2019-08-26 14:31:55 -07:00
|
|
|
#define MV88E6341_PORT_RESERVED_1A_FORCE_CMODE 0x8000
|
|
|
|
#define MV88E6341_PORT_RESERVED_1A_SGMII_AN 0x2000
|
2019-01-08 16:24:03 -07:00
|
|
|
|
2016-11-03 19:23:26 -07:00
|
|
|
int mv88e6xxx_port_read(struct mv88e6xxx_chip *chip, int port, int reg,
|
|
|
|
u16 *val);
|
|
|
|
int mv88e6xxx_port_write(struct mv88e6xxx_chip *chip, int port, int reg,
|
|
|
|
u16 val);
|
2021-03-17 06:46:42 -07:00
|
|
|
int mv88e6xxx_port_wait_bit(struct mv88e6xxx_chip *chip, int port, int reg,
|
|
|
|
int bit, int val);
|
2016-11-03 19:23:26 -07:00
|
|
|
|
2018-08-09 06:38:37 -07:00
|
|
|
int mv88e6185_port_set_pause(struct mv88e6xxx_chip *chip, int port,
|
|
|
|
int pause);
|
2022-10-28 09:31:58 -07:00
|
|
|
int mv88e6320_port_set_rgmii_delay(struct mv88e6xxx_chip *chip, int port,
|
|
|
|
phy_interface_t mode);
|
2016-11-03 19:23:34 -07:00
|
|
|
int mv88e6352_port_set_rgmii_delay(struct mv88e6xxx_chip *chip, int port,
|
|
|
|
phy_interface_t mode);
|
|
|
|
int mv88e6390_port_set_rgmii_delay(struct mv88e6xxx_chip *chip, int port,
|
|
|
|
phy_interface_t mode);
|
|
|
|
|
2016-11-03 19:23:32 -07:00
|
|
|
int mv88e6xxx_port_set_link(struct mv88e6xxx_chip *chip, int port, int link);
|
|
|
|
|
2020-11-23 21:34:37 -07:00
|
|
|
int mv88e6xxx_port_sync_link(struct mv88e6xxx_chip *chip, int port, unsigned int mode, bool isup);
|
|
|
|
int mv88e6185_port_sync_link(struct mv88e6xxx_chip *chip, int port, unsigned int mode, bool isup);
|
|
|
|
|
2020-03-14 03:15:53 -07:00
|
|
|
int mv88e6185_port_set_speed_duplex(struct mv88e6xxx_chip *chip, int port,
|
|
|
|
int speed, int duplex);
|
|
|
|
int mv88e6250_port_set_speed_duplex(struct mv88e6xxx_chip *chip, int port,
|
|
|
|
int speed, int duplex);
|
|
|
|
int mv88e6341_port_set_speed_duplex(struct mv88e6xxx_chip *chip, int port,
|
|
|
|
int speed, int duplex);
|
|
|
|
int mv88e6352_port_set_speed_duplex(struct mv88e6xxx_chip *chip, int port,
|
|
|
|
int speed, int duplex);
|
|
|
|
int mv88e6390_port_set_speed_duplex(struct mv88e6xxx_chip *chip, int port,
|
|
|
|
int speed, int duplex);
|
|
|
|
int mv88e6390x_port_set_speed_duplex(struct mv88e6xxx_chip *chip, int port,
|
|
|
|
int speed, int duplex);
|
2021-03-17 06:46:42 -07:00
|
|
|
int mv88e6393x_port_set_speed_duplex(struct mv88e6xxx_chip *chip, int port,
|
|
|
|
int speed, int duplex);
|
2016-11-03 19:23:35 -07:00
|
|
|
|
2023-05-29 01:02:45 -07:00
|
|
|
phy_interface_t mv88e6341_port_max_speed_mode(struct mv88e6xxx_chip *chip,
|
|
|
|
int port);
|
|
|
|
phy_interface_t mv88e6390_port_max_speed_mode(struct mv88e6xxx_chip *chip,
|
|
|
|
int port);
|
|
|
|
phy_interface_t mv88e6390x_port_max_speed_mode(struct mv88e6xxx_chip *chip,
|
|
|
|
int port);
|
|
|
|
phy_interface_t mv88e6393x_port_max_speed_mode(struct mv88e6xxx_chip *chip,
|
|
|
|
int port);
|
2019-03-07 17:21:27 -07:00
|
|
|
|
2016-11-03 19:23:27 -07:00
|
|
|
int mv88e6xxx_port_set_state(struct mv88e6xxx_chip *chip, int port, u8 state);
|
|
|
|
|
2016-11-03 19:23:28 -07:00
|
|
|
int mv88e6xxx_port_set_vlan_map(struct mv88e6xxx_chip *chip, int port, u16 map);
|
|
|
|
|
2016-11-03 19:23:29 -07:00
|
|
|
int mv88e6xxx_port_get_fid(struct mv88e6xxx_chip *chip, int port, u16 *fid);
|
|
|
|
int mv88e6xxx_port_set_fid(struct mv88e6xxx_chip *chip, int port, u16 fid);
|
|
|
|
|
2016-11-03 19:23:30 -07:00
|
|
|
int mv88e6xxx_port_get_pvid(struct mv88e6xxx_chip *chip, int port, u16 *pvid);
|
|
|
|
int mv88e6xxx_port_set_pvid(struct mv88e6xxx_chip *chip, int port, u16 pvid);
|
|
|
|
|
2022-02-23 03:16:49 -07:00
|
|
|
int mv88e6xxx_port_set_lock(struct mv88e6xxx_chip *chip, int port,
|
|
|
|
bool locked);
|
|
|
|
|
2016-11-03 19:23:31 -07:00
|
|
|
int mv88e6xxx_port_set_8021q_mode(struct mv88e6xxx_chip *chip, int port,
|
|
|
|
u16 mode);
|
2016-12-02 20:35:16 -07:00
|
|
|
int mv88e6095_port_tag_remap(struct mv88e6xxx_chip *chip, int port);
|
|
|
|
int mv88e6390_port_tag_remap(struct mv88e6xxx_chip *chip, int port);
|
2016-12-02 20:35:19 -07:00
|
|
|
int mv88e6xxx_port_set_egress_mode(struct mv88e6xxx_chip *chip, int port,
|
2017-06-08 15:34:09 -07:00
|
|
|
enum mv88e6xxx_egress_mode mode);
|
2016-12-02 20:35:19 -07:00
|
|
|
int mv88e6085_port_set_frame_mode(struct mv88e6xxx_chip *chip, int port,
|
|
|
|
enum mv88e6xxx_frame_mode mode);
|
|
|
|
int mv88e6351_port_set_frame_mode(struct mv88e6xxx_chip *chip, int port,
|
|
|
|
enum mv88e6xxx_frame_mode mode);
|
net: dsa: act as passthrough for bridge port flags
There are multiple ways in which a PORT_BRIDGE_FLAGS attribute can be
expressed by the bridge through switchdev, and not all of them can be
emulated by DSA mid-layer API at the same time.
One possible configuration is when the bridge offloads the port flags
using a mask that has a single bit set - therefore only one feature
should change. However, DSA currently groups together unicast and
multicast flooding in the .port_egress_floods method, which limits our
options when we try to add support for turning off broadcast flooding:
do we extend .port_egress_floods with a third parameter which b53 and
mv88e6xxx will ignore? But that means that the DSA layer, which
currently implements the PRE_BRIDGE_FLAGS attribute all by itself, will
see that .port_egress_floods is implemented, and will report that all 3
types of flooding are supported - not necessarily true.
Another configuration is when the user specifies more than one flag at
the same time, in the same netlink message. If we were to create one
individual function per offloadable bridge port flag, we would limit the
expressiveness of the switch driver of refusing certain combinations of
flag values. For example, a switch may not have an explicit knob for
flooding of unknown multicast, just for flooding in general. In that
case, the only correct thing to do is to allow changes to BR_FLOOD and
BR_MCAST_FLOOD in tandem, and never allow mismatched values. But having
a separate .port_set_unicast_flood and .port_set_multicast_flood would
not allow the driver to possibly reject that.
Also, DSA doesn't consider it necessary to inform the driver that a
SWITCHDEV_ATTR_ID_BRIDGE_MROUTER attribute was offloaded, because it
just calls .port_egress_floods for the CPU port. When we'll add support
for the plain SWITCHDEV_ATTR_ID_PORT_MROUTER, that will become a real
problem because the flood settings will need to be held statefully in
the DSA middle layer, otherwise changing the mrouter port attribute will
impact the flooding attribute. And that's _assuming_ that the underlying
hardware doesn't have anything else to do when a multicast router
attaches to a port than flood unknown traffic to it. If it does, there
will need to be a dedicated .port_set_mrouter anyway.
So we need to let the DSA drivers see the exact form that the bridge
passes this switchdev attribute in, otherwise we are standing in the
way. Therefore we also need to use this form of language when
communicating to the driver that it needs to configure its initial
(before bridge join) and final (after bridge leave) port flags.
The b53 and mv88e6xxx drivers are converted to the passthrough API and
their implementation of .port_egress_floods is split into two: a
function that configures unicast flooding and another for multicast.
The mv88e6xxx implementation is quite hairy, and it turns out that
the implementations of unknown unicast flooding are actually the same
for 6185 and for 6352:
behind the confusing names actually lie two individual bits:
NO_UNKNOWN_MC -> FLOOD_UC = 0x4 = BIT(2)
NO_UNKNOWN_UC -> FLOOD_MC = 0x8 = BIT(3)
so there was no reason to entangle them in the first place.
Whereas the 6185 writes to MV88E6185_PORT_CTL0_FORWARD_UNKNOWN of
PORT_CTL0, which has the exact same bit index. I have left the
implementations separate though, for the only reason that the names are
different enough to confuse me, since I am not able to double-check with
a user manual. The multicast flooding setting for 6185 is in a different
register than for 6352 though.
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2021-02-12 08:15:56 -07:00
|
|
|
int mv88e6185_port_set_forward_unknown(struct mv88e6xxx_chip *chip,
|
|
|
|
int port, bool unicast);
|
|
|
|
int mv88e6185_port_set_default_forward(struct mv88e6xxx_chip *chip,
|
|
|
|
int port, bool multicast);
|
|
|
|
int mv88e6352_port_set_ucast_flood(struct mv88e6xxx_chip *chip, int port,
|
|
|
|
bool unicast);
|
|
|
|
int mv88e6352_port_set_mcast_flood(struct mv88e6xxx_chip *chip, int port,
|
|
|
|
bool multicast);
|
2019-09-07 13:00:48 -07:00
|
|
|
int mv88e6352_port_set_policy(struct mv88e6xxx_chip *chip, int port,
|
|
|
|
enum mv88e6xxx_policy_mapping mapping,
|
|
|
|
enum mv88e6xxx_policy_action action);
|
2021-03-17 06:46:43 -07:00
|
|
|
int mv88e6393x_port_set_policy(struct mv88e6xxx_chip *chip, int port,
|
|
|
|
enum mv88e6xxx_policy_mapping mapping,
|
|
|
|
enum mv88e6xxx_policy_action action);
|
2016-12-02 20:35:19 -07:00
|
|
|
int mv88e6351_port_set_ether_type(struct mv88e6xxx_chip *chip, int port,
|
|
|
|
u16 etype);
|
2021-03-17 06:46:42 -07:00
|
|
|
int mv88e6393x_set_egress_port(struct mv88e6xxx_chip *chip,
|
|
|
|
enum mv88e6xxx_egress_direction direction,
|
|
|
|
int port);
|
|
|
|
int mv88e6393x_port_set_upstream_port(struct mv88e6xxx_chip *chip, int port,
|
|
|
|
int upstream_port);
|
|
|
|
int mv88e6393x_port_mgmt_rsvd2cpu(struct mv88e6xxx_chip *chip);
|
|
|
|
int mv88e6393x_port_set_ether_type(struct mv88e6xxx_chip *chip, int port,
|
|
|
|
u16 etype);
|
2017-03-11 14:12:50 -07:00
|
|
|
int mv88e6xxx_port_set_message_port(struct mv88e6xxx_chip *chip, int port,
|
|
|
|
bool message_port);
|
2021-01-13 01:42:54 -07:00
|
|
|
int mv88e6xxx_port_set_trunk(struct mv88e6xxx_chip *chip, int port,
|
|
|
|
bool trunk, u8 id);
|
2017-06-08 15:34:13 -07:00
|
|
|
int mv88e6165_port_set_jumbo_size(struct mv88e6xxx_chip *chip, int port,
|
|
|
|
size_t size);
|
2016-12-02 20:45:18 -07:00
|
|
|
int mv88e6095_port_egress_rate_limiting(struct mv88e6xxx_chip *chip, int port);
|
|
|
|
int mv88e6097_port_egress_rate_limiting(struct mv88e6xxx_chip *chip, int port);
|
2021-03-18 12:25:39 -07:00
|
|
|
int mv88e6xxx_port_set_assoc_vector(struct mv88e6xxx_chip *chip, int port,
|
|
|
|
u16 pav);
|
2017-06-08 15:34:12 -07:00
|
|
|
int mv88e6097_port_pause_limit(struct mv88e6xxx_chip *chip, int port, u8 in,
|
|
|
|
u8 out);
|
|
|
|
int mv88e6390_port_pause_limit(struct mv88e6xxx_chip *chip, int port, u8 in,
|
|
|
|
u8 out);
|
2019-08-26 14:31:55 -07:00
|
|
|
int mv88e6341_port_set_cmode(struct mv88e6xxx_chip *chip, int port,
|
|
|
|
phy_interface_t mode);
|
2018-11-10 16:32:15 -07:00
|
|
|
int mv88e6390_port_set_cmode(struct mv88e6xxx_chip *chip, int port,
|
|
|
|
phy_interface_t mode);
|
net: dsa: mv88e6xxx: Set the CMODE for mv88e6390 ports 9 & 10
Unlike most ports, ports 9 and 10 of the 6390X family have configurable
PHY modes. Set the mode as part of adjust_link().
Ordering is important, because the SERDES interfaces connected to
ports 9 and 10 can be split and assigned to other ports. The CMODE has
to be correctly set before the SERDES interface on another port can be
configured. Such configuration is likely to be performed in
port_enable() and port_disabled(), called on slave_open() and
slave_close().
The simple case is port 9 and 10 are used for 'CPU' or 'DSA'. In this
case, the CMODE is set via a phy-mode in dsa_cpu_dsa_setup(), which is
called early in the switch setup.
When ports 9 or 10 are used as user ports, and have a fixed-phy, when
the fixed fixed-phy is attached, dsa_slave_adjust_link() is called,
which results in the adjust_link function being called, setting the
cmode. The port_enable() will for other ports will be called much
later.
When ports 9 or 10 are used as user ports and have a real phy attached
which does not use all the available SERDES interface, e.g. a 1Gbps
SGMII, there is currently no mechanism in place to set the CMODE of
the port from software. It must be hoped the stripping resistors are
correct.
At the same time, add a function to get the cmode. This will be needed
when configuring the SERDES interfaces.
Signed-off-by: Andrew Lunn <andrew@lunn.ch>
Reviewed-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2017-02-04 12:02:50 -07:00
|
|
|
int mv88e6390x_port_set_cmode(struct mv88e6xxx_chip *chip, int port,
|
2021-03-17 06:46:42 -07:00
|
|
|
phy_interface_t mode);
|
|
|
|
int mv88e6393x_port_set_cmode(struct mv88e6xxx_chip *chip, int port,
|
net: dsa: mv88e6xxx: Set the CMODE for mv88e6390 ports 9 & 10
Unlike most ports, ports 9 and 10 of the 6390X family have configurable
PHY modes. Set the mode as part of adjust_link().
Ordering is important, because the SERDES interfaces connected to
ports 9 and 10 can be split and assigned to other ports. The CMODE has
to be correctly set before the SERDES interface on another port can be
configured. Such configuration is likely to be performed in
port_enable() and port_disabled(), called on slave_open() and
slave_close().
The simple case is port 9 and 10 are used for 'CPU' or 'DSA'. In this
case, the CMODE is set via a phy-mode in dsa_cpu_dsa_setup(), which is
called early in the switch setup.
When ports 9 or 10 are used as user ports, and have a fixed-phy, when
the fixed fixed-phy is attached, dsa_slave_adjust_link() is called,
which results in the adjust_link function being called, setting the
cmode. The port_enable() will for other ports will be called much
later.
When ports 9 or 10 are used as user ports and have a real phy attached
which does not use all the available SERDES interface, e.g. a 1Gbps
SGMII, there is currently no mechanism in place to set the CMODE of
the port from software. It must be hoped the stripping resistors are
correct.
At the same time, add a function to get the cmode. This will be needed
when configuring the SERDES interfaces.
Signed-off-by: Andrew Lunn <andrew@lunn.ch>
Reviewed-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2017-02-04 12:02:50 -07:00
|
|
|
phy_interface_t mode);
|
2018-08-09 06:38:45 -07:00
|
|
|
int mv88e6185_port_get_cmode(struct mv88e6xxx_chip *chip, int port, u8 *cmode);
|
|
|
|
int mv88e6352_port_get_cmode(struct mv88e6xxx_chip *chip, int port, u8 *cmode);
|
net: dsa: mv88e6xxx: keep the pvid at 0 when VLAN-unaware
The VLAN support in mv88e6xxx has a loaded history. Commit 2ea7a679ca2a
("net: dsa: Don't add vlans when vlan filtering is disabled") noticed
some issues with VLAN and decided the best way to deal with them was to
make the DSA core ignore VLANs added by the bridge while VLAN awareness
is turned off. Those issues were never explained, just presented as
"at least one corner case".
That approach had problems of its own, presented by
commit 54a0ed0df496 ("net: dsa: provide an option for drivers to always
receive bridge VLANs") for the DSA core, followed by
commit 1fb74191988f ("net: dsa: mv88e6xxx: fix vlan setup") which
applied ds->configure_vlan_while_not_filtering = true for mv88e6xxx in
particular.
We still don't know what corner case Andrew saw when he wrote
commit 2ea7a679ca2a ("net: dsa: Don't add vlans when vlan filtering is
disabled"), but Tobias now reports that when we use TX forwarding
offload, pinging an external station from the bridge device is broken if
the front-facing DSA user port has flooding turned off. The full
description is in the link below, but for short, when a mv88e6xxx port
is under a VLAN-unaware bridge, it inherits that bridge's pvid.
So packets ingressing a user port will be classified to e.g. VID 1
(assuming that value for the bridge_default_pvid), whereas when
tag_dsa.c xmits towards a user port, it always sends packets using a VID
of 0 if that port is standalone or under a VLAN-unaware bridge - or at
least it did so prior to commit d82f8ab0d874 ("net: dsa: tag_dsa:
offload the bridge forwarding process").
In any case, when there is a conversation between the CPU and a station
connected to a user port, the station's MAC address is learned in VID 1
but the CPU tries to transmit through VID 0. The packets reach the
intended station, but via flooding and not by virtue of matching the
existing ATU entry.
DSA has established (and enforced in other drivers: sja1105, felix,
mt7530) that a VLAN-unaware port should use a private pvid, and not
inherit the one from the bridge. The bridge's pvid should only be
inherited when that bridge is VLAN-aware, so all state transitions need
to be handled. On the other hand, all bridge VLANs should sit in the VTU
starting with the moment when the bridge offloads them via switchdev,
they are just not used.
This solves the problem that Tobias sees because packets ingressing on
VLAN-unaware user ports now get classified to VID 0, which is also the
VID used by tag_dsa.c on xmit.
Fixes: d82f8ab0d874 ("net: dsa: tag_dsa: offload the bridge forwarding process")
Link: https://patchwork.kernel.org/project/netdevbpf/patch/20211003222312.284175-2-vladimir.oltean@nxp.com/#24491503
Reported-by: Tobias Waldekranz <tobias@waldekranz.com>
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2021-10-07 09:47:10 -07:00
|
|
|
int mv88e6xxx_port_drop_untagged(struct mv88e6xxx_chip *chip, int port,
|
|
|
|
bool drop_untagged);
|
2022-02-03 03:16:53 -07:00
|
|
|
int mv88e6xxx_port_set_map_da(struct mv88e6xxx_chip *chip, int port, bool map);
|
2017-02-04 12:15:28 -07:00
|
|
|
int mv88e6095_port_set_upstream_port(struct mv88e6xxx_chip *chip, int port,
|
|
|
|
int upstream_port);
|
2019-11-07 14:11:14 -07:00
|
|
|
int mv88e6xxx_port_set_mirror(struct mv88e6xxx_chip *chip, int port,
|
|
|
|
enum mv88e6xxx_egress_direction direction,
|
|
|
|
bool mirror);
|
2017-03-11 14:13:01 -07:00
|
|
|
|
|
|
|
int mv88e6xxx_port_disable_learn_limit(struct mv88e6xxx_chip *chip, int port);
|
2017-03-11 14:13:02 -07:00
|
|
|
int mv88e6xxx_port_disable_pri_override(struct mv88e6xxx_chip *chip, int port);
|
2017-03-11 14:13:01 -07:00
|
|
|
|
2019-08-26 14:31:51 -07:00
|
|
|
int mv88e6xxx_port_hidden_write(struct mv88e6xxx_chip *chip, int block,
|
|
|
|
int port, int reg, u16 val);
|
|
|
|
int mv88e6xxx_port_hidden_wait(struct mv88e6xxx_chip *chip);
|
|
|
|
int mv88e6xxx_port_hidden_read(struct mv88e6xxx_chip *chip, int block, int port,
|
|
|
|
int reg, u16 *val);
|
|
|
|
|
2016-11-03 19:23:26 -07:00
|
|
|
#endif /* _MV88E6XXX_PORT_H */
|