diff options
Diffstat (limited to 'net/dsa')
| -rw-r--r-- | net/dsa/Kconfig | 4 | ||||
| -rw-r--r-- | net/dsa/dsa.c | 8 | ||||
| -rw-r--r-- | net/dsa/dsa_priv.h | 2 | ||||
| -rw-r--r-- | net/dsa/master.c | 29 | ||||
| -rw-r--r-- | net/dsa/port.c | 3 | ||||
| -rw-r--r-- | net/dsa/slave.c | 58 | ||||
| -rw-r--r-- | net/dsa/tag_brcm.c | 2 | ||||
| -rw-r--r-- | net/dsa/tag_dsa.c | 1 | ||||
| -rw-r--r-- | net/dsa/tag_edsa.c | 1 | ||||
| -rw-r--r-- | net/dsa/tag_gswip.c | 1 | ||||
| -rw-r--r-- | net/dsa/tag_ksz.c | 117 | ||||
| -rw-r--r-- | net/dsa/tag_lan9303.c | 1 | ||||
| -rw-r--r-- | net/dsa/tag_mtk.c | 1 | ||||
| -rw-r--r-- | net/dsa/tag_qca.c | 1 | ||||
| -rw-r--r-- | net/dsa/tag_trailer.c | 1 |
15 files changed, 181 insertions, 49 deletions
diff --git a/net/dsa/Kconfig b/net/dsa/Kconfig index 48c41918fb35..91e52973ee13 100644 --- a/net/dsa/Kconfig +++ b/net/dsa/Kconfig | |||
| @@ -44,6 +44,10 @@ config NET_DSA_TAG_GSWIP | |||
| 44 | config NET_DSA_TAG_KSZ | 44 | config NET_DSA_TAG_KSZ |
| 45 | bool | 45 | bool |
| 46 | 46 | ||
| 47 | config NET_DSA_TAG_KSZ9477 | ||
| 48 | bool | ||
| 49 | select NET_DSA_TAG_KSZ | ||
| 50 | |||
| 47 | config NET_DSA_TAG_LAN9303 | 51 | config NET_DSA_TAG_LAN9303 |
| 48 | bool | 52 | bool |
| 49 | 53 | ||
diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c index a69c1790bbfc..aee909bcddc4 100644 --- a/net/dsa/dsa.c +++ b/net/dsa/dsa.c | |||
| @@ -55,8 +55,8 @@ const struct dsa_device_ops *dsa_device_ops[DSA_TAG_LAST] = { | |||
| 55 | #ifdef CONFIG_NET_DSA_TAG_GSWIP | 55 | #ifdef CONFIG_NET_DSA_TAG_GSWIP |
| 56 | [DSA_TAG_PROTO_GSWIP] = &gswip_netdev_ops, | 56 | [DSA_TAG_PROTO_GSWIP] = &gswip_netdev_ops, |
| 57 | #endif | 57 | #endif |
| 58 | #ifdef CONFIG_NET_DSA_TAG_KSZ | 58 | #ifdef CONFIG_NET_DSA_TAG_KSZ9477 |
| 59 | [DSA_TAG_PROTO_KSZ] = &ksz_netdev_ops, | 59 | [DSA_TAG_PROTO_KSZ9477] = &ksz9477_netdev_ops, |
| 60 | #endif | 60 | #endif |
| 61 | #ifdef CONFIG_NET_DSA_TAG_LAN9303 | 61 | #ifdef CONFIG_NET_DSA_TAG_LAN9303 |
| 62 | [DSA_TAG_PROTO_LAN9303] = &lan9303_netdev_ops, | 62 | [DSA_TAG_PROTO_LAN9303] = &lan9303_netdev_ops, |
| @@ -91,8 +91,8 @@ const char *dsa_tag_protocol_to_str(const struct dsa_device_ops *ops) | |||
| 91 | #ifdef CONFIG_NET_DSA_TAG_GSWIP | 91 | #ifdef CONFIG_NET_DSA_TAG_GSWIP |
| 92 | [DSA_TAG_PROTO_GSWIP] = "gswip", | 92 | [DSA_TAG_PROTO_GSWIP] = "gswip", |
| 93 | #endif | 93 | #endif |
| 94 | #ifdef CONFIG_NET_DSA_TAG_KSZ | 94 | #ifdef CONFIG_NET_DSA_TAG_KSZ9477 |
| 95 | [DSA_TAG_PROTO_KSZ] = "ksz", | 95 | [DSA_TAG_PROTO_KSZ9477] = "ksz9477", |
| 96 | #endif | 96 | #endif |
| 97 | #ifdef CONFIG_NET_DSA_TAG_LAN9303 | 97 | #ifdef CONFIG_NET_DSA_TAG_LAN9303 |
| 98 | [DSA_TAG_PROTO_LAN9303] = "lan9303", | 98 | [DSA_TAG_PROTO_LAN9303] = "lan9303", |
diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h index 9e4fd04ab53c..026a05774bf7 100644 --- a/net/dsa/dsa_priv.h +++ b/net/dsa/dsa_priv.h | |||
| @@ -210,7 +210,7 @@ extern const struct dsa_device_ops edsa_netdev_ops; | |||
| 210 | extern const struct dsa_device_ops gswip_netdev_ops; | 210 | extern const struct dsa_device_ops gswip_netdev_ops; |
| 211 | 211 | ||
| 212 | /* tag_ksz.c */ | 212 | /* tag_ksz.c */ |
| 213 | extern const struct dsa_device_ops ksz_netdev_ops; | 213 | extern const struct dsa_device_ops ksz9477_netdev_ops; |
| 214 | 214 | ||
| 215 | /* tag_lan9303.c */ | 215 | /* tag_lan9303.c */ |
| 216 | extern const struct dsa_device_ops lan9303_netdev_ops; | 216 | extern const struct dsa_device_ops lan9303_netdev_ops; |
diff --git a/net/dsa/master.c b/net/dsa/master.c index 5e8c9bef78bd..71bb15f491c8 100644 --- a/net/dsa/master.c +++ b/net/dsa/master.c | |||
| @@ -179,10 +179,38 @@ static const struct attribute_group dsa_group = { | |||
| 179 | .attrs = dsa_slave_attrs, | 179 | .attrs = dsa_slave_attrs, |
| 180 | }; | 180 | }; |
| 181 | 181 | ||
| 182 | static void dsa_master_set_mtu(struct net_device *dev, struct dsa_port *cpu_dp) | ||
| 183 | { | ||
| 184 | unsigned int mtu = ETH_DATA_LEN + cpu_dp->tag_ops->overhead; | ||
| 185 | int err; | ||
| 186 | |||
| 187 | rtnl_lock(); | ||
| 188 | if (mtu <= dev->max_mtu) { | ||
| 189 | err = dev_set_mtu(dev, mtu); | ||
| 190 | if (err) | ||
| 191 | netdev_dbg(dev, "Unable to set MTU to include for DSA overheads\n"); | ||
| 192 | } | ||
| 193 | rtnl_unlock(); | ||
| 194 | } | ||
| 195 | |||
| 196 | static void dsa_master_reset_mtu(struct net_device *dev) | ||
| 197 | { | ||
| 198 | int err; | ||
| 199 | |||
| 200 | rtnl_lock(); | ||
| 201 | err = dev_set_mtu(dev, ETH_DATA_LEN); | ||
| 202 | if (err) | ||
| 203 | netdev_dbg(dev, | ||
| 204 | "Unable to reset MTU to exclude DSA overheads\n"); | ||
| 205 | rtnl_unlock(); | ||
| 206 | } | ||
| 207 | |||
| 182 | int dsa_master_setup(struct net_device *dev, struct dsa_port *cpu_dp) | 208 | int dsa_master_setup(struct net_device *dev, struct dsa_port *cpu_dp) |
| 183 | { | 209 | { |
| 184 | int ret; | 210 | int ret; |
| 185 | 211 | ||
| 212 | dsa_master_set_mtu(dev, cpu_dp); | ||
| 213 | |||
| 186 | /* If we use a tagging format that doesn't have an ethertype | 214 | /* If we use a tagging format that doesn't have an ethertype |
| 187 | * field, make sure that all packets from this point on get | 215 | * field, make sure that all packets from this point on get |
| 188 | * sent to the tag format's receive function. | 216 | * sent to the tag format's receive function. |
| @@ -206,6 +234,7 @@ void dsa_master_teardown(struct net_device *dev) | |||
| 206 | { | 234 | { |
| 207 | sysfs_remove_group(&dev->dev.kobj, &dsa_group); | 235 | sysfs_remove_group(&dev->dev.kobj, &dsa_group); |
| 208 | dsa_master_ethtool_teardown(dev); | 236 | dsa_master_ethtool_teardown(dev); |
| 237 | dsa_master_reset_mtu(dev); | ||
| 209 | 238 | ||
| 210 | dev->dsa_ptr = NULL; | 239 | dev->dsa_ptr = NULL; |
| 211 | 240 | ||
diff --git a/net/dsa/port.c b/net/dsa/port.c index ed0595459df1..2d7e01b23572 100644 --- a/net/dsa/port.c +++ b/net/dsa/port.c | |||
| @@ -252,9 +252,6 @@ int dsa_port_vlan_add(struct dsa_port *dp, | |||
| 252 | .vlan = vlan, | 252 | .vlan = vlan, |
| 253 | }; | 253 | }; |
| 254 | 254 | ||
| 255 | if (netif_is_bridge_master(vlan->obj.orig_dev)) | ||
| 256 | return -EOPNOTSUPP; | ||
| 257 | |||
| 258 | if (br_vlan_enabled(dp->bridge_dev)) | 255 | if (br_vlan_enabled(dp->bridge_dev)) |
| 259 | return dsa_port_notify(dp, DSA_NOTIFIER_VLAN_ADD, &info); | 256 | return dsa_port_notify(dp, DSA_NOTIFIER_VLAN_ADD, &info); |
| 260 | 257 | ||
diff --git a/net/dsa/slave.c b/net/dsa/slave.c index aec78f5aca72..a3fcc1d01615 100644 --- a/net/dsa/slave.c +++ b/net/dsa/slave.c | |||
| @@ -1050,8 +1050,6 @@ static const struct net_device_ops dsa_slave_netdev_ops = { | |||
| 1050 | static const struct switchdev_ops dsa_slave_switchdev_ops = { | 1050 | static const struct switchdev_ops dsa_slave_switchdev_ops = { |
| 1051 | .switchdev_port_attr_get = dsa_slave_port_attr_get, | 1051 | .switchdev_port_attr_get = dsa_slave_port_attr_get, |
| 1052 | .switchdev_port_attr_set = dsa_slave_port_attr_set, | 1052 | .switchdev_port_attr_set = dsa_slave_port_attr_set, |
| 1053 | .switchdev_port_obj_add = dsa_slave_port_obj_add, | ||
| 1054 | .switchdev_port_obj_del = dsa_slave_port_obj_del, | ||
| 1055 | }; | 1053 | }; |
| 1056 | 1054 | ||
| 1057 | static struct device_type dsa_type = { | 1055 | static struct device_type dsa_type = { |
| @@ -1529,6 +1527,44 @@ err_fdb_work_init: | |||
| 1529 | return NOTIFY_BAD; | 1527 | return NOTIFY_BAD; |
| 1530 | } | 1528 | } |
| 1531 | 1529 | ||
| 1530 | static int | ||
| 1531 | dsa_slave_switchdev_port_obj_event(unsigned long event, | ||
| 1532 | struct net_device *netdev, | ||
| 1533 | struct switchdev_notifier_port_obj_info *port_obj_info) | ||
| 1534 | { | ||
| 1535 | int err = -EOPNOTSUPP; | ||
| 1536 | |||
| 1537 | switch (event) { | ||
| 1538 | case SWITCHDEV_PORT_OBJ_ADD: | ||
| 1539 | err = dsa_slave_port_obj_add(netdev, port_obj_info->obj, | ||
| 1540 | port_obj_info->trans); | ||
| 1541 | break; | ||
| 1542 | case SWITCHDEV_PORT_OBJ_DEL: | ||
| 1543 | err = dsa_slave_port_obj_del(netdev, port_obj_info->obj); | ||
| 1544 | break; | ||
| 1545 | } | ||
| 1546 | |||
| 1547 | port_obj_info->handled = true; | ||
| 1548 | return notifier_from_errno(err); | ||
| 1549 | } | ||
| 1550 | |||
| 1551 | static int dsa_slave_switchdev_blocking_event(struct notifier_block *unused, | ||
| 1552 | unsigned long event, void *ptr) | ||
| 1553 | { | ||
| 1554 | struct net_device *dev = switchdev_notifier_info_to_dev(ptr); | ||
| 1555 | |||
| 1556 | if (!dsa_slave_dev_check(dev)) | ||
| 1557 | return NOTIFY_DONE; | ||
| 1558 | |||
| 1559 | switch (event) { | ||
| 1560 | case SWITCHDEV_PORT_OBJ_ADD: /* fall through */ | ||
| 1561 | case SWITCHDEV_PORT_OBJ_DEL: | ||
| 1562 | return dsa_slave_switchdev_port_obj_event(event, dev, ptr); | ||
| 1563 | } | ||
| 1564 | |||
| 1565 | return NOTIFY_DONE; | ||
| 1566 | } | ||
| 1567 | |||
| 1532 | static struct notifier_block dsa_slave_nb __read_mostly = { | 1568 | static struct notifier_block dsa_slave_nb __read_mostly = { |
| 1533 | .notifier_call = dsa_slave_netdevice_event, | 1569 | .notifier_call = dsa_slave_netdevice_event, |
| 1534 | }; | 1570 | }; |
| @@ -1537,8 +1573,13 @@ static struct notifier_block dsa_slave_switchdev_notifier = { | |||
| 1537 | .notifier_call = dsa_slave_switchdev_event, | 1573 | .notifier_call = dsa_slave_switchdev_event, |
| 1538 | }; | 1574 | }; |
| 1539 | 1575 | ||
| 1576 | static struct notifier_block dsa_slave_switchdev_blocking_notifier = { | ||
| 1577 | .notifier_call = dsa_slave_switchdev_blocking_event, | ||
| 1578 | }; | ||
| 1579 | |||
| 1540 | int dsa_slave_register_notifier(void) | 1580 | int dsa_slave_register_notifier(void) |
| 1541 | { | 1581 | { |
| 1582 | struct notifier_block *nb; | ||
| 1542 | int err; | 1583 | int err; |
| 1543 | 1584 | ||
| 1544 | err = register_netdevice_notifier(&dsa_slave_nb); | 1585 | err = register_netdevice_notifier(&dsa_slave_nb); |
| @@ -1549,8 +1590,15 @@ int dsa_slave_register_notifier(void) | |||
| 1549 | if (err) | 1590 | if (err) |
| 1550 | goto err_switchdev_nb; | 1591 | goto err_switchdev_nb; |
| 1551 | 1592 | ||
| 1593 | nb = &dsa_slave_switchdev_blocking_notifier; | ||
| 1594 | err = register_switchdev_blocking_notifier(nb); | ||
| 1595 | if (err) | ||
| 1596 | goto err_switchdev_blocking_nb; | ||
| 1597 | |||
| 1552 | return 0; | 1598 | return 0; |
| 1553 | 1599 | ||
| 1600 | err_switchdev_blocking_nb: | ||
| 1601 | unregister_switchdev_notifier(&dsa_slave_switchdev_notifier); | ||
| 1554 | err_switchdev_nb: | 1602 | err_switchdev_nb: |
| 1555 | unregister_netdevice_notifier(&dsa_slave_nb); | 1603 | unregister_netdevice_notifier(&dsa_slave_nb); |
| 1556 | return err; | 1604 | return err; |
| @@ -1558,8 +1606,14 @@ err_switchdev_nb: | |||
| 1558 | 1606 | ||
| 1559 | void dsa_slave_unregister_notifier(void) | 1607 | void dsa_slave_unregister_notifier(void) |
| 1560 | { | 1608 | { |
| 1609 | struct notifier_block *nb; | ||
| 1561 | int err; | 1610 | int err; |
| 1562 | 1611 | ||
| 1612 | nb = &dsa_slave_switchdev_blocking_notifier; | ||
| 1613 | err = unregister_switchdev_blocking_notifier(nb); | ||
| 1614 | if (err) | ||
| 1615 | pr_err("DSA: failed to unregister switchdev blocking notifier (%d)\n", err); | ||
| 1616 | |||
| 1563 | err = unregister_switchdev_notifier(&dsa_slave_switchdev_notifier); | 1617 | err = unregister_switchdev_notifier(&dsa_slave_switchdev_notifier); |
| 1564 | if (err) | 1618 | if (err) |
| 1565 | pr_err("DSA: failed to unregister switchdev notifier (%d)\n", err); | 1619 | pr_err("DSA: failed to unregister switchdev notifier (%d)\n", err); |
diff --git a/net/dsa/tag_brcm.c b/net/dsa/tag_brcm.c index 2b06bb91318b..4aa1d368a5ae 100644 --- a/net/dsa/tag_brcm.c +++ b/net/dsa/tag_brcm.c | |||
| @@ -174,6 +174,7 @@ static struct sk_buff *brcm_tag_rcv(struct sk_buff *skb, struct net_device *dev, | |||
| 174 | const struct dsa_device_ops brcm_netdev_ops = { | 174 | const struct dsa_device_ops brcm_netdev_ops = { |
| 175 | .xmit = brcm_tag_xmit, | 175 | .xmit = brcm_tag_xmit, |
| 176 | .rcv = brcm_tag_rcv, | 176 | .rcv = brcm_tag_rcv, |
| 177 | .overhead = BRCM_TAG_LEN, | ||
| 177 | }; | 178 | }; |
| 178 | #endif | 179 | #endif |
| 179 | 180 | ||
| @@ -196,5 +197,6 @@ static struct sk_buff *brcm_tag_rcv_prepend(struct sk_buff *skb, | |||
| 196 | const struct dsa_device_ops brcm_prepend_netdev_ops = { | 197 | const struct dsa_device_ops brcm_prepend_netdev_ops = { |
| 197 | .xmit = brcm_tag_xmit_prepend, | 198 | .xmit = brcm_tag_xmit_prepend, |
| 198 | .rcv = brcm_tag_rcv_prepend, | 199 | .rcv = brcm_tag_rcv_prepend, |
| 200 | .overhead = BRCM_TAG_LEN, | ||
| 199 | }; | 201 | }; |
| 200 | #endif | 202 | #endif |
diff --git a/net/dsa/tag_dsa.c b/net/dsa/tag_dsa.c index cd13cfc542ce..8b2f92e3f3a2 100644 --- a/net/dsa/tag_dsa.c +++ b/net/dsa/tag_dsa.c | |||
| @@ -149,4 +149,5 @@ static struct sk_buff *dsa_rcv(struct sk_buff *skb, struct net_device *dev, | |||
| 149 | const struct dsa_device_ops dsa_netdev_ops = { | 149 | const struct dsa_device_ops dsa_netdev_ops = { |
| 150 | .xmit = dsa_xmit, | 150 | .xmit = dsa_xmit, |
| 151 | .rcv = dsa_rcv, | 151 | .rcv = dsa_rcv, |
| 152 | .overhead = DSA_HLEN, | ||
| 152 | }; | 153 | }; |
diff --git a/net/dsa/tag_edsa.c b/net/dsa/tag_edsa.c index 4083326b806e..f5b87ee5c94e 100644 --- a/net/dsa/tag_edsa.c +++ b/net/dsa/tag_edsa.c | |||
| @@ -168,4 +168,5 @@ static struct sk_buff *edsa_rcv(struct sk_buff *skb, struct net_device *dev, | |||
| 168 | const struct dsa_device_ops edsa_netdev_ops = { | 168 | const struct dsa_device_ops edsa_netdev_ops = { |
| 169 | .xmit = edsa_xmit, | 169 | .xmit = edsa_xmit, |
| 170 | .rcv = edsa_rcv, | 170 | .rcv = edsa_rcv, |
| 171 | .overhead = EDSA_HLEN, | ||
| 171 | }; | 172 | }; |
diff --git a/net/dsa/tag_gswip.c b/net/dsa/tag_gswip.c index 49e9b73f1be3..cb6f82ffe5eb 100644 --- a/net/dsa/tag_gswip.c +++ b/net/dsa/tag_gswip.c | |||
| @@ -106,4 +106,5 @@ static struct sk_buff *gswip_tag_rcv(struct sk_buff *skb, | |||
| 106 | const struct dsa_device_ops gswip_netdev_ops = { | 106 | const struct dsa_device_ops gswip_netdev_ops = { |
| 107 | .xmit = gswip_tag_xmit, | 107 | .xmit = gswip_tag_xmit, |
| 108 | .rcv = gswip_tag_rcv, | 108 | .rcv = gswip_tag_rcv, |
| 109 | .overhead = GSWIP_RX_HEADER_LEN, | ||
| 109 | }; | 110 | }; |
diff --git a/net/dsa/tag_ksz.c b/net/dsa/tag_ksz.c index 0f62effad88f..da71b9e2af52 100644 --- a/net/dsa/tag_ksz.c +++ b/net/dsa/tag_ksz.c | |||
| @@ -14,34 +14,18 @@ | |||
| 14 | #include <net/dsa.h> | 14 | #include <net/dsa.h> |
| 15 | #include "dsa_priv.h" | 15 | #include "dsa_priv.h" |
| 16 | 16 | ||
| 17 | /* For Ingress (Host -> KSZ), 2 bytes are added before FCS. | 17 | /* Typically only one byte is used for tail tag. */ |
| 18 | * --------------------------------------------------------------------------- | 18 | #define KSZ_EGRESS_TAG_LEN 1 |
| 19 | * DA(6bytes)|SA(6bytes)|....|Data(nbytes)|tag0(1byte)|tag1(1byte)|FCS(4bytes) | ||
| 20 | * --------------------------------------------------------------------------- | ||
| 21 | * tag0 : Prioritization (not used now) | ||
| 22 | * tag1 : each bit represents port (eg, 0x01=port1, 0x02=port2, 0x10=port5) | ||
| 23 | * | ||
| 24 | * For Egress (KSZ -> Host), 1 byte is added before FCS. | ||
| 25 | * --------------------------------------------------------------------------- | ||
| 26 | * DA(6bytes)|SA(6bytes)|....|Data(nbytes)|tag0(1byte)|FCS(4bytes) | ||
| 27 | * --------------------------------------------------------------------------- | ||
| 28 | * tag0 : zero-based value represents port | ||
| 29 | * (eg, 0x00=port1, 0x02=port3, 0x06=port7) | ||
| 30 | */ | ||
| 31 | |||
| 32 | #define KSZ_INGRESS_TAG_LEN 2 | ||
| 33 | #define KSZ_EGRESS_TAG_LEN 1 | ||
| 34 | 19 | ||
| 35 | static struct sk_buff *ksz_xmit(struct sk_buff *skb, struct net_device *dev) | 20 | static struct sk_buff *ksz_common_xmit(struct sk_buff *skb, |
| 21 | struct net_device *dev, int len) | ||
| 36 | { | 22 | { |
| 37 | struct dsa_port *dp = dsa_slave_to_port(dev); | ||
| 38 | struct sk_buff *nskb; | 23 | struct sk_buff *nskb; |
| 39 | int padlen; | 24 | int padlen; |
| 40 | u8 *tag; | ||
| 41 | 25 | ||
| 42 | padlen = (skb->len >= ETH_ZLEN) ? 0 : ETH_ZLEN - skb->len; | 26 | padlen = (skb->len >= ETH_ZLEN) ? 0 : ETH_ZLEN - skb->len; |
| 43 | 27 | ||
| 44 | if (skb_tailroom(skb) >= padlen + KSZ_INGRESS_TAG_LEN) { | 28 | if (skb_tailroom(skb) >= padlen + len) { |
| 45 | /* Let dsa_slave_xmit() free skb */ | 29 | /* Let dsa_slave_xmit() free skb */ |
| 46 | if (__skb_put_padto(skb, skb->len + padlen, false)) | 30 | if (__skb_put_padto(skb, skb->len + padlen, false)) |
| 47 | return NULL; | 31 | return NULL; |
| @@ -49,7 +33,7 @@ static struct sk_buff *ksz_xmit(struct sk_buff *skb, struct net_device *dev) | |||
| 49 | nskb = skb; | 33 | nskb = skb; |
| 50 | } else { | 34 | } else { |
| 51 | nskb = alloc_skb(NET_IP_ALIGN + skb->len + | 35 | nskb = alloc_skb(NET_IP_ALIGN + skb->len + |
| 52 | padlen + KSZ_INGRESS_TAG_LEN, GFP_ATOMIC); | 36 | padlen + len, GFP_ATOMIC); |
| 53 | if (!nskb) | 37 | if (!nskb) |
| 54 | return NULL; | 38 | return NULL; |
| 55 | skb_reserve(nskb, NET_IP_ALIGN); | 39 | skb_reserve(nskb, NET_IP_ALIGN); |
| @@ -70,33 +54,88 @@ static struct sk_buff *ksz_xmit(struct sk_buff *skb, struct net_device *dev) | |||
| 70 | consume_skb(skb); | 54 | consume_skb(skb); |
| 71 | } | 55 | } |
| 72 | 56 | ||
| 73 | tag = skb_put(nskb, KSZ_INGRESS_TAG_LEN); | ||
| 74 | tag[0] = 0; | ||
| 75 | tag[1] = 1 << dp->index; /* destination port */ | ||
| 76 | |||
| 77 | return nskb; | 57 | return nskb; |
| 78 | } | 58 | } |
| 79 | 59 | ||
| 80 | static struct sk_buff *ksz_rcv(struct sk_buff *skb, struct net_device *dev, | 60 | static struct sk_buff *ksz_common_rcv(struct sk_buff *skb, |
| 81 | struct packet_type *pt) | 61 | struct net_device *dev, |
| 62 | unsigned int port, unsigned int len) | ||
| 82 | { | 63 | { |
| 83 | u8 *tag; | 64 | skb->dev = dsa_master_find_slave(dev, 0, port); |
| 84 | int source_port; | 65 | if (!skb->dev) |
| 66 | return NULL; | ||
| 85 | 67 | ||
| 86 | tag = skb_tail_pointer(skb) - KSZ_EGRESS_TAG_LEN; | 68 | pskb_trim_rcsum(skb, skb->len - len); |
| 87 | 69 | ||
| 88 | source_port = tag[0] & 7; | 70 | return skb; |
| 71 | } | ||
| 89 | 72 | ||
| 90 | skb->dev = dsa_master_find_slave(dev, 0, source_port); | 73 | /* |
| 91 | if (!skb->dev) | 74 | * For Ingress (Host -> KSZ9477), 2 bytes are added before FCS. |
| 75 | * --------------------------------------------------------------------------- | ||
| 76 | * DA(6bytes)|SA(6bytes)|....|Data(nbytes)|tag0(1byte)|tag1(1byte)|FCS(4bytes) | ||
| 77 | * --------------------------------------------------------------------------- | ||
| 78 | * tag0 : Prioritization (not used now) | ||
| 79 | * tag1 : each bit represents port (eg, 0x01=port1, 0x02=port2, 0x10=port5) | ||
| 80 | * | ||
| 81 | * For Egress (KSZ9477 -> Host), 1 byte is added before FCS. | ||
| 82 | * --------------------------------------------------------------------------- | ||
| 83 | * DA(6bytes)|SA(6bytes)|....|Data(nbytes)|tag0(1byte)|FCS(4bytes) | ||
| 84 | * --------------------------------------------------------------------------- | ||
| 85 | * tag0 : zero-based value represents port | ||
| 86 | * (eg, 0x00=port1, 0x02=port3, 0x06=port7) | ||
| 87 | */ | ||
| 88 | |||
| 89 | #define KSZ9477_INGRESS_TAG_LEN 2 | ||
| 90 | #define KSZ9477_PTP_TAG_LEN 4 | ||
| 91 | #define KSZ9477_PTP_TAG_INDICATION 0x80 | ||
| 92 | |||
| 93 | #define KSZ9477_TAIL_TAG_OVERRIDE BIT(9) | ||
| 94 | #define KSZ9477_TAIL_TAG_LOOKUP BIT(10) | ||
| 95 | |||
| 96 | static struct sk_buff *ksz9477_xmit(struct sk_buff *skb, | ||
| 97 | struct net_device *dev) | ||
| 98 | { | ||
| 99 | struct dsa_port *dp = dsa_slave_to_port(dev); | ||
| 100 | struct sk_buff *nskb; | ||
| 101 | u16 *tag; | ||
| 102 | u8 *addr; | ||
| 103 | |||
| 104 | nskb = ksz_common_xmit(skb, dev, KSZ9477_INGRESS_TAG_LEN); | ||
| 105 | if (!nskb) | ||
| 92 | return NULL; | 106 | return NULL; |
| 93 | 107 | ||
| 94 | pskb_trim_rcsum(skb, skb->len - KSZ_EGRESS_TAG_LEN); | 108 | /* Tag encoding */ |
| 109 | tag = skb_put(nskb, KSZ9477_INGRESS_TAG_LEN); | ||
| 110 | addr = skb_mac_header(nskb); | ||
| 95 | 111 | ||
| 96 | return skb; | 112 | *tag = BIT(dp->index); |
| 113 | |||
| 114 | if (is_link_local_ether_addr(addr)) | ||
| 115 | *tag |= KSZ9477_TAIL_TAG_OVERRIDE; | ||
| 116 | |||
| 117 | *tag = cpu_to_be16(*tag); | ||
| 118 | |||
| 119 | return nskb; | ||
| 120 | } | ||
| 121 | |||
| 122 | static struct sk_buff *ksz9477_rcv(struct sk_buff *skb, struct net_device *dev, | ||
| 123 | struct packet_type *pt) | ||
| 124 | { | ||
| 125 | /* Tag decoding */ | ||
| 126 | u8 *tag = skb_tail_pointer(skb) - KSZ_EGRESS_TAG_LEN; | ||
| 127 | unsigned int port = tag[0] & 7; | ||
| 128 | unsigned int len = KSZ_EGRESS_TAG_LEN; | ||
| 129 | |||
| 130 | /* Extra 4-bytes PTP timestamp */ | ||
| 131 | if (tag[0] & KSZ9477_PTP_TAG_INDICATION) | ||
| 132 | len += KSZ9477_PTP_TAG_LEN; | ||
| 133 | |||
| 134 | return ksz_common_rcv(skb, dev, port, len); | ||
| 97 | } | 135 | } |
| 98 | 136 | ||
| 99 | const struct dsa_device_ops ksz_netdev_ops = { | 137 | const struct dsa_device_ops ksz9477_netdev_ops = { |
| 100 | .xmit = ksz_xmit, | 138 | .xmit = ksz9477_xmit, |
| 101 | .rcv = ksz_rcv, | 139 | .rcv = ksz9477_rcv, |
| 140 | .overhead = KSZ9477_INGRESS_TAG_LEN, | ||
| 102 | }; | 141 | }; |
diff --git a/net/dsa/tag_lan9303.c b/net/dsa/tag_lan9303.c index 548c00254c07..f48889e46ff7 100644 --- a/net/dsa/tag_lan9303.c +++ b/net/dsa/tag_lan9303.c | |||
| @@ -140,4 +140,5 @@ static struct sk_buff *lan9303_rcv(struct sk_buff *skb, struct net_device *dev, | |||
| 140 | const struct dsa_device_ops lan9303_netdev_ops = { | 140 | const struct dsa_device_ops lan9303_netdev_ops = { |
| 141 | .xmit = lan9303_xmit, | 141 | .xmit = lan9303_xmit, |
| 142 | .rcv = lan9303_rcv, | 142 | .rcv = lan9303_rcv, |
| 143 | .overhead = LAN9303_TAG_LEN, | ||
| 143 | }; | 144 | }; |
diff --git a/net/dsa/tag_mtk.c b/net/dsa/tag_mtk.c index 11535bc70743..f39f4dfeda34 100644 --- a/net/dsa/tag_mtk.c +++ b/net/dsa/tag_mtk.c | |||
| @@ -109,4 +109,5 @@ const struct dsa_device_ops mtk_netdev_ops = { | |||
| 109 | .xmit = mtk_tag_xmit, | 109 | .xmit = mtk_tag_xmit, |
| 110 | .rcv = mtk_tag_rcv, | 110 | .rcv = mtk_tag_rcv, |
| 111 | .flow_dissect = mtk_tag_flow_dissect, | 111 | .flow_dissect = mtk_tag_flow_dissect, |
| 112 | .overhead = MTK_HDR_LEN, | ||
| 112 | }; | 113 | }; |
diff --git a/net/dsa/tag_qca.c b/net/dsa/tag_qca.c index 613f4ee97771..ed4f6dc26365 100644 --- a/net/dsa/tag_qca.c +++ b/net/dsa/tag_qca.c | |||
| @@ -101,4 +101,5 @@ static struct sk_buff *qca_tag_rcv(struct sk_buff *skb, struct net_device *dev, | |||
| 101 | const struct dsa_device_ops qca_netdev_ops = { | 101 | const struct dsa_device_ops qca_netdev_ops = { |
| 102 | .xmit = qca_tag_xmit, | 102 | .xmit = qca_tag_xmit, |
| 103 | .rcv = qca_tag_rcv, | 103 | .rcv = qca_tag_rcv, |
| 104 | .overhead = QCA_HDR_LEN, | ||
| 104 | }; | 105 | }; |
diff --git a/net/dsa/tag_trailer.c b/net/dsa/tag_trailer.c index 56197f0d9608..b40756ed6e57 100644 --- a/net/dsa/tag_trailer.c +++ b/net/dsa/tag_trailer.c | |||
| @@ -84,4 +84,5 @@ static struct sk_buff *trailer_rcv(struct sk_buff *skb, struct net_device *dev, | |||
| 84 | const struct dsa_device_ops trailer_netdev_ops = { | 84 | const struct dsa_device_ops trailer_netdev_ops = { |
| 85 | .xmit = trailer_xmit, | 85 | .xmit = trailer_xmit, |
| 86 | .rcv = trailer_rcv, | 86 | .rcv = trailer_rcv, |
| 87 | .overhead = 4, | ||
| 87 | }; | 88 | }; |
