diff mbox series

[1/2] net: emac: implement 802.1Q VLAN TX tagging support

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

Commit Message

Christian Lamparter Oct. 17, 2018, 7:53 p.m. UTC
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(-)

Comments

Florian Fainelli Oct. 17, 2018, 8:08 p.m. UTC | #1
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 ;)
Florian Fainelli Oct. 17, 2018, 8:09 p.m. UTC | #2
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 ;)
Christian Lamparter Oct. 19, 2018, 3:56 p.m. UTC | #3
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 mbox series

Patch

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,