Commit 116f5af7 authored by Oleksandr Mazur's avatar Oleksandr Mazur Committed by David S. Miller

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: default avatarOleksandr Mazur <oleksandr.mazur@plvision.eu>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent b09ab9c9
...@@ -331,6 +331,10 @@ struct prestera_port *prestera_port_dev_lower_find(struct net_device *dev); ...@@ -331,6 +331,10 @@ struct prestera_port *prestera_port_dev_lower_find(struct net_device *dev);
void prestera_queue_work(struct work_struct *work); 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); int prestera_port_pvid_set(struct prestera_port *port, u16 vid);
bool prestera_netdev_check(const struct net_device *dev); 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) ...@@ -1531,7 +1531,7 @@ int prestera_hw_port_learning_set(struct prestera_port *port, bool enable)
&req.cmd, sizeof(req)); &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 = { struct prestera_msg_port_attr_req req = {
.attr = __cpu_to_le32(PRESTERA_CMD_PORT_ATTR_FLOOD), .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) ...@@ -1549,7 +1549,7 @@ static int prestera_hw_port_uc_flood_set(struct prestera_port *port, bool flood)
&req.cmd, sizeof(req)); &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 = { struct prestera_msg_port_attr_req req = {
.attr = __cpu_to_le32(PRESTERA_CMD_PORT_ATTR_FLOOD), .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) ...@@ -1567,56 +1567,6 @@ static int prestera_hw_port_mc_flood_set(struct prestera_port *port, bool flood)
&req.cmd, sizeof(req)); &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) int prestera_hw_vlan_create(struct prestera_switch *sw, u16 vid)
{ {
struct prestera_msg_vlan_req req = { struct prestera_msg_vlan_req req = {
......
...@@ -179,8 +179,8 @@ int prestera_hw_port_stats_get(const struct prestera_port *port, ...@@ -179,8 +179,8 @@ int prestera_hw_port_stats_get(const struct prestera_port *port,
struct prestera_port_stats *stats); struct prestera_port_stats *stats);
int prestera_hw_port_speed_get(const struct prestera_port *port, u32 *speed); 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_learning_set(struct prestera_port *port, bool enable);
int prestera_hw_port_flood_set(struct prestera_port *port, unsigned long mask, int prestera_hw_port_uc_flood_set(const struct prestera_port *port, bool flood);
unsigned long val); 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, int prestera_hw_port_accept_frm_type(struct prestera_port *port,
enum prestera_accept_frm_type type); enum prestera_accept_frm_type type);
/* Vlan API */ /* Vlan API */
......
...@@ -35,6 +35,21 @@ void prestera_queue_work(struct work_struct *work) ...@@ -35,6 +35,21 @@ void prestera_queue_work(struct work_struct *work)
queue_work(prestera_owq, 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) int prestera_port_pvid_set(struct prestera_port *port, u16 vid)
{ {
enum prestera_accept_frm_type frm_type; enum prestera_accept_frm_type frm_type;
......
...@@ -74,6 +74,39 @@ static void prestera_bridge_port_put(struct prestera_bridge_port *br_port); ...@@ -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, static int prestera_port_vid_stp_set(struct prestera_port *port, u16 vid,
u8 state); 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 * static struct prestera_bridge_vlan *
prestera_bridge_vlan_create(struct prestera_bridge_port *br_port, u16 vid) 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) ...@@ -461,19 +494,13 @@ prestera_bridge_1d_port_join(struct prestera_bridge_port *br_port)
if (err) if (err)
return err; return err;
err = prestera_hw_port_flood_set(port, BR_FLOOD | BR_MCAST_FLOOD, err = prestera_br_port_flags_set(br_port, port);
br_port->flags);
if (err)
goto err_port_flood_set;
err = prestera_hw_port_learning_set(port, br_port->flags & BR_LEARNING);
if (err) if (err)
goto err_port_learning_set; goto err_flags2port_set;
return 0; return 0;
err_port_learning_set: err_flags2port_set:
err_port_flood_set:
prestera_hw_bridge_port_delete(port, bridge->bridge_id); prestera_hw_bridge_port_delete(port, bridge->bridge_id);
return err; return err;
...@@ -592,8 +619,7 @@ void prestera_bridge_port_leave(struct net_device *br_dev, ...@@ -592,8 +619,7 @@ void prestera_bridge_port_leave(struct net_device *br_dev,
switchdev_bridge_port_unoffload(br_port->dev, NULL, NULL, NULL); switchdev_bridge_port_unoffload(br_port->dev, NULL, NULL, NULL);
prestera_hw_port_learning_set(port, false); prestera_br_port_flags_reset(br_port, port);
prestera_hw_port_flood_set(port, BR_FLOOD | BR_MCAST_FLOOD, 0);
prestera_port_vid_stp_set(port, PRESTERA_VID_ALL, BR_STATE_FORWARDING); prestera_port_vid_stp_set(port, PRESTERA_VID_ALL, BR_STATE_FORWARDING);
prestera_bridge_port_put(br_port); prestera_bridge_port_put(br_port);
} }
...@@ -603,26 +629,14 @@ static int prestera_port_attr_br_flags_set(struct prestera_port *port, ...@@ -603,26 +629,14 @@ static int prestera_port_attr_br_flags_set(struct prestera_port *port,
struct switchdev_brport_flags flags) struct switchdev_brport_flags flags)
{ {
struct prestera_bridge_port *br_port; struct prestera_bridge_port *br_port;
int err;
br_port = prestera_bridge_port_by_dev(port->sw->swdev, dev); br_port = prestera_bridge_port_by_dev(port->sw->swdev, dev);
if (!br_port) if (!br_port)
return 0; return 0;
err = prestera_hw_port_flood_set(port, flags.mask, flags.val); br_port->flags &= ~flags.mask;
if (err) br_port->flags |= flags.val & flags.mask;
return err; return prestera_br_port_flags_set(br_port, port);
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;
} }
static int prestera_port_attr_br_ageing_set(struct prestera_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, ...@@ -918,14 +932,9 @@ prestera_port_vlan_bridge_join(struct prestera_port_vlan *port_vlan,
if (port_vlan->br_port) if (port_vlan->br_port)
return 0; return 0;
err = prestera_hw_port_flood_set(port, BR_FLOOD | BR_MCAST_FLOOD, err = prestera_br_port_flags_set(br_port, port);
br_port->flags);
if (err)
return err;
err = prestera_hw_port_learning_set(port, br_port->flags & BR_LEARNING);
if (err) if (err)
goto err_port_learning_set; goto err_flags2port_set;
err = prestera_port_vid_stp_set(port, vid, br_port->stp_state); err = prestera_port_vid_stp_set(port, vid, br_port->stp_state);
if (err) if (err)
...@@ -950,8 +959,8 @@ prestera_port_vlan_bridge_join(struct prestera_port_vlan *port_vlan, ...@@ -950,8 +959,8 @@ prestera_port_vlan_bridge_join(struct prestera_port_vlan *port_vlan,
err_bridge_vlan_get: err_bridge_vlan_get:
prestera_port_vid_stp_set(port, vid, BR_STATE_FORWARDING); prestera_port_vid_stp_set(port, vid, BR_STATE_FORWARDING);
err_port_vid_stp_set: err_port_vid_stp_set:
prestera_hw_port_learning_set(port, false); prestera_br_port_flags_reset(br_port, port);
err_port_learning_set: err_flags2port_set:
return err; return err;
} }
......
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