void dsa_port_link_unregister_of(struct dsa_port *dp);
int dsa_port_hsr_join(struct dsa_port *dp, struct net_device *hsr);
void dsa_port_hsr_leave(struct dsa_port *dp, struct net_device *hsr);
-int dsa_port_tag_8021q_vlan_add(struct dsa_port *dp, u16 vid);
-void dsa_port_tag_8021q_vlan_del(struct dsa_port *dp, u16 vid);
+int dsa_port_tag_8021q_vlan_add(struct dsa_port *dp, u16 vid, bool broadcast);
+void dsa_port_tag_8021q_vlan_del(struct dsa_port *dp, u16 vid, bool broadcast);
extern const struct phylink_mac_ops dsa_port_phylink_mac_ops;
static inline bool dsa_port_offloads_bridge_port(struct dsa_port *dp,
dp->index, ERR_PTR(err));
}
-int dsa_port_tag_8021q_vlan_add(struct dsa_port *dp, u16 vid)
+int dsa_port_tag_8021q_vlan_add(struct dsa_port *dp, u16 vid, bool broadcast)
{
struct dsa_notifier_tag_8021q_vlan_info info = {
.tree_index = dp->ds->dst->index,
.vid = vid,
};
- return dsa_broadcast(DSA_NOTIFIER_TAG_8021Q_VLAN_ADD, &info);
+ if (broadcast)
+ return dsa_broadcast(DSA_NOTIFIER_TAG_8021Q_VLAN_ADD, &info);
+
+ return dsa_port_notify(dp, DSA_NOTIFIER_TAG_8021Q_VLAN_ADD, &info);
}
-void dsa_port_tag_8021q_vlan_del(struct dsa_port *dp, u16 vid)
+void dsa_port_tag_8021q_vlan_del(struct dsa_port *dp, u16 vid, bool broadcast)
{
struct dsa_notifier_tag_8021q_vlan_info info = {
.tree_index = dp->ds->dst->index,
};
int err;
- err = dsa_broadcast(DSA_NOTIFIER_TAG_8021Q_VLAN_DEL, &info);
+ if (broadcast)
+ err = dsa_broadcast(DSA_NOTIFIER_TAG_8021Q_VLAN_DEL, &info);
+ else
+ err = dsa_port_notify(dp, DSA_NOTIFIER_TAG_8021Q_VLAN_DEL, &info);
if (err)
dev_err(dp->ds->dev,
"port %d failed to notify tag_8021q VLAN %d deletion: %pe\n",
continue;
/* Install the RX VID of the targeted port in our VLAN table */
- err = dsa_port_tag_8021q_vlan_add(dp, targeted_rx_vid);
+ err = dsa_port_tag_8021q_vlan_add(dp, targeted_rx_vid, false);
if (err)
return err;
/* Install our RX VID into the targeted port's VLAN table */
- err = dsa_port_tag_8021q_vlan_add(targeted_dp, rx_vid);
+ err = dsa_port_tag_8021q_vlan_add(targeted_dp, rx_vid, false);
if (err)
return err;
}
continue;
/* Remove the RX VID of the targeted port from our VLAN table */
- dsa_port_tag_8021q_vlan_del(dp, targeted_rx_vid);
+ dsa_port_tag_8021q_vlan_del(dp, targeted_rx_vid, true);
/* Remove our RX VID from the targeted port's VLAN table */
- dsa_port_tag_8021q_vlan_del(targeted_dp, rx_vid);
+ dsa_port_tag_8021q_vlan_del(targeted_dp, rx_vid, true);
}
return 0;
{
u16 tx_vid = dsa_8021q_bridge_tx_fwd_offload_vid(bridge_num);
- return dsa_port_tag_8021q_vlan_add(dsa_to_port(ds, port), tx_vid);
+ return dsa_port_tag_8021q_vlan_add(dsa_to_port(ds, port), tx_vid,
+ true);
}
EXPORT_SYMBOL_GPL(dsa_tag_8021q_bridge_tx_fwd_offload);
{
u16 tx_vid = dsa_8021q_bridge_tx_fwd_offload_vid(bridge_num);
- dsa_port_tag_8021q_vlan_del(dsa_to_port(ds, port), tx_vid);
+ dsa_port_tag_8021q_vlan_del(dsa_to_port(ds, port), tx_vid, true);
}
EXPORT_SYMBOL_GPL(dsa_tag_8021q_bridge_tx_fwd_unoffload);
* L2 forwarding rules still take precedence when there are no VLAN
* restrictions, so there are no concerns about leaking traffic.
*/
- err = dsa_port_tag_8021q_vlan_add(dp, rx_vid);
+ err = dsa_port_tag_8021q_vlan_add(dp, rx_vid, true);
if (err) {
dev_err(ds->dev,
"Failed to apply RX VID %d to port %d: %pe\n",
vlan_vid_add(master, ctx->proto, rx_vid);
/* Finally apply the TX VID on this port and on the CPU port */
- err = dsa_port_tag_8021q_vlan_add(dp, tx_vid);
+ err = dsa_port_tag_8021q_vlan_add(dp, tx_vid, true);
if (err) {
dev_err(ds->dev,
"Failed to apply TX VID %d on port %d: %pe\n",
master = dp->cpu_dp->master;
- dsa_port_tag_8021q_vlan_del(dp, rx_vid);
+ dsa_port_tag_8021q_vlan_del(dp, rx_vid, false);
vlan_vid_del(master, ctx->proto, rx_vid);
- dsa_port_tag_8021q_vlan_del(dp, tx_vid);
+ dsa_port_tag_8021q_vlan_del(dp, tx_vid, false);
}
static int dsa_tag_8021q_setup(struct dsa_switch *ds)