diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
index f66ddde484dc..32a613c965b1 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.c
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
@@ -47,6 +47,14 @@ struct mv88e6xxx_bridge {
 	struct list_head head;
 	struct net_device *br_dev;
 	u16 ports;
+	struct list_head br_mdb_list;
+};
+
+struct mv88e6xxx_br_mdb {
+	struct list_head head;
+	unsigned char addr[ETH_ALEN];
+	u16 vid;
+	u16 portvec;
 };
 
 static void assert_reg_lock(struct mv88e6xxx_chip *chip)
@@ -2974,6 +2982,7 @@ mv88e6xxx_bridge_create(struct mv88e6xxx_chip *chip, struct net_device *br_dev)
 		return ERR_PTR(-ENOMEM);
 
 	mv_bridge->br_dev = br_dev;
+	INIT_LIST_HEAD(&mv_bridge->br_mdb_list);
 	list_add(&mv_bridge->head, &chip->bridge_list);
 
 	return mv_bridge;
@@ -2984,6 +2993,7 @@ static void mv88e6xxx_bridge_destroy(struct mv88e6xxx_bridge *mv_bridge)
 	list_del(&mv_bridge->head);
 
 	WARN_ON(mv_bridge->ports);
+	WARN_ON(!list_empty(&mv_bridge->br_mdb_list));
 	kfree(mv_bridge);
 }
 
@@ -6583,16 +6593,101 @@ static int mv88e6xxx_change_tag_protocol(struct dsa_switch *ds,
 	return err;
 }
 
+static struct mv88e6xxx_br_mdb *
+mv88e6xxx_br_mdb_create(struct mv88e6xxx_bridge *mv_bridge,
+			const struct switchdev_obj_port_mdb *mdb)
+{
+	struct mv88e6xxx_br_mdb *mv_br_mdb;
+
+	mv_br_mdb = kzalloc(sizeof(*mv_br_mdb), GFP_KERNEL);
+	if (!mv_br_mdb)
+		return ERR_PTR(-ENOMEM);
+
+	ether_addr_copy(mv_br_mdb->addr, mdb->addr);
+	mv_br_mdb->vid = mdb->vid;
+	list_add(&mv_br_mdb->head, &mv_bridge->br_mdb_list);
+
+	return mv_br_mdb;
+}
+
+static void mv88e6xxx_br_mdb_destroy(struct mv88e6xxx_br_mdb *mv_br_mdb)
+{
+	list_del(&mv_br_mdb->head);
+
+	WARN_ON(mv_br_mdb->portvec);
+	kfree(mv_br_mdb);
+}
+
+static struct mv88e6xxx_br_mdb *
+mv88e6xxx_br_mdb_find(struct mv88e6xxx_bridge *mv_bridge,
+		      const struct switchdev_obj_port_mdb *mdb)
+{
+	struct mv88e6xxx_br_mdb *mv_br_mdb;
+
+	list_for_each_entry(mv_br_mdb, &mv_bridge->br_mdb_list, head)
+		if (ether_addr_equal(mv_br_mdb->addr, mdb->addr) &&
+		    mv_br_mdb->vid == mdb->vid)
+			return mv_br_mdb;
+
+	return NULL;
+}
+
+static struct mv88e6xxx_br_mdb *
+mv88e6xxx_br_mdb_get(struct mv88e6xxx_bridge *mv_bridge,
+		     const struct switchdev_obj_port_mdb *mdb)
+{
+	struct mv88e6xxx_br_mdb *mv_br_mdb;
+
+	mv_br_mdb = mv88e6xxx_br_mdb_find(mv_bridge, mdb);
+	if (!mv_br_mdb)
+		mv_br_mdb = mv88e6xxx_br_mdb_create(mv_bridge, mdb);
+
+	return mv_br_mdb;
+}
+
+static void mv88e6xxx_br_mdb_put(struct mv88e6xxx_br_mdb *mv_br_mdb)
+{
+	if (!mv_br_mdb->portvec)
+		mv88e6xxx_br_mdb_destroy(mv_br_mdb);
+}
+
 static int mv88e6xxx_port_mdb_add(struct dsa_switch *ds, int port,
 				  const struct switchdev_obj_port_mdb *mdb,
 				  struct dsa_db db)
 {
 	struct mv88e6xxx_chip *chip = ds->priv;
+	struct mv88e6xxx_bridge *mv_bridge;
+	struct mv88e6xxx_br_mdb *mv_br_mdb;
+	struct net_device *orig_dev;
+	struct net_device *br_dev;
 	int err;
 
+	orig_dev = mdb->obj.orig_dev;
+	br_dev = netdev_master_upper_dev_get(orig_dev);
+	if (!br_dev)
+		br_dev = orig_dev;
+
+	mv_bridge = mv88e6xxx_bridge_by_dev(chip, br_dev);
+	if (!mv_bridge)
+		return -EINVAL;
+
+	mv_br_mdb = mv88e6xxx_br_mdb_get(mv_bridge, mdb);
+	if (IS_ERR(mv_br_mdb))
+		return PTR_ERR(mv_br_mdb);
+
+	if (mv_br_mdb->portvec & BIT(port))
+		return -EEXIST;
+
 	mv88e6xxx_reg_lock(chip);
 	err = mv88e6xxx_port_db_load_purge(chip, port, mdb->addr, mdb->vid,
 					   MV88E6XXX_G1_ATU_DATA_STATE_MC_STATIC);
+
+	if (err)
+		goto out;
+
+	mv_br_mdb->portvec |= BIT(port);
+
+out:
 	mv88e6xxx_reg_unlock(chip);
 
 	return err;
@@ -6603,10 +6698,32 @@ static int mv88e6xxx_port_mdb_del(struct dsa_switch *ds, int port,
 				  struct dsa_db db)
 {
 	struct mv88e6xxx_chip *chip = ds->priv;
+	struct mv88e6xxx_bridge *mv_bridge;
+	struct mv88e6xxx_br_mdb *mv_br_mdb;
+	struct net_device *orig_dev;
+	struct net_device *br_dev;
 	int err;
 
+	orig_dev = mdb->obj.orig_dev;
+	br_dev = netdev_master_upper_dev_get(orig_dev);
+	if (!br_dev)
+		br_dev = orig_dev;
+
+	mv_bridge = mv88e6xxx_bridge_by_dev(chip, br_dev);
+	if (!mv_bridge)
+		return -EINVAL;
+
+	mv_br_mdb = mv88e6xxx_br_mdb_find(mv_bridge, mdb);
+	if (!mv_br_mdb)
+		return -ENOENT;
+
+	if (!(mv_br_mdb->portvec & BIT(port)))
+		return -ENOENT;
+
 	mv88e6xxx_reg_lock(chip);
 	err = mv88e6xxx_port_db_load_purge(chip, port, mdb->addr, mdb->vid, 0);
+	mv_br_mdb->portvec &= ~BIT(port);
+	mv88e6xxx_br_mdb_put(mv_br_mdb);
 	mv88e6xxx_reg_unlock(chip);
 
 	return err;
