net: dsa: allow switches to work without tagging
authorFlorian Fainelli <f.fainelli@gmail.com>
Thu, 28 Aug 2014 00:04:52 +0000 (17:04 -0700)
committerDavid S. Miller <davem@davemloft.net>
Thu, 28 Aug 2014 05:59:40 +0000 (22:59 -0700)
In case switch port tagging is disabled (voluntarily, or the switch just
does not support it), allow us to continue using the defined set of
dsa_device_ops in net/dsa/slave.c.

We introduce dsa_protocol_is_tagged() to check whether we need to
override skb->protocol and go through the DSA-specifif packet_type
function, or if we just go on and receive the SKB through the normal
path.

Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/linux/netdevice.h
include/net/dsa.h
net/dsa/slave.c

index 1875dc71422ab99ae6b6ed651ba48c64724000f2..429801370d0c45c677f0cd9667cc07d17f531490 100644 (file)
@@ -1784,10 +1784,10 @@ void dev_net_set(struct net_device *dev, struct net *net)
 static inline bool netdev_uses_dsa(struct net_device *dev)
 {
 #ifdef CONFIG_NET_DSA
-       return dev->dsa_ptr != NULL;
-#else
-       return false;
+       if (dev->dsa_ptr != NULL)
+               return dsa_uses_tagged_protocol(dev->dsa_ptr);
 #endif
+       return false;
 }
 
 /**
index dc357454ae3b82e0f049e2681f0d169bde409e96..1035f6452d7931ce8ca1e388f47b49137936721f 100644 (file)
@@ -198,4 +198,9 @@ static inline void *ds_to_priv(struct dsa_switch *ds)
        return (void *)(ds + 1);
 }
 
+static inline bool dsa_uses_tagged_protocol(struct dsa_switch_tree *dst)
+{
+       return dst->tag_protocol != 0;
+}
+
 #endif
index 03d2894a0f8aca6eddd98ce11530afb26105a243..241c2a1684cbb120ac62ae6d96f084cc1a5654ff 100644 (file)
@@ -181,6 +181,17 @@ static netdev_tx_t dsa_slave_xmit(struct sk_buff *skb, struct net_device *dev)
        return dst->ops->xmit(skb, dev);
 }
 
+static netdev_tx_t dsa_slave_notag_xmit(struct sk_buff *skb,
+                                       struct net_device *dev)
+{
+       struct dsa_slave_priv *p = netdev_priv(dev);
+
+       skb->dev = p->parent->dst->master_netdev;
+       dev_queue_xmit(skb);
+
+       return NETDEV_TX_OK;
+}
+
 
 /* ethtool operations *******************************************************/
 static int
@@ -314,6 +325,11 @@ static const struct net_device_ops dsa_slave_netdev_ops = {
        .ndo_do_ioctl           = dsa_slave_ioctl,
 };
 
+static const struct dsa_device_ops notag_netdev_ops = {
+       .xmit   = dsa_slave_notag_xmit,
+       .rcv    = NULL,
+};
+
 static void dsa_slave_adjust_link(struct net_device *dev)
 {
        struct dsa_slave_priv *p = netdev_priv(dev);
@@ -415,7 +431,8 @@ dsa_slave_create(struct dsa_switch *ds, struct device *parent,
                break;
 #endif
        default:
-               BUG();
+               ds->dst->ops = &notag_netdev_ops;
+               break;
        }
 
        SET_NETDEV_DEV(slave_dev, parent);