net: dsa: Refactor selection of tag ops into a function
authorAndrew Lunn <andrew@lunn.ch>
Sat, 4 Jun 2016 19:17:03 +0000 (21:17 +0200)
committerDavid S. Miller <davem@davemloft.net>
Sat, 4 Jun 2016 21:29:54 +0000 (14:29 -0700)
Replace the two switch statements with an array lookup, and store the
result in the dsa tree structure. The drivers no longer need to know
the selected tag protocol, so remove it from the dsa switch structure.

Signed-off-by: Andrew Lunn <andrew@lunn.ch>
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
Reviewed-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/net/dsa.h
net/dsa/dsa.c
net/dsa/dsa_priv.h
net/dsa/slave.c

index b666f27b3daa38bb1ad864cb49ae0f524472d229..bd6ecaa0de960ea2951253e74355ecc4c1198800 100644 (file)
@@ -26,6 +26,7 @@ enum dsa_tag_protocol {
        DSA_TAG_PROTO_TRAILER,
        DSA_TAG_PROTO_EDSA,
        DSA_TAG_PROTO_BRCM,
+       DSA_TAG_LAST,           /* MUST BE LAST */
 };
 
 #define DSA_MAX_SWITCHES       4
@@ -99,7 +100,6 @@ struct dsa_switch_tree {
                                       struct net_device *dev,
                                       struct packet_type *pt,
                                       struct net_device *orig_dev);
-       enum dsa_tag_protocol   tag_protocol;
 
        /*
         * Original copy of the master netdev ethtool_ops
@@ -116,6 +116,12 @@ struct dsa_switch_tree {
         * Data for the individual switch chips.
         */
        struct dsa_switch       *ds[DSA_MAX_SWITCHES];
+
+       /*
+        * Tagging protocol operations for adding and removing an
+        * encapsulation tag.
+        */
+       const struct dsa_device_ops *tag_ops;
 };
 
 struct dsa_port {
index 7140de475c07736030c491b524e00303af08e064..221ebde4318d6826c3e99dcc928fb4b92379ada2 100644 (file)
 
 char dsa_driver_version[] = "0.1";
 
+static struct sk_buff *dsa_slave_notag_xmit(struct sk_buff *skb,
+                                           struct net_device *dev)
+{
+       /* Just return the original SKB */
+       return skb;
+}
+
+static const struct dsa_device_ops none_ops = {
+       .xmit   = dsa_slave_notag_xmit,
+       .rcv    = NULL,
+};
+
+const struct dsa_device_ops *dsa_device_ops[DSA_TAG_LAST] = {
+#ifdef CONFIG_NET_DSA_TAG_DSA
+       [DSA_TAG_PROTO_DSA] = &dsa_netdev_ops,
+#endif
+#ifdef CONFIG_NET_DSA_TAG_EDSA
+       [DSA_TAG_PROTO_EDSA] = &edsa_netdev_ops,
+#endif
+#ifdef CONFIG_NET_DSA_TAG_TRAILER
+       [DSA_TAG_PROTO_TRAILER] = &trailer_netdev_ops,
+#endif
+#ifdef CONFIG_NET_DSA_TAG_BRCM
+       [DSA_TAG_PROTO_BRCM] = &brcm_netdev_ops,
+#endif
+       [DSA_TAG_PROTO_NONE] = &none_ops,
+};
 
 /* switch driver registration ***********************************************/
 static DEFINE_MUTEX(dsa_switch_drivers_mutex);
@@ -225,6 +252,20 @@ static int dsa_cpu_dsa_setups(struct dsa_switch *ds, struct device *dev)
        return 0;
 }
 
+const struct dsa_device_ops *dsa_resolve_tag_protocol(int tag_protocol)
+{
+       const struct dsa_device_ops *ops;
+
+       if (tag_protocol >= DSA_TAG_LAST)
+               return ERR_PTR(-EINVAL);
+       ops = dsa_device_ops[tag_protocol];
+
+       if (!ops)
+               return ERR_PTR(-ENOPROTOOPT);
+
+       return ops;
+}
+
 static int dsa_switch_setup_one(struct dsa_switch *ds, struct device *parent)
 {
        struct dsa_switch_driver *drv = ds->drv;
@@ -277,35 +318,13 @@ static int dsa_switch_setup_one(struct dsa_switch *ds, struct device *parent)
         * switch.
         */
        if (dst->cpu_switch == index) {
-               switch (drv->tag_protocol) {
-#ifdef CONFIG_NET_DSA_TAG_DSA
-               case DSA_TAG_PROTO_DSA:
-                       dst->rcv = dsa_netdev_ops.rcv;
-                       break;
-#endif
-#ifdef CONFIG_NET_DSA_TAG_EDSA
-               case DSA_TAG_PROTO_EDSA:
-                       dst->rcv = edsa_netdev_ops.rcv;
-                       break;
-#endif
-#ifdef CONFIG_NET_DSA_TAG_TRAILER
-               case DSA_TAG_PROTO_TRAILER:
-                       dst->rcv = trailer_netdev_ops.rcv;
-                       break;
-#endif
-#ifdef CONFIG_NET_DSA_TAG_BRCM
-               case DSA_TAG_PROTO_BRCM:
-                       dst->rcv = brcm_netdev_ops.rcv;
-                       break;
-#endif
-               case DSA_TAG_PROTO_NONE:
-                       break;
-               default:
-                       ret = -ENOPROTOOPT;
+               dst->tag_ops = dsa_resolve_tag_protocol(drv->tag_protocol);
+               if (IS_ERR(dst->tag_ops)) {
+                       ret = PTR_ERR(dst->tag_ops);
                        goto out;
                }
 
-               dst->tag_protocol = drv->tag_protocol;
+               dst->rcv = dst->tag_ops->rcv;
        }
 
        memcpy(ds->rtable, cd->rtable, sizeof(ds->rtable));
index dbea5d9e7f75f900a33cbc8b74c465562e13a632..72f7b8989cfb2e3224a036d569f920a508ae5803 100644 (file)
@@ -53,6 +53,7 @@ extern char dsa_driver_version[];
 int dsa_cpu_dsa_setup(struct dsa_switch *ds, struct device *dev,
                      struct device_node *port_dn, int port);
 void dsa_cpu_dsa_destroy(struct device_node *port_dn);
+const struct dsa_device_ops *dsa_resolve_tag_protocol(int tag_protocol);
 
 /* slave.c */
 extern const struct dsa_device_ops notag_netdev_ops;
index 52f1183c42a03362ad54bd1729e0c3b2e1e66cf7..35e5f0f6688be098ae96c2829584c162c5b49c06 100644 (file)
@@ -521,14 +521,6 @@ static netdev_tx_t dsa_slave_xmit(struct sk_buff *skb, struct net_device *dev)
        return NETDEV_TX_OK;
 }
 
-static struct sk_buff *dsa_slave_notag_xmit(struct sk_buff *skb,
-                                           struct net_device *dev)
-{
-       /* Just return the original SKB */
-       return skb;
-}
-
-
 /* ethtool operations *******************************************************/
 static int
 dsa_slave_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
@@ -1151,32 +1143,7 @@ int dsa_slave_create(struct dsa_switch *ds, struct device *parent,
        p = netdev_priv(slave_dev);
        p->parent = ds;
        p->port = port;
-
-       switch (ds->dst->tag_protocol) {
-#ifdef CONFIG_NET_DSA_TAG_DSA
-       case DSA_TAG_PROTO_DSA:
-               p->xmit = dsa_netdev_ops.xmit;
-               break;
-#endif
-#ifdef CONFIG_NET_DSA_TAG_EDSA
-       case DSA_TAG_PROTO_EDSA:
-               p->xmit = edsa_netdev_ops.xmit;
-               break;
-#endif
-#ifdef CONFIG_NET_DSA_TAG_TRAILER
-       case DSA_TAG_PROTO_TRAILER:
-               p->xmit = trailer_netdev_ops.xmit;
-               break;
-#endif
-#ifdef CONFIG_NET_DSA_TAG_BRCM
-       case DSA_TAG_PROTO_BRCM:
-               p->xmit = brcm_netdev_ops.xmit;
-               break;
-#endif
-       default:
-               p->xmit = dsa_slave_notag_xmit;
-               break;
-       }
+       p->xmit = dst->tag_ops->xmit;
 
        p->old_pause = -1;
        p->old_link = -1;