#ifndef __DSA_PRIV_H
 #define __DSA_PRIV_H
 
+#include <linux/if_bridge.h>
 #include <linux/phy.h>
 #include <linux/netdevice.h>
 #include <linux/netpoll.h>
        return dp->cpu_dp->master;
 }
 
+/* If under a bridge with vlan_filtering=0, make sure to send pvid-tagged
+ * frames as untagged, since the bridge will not untag them.
+ */
+static inline struct sk_buff *dsa_untag_bridge_pvid(struct sk_buff *skb)
+{
+       struct dsa_port *dp = dsa_slave_to_port(skb->dev);
+       struct vlan_ethhdr *hdr = vlan_eth_hdr(skb);
+       struct net_device *br = dp->bridge_dev;
+       struct net_device *dev = skb->dev;
+       struct net_device *upper_dev;
+       struct list_head *iter;
+       u16 vid, pvid, proto;
+       int err;
+
+       if (!br || br_vlan_enabled(br))
+               return skb;
+
+       err = br_vlan_get_proto(br, &proto);
+       if (err)
+               return skb;
+
+       /* Move VLAN tag from data to hwaccel */
+       if (!skb_vlan_tag_present(skb) && hdr->h_vlan_proto == htons(proto)) {
+               skb = skb_vlan_untag(skb);
+               if (!skb)
+                       return NULL;
+       }
+
+       if (!skb_vlan_tag_present(skb))
+               return skb;
+
+       vid = skb_vlan_tag_get_id(skb);
+
+       /* We already run under an RCU read-side critical section since
+        * we are called from netif_receive_skb_list_internal().
+        */
+       err = br_vlan_get_pvid_rcu(dev, &pvid);
+       if (err)
+               return skb;
+
+       if (vid != pvid)
+               return skb;
+
+       /* The sad part about attempting to untag from DSA is that we
+        * don't know, unless we check, if the skb will end up in
+        * the bridge's data path - br_allowed_ingress() - or not.
+        * For example, there might be an 8021q upper for the
+        * default_pvid of the bridge, which will steal VLAN-tagged traffic
+        * from the bridge's data path. This is a configuration that DSA
+        * supports because vlan_filtering is 0. In that case, we should
+        * definitely keep the tag, to make sure it keeps working.
+        */
+       netdev_for_each_upper_dev_rcu(dev, upper_dev, iter) {
+               if (!is_vlan_dev(upper_dev))
+                       continue;
+
+               if (vid == vlan_dev_vlan_id(upper_dev))
+                       return skb;
+       }
+
+       __vlan_hwaccel_clear_tag(skb);
+
+       return skb;
+}
+
 /* switch.c */
 int dsa_switch_register_notifier(struct dsa_switch *ds);
 void dsa_switch_unregister_notifier(struct dsa_switch *ds);