Commit 4e500251 authored by Vladimir Oltean's avatar Vladimir Oltean Committed by David S. Miller

net: dsa: generalize overhead for taggers that use both headers and trailers

Some really really weird switches just couldn't decide whether to use a
normal or a tail tagger, so they just did both.

This creates problems for DSA, because we only have the concept of an
'overhead' which can be applied to the headroom or to the tailroom of
the skb (like for example during the central TX reallocation procedure),
depending on the value of bool tail_tag, but not to both.

We need to generalize DSA to cater for these odd switches by
transforming the 'overhead / tail_tag' pair into 'needed_headroom /
needed_tailroom'.

The DSA master's MTU is increased to account for both.

The flow dissector code is modified such that it only calls the DSA
adjustment callback if the tagger has a non-zero header length.

Taggers are trivially modified to declare either needed_headroom or
needed_tailroom, based on the tail_tag value that they currently
declare.
Signed-off-by: default avatarVladimir Oltean <vladimir.oltean@nxp.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 6c0de59b
...@@ -93,14 +93,15 @@ A tagging protocol may tag all packets with switch tags of the same length, or ...@@ -93,14 +93,15 @@ A tagging protocol may tag all packets with switch tags of the same length, or
the tag length might vary (for example packets with PTP timestamps might the tag length might vary (for example packets with PTP timestamps might
require an extended switch tag, or there might be one tag length on TX and a require an extended switch tag, or there might be one tag length on TX and a
different one on RX). Either way, the tagging protocol driver must populate the different one on RX). Either way, the tagging protocol driver must populate the
``struct dsa_device_ops::overhead`` with the length in octets of the longest ``struct dsa_device_ops::needed_headroom`` and/or ``struct dsa_device_ops::needed_tailroom``
switch frame header. The DSA framework will automatically adjust the MTU of the with the length in octets of the longest switch frame header/trailer. The DSA
master interface to accomodate for this extra size in order for DSA user ports framework will automatically adjust the MTU of the master interface to
to support the standard MTU (L2 payload length) of 1500 octets. The ``overhead`` accommodate for this extra size in order for DSA user ports to support the
is also used to request from the network stack, on a best-effort basis, the standard MTU (L2 payload length) of 1500 octets. The ``needed_headroom`` and
allocation of packets with a ``needed_headroom`` or ``needed_tailroom`` ``needed_tailroom`` properties are also used to request from the network stack,
sufficient such that the act of pushing the switch tag on transmission of a on a best-effort basis, the allocation of packets with enough extra space such
packet does not cause it to reallocate due to lack of memory. that the act of pushing the switch tag on transmission of a packet does not
cause it to reallocate due to lack of memory.
Even though applications are not expected to parse DSA-specific frame headers, Even though applications are not expected to parse DSA-specific frame headers,
the format on the wire of the tagging protocol represents an Application Binary the format on the wire of the tagging protocol represents an Application Binary
...@@ -169,8 +170,8 @@ The job of this method is to prepare the skb in a way that the switch will ...@@ -169,8 +170,8 @@ The job of this method is to prepare the skb in a way that the switch will
understand what egress port the packet is for (and not deliver it towards other understand what egress port the packet is for (and not deliver it towards other
ports). Typically this is fulfilled by pushing a frame header. Checking for ports). Typically this is fulfilled by pushing a frame header. Checking for
insufficient size in the skb headroom or tailroom is unnecessary provided that insufficient size in the skb headroom or tailroom is unnecessary provided that
the ``overhead`` and ``tail_tag`` properties were filled out properly, because the ``needed_headroom`` and ``needed_tailroom`` properties were filled out
DSA ensures there is enough space before calling this method. properly, because DSA ensures there is enough space before calling this method.
The reception of a packet goes through the tagger's ``rcv`` function. The The reception of a packet goes through the tagger's ``rcv`` function. The
passed ``struct sk_buff *skb`` has ``skb->data`` pointing at passed ``struct sk_buff *skb`` has ``skb->data`` pointing at
......
...@@ -91,7 +91,8 @@ struct dsa_device_ops { ...@@ -91,7 +91,8 @@ struct dsa_device_ops {
* as regular on the master net device. * as regular on the master net device.
*/ */
bool (*filter)(const struct sk_buff *skb, struct net_device *dev); bool (*filter)(const struct sk_buff *skb, struct net_device *dev);
unsigned int overhead; unsigned int needed_headroom;
unsigned int needed_tailroom;
const char *name; const char *name;
enum dsa_tag_protocol proto; enum dsa_tag_protocol proto;
/* Some tagging protocols either mangle or shift the destination MAC /* Some tagging protocols either mangle or shift the destination MAC
...@@ -100,7 +101,6 @@ struct dsa_device_ops { ...@@ -100,7 +101,6 @@ struct dsa_device_ops {
* its RX filter. * its RX filter.
*/ */
bool promisc_on_master; bool promisc_on_master;
bool tail_tag;
}; };
/* This structure defines the control interfaces that are overlayed by the /* This structure defines the control interfaces that are overlayed by the
...@@ -926,7 +926,7 @@ static inline void dsa_tag_generic_flow_dissect(const struct sk_buff *skb, ...@@ -926,7 +926,7 @@ static inline void dsa_tag_generic_flow_dissect(const struct sk_buff *skb,
{ {
#if IS_ENABLED(CONFIG_NET_DSA) #if IS_ENABLED(CONFIG_NET_DSA)
const struct dsa_device_ops *ops = skb->dev->dsa_ptr->tag_ops; const struct dsa_device_ops *ops = skb->dev->dsa_ptr->tag_ops;
int tag_len = ops->overhead; int tag_len = ops->needed_headroom;
*offset = tag_len; *offset = tag_len;
*proto = ((__be16 *)skb->data)[(tag_len / 2) - 1]; *proto = ((__be16 *)skb->data)[(tag_len / 2) - 1];
......
...@@ -944,7 +944,7 @@ bool __skb_flow_dissect(const struct net *net, ...@@ -944,7 +944,7 @@ bool __skb_flow_dissect(const struct net *net,
ops = skb->dev->dsa_ptr->tag_ops; ops = skb->dev->dsa_ptr->tag_ops;
/* Tail taggers don't break flow dissection */ /* Tail taggers don't break flow dissection */
if (!ops->tail_tag) { if (!ops->needed_headroom) {
if (ops->flow_dissect) if (ops->flow_dissect)
ops->flow_dissect(skb, &proto, &offset); ops->flow_dissect(skb, &proto, &offset);
else else
......
...@@ -154,6 +154,11 @@ const struct dsa_device_ops *dsa_find_tagger_by_name(const char *buf); ...@@ -154,6 +154,11 @@ const struct dsa_device_ops *dsa_find_tagger_by_name(const char *buf);
bool dsa_schedule_work(struct work_struct *work); bool dsa_schedule_work(struct work_struct *work);
const char *dsa_tag_protocol_to_str(const struct dsa_device_ops *ops); const char *dsa_tag_protocol_to_str(const struct dsa_device_ops *ops);
static inline int dsa_tag_protocol_overhead(const struct dsa_device_ops *ops)
{
return ops->needed_headroom + ops->needed_tailroom;
}
/* master.c */ /* master.c */
int dsa_master_setup(struct net_device *dev, struct dsa_port *cpu_dp); int dsa_master_setup(struct net_device *dev, struct dsa_port *cpu_dp);
void dsa_master_teardown(struct net_device *dev); void dsa_master_teardown(struct net_device *dev);
......
...@@ -346,10 +346,12 @@ static struct lock_class_key dsa_master_addr_list_lock_key; ...@@ -346,10 +346,12 @@ static struct lock_class_key dsa_master_addr_list_lock_key;
int dsa_master_setup(struct net_device *dev, struct dsa_port *cpu_dp) int dsa_master_setup(struct net_device *dev, struct dsa_port *cpu_dp)
{ {
int mtu = ETH_DATA_LEN + cpu_dp->tag_ops->overhead; const struct dsa_device_ops *tag_ops = cpu_dp->tag_ops;
struct dsa_switch *ds = cpu_dp->ds; struct dsa_switch *ds = cpu_dp->ds;
struct device_link *consumer_link; struct device_link *consumer_link;
int ret; int mtu, ret;
mtu = ETH_DATA_LEN + dsa_tag_protocol_overhead(tag_ops);
/* The DSA master must use SET_NETDEV_DEV for this to work. */ /* The DSA master must use SET_NETDEV_DEV for this to work. */
consumer_link = device_link_add(ds->dev, dev->dev.parent, consumer_link = device_link_add(ds->dev, dev->dev.parent,
......
...@@ -1569,7 +1569,7 @@ int dsa_slave_change_mtu(struct net_device *dev, int new_mtu) ...@@ -1569,7 +1569,7 @@ int dsa_slave_change_mtu(struct net_device *dev, int new_mtu)
mtu_limit = min_t(int, master->max_mtu, dev->max_mtu); mtu_limit = min_t(int, master->max_mtu, dev->max_mtu);
old_master_mtu = master->mtu; old_master_mtu = master->mtu;
new_master_mtu = largest_mtu + cpu_dp->tag_ops->overhead; new_master_mtu = largest_mtu + dsa_tag_protocol_overhead(cpu_dp->tag_ops);
if (new_master_mtu > mtu_limit) if (new_master_mtu > mtu_limit)
return -ERANGE; return -ERANGE;
...@@ -1605,7 +1605,7 @@ int dsa_slave_change_mtu(struct net_device *dev, int new_mtu) ...@@ -1605,7 +1605,7 @@ int dsa_slave_change_mtu(struct net_device *dev, int new_mtu)
out_port_failed: out_port_failed:
if (new_master_mtu != old_master_mtu) if (new_master_mtu != old_master_mtu)
dsa_port_mtu_change(cpu_dp, old_master_mtu - dsa_port_mtu_change(cpu_dp, old_master_mtu -
cpu_dp->tag_ops->overhead, dsa_tag_protocol_overhead(cpu_dp->tag_ops),
true); true);
out_cpu_failed: out_cpu_failed:
if (new_master_mtu != old_master_mtu) if (new_master_mtu != old_master_mtu)
...@@ -1824,10 +1824,8 @@ void dsa_slave_setup_tagger(struct net_device *slave) ...@@ -1824,10 +1824,8 @@ void dsa_slave_setup_tagger(struct net_device *slave)
const struct dsa_port *cpu_dp = dp->cpu_dp; const struct dsa_port *cpu_dp = dp->cpu_dp;
struct net_device *master = cpu_dp->master; struct net_device *master = cpu_dp->master;
if (cpu_dp->tag_ops->tail_tag) slave->needed_headroom = cpu_dp->tag_ops->needed_headroom;
slave->needed_tailroom = cpu_dp->tag_ops->overhead; slave->needed_tailroom = cpu_dp->tag_ops->needed_tailroom;
else
slave->needed_headroom = cpu_dp->tag_ops->overhead;
/* Try to save one extra realloc later in the TX path (in the master) /* Try to save one extra realloc later in the TX path (in the master)
* by also inheriting the master's needed headroom and tailroom. * by also inheriting the master's needed headroom and tailroom.
* The 8021q driver also does this. * The 8021q driver also does this.
......
...@@ -85,7 +85,7 @@ static const struct dsa_device_ops ar9331_netdev_ops = { ...@@ -85,7 +85,7 @@ static const struct dsa_device_ops ar9331_netdev_ops = {
.proto = DSA_TAG_PROTO_AR9331, .proto = DSA_TAG_PROTO_AR9331,
.xmit = ar9331_tag_xmit, .xmit = ar9331_tag_xmit,
.rcv = ar9331_tag_rcv, .rcv = ar9331_tag_rcv,
.overhead = AR9331_HDR_LEN, .needed_headroom = AR9331_HDR_LEN,
}; };
MODULE_LICENSE("GPL v2"); MODULE_LICENSE("GPL v2");
......
...@@ -205,7 +205,7 @@ static const struct dsa_device_ops brcm_netdev_ops = { ...@@ -205,7 +205,7 @@ static const struct dsa_device_ops brcm_netdev_ops = {
.proto = DSA_TAG_PROTO_BRCM, .proto = DSA_TAG_PROTO_BRCM,
.xmit = brcm_tag_xmit, .xmit = brcm_tag_xmit,
.rcv = brcm_tag_rcv, .rcv = brcm_tag_rcv,
.overhead = BRCM_TAG_LEN, .needed_headroom = BRCM_TAG_LEN,
}; };
DSA_TAG_DRIVER(brcm_netdev_ops); DSA_TAG_DRIVER(brcm_netdev_ops);
...@@ -286,7 +286,7 @@ static const struct dsa_device_ops brcm_legacy_netdev_ops = { ...@@ -286,7 +286,7 @@ static const struct dsa_device_ops brcm_legacy_netdev_ops = {
.proto = DSA_TAG_PROTO_BRCM_LEGACY, .proto = DSA_TAG_PROTO_BRCM_LEGACY,
.xmit = brcm_leg_tag_xmit, .xmit = brcm_leg_tag_xmit,
.rcv = brcm_leg_tag_rcv, .rcv = brcm_leg_tag_rcv,
.overhead = BRCM_LEG_TAG_LEN, .needed_headroom = BRCM_LEG_TAG_LEN,
}; };
DSA_TAG_DRIVER(brcm_legacy_netdev_ops); DSA_TAG_DRIVER(brcm_legacy_netdev_ops);
...@@ -314,7 +314,7 @@ static const struct dsa_device_ops brcm_prepend_netdev_ops = { ...@@ -314,7 +314,7 @@ static const struct dsa_device_ops brcm_prepend_netdev_ops = {
.proto = DSA_TAG_PROTO_BRCM_PREPEND, .proto = DSA_TAG_PROTO_BRCM_PREPEND,
.xmit = brcm_tag_xmit_prepend, .xmit = brcm_tag_xmit_prepend,
.rcv = brcm_tag_rcv_prepend, .rcv = brcm_tag_rcv_prepend,
.overhead = BRCM_TAG_LEN, .needed_headroom = BRCM_TAG_LEN,
}; };
DSA_TAG_DRIVER(brcm_prepend_netdev_ops); DSA_TAG_DRIVER(brcm_prepend_netdev_ops);
......
...@@ -303,7 +303,7 @@ static const struct dsa_device_ops dsa_netdev_ops = { ...@@ -303,7 +303,7 @@ static const struct dsa_device_ops dsa_netdev_ops = {
.proto = DSA_TAG_PROTO_DSA, .proto = DSA_TAG_PROTO_DSA,
.xmit = dsa_xmit, .xmit = dsa_xmit,
.rcv = dsa_rcv, .rcv = dsa_rcv,
.overhead = DSA_HLEN, .needed_headroom = DSA_HLEN,
}; };
DSA_TAG_DRIVER(dsa_netdev_ops); DSA_TAG_DRIVER(dsa_netdev_ops);
...@@ -346,7 +346,7 @@ static const struct dsa_device_ops edsa_netdev_ops = { ...@@ -346,7 +346,7 @@ static const struct dsa_device_ops edsa_netdev_ops = {
.proto = DSA_TAG_PROTO_EDSA, .proto = DSA_TAG_PROTO_EDSA,
.xmit = edsa_xmit, .xmit = edsa_xmit,
.rcv = edsa_rcv, .rcv = edsa_rcv,
.overhead = EDSA_HLEN, .needed_headroom = EDSA_HLEN,
}; };
DSA_TAG_DRIVER(edsa_netdev_ops); DSA_TAG_DRIVER(edsa_netdev_ops);
......
...@@ -103,7 +103,7 @@ static const struct dsa_device_ops gswip_netdev_ops = { ...@@ -103,7 +103,7 @@ static const struct dsa_device_ops gswip_netdev_ops = {
.proto = DSA_TAG_PROTO_GSWIP, .proto = DSA_TAG_PROTO_GSWIP,
.xmit = gswip_tag_xmit, .xmit = gswip_tag_xmit,
.rcv = gswip_tag_rcv, .rcv = gswip_tag_rcv,
.overhead = GSWIP_RX_HEADER_LEN, .needed_headroom = GSWIP_RX_HEADER_LEN,
}; };
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
......
...@@ -54,8 +54,7 @@ static const struct dsa_device_ops hellcreek_netdev_ops = { ...@@ -54,8 +54,7 @@ static const struct dsa_device_ops hellcreek_netdev_ops = {
.proto = DSA_TAG_PROTO_HELLCREEK, .proto = DSA_TAG_PROTO_HELLCREEK,
.xmit = hellcreek_xmit, .xmit = hellcreek_xmit,
.rcv = hellcreek_rcv, .rcv = hellcreek_rcv,
.overhead = HELLCREEK_TAG_LEN, .needed_tailroom = HELLCREEK_TAG_LEN,
.tail_tag = true,
}; };
MODULE_LICENSE("Dual MIT/GPL"); MODULE_LICENSE("Dual MIT/GPL");
......
...@@ -77,8 +77,7 @@ static const struct dsa_device_ops ksz8795_netdev_ops = { ...@@ -77,8 +77,7 @@ static const struct dsa_device_ops ksz8795_netdev_ops = {
.proto = DSA_TAG_PROTO_KSZ8795, .proto = DSA_TAG_PROTO_KSZ8795,
.xmit = ksz8795_xmit, .xmit = ksz8795_xmit,
.rcv = ksz8795_rcv, .rcv = ksz8795_rcv,
.overhead = KSZ_INGRESS_TAG_LEN, .needed_tailroom = KSZ_INGRESS_TAG_LEN,
.tail_tag = true,
}; };
DSA_TAG_DRIVER(ksz8795_netdev_ops); DSA_TAG_DRIVER(ksz8795_netdev_ops);
...@@ -149,8 +148,7 @@ static const struct dsa_device_ops ksz9477_netdev_ops = { ...@@ -149,8 +148,7 @@ static const struct dsa_device_ops ksz9477_netdev_ops = {
.proto = DSA_TAG_PROTO_KSZ9477, .proto = DSA_TAG_PROTO_KSZ9477,
.xmit = ksz9477_xmit, .xmit = ksz9477_xmit,
.rcv = ksz9477_rcv, .rcv = ksz9477_rcv,
.overhead = KSZ9477_INGRESS_TAG_LEN, .needed_tailroom = KSZ9477_INGRESS_TAG_LEN,
.tail_tag = true,
}; };
DSA_TAG_DRIVER(ksz9477_netdev_ops); DSA_TAG_DRIVER(ksz9477_netdev_ops);
...@@ -183,8 +181,7 @@ static const struct dsa_device_ops ksz9893_netdev_ops = { ...@@ -183,8 +181,7 @@ static const struct dsa_device_ops ksz9893_netdev_ops = {
.proto = DSA_TAG_PROTO_KSZ9893, .proto = DSA_TAG_PROTO_KSZ9893,
.xmit = ksz9893_xmit, .xmit = ksz9893_xmit,
.rcv = ksz9477_rcv, .rcv = ksz9477_rcv,
.overhead = KSZ_INGRESS_TAG_LEN, .needed_tailroom = KSZ_INGRESS_TAG_LEN,
.tail_tag = true,
}; };
DSA_TAG_DRIVER(ksz9893_netdev_ops); DSA_TAG_DRIVER(ksz9893_netdev_ops);
......
...@@ -125,7 +125,7 @@ static const struct dsa_device_ops lan9303_netdev_ops = { ...@@ -125,7 +125,7 @@ static const struct dsa_device_ops lan9303_netdev_ops = {
.proto = DSA_TAG_PROTO_LAN9303, .proto = DSA_TAG_PROTO_LAN9303,
.xmit = lan9303_xmit, .xmit = lan9303_xmit,
.rcv = lan9303_rcv, .rcv = lan9303_rcv,
.overhead = LAN9303_TAG_LEN, .needed_headroom = LAN9303_TAG_LEN,
}; };
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
......
...@@ -102,7 +102,7 @@ static const struct dsa_device_ops mtk_netdev_ops = { ...@@ -102,7 +102,7 @@ static const struct dsa_device_ops mtk_netdev_ops = {
.proto = DSA_TAG_PROTO_MTK, .proto = DSA_TAG_PROTO_MTK,
.xmit = mtk_tag_xmit, .xmit = mtk_tag_xmit,
.rcv = mtk_tag_rcv, .rcv = mtk_tag_rcv,
.overhead = MTK_HDR_LEN, .needed_headroom = MTK_HDR_LEN,
}; };
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
......
...@@ -143,7 +143,7 @@ static const struct dsa_device_ops ocelot_netdev_ops = { ...@@ -143,7 +143,7 @@ static const struct dsa_device_ops ocelot_netdev_ops = {
.proto = DSA_TAG_PROTO_OCELOT, .proto = DSA_TAG_PROTO_OCELOT,
.xmit = ocelot_xmit, .xmit = ocelot_xmit,
.rcv = ocelot_rcv, .rcv = ocelot_rcv,
.overhead = OCELOT_TOTAL_TAG_LEN, .needed_headroom = OCELOT_TOTAL_TAG_LEN,
.promisc_on_master = true, .promisc_on_master = true,
}; };
...@@ -155,7 +155,7 @@ static const struct dsa_device_ops seville_netdev_ops = { ...@@ -155,7 +155,7 @@ static const struct dsa_device_ops seville_netdev_ops = {
.proto = DSA_TAG_PROTO_SEVILLE, .proto = DSA_TAG_PROTO_SEVILLE,
.xmit = seville_xmit, .xmit = seville_xmit,
.rcv = ocelot_rcv, .rcv = ocelot_rcv,
.overhead = OCELOT_TOTAL_TAG_LEN, .needed_headroom = OCELOT_TOTAL_TAG_LEN,
.promisc_on_master = true, .promisc_on_master = true,
}; };
......
...@@ -73,7 +73,7 @@ static const struct dsa_device_ops ocelot_8021q_netdev_ops = { ...@@ -73,7 +73,7 @@ static const struct dsa_device_ops ocelot_8021q_netdev_ops = {
.proto = DSA_TAG_PROTO_OCELOT_8021Q, .proto = DSA_TAG_PROTO_OCELOT_8021Q,
.xmit = ocelot_xmit, .xmit = ocelot_xmit,
.rcv = ocelot_rcv, .rcv = ocelot_rcv,
.overhead = VLAN_HLEN, .needed_headroom = VLAN_HLEN,
.promisc_on_master = true, .promisc_on_master = true,
}; };
......
...@@ -91,7 +91,7 @@ static const struct dsa_device_ops qca_netdev_ops = { ...@@ -91,7 +91,7 @@ static const struct dsa_device_ops qca_netdev_ops = {
.proto = DSA_TAG_PROTO_QCA, .proto = DSA_TAG_PROTO_QCA,
.xmit = qca_tag_xmit, .xmit = qca_tag_xmit,
.rcv = qca_tag_rcv, .rcv = qca_tag_rcv,
.overhead = QCA_HDR_LEN, .needed_headroom = QCA_HDR_LEN,
}; };
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
......
...@@ -124,7 +124,7 @@ static const struct dsa_device_ops rtl4a_netdev_ops = { ...@@ -124,7 +124,7 @@ static const struct dsa_device_ops rtl4a_netdev_ops = {
.proto = DSA_TAG_PROTO_RTL4_A, .proto = DSA_TAG_PROTO_RTL4_A,
.xmit = rtl4a_tag_xmit, .xmit = rtl4a_tag_xmit,
.rcv = rtl4a_tag_rcv, .rcv = rtl4a_tag_rcv,
.overhead = RTL4_A_HDR_LEN, .needed_headroom = RTL4_A_HDR_LEN,
}; };
module_dsa_tag_driver(rtl4a_netdev_ops); module_dsa_tag_driver(rtl4a_netdev_ops);
......
...@@ -362,7 +362,7 @@ static const struct dsa_device_ops sja1105_netdev_ops = { ...@@ -362,7 +362,7 @@ static const struct dsa_device_ops sja1105_netdev_ops = {
.xmit = sja1105_xmit, .xmit = sja1105_xmit,
.rcv = sja1105_rcv, .rcv = sja1105_rcv,
.filter = sja1105_filter, .filter = sja1105_filter,
.overhead = VLAN_HLEN, .needed_headroom = VLAN_HLEN,
.flow_dissect = sja1105_flow_dissect, .flow_dissect = sja1105_flow_dissect,
.promisc_on_master = true, .promisc_on_master = true,
}; };
......
...@@ -55,8 +55,7 @@ static const struct dsa_device_ops trailer_netdev_ops = { ...@@ -55,8 +55,7 @@ static const struct dsa_device_ops trailer_netdev_ops = {
.proto = DSA_TAG_PROTO_TRAILER, .proto = DSA_TAG_PROTO_TRAILER,
.xmit = trailer_xmit, .xmit = trailer_xmit,
.rcv = trailer_rcv, .rcv = trailer_rcv,
.overhead = 4, .needed_tailroom = 4,
.tail_tag = true,
}; };
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
......
...@@ -56,8 +56,7 @@ static const struct dsa_device_ops xrs700x_netdev_ops = { ...@@ -56,8 +56,7 @@ static const struct dsa_device_ops xrs700x_netdev_ops = {
.proto = DSA_TAG_PROTO_XRS700X, .proto = DSA_TAG_PROTO_XRS700X,
.xmit = xrs700x_xmit, .xmit = xrs700x_xmit,
.rcv = xrs700x_rcv, .rcv = xrs700x_rcv,
.overhead = 1, .needed_tailroom = 1,
.tail_tag = true,
}; };
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment