Hi Florian, On Tue, 29 Jan 2019 16:55:43 -0800, Florian Fainelli <f.faine...@gmail.com> wrote:
> +static int dsa_slave_sync_unsync_mdb_addr(struct net_device *dev, > + const unsigned char *addr, bool add) > +{ > + struct switchdev_obj_port_mdb mdb = { > + .obj = { > + .id = SWITCHDEV_OBJ_ID_HOST_MDB, > + .flags = SWITCHDEV_F_DEFER, > + }, > + .vid = 0, > + }; > + int ret = -EOPNOTSUPP; Assignment unneeded here. > + > + ether_addr_copy(mdb.addr, addr); > + if (add) > + ret = switchdev_port_obj_add(dev, &mdb.obj, NULL); > + else > + ret = switchdev_port_obj_del(dev, &mdb.obj); > + > + return ret; > +} > + > +static int dsa_slave_sync_mdb_addr(struct net_device *dev, > + const unsigned char *addr) > +{ > + return dsa_slave_sync_unsync_mdb_addr(dev, addr, true); > +} > + > +static int dsa_slave_unsync_mdb_addr(struct net_device *dev, > + const unsigned char *addr) > +{ > + return dsa_slave_sync_unsync_mdb_addr(dev, addr, false); > +} This wrapper isn't necessary IMO. I'd go with something like: static int dsa_slave_sync(struct net_device *dev, const unsigned char *addr) { struct switchdev_obj_port_mdb mdb = { .obj.id = SWITCHDEV_OBJ_ID_HOST_MDB, .obj.flags = SWITCHDEV_F_DEFER, }; ether_addr_copy(mdb.addr, addr); return switchdev_port_obj_add(dev, &mdb.obj, NULL); } static int dsa_slave_unsync(struct net_device *dev, const unsigned char *addr) { struct switchdev_obj_port_mdb mdb = { .obj.id = SWITCHDEV_OBJ_ID_HOST_MDB, .obj.flags = SWITCHDEV_F_DEFER, }; ether_addr_copy(mdb.addr, addr); return switchdev_port_obj_del(dev, &mdb.obj); } We may eventually wrap this cryptic netdevery in: static int dsa_slave_mc_sync(struct net_device *dev) { return __hw_addr_sync_dev(&dev->mc, dev, dsa_slave_sync, dsa_slave_unsync); } static void dsa_slave_mc_unsync(struct net_device *dev) { __hw_addr_unsync_dev(&dev->mc, dev, dsa_slave_sync); } > + > static int dsa_slave_open(struct net_device *dev) > { > struct net_device *master = dsa_slave_to_master(dev); > @@ -126,6 +159,8 @@ static int dsa_slave_close(struct net_device *dev) > > dev_mc_unsync(master, dev); > dev_uc_unsync(master, dev); > + __hw_addr_unsync_dev(&dev->mc, dev, dsa_slave_unsync_mdb_addr); > + > if (dev->flags & IFF_ALLMULTI) > dev_set_allmulti(master, -1); > if (dev->flags & IFF_PROMISC) > @@ -150,7 +185,17 @@ static void dsa_slave_change_rx_flags(struct net_device > *dev, int change) > static void dsa_slave_set_rx_mode(struct net_device *dev) > { > struct net_device *master = dsa_slave_to_master(dev); > + struct dsa_port *dp = dsa_slave_to_port(dev); > > + /* If the port is bridged, the bridge takes care of sending > + * SWITCHDEV_OBJ_ID_HOST_MDB to program the host's MC filter > + */ > + if (netdev_mc_empty(dev) || dp->bridge_dev) > + goto out; > + > + __hw_addr_sync_dev(&dev->mc, dev, dsa_slave_sync_mdb_addr, > + dsa_slave_unsync_mdb_addr); And check the returned error code. > +out: > dev_mc_sync(master, dev); > dev_uc_sync(master, dev); > } Thanks, Vivien