Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 22 additions & 3 deletions drivers/net/dsa/mxl862xx/mxl862xx-api.h
Original file line number Diff line number Diff line change
Expand Up @@ -2131,6 +2131,26 @@ enum mxl862xx_pce_action_cross_state {
MXL862XX_PCE_ACTION_CROSS_STATE_CROSS = 2,
};

/**
* enum mxl862xx_pce_action_learning - MAC learning action selector
*
* Controls source address learning for packets matching the rule.
*
* @MXL862XX_PCE_ACTION_LEARNING_DISABLE: Learning action is disabled
* @MXL862XX_PCE_ACTION_LEARNING_REGULAR: Enabled; learning follows the
* regular port and bridge configuration
* @MXL862XX_PCE_ACTION_LEARNING_FORCE_NOT: Enabled; the source address
* of matching packets is never learned
* @MXL862XX_PCE_ACTION_LEARNING_FORCE: Enabled; the source address of
* matching packets is always learned
*/
enum mxl862xx_pce_action_learning {
MXL862XX_PCE_ACTION_LEARNING_DISABLE = 0,
MXL862XX_PCE_ACTION_LEARNING_REGULAR = 1,
MXL862XX_PCE_ACTION_LEARNING_FORCE_NOT = 2,
MXL862XX_PCE_ACTION_LEARNING_FORCE = 3,
};

/**
* struct mxl862xx_pce_action - PCE rule action configuration
*
Expand Down Expand Up @@ -2161,9 +2181,8 @@ enum mxl862xx_pce_action_cross_state {
* @traffic_class_action: Traffic class action selector
* (0 = disable, 1 = regular CoS, 2 = alternative)
* @snooping_type_action: IGMP snooping control selector
* @learning_action: MAC learning action selector
* (0 = disable, 1 = regular, 2 = force no learn,
* 3 = force learn)
* @learning_action: MAC learning action selector.
* See &enum mxl862xx_pce_action_learning
* @irq_action: Interrupt action selector
* (0 = disable, 1 = regular, 2 = generate interrupt)
* @cross_state_action: Cross state action selector.
Expand Down
45 changes: 34 additions & 11 deletions drivers/net/dsa/mxl862xx/mxl862xx.c
Original file line number Diff line number Diff line change
Expand Up @@ -721,6 +721,9 @@ static void mxl862xx_fill_cpu_trap_action(struct dsa_switch *ds, int port,
rule->action.cross_state_action =
cpu_to_le32(MXL862XX_PCE_ACTION_CROSS_STATE_CROSS);

rule->action.learning_action =
cpu_to_le32(MXL862XX_PCE_ACTION_LEARNING_FORCE_NOT);

rule->action.fid_enable = 1;
rule->action.fid = priv->cpu_trap_fid;
}
Expand Down Expand Up @@ -1491,6 +1494,12 @@ static int mxl862xx_configure_sp_tag_proto(struct dsa_switch *ds, int port,
* Per-port host flood control is implemented via egress sub-meters on
* the VBP.
*
* The bridge port map is written on every update rather than only at
* allocation time. It contains just the user port the VBP belongs to,
* and it is the path by which a CPU-originated frame reassigned onto
* the VBP reaches the wire, so it must never be left to the firmware
* to preserve across an unrelated field update.
*
* This is intentionally separate from mxl862xx_set_bridge_port() because
* the VBP and the physical bridge port are independent firmware entities:
* host flood changes (deferred from atomic context) only need the VBP
Expand All @@ -1510,8 +1519,10 @@ static int mxl862xx_set_cpu_vbp(struct dsa_switch *ds, int port)
vbp_cfg.bridge_port_id = cpu_to_le16(p->bridge_port_cpu);
vbp_cfg.mask = cpu_to_le32(
MXL862XX_BRIDGE_PORT_CONFIG_MASK_BRIDGE_ID |
MXL862XX_BRIDGE_PORT_CONFIG_MASK_BRIDGE_PORT_MAP |
MXL862XX_BRIDGE_PORT_CONFIG_MASK_EGRESS_SUB_METER);
vbp_cfg.bridge_id = cpu_to_le16(p->fid);
mxl862xx_fw_portmap_set_bit(vbp_cfg.bridge_port_map, port);

for (i = 0; i < ARRAY_SIZE(mxl862xx_flood_meters); i++) {
idx = mxl862xx_flood_meters[i];
Expand Down Expand Up @@ -2361,15 +2372,24 @@ static int mxl862xx_mac_portmap_del(struct mxl862xx_priv *priv,
* @ds: DSA switch
* @addr: MAC address
* @vid: VLAN ID
* @bridge: bridge whose members' VBPs to include
* @bridge: bridge the entry is scoped to (used to pick the FID)
*
* In tag_8021q mode, host FDB/MDB entries in a shared bridge FID must use
* portmap mode targeting ALL bridge members' virtual bridge ports (VBPs).
* The firmware ANDs the entry's portmap with each ingress port's
* bridge_port_map, which contains only that port's own VBP. This
* selects the correct VBP per ingress port, ensuring frames exit
* through the right egress EVLAN (which inserts the per-port management
* VID that identifies the source port to DSA on the CPU side).
* portmap mode targeting virtual bridge ports (VBPs). The firmware ANDs
* the entry's portmap with the ingress port's bridge_port_map, which
* contains only that port's own VBP, so listing every user port's VBP
* unconditionally still leaves exactly the ingress port's VBP after the
* intersection. That selects the correct egress EVLAN, which inserts the
* per-port management VID identifying the source port to DSA on the CPU
* side.
*
* Listing all user ports rather than the current bridge members keeps the
* entry correct without tracking membership changes, and avoids depending
* on every member's VBP having been allocated by the time the entry is
* installed. A port whose VBP is not yet allocated reads back as 0, and
* mxl862xx_fw_portmap_set_bit() would then set bit 0 -- a valid portmap
* bit belonging to another port, not a no-op -- corrupting the portmap of
* an entry the host depends on. Skip unallocated VBPs explicitly.
*/
static int mxl862xx_mac_add_host_bridge(struct dsa_switch *ds,
const unsigned char *addr, u16 vid,
Expand All @@ -2378,11 +2398,14 @@ static int mxl862xx_mac_add_host_bridge(struct dsa_switch *ds,
__le16 add_map[MXL862XX_FW_PORTMAP_WORDS] = {};
struct mxl862xx_priv *priv = ds->priv;
u16 fid = priv->bridges[bridge->num];
struct dsa_port *member_dp;
struct dsa_port *dp;
u16 vbp;

dsa_switch_for_each_bridge_member(member_dp, ds, bridge->dev)
mxl862xx_fw_portmap_set_bit(add_map,
priv->ports[member_dp->index].bridge_port_cpu);
dsa_switch_for_each_user_port(dp, ds) {
vbp = priv->ports[dp->index].bridge_port_cpu;
if (vbp)
mxl862xx_fw_portmap_set_bit(add_map, vbp);
}

return mxl862xx_mac_portmap_add(priv, addr, fid, vid, add_map);
}
Expand Down