struct dsa_switch *ds = dp->ds;
        struct dsa_mac_addr *a;
        int port = dp->index;
-       int err;
+       int err = 0;
 
        /* No need to bother with refcounting for user ports */
        if (!(dsa_port_is_cpu(dp) || dsa_port_is_dsa(dp)))
                return ds->ops->port_mdb_add(ds, port, mdb);
 
+       mutex_lock(&dp->addr_lists_lock);
+
        a = dsa_mac_addr_find(&dp->mdbs, mdb->addr, mdb->vid);
        if (a) {
                refcount_inc(&a->refcount);
-               return 0;
+               goto out;
        }
 
        a = kzalloc(sizeof(*a), GFP_KERNEL);
-       if (!a)
-               return -ENOMEM;
+       if (!a) {
+               err = -ENOMEM;
+               goto out;
+       }
 
        err = ds->ops->port_mdb_add(ds, port, mdb);
        if (err) {
                kfree(a);
-               return err;
+               goto out;
        }
 
        ether_addr_copy(a->addr, mdb->addr);
        refcount_set(&a->refcount, 1);
        list_add_tail(&a->list, &dp->mdbs);
 
-       return 0;
+out:
+       mutex_unlock(&dp->addr_lists_lock);
+
+       return err;
 }
 
 static int dsa_port_do_mdb_del(struct dsa_port *dp,
        struct dsa_switch *ds = dp->ds;
        struct dsa_mac_addr *a;
        int port = dp->index;
-       int err;
+       int err = 0;
 
        /* No need to bother with refcounting for user ports */
        if (!(dsa_port_is_cpu(dp) || dsa_port_is_dsa(dp)))
                return ds->ops->port_mdb_del(ds, port, mdb);
 
+       mutex_lock(&dp->addr_lists_lock);
+
        a = dsa_mac_addr_find(&dp->mdbs, mdb->addr, mdb->vid);
-       if (!a)
-               return -ENOENT;
+       if (!a) {
+               err = -ENOENT;
+               goto out;
+       }
 
        if (!refcount_dec_and_test(&a->refcount))
-               return 0;
+               goto out;
 
        err = ds->ops->port_mdb_del(ds, port, mdb);
        if (err) {
                refcount_set(&a->refcount, 1);
-               return err;
+               goto out;
        }
 
        list_del(&a->list);
        kfree(a);
 
-       return 0;
+out:
+       mutex_unlock(&dp->addr_lists_lock);
+
+       return err;
 }
 
 static int dsa_port_do_fdb_add(struct dsa_port *dp, const unsigned char *addr,
        struct dsa_switch *ds = dp->ds;
        struct dsa_mac_addr *a;
        int port = dp->index;
-       int err;
+       int err = 0;
 
        /* No need to bother with refcounting for user ports */
        if (!(dsa_port_is_cpu(dp) || dsa_port_is_dsa(dp)))
                return ds->ops->port_fdb_add(ds, port, addr, vid);
 
+       mutex_lock(&dp->addr_lists_lock);
+
        a = dsa_mac_addr_find(&dp->fdbs, addr, vid);
        if (a) {
                refcount_inc(&a->refcount);
-               return 0;
+               goto out;
        }
 
        a = kzalloc(sizeof(*a), GFP_KERNEL);
-       if (!a)
-               return -ENOMEM;
+       if (!a) {
+               err = -ENOMEM;
+               goto out;
+       }
 
        err = ds->ops->port_fdb_add(ds, port, addr, vid);
        if (err) {
                kfree(a);
-               return err;
+               goto out;
        }
 
        ether_addr_copy(a->addr, addr);
        refcount_set(&a->refcount, 1);
        list_add_tail(&a->list, &dp->fdbs);
 
-       return 0;
+out:
+       mutex_unlock(&dp->addr_lists_lock);
+
+       return err;
 }
 
 static int dsa_port_do_fdb_del(struct dsa_port *dp, const unsigned char *addr,
        struct dsa_switch *ds = dp->ds;
        struct dsa_mac_addr *a;
        int port = dp->index;
-       int err;
+       int err = 0;
 
        /* No need to bother with refcounting for user ports */
        if (!(dsa_port_is_cpu(dp) || dsa_port_is_dsa(dp)))
                return ds->ops->port_fdb_del(ds, port, addr, vid);
 
+       mutex_lock(&dp->addr_lists_lock);
+
        a = dsa_mac_addr_find(&dp->fdbs, addr, vid);
-       if (!a)
-               return -ENOENT;
+       if (!a) {
+               err = -ENOENT;
+               goto out;
+       }
 
        if (!refcount_dec_and_test(&a->refcount))
-               return 0;
+               goto out;
 
        err = ds->ops->port_fdb_del(ds, port, addr, vid);
        if (err) {
                refcount_set(&a->refcount, 1);
-               return err;
+               goto out;
        }
 
        list_del(&a->list);
        kfree(a);
 
-       return 0;
+out:
+       mutex_unlock(&dp->addr_lists_lock);
+
+       return err;
 }
 
 static int dsa_switch_host_fdb_add(struct dsa_switch *ds,