mirror of
				git://git.openwrt.org/openwrt/openwrt.git
				synced 2025-10-30 13:34:27 -04:00 
			
		
		
		
	Backport upstream code split patch for qca8k needed for ipq40xx target to correctly implement a DSA driver. Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
		
			
				
	
	
		
			238 lines
		
	
	
		
			6.5 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			238 lines
		
	
	
		
			6.5 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
| From fd3cae2f3ac190d06e48f43739237e02f9dc51ff Mon Sep 17 00:00:00 2001
 | |
| From: Christian Marangi <ansuelsmth@gmail.com>
 | |
| Date: Wed, 27 Jul 2022 13:35:17 +0200
 | |
| Subject: [PATCH 08/14] net: dsa: qca8k: move bridge functions to common code
 | |
| 
 | |
| The same bridge functions are used by drivers based on qca8k family
 | |
| switch. Move them to common code to make them accessible also by other
 | |
| drivers.
 | |
| While at it also drop unnecessary qca8k_priv cast for void pointers.
 | |
| 
 | |
| Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
 | |
| Reviewed-by: Vladimir Oltean <olteanv@gmail.com>
 | |
| Signed-off-by: Jakub Kicinski <kuba@kernel.org>
 | |
| ---
 | |
|  drivers/net/dsa/qca/qca8k-8xxx.c   | 93 ------------------------------
 | |
|  drivers/net/dsa/qca/qca8k-common.c | 93 ++++++++++++++++++++++++++++++
 | |
|  drivers/net/dsa/qca/qca8k.h        |  9 +++
 | |
|  3 files changed, 102 insertions(+), 93 deletions(-)
 | |
| 
 | |
| --- a/drivers/net/dsa/qca/qca8k-8xxx.c
 | |
| +++ b/drivers/net/dsa/qca/qca8k-8xxx.c
 | |
| @@ -2049,97 +2049,6 @@ exit:
 | |
|  }
 | |
|  
 | |
|  static void
 | |
| -qca8k_port_stp_state_set(struct dsa_switch *ds, int port, u8 state)
 | |
| -{
 | |
| -	struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv;
 | |
| -	u32 stp_state;
 | |
| -
 | |
| -	switch (state) {
 | |
| -	case BR_STATE_DISABLED:
 | |
| -		stp_state = QCA8K_PORT_LOOKUP_STATE_DISABLED;
 | |
| -		break;
 | |
| -	case BR_STATE_BLOCKING:
 | |
| -		stp_state = QCA8K_PORT_LOOKUP_STATE_BLOCKING;
 | |
| -		break;
 | |
| -	case BR_STATE_LISTENING:
 | |
| -		stp_state = QCA8K_PORT_LOOKUP_STATE_LISTENING;
 | |
| -		break;
 | |
| -	case BR_STATE_LEARNING:
 | |
| -		stp_state = QCA8K_PORT_LOOKUP_STATE_LEARNING;
 | |
| -		break;
 | |
| -	case BR_STATE_FORWARDING:
 | |
| -	default:
 | |
| -		stp_state = QCA8K_PORT_LOOKUP_STATE_FORWARD;
 | |
| -		break;
 | |
| -	}
 | |
| -
 | |
| -	qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(port),
 | |
| -		  QCA8K_PORT_LOOKUP_STATE_MASK, stp_state);
 | |
| -}
 | |
| -
 | |
| -static int
 | |
| -qca8k_port_bridge_join(struct dsa_switch *ds, int port, struct net_device *br)
 | |
| -{
 | |
| -	struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv;
 | |
| -	int port_mask, cpu_port;
 | |
| -	int i, ret;
 | |
| -
 | |
| -	cpu_port = dsa_to_port(ds, port)->cpu_dp->index;
 | |
| -	port_mask = BIT(cpu_port);
 | |
| -
 | |
| -	for (i = 0; i < QCA8K_NUM_PORTS; i++) {
 | |
| -		if (dsa_is_cpu_port(ds, i))
 | |
| -			continue;
 | |
| -		if (dsa_to_port(ds, i)->bridge_dev != br)
 | |
| -			continue;
 | |
| -		/* Add this port to the portvlan mask of the other ports
 | |
| -		 * in the bridge
 | |
| -		 */
 | |
| -		ret = regmap_set_bits(priv->regmap,
 | |
| -				      QCA8K_PORT_LOOKUP_CTRL(i),
 | |
| -				      BIT(port));
 | |
| -		if (ret)
 | |
| -			return ret;
 | |
| -		if (i != port)
 | |
| -			port_mask |= BIT(i);
 | |
| -	}
 | |
| -
 | |
| -	/* Add all other ports to this ports portvlan mask */
 | |
| -	ret = qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(port),
 | |
| -			QCA8K_PORT_LOOKUP_MEMBER, port_mask);
 | |
| -
 | |
| -	return ret;
 | |
| -}
 | |
| -
 | |
| -static void
 | |
| -qca8k_port_bridge_leave(struct dsa_switch *ds, int port, struct net_device *br)
 | |
| -{
 | |
| -	struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv;
 | |
| -	int cpu_port, i;
 | |
| -
 | |
| -	cpu_port = dsa_to_port(ds, port)->cpu_dp->index;
 | |
| -
 | |
| -	for (i = 0; i < QCA8K_NUM_PORTS; i++) {
 | |
| -		if (dsa_is_cpu_port(ds, i))
 | |
| -			continue;
 | |
| -		if (dsa_to_port(ds, i)->bridge_dev != br)
 | |
| -			continue;
 | |
| -		/* Remove this port to the portvlan mask of the other ports
 | |
| -		 * in the bridge
 | |
| -		 */
 | |
| -		regmap_clear_bits(priv->regmap,
 | |
| -				  QCA8K_PORT_LOOKUP_CTRL(i),
 | |
| -				  BIT(port));
 | |
| -	}
 | |
| -
 | |
| -	/* Set the cpu port to be the only one in the portvlan mask of
 | |
| -	 * this port
 | |
| -	 */
 | |
| -	qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(port),
 | |
| -		  QCA8K_PORT_LOOKUP_MEMBER, BIT(cpu_port));
 | |
| -}
 | |
| -
 | |
| -static void
 | |
|  qca8k_port_fast_age(struct dsa_switch *ds, int port)
 | |
|  {
 | |
|  	struct qca8k_priv *priv = ds->priv;
 | |
| --- a/drivers/net/dsa/qca/qca8k-common.c
 | |
| +++ b/drivers/net/dsa/qca/qca8k-common.c
 | |
| @@ -9,6 +9,7 @@
 | |
|  #include <linux/netdevice.h>
 | |
|  #include <linux/bitfield.h>
 | |
|  #include <net/dsa.h>
 | |
| +#include <linux/if_bridge.h>
 | |
|  
 | |
|  #include "qca8k.h"
 | |
|  
 | |
| @@ -276,3 +277,93 @@ int qca8k_get_mac_eee(struct dsa_switch
 | |
|  	/* Nothing to do on the port's MAC */
 | |
|  	return 0;
 | |
|  }
 | |
| +
 | |
| +void qca8k_port_stp_state_set(struct dsa_switch *ds, int port, u8 state)
 | |
| +{
 | |
| +	struct qca8k_priv *priv = ds->priv;
 | |
| +	u32 stp_state;
 | |
| +
 | |
| +	switch (state) {
 | |
| +	case BR_STATE_DISABLED:
 | |
| +		stp_state = QCA8K_PORT_LOOKUP_STATE_DISABLED;
 | |
| +		break;
 | |
| +	case BR_STATE_BLOCKING:
 | |
| +		stp_state = QCA8K_PORT_LOOKUP_STATE_BLOCKING;
 | |
| +		break;
 | |
| +	case BR_STATE_LISTENING:
 | |
| +		stp_state = QCA8K_PORT_LOOKUP_STATE_LISTENING;
 | |
| +		break;
 | |
| +	case BR_STATE_LEARNING:
 | |
| +		stp_state = QCA8K_PORT_LOOKUP_STATE_LEARNING;
 | |
| +		break;
 | |
| +	case BR_STATE_FORWARDING:
 | |
| +	default:
 | |
| +		stp_state = QCA8K_PORT_LOOKUP_STATE_FORWARD;
 | |
| +		break;
 | |
| +	}
 | |
| +
 | |
| +	qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(port),
 | |
| +		  QCA8K_PORT_LOOKUP_STATE_MASK, stp_state);
 | |
| +}
 | |
| +
 | |
| +int qca8k_port_bridge_join(struct dsa_switch *ds, int port,
 | |
| +			   struct net_device *br)
 | |
| +{
 | |
| +	struct qca8k_priv *priv = ds->priv;
 | |
| +	int port_mask, cpu_port;
 | |
| +	int i, ret;
 | |
| +
 | |
| +	cpu_port = dsa_to_port(ds, port)->cpu_dp->index;
 | |
| +	port_mask = BIT(cpu_port);
 | |
| +
 | |
| +	for (i = 0; i < QCA8K_NUM_PORTS; i++) {
 | |
| +		if (dsa_is_cpu_port(ds, i))
 | |
| +			continue;
 | |
| +		if (dsa_to_port(ds, i)->bridge_dev != br)
 | |
| +			continue;
 | |
| +		/* Add this port to the portvlan mask of the other ports
 | |
| +		 * in the bridge
 | |
| +		 */
 | |
| +		ret = regmap_set_bits(priv->regmap,
 | |
| +				      QCA8K_PORT_LOOKUP_CTRL(i),
 | |
| +				      BIT(port));
 | |
| +		if (ret)
 | |
| +			return ret;
 | |
| +		if (i != port)
 | |
| +			port_mask |= BIT(i);
 | |
| +	}
 | |
| +
 | |
| +	/* Add all other ports to this ports portvlan mask */
 | |
| +	ret = qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(port),
 | |
| +			QCA8K_PORT_LOOKUP_MEMBER, port_mask);
 | |
| +
 | |
| +	return ret;
 | |
| +}
 | |
| +
 | |
| +void qca8k_port_bridge_leave(struct dsa_switch *ds, int port,
 | |
| +			     struct net_device *br)
 | |
| +{
 | |
| +	struct qca8k_priv *priv = ds->priv;
 | |
| +	int cpu_port, i;
 | |
| +
 | |
| +	cpu_port = dsa_to_port(ds, port)->cpu_dp->index;
 | |
| +
 | |
| +	for (i = 0; i < QCA8K_NUM_PORTS; i++) {
 | |
| +		if (dsa_is_cpu_port(ds, i))
 | |
| +			continue;
 | |
| +		if (dsa_to_port(ds, i)->bridge_dev != br)
 | |
| +			continue;
 | |
| +		/* Remove this port to the portvlan mask of the other ports
 | |
| +		 * in the bridge
 | |
| +		 */
 | |
| +		regmap_clear_bits(priv->regmap,
 | |
| +				  QCA8K_PORT_LOOKUP_CTRL(i),
 | |
| +				  BIT(port));
 | |
| +	}
 | |
| +
 | |
| +	/* Set the cpu port to be the only one in the portvlan mask of
 | |
| +	 * this port
 | |
| +	 */
 | |
| +	qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(port),
 | |
| +		  QCA8K_PORT_LOOKUP_MEMBER, BIT(cpu_port));
 | |
| +}
 | |
| --- a/drivers/net/dsa/qca/qca8k.h
 | |
| +++ b/drivers/net/dsa/qca/qca8k.h
 | |
| @@ -446,4 +446,11 @@ int qca8k_get_sset_count(struct dsa_swit
 | |
|  int qca8k_set_mac_eee(struct dsa_switch *ds, int port, struct ethtool_eee *eee);
 | |
|  int qca8k_get_mac_eee(struct dsa_switch *ds, int port, struct ethtool_eee *e);
 | |
|  
 | |
| +/* Common bridge function */
 | |
| +void qca8k_port_stp_state_set(struct dsa_switch *ds, int port, u8 state);
 | |
| +int qca8k_port_bridge_join(struct dsa_switch *ds, int port,
 | |
| +			   struct net_device *br);
 | |
| +void qca8k_port_bridge_leave(struct dsa_switch *ds, int port,
 | |
| +			     struct net_device *br);
 | |
| +
 | |
|  #endif /* __QCA8K_H */
 |