In VLAN-unaware mode, sja1105 uses VLAN tags with a custom TPID of 0xdadb. While in the yet-to-be introduced best_effort_vlan_filtering mode, it needs to work with normal VLAN TPID values. A complication arises when we must transmit a VLAN-tagged packet to the switch when it's in VLAN-aware mode. We need to construct a packet with 2 VLAN tags, and the switch will use the outer header for routing and pop it on egress. But sadly, here the 2 hardware generations don't behave the same: - E/T switches won't pop an ETH_P_8021AD tag on egress, it seems (packets will remain double-tagged). - P/Q/R/S switches will drop a packet with 2 ETH_P_8021Q tags (it looks like it tries to prevent VLAN hopping). But looks like the reverse is also true: - E/T switches have no problem popping the outer tag from packets with 2 ETH_P_8021Q tags. - P/Q/R/S will have no problem popping a single tag even if that is ETH_P_8021AD. So it is clear that if we want the hardware to work with dsa_8021q tagging in VLAN-aware mode, we need to send different TPIDs depending on revision. Keep that information in priv->info->qinq_tpid. The per-port tagger structure will hold an xmit_tpid value that depends not only upon the qinq_tpid, but also upon the VLAN awareness state itself (in case we must transmit using 0xdadb).
Unified · Split
| @@ -87,6 +87,12 @@ struct sja1105_info { · 86 unmodified lines | |||
| 87 | const struct sja1105_dynamic_table_ops *dyn_ops; | 87 | const struct sja1105_dynamic_table_ops *dyn_ops; |
| 88 | const struct sja1105_table_ops *static_ops; | 88 | const struct sja1105_table_ops *static_ops; |
| 89 | const struct sja1105_regs *regs; | 89 | const struct sja1105_regs *regs; |
| 90 | /* Both E/T and P/Q/R/S have quirks when it comes to popping the S-Tag | ||
| 91 | * from double-tagged frames. E/T will pop it only when it's equal to | ||
| 92 | * TPID from the General Parameters Table, while P/Q/R/S will only | ||
| 93 | * pop it when it's equal to TPID2. | ||
| 94 | */ | ||
| 95 | u16 qinq_tpid; | ||
| 90 | int (*reset_cmd)(struct dsa_switch *ds); | 96 | int (*reset_cmd)(struct dsa_switch *ds); |
| 91 | int (*setup_rgmii_delay)(const void *ctx, int port); | 97 | int (*setup_rgmii_delay)(const void *ctx, int port); |
| 92 | /* Prototypes from include/net/dsa.h */ | 98 | /* Prototypes from include/net/dsa.h */ |
| @@ -2153,6 +2153,15 @@ static int sja1105_vlan_filtering(struct dsa_switch *ds, int port, bool enabled) · 2152 unmodified lines | |||
| 2153 | tpid2 = ETH_P_SJA1105; | 2153 | tpid2 = ETH_P_SJA1105; |
| 2154 | } | 2154 | } |
| 2155 | 2155 | ||
| 2156 | for (port = 0; port < ds->num_ports; port++) { | ||
| 2157 | struct sja1105_port *sp = &priv->ports[port]; | ||
| 2158 | |||
| 2159 | if (enabled) | ||
| 2160 | sp->xmit_tpid = priv->info->qinq_tpid; | ||
| 2161 | else | ||
| 2162 | sp->xmit_tpid = ETH_P_SJA1105; | ||
| 2163 | } | ||
| 2164 | |||
| 2156 | if (!enabled) | 2165 | if (!enabled) |
| 2157 | state = SJA1105_VLAN_UNAWARE; | 2166 | state = SJA1105_VLAN_UNAWARE; |
| 2158 | else | 2167 | else |
| @@ -2866,6 +2875,7 @@ static int sja1105_probe(struct spi_device *spi) · 707 unmodified lines | |||
| 2866 | goto out; | 2875 | goto out; |
| 2867 | } | 2876 | } |
| 2868 | skb_queue_head_init(&sp->xmit_queue); | 2877 | skb_queue_head_init(&sp->xmit_queue); |
| 2878 | sp->xmit_tpid = ETH_P_SJA1105; | ||
| 2869 | } | 2879 | } |
| 2870 | 2880 | ||
| 2871 | return 0; | 2881 | return 0; |
| @@ -512,6 +512,7 @@ struct sja1105_info sja1105e_info = { · 511 unmodified lines | |||
| 512 | .part_no = SJA1105ET_PART_NO, | 512 | .part_no = SJA1105ET_PART_NO, |
| 513 | .static_ops = sja1105e_table_ops, | 513 | .static_ops = sja1105e_table_ops, |
| 514 | .dyn_ops = sja1105et_dyn_ops, | 514 | .dyn_ops = sja1105et_dyn_ops, |
| 515 | .qinq_tpid = ETH_P_8021Q, | ||
| 515 | .ptp_ts_bits = 24, | 516 | .ptp_ts_bits = 24, |
| 516 | .ptpegr_ts_bytes = 4, | 517 | .ptpegr_ts_bytes = 4, |
| 517 | .reset_cmd = sja1105et_reset_cmd, | 518 | .reset_cmd = sja1105et_reset_cmd, |
| @@ -526,6 +527,7 @@ struct sja1105_info sja1105t_info = { · 8 unmodified lines | |||
| 526 | .part_no = SJA1105ET_PART_NO, | 527 | .part_no = SJA1105ET_PART_NO, |
| 527 | .static_ops = sja1105t_table_ops, | 528 | .static_ops = sja1105t_table_ops, |
| 528 | .dyn_ops = sja1105et_dyn_ops, | 529 | .dyn_ops = sja1105et_dyn_ops, |
| 530 | .qinq_tpid = ETH_P_8021Q, | ||
| 529 | .ptp_ts_bits = 24, | 531 | .ptp_ts_bits = 24, |
| 530 | .ptpegr_ts_bytes = 4, | 532 | .ptpegr_ts_bytes = 4, |
| 531 | .reset_cmd = sja1105et_reset_cmd, | 533 | .reset_cmd = sja1105et_reset_cmd, |
| @@ -540,6 +542,7 @@ struct sja1105_info sja1105p_info = { · 8 unmodified lines | |||
| 540 | .part_no = SJA1105P_PART_NO, | 542 | .part_no = SJA1105P_PART_NO, |
| 541 | .static_ops = sja1105p_table_ops, | 543 | .static_ops = sja1105p_table_ops, |
| 542 | .dyn_ops = sja1105pqrs_dyn_ops, | 544 | .dyn_ops = sja1105pqrs_dyn_ops, |
| 545 | .qinq_tpid = ETH_P_8021AD, | ||
| 543 | .ptp_ts_bits = 32, | 546 | .ptp_ts_bits = 32, |
| 544 | .ptpegr_ts_bytes = 8, | 547 | .ptpegr_ts_bytes = 8, |
| 545 | .setup_rgmii_delay = sja1105pqrs_setup_rgmii_delay, | 548 | .setup_rgmii_delay = sja1105pqrs_setup_rgmii_delay, |
| @@ -555,6 +558,7 @@ struct sja1105_info sja1105q_info = { · 9 unmodified lines | |||
| 555 | .part_no = SJA1105Q_PART_NO, | 558 | .part_no = SJA1105Q_PART_NO, |
| 556 | .static_ops = sja1105q_table_ops, | 559 | .static_ops = sja1105q_table_ops, |
| 557 | .dyn_ops = sja1105pqrs_dyn_ops, | 560 | .dyn_ops = sja1105pqrs_dyn_ops, |
| 561 | .qinq_tpid = ETH_P_8021AD, | ||
| 558 | .ptp_ts_bits = 32, | 562 | .ptp_ts_bits = 32, |
| 559 | .ptpegr_ts_bytes = 8, | 563 | .ptpegr_ts_bytes = 8, |
| 560 | .setup_rgmii_delay = sja1105pqrs_setup_rgmii_delay, | 564 | .setup_rgmii_delay = sja1105pqrs_setup_rgmii_delay, |
| @@ -570,6 +574,7 @@ struct sja1105_info sja1105r_info = { · 9 unmodified lines | |||
| 570 | .part_no = SJA1105R_PART_NO, | 574 | .part_no = SJA1105R_PART_NO, |
| 571 | .static_ops = sja1105r_table_ops, | 575 | .static_ops = sja1105r_table_ops, |
| 572 | .dyn_ops = sja1105pqrs_dyn_ops, | 576 | .dyn_ops = sja1105pqrs_dyn_ops, |
| 577 | .qinq_tpid = ETH_P_8021AD, | ||
| 573 | .ptp_ts_bits = 32, | 578 | .ptp_ts_bits = 32, |
| 574 | .ptpegr_ts_bytes = 8, | 579 | .ptpegr_ts_bytes = 8, |
| 575 | .setup_rgmii_delay = sja1105pqrs_setup_rgmii_delay, | 580 | .setup_rgmii_delay = sja1105pqrs_setup_rgmii_delay, |
| @@ -586,6 +591,7 @@ struct sja1105_info sja1105s_info = { · 10 unmodified lines | |||
| 586 | .static_ops = sja1105s_table_ops, | 591 | .static_ops = sja1105s_table_ops, |
| 587 | .dyn_ops = sja1105pqrs_dyn_ops, | 592 | .dyn_ops = sja1105pqrs_dyn_ops, |
| 588 | .regs = &sja1105pqrs_regs, | 593 | .regs = &sja1105pqrs_regs, |
| 594 | .qinq_tpid = ETH_P_8021AD, | ||
| 589 | .ptp_ts_bits = 32, | 595 | .ptp_ts_bits = 32, |
| 590 | .ptpegr_ts_bytes = 8, | 596 | .ptpegr_ts_bytes = 8, |
| 591 | .setup_rgmii_delay = sja1105pqrs_setup_rgmii_delay, | 597 | .setup_rgmii_delay = sja1105pqrs_setup_rgmii_delay, |
| @@ -59,6 +59,7 @@ struct sja1105_port { · 58 unmodified lines | |||
| 59 | struct sja1105_tagger_data *data; | 59 | struct sja1105_tagger_data *data; |
| 60 | struct dsa_port *dp; | 60 | struct dsa_port *dp; |
| 61 | bool hwts_tx_en; | 61 | bool hwts_tx_en; |
| 62 | u16 xmit_tpid; | ||
| 62 | }; | 63 | }; |
| 63 | 64 | ||
| 64 | #endif /* _NET_DSA_SJA1105_H */ | 65 | #endif /* _NET_DSA_SJA1105_H */ |
| @@ -69,12 +69,25 @@ static inline bool sja1105_is_meta_frame(const struct sk_buff *skb) · 68 unmodified lines | |||
| 69 | return true; | 69 | return true; |
| 70 | } | 70 | } |
| 71 | 71 | ||
| 72 | static bool sja1105_can_use_vlan_as_tags(const struct sk_buff *skb) | ||
| 73 | { | ||
| 74 | struct vlan_ethhdr *hdr = vlan_eth_hdr(skb); | ||
| 75 | |||
| 76 | if (hdr->h_vlan_proto == ntohs(ETH_P_SJA1105)) | ||
| 77 | return true; | ||
| 78 | |||
| 79 | if (hdr->h_vlan_proto != ntohs(ETH_P_8021Q)) | ||
| 80 | return false; | ||
| 81 | |||
| 82 | return vid_is_dsa_8021q(ntohs(hdr->h_vlan_TCI) & VLAN_VID_MASK); | ||
| 83 | } | ||
| 84 | |||
| 72 | /* This is the first time the tagger sees the frame on RX. | 85 | /* This is the first time the tagger sees the frame on RX. |
| 73 | * Figure out if we can decode it. | 86 | * Figure out if we can decode it. |
| 74 | */ | 87 | */ |
| 75 | static bool sja1105_filter(const struct sk_buff *skb, struct net_device *dev) | 88 | static bool sja1105_filter(const struct sk_buff *skb, struct net_device *dev) |
| 76 | { | 89 | { |
| 77 | if (!dsa_port_is_vlan_filtering(dev->dsa_ptr)) | 90 | if (sja1105_can_use_vlan_as_tags(skb)) |
| 78 | return true; | 91 | return true; |
| 79 | if (sja1105_is_link_local(skb)) | 92 | if (sja1105_is_link_local(skb)) |
| 80 | return true; | 93 | return true; |
| @@ -96,6 +109,11 @@ static struct sk_buff *sja1105_defer_xmit(struct sja1105_port *sp, · 15 unmodified lines | |||
| 96 | return NULL; | 109 | return NULL; |
| 97 | } | 110 | } |
| 98 | 111 | ||
| 112 | static u16 sja1105_xmit_tpid(struct sja1105_port *sp) | ||
| 113 | { | ||
| 114 | return sp->xmit_tpid; | ||
| 115 | } | ||
| 116 | |||
| 99 | static struct sk_buff *sja1105_xmit(struct sk_buff *skb, | 117 | static struct sk_buff *sja1105_xmit(struct sk_buff *skb, |
| 100 | struct net_device *netdev) | 118 | struct net_device *netdev) |
| 101 | { | 119 | { |
| @@ -111,15 +129,7 @@ static struct sk_buff *sja1105_xmit(struct sk_buff *skb, · 9 unmodified lines | |||
| 111 | if (unlikely(sja1105_is_link_local(skb))) | 129 | if (unlikely(sja1105_is_link_local(skb))) |
| 112 | return sja1105_defer_xmit(dp->priv, skb); | 130 | return sja1105_defer_xmit(dp->priv, skb); |
| 113 | 131 | ||
| 114 | /* If we are under a vlan_filtering bridge, IP termination on | 132 | return dsa_8021q_xmit(skb, netdev, sja1105_xmit_tpid(dp->priv), |
| 115 | * switch ports based on 802.1Q tags is simply too brittle to | ||
| 116 | * be passable. So just defer to the dsa_slave_notag_xmit | ||
| 117 | * implementation. | ||
| 118 | */ | ||
| 119 | if (dsa_port_is_vlan_filtering(dp)) | ||
| 120 | return skb; | ||
| 121 | |||
| 122 | return dsa_8021q_xmit(skb, netdev, ETH_P_SJA1105, | ||
| 123 | ((pcp << VLAN_PRIO_SHIFT) | tx_vid)); | 133 | ((pcp << VLAN_PRIO_SHIFT) | tx_vid)); |
| 124 | } | 134 | } |
| 125 | 135 | ||
| @@ -258,7 +268,7 @@ static struct sk_buff *sja1105_rcv(struct sk_buff *skb, · 132 unmodified lines | |||
| 258 | 268 | ||
| 259 | hdr = eth_hdr(skb); | 269 | hdr = eth_hdr(skb); |
| 260 | tpid = ntohs(hdr->h_proto); | 270 | tpid = ntohs(hdr->h_proto); |
| 261 | is_tagged = (tpid == ETH_P_SJA1105); | 271 | is_tagged = (tpid == ETH_P_SJA1105 || tpid == ETH_P_8021Q); |
| 262 | is_link_local = sja1105_is_link_local(skb); | 272 | is_link_local = sja1105_is_link_local(skb); |
| 263 | is_meta = sja1105_is_meta_frame(skb); | 273 | is_meta = sja1105_is_meta_frame(skb); |
| 264 | 274 | ||