|
|
@@ -29,6 +29,33 @@
|
|
|
|
|
|
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));
|