enum sja1105_vlan_state state;
        struct sja1105_table *table;
        struct sja1105_rule *rule;
+       bool want_tagging;
        u16 tpid, tpid2;
        int rc;
 
 
        if (!enabled)
                state = SJA1105_VLAN_UNAWARE;
+       else if (priv->best_effort_vlan_filtering)
+               state = SJA1105_VLAN_BEST_EFFORT;
        else
                state = SJA1105_VLAN_FILTERING_FULL;
 
                return 0;
 
        priv->vlan_state = state;
+       want_tagging = (state == SJA1105_VLAN_UNAWARE ||
+                       state == SJA1105_VLAN_BEST_EFFORT);
 
        table = &priv->static_config.tables[BLK_IDX_GENERAL_PARAMS];
        general_params = table->entries;
        general_params->incl_srcpt1 = enabled;
        general_params->incl_srcpt0 = enabled;
 
+       want_tagging = priv->best_effort_vlan_filtering || !enabled;
+
        /* VLAN filtering => independent VLAN learning.
-        * No VLAN filtering => shared VLAN learning.
+        * No VLAN filtering (or best effort) => shared VLAN learning.
         *
         * In shared VLAN learning mode, untagged traffic still gets
         * pvid-tagged, and the FDB table gets populated with entries
         */
        table = &priv->static_config.tables[BLK_IDX_L2_LOOKUP_PARAMS];
        l2_lookup_params = table->entries;
-       l2_lookup_params->shared_learn = !enabled;
+       l2_lookup_params->shared_learn = want_tagging;
 
        rc = sja1105_static_config_reload(priv, SJA1105_VLAN_FILTERING);
        if (rc)
 
        /* Switch port identification based on 802.1Q is only passable
         * if we are not under a vlan_filtering bridge. So make sure
-        * the two configurations are mutually exclusive.
+        * the two configurations are mutually exclusive (of course, the
+        * user may know better, i.e. best_effort_vlan_filtering).
         */
-       return sja1105_setup_8021q_tagging(ds, !enabled);
+       return sja1105_setup_8021q_tagging(ds, want_tagging);
 }
 
 static void sja1105_vlan_add(struct dsa_switch *ds, int port,
        return sja1105_build_vlan_table(priv, true);
 }
 
+static int sja1105_best_effort_vlan_filtering_get(struct sja1105_private *priv,
+                                                 bool *be_vlan)
+{
+       *be_vlan = priv->best_effort_vlan_filtering;
+
+       return 0;
+}
+
+static int sja1105_best_effort_vlan_filtering_set(struct sja1105_private *priv,
+                                                 bool be_vlan)
+{
+       struct dsa_switch *ds = priv->ds;
+       bool vlan_filtering;
+       int port;
+       int rc;
+
+       priv->best_effort_vlan_filtering = be_vlan;
+
+       rtnl_lock();
+       for (port = 0; port < ds->num_ports; port++) {
+               struct dsa_port *dp;
+
+               if (!dsa_is_user_port(ds, port))
+                       continue;
+
+               dp = dsa_to_port(ds, port);
+               vlan_filtering = dsa_port_is_vlan_filtering(dp);
+
+               rc = sja1105_vlan_filtering(ds, port, vlan_filtering);
+               if (rc)
+                       break;
+       }
+       rtnl_unlock();
+
+       return rc;
+}
+
+enum sja1105_devlink_param_id {
+       SJA1105_DEVLINK_PARAM_ID_BASE = DEVLINK_PARAM_GENERIC_ID_MAX,
+       SJA1105_DEVLINK_PARAM_ID_BEST_EFFORT_VLAN_FILTERING,
+};
+
+static int sja1105_devlink_param_get(struct dsa_switch *ds, u32 id,
+                                    struct devlink_param_gset_ctx *ctx)
+{
+       struct sja1105_private *priv = ds->priv;
+       int err;
+
+       switch (id) {
+       case SJA1105_DEVLINK_PARAM_ID_BEST_EFFORT_VLAN_FILTERING:
+               err = sja1105_best_effort_vlan_filtering_get(priv,
+                                                            &ctx->val.vbool);
+               break;
+       default:
+               err = -EOPNOTSUPP;
+               break;
+       }
+
+       return err;
+}
+
+static int sja1105_devlink_param_set(struct dsa_switch *ds, u32 id,
+                                    struct devlink_param_gset_ctx *ctx)
+{
+       struct sja1105_private *priv = ds->priv;
+       int err;
+
+       switch (id) {
+       case SJA1105_DEVLINK_PARAM_ID_BEST_EFFORT_VLAN_FILTERING:
+               err = sja1105_best_effort_vlan_filtering_set(priv,
+                                                            ctx->val.vbool);
+               break;
+       default:
+               err = -EOPNOTSUPP;
+               break;
+       }
+
+       return err;
+}
+
+static const struct devlink_param sja1105_devlink_params[] = {
+       DSA_DEVLINK_PARAM_DRIVER(SJA1105_DEVLINK_PARAM_ID_BEST_EFFORT_VLAN_FILTERING,
+                                "best_effort_vlan_filtering",
+                                DEVLINK_PARAM_TYPE_BOOL,
+                                BIT(DEVLINK_PARAM_CMODE_RUNTIME)),
+};
+
+static int sja1105_setup_devlink_params(struct dsa_switch *ds)
+{
+       return dsa_devlink_params_register(ds, sja1105_devlink_params,
+                                          ARRAY_SIZE(sja1105_devlink_params));
+}
+
+static void sja1105_teardown_devlink_params(struct dsa_switch *ds)
+{
+       dsa_devlink_params_unregister(ds, sja1105_devlink_params,
+                                     ARRAY_SIZE(sja1105_devlink_params));
+}
+
 /* The programming model for the SJA1105 switch is "all-at-once" via static
  * configuration tables. Some of these can be dynamically modified at runtime,
  * but not the xMII mode parameters table.
 
        ds->configure_vlan_while_not_filtering = true;
 
+       rc = sja1105_setup_devlink_params(ds);
+       if (rc < 0)
+               return rc;
+
        /* The DSA/switchdev model brings up switch ports in standalone mode by
         * default, and that means vlan_filtering is 0 since they're not under
         * a bridge, so it's safe to set up switch tagging at this time.
                        kthread_destroy_worker(sp->xmit_worker);
        }
 
+       sja1105_teardown_devlink_params(ds);
        sja1105_flower_teardown(ds);
        sja1105_tas_teardown(ds);
        sja1105_ptp_clock_unregister(ds);
        .cls_flower_stats       = sja1105_cls_flower_stats,
        .crosschip_bridge_join  = sja1105_crosschip_bridge_join,
        .crosschip_bridge_leave = sja1105_crosschip_bridge_leave,
+       .devlink_param_get      = sja1105_devlink_param_get,
+       .devlink_param_set      = sja1105_devlink_param_set,
 };
 
 static int sja1105_check_device_id(struct sja1105_private *priv)