Refresh patches. Remove upstreamed patches: - backport/080-v4.15-0001-arch-define-weak-abort.patch - backport/081-v4.15-0002-kernel-exit.c-export-abort-to-modules.patch Update patch that no longer applies: pending/493-ubi-set-ROOT_DEV-to-ubiblock-rootfs-if-unset.patch Fixes CVE-2017-8824. Compile-tested: octeon, x86/64. Runtime-tested: octeon, x86/64. Signed-off-by: Stijn Tintel <stijn@linux-ipv6.be>
		
			
				
	
	
		
			269 lines
		
	
	
		
			7.2 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			269 lines
		
	
	
		
			7.2 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
--- a/drivers/net/dsa/mt7530.c
 | 
						|
+++ b/drivers/net/dsa/mt7530.c
 | 
						|
@@ -670,6 +670,9 @@ static int
 | 
						|
 mt7530_cpu_port_enable(struct mt7530_priv *priv,
 | 
						|
 		       int port)
 | 
						|
 {
 | 
						|
+	u8 port_mask = 0;
 | 
						|
+	int i;
 | 
						|
+
 | 
						|
 	/* Enable Mediatek header mode on the cpu port */
 | 
						|
 	mt7530_write(priv, MT7530_PVC_P(port),
 | 
						|
 		     PORT_SPEC_TAG);
 | 
						|
@@ -686,8 +689,12 @@ mt7530_cpu_port_enable(struct mt7530_pri
 | 
						|
 	/* CPU port gets connected to all user ports of
 | 
						|
 	 * the switch
 | 
						|
 	 */
 | 
						|
+	for (i = 0; i < MT7530_NUM_PORTS; i++)
 | 
						|
+		if ((priv->ds->enabled_port_mask & BIT(i)) &&
 | 
						|
+		    (dsa_port_upstream_port(priv->ds, i) == port))
 | 
						|
+			port_mask |= BIT(i);
 | 
						|
 	mt7530_write(priv, MT7530_PCR_P(port),
 | 
						|
-		     PCR_MATRIX(priv->ds->enabled_port_mask));
 | 
						|
+		     PCR_MATRIX(port_mask));
 | 
						|
 
 | 
						|
 	return 0;
 | 
						|
 }
 | 
						|
@@ -697,6 +704,7 @@ mt7530_port_enable(struct dsa_switch *ds
 | 
						|
 		   struct phy_device *phy)
 | 
						|
 {
 | 
						|
 	struct mt7530_priv *priv = ds->priv;
 | 
						|
+	u8 upstream = dsa_port_upstream_port(ds, port);
 | 
						|
 
 | 
						|
 	mutex_lock(&priv->reg_mutex);
 | 
						|
 
 | 
						|
@@ -707,7 +715,7 @@ mt7530_port_enable(struct dsa_switch *ds
 | 
						|
 	 * restore the port matrix if the port is the member of a certain
 | 
						|
 	 * bridge.
 | 
						|
 	 */
 | 
						|
-	priv->ports[port].pm |= PCR_MATRIX(BIT(MT7530_CPU_PORT));
 | 
						|
+	priv->ports[port].pm |= PCR_MATRIX(BIT(upstream));
 | 
						|
 	priv->ports[port].enable = true;
 | 
						|
 	mt7530_rmw(priv, MT7530_PCR_P(port), PCR_MATRIX_MASK,
 | 
						|
 		   priv->ports[port].pm);
 | 
						|
@@ -770,7 +778,8 @@ mt7530_port_bridge_join(struct dsa_switc
 | 
						|
 			struct net_device *bridge)
 | 
						|
 {
 | 
						|
 	struct mt7530_priv *priv = ds->priv;
 | 
						|
-	u32 port_bitmap = BIT(MT7530_CPU_PORT);
 | 
						|
+	u8 upstream = dsa_port_upstream_port(ds, port);
 | 
						|
+	u32 port_bitmap = BIT(upstream);
 | 
						|
 	int i;
 | 
						|
 
 | 
						|
 	mutex_lock(&priv->reg_mutex);
 | 
						|
@@ -808,6 +817,7 @@ mt7530_port_bridge_leave(struct dsa_swit
 | 
						|
 			 struct net_device *bridge)
 | 
						|
 {
 | 
						|
 	struct mt7530_priv *priv = ds->priv;
 | 
						|
+	u8 upstream = dsa_port_upstream_port(ds, port);
 | 
						|
 	int i;
 | 
						|
 
 | 
						|
 	mutex_lock(&priv->reg_mutex);
 | 
						|
@@ -832,8 +842,8 @@ mt7530_port_bridge_leave(struct dsa_swit
 | 
						|
 	 */
 | 
						|
 	if (priv->ports[port].enable)
 | 
						|
 		mt7530_rmw(priv, MT7530_PCR_P(port), PCR_MATRIX_MASK,
 | 
						|
-			   PCR_MATRIX(BIT(MT7530_CPU_PORT)));
 | 
						|
-	priv->ports[port].pm = PCR_MATRIX(BIT(MT7530_CPU_PORT));
 | 
						|
+			   PCR_MATRIX(BIT(upstream)));
 | 
						|
+	priv->ports[port].pm = PCR_MATRIX(BIT(upstream));
 | 
						|
 
 | 
						|
 	mutex_unlock(&priv->reg_mutex);
 | 
						|
 }
 | 
						|
@@ -908,15 +918,7 @@ err:
 | 
						|
 static enum dsa_tag_protocol
 | 
						|
 mtk_get_tag_protocol(struct dsa_switch *ds)
 | 
						|
 {
 | 
						|
-	struct mt7530_priv *priv = ds->priv;
 | 
						|
-
 | 
						|
-	if (!dsa_is_cpu_port(ds, MT7530_CPU_PORT)) {
 | 
						|
-		dev_warn(priv->dev,
 | 
						|
-			 "port not matched with tagging CPU port\n");
 | 
						|
-		return DSA_TAG_PROTO_NONE;
 | 
						|
-	} else {
 | 
						|
-		return DSA_TAG_PROTO_MTK;
 | 
						|
-	}
 | 
						|
+	return DSA_TAG_PROTO_MTK;
 | 
						|
 }
 | 
						|
 
 | 
						|
 static int
 | 
						|
@@ -989,7 +991,7 @@ mt7530_setup(struct dsa_switch *ds)
 | 
						|
 
 | 
						|
 	/* Enable Port 6 only; P5 as GMAC5 which currently is not supported */
 | 
						|
 	val = mt7530_read(priv, MT7530_MHWTRAP);
 | 
						|
-	val &= ~MHWTRAP_P6_DIS & ~MHWTRAP_PHY_ACCESS;
 | 
						|
+	val &= ~MHWTRAP_P5_DIS & ~MHWTRAP_P6_DIS & ~MHWTRAP_PHY_ACCESS;
 | 
						|
 	val |= MHWTRAP_MANUAL;
 | 
						|
 	if (!dsa_is_cpu_port(ds, 5)) {
 | 
						|
 		val |= MHWTRAP_P5_DIS;
 | 
						|
--- a/include/net/dsa.h
 | 
						|
+++ b/include/net/dsa.h
 | 
						|
@@ -185,6 +185,10 @@ struct dsa_port {
 | 
						|
 	u8			stp_state;
 | 
						|
 	struct net_device	*bridge_dev;
 | 
						|
 	struct devlink_port	devlink_port;
 | 
						|
+
 | 
						|
+	struct net_device	*ethernet;
 | 
						|
+	int			upstream;
 | 
						|
+
 | 
						|
 	/*
 | 
						|
 	 * Original copy of the master netdev ethtool_ops
 | 
						|
 	 */
 | 
						|
@@ -266,6 +270,11 @@ static inline bool dsa_is_normal_port(st
 | 
						|
 	return !dsa_is_cpu_port(ds, p) && !dsa_is_dsa_port(ds, p);
 | 
						|
 }
 | 
						|
 
 | 
						|
+static inline bool dsa_is_upstream_port(struct dsa_switch *ds, int p)
 | 
						|
+{
 | 
						|
+	return dsa_is_cpu_port(ds, p) || dsa_is_dsa_port(ds, p);
 | 
						|
+}
 | 
						|
+
 | 
						|
 static inline u8 dsa_upstream_port(struct dsa_switch *ds)
 | 
						|
 {
 | 
						|
 	struct dsa_switch_tree *dst = ds->dst;
 | 
						|
@@ -282,6 +291,18 @@ static inline u8 dsa_upstream_port(struc
 | 
						|
 		return ds->rtable[dst->cpu_dp->ds->index];
 | 
						|
 }
 | 
						|
 
 | 
						|
+static inline u8 dsa_port_upstream_port(struct dsa_switch *ds, int port)
 | 
						|
+{
 | 
						|
+	/*
 | 
						|
+	 * If this port has a specific upstream cpu port, use it,
 | 
						|
+	 * otherwise use the switch default.
 | 
						|
+	 */
 | 
						|
+	if (ds->ports[port].upstream)
 | 
						|
+		return ds->ports[port].upstream;
 | 
						|
+	else
 | 
						|
+		return dsa_upstream_port(ds);
 | 
						|
+}
 | 
						|
+
 | 
						|
 typedef int dsa_fdb_dump_cb_t(const unsigned char *addr, u16 vid,
 | 
						|
 			      bool is_static, void *data);
 | 
						|
 struct dsa_switch_ops {
 | 
						|
--- a/net/dsa/dsa2.c
 | 
						|
+++ b/net/dsa/dsa2.c
 | 
						|
@@ -253,6 +253,8 @@ static int dsa_cpu_port_apply(struct dsa
 | 
						|
 	memset(&port->devlink_port, 0, sizeof(port->devlink_port));
 | 
						|
 	err = devlink_port_register(ds->devlink, &port->devlink_port,
 | 
						|
 				    port->index);
 | 
						|
+	if (port->netdev)
 | 
						|
+		port->netdev->dsa_ptr = ds->dst;
 | 
						|
 	return err;
 | 
						|
 }
 | 
						|
 
 | 
						|
@@ -262,6 +264,12 @@ static void dsa_cpu_port_unapply(struct
 | 
						|
 	dsa_cpu_dsa_destroy(port);
 | 
						|
 	port->ds->cpu_port_mask &= ~BIT(port->index);
 | 
						|
 
 | 
						|
+	if (port->netdev)
 | 
						|
+		port->netdev->dsa_ptr = NULL;
 | 
						|
+	if (port->ethernet) {
 | 
						|
+		dev_put(port->ethernet);
 | 
						|
+		port->ethernet = NULL;
 | 
						|
+	}
 | 
						|
 }
 | 
						|
 
 | 
						|
 static int dsa_user_port_apply(struct dsa_port *port)
 | 
						|
@@ -505,10 +513,9 @@ static int dsa_cpu_parse(struct dsa_port
 | 
						|
 		dev_put(ethernet_dev);
 | 
						|
 	}
 | 
						|
 
 | 
						|
-	if (!dst->cpu_dp) {
 | 
						|
+	if (!dst->cpu_dp)
 | 
						|
 		dst->cpu_dp = port;
 | 
						|
-		dst->cpu_dp->netdev = ethernet_dev;
 | 
						|
-	}
 | 
						|
+	port->netdev = ethernet_dev;
 | 
						|
 
 | 
						|
 	/* Initialize cpu_port_mask now for drv->setup()
 | 
						|
 	 * to have access to a correct value, just like what
 | 
						|
@@ -526,6 +533,29 @@ static int dsa_cpu_parse(struct dsa_port
 | 
						|
 
 | 
						|
 	dst->rcv = dst->tag_ops->rcv;
 | 
						|
 
 | 
						|
+	dev_hold(ethernet_dev);
 | 
						|
+	ds->ports[index].ethernet = ethernet_dev;
 | 
						|
+	ds->cpu_port_mask |= BIT(index);
 | 
						|
+
 | 
						|
+	return 0;
 | 
						|
+}
 | 
						|
+
 | 
						|
+static int dsa_user_parse(struct dsa_port *port, u32 index,
 | 
						|
+			  struct dsa_switch *ds)
 | 
						|
+{
 | 
						|
+	struct device_node *cpu_port;
 | 
						|
+	const unsigned int *cpu_port_reg;
 | 
						|
+	int cpu_port_index;
 | 
						|
+
 | 
						|
+	cpu_port = of_parse_phandle(port->dn, "cpu", 0);
 | 
						|
+	if (cpu_port) {
 | 
						|
+		cpu_port_reg = of_get_property(cpu_port, "reg", NULL);
 | 
						|
+		if (!cpu_port_reg)
 | 
						|
+			return -EINVAL;
 | 
						|
+		cpu_port_index = be32_to_cpup(cpu_port_reg);
 | 
						|
+		ds->ports[index].upstream = cpu_port_index;
 | 
						|
+	}
 | 
						|
+
 | 
						|
 	return 0;
 | 
						|
 }
 | 
						|
 
 | 
						|
@@ -533,7 +563,7 @@ static int dsa_ds_parse(struct dsa_switc
 | 
						|
 {
 | 
						|
 	struct dsa_port *port;
 | 
						|
 	u32 index;
 | 
						|
-	int err;
 | 
						|
+	int err = 0;
 | 
						|
 
 | 
						|
 	for (index = 0; index < ds->num_ports; index++) {
 | 
						|
 		port = &ds->ports[index];
 | 
						|
@@ -546,6 +576,9 @@ static int dsa_ds_parse(struct dsa_switc
 | 
						|
 			if (err)
 | 
						|
 				return err;
 | 
						|
 		} else {
 | 
						|
+			err = dsa_user_parse(port, index, ds);
 | 
						|
+			if (err)
 | 
						|
+				return err;
 | 
						|
 			/* Initialize enabled_port_mask now for drv->setup()
 | 
						|
 			 * to have access to a correct value, just like what
 | 
						|
 			 * net/dsa/dsa.c::dsa_switch_setup_one does.
 | 
						|
--- a/net/dsa/dsa_priv.h
 | 
						|
+++ b/net/dsa/dsa_priv.h
 | 
						|
@@ -91,6 +91,8 @@ struct dsa_slave_priv {
 | 
						|
 
 | 
						|
 	/* TC context */
 | 
						|
 	struct list_head	mall_tc_list;
 | 
						|
+
 | 
						|
+	struct net_device       *master;
 | 
						|
 };
 | 
						|
 
 | 
						|
 /* dsa.c */
 | 
						|
@@ -177,6 +179,9 @@ extern const struct dsa_device_ops trail
 | 
						|
 
 | 
						|
 static inline struct net_device *dsa_master_netdev(struct dsa_slave_priv *p)
 | 
						|
 {
 | 
						|
+	if (p->master)
 | 
						|
+		return p->master;
 | 
						|
+
 | 
						|
 	return p->dp->cpu_dp->netdev;
 | 
						|
 }
 | 
						|
 
 | 
						|
--- a/net/dsa/slave.c
 | 
						|
+++ b/net/dsa/slave.c
 | 
						|
@@ -1257,7 +1257,7 @@ int dsa_slave_create(struct dsa_port *po
 | 
						|
 	int ret;
 | 
						|
 
 | 
						|
 	cpu_dp = ds->dst->cpu_dp;
 | 
						|
-	master = cpu_dp->netdev;
 | 
						|
+	master = ds->ports[port->upstream].ethernet;
 | 
						|
 
 | 
						|
 	if (!ds->num_tx_queues)
 | 
						|
 		ds->num_tx_queues = 1;
 | 
						|
@@ -1295,6 +1295,7 @@ int dsa_slave_create(struct dsa_port *po
 | 
						|
 	p->dp = port;
 | 
						|
 	INIT_LIST_HEAD(&p->mall_tc_list);
 | 
						|
 	p->xmit = dst->tag_ops->xmit;
 | 
						|
+	p->master = master;
 | 
						|
 
 | 
						|
 	p->old_pause = -1;
 | 
						|
 	p->old_link = -1;
 |