Message ID | ee18e29386c00415991a790e88200ca6f5fd8fad.1539804852.git.chunkeey@gmail.com |
---|---|
State | Changes Requested, archived |
Delegated to: | David Miller |
Headers | show |
Series | [1/2] net: emac: implement 802.1Q VLAN TX tagging support | expand |
On 10/17/2018 12:53 PM, Christian Lamparter wrote: > As per' APM82181 Embedded Processor User Manual 26.1 EMAC Features: > VLAN: > - Support for VLAN tag ID in compliance with IEEE 802.3ac. > - VLAN tag insertion or replacement for transmit packets > > This patch completes the missing code for the VLAN tx tagging > support, as the the EMAC_MR1_VLE was already enabled. > > Signed-off-by: Christian Lamparter <chunkeey@gmail.com> > --- > drivers/net/ethernet/ibm/emac/core.c | 32 ++++++++++++++++++++++++---- > drivers/net/ethernet/ibm/emac/core.h | 6 +++++- > 2 files changed, 33 insertions(+), 5 deletions(-) > > diff --git a/drivers/net/ethernet/ibm/emac/core.c b/drivers/net/ethernet/ibm/emac/core.c > index 760b2ad8e295..be560f9031f4 100644 > --- a/drivers/net/ethernet/ibm/emac/core.c > +++ b/drivers/net/ethernet/ibm/emac/core.c > @@ -37,6 +37,7 @@ > #include <linux/ethtool.h> > #include <linux/mii.h> > #include <linux/bitops.h> > +#include <linux/if_vlan.h> > #include <linux/workqueue.h> > #include <linux/of.h> > #include <linux/of_address.h> > @@ -674,7 +675,7 @@ static int emac_configure(struct emac_instance *dev) > ndev->dev_addr[5]); > > /* VLAN Tag Protocol ID */ > - out_be32(&p->vtpid, 0x8100); > + out_be32(&p->vtpid, ETH_P_8021Q); > > /* Receive mode register */ > r = emac_iff2rmr(ndev); > @@ -1435,6 +1436,22 @@ static inline netdev_tx_t emac_xmit_finish(struct emac_instance *dev, int len) > return NETDEV_TX_OK; > } > > +static inline u16 emac_tx_vlan(struct emac_instance *dev, struct sk_buff *skb) > +{ > + /* Handle VLAN TPID and TCI insert if this is a VLAN skb */ > + if (emac_has_feature(dev, EMAC_FTR_HAS_VLAN_CTAG_TX) && > + skb_vlan_tag_present(skb)) { > + struct emac_regs __iomem *p = dev->emacp; > + > + /* update the VLAN TCI */ > + out_be32(&p->vtci, (u32)skb_vlan_tag_get(skb)); The only case where this is likely not going to be 0x8100/ETH_P_8021Q is if you do 802.1ad (QinQ) and you decided to somehow offload the S-Tag instead of the C-Tag. It would be a shame to slow down your TX path with an expensive register write, when maybe inserting the VLAN in software amounts to the same performance result ;)
On 10/17/2018 01:08 PM, Florian Fainelli wrote: > On 10/17/2018 12:53 PM, Christian Lamparter wrote: >> As per' APM82181 Embedded Processor User Manual 26.1 EMAC Features: >> VLAN: >> - Support for VLAN tag ID in compliance with IEEE 802.3ac. >> - VLAN tag insertion or replacement for transmit packets >> >> This patch completes the missing code for the VLAN tx tagging >> support, as the the EMAC_MR1_VLE was already enabled. >> >> Signed-off-by: Christian Lamparter <chunkeey@gmail.com> >> --- >> drivers/net/ethernet/ibm/emac/core.c | 32 ++++++++++++++++++++++++---- >> drivers/net/ethernet/ibm/emac/core.h | 6 +++++- >> 2 files changed, 33 insertions(+), 5 deletions(-) >> >> diff --git a/drivers/net/ethernet/ibm/emac/core.c b/drivers/net/ethernet/ibm/emac/core.c >> index 760b2ad8e295..be560f9031f4 100644 >> --- a/drivers/net/ethernet/ibm/emac/core.c >> +++ b/drivers/net/ethernet/ibm/emac/core.c >> @@ -37,6 +37,7 @@ >> #include <linux/ethtool.h> >> #include <linux/mii.h> >> #include <linux/bitops.h> >> +#include <linux/if_vlan.h> >> #include <linux/workqueue.h> >> #include <linux/of.h> >> #include <linux/of_address.h> >> @@ -674,7 +675,7 @@ static int emac_configure(struct emac_instance *dev) >> ndev->dev_addr[5]); >> >> /* VLAN Tag Protocol ID */ >> - out_be32(&p->vtpid, 0x8100); >> + out_be32(&p->vtpid, ETH_P_8021Q); >> >> /* Receive mode register */ >> r = emac_iff2rmr(ndev); >> @@ -1435,6 +1436,22 @@ static inline netdev_tx_t emac_xmit_finish(struct emac_instance *dev, int len) >> return NETDEV_TX_OK; >> } >> >> +static inline u16 emac_tx_vlan(struct emac_instance *dev, struct sk_buff *skb) >> +{ >> + /* Handle VLAN TPID and TCI insert if this is a VLAN skb */ >> + if (emac_has_feature(dev, EMAC_FTR_HAS_VLAN_CTAG_TX) && >> + skb_vlan_tag_present(skb)) { >> + struct emac_regs __iomem *p = dev->emacp; >> + >> + /* update the VLAN TCI */ >> + out_be32(&p->vtci, (u32)skb_vlan_tag_get(skb)); > > The only case where this is likely not going to be 0x8100/ETH_P_8021Q is > if you do 802.1ad (QinQ) and you decided to somehow offload the S-Tag > instead of the C-Tag. Sorry, looks like I mixed up TCI and TPID here, this looks obviously correct ;)
On Wednesday, October 17, 2018 10:09:10 PM CEST Florian Fainelli wrote: > On 10/17/2018 01:08 PM, Florian Fainelli wrote: > > On 10/17/2018 12:53 PM, Christian Lamparter wrote: > >> As per' APM82181 Embedded Processor User Manual 26.1 EMAC Features: > >> VLAN: > >> - Support for VLAN tag ID in compliance with IEEE 802.3ac. > >> - VLAN tag insertion or replacement for transmit packets > >> > >> This patch completes the missing code for the VLAN tx tagging > >> support, as the the EMAC_MR1_VLE was already enabled. > >> > >> Signed-off-by: Christian Lamparter <chunkeey@gmail.com> > >> --- > >> drivers/net/ethernet/ibm/emac/core.c | 32 ++++++++++++++++++++++++---- > >> drivers/net/ethernet/ibm/emac/core.h | 6 +++++- > >> 2 files changed, 33 insertions(+), 5 deletions(-) > >> > >> diff --git a/drivers/net/ethernet/ibm/emac/core.c b/drivers/net/ethernet/ibm/emac/core.c > >> index 760b2ad8e295..be560f9031f4 100644 > >> --- a/drivers/net/ethernet/ibm/emac/core.c > >> +++ b/drivers/net/ethernet/ibm/emac/core.c > >> @@ -37,6 +37,7 @@ > >> #include <linux/ethtool.h> > >> #include <linux/mii.h> > >> #include <linux/bitops.h> > >> +#include <linux/if_vlan.h> > >> #include <linux/workqueue.h> > >> #include <linux/of.h> > >> #include <linux/of_address.h> > >> @@ -674,7 +675,7 @@ static int emac_configure(struct emac_instance *dev) > >> ndev->dev_addr[5]); > >> > >> /* VLAN Tag Protocol ID */ > >> - out_be32(&p->vtpid, 0x8100); > >> + out_be32(&p->vtpid, ETH_P_8021Q); > >> > >> /* Receive mode register */ > >> r = emac_iff2rmr(ndev); > >> @@ -1435,6 +1436,22 @@ static inline netdev_tx_t emac_xmit_finish(struct emac_instance *dev, int len) > >> return NETDEV_TX_OK; > >> } > >> > >> +static inline u16 emac_tx_vlan(struct emac_instance *dev, struct sk_buff *skb) > >> +{ > >> + /* Handle VLAN TPID and TCI insert if this is a VLAN skb */ > >> + if (emac_has_feature(dev, EMAC_FTR_HAS_VLAN_CTAG_TX) && > >> + skb_vlan_tag_present(skb)) { > >> + struct emac_regs __iomem *p = dev->emacp; > >> + > >> + /* update the VLAN TCI */ > >> + out_be32(&p->vtci, (u32)skb_vlan_tag_get(skb)); > > > > The only case where this is likely not going to be 0x8100/ETH_P_8021Q is > > if you do 802.1ad (QinQ) and you decided to somehow offload the S-Tag > > instead of the C-Tag. > > Sorry, looks like I mixed up TCI and TPID here, this looks obviously > correct ;) Ok, I wasn't really sure what to write anyway ;). The hardware documentation mentions that: "Support for VLAN tag ID in compliance with IEEE Draft 802.3ac/D1.0 standard". It's too old for offloading any fancy QinQ stuff :(.
diff --git a/drivers/net/ethernet/ibm/emac/core.c b/drivers/net/ethernet/ibm/emac/core.c index 760b2ad8e295..be560f9031f4 100644 --- a/drivers/net/ethernet/ibm/emac/core.c +++ b/drivers/net/ethernet/ibm/emac/core.c @@ -37,6 +37,7 @@ #include <linux/ethtool.h> #include <linux/mii.h> #include <linux/bitops.h> +#include <linux/if_vlan.h> #include <linux/workqueue.h> #include <linux/of.h> #include <linux/of_address.h> @@ -674,7 +675,7 @@ static int emac_configure(struct emac_instance *dev) ndev->dev_addr[5]); /* VLAN Tag Protocol ID */ - out_be32(&p->vtpid, 0x8100); + out_be32(&p->vtpid, ETH_P_8021Q); /* Receive mode register */ r = emac_iff2rmr(ndev); @@ -1435,6 +1436,22 @@ static inline netdev_tx_t emac_xmit_finish(struct emac_instance *dev, int len) return NETDEV_TX_OK; } +static inline u16 emac_tx_vlan(struct emac_instance *dev, struct sk_buff *skb) +{ + /* Handle VLAN TPID and TCI insert if this is a VLAN skb */ + if (emac_has_feature(dev, EMAC_FTR_HAS_VLAN_CTAG_TX) && + skb_vlan_tag_present(skb)) { + struct emac_regs __iomem *p = dev->emacp; + + /* update the VLAN TCI */ + out_be32(&p->vtci, (u32)skb_vlan_tag_get(skb)); + + /* Insert VLAN tag */ + return EMAC_TX_CTRL_IVT; + } + return 0; +} + /* Tx lock BH */ static netdev_tx_t emac_start_xmit(struct sk_buff *skb, struct net_device *ndev) { @@ -1443,7 +1460,7 @@ static netdev_tx_t emac_start_xmit(struct sk_buff *skb, struct net_device *ndev) int slot; u16 ctrl = EMAC_TX_CTRL_GFCS | EMAC_TX_CTRL_GP | MAL_TX_CTRL_READY | - MAL_TX_CTRL_LAST | emac_tx_csum(dev, skb); + MAL_TX_CTRL_LAST | emac_tx_csum(dev, skb) | emac_tx_vlan(dev, skb); slot = dev->tx_slot++; if (dev->tx_slot == NUM_TX_BUFF) { @@ -1518,7 +1535,7 @@ emac_start_xmit_sg(struct sk_buff *skb, struct net_device *ndev) goto stop_queue; ctrl = EMAC_TX_CTRL_GFCS | EMAC_TX_CTRL_GP | MAL_TX_CTRL_READY | - emac_tx_csum(dev, skb); + emac_tx_csum(dev, skb) | emac_tx_vlan(dev, skb); slot = dev->tx_slot; /* skb data */ @@ -2891,7 +2908,8 @@ static int emac_init_config(struct emac_instance *dev) if (of_device_is_compatible(np, "ibm,emac-apm821xx")) { dev->features |= (EMAC_APM821XX_REQ_JUMBO_FRAME_SIZE | EMAC_FTR_APM821XX_NO_HALF_DUPLEX | - EMAC_FTR_460EX_PHY_CLK_FIX); + EMAC_FTR_460EX_PHY_CLK_FIX | + EMAC_FTR_HAS_VLAN_CTAG_TX); } } else if (of_device_is_compatible(np, "ibm,emac4")) { dev->features |= EMAC_FTR_EMAC4; @@ -3148,6 +3166,12 @@ static int emac_probe(struct platform_device *ofdev) if (dev->tah_dev) { ndev->hw_features = NETIF_F_IP_CSUM | NETIF_F_SG; + + if (emac_has_feature(dev, EMAC_FTR_HAS_VLAN_CTAG_TX)) { + ndev->vlan_features |= ndev->hw_features; + ndev->hw_features |= NETIF_F_HW_VLAN_CTAG_TX; + } + ndev->features |= ndev->hw_features | NETIF_F_RXCSUM; } ndev->watchdog_timeo = 5 * HZ; diff --git a/drivers/net/ethernet/ibm/emac/core.h b/drivers/net/ethernet/ibm/emac/core.h index 84caa4a3fc52..8d84d439168c 100644 --- a/drivers/net/ethernet/ibm/emac/core.h +++ b/drivers/net/ethernet/ibm/emac/core.h @@ -334,6 +334,8 @@ struct emac_instance { * APM821xx does not support Half Duplex mode */ #define EMAC_FTR_APM821XX_NO_HALF_DUPLEX 0x00001000 +/* EMAC can insert 802.1Q tag */ +#define EMAC_FTR_HAS_VLAN_CTAG_TX 0x00002000 /* Right now, we don't quite handle the always/possible masks on the * most optimal way as we don't have a way to say something like @@ -363,7 +365,9 @@ enum { EMAC_FTR_460EX_PHY_CLK_FIX | EMAC_FTR_440EP_PHY_CLK_FIX | EMAC_APM821XX_REQ_JUMBO_FRAME_SIZE | - EMAC_FTR_APM821XX_NO_HALF_DUPLEX, + EMAC_FTR_APM821XX_NO_HALF_DUPLEX | + EMAC_FTR_HAS_VLAN_CTAG_TX | + 0, }; static inline int emac_has_feature(struct emac_instance *dev,
As per' APM82181 Embedded Processor User Manual 26.1 EMAC Features: VLAN: - Support for VLAN tag ID in compliance with IEEE 802.3ac. - VLAN tag insertion or replacement for transmit packets This patch completes the missing code for the VLAN tx tagging support, as the the EMAC_MR1_VLE was already enabled. Signed-off-by: Christian Lamparter <chunkeey@gmail.com> --- drivers/net/ethernet/ibm/emac/core.c | 32 ++++++++++++++++++++++++---- drivers/net/ethernet/ibm/emac/core.h | 6 +++++- 2 files changed, 33 insertions(+), 5 deletions(-)