Commit 3b83fa94 authored by David S. Miller's avatar David S. Miller

Merge branch 'dpaa2-switch-small-improvements'

Ioana Ciornei says:

====================
dpaa2-switch: small improvements

This patch set consists of a series of small improvements on the
dpaa2-switch driver ranging from adding some more verbosity when
encountering errors to reorganizing code to be easily extensible.

Changes in v3:
- 4/8: removed the fixes tag and moved it to the commit message
- 5/8: specified that there is no user-visible effect
- 6/8: removed the initialization of the err variable

Changes in v2:
- No changes to the actual diff, only rephrased some commit messages and
  added more information.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents d11db8ad 71150d94
...@@ -289,7 +289,7 @@ static int dpaa2_switch_port_add_vlan(struct ethsw_port_priv *port_priv, ...@@ -289,7 +289,7 @@ static int dpaa2_switch_port_add_vlan(struct ethsw_port_priv *port_priv,
int err; int err;
if (port_priv->vlans[vid]) { if (port_priv->vlans[vid]) {
netdev_warn(netdev, "VLAN %d already configured\n", vid); netdev_err(netdev, "VLAN %d already configured\n", vid);
return -EEXIST; return -EEXIST;
} }
...@@ -1509,9 +1509,9 @@ static irqreturn_t dpaa2_switch_irq0_handler_thread(int irq_num, void *arg) ...@@ -1509,9 +1509,9 @@ static irqreturn_t dpaa2_switch_irq0_handler_thread(int irq_num, void *arg)
struct device *dev = (struct device *)arg; struct device *dev = (struct device *)arg;
struct ethsw_core *ethsw = dev_get_drvdata(dev); struct ethsw_core *ethsw = dev_get_drvdata(dev);
struct ethsw_port_priv *port_priv; struct ethsw_port_priv *port_priv;
u32 status = ~0;
int err, if_id; int err, if_id;
bool had_mac; bool had_mac;
u32 status;
err = dpsw_get_irq_status(ethsw->mc_io, 0, ethsw->dpsw_handle, err = dpsw_get_irq_status(ethsw->mc_io, 0, ethsw->dpsw_handle,
DPSW_IRQ_INDEX_IF, &status); DPSW_IRQ_INDEX_IF, &status);
...@@ -1523,12 +1523,11 @@ static irqreturn_t dpaa2_switch_irq0_handler_thread(int irq_num, void *arg) ...@@ -1523,12 +1523,11 @@ static irqreturn_t dpaa2_switch_irq0_handler_thread(int irq_num, void *arg)
if_id = (status & 0xFFFF0000) >> 16; if_id = (status & 0xFFFF0000) >> 16;
port_priv = ethsw->ports[if_id]; port_priv = ethsw->ports[if_id];
if (status & DPSW_IRQ_EVENT_LINK_CHANGED) { if (status & DPSW_IRQ_EVENT_LINK_CHANGED)
dpaa2_switch_port_link_state_update(port_priv->netdev); dpaa2_switch_port_link_state_update(port_priv->netdev);
dpaa2_switch_port_set_mac_addr(port_priv);
}
if (status & DPSW_IRQ_EVENT_ENDPOINT_CHANGED) { if (status & DPSW_IRQ_EVENT_ENDPOINT_CHANGED) {
dpaa2_switch_port_set_mac_addr(port_priv);
/* We can avoid locking because the "endpoint changed" IRQ /* We can avoid locking because the "endpoint changed" IRQ
* handler is the only one who changes priv->mac at runtime, * handler is the only one who changes priv->mac at runtime,
* so we are not racing with anyone. * so we are not racing with anyone.
...@@ -1540,20 +1539,20 @@ static irqreturn_t dpaa2_switch_irq0_handler_thread(int irq_num, void *arg) ...@@ -1540,20 +1539,20 @@ static irqreturn_t dpaa2_switch_irq0_handler_thread(int irq_num, void *arg)
dpaa2_switch_port_connect_mac(port_priv); dpaa2_switch_port_connect_mac(port_priv);
} }
out:
err = dpsw_clear_irq_status(ethsw->mc_io, 0, ethsw->dpsw_handle, err = dpsw_clear_irq_status(ethsw->mc_io, 0, ethsw->dpsw_handle,
DPSW_IRQ_INDEX_IF, status); DPSW_IRQ_INDEX_IF, status);
if (err) if (err)
dev_err(dev, "Can't clear irq status (err %d)\n", err); dev_err(dev, "Can't clear irq status (err %d)\n", err);
out:
return IRQ_HANDLED; return IRQ_HANDLED;
} }
static int dpaa2_switch_setup_irqs(struct fsl_mc_device *sw_dev) static int dpaa2_switch_setup_irqs(struct fsl_mc_device *sw_dev)
{ {
u32 mask = DPSW_IRQ_EVENT_LINK_CHANGED | DPSW_IRQ_EVENT_ENDPOINT_CHANGED;
struct device *dev = &sw_dev->dev; struct device *dev = &sw_dev->dev;
struct ethsw_core *ethsw = dev_get_drvdata(dev); struct ethsw_core *ethsw = dev_get_drvdata(dev);
u32 mask = DPSW_IRQ_EVENT_LINK_CHANGED;
struct fsl_mc_device_irq *irq; struct fsl_mc_device_irq *irq;
int err; int err;
...@@ -1775,8 +1774,10 @@ int dpaa2_switch_port_vlans_add(struct net_device *netdev, ...@@ -1775,8 +1774,10 @@ int dpaa2_switch_port_vlans_add(struct net_device *netdev,
/* Make sure that the VLAN is not already configured /* Make sure that the VLAN is not already configured
* on the switch port * on the switch port
*/ */
if (port_priv->vlans[vlan->vid] & ETHSW_VLAN_MEMBER) if (port_priv->vlans[vlan->vid] & ETHSW_VLAN_MEMBER) {
netdev_err(netdev, "VLAN %d already configured\n", vlan->vid);
return -EEXIST; return -EEXIST;
}
/* Check if there is space for a new VLAN */ /* Check if there is space for a new VLAN */
err = dpsw_get_attributes(ethsw->mc_io, 0, ethsw->dpsw_handle, err = dpsw_get_attributes(ethsw->mc_io, 0, ethsw->dpsw_handle,
...@@ -2003,25 +2004,11 @@ static int dpaa2_switch_port_bridge_join(struct net_device *netdev, ...@@ -2003,25 +2004,11 @@ static int dpaa2_switch_port_bridge_join(struct net_device *netdev,
struct netlink_ext_ack *extack) struct netlink_ext_ack *extack)
{ {
struct ethsw_port_priv *port_priv = netdev_priv(netdev); struct ethsw_port_priv *port_priv = netdev_priv(netdev);
struct dpaa2_switch_fdb *old_fdb = port_priv->fdb;
struct ethsw_core *ethsw = port_priv->ethsw_data; struct ethsw_core *ethsw = port_priv->ethsw_data;
struct ethsw_port_priv *other_port_priv;
struct net_device *other_dev;
struct list_head *iter;
bool learn_ena; bool learn_ena;
int err; int err;
netdev_for_each_lower_dev(upper_dev, other_dev, iter) {
if (!dpaa2_switch_port_dev_check(other_dev))
continue;
other_port_priv = netdev_priv(other_dev);
if (other_port_priv->ethsw_data != port_priv->ethsw_data) {
NL_SET_ERR_MSG_MOD(extack,
"Interface from a different DPSW is in the bridge already");
return -EINVAL;
}
}
/* Delete the previously manually installed VLAN 1 */ /* Delete the previously manually installed VLAN 1 */
err = dpaa2_switch_port_del_vlan(port_priv, 1); err = dpaa2_switch_port_del_vlan(port_priv, 1);
if (err) if (err)
...@@ -2039,6 +2026,11 @@ static int dpaa2_switch_port_bridge_join(struct net_device *netdev, ...@@ -2039,6 +2026,11 @@ static int dpaa2_switch_port_bridge_join(struct net_device *netdev,
if (err) if (err)
goto err_egress_flood; goto err_egress_flood;
/* Recreate the egress flood domain of the FDB that we just left. */
err = dpaa2_switch_fdb_set_egress_flood(ethsw, old_fdb->fdb_id);
if (err)
goto err_egress_flood;
err = switchdev_bridge_port_offload(netdev, netdev, NULL, err = switchdev_bridge_port_offload(netdev, netdev, NULL,
NULL, NULL, false, extack); NULL, NULL, false, extack);
if (err) if (err)
...@@ -2155,6 +2147,10 @@ dpaa2_switch_prechangeupper_sanity_checks(struct net_device *netdev, ...@@ -2155,6 +2147,10 @@ dpaa2_switch_prechangeupper_sanity_checks(struct net_device *netdev,
struct net_device *upper_dev, struct net_device *upper_dev,
struct netlink_ext_ack *extack) struct netlink_ext_ack *extack)
{ {
struct ethsw_port_priv *port_priv = netdev_priv(netdev);
struct ethsw_port_priv *other_port_priv;
struct net_device *other_dev;
struct list_head *iter;
int err; int err;
if (!br_vlan_enabled(upper_dev)) { if (!br_vlan_enabled(upper_dev)) {
...@@ -2169,54 +2165,93 @@ dpaa2_switch_prechangeupper_sanity_checks(struct net_device *netdev, ...@@ -2169,54 +2165,93 @@ dpaa2_switch_prechangeupper_sanity_checks(struct net_device *netdev,
return 0; return 0;
} }
netdev_for_each_lower_dev(upper_dev, other_dev, iter) {
if (!dpaa2_switch_port_dev_check(other_dev))
continue;
other_port_priv = netdev_priv(other_dev);
if (other_port_priv->ethsw_data != port_priv->ethsw_data) {
NL_SET_ERR_MSG_MOD(extack,
"Interface from a different DPSW is in the bridge already");
return -EINVAL;
}
}
return 0; return 0;
} }
static int dpaa2_switch_port_netdevice_event(struct notifier_block *nb, static int dpaa2_switch_port_prechangeupper(struct net_device *netdev,
unsigned long event, void *ptr) struct netdev_notifier_changeupper_info *info)
{ {
struct net_device *netdev = netdev_notifier_info_to_dev(ptr);
struct netdev_notifier_changeupper_info *info = ptr;
struct netlink_ext_ack *extack; struct netlink_ext_ack *extack;
struct net_device *upper_dev; struct net_device *upper_dev;
int err = 0; int err;
if (!dpaa2_switch_port_dev_check(netdev)) if (!dpaa2_switch_port_dev_check(netdev))
return NOTIFY_DONE; return 0;
extack = netdev_notifier_info_to_extack(&info->info); extack = netdev_notifier_info_to_extack(&info->info);
upper_dev = info->upper_dev;
switch (event) { if (netif_is_bridge_master(upper_dev)) {
case NETDEV_PRECHANGEUPPER:
upper_dev = info->upper_dev;
if (!netif_is_bridge_master(upper_dev))
break;
err = dpaa2_switch_prechangeupper_sanity_checks(netdev, err = dpaa2_switch_prechangeupper_sanity_checks(netdev,
upper_dev, upper_dev,
extack); extack);
if (err) if (err)
goto out; return err;
if (!info->linking) if (!info->linking)
dpaa2_switch_port_pre_bridge_leave(netdev); dpaa2_switch_port_pre_bridge_leave(netdev);
}
return 0;
}
static int dpaa2_switch_port_changeupper(struct net_device *netdev,
struct netdev_notifier_changeupper_info *info)
{
struct netlink_ext_ack *extack;
struct net_device *upper_dev;
if (!dpaa2_switch_port_dev_check(netdev))
return 0;
extack = netdev_notifier_info_to_extack(&info->info);
upper_dev = info->upper_dev;
if (netif_is_bridge_master(upper_dev)) {
if (info->linking)
return dpaa2_switch_port_bridge_join(netdev,
upper_dev,
extack);
else
return dpaa2_switch_port_bridge_leave(netdev);
}
return 0;
}
static int dpaa2_switch_port_netdevice_event(struct notifier_block *nb,
unsigned long event, void *ptr)
{
struct net_device *netdev = netdev_notifier_info_to_dev(ptr);
int err = 0;
switch (event) {
case NETDEV_PRECHANGEUPPER:
err = dpaa2_switch_port_prechangeupper(netdev, ptr);
if (err)
return notifier_from_errno(err);
break; break;
case NETDEV_CHANGEUPPER: case NETDEV_CHANGEUPPER:
upper_dev = info->upper_dev; err = dpaa2_switch_port_changeupper(netdev, ptr);
if (netif_is_bridge_master(upper_dev)) { if (err)
if (info->linking) return notifier_from_errno(err);
err = dpaa2_switch_port_bridge_join(netdev,
upper_dev,
extack);
else
err = dpaa2_switch_port_bridge_leave(netdev);
}
break; break;
} }
out: return NOTIFY_DONE;
return notifier_from_errno(err);
} }
struct ethsw_switchdev_event_work { struct ethsw_switchdev_event_work {
...@@ -3294,6 +3329,7 @@ static int dpaa2_switch_probe_port(struct ethsw_core *ethsw, ...@@ -3294,6 +3329,7 @@ static int dpaa2_switch_probe_port(struct ethsw_core *ethsw,
port_netdev->features = NETIF_F_HW_VLAN_CTAG_FILTER | port_netdev->features = NETIF_F_HW_VLAN_CTAG_FILTER |
NETIF_F_HW_VLAN_STAG_FILTER | NETIF_F_HW_VLAN_STAG_FILTER |
NETIF_F_HW_TC; NETIF_F_HW_TC;
port_netdev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
err = dpaa2_switch_port_init(port_priv, port_idx); err = dpaa2_switch_port_init(port_priv, port_idx);
if (err) if (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