diff mbox series

[net-next,v3,3/5] net: ipqess: Add out-of-band DSA tagging support

Message ID 20220826154650.615582-4-maxime.chevallier@bootlin.com (mailing list archive)
State Changes Requested
Delegated to: Netdev Maintainers
Headers show
Series net: ipqess: introduce Qualcomm IPQESS driver | expand

Checks

Context Check Description
netdev/tree_selection success Clearly marked for net-next, async
netdev/fixes_present success Fixes tag not required for -next series
netdev/subject_prefix success Link
netdev/cover_letter success Series has a cover letter
netdev/patch_count success Link
netdev/header_inline success No static functions without inline keyword in header files
netdev/build_32bit success Errors and warnings before: 0 this patch: 0
netdev/cc_maintainers warning 3 maintainers not CCed: edumazet@google.com kuba@kernel.org pabeni@redhat.com
netdev/build_clang success Errors and warnings before: 3 this patch: 3
netdev/module_param success Was 0 now: 0
netdev/verify_signedoff success Signed-off-by tag matches author and committer
netdev/check_selftest success No net selftest shell script
netdev/verify_fixes success No Fixes tag
netdev/build_allmodconfig_warn success Errors and warnings before: 3 this patch: 3
netdev/checkpatch warning WARNING: line length of 83 exceeds 80 columns
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/source_inline success Was 0 now: 0

Commit Message

Maxime Chevallier Aug. 26, 2022, 3:46 p.m. UTC
On the IPQ4019, there's an 5 ports switch connected to the CPU through
the IPQESS Ethernet controller. The way the DSA tag is sent-out to that
switch is through the DMA descriptor, due to how tightly it is
integrated with the switch.

This commit uses the out-of-band tagging protocol by getting the source
port from the descriptor, push it into the skb, and have the tagger pull
it to infer the destination netdev. The reverse process is done on the
TX side, where the driver pulls the tag from the skb and builds the
descriptor accordingly.

Signed-off-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
---
V2->V3:
 - No changes
V1->V2:
 - Use the new tagger, and the dsa_oob_tag_* helpers

 drivers/net/ethernet/qualcomm/Kconfig         |  3 ++-
 drivers/net/ethernet/qualcomm/ipqess/ipqess.c | 27 +++++++++++++++++++
 2 files changed, 29 insertions(+), 1 deletion(-)

Comments

Andrew Lunn Aug. 27, 2022, 7:12 p.m. UTC | #1
> @@ -409,6 +412,12 @@ static int ipqess_rx_poll(struct ipqess_rx_ring *rx_ring, int budget)
>  			__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021AD),
>  					       rd->rrd4);
>  
> +		if (netdev_uses_dsa(rx_ring->ess->netdev)) {
> +			tag_info.dp = FIELD_GET(IPQESS_RRD_PORT_ID_MASK, rd->rrd1);
> +			tag_info.proto = DSA_TAG_PROTO_OOB;
> +			dsa_oob_tag_push(skb, &tag_info);
> +		}
> +
>  		napi_gro_receive(&rx_ring->napi_rx, skb);
>  
>  		rx_ring->ess->stats.rx_packets++;
> @@ -713,6 +722,22 @@ static void ipqess_rollback_tx(struct ipqess *eth,
>  	tx_ring->head = start_index;
>  }
>  
> +static void ipqess_process_dsa_tag_sh(struct ipqess *ess, struct sk_buff *skb,
> +				      u32 *word3)
> +{
> +	struct dsa_oob_tag_info tag_info;
> +
> +	if (!netdev_uses_dsa(ess->netdev))
> +		return;
> +
> +	if (dsa_oob_tag_pop(skb, &tag_info))
> +		return;
> +
> +	*word3 |= tag_info.dp << IPQESS_TPD_PORT_BITMAP_SHIFT;
> +	*word3 |= BIT(IPQESS_TPD_FROM_CPU_SHIFT);
> +	*word3 |= 0x3e << IPQESS_TPD_PORT_BITMAP_SHIFT;
> +}

Using netdev_uses_dsa() here will work, but you are on the fast
path. You are following a lot of pointers, which could be bad on the
cache. You might want to consider caching this as a bool in struct
ipqess. Maybe update the cache on NETDEV_CHANGEUPPER?

	Andrew
diff mbox series

Patch

diff --git a/drivers/net/ethernet/qualcomm/Kconfig b/drivers/net/ethernet/qualcomm/Kconfig
index a723ddbea248..eeb2c608d6b9 100644
--- a/drivers/net/ethernet/qualcomm/Kconfig
+++ b/drivers/net/ethernet/qualcomm/Kconfig
@@ -62,8 +62,9 @@  config QCOM_EMAC
 
 config QCOM_IPQ4019_ESS_EDMA
 	tristate "Qualcomm Atheros IPQ4019 ESS EDMA support"
-	depends on OF
+	depends on OF && NET_DSA
 	select PHYLINK
+	select NET_DSA_TAG_OOB
 	help
 	  This driver supports the Qualcomm Atheros IPQ40xx built-in
 	  ESS EDMA ethernet controller.
diff --git a/drivers/net/ethernet/qualcomm/ipqess/ipqess.c b/drivers/net/ethernet/qualcomm/ipqess/ipqess.c
index 2783b4d66d45..da0d735342aa 100644
--- a/drivers/net/ethernet/qualcomm/ipqess/ipqess.c
+++ b/drivers/net/ethernet/qualcomm/ipqess/ipqess.c
@@ -9,6 +9,7 @@ 
 
 #include <linux/bitfield.h>
 #include <linux/clk.h>
+#include <linux/dsa/oob.h>
 #include <linux/if_vlan.h>
 #include <linux/interrupt.h>
 #include <linux/module.h>
@@ -22,6 +23,7 @@ 
 #include <linux/skbuff.h>
 #include <linux/vmalloc.h>
 #include <net/checksum.h>
+#include <net/dsa.h>
 #include <net/ip6_checksum.h>
 
 #include "ipqess.h"
@@ -330,6 +332,7 @@  static int ipqess_rx_poll(struct ipqess_rx_ring *rx_ring, int budget)
 	tail &= IPQESS_RFD_CONS_IDX_MASK;
 
 	while (done < budget) {
+		struct dsa_oob_tag_info tag_info;
 		struct ipqess_rx_desc *rd;
 		struct sk_buff *skb;
 
@@ -409,6 +412,12 @@  static int ipqess_rx_poll(struct ipqess_rx_ring *rx_ring, int budget)
 			__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021AD),
 					       rd->rrd4);
 
+		if (netdev_uses_dsa(rx_ring->ess->netdev)) {
+			tag_info.dp = FIELD_GET(IPQESS_RRD_PORT_ID_MASK, rd->rrd1);
+			tag_info.proto = DSA_TAG_PROTO_OOB;
+			dsa_oob_tag_push(skb, &tag_info);
+		}
+
 		napi_gro_receive(&rx_ring->napi_rx, skb);
 
 		rx_ring->ess->stats.rx_packets++;
@@ -713,6 +722,22 @@  static void ipqess_rollback_tx(struct ipqess *eth,
 	tx_ring->head = start_index;
 }
 
+static void ipqess_process_dsa_tag_sh(struct ipqess *ess, struct sk_buff *skb,
+				      u32 *word3)
+{
+	struct dsa_oob_tag_info tag_info;
+
+	if (!netdev_uses_dsa(ess->netdev))
+		return;
+
+	if (dsa_oob_tag_pop(skb, &tag_info))
+		return;
+
+	*word3 |= tag_info.dp << IPQESS_TPD_PORT_BITMAP_SHIFT;
+	*word3 |= BIT(IPQESS_TPD_FROM_CPU_SHIFT);
+	*word3 |= 0x3e << IPQESS_TPD_PORT_BITMAP_SHIFT;
+}
+
 static int ipqess_tx_map_and_fill(struct ipqess_tx_ring *tx_ring,
 				  struct sk_buff *skb)
 {
@@ -723,6 +748,8 @@  static int ipqess_tx_map_and_fill(struct ipqess_tx_ring *tx_ring,
 	u16 len;
 	int i;
 
+	ipqess_process_dsa_tag_sh(tx_ring->ess, skb, &word3);
+
 	if (skb_is_gso(skb)) {
 		if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV4) {
 			lso_word1 |= IPQESS_TPD_IPV4_EN;