Commit 601aeed3 authored by Vivien Didelot's avatar Vivien Didelot Committed by David S. Miller

net: dsa: mv88e6xxx: fix port egress flooding mode

The Marvell switch ports can be configured to allow or prevent egress of
frames with an unknown unicast or multicast destination address.

Some switch chips such as 88E6095 and 88E6185 have two disjoint bits in
Port Control Register (0x04) bit 2 "Forward Unknown" (for unicast) and
Port Control 2 Register (0x08) bit 6 "Default Forward" (for multicast).

Other chips such as 88E6085, 88E6123, 88E6352, and 88E6390 have a 2-bit
value in Port Control Register (0x04) bits 3:2 "EgressFloods".

The current code does not fully implement the disjoint bits variant and
assigns incorrect ones to some chip models. Fix that with two
implementation references (6185 and 6352 that I currently have) of a
port_set_egress_floods operation (as named in datasheets).

Old chips such as 88E6060 don't have egress flooding mode, so don't
error out if the operation is not provided.
Signed-off-by: default avatarVivien Didelot <vivien.didelot@savoirfairelinux.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 4314557c
This diff is collapsed.
...@@ -132,12 +132,12 @@ ...@@ -132,12 +132,12 @@
#define PORT_CONTROL_TAG_IF_BOTH BIT(6) #define PORT_CONTROL_TAG_IF_BOTH BIT(6)
#define PORT_CONTROL_USE_IP BIT(5) #define PORT_CONTROL_USE_IP BIT(5)
#define PORT_CONTROL_USE_TAG BIT(4) #define PORT_CONTROL_USE_TAG BIT(4)
#define PORT_CONTROL_FORWARD_UNKNOWN_MC BIT(3)
#define PORT_CONTROL_FORWARD_UNKNOWN BIT(2) #define PORT_CONTROL_FORWARD_UNKNOWN BIT(2)
#define PORT_CONTROL_NOT_EGRESS_UNKNOWN_DA (0x0 << 2) #define PORT_CONTROL_EGRESS_FLOODS_MASK (0x3 << 2)
#define PORT_CONTROL_NOT_EGRESS_UNKNOWN_MULTICAST_DA (0x1 << 2) #define PORT_CONTROL_EGRESS_FLOODS_NO_UNKNOWN_DA (0x0 << 2)
#define PORT_CONTROL_NOT_EGRESS_UNKNOWN_UNITCAST_DA (0x2 << 2) #define PORT_CONTROL_EGRESS_FLOODS_NO_UNKNOWN_MC_DA (0x1 << 2)
#define PORT_CONTROL_EGRESS_ALL_UNKNOWN_DA (0x3 << 2) #define PORT_CONTROL_EGRESS_FLOODS_NO_UNKNOWN_UC_DA (0x2 << 2)
#define PORT_CONTROL_EGRESS_FLOODS_ALL_UNKNOWN_DA (0x3 << 2)
#define PORT_CONTROL_STATE_MASK 0x03 #define PORT_CONTROL_STATE_MASK 0x03
#define PORT_CONTROL_STATE_DISABLED 0x00 #define PORT_CONTROL_STATE_DISABLED 0x00
#define PORT_CONTROL_STATE_BLOCKING 0x01 #define PORT_CONTROL_STATE_BLOCKING 0x01
...@@ -167,7 +167,6 @@ ...@@ -167,7 +167,6 @@
#define PORT_CONTROL_2_DISCARD_UNTAGGED BIT(8) #define PORT_CONTROL_2_DISCARD_UNTAGGED BIT(8)
#define PORT_CONTROL_2_MAP_DA BIT(7) #define PORT_CONTROL_2_MAP_DA BIT(7)
#define PORT_CONTROL_2_DEFAULT_FORWARD BIT(6) #define PORT_CONTROL_2_DEFAULT_FORWARD BIT(6)
#define PORT_CONTROL_2_FORWARD_UNKNOWN BIT(6)
#define PORT_CONTROL_2_EGRESS_MONITOR BIT(5) #define PORT_CONTROL_2_EGRESS_MONITOR BIT(5)
#define PORT_CONTROL_2_INGRESS_MONITOR BIT(4) #define PORT_CONTROL_2_INGRESS_MONITOR BIT(4)
#define PORT_CONTROL_2_UPSTREAM_MASK 0x0f #define PORT_CONTROL_2_UPSTREAM_MASK 0x0f
...@@ -864,8 +863,8 @@ struct mv88e6xxx_ops { ...@@ -864,8 +863,8 @@ struct mv88e6xxx_ops {
int (*port_set_frame_mode)(struct mv88e6xxx_chip *chip, int port, int (*port_set_frame_mode)(struct mv88e6xxx_chip *chip, int port,
enum mv88e6xxx_frame_mode mode); enum mv88e6xxx_frame_mode mode);
int (*port_set_egress_unknowns)(struct mv88e6xxx_chip *chip, int port, int (*port_set_egress_floods)(struct mv88e6xxx_chip *chip, int port,
bool on); bool unicast, bool multicast);
int (*port_set_ether_type)(struct mv88e6xxx_chip *chip, int port, int (*port_set_ether_type)(struct mv88e6xxx_chip *chip, int port,
u16 etype); u16 etype);
int (*port_jumbo_config)(struct mv88e6xxx_chip *chip, int port); int (*port_jumbo_config)(struct mv88e6xxx_chip *chip, int port);
......
...@@ -497,8 +497,8 @@ int mv88e6351_port_set_frame_mode(struct mv88e6xxx_chip *chip, int port, ...@@ -497,8 +497,8 @@ int mv88e6351_port_set_frame_mode(struct mv88e6xxx_chip *chip, int port,
return mv88e6xxx_port_write(chip, port, PORT_CONTROL, reg); return mv88e6xxx_port_write(chip, port, PORT_CONTROL, reg);
} }
int mv88e6085_port_set_egress_unknowns(struct mv88e6xxx_chip *chip, int port, static int mv88e6185_port_set_forward_unknown(struct mv88e6xxx_chip *chip,
bool on) int port, bool unicast)
{ {
int err; int err;
u16 reg; u16 reg;
...@@ -507,7 +507,7 @@ int mv88e6085_port_set_egress_unknowns(struct mv88e6xxx_chip *chip, int port, ...@@ -507,7 +507,7 @@ int mv88e6085_port_set_egress_unknowns(struct mv88e6xxx_chip *chip, int port,
if (err) if (err)
return err; return err;
if (on) if (unicast)
reg |= PORT_CONTROL_FORWARD_UNKNOWN; reg |= PORT_CONTROL_FORWARD_UNKNOWN;
else else
reg &= ~PORT_CONTROL_FORWARD_UNKNOWN; reg &= ~PORT_CONTROL_FORWARD_UNKNOWN;
...@@ -515,8 +515,8 @@ int mv88e6085_port_set_egress_unknowns(struct mv88e6xxx_chip *chip, int port, ...@@ -515,8 +515,8 @@ int mv88e6085_port_set_egress_unknowns(struct mv88e6xxx_chip *chip, int port,
return mv88e6xxx_port_write(chip, port, PORT_CONTROL, reg); return mv88e6xxx_port_write(chip, port, PORT_CONTROL, reg);
} }
int mv88e6351_port_set_egress_unknowns(struct mv88e6xxx_chip *chip, int port, int mv88e6352_port_set_egress_floods(struct mv88e6xxx_chip *chip, int port,
bool on) bool unicast, bool multicast)
{ {
int err; int err;
u16 reg; u16 reg;
...@@ -525,10 +525,16 @@ int mv88e6351_port_set_egress_unknowns(struct mv88e6xxx_chip *chip, int port, ...@@ -525,10 +525,16 @@ int mv88e6351_port_set_egress_unknowns(struct mv88e6xxx_chip *chip, int port,
if (err) if (err)
return err; return err;
if (on) reg &= ~PORT_CONTROL_EGRESS_FLOODS_MASK;
reg |= PORT_CONTROL_EGRESS_ALL_UNKNOWN_DA;
if (unicast && multicast)
reg |= PORT_CONTROL_EGRESS_FLOODS_ALL_UNKNOWN_DA;
else if (unicast)
reg |= PORT_CONTROL_EGRESS_FLOODS_NO_UNKNOWN_MC_DA;
else if (multicast)
reg |= PORT_CONTROL_EGRESS_FLOODS_NO_UNKNOWN_UC_DA;
else else
reg &= ~PORT_CONTROL_EGRESS_ALL_UNKNOWN_DA; reg |= PORT_CONTROL_EGRESS_FLOODS_NO_UNKNOWN_DA;
return mv88e6xxx_port_write(chip, port, PORT_CONTROL, reg); return mv88e6xxx_port_write(chip, port, PORT_CONTROL, reg);
} }
...@@ -690,8 +696,8 @@ static const char * const mv88e6xxx_port_8021q_mode_names[] = { ...@@ -690,8 +696,8 @@ static const char * const mv88e6xxx_port_8021q_mode_names[] = {
[PORT_CONTROL_2_8021Q_SECURE] = "Secure", [PORT_CONTROL_2_8021Q_SECURE] = "Secure",
}; };
int mv88e6095_port_set_egress_unknowns(struct mv88e6xxx_chip *chip, int port, static int mv88e6185_port_set_default_forward(struct mv88e6xxx_chip *chip,
bool on) int port, bool multicast)
{ {
int err; int err;
u16 reg; u16 reg;
...@@ -700,14 +706,26 @@ int mv88e6095_port_set_egress_unknowns(struct mv88e6xxx_chip *chip, int port, ...@@ -700,14 +706,26 @@ int mv88e6095_port_set_egress_unknowns(struct mv88e6xxx_chip *chip, int port,
if (err) if (err)
return err; return err;
if (on) if (multicast)
reg |= PORT_CONTROL_2_FORWARD_UNKNOWN; reg |= PORT_CONTROL_2_DEFAULT_FORWARD;
else else
reg &= ~PORT_CONTROL_2_FORWARD_UNKNOWN; reg &= ~PORT_CONTROL_2_DEFAULT_FORWARD;
return mv88e6xxx_port_write(chip, port, PORT_CONTROL_2, reg); return mv88e6xxx_port_write(chip, port, PORT_CONTROL_2, reg);
} }
int mv88e6185_port_set_egress_floods(struct mv88e6xxx_chip *chip, int port,
bool unicast, bool multicast)
{
int err;
err = mv88e6185_port_set_forward_unknown(chip, port, unicast);
if (err)
return err;
return mv88e6185_port_set_default_forward(chip, port, multicast);
}
int mv88e6095_port_set_upstream_port(struct mv88e6xxx_chip *chip, int port, int mv88e6095_port_set_upstream_port(struct mv88e6xxx_chip *chip, int port,
int upstream_port) int upstream_port)
{ {
......
...@@ -56,12 +56,10 @@ int mv88e6085_port_set_frame_mode(struct mv88e6xxx_chip *chip, int port, ...@@ -56,12 +56,10 @@ int mv88e6085_port_set_frame_mode(struct mv88e6xxx_chip *chip, int port,
enum mv88e6xxx_frame_mode mode); enum mv88e6xxx_frame_mode mode);
int mv88e6351_port_set_frame_mode(struct mv88e6xxx_chip *chip, int port, int mv88e6351_port_set_frame_mode(struct mv88e6xxx_chip *chip, int port,
enum mv88e6xxx_frame_mode mode); enum mv88e6xxx_frame_mode mode);
int mv88e6085_port_set_egress_unknowns(struct mv88e6xxx_chip *chip, int port, int mv88e6185_port_set_egress_floods(struct mv88e6xxx_chip *chip, int port,
bool on); bool unicast, bool multicast);
int mv88e6095_port_set_egress_unknowns(struct mv88e6xxx_chip *chip, int port, int mv88e6352_port_set_egress_floods(struct mv88e6xxx_chip *chip, int port,
bool on); bool unicast, bool multicast);
int mv88e6351_port_set_egress_unknowns(struct mv88e6xxx_chip *chip, int port,
bool on);
int mv88e6351_port_set_ether_type(struct mv88e6xxx_chip *chip, int port, int mv88e6351_port_set_ether_type(struct mv88e6xxx_chip *chip, int port,
u16 etype); u16 etype);
int mv88e6xxx_port_set_message_port(struct mv88e6xxx_chip *chip, int port, int mv88e6xxx_port_set_message_port(struct mv88e6xxx_chip *chip, int port,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment