net: dsa: deduplicate code adding / deleting the port address to fdb

The sequence
  if (dsa_switch_supports_uc_filtering(ds))
    dsa_port_standalone_host_fdb_add(dp, addr, 0);
  if (!ether_addr_equal(addr, conduit->dev_addr))
    dev_uc_add(conduit, addr);
is executed both in dsa_user_open() and dsa_user_set_mac_addr().

Its reverse is executed both in dsa_user_close() and
dsa_user_set_mac_addr().

Refactor these sequences into new functions dsa_user_host_uc_install()
and dsa_user_host_uc_uninstall().

Signed-off-by: Marek Behún <kabel@kernel.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Marek Behún 2024-06-05 15:33:28 +02:00 committed by David S. Miller
parent 395059c52e
commit 77f7541248

View File

@ -355,60 +355,82 @@ static int dsa_user_get_iflink(const struct net_device *dev)
return READ_ONCE(dsa_user_to_conduit(dev)->ifindex);
}
static int dsa_user_open(struct net_device *dev)
static int dsa_user_host_uc_install(struct net_device *dev, const u8 *addr)
{
struct net_device *conduit = dsa_user_to_conduit(dev);
struct dsa_port *dp = dsa_user_to_port(dev);
struct dsa_switch *ds = dp->ds;
int err;
if (dsa_switch_supports_uc_filtering(ds)) {
err = dsa_port_standalone_host_fdb_add(dp, addr, 0);
if (err)
goto out;
}
if (!ether_addr_equal(addr, conduit->dev_addr)) {
err = dev_uc_add(conduit, addr);
if (err < 0)
goto del_host_addr;
}
return 0;
del_host_addr:
if (dsa_switch_supports_uc_filtering(ds))
dsa_port_standalone_host_fdb_del(dp, addr, 0);
out:
return err;
}
static void dsa_user_host_uc_uninstall(struct net_device *dev)
{
struct net_device *conduit = dsa_user_to_conduit(dev);
struct dsa_port *dp = dsa_user_to_port(dev);
struct dsa_switch *ds = dp->ds;
if (!ether_addr_equal(dev->dev_addr, conduit->dev_addr))
dev_uc_del(conduit, dev->dev_addr);
if (dsa_switch_supports_uc_filtering(ds))
dsa_port_standalone_host_fdb_del(dp, dev->dev_addr, 0);
}
static int dsa_user_open(struct net_device *dev)
{
struct net_device *conduit = dsa_user_to_conduit(dev);
struct dsa_port *dp = dsa_user_to_port(dev);
int err;
err = dev_open(conduit, NULL);
if (err < 0) {
netdev_err(dev, "failed to open conduit %s\n", conduit->name);
goto out;
}
if (dsa_switch_supports_uc_filtering(ds)) {
err = dsa_port_standalone_host_fdb_add(dp, dev->dev_addr, 0);
if (err)
goto out;
}
if (!ether_addr_equal(dev->dev_addr, conduit->dev_addr)) {
err = dev_uc_add(conduit, dev->dev_addr);
if (err < 0)
goto del_host_addr;
}
err = dsa_user_host_uc_install(dev, dev->dev_addr);
if (err)
goto out;
err = dsa_port_enable_rt(dp, dev->phydev);
if (err)
goto del_unicast;
goto out_del_host_uc;
return 0;
del_unicast:
if (!ether_addr_equal(dev->dev_addr, conduit->dev_addr))
dev_uc_del(conduit, dev->dev_addr);
del_host_addr:
if (dsa_switch_supports_uc_filtering(ds))
dsa_port_standalone_host_fdb_del(dp, dev->dev_addr, 0);
out_del_host_uc:
dsa_user_host_uc_uninstall(dev);
out:
return err;
}
static int dsa_user_close(struct net_device *dev)
{
struct net_device *conduit = dsa_user_to_conduit(dev);
struct dsa_port *dp = dsa_user_to_port(dev);
struct dsa_switch *ds = dp->ds;
dsa_port_disable_rt(dp);
if (!ether_addr_equal(dev->dev_addr, conduit->dev_addr))
dev_uc_del(conduit, dev->dev_addr);
if (dsa_switch_supports_uc_filtering(ds))
dsa_port_standalone_host_fdb_del(dp, dev->dev_addr, 0);
dsa_user_host_uc_uninstall(dev);
return 0;
}
@ -448,7 +470,6 @@ static void dsa_user_set_rx_mode(struct net_device *dev)
static int dsa_user_set_mac_address(struct net_device *dev, void *a)
{
struct net_device *conduit = dsa_user_to_conduit(dev);
struct dsa_port *dp = dsa_user_to_port(dev);
struct dsa_switch *ds = dp->ds;
struct sockaddr *addr = a;
@ -470,34 +491,16 @@ static int dsa_user_set_mac_address(struct net_device *dev, void *a)
if (!(dev->flags & IFF_UP))
goto out_change_dev_addr;
if (dsa_switch_supports_uc_filtering(ds)) {
err = dsa_port_standalone_host_fdb_add(dp, addr->sa_data, 0);
if (err)
return err;
}
err = dsa_user_host_uc_install(dev, addr->sa_data);
if (err)
return err;
if (!ether_addr_equal(addr->sa_data, conduit->dev_addr)) {
err = dev_uc_add(conduit, addr->sa_data);
if (err < 0)
goto del_unicast;
}
if (!ether_addr_equal(dev->dev_addr, conduit->dev_addr))
dev_uc_del(conduit, dev->dev_addr);
if (dsa_switch_supports_uc_filtering(ds))
dsa_port_standalone_host_fdb_del(dp, dev->dev_addr, 0);
dsa_user_host_uc_uninstall(dev);
out_change_dev_addr:
eth_hw_addr_set(dev, addr->sa_data);
return 0;
del_unicast:
if (dsa_switch_supports_uc_filtering(ds))
dsa_port_standalone_host_fdb_del(dp, addr->sa_data, 0);
return err;
}
struct dsa_user_dump_ctx {