Netdev List
 help / color / mirror / Atom feed
* [PATCH net-next 0/7] net: dsa: mv88e6xxx: factorize switch info
From: Vivien Didelot @ 2016-04-15 18:25 UTC (permalink / raw)
  To: netdev
  Cc: linux-kernel, kernel, David S. Miller, Florian Fainelli,
	Andrew Lunn, Vivien Didelot

This patchset factorizes drastically the mv88e6xxx code by sharing a new
extendable info structure to store static data such as switch family,
product number, number of ports, number of databases and the name.

The next step is to add a "features" bitmap member to the info structure
in order to simplify the shared code with a feature-based logic instead
of checking their family/ID.

This is a step forward having a single mv88e6xxx driver supporting many
similar devices, like any usual Linux driver.

Vivien Didelot (7):
  net: dsa: mv88e6xxx: drop double ds assignment
  net: dsa: mv88e6xxx: drop revision probing
  net: dsa: mv88e6xxx: add switch info
  net: dsa: mv88e6xxx: add family to info
  net: dsa: mv88e6xxx: add number of ports to info
  net: dsa: mv88e6xxx: add number of database to info
  net: dsa: mv88e6xxx: drop switch id

 drivers/net/dsa/mv88e6123.c |  29 +------
 drivers/net/dsa/mv88e6131.c |  32 ++-----
 drivers/net/dsa/mv88e6171.c |  15 ++--
 drivers/net/dsa/mv88e6352.c |  24 ++----
 drivers/net/dsa/mv88e6xxx.c | 201 ++++++++++++--------------------------------
 drivers/net/dsa/mv88e6xxx.h |  83 +++++++-----------
 6 files changed, 106 insertions(+), 278 deletions(-)

-- 
2.8.0

^ permalink raw reply

* [PATCH net-next 1/7] net: dsa: mv88e6xxx: drop double ds assignment
From: Vivien Didelot @ 2016-04-15 18:25 UTC (permalink / raw)
  To: netdev
  Cc: linux-kernel, kernel, David S. Miller, Florian Fainelli,
	Andrew Lunn, Vivien Didelot
In-Reply-To: <1460744750-13896-1-git-send-email-vivien.didelot@savoirfairelinux.com>

Every driver assigns ps->ds even though it gets assigned in the shared
mv88e6xxx_setup_common function. Kill redundancy.

Signed-off-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
---
 drivers/net/dsa/mv88e6123.c | 2 --
 drivers/net/dsa/mv88e6131.c | 2 --
 drivers/net/dsa/mv88e6171.c | 2 --
 drivers/net/dsa/mv88e6352.c | 2 --
 4 files changed, 8 deletions(-)

diff --git a/drivers/net/dsa/mv88e6123.c b/drivers/net/dsa/mv88e6123.c
index c34283d..88a812d 100644
--- a/drivers/net/dsa/mv88e6123.c
+++ b/drivers/net/dsa/mv88e6123.c
@@ -76,8 +76,6 @@ static int mv88e6123_setup(struct dsa_switch *ds)
 	struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
 	int ret;
 
-	ps->ds = ds;
-
 	ret = mv88e6xxx_setup_common(ds);
 	if (ret < 0)
 		return ret;
diff --git a/drivers/net/dsa/mv88e6131.c b/drivers/net/dsa/mv88e6131.c
index f5d75fc..6b2bcb0 100644
--- a/drivers/net/dsa/mv88e6131.c
+++ b/drivers/net/dsa/mv88e6131.c
@@ -94,8 +94,6 @@ static int mv88e6131_setup(struct dsa_switch *ds)
 	struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
 	int ret;
 
-	ps->ds = ds;
-
 	ret = mv88e6xxx_setup_common(ds);
 	if (ret < 0)
 		return ret;
diff --git a/drivers/net/dsa/mv88e6171.c b/drivers/net/dsa/mv88e6171.c
index f562250..40222b0 100644
--- a/drivers/net/dsa/mv88e6171.c
+++ b/drivers/net/dsa/mv88e6171.c
@@ -72,8 +72,6 @@ static int mv88e6171_setup(struct dsa_switch *ds)
 	struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
 	int ret;
 
-	ps->ds = ds;
-
 	ret = mv88e6xxx_setup_common(ds);
 	if (ret < 0)
 		return ret;
diff --git a/drivers/net/dsa/mv88e6352.c b/drivers/net/dsa/mv88e6352.c
index e54ee27..dbd920e 100644
--- a/drivers/net/dsa/mv88e6352.c
+++ b/drivers/net/dsa/mv88e6352.c
@@ -84,8 +84,6 @@ static int mv88e6352_setup(struct dsa_switch *ds)
 	struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
 	int ret;
 
-	ps->ds = ds;
-
 	ret = mv88e6xxx_setup_common(ds);
 	if (ret < 0)
 		return ret;
-- 
2.8.0

^ permalink raw reply related

* [PATCH net-next 2/7] net: dsa: mv88e6xxx: drop revision probing
From: Vivien Didelot @ 2016-04-15 18:25 UTC (permalink / raw)
  To: netdev
  Cc: linux-kernel, kernel, David S. Miller, Florian Fainelli,
	Andrew Lunn, Vivien Didelot
In-Reply-To: <1460744750-13896-1-git-send-email-vivien.didelot@savoirfairelinux.com>

There is no point in having special case for the revision when probing a
switch model. The code gets cluttered with unnecessary defines, and
leads to errors when code such as mv88e6131_setup compares
PORT_SWITCH_ID_6131_B2 to ps->id which mask the revision.

Drop every revision definitions, add a ps->rev variable for eventual
runtime checking and lookup only the product number.

Signed-off-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
---
 drivers/net/dsa/mv88e6123.c |  6 ------
 drivers/net/dsa/mv88e6131.c |  2 --
 drivers/net/dsa/mv88e6352.c |  6 ------
 drivers/net/dsa/mv88e6xxx.c | 19 ++++++-------------
 drivers/net/dsa/mv88e6xxx.h | 15 ++-------------
 5 files changed, 8 insertions(+), 40 deletions(-)

diff --git a/drivers/net/dsa/mv88e6123.c b/drivers/net/dsa/mv88e6123.c
index 88a812d..00c1121 100644
--- a/drivers/net/dsa/mv88e6123.c
+++ b/drivers/net/dsa/mv88e6123.c
@@ -19,14 +19,8 @@
 
 static const struct mv88e6xxx_switch_id mv88e6123_table[] = {
 	{ PORT_SWITCH_ID_6123, "Marvell 88E6123" },
-	{ PORT_SWITCH_ID_6123_A1, "Marvell 88E6123 (A1)" },
-	{ PORT_SWITCH_ID_6123_A2, "Marvell 88E6123 (A2)" },
 	{ PORT_SWITCH_ID_6161, "Marvell 88E6161" },
-	{ PORT_SWITCH_ID_6161_A1, "Marvell 88E6161 (A1)" },
-	{ PORT_SWITCH_ID_6161_A2, "Marvell 88E6161 (A2)" },
 	{ PORT_SWITCH_ID_6165, "Marvell 88E6165" },
-	{ PORT_SWITCH_ID_6165_A1, "Marvell 88E6165 (A1)" },
-	{ PORT_SWITCH_ID_6165_A2, "Marvell 88e6165 (A2)" },
 };
 
 static char *mv88e6123_drv_probe(struct device *dsa_dev,
diff --git a/drivers/net/dsa/mv88e6131.c b/drivers/net/dsa/mv88e6131.c
index 6b2bcb0..df534da 100644
--- a/drivers/net/dsa/mv88e6131.c
+++ b/drivers/net/dsa/mv88e6131.c
@@ -21,7 +21,6 @@ static const struct mv88e6xxx_switch_id mv88e6131_table[] = {
 	{ PORT_SWITCH_ID_6085, "Marvell 88E6085" },
 	{ PORT_SWITCH_ID_6095, "Marvell 88E6095/88E6095F" },
 	{ PORT_SWITCH_ID_6131, "Marvell 88E6131" },
-	{ PORT_SWITCH_ID_6131_B2, "Marvell 88E6131 (B2)" },
 	{ PORT_SWITCH_ID_6185, "Marvell 88E6185" },
 };
 
@@ -109,7 +108,6 @@ static int mv88e6131_setup(struct dsa_switch *ds)
 		ps->num_ports = 11;
 		break;
 	case PORT_SWITCH_ID_6131:
-	case PORT_SWITCH_ID_6131_B2:
 		ps->num_ports = 8;
 		break;
 	default:
diff --git a/drivers/net/dsa/mv88e6352.c b/drivers/net/dsa/mv88e6352.c
index dbd920e..30fc5f6 100644
--- a/drivers/net/dsa/mv88e6352.c
+++ b/drivers/net/dsa/mv88e6352.c
@@ -27,14 +27,8 @@ static const struct mv88e6xxx_switch_id mv88e6352_table[] = {
 	{ PORT_SWITCH_ID_6176, "Marvell 88E6176" },
 	{ PORT_SWITCH_ID_6240, "Marvell 88E6240" },
 	{ PORT_SWITCH_ID_6320, "Marvell 88E6320" },
-	{ PORT_SWITCH_ID_6320_A1, "Marvell 88E6320 (A1)" },
-	{ PORT_SWITCH_ID_6320_A2, "Marvell 88e6320 (A2)" },
 	{ PORT_SWITCH_ID_6321, "Marvell 88E6321" },
-	{ PORT_SWITCH_ID_6321_A1, "Marvell 88E6321 (A1)" },
-	{ PORT_SWITCH_ID_6321_A2, "Marvell 88e6321 (A2)" },
 	{ PORT_SWITCH_ID_6352, "Marvell 88E6352" },
-	{ PORT_SWITCH_ID_6352_A0, "Marvell 88E6352 (A0)" },
-	{ PORT_SWITCH_ID_6352_A1, "Marvell 88E6352 (A1)" },
 };
 
 static char *mv88e6352_drv_probe(struct device *dsa_dev,
diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c
index 9985a0c..ad29040 100644
--- a/drivers/net/dsa/mv88e6xxx.c
+++ b/drivers/net/dsa/mv88e6xxx.c
@@ -2663,11 +2663,15 @@ int mv88e6xxx_setup_ports(struct dsa_switch *ds)
 int mv88e6xxx_setup_common(struct dsa_switch *ds)
 {
 	struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
+	int id;
 
 	ps->ds = ds;
 	mutex_init(&ps->smi_mutex);
 
-	ps->id = REG_READ(REG_PORT(0), PORT_SWITCH_ID) & 0xfff0;
+	id = REG_READ(REG_PORT(0), PORT_SWITCH_ID);
+
+	ps->id = id & 0xfff0;
+	ps->rev = id & 0xf;
 
 	INIT_WORK(&ps->bridge_work, mv88e6xxx_bridge_work);
 
@@ -3083,19 +3087,8 @@ static char *mv88e6xxx_lookup_name(struct mii_bus *bus, int sw_addr,
 
 	/* Look up the exact switch ID */
 	for (i = 0; i < num; ++i)
-		if (table[i].id == ret)
-			return table[i].name;
-
-	/* Look up only the product number */
-	for (i = 0; i < num; ++i) {
-		if (table[i].id == (ret & PORT_SWITCH_ID_PROD_NUM_MASK)) {
-			dev_warn(&bus->dev,
-				 "unknown revision %d, using base switch 0x%x\n",
-				 ret & PORT_SWITCH_ID_REV_MASK,
-				 ret & PORT_SWITCH_ID_PROD_NUM_MASK);
+		if (table[i].id == (ret & 0xfff0))
 			return table[i].name;
-		}
-	}
 
 	return NULL;
 }
diff --git a/drivers/net/dsa/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx.h
index 5d27dec..7304f88 100644
--- a/drivers/net/dsa/mv88e6xxx.h
+++ b/drivers/net/dsa/mv88e6xxx.h
@@ -84,18 +84,11 @@
 #define PORT_SWITCH_ID_6121	0x1040
 #define PORT_SWITCH_ID_6122	0x1050
 #define PORT_SWITCH_ID_6123	0x1210
-#define PORT_SWITCH_ID_6123_A1	0x1212
-#define PORT_SWITCH_ID_6123_A2	0x1213
 #define PORT_SWITCH_ID_6131	0x1060
-#define PORT_SWITCH_ID_6131_B2	0x1066
 #define PORT_SWITCH_ID_6152	0x1a40
 #define PORT_SWITCH_ID_6155	0x1a50
 #define PORT_SWITCH_ID_6161	0x1610
-#define PORT_SWITCH_ID_6161_A1	0x1612
-#define PORT_SWITCH_ID_6161_A2	0x1613
 #define PORT_SWITCH_ID_6165	0x1650
-#define PORT_SWITCH_ID_6165_A1	0x1652
-#define PORT_SWITCH_ID_6165_A2	0x1653
 #define PORT_SWITCH_ID_6171	0x1710
 #define PORT_SWITCH_ID_6172	0x1720
 #define PORT_SWITCH_ID_6175	0x1750
@@ -104,16 +97,10 @@
 #define PORT_SWITCH_ID_6185	0x1a70
 #define PORT_SWITCH_ID_6240	0x2400
 #define PORT_SWITCH_ID_6320	0x1150
-#define PORT_SWITCH_ID_6320_A1	0x1151
-#define PORT_SWITCH_ID_6320_A2	0x1152
 #define PORT_SWITCH_ID_6321	0x3100
-#define PORT_SWITCH_ID_6321_A1	0x3101
-#define PORT_SWITCH_ID_6321_A2	0x3102
 #define PORT_SWITCH_ID_6350	0x3710
 #define PORT_SWITCH_ID_6351	0x3750
 #define PORT_SWITCH_ID_6352	0x3520
-#define PORT_SWITCH_ID_6352_A0	0x3521
-#define PORT_SWITCH_ID_6352_A1	0x3522
 #define PORT_CONTROL		0x04
 #define PORT_CONTROL_USE_CORE_TAG	BIT(15)
 #define PORT_CONTROL_DROP_ON_LOCK	BIT(14)
@@ -397,6 +384,8 @@ struct mv88e6xxx_priv_port {
 };
 
 struct mv88e6xxx_priv_state {
+	int rev;
+
 	/* The dsa_switch this private structure is related to */
 	struct dsa_switch *ds;
 
-- 
2.8.0

^ permalink raw reply related

* [PATCH net-next 3/7] net: dsa: mv88e6xxx: add switch info
From: Vivien Didelot @ 2016-04-15 18:25 UTC (permalink / raw)
  To: netdev
  Cc: linux-kernel, kernel, David S. Miller, Florian Fainelli,
	Andrew Lunn, Vivien Didelot
In-Reply-To: <1460744750-13896-1-git-send-email-vivien.didelot@savoirfairelinux.com>

Add a new switch info structure which will be later extended to store
switch models static information, such as product number, name, number
of ports, number of databases, etc.

Merge the lookup function in the probing code, so that we avoid multiple
checking of the MII bus, as well a multiple ID reading.

Signed-off-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
---
 drivers/net/dsa/mv88e6123.c |  8 +++---
 drivers/net/dsa/mv88e6131.c | 10 +++----
 drivers/net/dsa/mv88e6171.c | 10 +++----
 drivers/net/dsa/mv88e6352.c | 14 +++++-----
 drivers/net/dsa/mv88e6xxx.c | 67 +++++++++++++++++++--------------------------
 drivers/net/dsa/mv88e6xxx.h | 14 ++++++----
 6 files changed, 58 insertions(+), 65 deletions(-)

diff --git a/drivers/net/dsa/mv88e6123.c b/drivers/net/dsa/mv88e6123.c
index 00c1121..02bf16c 100644
--- a/drivers/net/dsa/mv88e6123.c
+++ b/drivers/net/dsa/mv88e6123.c
@@ -17,10 +17,10 @@
 #include <net/dsa.h>
 #include "mv88e6xxx.h"
 
-static const struct mv88e6xxx_switch_id mv88e6123_table[] = {
-	{ PORT_SWITCH_ID_6123, "Marvell 88E6123" },
-	{ PORT_SWITCH_ID_6161, "Marvell 88E6161" },
-	{ PORT_SWITCH_ID_6165, "Marvell 88E6165" },
+static const struct mv88e6xxx_info mv88e6123_table[] = {
+	{ MV88E6XXX_INFO(0x121, "Marvell 88E6123") },
+	{ MV88E6XXX_INFO(0x161, "Marvell 88E6161") },
+	{ MV88E6XXX_INFO(0x165, "Marvell 88E6165") },
 };
 
 static char *mv88e6123_drv_probe(struct device *dsa_dev,
diff --git a/drivers/net/dsa/mv88e6131.c b/drivers/net/dsa/mv88e6131.c
index df534da..27dd102 100644
--- a/drivers/net/dsa/mv88e6131.c
+++ b/drivers/net/dsa/mv88e6131.c
@@ -17,11 +17,11 @@
 #include <net/dsa.h>
 #include "mv88e6xxx.h"
 
-static const struct mv88e6xxx_switch_id mv88e6131_table[] = {
-	{ PORT_SWITCH_ID_6085, "Marvell 88E6085" },
-	{ PORT_SWITCH_ID_6095, "Marvell 88E6095/88E6095F" },
-	{ PORT_SWITCH_ID_6131, "Marvell 88E6131" },
-	{ PORT_SWITCH_ID_6185, "Marvell 88E6185" },
+static const struct mv88e6xxx_info mv88e6131_table[] = {
+	{ MV88E6XXX_INFO(0x095, "Marvell 88E6095/88E6095F") },
+	{ MV88E6XXX_INFO(0x04a, "Marvell 88E6085") },
+	{ MV88E6XXX_INFO(0x106, "Marvell 88E6131") },
+	{ MV88E6XXX_INFO(0x1a7, "Marvell 88E6185") },
 };
 
 static char *mv88e6131_drv_probe(struct device *dsa_dev,
diff --git a/drivers/net/dsa/mv88e6171.c b/drivers/net/dsa/mv88e6171.c
index 40222b0..334e097 100644
--- a/drivers/net/dsa/mv88e6171.c
+++ b/drivers/net/dsa/mv88e6171.c
@@ -17,11 +17,11 @@
 #include <net/dsa.h>
 #include "mv88e6xxx.h"
 
-static const struct mv88e6xxx_switch_id mv88e6171_table[] = {
-	{ PORT_SWITCH_ID_6171, "Marvell 88E6171" },
-	{ PORT_SWITCH_ID_6175, "Marvell 88E6175" },
-	{ PORT_SWITCH_ID_6350, "Marvell 88E6350" },
-	{ PORT_SWITCH_ID_6351, "Marvell 88E6351" },
+static const struct mv88e6xxx_info mv88e6171_table[] = {
+	{ MV88E6XXX_INFO(0x171, "Marvell 88E6171") },
+	{ MV88E6XXX_INFO(0x175, "Marvell 88E6175") },
+	{ MV88E6XXX_INFO(0x371, "Marvell 88E6350") },
+	{ MV88E6XXX_INFO(0x375, "Marvell 88E6351") },
 };
 
 static char *mv88e6171_drv_probe(struct device *dsa_dev,
diff --git a/drivers/net/dsa/mv88e6352.c b/drivers/net/dsa/mv88e6352.c
index 30fc5f6..371edd7 100644
--- a/drivers/net/dsa/mv88e6352.c
+++ b/drivers/net/dsa/mv88e6352.c
@@ -22,13 +22,13 @@
 #include <net/dsa.h>
 #include "mv88e6xxx.h"
 
-static const struct mv88e6xxx_switch_id mv88e6352_table[] = {
-	{ PORT_SWITCH_ID_6172, "Marvell 88E6172" },
-	{ PORT_SWITCH_ID_6176, "Marvell 88E6176" },
-	{ PORT_SWITCH_ID_6240, "Marvell 88E6240" },
-	{ PORT_SWITCH_ID_6320, "Marvell 88E6320" },
-	{ PORT_SWITCH_ID_6321, "Marvell 88E6321" },
-	{ PORT_SWITCH_ID_6352, "Marvell 88E6352" },
+static const struct mv88e6xxx_info mv88e6352_table[] = {
+	{ MV88E6XXX_INFO(0x115, "Marvell 88E6320") },
+	{ MV88E6XXX_INFO(0x310, "Marvell 88E6321") },
+	{ MV88E6XXX_INFO(0x172, "Marvell 88E6172") },
+	{ MV88E6XXX_INFO(0x176, "Marvell 88E6176") },
+	{ MV88E6XXX_INFO(0x240, "Marvell 88E6240") },
+	{ MV88E6XXX_INFO(0x352, "Marvell 88E6352") },
 };
 
 static char *mv88e6352_drv_probe(struct device *dsa_dev,
diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c
index ad29040..48fd1f4 100644
--- a/drivers/net/dsa/mv88e6xxx.c
+++ b/drivers/net/dsa/mv88e6xxx.c
@@ -2663,16 +2663,10 @@ int mv88e6xxx_setup_ports(struct dsa_switch *ds)
 int mv88e6xxx_setup_common(struct dsa_switch *ds)
 {
 	struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
-	int id;
 
 	ps->ds = ds;
 	mutex_init(&ps->smi_mutex);
 
-	id = REG_READ(REG_PORT(0), PORT_SWITCH_ID);
-
-	ps->id = id & 0xfff0;
-	ps->rev = id & 0xf;
-
 	INIT_WORK(&ps->bridge_work, mv88e6xxx_bridge_work);
 
 	return 0;
@@ -3072,51 +3066,46 @@ int mv88e6xxx_get_temp_alarm(struct dsa_switch *ds, bool *alarm)
 }
 #endif /* CONFIG_NET_DSA_HWMON */
 
-static char *mv88e6xxx_lookup_name(struct mii_bus *bus, int sw_addr,
-				   const struct mv88e6xxx_switch_id *table,
-				   unsigned int num)
+char *mv88e6xxx_drv_probe(struct device *dsa_dev, struct device *host_dev,
+			  int sw_addr, void **priv,
+			  const struct mv88e6xxx_info *table, unsigned int num)
 {
-	int i, ret;
+	const struct mv88e6xxx_info *info;
+	struct mv88e6xxx_priv_state *ps;
+	struct mii_bus *bus;
+	int id, i;
 
+	bus = dsa_host_dev_to_mii_bus(host_dev);
 	if (!bus)
 		return NULL;
 
-	ret = __mv88e6xxx_reg_read(bus, sw_addr, REG_PORT(0), PORT_SWITCH_ID);
-	if (ret < 0)
+	id = __mv88e6xxx_reg_read(bus, sw_addr, REG_PORT(0), PORT_SWITCH_ID);
+	if (id < 0)
 		return NULL;
 
-	/* Look up the exact switch ID */
-	for (i = 0; i < num; ++i)
-		if (table[i].id == (ret & 0xfff0))
-			return table[i].name;
+	for (i = 0, info = &table[i]; i < num; info = &table[++i])
+		if (info->prod_num == (id & 0xfff0) >> 4)
+			goto found;
 
 	return NULL;
-}
 
-char *mv88e6xxx_drv_probe(struct device *dsa_dev, struct device *host_dev,
-			  int sw_addr, void **priv,
-			  const struct mv88e6xxx_switch_id *table,
-			  unsigned int num)
-{
-	struct mv88e6xxx_priv_state *ps;
-	struct mii_bus *bus = dsa_host_dev_to_mii_bus(host_dev);
-	char *name;
-
-	if (!bus)
+found:
+	ps = devm_kzalloc(dsa_dev, sizeof(*ps), GFP_KERNEL);
+	if (!ps)
 		return NULL;
 
-	name = mv88e6xxx_lookup_name(bus, sw_addr, table, num);
-	if (name) {
-		ps = devm_kzalloc(dsa_dev, sizeof(*ps), GFP_KERNEL);
-		if (!ps)
-			return NULL;
-		*priv = ps;
-		ps->bus = dsa_host_dev_to_mii_bus(host_dev);
-		if (!ps->bus)
-			return NULL;
-		ps->sw_addr = sw_addr;
-	}
-	return name;
+	*priv = ps;
+
+	ps->bus = bus;
+	ps->sw_addr = sw_addr;
+	ps->info = info;
+	ps->id = id & 0xfff0;
+	ps->rev = id & 0xf;
+
+	dev_info(&ps->bus->dev, "found switch %s, revision %u\n",
+		 ps->info->name, ps->rev);
+
+	return (char *) ps->info->name;
 }
 
 static int __init mv88e6xxx_init(void)
diff --git a/drivers/net/dsa/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx.h
index 7304f88..5556098 100644
--- a/drivers/net/dsa/mv88e6xxx.h
+++ b/drivers/net/dsa/mv88e6xxx.h
@@ -354,11 +354,15 @@
 
 #define MV88E6XXX_N_FID		4096
 
-struct mv88e6xxx_switch_id {
-	u16 id;
-	char *name;
+struct mv88e6xxx_info {
+	u16 prod_num;
+	const char *name;
 };
 
+#define MV88E6XXX_INFO(_prod_num, _name) \
+	.prod_num = _prod_num, \
+	.name = _name, \
+
 struct mv88e6xxx_atu_entry {
 	u16	fid;
 	u8	state;
@@ -384,6 +388,7 @@ struct mv88e6xxx_priv_port {
 };
 
 struct mv88e6xxx_priv_state {
+	const struct mv88e6xxx_info *info;
 	int rev;
 
 	/* The dsa_switch this private structure is related to */
@@ -453,8 +458,7 @@ struct mv88e6xxx_hw_stat {
 int mv88e6xxx_switch_reset(struct dsa_switch *ds, bool ppu_active);
 char *mv88e6xxx_drv_probe(struct device *dsa_dev, struct device *host_dev,
 			  int sw_addr, void **priv,
-			  const struct mv88e6xxx_switch_id *table,
-			  unsigned int num);
+			  const struct mv88e6xxx_info *table, unsigned int num);
 
 int mv88e6xxx_setup_ports(struct dsa_switch *ds);
 int mv88e6xxx_setup_common(struct dsa_switch *ds);
-- 
2.8.0

^ permalink raw reply related

* [PATCH net-next 4/7] net: dsa: mv88e6xxx: add family to info
From: Vivien Didelot @ 2016-04-15 18:25 UTC (permalink / raw)
  To: netdev
  Cc: linux-kernel, kernel, David S. Miller, Florian Fainelli,
	Andrew Lunn, Vivien Didelot
In-Reply-To: <1460744750-13896-1-git-send-email-vivien.didelot@savoirfairelinux.com>

Add an mv88e6xxx_family enum to the info structure for better family
indentification.

Signed-off-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
---
 drivers/net/dsa/mv88e6123.c |  6 ++--
 drivers/net/dsa/mv88e6131.c |  8 ++---
 drivers/net/dsa/mv88e6171.c |  8 ++---
 drivers/net/dsa/mv88e6352.c | 12 ++++----
 drivers/net/dsa/mv88e6xxx.c | 71 +++++----------------------------------------
 drivers/net/dsa/mv88e6xxx.h | 16 +++++++++-
 6 files changed, 40 insertions(+), 81 deletions(-)

diff --git a/drivers/net/dsa/mv88e6123.c b/drivers/net/dsa/mv88e6123.c
index 02bf16c..36a0340 100644
--- a/drivers/net/dsa/mv88e6123.c
+++ b/drivers/net/dsa/mv88e6123.c
@@ -18,9 +18,9 @@
 #include "mv88e6xxx.h"
 
 static const struct mv88e6xxx_info mv88e6123_table[] = {
-	{ MV88E6XXX_INFO(0x121, "Marvell 88E6123") },
-	{ MV88E6XXX_INFO(0x161, "Marvell 88E6161") },
-	{ MV88E6XXX_INFO(0x165, "Marvell 88E6165") },
+	{ MV88E6XXX_INFO(6165, 0x121, "Marvell 88E6123") },
+	{ MV88E6XXX_INFO(6165, 0x161, "Marvell 88E6161") },
+	{ MV88E6XXX_INFO(6165, 0x165, "Marvell 88E6165") },
 };
 
 static char *mv88e6123_drv_probe(struct device *dsa_dev,
diff --git a/drivers/net/dsa/mv88e6131.c b/drivers/net/dsa/mv88e6131.c
index 27dd102..f75d2dd 100644
--- a/drivers/net/dsa/mv88e6131.c
+++ b/drivers/net/dsa/mv88e6131.c
@@ -18,10 +18,10 @@
 #include "mv88e6xxx.h"
 
 static const struct mv88e6xxx_info mv88e6131_table[] = {
-	{ MV88E6XXX_INFO(0x095, "Marvell 88E6095/88E6095F") },
-	{ MV88E6XXX_INFO(0x04a, "Marvell 88E6085") },
-	{ MV88E6XXX_INFO(0x106, "Marvell 88E6131") },
-	{ MV88E6XXX_INFO(0x1a7, "Marvell 88E6185") },
+	{ MV88E6XXX_INFO(6095, 0x095, "Marvell 88E6095/88E6095F") },
+	{ MV88E6XXX_INFO(6097, 0x04a, "Marvell 88E6085") },
+	{ MV88E6XXX_INFO(6185, 0x106, "Marvell 88E6131") },
+	{ MV88E6XXX_INFO(6185, 0x1a7, "Marvell 88E6185") },
 };
 
 static char *mv88e6131_drv_probe(struct device *dsa_dev,
diff --git a/drivers/net/dsa/mv88e6171.c b/drivers/net/dsa/mv88e6171.c
index 334e097..cb5bb19 100644
--- a/drivers/net/dsa/mv88e6171.c
+++ b/drivers/net/dsa/mv88e6171.c
@@ -18,10 +18,10 @@
 #include "mv88e6xxx.h"
 
 static const struct mv88e6xxx_info mv88e6171_table[] = {
-	{ MV88E6XXX_INFO(0x171, "Marvell 88E6171") },
-	{ MV88E6XXX_INFO(0x175, "Marvell 88E6175") },
-	{ MV88E6XXX_INFO(0x371, "Marvell 88E6350") },
-	{ MV88E6XXX_INFO(0x375, "Marvell 88E6351") },
+	{ MV88E6XXX_INFO(6351, 0x171, "Marvell 88E6171") },
+	{ MV88E6XXX_INFO(6351, 0x175, "Marvell 88E6175") },
+	{ MV88E6XXX_INFO(6351, 0x371, "Marvell 88E6350") },
+	{ MV88E6XXX_INFO(6351, 0x375, "Marvell 88E6351") },
 };
 
 static char *mv88e6171_drv_probe(struct device *dsa_dev,
diff --git a/drivers/net/dsa/mv88e6352.c b/drivers/net/dsa/mv88e6352.c
index 371edd7..94db0c3 100644
--- a/drivers/net/dsa/mv88e6352.c
+++ b/drivers/net/dsa/mv88e6352.c
@@ -23,12 +23,12 @@
 #include "mv88e6xxx.h"
 
 static const struct mv88e6xxx_info mv88e6352_table[] = {
-	{ MV88E6XXX_INFO(0x115, "Marvell 88E6320") },
-	{ MV88E6XXX_INFO(0x310, "Marvell 88E6321") },
-	{ MV88E6XXX_INFO(0x172, "Marvell 88E6172") },
-	{ MV88E6XXX_INFO(0x176, "Marvell 88E6176") },
-	{ MV88E6XXX_INFO(0x240, "Marvell 88E6240") },
-	{ MV88E6XXX_INFO(0x352, "Marvell 88E6352") },
+	{ MV88E6XXX_INFO(6320, 0x115, "Marvell 88E6320") },
+	{ MV88E6XXX_INFO(6320, 0x310, "Marvell 88E6321") },
+	{ MV88E6XXX_INFO(6352, 0x172, "Marvell 88E6172") },
+	{ MV88E6XXX_INFO(6352, 0x176, "Marvell 88E6176") },
+	{ MV88E6XXX_INFO(6352, 0x240, "Marvell 88E6240") },
+	{ MV88E6XXX_INFO(6352, 0x352, "Marvell 88E6352") },
 };
 
 static char *mv88e6352_drv_probe(struct device *dsa_dev,
diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c
index 48fd1f4..05d59f9 100644
--- a/drivers/net/dsa/mv88e6xxx.c
+++ b/drivers/net/dsa/mv88e6xxx.c
@@ -369,111 +369,56 @@ static bool mv88e6xxx_6065_family(struct dsa_switch *ds)
 {
 	struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
 
-	switch (ps->id) {
-	case PORT_SWITCH_ID_6031:
-	case PORT_SWITCH_ID_6061:
-	case PORT_SWITCH_ID_6035:
-	case PORT_SWITCH_ID_6065:
-		return true;
-	}
-	return false;
+	return ps->info->family == MV88E6XXX_FAMILY_6065;
 }
 
 static bool mv88e6xxx_6095_family(struct dsa_switch *ds)
 {
 	struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
 
-	switch (ps->id) {
-	case PORT_SWITCH_ID_6092:
-	case PORT_SWITCH_ID_6095:
-		return true;
-	}
-	return false;
+	return ps->info->family == MV88E6XXX_FAMILY_6095;
 }
 
 static bool mv88e6xxx_6097_family(struct dsa_switch *ds)
 {
 	struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
 
-	switch (ps->id) {
-	case PORT_SWITCH_ID_6046:
-	case PORT_SWITCH_ID_6085:
-	case PORT_SWITCH_ID_6096:
-	case PORT_SWITCH_ID_6097:
-		return true;
-	}
-	return false;
+	return ps->info->family == MV88E6XXX_FAMILY_6097;
 }
 
 static bool mv88e6xxx_6165_family(struct dsa_switch *ds)
 {
 	struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
 
-	switch (ps->id) {
-	case PORT_SWITCH_ID_6123:
-	case PORT_SWITCH_ID_6161:
-	case PORT_SWITCH_ID_6165:
-		return true;
-	}
-	return false;
+	return ps->info->family == MV88E6XXX_FAMILY_6165;
 }
 
 static bool mv88e6xxx_6185_family(struct dsa_switch *ds)
 {
 	struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
 
-	switch (ps->id) {
-	case PORT_SWITCH_ID_6121:
-	case PORT_SWITCH_ID_6122:
-	case PORT_SWITCH_ID_6152:
-	case PORT_SWITCH_ID_6155:
-	case PORT_SWITCH_ID_6182:
-	case PORT_SWITCH_ID_6185:
-	case PORT_SWITCH_ID_6108:
-	case PORT_SWITCH_ID_6131:
-		return true;
-	}
-	return false;
+	return ps->info->family == MV88E6XXX_FAMILY_6185;
 }
 
 static bool mv88e6xxx_6320_family(struct dsa_switch *ds)
 {
 	struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
 
-	switch (ps->id) {
-	case PORT_SWITCH_ID_6320:
-	case PORT_SWITCH_ID_6321:
-		return true;
-	}
-	return false;
+	return ps->info->family == MV88E6XXX_FAMILY_6320;
 }
 
 static bool mv88e6xxx_6351_family(struct dsa_switch *ds)
 {
 	struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
 
-	switch (ps->id) {
-	case PORT_SWITCH_ID_6171:
-	case PORT_SWITCH_ID_6175:
-	case PORT_SWITCH_ID_6350:
-	case PORT_SWITCH_ID_6351:
-		return true;
-	}
-	return false;
+	return ps->info->family == MV88E6XXX_FAMILY_6351;
 }
 
 static bool mv88e6xxx_6352_family(struct dsa_switch *ds)
 {
 	struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
 
-	switch (ps->id) {
-	case PORT_SWITCH_ID_6172:
-	case PORT_SWITCH_ID_6176:
-	case PORT_SWITCH_ID_6240:
-	case PORT_SWITCH_ID_6352:
-		return true;
-	}
-	return false;
+	return ps->info->family == MV88E6XXX_FAMILY_6352;
 }
 
 static unsigned int mv88e6xxx_num_databases(struct dsa_switch *ds)
diff --git a/drivers/net/dsa/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx.h
index 5556098..3d2a186 100644
--- a/drivers/net/dsa/mv88e6xxx.h
+++ b/drivers/net/dsa/mv88e6xxx.h
@@ -352,14 +352,28 @@
 #define GLOBAL2_QOS_WEIGHT	0x1c
 #define GLOBAL2_MISC		0x1d
 
+enum mv88e6xxx_family {
+	MV88E6XXX_FAMILY_NONE,
+	MV88E6XXX_FAMILY_6065,	/* 6031 6035 6061 6065 */
+	MV88E6XXX_FAMILY_6095,	/* 6092 6095 */
+	MV88E6XXX_FAMILY_6097,	/* 6046 6085 6096 6097 */
+	MV88E6XXX_FAMILY_6165,	/* 6123 6161 6165 */
+	MV88E6XXX_FAMILY_6185,	/* 6108 6121 6122 6131 6152 6155 6182 6185 */
+	MV88E6XXX_FAMILY_6320,	/* 6320 6321 */
+	MV88E6XXX_FAMILY_6351,	/* 6171 6175 6350 6351 */
+	MV88E6XXX_FAMILY_6352,	/* 6172 6176 6240 6352 */
+};
+
 #define MV88E6XXX_N_FID		4096
 
 struct mv88e6xxx_info {
+	enum mv88e6xxx_family family;
 	u16 prod_num;
 	const char *name;
 };
 
-#define MV88E6XXX_INFO(_prod_num, _name) \
+#define MV88E6XXX_INFO(_family, _prod_num, _name) \
+	.family = MV88E6XXX_FAMILY_##_family, \
 	.prod_num = _prod_num, \
 	.name = _name, \
 
-- 
2.8.0

^ permalink raw reply related

* [PATCH net-next 5/7] net: dsa: mv88e6xxx: add number of ports to info
From: Vivien Didelot @ 2016-04-15 18:25 UTC (permalink / raw)
  To: netdev
  Cc: linux-kernel, kernel, David S. Miller, Florian Fainelli,
	Andrew Lunn, Vivien Didelot
In-Reply-To: <1460744750-13896-1-git-send-email-vivien.didelot@savoirfairelinux.com>

Drop the ps->num_ports variable for a new member of the info structure.
This removes the need to assign it at setup time.

Signed-off-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
---
 drivers/net/dsa/mv88e6123.c | 19 +++----------------
 drivers/net/dsa/mv88e6131.c | 26 +++++---------------------
 drivers/net/dsa/mv88e6171.c | 11 ++++-------
 drivers/net/dsa/mv88e6352.c | 14 ++++++--------
 drivers/net/dsa/mv88e6xxx.c | 38 +++++++++++++++++++-------------------
 drivers/net/dsa/mv88e6xxx.h |  6 +++---
 6 files changed, 40 insertions(+), 74 deletions(-)

diff --git a/drivers/net/dsa/mv88e6123.c b/drivers/net/dsa/mv88e6123.c
index 36a0340..2048719 100644
--- a/drivers/net/dsa/mv88e6123.c
+++ b/drivers/net/dsa/mv88e6123.c
@@ -18,9 +18,9 @@
 #include "mv88e6xxx.h"
 
 static const struct mv88e6xxx_info mv88e6123_table[] = {
-	{ MV88E6XXX_INFO(6165, 0x121, "Marvell 88E6123") },
-	{ MV88E6XXX_INFO(6165, 0x161, "Marvell 88E6161") },
-	{ MV88E6XXX_INFO(6165, 0x165, "Marvell 88E6165") },
+	{ MV88E6XXX_INFO(6165, 0x121, 3, "Marvell 88E6123") },
+	{ MV88E6XXX_INFO(6165, 0x161, 6, "Marvell 88E6161") },
+	{ MV88E6XXX_INFO(6165, 0x165, 6, "Marvell 88E6165") },
 };
 
 static char *mv88e6123_drv_probe(struct device *dsa_dev,
@@ -67,25 +67,12 @@ static int mv88e6123_setup_global(struct dsa_switch *ds)
 
 static int mv88e6123_setup(struct dsa_switch *ds)
 {
-	struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
 	int ret;
 
 	ret = mv88e6xxx_setup_common(ds);
 	if (ret < 0)
 		return ret;
 
-	switch (ps->id) {
-	case PORT_SWITCH_ID_6123:
-		ps->num_ports = 3;
-		break;
-	case PORT_SWITCH_ID_6161:
-	case PORT_SWITCH_ID_6165:
-		ps->num_ports = 6;
-		break;
-	default:
-		return -ENODEV;
-	}
-
 	ret = mv88e6xxx_switch_reset(ds, false);
 	if (ret < 0)
 		return ret;
diff --git a/drivers/net/dsa/mv88e6131.c b/drivers/net/dsa/mv88e6131.c
index f75d2dd..2eb9fa3 100644
--- a/drivers/net/dsa/mv88e6131.c
+++ b/drivers/net/dsa/mv88e6131.c
@@ -18,10 +18,10 @@
 #include "mv88e6xxx.h"
 
 static const struct mv88e6xxx_info mv88e6131_table[] = {
-	{ MV88E6XXX_INFO(6095, 0x095, "Marvell 88E6095/88E6095F") },
-	{ MV88E6XXX_INFO(6097, 0x04a, "Marvell 88E6085") },
-	{ MV88E6XXX_INFO(6185, 0x106, "Marvell 88E6131") },
-	{ MV88E6XXX_INFO(6185, 0x1a7, "Marvell 88E6185") },
+	{ MV88E6XXX_INFO(6095, 0x095, 11, "Marvell 88E6095/88E6095F") },
+	{ MV88E6XXX_INFO(6097, 0x04a, 10, "Marvell 88E6085") },
+	{ MV88E6XXX_INFO(6185, 0x106, 8,  "Marvell 88E6131") },
+	{ MV88E6XXX_INFO(6185, 0x1a7, 10, "Marvell 88E6185") },
 };
 
 static char *mv88e6131_drv_probe(struct device *dsa_dev,
@@ -90,7 +90,6 @@ static int mv88e6131_setup_global(struct dsa_switch *ds)
 
 static int mv88e6131_setup(struct dsa_switch *ds)
 {
-	struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
 	int ret;
 
 	ret = mv88e6xxx_setup_common(ds);
@@ -99,21 +98,6 @@ static int mv88e6131_setup(struct dsa_switch *ds)
 
 	mv88e6xxx_ppu_state_init(ds);
 
-	switch (ps->id) {
-	case PORT_SWITCH_ID_6085:
-	case PORT_SWITCH_ID_6185:
-		ps->num_ports = 10;
-		break;
-	case PORT_SWITCH_ID_6095:
-		ps->num_ports = 11;
-		break;
-	case PORT_SWITCH_ID_6131:
-		ps->num_ports = 8;
-		break;
-	default:
-		return -ENODEV;
-	}
-
 	ret = mv88e6xxx_switch_reset(ds, false);
 	if (ret < 0)
 		return ret;
@@ -129,7 +113,7 @@ static int mv88e6131_port_to_phy_addr(struct dsa_switch *ds, int port)
 {
 	struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
 
-	if (port >= 0 && port < ps->num_ports)
+	if (port >= 0 && port < ps->info->num_ports)
 		return port;
 
 	return -EINVAL;
diff --git a/drivers/net/dsa/mv88e6171.c b/drivers/net/dsa/mv88e6171.c
index cb5bb19..d5f33d7 100644
--- a/drivers/net/dsa/mv88e6171.c
+++ b/drivers/net/dsa/mv88e6171.c
@@ -18,10 +18,10 @@
 #include "mv88e6xxx.h"
 
 static const struct mv88e6xxx_info mv88e6171_table[] = {
-	{ MV88E6XXX_INFO(6351, 0x171, "Marvell 88E6171") },
-	{ MV88E6XXX_INFO(6351, 0x175, "Marvell 88E6175") },
-	{ MV88E6XXX_INFO(6351, 0x371, "Marvell 88E6350") },
-	{ MV88E6XXX_INFO(6351, 0x375, "Marvell 88E6351") },
+	{ MV88E6XXX_INFO(6351, 0x171, 7, "Marvell 88E6171") },
+	{ MV88E6XXX_INFO(6351, 0x175, 7, "Marvell 88E6175") },
+	{ MV88E6XXX_INFO(6351, 0x371, 7, "Marvell 88E6350") },
+	{ MV88E6XXX_INFO(6351, 0x375, 7, "Marvell 88E6351") },
 };
 
 static char *mv88e6171_drv_probe(struct device *dsa_dev,
@@ -69,15 +69,12 @@ static int mv88e6171_setup_global(struct dsa_switch *ds)
 
 static int mv88e6171_setup(struct dsa_switch *ds)
 {
-	struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
 	int ret;
 
 	ret = mv88e6xxx_setup_common(ds);
 	if (ret < 0)
 		return ret;
 
-	ps->num_ports = 7;
-
 	ret = mv88e6xxx_switch_reset(ds, true);
 	if (ret < 0)
 		return ret;
diff --git a/drivers/net/dsa/mv88e6352.c b/drivers/net/dsa/mv88e6352.c
index 94db0c3..e529c18 100644
--- a/drivers/net/dsa/mv88e6352.c
+++ b/drivers/net/dsa/mv88e6352.c
@@ -23,12 +23,12 @@
 #include "mv88e6xxx.h"
 
 static const struct mv88e6xxx_info mv88e6352_table[] = {
-	{ MV88E6XXX_INFO(6320, 0x115, "Marvell 88E6320") },
-	{ MV88E6XXX_INFO(6320, 0x310, "Marvell 88E6321") },
-	{ MV88E6XXX_INFO(6352, 0x172, "Marvell 88E6172") },
-	{ MV88E6XXX_INFO(6352, 0x176, "Marvell 88E6176") },
-	{ MV88E6XXX_INFO(6352, 0x240, "Marvell 88E6240") },
-	{ MV88E6XXX_INFO(6352, 0x352, "Marvell 88E6352") },
+	{ MV88E6XXX_INFO(6320, 0x115, 7, "Marvell 88E6320") },
+	{ MV88E6XXX_INFO(6320, 0x310, 7, "Marvell 88E6321") },
+	{ MV88E6XXX_INFO(6352, 0x172, 7, "Marvell 88E6172") },
+	{ MV88E6XXX_INFO(6352, 0x176, 7, "Marvell 88E6176") },
+	{ MV88E6XXX_INFO(6352, 0x240, 7, "Marvell 88E6240") },
+	{ MV88E6XXX_INFO(6352, 0x352, 7, "Marvell 88E6352") },
 };
 
 static char *mv88e6352_drv_probe(struct device *dsa_dev,
@@ -82,8 +82,6 @@ static int mv88e6352_setup(struct dsa_switch *ds)
 	if (ret < 0)
 		return ret;
 
-	ps->num_ports = 7;
-
 	mutex_init(&ps->eeprom_mutex);
 
 	ret = mv88e6xxx_switch_reset(ds, true);
diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c
index 05d59f9..f3e8c68 100644
--- a/drivers/net/dsa/mv88e6xxx.c
+++ b/drivers/net/dsa/mv88e6xxx.c
@@ -518,7 +518,7 @@ void mv88e6xxx_adjust_link(struct dsa_switch *ds, int port,
 		reg |= PORT_PCS_CTRL_DUPLEX_FULL;
 
 	if ((mv88e6xxx_6352_family(ds) || mv88e6xxx_6351_family(ds)) &&
-	    (port >= ps->num_ports - 2)) {
+	    (port >= ps->info->num_ports - 2)) {
 		if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID)
 			reg |= PORT_PCS_CTRL_RGMII_DELAY_RXCLK;
 		if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID)
@@ -1099,7 +1099,7 @@ static int _mv88e6xxx_port_based_vlan_map(struct dsa_switch *ds, int port)
 {
 	struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
 	struct net_device *bridge = ps->ports[port].bridge_dev;
-	const u16 mask = (1 << ps->num_ports) - 1;
+	const u16 mask = (1 << ps->info->num_ports) - 1;
 	u16 output_ports = 0;
 	int reg;
 	int i;
@@ -1108,7 +1108,7 @@ static int _mv88e6xxx_port_based_vlan_map(struct dsa_switch *ds, int port)
 	if (dsa_is_cpu_port(ds, port) || dsa_is_dsa_port(ds, port)) {
 		output_ports = mask;
 	} else {
-		for (i = 0; i < ps->num_ports; ++i) {
+		for (i = 0; i < ps->info->num_ports; ++i) {
 			/* allow sending frames to every group member */
 			if (bridge && ps->ports[i].bridge_dev == bridge)
 				output_ports |= BIT(i);
@@ -1249,7 +1249,7 @@ static int _mv88e6xxx_vtu_stu_data_read(struct dsa_switch *ds,
 		regs[i] = ret;
 	}
 
-	for (i = 0; i < ps->num_ports; ++i) {
+	for (i = 0; i < ps->info->num_ports; ++i) {
 		unsigned int shift = (i % 4) * 4 + nibble_offset;
 		u16 reg = regs[i / 4];
 
@@ -1268,7 +1268,7 @@ static int _mv88e6xxx_vtu_stu_data_write(struct dsa_switch *ds,
 	int i;
 	int ret;
 
-	for (i = 0; i < ps->num_ports; ++i) {
+	for (i = 0; i < ps->info->num_ports; ++i) {
 		unsigned int shift = (i % 4) * 4 + nibble_offset;
 		u8 data = entry->data[i];
 
@@ -1600,7 +1600,7 @@ static int _mv88e6xxx_fid_new(struct dsa_switch *ds, u16 *fid)
 	bitmap_zero(fid_bitmap, MV88E6XXX_N_FID);
 
 	/* Set every FID bit used by the (un)bridged ports */
-	for (i = 0; i < ps->num_ports; ++i) {
+	for (i = 0; i < ps->info->num_ports; ++i) {
 		err = _mv88e6xxx_port_fid_get(ds, i, fid);
 		if (err)
 			return err;
@@ -1650,7 +1650,7 @@ static int _mv88e6xxx_vtu_new(struct dsa_switch *ds, u16 vid,
 		return err;
 
 	/* exclude all ports except the CPU and DSA ports */
-	for (i = 0; i < ps->num_ports; ++i)
+	for (i = 0; i < ps->info->num_ports; ++i)
 		vlan.data[i] = dsa_is_cpu_port(ds, i) || dsa_is_dsa_port(ds, i)
 			? GLOBAL_VTU_DATA_MEMBER_TAG_UNMODIFIED
 			: GLOBAL_VTU_DATA_MEMBER_TAG_NON_MEMBER;
@@ -1739,7 +1739,7 @@ static int mv88e6xxx_port_check_hw_vlan(struct dsa_switch *ds, int port,
 		if (vlan.vid > vid_end)
 			break;
 
-		for (i = 0; i < ps->num_ports; ++i) {
+		for (i = 0; i < ps->info->num_ports; ++i) {
 			if (dsa_is_dsa_port(ds, i) || dsa_is_cpu_port(ds, i))
 				continue;
 
@@ -1888,7 +1888,7 @@ static int _mv88e6xxx_port_vlan_del(struct dsa_switch *ds, int port, u16 vid)
 
 	/* keep the VLAN unless all ports are excluded */
 	vlan.valid = false;
-	for (i = 0; i < ps->num_ports; ++i) {
+	for (i = 0; i < ps->info->num_ports; ++i) {
 		if (dsa_is_cpu_port(ds, i) || dsa_is_dsa_port(ds, i))
 			continue;
 
@@ -2197,11 +2197,11 @@ int mv88e6xxx_port_bridge_join(struct dsa_switch *ds, int port,
 	mutex_lock(&ps->smi_mutex);
 
 	/* Get or create the bridge FID and assign it to the port */
-	for (i = 0; i < ps->num_ports; ++i)
+	for (i = 0; i < ps->info->num_ports; ++i)
 		if (ps->ports[i].bridge_dev == bridge)
 			break;
 
-	if (i < ps->num_ports)
+	if (i < ps->info->num_ports)
 		err = _mv88e6xxx_port_fid_get(ds, i, &fid);
 	else
 		err = _mv88e6xxx_fid_new(ds, &fid);
@@ -2215,7 +2215,7 @@ int mv88e6xxx_port_bridge_join(struct dsa_switch *ds, int port,
 	/* Assign the bridge and remap each port's VLANTable */
 	ps->ports[port].bridge_dev = bridge;
 
-	for (i = 0; i < ps->num_ports; ++i) {
+	for (i = 0; i < ps->info->num_ports; ++i) {
 		if (ps->ports[i].bridge_dev == bridge) {
 			err = _mv88e6xxx_port_based_vlan_map(ds, i);
 			if (err)
@@ -2246,7 +2246,7 @@ void mv88e6xxx_port_bridge_leave(struct dsa_switch *ds, int port)
 	/* Unassign the bridge and remap each port's VLANTable */
 	ps->ports[port].bridge_dev = NULL;
 
-	for (i = 0; i < ps->num_ports; ++i)
+	for (i = 0; i < ps->info->num_ports; ++i)
 		if (i == port || ps->ports[i].bridge_dev == bridge)
 			if (_mv88e6xxx_port_based_vlan_map(ds, i))
 				netdev_warn(ds->ports[i], "failed to remap\n");
@@ -2265,7 +2265,7 @@ static void mv88e6xxx_bridge_work(struct work_struct *work)
 
 	mutex_lock(&ps->smi_mutex);
 
-	for (port = 0; port < ps->num_ports; ++port)
+	for (port = 0; port < ps->info->num_ports; ++port)
 		if (test_and_clear_bit(port, ps->port_state_update_mask) &&
 		    _mv88e6xxx_port_state(ds, port, ps->ports[port].state))
 			netdev_warn(ds->ports[port], "failed to update state to %s\n",
@@ -2597,7 +2597,7 @@ int mv88e6xxx_setup_ports(struct dsa_switch *ds)
 	int ret;
 	int i;
 
-	for (i = 0; i < ps->num_ports; i++) {
+	for (i = 0; i < ps->info->num_ports; i++) {
 		ret = mv88e6xxx_setup_port(ds, i);
 		if (ret < 0)
 			return ret;
@@ -2675,7 +2675,7 @@ int mv88e6xxx_setup_global(struct dsa_switch *ds)
 	for (i = 0; i < 8; i++)
 		REG_WRITE(REG_GLOBAL2, GLOBAL2_TRUNK_MASK,
 			  0x8000 | (i << GLOBAL2_TRUNK_MASK_NUM_SHIFT) |
-			  ((1 << ps->num_ports) - 1));
+			  ((1 << ps->info->num_ports) - 1));
 
 	/* Clear all trunk mappings. */
 	for (i = 0; i < 16; i++)
@@ -2710,7 +2710,7 @@ int mv88e6xxx_setup_global(struct dsa_switch *ds)
 		 * ingress rate limit registers to their initial
 		 * state.
 		 */
-		for (i = 0; i < ps->num_ports; i++)
+		for (i = 0; i < ps->info->num_ports; i++)
 			REG_WRITE(REG_GLOBAL2, GLOBAL2_INGRESS_OP,
 				  0x9000 | (i << 8));
 	}
@@ -2747,7 +2747,7 @@ int mv88e6xxx_switch_reset(struct dsa_switch *ds, bool ppu_active)
 	int i;
 
 	/* Set all ports to the disabled state. */
-	for (i = 0; i < ps->num_ports; i++) {
+	for (i = 0; i < ps->info->num_ports; i++) {
 		ret = REG_READ(REG_PORT(i), PORT_CONTROL);
 		REG_WRITE(REG_PORT(i), PORT_CONTROL, ret & 0xfffc);
 	}
@@ -2815,7 +2815,7 @@ static int mv88e6xxx_port_to_phy_addr(struct dsa_switch *ds, int port)
 {
 	struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
 
-	if (port >= 0 && port < ps->num_ports)
+	if (port >= 0 && port < ps->info->num_ports)
 		return port;
 	return -EINVAL;
 }
diff --git a/drivers/net/dsa/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx.h
index 3d2a186..6b2d62e 100644
--- a/drivers/net/dsa/mv88e6xxx.h
+++ b/drivers/net/dsa/mv88e6xxx.h
@@ -369,12 +369,14 @@ enum mv88e6xxx_family {
 struct mv88e6xxx_info {
 	enum mv88e6xxx_family family;
 	u16 prod_num;
+	unsigned int num_ports;
 	const char *name;
 };
 
-#define MV88E6XXX_INFO(_family, _prod_num, _name) \
+#define MV88E6XXX_INFO(_family, _prod_num, _num_ports, _name) \
 	.family = MV88E6XXX_FAMILY_##_family, \
 	.prod_num = _prod_num, \
+	.num_ports = _num_ports, \
 	.name = _name, \
 
 struct mv88e6xxx_atu_entry {
@@ -447,8 +449,6 @@ struct mv88e6xxx_priv_state {
 	struct mutex eeprom_mutex;
 
 	int		id; /* switch product id */
-	int		num_ports;	/* number of switch ports */
-
 	struct mv88e6xxx_priv_port	ports[DSA_MAX_PORTS];
 
 	DECLARE_BITMAP(port_state_update_mask, DSA_MAX_PORTS);
-- 
2.8.0

^ permalink raw reply related

* [PATCH net-next 6/7] net: dsa: mv88e6xxx: add number of database to info
From: Vivien Didelot @ 2016-04-15 18:25 UTC (permalink / raw)
  To: netdev
  Cc: linux-kernel, kernel, David S. Miller, Florian Fainelli,
	Andrew Lunn, Vivien Didelot
In-Reply-To: <1460744750-13896-1-git-send-email-vivien.didelot@savoirfairelinux.com>

Move the number of databases to the info structure.

Signed-off-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
---
 drivers/net/dsa/mv88e6123.c |  6 +++---
 drivers/net/dsa/mv88e6131.c |  8 ++++----
 drivers/net/dsa/mv88e6171.c |  8 ++++----
 drivers/net/dsa/mv88e6352.c | 12 ++++++------
 drivers/net/dsa/mv88e6xxx.c | 19 +------------------
 drivers/net/dsa/mv88e6xxx.h |  4 +++-
 6 files changed, 21 insertions(+), 36 deletions(-)

diff --git a/drivers/net/dsa/mv88e6123.c b/drivers/net/dsa/mv88e6123.c
index 2048719..9731e56 100644
--- a/drivers/net/dsa/mv88e6123.c
+++ b/drivers/net/dsa/mv88e6123.c
@@ -18,9 +18,9 @@
 #include "mv88e6xxx.h"
 
 static const struct mv88e6xxx_info mv88e6123_table[] = {
-	{ MV88E6XXX_INFO(6165, 0x121, 3, "Marvell 88E6123") },
-	{ MV88E6XXX_INFO(6165, 0x161, 6, "Marvell 88E6161") },
-	{ MV88E6XXX_INFO(6165, 0x165, 6, "Marvell 88E6165") },
+	{ MV88E6XXX_INFO(6165, 0x121, 3, 4096, "Marvell 88E6123") },
+	{ MV88E6XXX_INFO(6165, 0x161, 6, 4096, "Marvell 88E6161") },
+	{ MV88E6XXX_INFO(6165, 0x165, 6, 4096, "Marvell 88E6165") },
 };
 
 static char *mv88e6123_drv_probe(struct device *dsa_dev,
diff --git a/drivers/net/dsa/mv88e6131.c b/drivers/net/dsa/mv88e6131.c
index 2eb9fa3..c507ecb 100644
--- a/drivers/net/dsa/mv88e6131.c
+++ b/drivers/net/dsa/mv88e6131.c
@@ -18,10 +18,10 @@
 #include "mv88e6xxx.h"
 
 static const struct mv88e6xxx_info mv88e6131_table[] = {
-	{ MV88E6XXX_INFO(6095, 0x095, 11, "Marvell 88E6095/88E6095F") },
-	{ MV88E6XXX_INFO(6097, 0x04a, 10, "Marvell 88E6085") },
-	{ MV88E6XXX_INFO(6185, 0x106, 8,  "Marvell 88E6131") },
-	{ MV88E6XXX_INFO(6185, 0x1a7, 10, "Marvell 88E6185") },
+	{ MV88E6XXX_INFO(6095, 0x095, 11, 256,  "Marvell 88E6095/88E6095F") },
+	{ MV88E6XXX_INFO(6097, 0x04a, 10, 4096, "Marvell 88E6085") },
+	{ MV88E6XXX_INFO(6185, 0x106, 8,  256,  "Marvell 88E6131") },
+	{ MV88E6XXX_INFO(6185, 0x1a7, 10, 256,  "Marvell 88E6185") },
 };
 
 static char *mv88e6131_drv_probe(struct device *dsa_dev,
diff --git a/drivers/net/dsa/mv88e6171.c b/drivers/net/dsa/mv88e6171.c
index d5f33d7..bce8f40 100644
--- a/drivers/net/dsa/mv88e6171.c
+++ b/drivers/net/dsa/mv88e6171.c
@@ -18,10 +18,10 @@
 #include "mv88e6xxx.h"
 
 static const struct mv88e6xxx_info mv88e6171_table[] = {
-	{ MV88E6XXX_INFO(6351, 0x171, 7, "Marvell 88E6171") },
-	{ MV88E6XXX_INFO(6351, 0x175, 7, "Marvell 88E6175") },
-	{ MV88E6XXX_INFO(6351, 0x371, 7, "Marvell 88E6350") },
-	{ MV88E6XXX_INFO(6351, 0x375, 7, "Marvell 88E6351") },
+	{ MV88E6XXX_INFO(6351, 0x171, 7, 4096, "Marvell 88E6171") },
+	{ MV88E6XXX_INFO(6351, 0x175, 7, 4096, "Marvell 88E6175") },
+	{ MV88E6XXX_INFO(6351, 0x371, 7, 4096, "Marvell 88E6350") },
+	{ MV88E6XXX_INFO(6351, 0x375, 7, 4096, "Marvell 88E6351") },
 };
 
 static char *mv88e6171_drv_probe(struct device *dsa_dev,
diff --git a/drivers/net/dsa/mv88e6352.c b/drivers/net/dsa/mv88e6352.c
index e529c18..c26d674 100644
--- a/drivers/net/dsa/mv88e6352.c
+++ b/drivers/net/dsa/mv88e6352.c
@@ -23,12 +23,12 @@
 #include "mv88e6xxx.h"
 
 static const struct mv88e6xxx_info mv88e6352_table[] = {
-	{ MV88E6XXX_INFO(6320, 0x115, 7, "Marvell 88E6320") },
-	{ MV88E6XXX_INFO(6320, 0x310, 7, "Marvell 88E6321") },
-	{ MV88E6XXX_INFO(6352, 0x172, 7, "Marvell 88E6172") },
-	{ MV88E6XXX_INFO(6352, 0x176, 7, "Marvell 88E6176") },
-	{ MV88E6XXX_INFO(6352, 0x240, 7, "Marvell 88E6240") },
-	{ MV88E6XXX_INFO(6352, 0x352, 7, "Marvell 88E6352") },
+	{ MV88E6XXX_INFO(6320, 0x115, 7, 4096, "Marvell 88E6320") },
+	{ MV88E6XXX_INFO(6320, 0x310, 7, 4096, "Marvell 88E6321") },
+	{ MV88E6XXX_INFO(6352, 0x172, 7, 4096, "Marvell 88E6172") },
+	{ MV88E6XXX_INFO(6352, 0x176, 7, 4096, "Marvell 88E6176") },
+	{ MV88E6XXX_INFO(6352, 0x240, 7, 4096, "Marvell 88E6240") },
+	{ MV88E6XXX_INFO(6352, 0x352, 7, 4096, "Marvell 88E6352") },
 };
 
 static char *mv88e6352_drv_probe(struct device *dsa_dev,
diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c
index f3e8c68..d40ac4d 100644
--- a/drivers/net/dsa/mv88e6xxx.c
+++ b/drivers/net/dsa/mv88e6xxx.c
@@ -425,24 +425,7 @@ static unsigned int mv88e6xxx_num_databases(struct dsa_switch *ds)
 {
 	struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
 
-	/* The following devices have 4-bit identifiers for 16 databases */
-	if (ps->id == PORT_SWITCH_ID_6061)
-		return 16;
-
-	/* The following devices have 6-bit identifiers for 64 databases */
-	if (ps->id == PORT_SWITCH_ID_6065)
-		return 64;
-
-	/* The following devices have 8-bit identifiers for 256 databases */
-	if (mv88e6xxx_6095_family(ds) || mv88e6xxx_6185_family(ds))
-		return 256;
-
-	/* The following devices have 12-bit identifiers for 4096 databases */
-	if (mv88e6xxx_6097_family(ds) || mv88e6xxx_6165_family(ds) ||
-	    mv88e6xxx_6351_family(ds) || mv88e6xxx_6352_family(ds))
-		return 4096;
-
-	return 0;
+	return ps->info->num_databases;
 }
 
 static bool mv88e6xxx_has_fid_reg(struct dsa_switch *ds)
diff --git a/drivers/net/dsa/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx.h
index 6b2d62e..7e86cc6 100644
--- a/drivers/net/dsa/mv88e6xxx.h
+++ b/drivers/net/dsa/mv88e6xxx.h
@@ -370,13 +370,15 @@ struct mv88e6xxx_info {
 	enum mv88e6xxx_family family;
 	u16 prod_num;
 	unsigned int num_ports;
+	unsigned int num_databases;
 	const char *name;
 };
 
-#define MV88E6XXX_INFO(_family, _prod_num, _num_ports, _name) \
+#define MV88E6XXX_INFO(_family, _prod_num, _num_ports, _num_db, _name) \
 	.family = MV88E6XXX_FAMILY_##_family, \
 	.prod_num = _prod_num, \
 	.num_ports = _num_ports, \
+	.num_databases = _num_db, \
 	.name = _name, \
 
 struct mv88e6xxx_atu_entry {
-- 
2.8.0

^ permalink raw reply related

* [PATCH net-next 7/7] net: dsa: mv88e6xxx: drop switch id
From: Vivien Didelot @ 2016-04-15 18:25 UTC (permalink / raw)
  To: netdev
  Cc: linux-kernel, kernel, David S. Miller, Florian Fainelli,
	Andrew Lunn, Vivien Didelot
In-Reply-To: <1460744750-13896-1-git-send-email-vivien.didelot@savoirfairelinux.com>

We already have the product number and revision stored in the info
structure and the switch private state.

It is not necessary to clutter the header file with shifted product
number for devices that we don't even support yet. Remove them.

Signed-off-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
---
 drivers/net/dsa/mv88e6xxx.c |  1 -
 drivers/net/dsa/mv88e6xxx.h | 34 ----------------------------------
 2 files changed, 35 deletions(-)

diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c
index d40ac4d..7ec87df 100644
--- a/drivers/net/dsa/mv88e6xxx.c
+++ b/drivers/net/dsa/mv88e6xxx.c
@@ -3027,7 +3027,6 @@ found:
 	ps->bus = bus;
 	ps->sw_addr = sw_addr;
 	ps->info = info;
-	ps->id = id & 0xfff0;
 	ps->rev = id & 0xf;
 
 	dev_info(&ps->bus->dev, "found switch %s, revision %u\n",
diff --git a/drivers/net/dsa/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx.h
index 7e86cc6..fb81945 100644
--- a/drivers/net/dsa/mv88e6xxx.h
+++ b/drivers/net/dsa/mv88e6xxx.h
@@ -68,39 +68,6 @@
 #define PORT_PCS_CTRL_UNFORCED		0x03
 #define PORT_PAUSE_CTRL		0x02
 #define PORT_SWITCH_ID		0x03
-#define PORT_SWITCH_ID_PROD_NUM_MASK	0xfff0
-#define PORT_SWITCH_ID_REV_MASK		0x000f
-#define PORT_SWITCH_ID_6031	0x0310
-#define PORT_SWITCH_ID_6035	0x0350
-#define PORT_SWITCH_ID_6046	0x0480
-#define PORT_SWITCH_ID_6061	0x0610
-#define PORT_SWITCH_ID_6065	0x0650
-#define PORT_SWITCH_ID_6085	0x04a0
-#define PORT_SWITCH_ID_6092	0x0970
-#define PORT_SWITCH_ID_6095	0x0950
-#define PORT_SWITCH_ID_6096	0x0980
-#define PORT_SWITCH_ID_6097	0x0990
-#define PORT_SWITCH_ID_6108	0x1070
-#define PORT_SWITCH_ID_6121	0x1040
-#define PORT_SWITCH_ID_6122	0x1050
-#define PORT_SWITCH_ID_6123	0x1210
-#define PORT_SWITCH_ID_6131	0x1060
-#define PORT_SWITCH_ID_6152	0x1a40
-#define PORT_SWITCH_ID_6155	0x1a50
-#define PORT_SWITCH_ID_6161	0x1610
-#define PORT_SWITCH_ID_6165	0x1650
-#define PORT_SWITCH_ID_6171	0x1710
-#define PORT_SWITCH_ID_6172	0x1720
-#define PORT_SWITCH_ID_6175	0x1750
-#define PORT_SWITCH_ID_6176	0x1760
-#define PORT_SWITCH_ID_6182	0x1a60
-#define PORT_SWITCH_ID_6185	0x1a70
-#define PORT_SWITCH_ID_6240	0x2400
-#define PORT_SWITCH_ID_6320	0x1150
-#define PORT_SWITCH_ID_6321	0x3100
-#define PORT_SWITCH_ID_6350	0x3710
-#define PORT_SWITCH_ID_6351	0x3750
-#define PORT_SWITCH_ID_6352	0x3520
 #define PORT_CONTROL		0x04
 #define PORT_CONTROL_USE_CORE_TAG	BIT(15)
 #define PORT_CONTROL_DROP_ON_LOCK	BIT(14)
@@ -450,7 +417,6 @@ struct mv88e6xxx_priv_state {
 	 */
 	struct mutex eeprom_mutex;
 
-	int		id; /* switch product id */
 	struct mv88e6xxx_priv_port	ports[DSA_MAX_PORTS];
 
 	DECLARE_BITMAP(port_state_update_mask, DSA_MAX_PORTS);
-- 
2.8.0

^ permalink raw reply related

* Hello DEAR
From: Mitchell H Peacock @ 2016-04-15 18:28 UTC (permalink / raw)


Hi my name is Mitchell H Peacock. I'm an American soldier currently in Syria fighting IS. This might be a little strange for you but Its very lonely out here. I miss normal human interaction and being loved by someone so I would love to get to know you and keep in touch with you. I'm loving, Funny and have a lot to offer emotionally.....Tell me about you?hope to hear back from you soon

Mitchell

^ permalink raw reply

* Re: [PATCH net-next 0/2] act_bpf, cls_bpf: send eBPF bytecode through
From: Alexei Starovoitov @ 2016-04-15 18:44 UTC (permalink / raw)
  To: Daniel Borkmann; +Cc: Quentin Monnet, netdev
In-Reply-To: <5710C541.7070609@iogearbox.net>

On Fri, Apr 15, 2016 at 12:41:05PM +0200, Daniel Borkmann wrote:
> Hi Quentin,
> 
> On 04/15/2016 12:07 PM, Quentin Monnet wrote:
> >When a new BPF traffic control filter or action is set up with tc, the
> >bytecode is sent back to userspace through a netlink socket for cBPF, but
> >not for eBPF (the file descriptor pointing to the object file containing
> >the bytecode is sent instead).
> >
> >This patch makes cls_bpf and act_bpf modules send the bytecode for eBPF as
> >well (in addition to the file descriptor).
> >
> >New BPF flags are used in order to differenciate what BPF version is in
> >use, so that userspace tools can process the bytecode properly.
> >
> >Once the series is accepted and merged, it is intended to submit a patch
> >for the iproute2 package, so as to fix tc utility so as to use the new
> >flags and to display the bytecode in eBPF format when needed. This tc
> >patch is already available at:
> >https://github.com/6WIND/iproute2/commits/netlink_eBPF
> 
> Thanks for working on this, but it's unfortunately not that easy. Let
> me ask, what would be the intended use-case to dump the insns?

+1

> I'm asking because if you dump them as-is, then a reinject at a later
> time of that bytecode back into the kernel will most likely be rejected
> by the verifier.
> 
> This is because on load time, verifier does rewrites/expansion on some
> of the insns (f.e. map pointers, helper functions, ctx access etc, see
> also appendix in [1]), so the code as seen in the kernel would need to
> be sanitized first.

+1
we had similar discussion about this in seccomp context and decided that
the only sensible way is to keep original instructions, but it's wasteful
to do unconditionally and snapshotting of maps is not possible,
so there was no use for such dumping facility other than debugging.
Is it what the patch after?
We need to discuss it in the proper context.

> Also, how would you make sense/transform maps into a meaningful
> representation (probably possible to find a scheme when they are pinned)?
> 
> Another possibility is that such programs need to be pinned (can be done
> easily by tc in the background) and then implement a CRIU facility into
> the bpf(2) syscall to retrieve them. tc could make use of this w/o too
> much effort, and at the same time it would help CRIU folks, too. It
> also seems cleaner to have only one central api (bpf(2)) to dump them,
> but needs a bit of thought.

+1
any debugging or criu needs to be done in a centralized way via syscall
and/or bpffs.

^ permalink raw reply

* Re: [PATCH net-next 4/7] net: dsa: mv88e6xxx: add family to info
From: Andrew Lunn @ 2016-04-15 19:11 UTC (permalink / raw)
  To: Vivien Didelot
  Cc: netdev, linux-kernel, kernel, David S. Miller, Florian Fainelli
In-Reply-To: <1460744750-13896-5-git-send-email-vivien.didelot@savoirfairelinux.com>

On Fri, Apr 15, 2016 at 02:25:47PM -0400, Vivien Didelot wrote:
> Add an mv88e6xxx_family enum to the info structure for better family
> indentification.
> 
> Signed-off-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
> ---
>  drivers/net/dsa/mv88e6123.c |  6 ++--
>  drivers/net/dsa/mv88e6131.c |  8 ++---
>  drivers/net/dsa/mv88e6171.c |  8 ++---
>  drivers/net/dsa/mv88e6352.c | 12 ++++----
>  drivers/net/dsa/mv88e6xxx.c | 71 +++++----------------------------------------
>  drivers/net/dsa/mv88e6xxx.h | 16 +++++++++-
>  6 files changed, 40 insertions(+), 81 deletions(-)
> 
> diff --git a/drivers/net/dsa/mv88e6123.c b/drivers/net/dsa/mv88e6123.c
> index 02bf16c..36a0340 100644
> --- a/drivers/net/dsa/mv88e6123.c
> +++ b/drivers/net/dsa/mv88e6123.c
> @@ -18,9 +18,9 @@
>  #include "mv88e6xxx.h"
>  
>  static const struct mv88e6xxx_info mv88e6123_table[] = {
> -	{ MV88E6XXX_INFO(0x121, "Marvell 88E6123") },
> -	{ MV88E6XXX_INFO(0x161, "Marvell 88E6161") },
> -	{ MV88E6XXX_INFO(0x165, "Marvell 88E6165") },
> +	{ MV88E6XXX_INFO(6165, 0x121, "Marvell 88E6123") },
> +	{ MV88E6XXX_INFO(6165, 0x161, "Marvell 88E6161") },
> +	{ MV88E6XXX_INFO(6165, 0x165, "Marvell 88E6165") },

I think 

> +	{ MV88E6XXX_INFO(MV88E6XXX_FAMILY_6165, 0x165, "Marvell 88E6165") },

is clearer. It is hard to know what these values mean unless you go
look at the macro.

     Andrew

^ permalink raw reply

* Re: [PATCH net-next 3/7] net: dsa: mv88e6xxx: add switch info
From: Andrew Lunn @ 2016-04-15 19:13 UTC (permalink / raw)
  To: Vivien Didelot
  Cc: netdev, linux-kernel, kernel, David S. Miller, Florian Fainelli
In-Reply-To: <1460744750-13896-4-git-send-email-vivien.didelot@savoirfairelinux.com>

On Fri, Apr 15, 2016 at 02:25:46PM -0400, Vivien Didelot wrote:
> Add a new switch info structure which will be later extended to store
> switch models static information, such as product number, name, number
> of ports, number of databases, etc.
> 
> Merge the lookup function in the probing code, so that we avoid multiple
> checking of the MII bus, as well a multiple ID reading.
> 
> Signed-off-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
> ---
>  drivers/net/dsa/mv88e6123.c |  8 +++---
>  drivers/net/dsa/mv88e6131.c | 10 +++----
>  drivers/net/dsa/mv88e6171.c | 10 +++----
>  drivers/net/dsa/mv88e6352.c | 14 +++++-----
>  drivers/net/dsa/mv88e6xxx.c | 67 +++++++++++++++++++--------------------------
>  drivers/net/dsa/mv88e6xxx.h | 14 ++++++----
>  6 files changed, 58 insertions(+), 65 deletions(-)
> 
> diff --git a/drivers/net/dsa/mv88e6123.c b/drivers/net/dsa/mv88e6123.c
> index 00c1121..02bf16c 100644
> --- a/drivers/net/dsa/mv88e6123.c
> +++ b/drivers/net/dsa/mv88e6123.c
> @@ -17,10 +17,10 @@
>  #include <net/dsa.h>
>  #include "mv88e6xxx.h"
>  
> -static const struct mv88e6xxx_switch_id mv88e6123_table[] = {
> -	{ PORT_SWITCH_ID_6123, "Marvell 88E6123" },
> -	{ PORT_SWITCH_ID_6161, "Marvell 88E6161" },
> -	{ PORT_SWITCH_ID_6165, "Marvell 88E6165" },
> +static const struct mv88e6xxx_info mv88e6123_table[] = {
> +	{ MV88E6XXX_INFO(0x121, "Marvell 88E6123") },
> +	{ MV88E6XXX_INFO(0x161, "Marvell 88E6161") },
> +	{ MV88E6XXX_INFO(0x165, "Marvell 88E6165") },

Why replace PORT_SWITCH_ID_6123 with the magic number 0x121?

    Andrew

^ permalink raw reply

* Re: [PATCH net-next 2/7] net: dsa: mv88e6xxx: drop revision probing
From: Andrew Lunn @ 2016-04-15 19:16 UTC (permalink / raw)
  To: Vivien Didelot
  Cc: netdev, linux-kernel, kernel, David S. Miller, Florian Fainelli
In-Reply-To: <1460744750-13896-3-git-send-email-vivien.didelot@savoirfairelinux.com>

> --- a/drivers/net/dsa/mv88e6xxx.c
> +++ b/drivers/net/dsa/mv88e6xxx.c
> @@ -2663,11 +2663,15 @@ int mv88e6xxx_setup_ports(struct dsa_switch *ds)
>  int mv88e6xxx_setup_common(struct dsa_switch *ds)
>  {
>  	struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
> +	int id;
>  
>  	ps->ds = ds;
>  	mutex_init(&ps->smi_mutex);
>  
> -	ps->id = REG_READ(REG_PORT(0), PORT_SWITCH_ID) & 0xfff0;
> +	id = REG_READ(REG_PORT(0), PORT_SWITCH_ID);
> +
> +	ps->id = id & 0xfff0;
> +	ps->rev = id & 0xf;

ps->rev is not actually used anywhere. Drop it.

	Andrew

^ permalink raw reply

* [PATCH net-next] enic: set netdev->vlan_features
From: Govindarajulu Varadarajan @ 2016-04-15 19:10 UTC (permalink / raw)
  To: davem, netdev; +Cc: benve, mkubecek, Govindarajulu Varadarajan

From: Govindarajulu Varadarajan <_govind@gmx.com>

Driver sets vlan_feature to netdev->features as hardware supports all of
them on vlan interface.

Signed-off-by: Govindarajulu Varadarajan <_govind@gmx.com>
---
 drivers/net/ethernet/cisco/enic/enic_main.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/net/ethernet/cisco/enic/enic_main.c b/drivers/net/ethernet/cisco/enic/enic_main.c
index b2182d3..f15560a 100644
--- a/drivers/net/ethernet/cisco/enic/enic_main.c
+++ b/drivers/net/ethernet/cisco/enic/enic_main.c
@@ -2740,6 +2740,7 @@ static int enic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 		netdev->hw_features |= NETIF_F_RXCSUM;
 
 	netdev->features |= netdev->hw_features;
+	netdev->vlan_features |= netdev->features;
 
 #ifdef CONFIG_RFS_ACCEL
 	netdev->hw_features |= NETIF_F_NTUPLE;
-- 
2.8.0

^ permalink raw reply related

* Re: [PATCH net-next 6/7] net: dsa: mv88e6xxx: add number of database to info
From: Andrew Lunn @ 2016-04-15 19:35 UTC (permalink / raw)
  To: Vivien Didelot
  Cc: netdev, linux-kernel, kernel, David S. Miller, Florian Fainelli
In-Reply-To: <1460744750-13896-7-git-send-email-vivien.didelot@savoirfairelinux.com>

On Fri, Apr 15, 2016 at 02:25:49PM -0400, Vivien Didelot wrote:
> Move the number of databases to the info structure.

Isn't the number of databases a property of the family?

I would add a table indexed by family.

  Andrew

^ permalink raw reply

* Re: [PATCH net-next 7/7] net: dsa: mv88e6xxx: drop switch id
From: Andrew Lunn @ 2016-04-15 19:38 UTC (permalink / raw)
  To: Vivien Didelot
  Cc: netdev, linux-kernel, kernel, David S. Miller, Florian Fainelli
In-Reply-To: <1460744750-13896-8-git-send-email-vivien.didelot@savoirfairelinux.com>

On Fri, Apr 15, 2016 at 02:25:50PM -0400, Vivien Didelot wrote:
> We already have the product number and revision stored in the info
> structure and the switch private state.
> 
> It is not necessary to clutter the header file with shifted product
> number for devices that we don't even support yet. Remove them.
> 
> Signed-off-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
> ---
>  drivers/net/dsa/mv88e6xxx.c |  1 -
>  drivers/net/dsa/mv88e6xxx.h | 34 ----------------------------------
>  2 files changed, 35 deletions(-)
> 
> diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c
> index d40ac4d..7ec87df 100644
> --- a/drivers/net/dsa/mv88e6xxx.c
> +++ b/drivers/net/dsa/mv88e6xxx.c
> @@ -3027,7 +3027,6 @@ found:
>  	ps->bus = bus;
>  	ps->sw_addr = sw_addr;
>  	ps->info = info;
> -	ps->id = id & 0xfff0;
>  	ps->rev = id & 0xf;
>  
>  	dev_info(&ps->bus->dev, "found switch %s, revision %u\n",
> diff --git a/drivers/net/dsa/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx.h
> index 7e86cc6..fb81945 100644
> --- a/drivers/net/dsa/mv88e6xxx.h
> +++ b/drivers/net/dsa/mv88e6xxx.h
> @@ -68,39 +68,6 @@
>  #define PORT_PCS_CTRL_UNFORCED		0x03
>  #define PORT_PAUSE_CTRL		0x02
>  #define PORT_SWITCH_ID		0x03
> -#define PORT_SWITCH_ID_PROD_NUM_MASK	0xfff0
> -#define PORT_SWITCH_ID_REV_MASK		0x000f
> -#define PORT_SWITCH_ID_6031	0x0310
> -#define PORT_SWITCH_ID_6035	0x0350
> -#define PORT_SWITCH_ID_6046	0x0480
> -#define PORT_SWITCH_ID_6061	0x0610
> -#define PORT_SWITCH_ID_6065	0x0650
> -#define PORT_SWITCH_ID_6085	0x04a0
> -#define PORT_SWITCH_ID_6092	0x0970
> -#define PORT_SWITCH_ID_6095	0x0950
> -#define PORT_SWITCH_ID_6096	0x0980
> -#define PORT_SWITCH_ID_6097	0x0990
> -#define PORT_SWITCH_ID_6108	0x1070
> -#define PORT_SWITCH_ID_6121	0x1040
> -#define PORT_SWITCH_ID_6122	0x1050
> -#define PORT_SWITCH_ID_6123	0x1210
> -#define PORT_SWITCH_ID_6131	0x1060
> -#define PORT_SWITCH_ID_6152	0x1a40
> -#define PORT_SWITCH_ID_6155	0x1a50
> -#define PORT_SWITCH_ID_6161	0x1610
> -#define PORT_SWITCH_ID_6165	0x1650
> -#define PORT_SWITCH_ID_6171	0x1710
> -#define PORT_SWITCH_ID_6172	0x1720
> -#define PORT_SWITCH_ID_6175	0x1750
> -#define PORT_SWITCH_ID_6176	0x1760
> -#define PORT_SWITCH_ID_6182	0x1a60
> -#define PORT_SWITCH_ID_6185	0x1a70
> -#define PORT_SWITCH_ID_6240	0x2400
> -#define PORT_SWITCH_ID_6320	0x1150
> -#define PORT_SWITCH_ID_6321	0x3100
> -#define PORT_SWITCH_ID_6350	0x3710
> -#define PORT_SWITCH_ID_6351	0x3750
> -#define PORT_SWITCH_ID_6352	0x3520

NACK

These numbers are not obvious. PORT_SWITCH_ID_6320 i can
understand. 0x1150 i have no idea what it is.

	    Andrwe

^ permalink raw reply

* FlameGraph of mlx4 early drop with order-0 pages
From: Jesper Dangaard Brouer @ 2016-04-15 19:40 UTC (permalink / raw)
  To: Mel Gorman, linux-mm, netdev@vger.kernel.org, Brenden Blanco
  Cc: brouer, tom, alexei.starovoitov, ogerlitz, daniel, brouer,
	eric.dumazet, ecree, john.fastabend, tgraf, johannes,
	eranlinuxmellanox

Hi Mel,

I did an experiment that you might find interesting.  Using Brenden's
early drop with eBPF in the mxl4 driver.  I changed the mlx4 driver to
use order-0 pages.  It usually use order-3 pages to amortize the cost
of calling the page allocator (which is problematic for other reasons,
like memory pin-down, latency spikes and multi CPU scalability)

With this change I could do around 12Mpps (Mill packet per sec) drops,
usually does 14.5Mpps (limited due to a HW setup/limit, with idle cycles). 

Looking at the perf report as a FlameGraph, the page allocator clearly
show up as the bottleneck: 

http://people.netfilter.org/hawk/FlameGraph/flamegraph-mlx4-order0-pages-eBPF-XDP-drop.svg

Signing off, heading for the plane soon... see you at MM-summit!
-- 
Best regards,
  Jesper Dangaard Brouer
  MSc.CS, Principal Kernel Engineer at Red Hat
  Author of http://www.iptv-analyzer.org
  LinkedIn: http://www.linkedin.com/in/brouer

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply

* [PATCH] net: phy: Ensure the state machine is called when phy is UP
From: Alexandre Belloni @ 2016-04-15 19:56 UTC (permalink / raw)
  To: Florian Fainelli, David S . Miller
  Cc: Nicolas Ferre, netdev, linux-kernel, Alexandre Belloni

Commit d5c3d84657db ("net: phy: Avoid polling PHY with
PHY_IGNORE_INTERRUPTS") removed the last polling done on the phy. Since
then, the last actual poll done on the phy happens PHY_STATE_TIME seconds
(that is actually one second) after registering the phy. If the interface
is not UP by that time, any previous IRQ indicating the link is up is
ignored. Moreover, nothing will start the autonegociation so the phy will
simply change from READY to UP and never actually go to RUNNING.

The one second delay explains why the issue is not seen when booting from
NFS or when the interface is configured at boot time.

To solve that, ensure the state machine is called as soon as the state
changes from READY to UP.

Fixes: d5c3d84657db ("net: phy: Avoid polling PHY with PHY_IGNORE_INTERRUPTS")
Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
---
 drivers/net/phy/phy.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index 5590b9c182c9..25f6bfd1c8fd 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -787,6 +787,9 @@ void phy_start(struct phy_device *phydev)
 		break;
 	case PHY_READY:
 		phydev->state = PHY_UP;
+		cancel_delayed_work_sync(&phydev->state_queue);
+		queue_delayed_work(system_power_efficient_wq,
+				   &phydev->state_queue, 0);
 		break;
 	case PHY_HALTED:
 		/* make sure interrupts are re-enabled for the PHY */
-- 
2.8.0.rc3

^ permalink raw reply related

* Re: [PATCH] net: phy: Ensure the state machine is called when phy is UP
From: Florian Fainelli @ 2016-04-15 20:10 UTC (permalink / raw)
  To: Alexandre Belloni, David S . Miller
  Cc: Nicolas Ferre, netdev, linux-kernel, Andrew Lunn
In-Reply-To: <1460750172-7796-1-git-send-email-alexandre.belloni@free-electrons.com>

On 15/04/16 12:56, Alexandre Belloni wrote:
> Commit d5c3d84657db ("net: phy: Avoid polling PHY with
> PHY_IGNORE_INTERRUPTS") removed the last polling done on the phy. Since
> then, the last actual poll done on the phy happens PHY_STATE_TIME seconds
> (that is actually one second) after registering the phy. If the interface
> is not UP by that time, any previous IRQ indicating the link is up is
> ignored. Moreover, nothing will start the autonegociation so the phy will
> simply change from READY to UP and never actually go to RUNNING.

What do you mean by that? phy_start() will start auto-negotiation.

> 
> The one second delay explains why the issue is not seen when booting from
> NFS or when the interface is configured at boot time.
> 
> To solve that, ensure the state machine is called as soon as the state
> changes from READY to UP.

The fix may be good, but I would like to see which driver are you
observing this with? Also, having a capture of the PHY state machine
with debug prints enabled could help us figure out the sequence of
events leading to what you observed.

Assuming you might be using the macb driver, I see a race condition in
how macb_probe() registers for its MDIO bus and probes for the PHY,
after calling register_netdev(), which is something that is not good,
because as soon as register_netdev() is called, an in-kernel notifier
can start opening the device for use before you have returned...

> 
> Fixes: d5c3d84657db ("net: phy: Avoid polling PHY with PHY_IGNORE_INTERRUPTS")
> Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
> ---
>  drivers/net/phy/phy.c | 3 +++
>  1 file changed, 3 insertions(+)
> 
> diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
> index 5590b9c182c9..25f6bfd1c8fd 100644
> --- a/drivers/net/phy/phy.c
> +++ b/drivers/net/phy/phy.c
> @@ -787,6 +787,9 @@ void phy_start(struct phy_device *phydev)
>  		break;
>  	case PHY_READY:
>  		phydev->state = PHY_UP;
> +		cancel_delayed_work_sync(&phydev->state_queue);
> +		queue_delayed_work(system_power_efficient_wq,
> +				   &phydev->state_queue, 0);
>  		break;
>  	case PHY_HALTED:
>  		/* make sure interrupts are re-enabled for the PHY */
> 


-- 
Florian

^ permalink raw reply

* Re: [PATCH net-next 0/5] tipc: improvements to the link setup algorithm
From: David Miller @ 2016-04-15 20:10 UTC (permalink / raw)
  To: jon.maloy
  Cc: netdev, paul.gortmaker, parthasarathy.bhuvaragan, richard.alpe,
	ying.xue, maloy, tipc-discussion
In-Reply-To: <1460741587-13935-1-git-send-email-jon.maloy@ericsson.com>

From: Jon Maloy <jon.maloy@ericsson.com>
Date: Fri, 15 Apr 2016 13:33:02 -0400

> This series addresses some smaller issues regarding the link setup 
> algorithm. The first commit fixes a rare bug we have discovered during
> testing; the second one may have some future impact on cluster 
> scalabilty, while remaining ones can be regarded as cosmetic in
> a wider sense of the word.

Series applied, thanks.

^ permalink raw reply

* Re: [PATCH net-next 6/7] net: dsa: mv88e6xxx: add number of database to info
From: Vivien Didelot @ 2016-04-15 20:24 UTC (permalink / raw)
  To: Andrew Lunn
  Cc: netdev, linux-kernel, kernel, David S. Miller, Florian Fainelli
In-Reply-To: <20160415193516.GD18523@lunn.ch>

Hi Andrew,

Andrew Lunn <andrew@lunn.ch> writes:

> On Fri, Apr 15, 2016 at 02:25:49PM -0400, Vivien Didelot wrote:
>> Move the number of databases to the info structure.
>
> Isn't the number of databases a property of the family?

No.

We've seen [1] for instance that 6061 and 6065 are both part of the 6065
family, but 6061 has 16 databases while 6065 has 64 databases.

> I would add a table indexed by family.

I'm not even sure every Marvell switch has a family. I think we really
want a table of supported *devices*.

To go further, with the coming feature-based logic, checking the family
might not even be that valuable.

[1] https://lkml.org/lkml/2016/3/26/155

Thanks,
Vivien

^ permalink raw reply

* Re: [PATCH net-next 6/7] net: dsa: mv88e6xxx: add number of database to info
From: Andrew Lunn @ 2016-04-15 20:27 UTC (permalink / raw)
  To: Vivien Didelot
  Cc: netdev, linux-kernel, kernel, David S. Miller, Florian Fainelli
In-Reply-To: <87mvouaadh.fsf@ketchup.mtl.sfl>

On Fri, Apr 15, 2016 at 04:24:26PM -0400, Vivien Didelot wrote:
> Hi Andrew,
> 
> Andrew Lunn <andrew@lunn.ch> writes:
> 
> > On Fri, Apr 15, 2016 at 02:25:49PM -0400, Vivien Didelot wrote:
> >> Move the number of databases to the info structure.
> >
> > Isn't the number of databases a property of the family?
> 
> No.

O.K, then lets put it in the device info table.

     Andrew

^ permalink raw reply

* [PATCH net-next 0/3] ila: Support for checksum neutral translations
From: Tom Herbert @ 2016-04-15 20:34 UTC (permalink / raw)
  To: davem, netdev; +Cc: kernel-team

This patch set updates ILA to support draft-herbert-nvo3-ila-02. The
primary addition is support checksum neutral ILA translation.
This allows address to be performed and still keep any transport
layer checksums that include the addresses in their pseudo header to
still be correct without the translator needing to parse L4.

Other items are:
   - Structures for ILA addresses, identifiers, locators
   - Disallow translation on non-ILA addresses (check by
     type in identifier).
   - Change xlat (nf_input) to translates solely based
     on matching locators not identifiers (since identifiers
     are not obfuscated by checksum neutral).
   - Side effect if above is that multiple ILA domains are
     supported. Each local locator can map to a different
     SIR address (ILA domain), and each domain defines its
     own identifier space.

Tested: Ran TCP_RR with 200 cnxs. ILA performance is slightly better
than previously since we are not longer parsing L4 for checksum
handling. I amd seeing about 1% performance overhead. Also ran
TCP_STREAM and tested non-ILA address (type=0) are not translated.

Tom Herbert (3):
  ila: Add struct definitions and helpers
  ila: xlat changes
  ila: add checksum neutral ILA translations

 include/uapi/linux/ila.h  |   7 ++
 net/ipv6/ila/ila.h        |  79 ++++++++++++++++++++++-
 net/ipv6/ila/ila_common.c |  81 +++++++++++++++++++++--
 net/ipv6/ila/ila_lwt.c    |  49 ++++++++++----
 net/ipv6/ila/ila_xlat.c   | 160 +++++++++++++++++++---------------------------
 5 files changed, 259 insertions(+), 117 deletions(-)

-- 
2.8.0.rc2

^ permalink raw reply

* [PATCH net-next 1/3] ila: Add struct definitions and helpers
From: Tom Herbert @ 2016-04-15 20:34 UTC (permalink / raw)
  To: davem, netdev; +Cc: kernel-team
In-Reply-To: <1460752452-3328784-1-git-send-email-tom@herbertland.com>

Add structures for identifiers, locators, and an ila address which
is composed of a locator and identifier and in6_addr can be cast to
it. This includes a three bit type field and enums for the types defined
in ILA I-D.

In ILA lwt don't allow user to set a translation for a non-ILA
address (type of identifier is zero meaning it is an IID). This also
requires that the destination prefix is at least 65 bytes (64
bit locator and first byte of identifier).

Signed-off-by: Tom Herbert <tom@herbertland.com>
---
 net/ipv6/ila/ila.h        |  67 ++++++++++++++++++++++--
 net/ipv6/ila/ila_common.c |  11 ++--
 net/ipv6/ila/ila_lwt.c    |  39 +++++++++-----
 net/ipv6/ila/ila_xlat.c   | 126 +++++++++++++++++++++++-----------------------
 4 files changed, 161 insertions(+), 82 deletions(-)

diff --git a/net/ipv6/ila/ila.h b/net/ipv6/ila/ila.h
index 28542cb..f532967 100644
--- a/net/ipv6/ila/ila.h
+++ b/net/ipv6/ila/ila.h
@@ -23,9 +23,70 @@
 #include <net/protocol.h>
 #include <uapi/linux/ila.h>
 
+struct ila_locator {
+	union {
+		__u8            v8[8];
+		__be16          v16[4];
+		__be32          v32[2];
+		__be64		v64;
+	};
+};
+
+struct ila_identifier {
+	union {
+		struct {
+#if defined(__LITTLE_ENDIAN_BITFIELD)
+			u8 __space:5;
+			u8 type:3;
+#elif defined(__BIG_ENDIAN_BITFIELD)
+			u8 type:3;
+			u8 __space:5;
+#else
+#error  "Adjust your <asm/byteorder.h> defines"
+#endif
+			u8 __space2[7];
+		};
+		__u8            v8[8];
+		__be16          v16[4];
+		__be32          v32[2];
+		__be64		v64;
+	};
+};
+
+enum {
+	ILA_ATYPE_IID = 0,
+	ILA_ATYPE_LUID,
+	ILA_ATYPE_VIRT_V4,
+	ILA_ATYPE_VIRT_UNI_V6,
+	ILA_ATYPE_VIRT_MULTI_V6,
+	ILA_ATYPE_RSVD_1,
+	ILA_ATYPE_RSVD_2,
+	ILA_ATYPE_RSVD_3,
+};
+
+struct ila_addr {
+	union {
+		struct in6_addr addr;
+		struct {
+			struct ila_locator loc;
+			struct ila_identifier ident;
+		};
+	};
+};
+
+static inline struct ila_addr *ila_a2i(struct in6_addr *addr)
+{
+	return (struct ila_addr *)addr;
+}
+
+static inline bool ila_addr_is_ila(struct ila_addr *iaddr)
+{
+	return (iaddr->ident.type != ILA_ATYPE_IID);
+}
+
 struct ila_params {
-	__be64 locator;
-	__be64 locator_match;
+	struct ila_locator locator;
+	struct ila_locator locator_match;
 	__wsum csum_diff;
 };
 
@@ -38,7 +99,7 @@ static inline __wsum compute_csum_diff8(const __be32 *from, const __be32 *to)
 	return csum_partial(diff, sizeof(diff), 0);
 }
 
-void update_ipv6_locator(struct sk_buff *skb, struct ila_params *p);
+void ila_update_ipv6_locator(struct sk_buff *skb, struct ila_params *p);
 
 int ila_lwt_init(void);
 void ila_lwt_fini(void);
diff --git a/net/ipv6/ila/ila_common.c b/net/ipv6/ila/ila_common.c
index 3061305..c3078d0 100644
--- a/net/ipv6/ila/ila_common.c
+++ b/net/ipv6/ila/ila_common.c
@@ -15,17 +15,20 @@
 
 static __wsum get_csum_diff(struct ipv6hdr *ip6h, struct ila_params *p)
 {
-	if (*(__be64 *)&ip6h->daddr == p->locator_match)
+	struct ila_addr *iaddr = ila_a2i(&ip6h->daddr);
+
+	if (iaddr->loc.v64 == p->locator_match.v64)
 		return p->csum_diff;
 	else
-		return compute_csum_diff8((__be32 *)&ip6h->daddr,
+		return compute_csum_diff8((__be32 *)&iaddr->loc,
 					  (__be32 *)&p->locator);
 }
 
-void update_ipv6_locator(struct sk_buff *skb, struct ila_params *p)
+void ila_update_ipv6_locator(struct sk_buff *skb, struct ila_params *p)
 {
 	__wsum diff;
 	struct ipv6hdr *ip6h = ipv6_hdr(skb);
+	struct ila_addr *iaddr = ila_a2i(&ip6h->daddr);
 	size_t nhoff = sizeof(struct ipv6hdr);
 
 	/* First update checksum */
@@ -68,7 +71,7 @@ void update_ipv6_locator(struct sk_buff *skb, struct ila_params *p)
 	}
 
 	/* Now change destination address */
-	*(__be64 *)&ip6h->daddr = p->locator;
+	iaddr->loc = p->locator;
 }
 
 static int __init ila_init(void)
diff --git a/net/ipv6/ila/ila_lwt.c b/net/ipv6/ila/ila_lwt.c
index 2ae3c4f..27e68de 100644
--- a/net/ipv6/ila/ila_lwt.c
+++ b/net/ipv6/ila/ila_lwt.c
@@ -26,7 +26,7 @@ static int ila_output(struct net *net, struct sock *sk, struct sk_buff *skb)
 	if (skb->protocol != htons(ETH_P_IPV6))
 		goto drop;
 
-	update_ipv6_locator(skb, ila_params_lwtunnel(dst->lwtstate));
+	ila_update_ipv6_locator(skb, ila_params_lwtunnel(dst->lwtstate));
 
 	return dst->lwtstate->orig_output(net, sk, skb);
 
@@ -42,7 +42,7 @@ static int ila_input(struct sk_buff *skb)
 	if (skb->protocol != htons(ETH_P_IPV6))
 		goto drop;
 
-	update_ipv6_locator(skb, ila_params_lwtunnel(dst->lwtstate));
+	ila_update_ipv6_locator(skb, ila_params_lwtunnel(dst->lwtstate));
 
 	return dst->lwtstate->orig_input(skb);
 
@@ -64,11 +64,26 @@ static int ila_build_state(struct net_device *dev, struct nlattr *nla,
 	size_t encap_len = sizeof(*p);
 	struct lwtunnel_state *newts;
 	const struct fib6_config *cfg6 = cfg;
+	struct ila_addr *iaddr;
 	int ret;
 
 	if (family != AF_INET6)
 		return -EINVAL;
 
+	if (cfg6->fc_dst_len < sizeof(struct ila_locator) + 1) {
+		/* Need to have full locator and at least type field
+		 * included in destination
+		 */
+		return -EINVAL;
+	}
+
+	iaddr = (struct ila_addr *)&cfg6->fc_dst;
+
+	if (!ila_is_ila_addr(iaddr)) {
+		/* Don't allow setting a translation for a non-ILA address */
+		return -EINVAL;
+	}
+
 	ret = nla_parse_nested(tb, ILA_ATTR_MAX, nla,
 			       ila_nl_policy);
 	if (ret < 0)
@@ -84,16 +99,14 @@ static int ila_build_state(struct net_device *dev, struct nlattr *nla,
 	newts->len = encap_len;
 	p = ila_params_lwtunnel(newts);
 
-	p->locator = (__force __be64)nla_get_u64(tb[ILA_ATTR_LOCATOR]);
+	p->locator.v64 = (__force __be64)nla_get_u64(tb[ILA_ATTR_LOCATOR]);
 
-	if (cfg6->fc_dst_len > sizeof(__be64)) {
-		/* Precompute checksum difference for translation since we
-		 * know both the old locator and the new one.
-		 */
-		p->locator_match = *(__be64 *)&cfg6->fc_dst;
-		p->csum_diff = compute_csum_diff8(
-			(__be32 *)&p->locator_match, (__be32 *)&p->locator);
-	}
+	/* Precompute checksum difference for translation since we
+	 * know both the old locator and the new one.
+	 */
+	p->locator_match = iaddr->loc;
+	p->csum_diff = compute_csum_diff8(
+		(__be32 *)&p->locator_match, (__be32 *)&p->locator);
 
 	newts->type = LWTUNNEL_ENCAP_ILA;
 	newts->flags |= LWTUNNEL_STATE_OUTPUT_REDIRECT |
@@ -109,7 +122,7 @@ static int ila_fill_encap_info(struct sk_buff *skb,
 {
 	struct ila_params *p = ila_params_lwtunnel(lwtstate);
 
-	if (nla_put_u64(skb, ILA_ATTR_LOCATOR, (__force u64)p->locator))
+	if (nla_put_u64(skb, ILA_ATTR_LOCATOR, (__force u64)p->locator.v64))
 		goto nla_put_failure;
 
 	return 0;
@@ -129,7 +142,7 @@ static int ila_encap_cmp(struct lwtunnel_state *a, struct lwtunnel_state *b)
 	struct ila_params *a_p = ila_params_lwtunnel(a);
 	struct ila_params *b_p = ila_params_lwtunnel(b);
 
-	return (a_p->locator != b_p->locator);
+	return (a_p->locator.v64 != b_p->locator.v64);
 }
 
 static const struct lwtunnel_encap_ops ila_encap_ops = {
diff --git a/net/ipv6/ila/ila_xlat.c b/net/ipv6/ila/ila_xlat.c
index 0b03533..075c782 100644
--- a/net/ipv6/ila/ila_xlat.c
+++ b/net/ipv6/ila/ila_xlat.c
@@ -11,13 +11,13 @@
 
 struct ila_xlat_params {
 	struct ila_params ip;
-	__be64 identifier;
+	struct ila_identifier identifier;
 	int ifindex;
 	unsigned int dir;
 };
 
 struct ila_map {
-	struct ila_xlat_params p;
+	struct ila_xlat_params xp;
 	struct rhash_head node;
 	struct ila_map __rcu *next;
 	struct rcu_head rcu;
@@ -66,31 +66,35 @@ static __always_inline void __ila_hash_secret_init(void)
 	net_get_random_once(&hashrnd, sizeof(hashrnd));
 }
 
-static inline u32 ila_identifier_hash(__be64 identifier)
+static inline u32 ila_identifier_hash(struct ila_identifier ident)
 {
-	u32 *v = (u32 *)&identifier;
+	u32 *v = (u32 *)ident.v32;
 
 	return jhash_2words(v[0], v[1], hashrnd);
 }
 
-static inline spinlock_t *ila_get_lock(struct ila_net *ilan, __be64 identifier)
+static inline spinlock_t *ila_get_lock(struct ila_net *ilan,
+				       struct ila_identifier ident)
 {
-	return &ilan->locks[ila_identifier_hash(identifier) & ilan->locks_mask];
+	return &ilan->locks[ila_identifier_hash(ident) & ilan->locks_mask];
 }
 
-static inline int ila_cmp_wildcards(struct ila_map *ila, __be64 loc,
-				    int ifindex, unsigned int dir)
+static inline int ila_cmp_wildcards(struct ila_map *ila,
+				    struct ila_addr *iaddr, int ifindex,
+				    unsigned int dir)
 {
-	return (ila->p.ip.locator_match && ila->p.ip.locator_match != loc) ||
-	       (ila->p.ifindex && ila->p.ifindex != ifindex) ||
-	       !(ila->p.dir & dir);
+	return (ila->xp.ip.locator_match.v64 &&
+		ila->xp.ip.locator_match.v64 != iaddr->loc.v64) ||
+	       (ila->xp.ifindex && ila->xp.ifindex != ifindex) ||
+	       !(ila->xp.dir & dir);
 }
 
-static inline int ila_cmp_params(struct ila_map *ila, struct ila_xlat_params *p)
+static inline int ila_cmp_params(struct ila_map *ila,
+				 struct ila_xlat_params *xp)
 {
-	return (ila->p.ip.locator_match != p->ip.locator_match) ||
-	       (ila->p.ifindex != p->ifindex) ||
-	       (ila->p.dir != p->dir);
+	return (ila->xp.ip.locator_match.v64 != xp->ip.locator_match.v64) ||
+	       (ila->xp.ifindex != xp->ifindex) ||
+	       (ila->xp.dir != xp->dir);
 }
 
 static int ila_cmpfn(struct rhashtable_compare_arg *arg,
@@ -98,17 +102,17 @@ static int ila_cmpfn(struct rhashtable_compare_arg *arg,
 {
 	const struct ila_map *ila = obj;
 
-	return (ila->p.identifier != *(__be64 *)arg->key);
+	return (ila->xp.identifier.v64 != *(__be64 *)arg->key);
 }
 
 static inline int ila_order(struct ila_map *ila)
 {
 	int score = 0;
 
-	if (ila->p.ip.locator_match)
+	if (ila->xp.ip.locator_match.v64)
 		score += 1 << 0;
 
-	if (ila->p.ifindex)
+	if (ila->xp.ifindex)
 		score += 1 << 1;
 
 	return score;
@@ -117,7 +121,7 @@ static inline int ila_order(struct ila_map *ila)
 static const struct rhashtable_params rht_params = {
 	.nelem_hint = 1024,
 	.head_offset = offsetof(struct ila_map, node),
-	.key_offset = offsetof(struct ila_map, p.identifier),
+	.key_offset = offsetof(struct ila_map, xp.identifier),
 	.key_len = sizeof(u64), /* identifier */
 	.max_size = 1048576,
 	.min_size = 256,
@@ -144,42 +148,43 @@ static struct nla_policy ila_nl_policy[ILA_ATTR_MAX + 1] = {
 };
 
 static int parse_nl_config(struct genl_info *info,
-			   struct ila_xlat_params *p)
+			   struct ila_xlat_params *xp)
 {
-	memset(p, 0, sizeof(*p));
+	memset(xp, 0, sizeof(*xp));
 
 	if (info->attrs[ILA_ATTR_IDENTIFIER])
-		p->identifier = (__force __be64)nla_get_u64(
+		xp->identifier.v64 = (__force __be64)nla_get_u64(
 			info->attrs[ILA_ATTR_IDENTIFIER]);
 
 	if (info->attrs[ILA_ATTR_LOCATOR])
-		p->ip.locator = (__force __be64)nla_get_u64(
+		xp->ip.locator.v64 = (__force __be64)nla_get_u64(
 			info->attrs[ILA_ATTR_LOCATOR]);
 
 	if (info->attrs[ILA_ATTR_LOCATOR_MATCH])
-		p->ip.locator_match = (__force __be64)nla_get_u64(
+		xp->ip.locator_match.v64 = (__force __be64)nla_get_u64(
 			info->attrs[ILA_ATTR_LOCATOR_MATCH]);
 
 	if (info->attrs[ILA_ATTR_IFINDEX])
-		p->ifindex = nla_get_s32(info->attrs[ILA_ATTR_IFINDEX]);
+		xp->ifindex = nla_get_s32(info->attrs[ILA_ATTR_IFINDEX]);
 
 	if (info->attrs[ILA_ATTR_DIR])
-		p->dir = nla_get_u32(info->attrs[ILA_ATTR_DIR]);
+		xp->dir = nla_get_u32(info->attrs[ILA_ATTR_DIR]);
 
 	return 0;
 }
 
 /* Must be called with rcu readlock */
-static inline struct ila_map *ila_lookup_wildcards(__be64 id, __be64 loc,
+static inline struct ila_map *ila_lookup_wildcards(struct ila_addr *iaddr,
 						   int ifindex,
 						   unsigned int dir,
 						   struct ila_net *ilan)
 {
 	struct ila_map *ila;
 
-	ila = rhashtable_lookup_fast(&ilan->rhash_table, &id, rht_params);
+	ila = rhashtable_lookup_fast(&ilan->rhash_table, &iaddr->ident,
+				     rht_params);
 	while (ila) {
-		if (!ila_cmp_wildcards(ila, loc, ifindex, dir))
+		if (!ila_cmp_wildcards(ila, iaddr, ifindex, dir))
 			return ila;
 		ila = rcu_access_pointer(ila->next);
 	}
@@ -188,15 +193,15 @@ static inline struct ila_map *ila_lookup_wildcards(__be64 id, __be64 loc,
 }
 
 /* Must be called with rcu readlock */
-static inline struct ila_map *ila_lookup_by_params(struct ila_xlat_params *p,
+static inline struct ila_map *ila_lookup_by_params(struct ila_xlat_params *xp,
 						   struct ila_net *ilan)
 {
 	struct ila_map *ila;
 
-	ila = rhashtable_lookup_fast(&ilan->rhash_table, &p->identifier,
+	ila = rhashtable_lookup_fast(&ilan->rhash_table, &xp->identifier,
 				     rht_params);
 	while (ila) {
-		if (!ila_cmp_params(ila, p))
+		if (!ila_cmp_params(ila, xp))
 			return ila;
 		ila = rcu_access_pointer(ila->next);
 	}
@@ -241,11 +246,11 @@ static struct nf_hook_ops ila_nf_hook_ops[] __read_mostly = {
 	},
 };
 
-static int ila_add_mapping(struct net *net, struct ila_xlat_params *p)
+static int ila_add_mapping(struct net *net, struct ila_xlat_params *xp)
 {
 	struct ila_net *ilan = net_generic(net, ila_net_id);
 	struct ila_map *ila, *head;
-	spinlock_t *lock = ila_get_lock(ilan, p->identifier);
+	spinlock_t *lock = ila_get_lock(ilan, xp->identifier);
 	int err = 0, order;
 
 	if (!ilan->hooks_registered) {
@@ -264,22 +269,22 @@ static int ila_add_mapping(struct net *net, struct ila_xlat_params *p)
 	if (!ila)
 		return -ENOMEM;
 
-	ila->p = *p;
+	ila->xp = *xp;
 
-	if (p->ip.locator_match) {
+	if (xp->ip.locator_match.v64) {
 		/* Precompute checksum difference for translation since we
 		 * know both the old identifier and the new one.
 		 */
-		ila->p.ip.csum_diff = compute_csum_diff8(
-			(__be32 *)&p->ip.locator_match,
-			(__be32 *)&p->ip.locator);
+		ila->xp.ip.csum_diff = compute_csum_diff8(
+			(__be32 *)&xp->ip.locator_match,
+			(__be32 *)&xp->ip.locator);
 	}
 
 	order = ila_order(ila);
 
 	spin_lock(lock);
 
-	head = rhashtable_lookup_fast(&ilan->rhash_table, &p->identifier,
+	head = rhashtable_lookup_fast(&ilan->rhash_table, &xp->identifier,
 				      rht_params);
 	if (!head) {
 		/* New entry for the rhash_table */
@@ -289,7 +294,7 @@ static int ila_add_mapping(struct net *net, struct ila_xlat_params *p)
 		struct ila_map *tila = head, *prev = NULL;
 
 		do {
-			if (!ila_cmp_params(tila, p)) {
+			if (!ila_cmp_params(tila, xp)) {
 				err = -EEXIST;
 				goto out;
 			}
@@ -326,23 +331,23 @@ out:
 	return err;
 }
 
-static int ila_del_mapping(struct net *net, struct ila_xlat_params *p)
+static int ila_del_mapping(struct net *net, struct ila_xlat_params *xp)
 {
 	struct ila_net *ilan = net_generic(net, ila_net_id);
 	struct ila_map *ila, *head, *prev;
-	spinlock_t *lock = ila_get_lock(ilan, p->identifier);
+	spinlock_t *lock = ila_get_lock(ilan, xp->identifier);
 	int err = -ENOENT;
 
 	spin_lock(lock);
 
 	head = rhashtable_lookup_fast(&ilan->rhash_table,
-				      &p->identifier, rht_params);
+				      &xp->identifier, rht_params);
 	ila = head;
 
 	prev = NULL;
 
 	while (ila) {
-		if (ila_cmp_params(ila, p)) {
+		if (ila_cmp_params(ila, xp)) {
 			prev = ila;
 			ila = rcu_dereference_protected(ila->next,
 							lockdep_is_held(lock));
@@ -404,14 +409,14 @@ static int ila_nl_cmd_add_mapping(struct sk_buff *skb, struct genl_info *info)
 static int ila_nl_cmd_del_mapping(struct sk_buff *skb, struct genl_info *info)
 {
 	struct net *net = genl_info_net(info);
-	struct ila_xlat_params p;
+	struct ila_xlat_params xp;
 	int err;
 
-	err = parse_nl_config(info, &p);
+	err = parse_nl_config(info, &xp);
 	if (err)
 		return err;
 
-	ila_del_mapping(net, &p);
+	ila_del_mapping(net, &xp);
 
 	return 0;
 }
@@ -419,13 +424,13 @@ static int ila_nl_cmd_del_mapping(struct sk_buff *skb, struct genl_info *info)
 static int ila_fill_info(struct ila_map *ila, struct sk_buff *msg)
 {
 	if (nla_put_u64(msg, ILA_ATTR_IDENTIFIER,
-			(__force u64)ila->p.identifier) ||
+			(__force u64)ila->xp.identifier.v64) ||
 	    nla_put_u64(msg, ILA_ATTR_LOCATOR,
-			(__force u64)ila->p.ip.locator) ||
+			(__force u64)ila->xp.ip.locator.v64) ||
 	    nla_put_u64(msg, ILA_ATTR_LOCATOR_MATCH,
-			(__force u64)ila->p.ip.locator_match) ||
-	    nla_put_s32(msg, ILA_ATTR_IFINDEX, ila->p.ifindex) ||
-	    nla_put_u32(msg, ILA_ATTR_DIR, ila->p.dir))
+			(__force u64)ila->xp.ip.locator_match.v64) ||
+	    nla_put_s32(msg, ILA_ATTR_IFINDEX, ila->xp.ifindex) ||
+	    nla_put_u32(msg, ILA_ATTR_DIR, ila->xp.dir))
 		return -1;
 
 	return 0;
@@ -457,11 +462,11 @@ static int ila_nl_cmd_get_mapping(struct sk_buff *skb, struct genl_info *info)
 	struct net *net = genl_info_net(info);
 	struct ila_net *ilan = net_generic(net, ila_net_id);
 	struct sk_buff *msg;
-	struct ila_xlat_params p;
+	struct ila_xlat_params xp;
 	struct ila_map *ila;
 	int ret;
 
-	ret = parse_nl_config(info, &p);
+	ret = parse_nl_config(info, &xp);
 	if (ret)
 		return ret;
 
@@ -471,7 +476,7 @@ static int ila_nl_cmd_get_mapping(struct sk_buff *skb, struct genl_info *info)
 
 	rcu_read_lock();
 
-	ila = ila_lookup_by_params(&p, ilan);
+	ila = ila_lookup_by_params(&xp, ilan);
 	if (ila) {
 		ret = ila_dump_info(ila,
 				    info->snd_portid,
@@ -620,21 +625,18 @@ static int ila_xlat_addr(struct sk_buff *skb, int dir)
 	struct ipv6hdr *ip6h = ipv6_hdr(skb);
 	struct net *net = dev_net(skb->dev);
 	struct ila_net *ilan = net_generic(net, ila_net_id);
-	__be64 identifier, locator_match;
+	struct ila_addr *iaddr = ila_a2i(&ip6h->daddr);
 	size_t nhoff;
 
 	/* Assumes skb contains a valid IPv6 header that is pulled */
 
-	identifier = *(__be64 *)&ip6h->daddr.in6_u.u6_addr8[8];
-	locator_match = *(__be64 *)&ip6h->daddr.in6_u.u6_addr8[0];
 	nhoff = sizeof(struct ipv6hdr);
 
 	rcu_read_lock();
 
-	ila = ila_lookup_wildcards(identifier, locator_match,
-				   skb->dev->ifindex, dir, ilan);
+	ila = ila_lookup_wildcards(iaddr, skb->dev->ifindex, dir, ilan);
 	if (ila)
-		update_ipv6_locator(skb, &ila->p.ip);
+		ila_update_ipv6_locator(skb, &ila->xp.ip);
 
 	rcu_read_unlock();
 
-- 
2.8.0.rc2

^ permalink raw reply related

* [PATCH net-next 2/3] ila: xlat changes
From: Tom Herbert @ 2016-04-15 20:34 UTC (permalink / raw)
  To: davem, netdev; +Cc: kernel-team
In-Reply-To: <1460752452-3328784-1-git-send-email-tom@herbertland.com>

Change model of xlat to be used only for input where lookup is done on
the locator part of an address (comparing to locator_match as key
in rhashtable). This is needed for checksum neutral translation
which obfuscates the low order 16 bits of the identifier. It also
permits hosts to be in muliple ILA domains (each locator can map
to a different SIR address). A check is also added to disallow
translating non-ILA addresses (check of type in identifier).

Signed-off-by: Tom Herbert <tom@herbertland.com>
---
 net/ipv6/ila/ila_xlat.c | 102 ++++++++++++++++--------------------------------
 1 file changed, 34 insertions(+), 68 deletions(-)

diff --git a/net/ipv6/ila/ila_xlat.c b/net/ipv6/ila/ila_xlat.c
index 075c782..d17d429 100644
--- a/net/ipv6/ila/ila_xlat.c
+++ b/net/ipv6/ila/ila_xlat.c
@@ -11,9 +11,7 @@
 
 struct ila_xlat_params {
 	struct ila_params ip;
-	struct ila_identifier identifier;
 	int ifindex;
-	unsigned int dir;
 };
 
 struct ila_map {
@@ -66,35 +64,29 @@ static __always_inline void __ila_hash_secret_init(void)
 	net_get_random_once(&hashrnd, sizeof(hashrnd));
 }
 
-static inline u32 ila_identifier_hash(struct ila_identifier ident)
+static inline u32 ila_locator_hash(struct ila_locator loc)
 {
-	u32 *v = (u32 *)ident.v32;
+	u32 *v = (u32 *)loc.v32;
 
 	return jhash_2words(v[0], v[1], hashrnd);
 }
 
 static inline spinlock_t *ila_get_lock(struct ila_net *ilan,
-				       struct ila_identifier ident)
+				       struct ila_locator loc)
 {
-	return &ilan->locks[ila_identifier_hash(ident) & ilan->locks_mask];
+	return &ilan->locks[ila_locator_hash(loc) & ilan->locks_mask];
 }
 
 static inline int ila_cmp_wildcards(struct ila_map *ila,
-				    struct ila_addr *iaddr, int ifindex,
-				    unsigned int dir)
+				    struct ila_addr *iaddr, int ifindex)
 {
-	return (ila->xp.ip.locator_match.v64 &&
-		ila->xp.ip.locator_match.v64 != iaddr->loc.v64) ||
-	       (ila->xp.ifindex && ila->xp.ifindex != ifindex) ||
-	       !(ila->xp.dir & dir);
+	return (ila->xp.ifindex && ila->xp.ifindex != ifindex);
 }
 
 static inline int ila_cmp_params(struct ila_map *ila,
 				 struct ila_xlat_params *xp)
 {
-	return (ila->xp.ip.locator_match.v64 != xp->ip.locator_match.v64) ||
-	       (ila->xp.ifindex != xp->ifindex) ||
-	       (ila->xp.dir != xp->dir);
+	return (ila->xp.ifindex != xp->ifindex);
 }
 
 static int ila_cmpfn(struct rhashtable_compare_arg *arg,
@@ -102,16 +94,13 @@ static int ila_cmpfn(struct rhashtable_compare_arg *arg,
 {
 	const struct ila_map *ila = obj;
 
-	return (ila->xp.identifier.v64 != *(__be64 *)arg->key);
+	return (ila->xp.ip.locator_match.v64 != *(__be64 *)arg->key);
 }
 
 static inline int ila_order(struct ila_map *ila)
 {
 	int score = 0;
 
-	if (ila->xp.ip.locator_match.v64)
-		score += 1 << 0;
-
 	if (ila->xp.ifindex)
 		score += 1 << 1;
 
@@ -121,7 +110,7 @@ static inline int ila_order(struct ila_map *ila)
 static const struct rhashtable_params rht_params = {
 	.nelem_hint = 1024,
 	.head_offset = offsetof(struct ila_map, node),
-	.key_offset = offsetof(struct ila_map, xp.identifier),
+	.key_offset = offsetof(struct ila_map, xp.ip.locator_match),
 	.key_len = sizeof(u64), /* identifier */
 	.max_size = 1048576,
 	.min_size = 256,
@@ -140,11 +129,9 @@ static struct genl_family ila_nl_family = {
 };
 
 static struct nla_policy ila_nl_policy[ILA_ATTR_MAX + 1] = {
-	[ILA_ATTR_IDENTIFIER] = { .type = NLA_U64, },
 	[ILA_ATTR_LOCATOR] = { .type = NLA_U64, },
 	[ILA_ATTR_LOCATOR_MATCH] = { .type = NLA_U64, },
 	[ILA_ATTR_IFINDEX] = { .type = NLA_U32, },
-	[ILA_ATTR_DIR] = { .type = NLA_U32, },
 };
 
 static int parse_nl_config(struct genl_info *info,
@@ -152,10 +139,6 @@ static int parse_nl_config(struct genl_info *info,
 {
 	memset(xp, 0, sizeof(*xp));
 
-	if (info->attrs[ILA_ATTR_IDENTIFIER])
-		xp->identifier.v64 = (__force __be64)nla_get_u64(
-			info->attrs[ILA_ATTR_IDENTIFIER]);
-
 	if (info->attrs[ILA_ATTR_LOCATOR])
 		xp->ip.locator.v64 = (__force __be64)nla_get_u64(
 			info->attrs[ILA_ATTR_LOCATOR]);
@@ -167,24 +150,20 @@ static int parse_nl_config(struct genl_info *info,
 	if (info->attrs[ILA_ATTR_IFINDEX])
 		xp->ifindex = nla_get_s32(info->attrs[ILA_ATTR_IFINDEX]);
 
-	if (info->attrs[ILA_ATTR_DIR])
-		xp->dir = nla_get_u32(info->attrs[ILA_ATTR_DIR]);
-
 	return 0;
 }
 
 /* Must be called with rcu readlock */
 static inline struct ila_map *ila_lookup_wildcards(struct ila_addr *iaddr,
 						   int ifindex,
-						   unsigned int dir,
 						   struct ila_net *ilan)
 {
 	struct ila_map *ila;
 
-	ila = rhashtable_lookup_fast(&ilan->rhash_table, &iaddr->ident,
+	ila = rhashtable_lookup_fast(&ilan->rhash_table, &iaddr->loc,
 				     rht_params);
 	while (ila) {
-		if (!ila_cmp_wildcards(ila, iaddr, ifindex, dir))
+		if (!ila_cmp_wildcards(ila, iaddr, ifindex))
 			return ila;
 		ila = rcu_access_pointer(ila->next);
 	}
@@ -198,7 +177,8 @@ static inline struct ila_map *ila_lookup_by_params(struct ila_xlat_params *xp,
 {
 	struct ila_map *ila;
 
-	ila = rhashtable_lookup_fast(&ilan->rhash_table, &xp->identifier,
+	ila = rhashtable_lookup_fast(&ilan->rhash_table,
+				     &xp->ip.locator_match,
 				     rht_params);
 	while (ila) {
 		if (!ila_cmp_params(ila, xp))
@@ -226,14 +206,14 @@ static void ila_free_cb(void *ptr, void *arg)
 	}
 }
 
-static int ila_xlat_addr(struct sk_buff *skb, int dir);
+static int ila_xlat_addr(struct sk_buff *skb);
 
 static unsigned int
 ila_nf_input(void *priv,
 	     struct sk_buff *skb,
 	     const struct nf_hook_state *state)
 {
-	ila_xlat_addr(skb, ILA_DIR_IN);
+	ila_xlat_addr(skb);
 	return NF_ACCEPT;
 }
 
@@ -250,7 +230,7 @@ static int ila_add_mapping(struct net *net, struct ila_xlat_params *xp)
 {
 	struct ila_net *ilan = net_generic(net, ila_net_id);
 	struct ila_map *ila, *head;
-	spinlock_t *lock = ila_get_lock(ilan, xp->identifier);
+	spinlock_t *lock = ila_get_lock(ilan, xp->ip.locator_match);
 	int err = 0, order;
 
 	if (!ilan->hooks_registered) {
@@ -271,20 +251,19 @@ static int ila_add_mapping(struct net *net, struct ila_xlat_params *xp)
 
 	ila->xp = *xp;
 
-	if (xp->ip.locator_match.v64) {
-		/* Precompute checksum difference for translation since we
-		 * know both the old identifier and the new one.
-		 */
-		ila->xp.ip.csum_diff = compute_csum_diff8(
-			(__be32 *)&xp->ip.locator_match,
-			(__be32 *)&xp->ip.locator);
-	}
+	/* Precompute checksum difference for translation since we
+	 * know both the old identifier and the new one.
+	 */
+	ila->xp.ip.csum_diff = compute_csum_diff8(
+		(__be32 *)&xp->ip.locator_match,
+		(__be32 *)&xp->ip.locator);
 
 	order = ila_order(ila);
 
 	spin_lock(lock);
 
-	head = rhashtable_lookup_fast(&ilan->rhash_table, &xp->identifier,
+	head = rhashtable_lookup_fast(&ilan->rhash_table,
+				      &xp->ip.locator_match,
 				      rht_params);
 	if (!head) {
 		/* New entry for the rhash_table */
@@ -335,13 +314,13 @@ static int ila_del_mapping(struct net *net, struct ila_xlat_params *xp)
 {
 	struct ila_net *ilan = net_generic(net, ila_net_id);
 	struct ila_map *ila, *head, *prev;
-	spinlock_t *lock = ila_get_lock(ilan, xp->identifier);
+	spinlock_t *lock = ila_get_lock(ilan, xp->ip.locator_match);
 	int err = -ENOENT;
 
 	spin_lock(lock);
 
 	head = rhashtable_lookup_fast(&ilan->rhash_table,
-				      &xp->identifier, rht_params);
+				      &xp->ip.locator_match, rht_params);
 	ila = head;
 
 	prev = NULL;
@@ -423,14 +402,11 @@ static int ila_nl_cmd_del_mapping(struct sk_buff *skb, struct genl_info *info)
 
 static int ila_fill_info(struct ila_map *ila, struct sk_buff *msg)
 {
-	if (nla_put_u64(msg, ILA_ATTR_IDENTIFIER,
-			(__force u64)ila->xp.identifier.v64) ||
-	    nla_put_u64(msg, ILA_ATTR_LOCATOR,
+	if (nla_put_u64(msg, ILA_ATTR_LOCATOR,
 			(__force u64)ila->xp.ip.locator.v64) ||
 	    nla_put_u64(msg, ILA_ATTR_LOCATOR_MATCH,
 			(__force u64)ila->xp.ip.locator_match.v64) ||
-	    nla_put_s32(msg, ILA_ATTR_IFINDEX, ila->xp.ifindex) ||
-	    nla_put_u32(msg, ILA_ATTR_DIR, ila->xp.dir))
+	    nla_put_s32(msg, ILA_ATTR_IFINDEX, ila->xp.ifindex))
 		return -1;
 
 	return 0;
@@ -619,22 +595,24 @@ static struct pernet_operations ila_net_ops = {
 	.size = sizeof(struct ila_net),
 };
 
-static int ila_xlat_addr(struct sk_buff *skb, int dir)
+static int ila_xlat_addr(struct sk_buff *skb)
 {
 	struct ila_map *ila;
 	struct ipv6hdr *ip6h = ipv6_hdr(skb);
 	struct net *net = dev_net(skb->dev);
 	struct ila_net *ilan = net_generic(net, ila_net_id);
 	struct ila_addr *iaddr = ila_a2i(&ip6h->daddr);
-	size_t nhoff;
 
 	/* Assumes skb contains a valid IPv6 header that is pulled */
 
-	nhoff = sizeof(struct ipv6hdr);
+	if (!ila_addr_is_ila(iaddr)) {
+		/* Type indicates this is not an ILA address */
+		return 0;
+	}
 
 	rcu_read_lock();
 
-	ila = ila_lookup_wildcards(iaddr, skb->dev->ifindex, dir, ilan);
+	ila = ila_lookup_wildcards(iaddr, skb->dev->ifindex, ilan);
 	if (ila)
 		ila_update_ipv6_locator(skb, &ila->xp.ip);
 
@@ -643,18 +621,6 @@ static int ila_xlat_addr(struct sk_buff *skb, int dir)
 	return 0;
 }
 
-int ila_xlat_incoming(struct sk_buff *skb)
-{
-	return ila_xlat_addr(skb, ILA_DIR_IN);
-}
-EXPORT_SYMBOL(ila_xlat_incoming);
-
-int ila_xlat_outgoing(struct sk_buff *skb)
-{
-	return ila_xlat_addr(skb, ILA_DIR_OUT);
-}
-EXPORT_SYMBOL(ila_xlat_outgoing);
-
 int ila_xlat_init(void)
 {
 	int ret;
-- 
2.8.0.rc2

^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox