mirror of
https://github.com/tbsdtv/linux_media.git
synced 2025-07-23 12:43:29 +02:00
net: switchdev: pass flags and mask to both {PRE_,}BRIDGE_FLAGS attributes
This switchdev attribute offers a counterproductive API for a driver writer, because although br_switchdev_set_port_flag gets passed a "flags" and a "mask", those are passed piecemeal to the driver, so while the PRE_BRIDGE_FLAGS listener knows what changed because it has the "mask", the BRIDGE_FLAGS listener doesn't, because it only has the final value. But certain drivers can offload only certain combinations of settings, like for example they cannot change unicast flooding independently of multicast flooding - they must be both on or both off. The way the information is passed to switchdev makes drivers not expressive enough, and unable to reject this request ahead of time, in the PRE_BRIDGE_FLAGS notifier, so they are forced to reject it during the deferred BRIDGE_FLAGS attribute, where the rejection is currently ignored. This patch also changes drivers to make use of the "mask" field for edge detection when possible. Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com> Reviewed-by: Grygorii Strashko <grygorii.strashko@ti.com> Reviewed-by: Florian Fainelli <f.fainelli@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
committed by
David S. Miller
parent
5e38c15856
commit
e18f4c18ab
@@ -183,8 +183,10 @@ int dsa_port_mdb_add(const struct dsa_port *dp,
|
||||
const struct switchdev_obj_port_mdb *mdb);
|
||||
int dsa_port_mdb_del(const struct dsa_port *dp,
|
||||
const struct switchdev_obj_port_mdb *mdb);
|
||||
int dsa_port_pre_bridge_flags(const struct dsa_port *dp, unsigned long flags);
|
||||
int dsa_port_bridge_flags(const struct dsa_port *dp, unsigned long flags);
|
||||
int dsa_port_pre_bridge_flags(const struct dsa_port *dp,
|
||||
struct switchdev_brport_flags flags);
|
||||
int dsa_port_bridge_flags(const struct dsa_port *dp,
|
||||
struct switchdev_brport_flags flags);
|
||||
int dsa_port_mrouter(struct dsa_port *dp, bool mrouter);
|
||||
int dsa_port_vlan_add(struct dsa_port *dp,
|
||||
const struct switchdev_obj_port_vlan *vlan);
|
||||
|
@@ -125,21 +125,22 @@ void dsa_port_disable(struct dsa_port *dp)
|
||||
static void dsa_port_change_brport_flags(struct dsa_port *dp,
|
||||
bool bridge_offload)
|
||||
{
|
||||
unsigned long mask, flags;
|
||||
int flag, err;
|
||||
struct switchdev_brport_flags flags;
|
||||
int flag;
|
||||
|
||||
mask = BR_LEARNING | BR_FLOOD | BR_MCAST_FLOOD | BR_BCAST_FLOOD;
|
||||
flags.mask = BR_LEARNING | BR_FLOOD | BR_MCAST_FLOOD | BR_BCAST_FLOOD;
|
||||
if (bridge_offload)
|
||||
flags = mask;
|
||||
flags.val = flags.mask;
|
||||
else
|
||||
flags = mask & ~BR_LEARNING;
|
||||
flags.val = flags.mask & ~BR_LEARNING;
|
||||
|
||||
for_each_set_bit(flag, &mask, 32) {
|
||||
err = dsa_port_pre_bridge_flags(dp, BIT(flag));
|
||||
if (err)
|
||||
continue;
|
||||
for_each_set_bit(flag, &flags.mask, 32) {
|
||||
struct switchdev_brport_flags tmp;
|
||||
|
||||
dsa_port_bridge_flags(dp, flags & BIT(flag));
|
||||
tmp.val = flags.val & BIT(flag);
|
||||
tmp.mask = BIT(flag);
|
||||
|
||||
dsa_port_bridge_flags(dp, tmp);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -423,26 +424,29 @@ int dsa_port_ageing_time(struct dsa_port *dp, clock_t ageing_clock)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dsa_port_pre_bridge_flags(const struct dsa_port *dp, unsigned long flags)
|
||||
int dsa_port_pre_bridge_flags(const struct dsa_port *dp,
|
||||
struct switchdev_brport_flags flags)
|
||||
{
|
||||
struct dsa_switch *ds = dp->ds;
|
||||
|
||||
if (!ds->ops->port_egress_floods ||
|
||||
(flags & ~(BR_FLOOD | BR_MCAST_FLOOD)))
|
||||
(flags.mask & ~(BR_FLOOD | BR_MCAST_FLOOD)))
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dsa_port_bridge_flags(const struct dsa_port *dp, unsigned long flags)
|
||||
int dsa_port_bridge_flags(const struct dsa_port *dp,
|
||||
struct switchdev_brport_flags flags)
|
||||
{
|
||||
struct dsa_switch *ds = dp->ds;
|
||||
int port = dp->index;
|
||||
int err = 0;
|
||||
|
||||
if (ds->ops->port_egress_floods)
|
||||
err = ds->ops->port_egress_floods(ds, port, flags & BR_FLOOD,
|
||||
flags & BR_MCAST_FLOOD);
|
||||
err = ds->ops->port_egress_floods(ds, port,
|
||||
flags.val & BR_FLOOD,
|
||||
flags.val & BR_MCAST_FLOOD);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
Reference in New Issue
Block a user