mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-02 10:59:18 -04:00
net: marvell: prestera: rework bridge flags setting
Separate flags to make it possible to alter them separately; Move bridge flags setting logic from HW API level to prestera_main where it belongs; Move bridge flags parsing (and setting using prestera API) to prestera_switchdev.c - module responsible for bridge operations handling; Signed-off-by: Oleksandr Mazur <oleksandr.mazur@plvision.eu> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
committed by
David S. Miller
parent
b09ab9c92e
commit
116f5af7c3
@@ -331,6 +331,10 @@ struct prestera_port *prestera_port_dev_lower_find(struct net_device *dev);
|
||||
|
||||
void prestera_queue_work(struct work_struct *work);
|
||||
|
||||
int prestera_port_learning_set(struct prestera_port *port, bool learn_enable);
|
||||
int prestera_port_uc_flood_set(struct prestera_port *port, bool flood);
|
||||
int prestera_port_mc_flood_set(struct prestera_port *port, bool flood);
|
||||
|
||||
int prestera_port_pvid_set(struct prestera_port *port, u16 vid);
|
||||
|
||||
bool prestera_netdev_check(const struct net_device *dev);
|
||||
|
||||
@@ -1531,7 +1531,7 @@ int prestera_hw_port_learning_set(struct prestera_port *port, bool enable)
|
||||
&req.cmd, sizeof(req));
|
||||
}
|
||||
|
||||
static int prestera_hw_port_uc_flood_set(struct prestera_port *port, bool flood)
|
||||
int prestera_hw_port_uc_flood_set(const struct prestera_port *port, bool flood)
|
||||
{
|
||||
struct prestera_msg_port_attr_req req = {
|
||||
.attr = __cpu_to_le32(PRESTERA_CMD_PORT_ATTR_FLOOD),
|
||||
@@ -1549,7 +1549,7 @@ static int prestera_hw_port_uc_flood_set(struct prestera_port *port, bool flood)
|
||||
&req.cmd, sizeof(req));
|
||||
}
|
||||
|
||||
static int prestera_hw_port_mc_flood_set(struct prestera_port *port, bool flood)
|
||||
int prestera_hw_port_mc_flood_set(const struct prestera_port *port, bool flood)
|
||||
{
|
||||
struct prestera_msg_port_attr_req req = {
|
||||
.attr = __cpu_to_le32(PRESTERA_CMD_PORT_ATTR_FLOOD),
|
||||
@@ -1567,56 +1567,6 @@ static int prestera_hw_port_mc_flood_set(struct prestera_port *port, bool flood)
|
||||
&req.cmd, sizeof(req));
|
||||
}
|
||||
|
||||
static int prestera_hw_port_flood_set_v2(struct prestera_port *port, bool flood)
|
||||
{
|
||||
struct prestera_msg_port_attr_req req = {
|
||||
.attr = __cpu_to_le32(PRESTERA_CMD_PORT_ATTR_FLOOD),
|
||||
.port = __cpu_to_le32(port->hw_id),
|
||||
.dev = __cpu_to_le32(port->dev_id),
|
||||
.param = {
|
||||
.flood = flood,
|
||||
}
|
||||
};
|
||||
|
||||
return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
|
||||
&req.cmd, sizeof(req));
|
||||
}
|
||||
|
||||
int prestera_hw_port_flood_set(struct prestera_port *port, unsigned long mask,
|
||||
unsigned long val)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (port->sw->dev->fw_rev.maj <= 2) {
|
||||
if (!(mask & BR_FLOOD))
|
||||
return 0;
|
||||
|
||||
return prestera_hw_port_flood_set_v2(port, val & BR_FLOOD);
|
||||
}
|
||||
|
||||
if (mask & BR_FLOOD) {
|
||||
err = prestera_hw_port_uc_flood_set(port, val & BR_FLOOD);
|
||||
if (err)
|
||||
goto err_uc_flood;
|
||||
}
|
||||
|
||||
if (mask & BR_MCAST_FLOOD) {
|
||||
err = prestera_hw_port_mc_flood_set(port, val & BR_MCAST_FLOOD);
|
||||
if (err)
|
||||
goto err_mc_flood;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_mc_flood:
|
||||
prestera_hw_port_mc_flood_set(port, 0);
|
||||
err_uc_flood:
|
||||
if (mask & BR_FLOOD)
|
||||
prestera_hw_port_uc_flood_set(port, 0);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
int prestera_hw_vlan_create(struct prestera_switch *sw, u16 vid)
|
||||
{
|
||||
struct prestera_msg_vlan_req req = {
|
||||
|
||||
@@ -179,8 +179,8 @@ int prestera_hw_port_stats_get(const struct prestera_port *port,
|
||||
struct prestera_port_stats *stats);
|
||||
int prestera_hw_port_speed_get(const struct prestera_port *port, u32 *speed);
|
||||
int prestera_hw_port_learning_set(struct prestera_port *port, bool enable);
|
||||
int prestera_hw_port_flood_set(struct prestera_port *port, unsigned long mask,
|
||||
unsigned long val);
|
||||
int prestera_hw_port_uc_flood_set(const struct prestera_port *port, bool flood);
|
||||
int prestera_hw_port_mc_flood_set(const struct prestera_port *port, bool flood);
|
||||
int prestera_hw_port_accept_frm_type(struct prestera_port *port,
|
||||
enum prestera_accept_frm_type type);
|
||||
/* Vlan API */
|
||||
|
||||
@@ -35,6 +35,21 @@ void prestera_queue_work(struct work_struct *work)
|
||||
queue_work(prestera_owq, work);
|
||||
}
|
||||
|
||||
int prestera_port_learning_set(struct prestera_port *port, bool learn)
|
||||
{
|
||||
return prestera_hw_port_learning_set(port, learn);
|
||||
}
|
||||
|
||||
int prestera_port_uc_flood_set(struct prestera_port *port, bool flood)
|
||||
{
|
||||
return prestera_hw_port_uc_flood_set(port, flood);
|
||||
}
|
||||
|
||||
int prestera_port_mc_flood_set(struct prestera_port *port, bool flood)
|
||||
{
|
||||
return prestera_hw_port_mc_flood_set(port, flood);
|
||||
}
|
||||
|
||||
int prestera_port_pvid_set(struct prestera_port *port, u16 vid)
|
||||
{
|
||||
enum prestera_accept_frm_type frm_type;
|
||||
|
||||
@@ -74,6 +74,39 @@ static void prestera_bridge_port_put(struct prestera_bridge_port *br_port);
|
||||
static int prestera_port_vid_stp_set(struct prestera_port *port, u16 vid,
|
||||
u8 state);
|
||||
|
||||
static void
|
||||
prestera_br_port_flags_reset(struct prestera_bridge_port *br_port,
|
||||
struct prestera_port *port)
|
||||
{
|
||||
prestera_port_uc_flood_set(port, false);
|
||||
prestera_port_mc_flood_set(port, false);
|
||||
prestera_port_learning_set(port, false);
|
||||
}
|
||||
|
||||
static int prestera_br_port_flags_set(struct prestera_bridge_port *br_port,
|
||||
struct prestera_port *port)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = prestera_port_uc_flood_set(port, br_port->flags & BR_FLOOD);
|
||||
if (err)
|
||||
goto err_out;
|
||||
|
||||
err = prestera_port_mc_flood_set(port, br_port->flags & BR_MCAST_FLOOD);
|
||||
if (err)
|
||||
goto err_out;
|
||||
|
||||
err = prestera_port_learning_set(port, br_port->flags & BR_LEARNING);
|
||||
if (err)
|
||||
goto err_out;
|
||||
|
||||
return 0;
|
||||
|
||||
err_out:
|
||||
prestera_br_port_flags_reset(br_port, port);
|
||||
return err;
|
||||
}
|
||||
|
||||
static struct prestera_bridge_vlan *
|
||||
prestera_bridge_vlan_create(struct prestera_bridge_port *br_port, u16 vid)
|
||||
{
|
||||
@@ -461,19 +494,13 @@ prestera_bridge_1d_port_join(struct prestera_bridge_port *br_port)
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = prestera_hw_port_flood_set(port, BR_FLOOD | BR_MCAST_FLOOD,
|
||||
br_port->flags);
|
||||
err = prestera_br_port_flags_set(br_port, port);
|
||||
if (err)
|
||||
goto err_port_flood_set;
|
||||
|
||||
err = prestera_hw_port_learning_set(port, br_port->flags & BR_LEARNING);
|
||||
if (err)
|
||||
goto err_port_learning_set;
|
||||
goto err_flags2port_set;
|
||||
|
||||
return 0;
|
||||
|
||||
err_port_learning_set:
|
||||
err_port_flood_set:
|
||||
err_flags2port_set:
|
||||
prestera_hw_bridge_port_delete(port, bridge->bridge_id);
|
||||
|
||||
return err;
|
||||
@@ -592,8 +619,7 @@ void prestera_bridge_port_leave(struct net_device *br_dev,
|
||||
|
||||
switchdev_bridge_port_unoffload(br_port->dev, NULL, NULL, NULL);
|
||||
|
||||
prestera_hw_port_learning_set(port, false);
|
||||
prestera_hw_port_flood_set(port, BR_FLOOD | BR_MCAST_FLOOD, 0);
|
||||
prestera_br_port_flags_reset(br_port, port);
|
||||
prestera_port_vid_stp_set(port, PRESTERA_VID_ALL, BR_STATE_FORWARDING);
|
||||
prestera_bridge_port_put(br_port);
|
||||
}
|
||||
@@ -603,26 +629,14 @@ static int prestera_port_attr_br_flags_set(struct prestera_port *port,
|
||||
struct switchdev_brport_flags flags)
|
||||
{
|
||||
struct prestera_bridge_port *br_port;
|
||||
int err;
|
||||
|
||||
br_port = prestera_bridge_port_by_dev(port->sw->swdev, dev);
|
||||
if (!br_port)
|
||||
return 0;
|
||||
|
||||
err = prestera_hw_port_flood_set(port, flags.mask, flags.val);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (flags.mask & BR_LEARNING) {
|
||||
err = prestera_hw_port_learning_set(port,
|
||||
flags.val & BR_LEARNING);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
memcpy(&br_port->flags, &flags.val, sizeof(flags.val));
|
||||
|
||||
return 0;
|
||||
br_port->flags &= ~flags.mask;
|
||||
br_port->flags |= flags.val & flags.mask;
|
||||
return prestera_br_port_flags_set(br_port, port);
|
||||
}
|
||||
|
||||
static int prestera_port_attr_br_ageing_set(struct prestera_port *port,
|
||||
@@ -918,14 +932,9 @@ prestera_port_vlan_bridge_join(struct prestera_port_vlan *port_vlan,
|
||||
if (port_vlan->br_port)
|
||||
return 0;
|
||||
|
||||
err = prestera_hw_port_flood_set(port, BR_FLOOD | BR_MCAST_FLOOD,
|
||||
br_port->flags);
|
||||
err = prestera_br_port_flags_set(br_port, port);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = prestera_hw_port_learning_set(port, br_port->flags & BR_LEARNING);
|
||||
if (err)
|
||||
goto err_port_learning_set;
|
||||
goto err_flags2port_set;
|
||||
|
||||
err = prestera_port_vid_stp_set(port, vid, br_port->stp_state);
|
||||
if (err)
|
||||
@@ -950,8 +959,8 @@ prestera_port_vlan_bridge_join(struct prestera_port_vlan *port_vlan,
|
||||
err_bridge_vlan_get:
|
||||
prestera_port_vid_stp_set(port, vid, BR_STATE_FORWARDING);
|
||||
err_port_vid_stp_set:
|
||||
prestera_hw_port_learning_set(port, false);
|
||||
err_port_learning_set:
|
||||
prestera_br_port_flags_reset(br_port, port);
|
||||
err_flags2port_set:
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user