{
        struct net_bridge *br = netdev_priv(dev);
 
-       if (new_mtu > br_mtu(br, br_vlan_enabled(dev)))
-               return -EINVAL;
-
        dev->mtu = new_mtu;
 
+       /* this flag will be cleared if the MTU was automatically adjusted */
+       br->mtu_set_by_user = true;
 #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
        /* remember the MTU in the rtable for PMTU */
        dst_metric_set(&br->fake_rtable.dst, RTAX_MTU, new_mtu);
 
        return ret;
 }
 
-/* MTU of the bridge pseudo-device: ETH_DATA_LEN if there are no ports, the
- * minimum of the ports if @max is false or the maximum if it's true
- */
-int br_mtu(const struct net_bridge *br, bool max)
+/* MTU of the bridge pseudo-device: ETH_DATA_LEN or the minimum of the ports */
+static int br_mtu_min(const struct net_bridge *br)
 {
        const struct net_bridge_port *p;
        int ret_mtu = 0;
 
-       ASSERT_RTNL();
-
-       list_for_each_entry(p, &br->port_list, list) {
-               if (!max) {
-                       if (!ret_mtu || ret_mtu > p->dev->mtu)
-                               ret_mtu = p->dev->mtu;
-               } else if (p->dev->mtu > ret_mtu) {
+       list_for_each_entry(p, &br->port_list, list)
+               if (!ret_mtu || ret_mtu > p->dev->mtu)
                        ret_mtu = p->dev->mtu;
-               }
-       }
 
        return ret_mtu ? ret_mtu : ETH_DATA_LEN;
 }
 
+void br_mtu_auto_adjust(struct net_bridge *br)
+{
+       ASSERT_RTNL();
+
+       /* if the bridge MTU was manually configured don't mess with it */
+       if (br->mtu_set_by_user)
+               return;
+
+       /* change to the minimum MTU and clear the flag which was set by
+        * the bridge ndo_change_mtu callback
+        */
+       dev_set_mtu(br->dev, br_mtu_min(br));
+       br->mtu_set_by_user = false;
+}
+
 static void br_set_gso_limits(struct net_bridge *br)
 {
        unsigned int gso_max_size = GSO_MAX_SIZE;
        if (changed_addr)
                call_netdevice_notifiers(NETDEV_CHANGEADDR, br->dev);
 
-       dev_set_mtu(br->dev, br_mtu(br, false));
+       br_mtu_auto_adjust(br);
        br_set_gso_limits(br);
 
        kobject_uevent(&p->kobj, KOBJ_ADD);
         */
        del_nbp(p);
 
-       dev_set_mtu(br->dev, br_mtu(br, false));
+       br_mtu_auto_adjust(br);
        br_set_gso_limits(br);
 
        spin_lock_bh(&br->lock);
 
        int offload_fwd_mark;
 #endif
        bool                            neigh_suppress_enabled;
+       bool                            mtu_set_by_user;
        struct hlist_head               fdb_list;
 };
 
 int br_add_if(struct net_bridge *br, struct net_device *dev,
              struct netlink_ext_ack *extack);
 int br_del_if(struct net_bridge *br, struct net_device *dev);
-int br_mtu(const struct net_bridge *br, bool max);
+void br_mtu_auto_adjust(struct net_bridge *br);
 netdev_features_t br_features_recompute(struct net_bridge *br,
                                        netdev_features_t features);
 void br_port_flags_change(struct net_bridge_port *port, unsigned long mask);